• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Logic Design
  3. Problem with Simvision hanging in an endless loop

Stats

  • Locked Locked
  • Replies 6
  • Subscribers 64
  • Views 24480
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem with Simvision hanging in an endless loop

Rony Ross
Rony Ross over 15 years ago

I have a problem with Simvision hanging in an endless loop. I encounter this problem from time to time probably since I use a lot of complicated always @(*) blocks. The problem occurs with two blocks that have some dependencies between them. However, it is not a combinatorial loop. I believe that it got something to do with the way that Simvision creates and updates its dependency tree. Usually, some "cosmetic" change, such as taking out a line and changing it to "assign ...", solves the problem. However, it is very difficult to find out which line causes the problem. I tried to reproduce a simple example below. I belive that it can be even simpler.

module endlessloop
(
 output reg c_cld
);

  parameter CREATE_ENDLESS_LOOP = 1; // =0 will not cause the endless loop

reg a;
reg b;
reg c;
reg d;
reg d_cld;

reg clk;
reg rst_l;

initial
begin
  clk = 1'b1;
  rst_l = 1'b0;
  #50 rst_l = 1'b1;
end

always
  #10 clk = ~clk;

always @(posedge clk or negedge rst_l)
begin
  if (~rst_l)
  begin
    c_cld <= 1'b0;
    d_cld <= 1'b0;
  end
  else
  begin
    c_cld <= c;
    d_cld <= ~d_cld;
  end
end

always @(*)
begin
  $display("%d; in 1",$time);
  if (CREATE_ENDLESS_LOOP)
  begin
    a = 1'b0;
    d = 1'b0;
  end

  a = b;
  d = d_cld;
end

always @(*)
begin
  $display("%d; in 2",$time);
  if (CREATE_ENDLESS_LOOP)
  begin
    c = 1'b0;
    b = 1'b0;
  end

  c = a;
  b = d;
end

endmodule // endlessloop

 

  • Cancel
  • TAM1
    TAM1 over 15 years ago

    The simulator is behaving correctly in this. Your block 'one' has some events which trigger block 'two', which has some events which trigger block 'one' and so on, ad infinitum. To avoid this kind of behavior, many design methodologies don't allow combinatorial blocks to feed back to each other, even if the signals involved are apparently unrelated. Because every signal in a block can be updated when it executes, even if triggered by an event on another signal entirely, you need to be aware that a combinatorial feedback path can be triggered even when you think it would not.

    You can work around this using the command line option "-delay_trigger" on your ncvlog command line. It will wait until the last assignment on a net before determining if the net had an "event" on it.

    PS. I found this information looking a Cadence solution published at: http://support.cadence.com/wps/mypoc/cos?uri=deeplinkmin:ViewSolution;solutionNumber=11594558

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Rony Ross
    Rony Ross over 15 years ago
    Thank you for the reply.
    Unfortunately, I don't have access for the link of the Cadence solution. For some reason I couldn't find this flag in my Cadence help. However, it solves the problem with the example that I gave. Now it raises few more questions...

        1. What else does this flag do? Would it have any other effect on my simulation?
        2. Why is it an ncvlog flag and not an ncsim?
        3. Although it is a correct behavior, one could expect the following:
            1. A Lint warning
            2. That the simulator won't hang. It should exit with a warning that it encountered an infinite loop involving the following blocks …
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Shalom B
    Shalom B over 15 years ago

    Here is the content of that note:

     Using the -delay_trigger switch to avoid repeated retriggering of always blocks due to glitches

    Problem

    Sometimes there are situations where glitches on signals result in repeated re-triggering of the blocks which reference them.

    A Verilog always block executes when an object in the event control expression for the block has changed value from when the block was last executed. This default wait mechanism is sensitive to zero-width glitches on the variables the block is waiting on. These glitches are usually created when a writer process assigns a default value to the variable and then overwrites it with a different value. Even if the writer changes the variable back to the old value, there was a change in the value of the variable before it was changed back to the old value, and that is sufficient to wake up the waiting block. When such glitches are combined with a combinational loop in the design, they can stall the simulation.

    Consider the following example:

    module top();

    reg a,b;

    initial begin

      #1 b = 1;

      #1

      $finish;

    end

    always @(*) begin : BLK_B_TO_A

      $display("Entering first block");

      a = b;

      a = 1'b0;

    end

    always @(*) begin : BLK_A_TO_B

      $display("Entering second block");

      b = a;

      b = 1'b1;

    end

    endmodule

    If you run this example code with the -linedebug switch:

    % irun -linedebug test.v

    You will see a hang with both the blocks triggering each other continuously. How can one avoid

    Careful observation shows that they trigger each other because of glitches.

    How can one avoid this?

     

    Solution

    The sequence of events happening in the above example is as follows:

    - The first update to 'b' is made at 1 NS from the initial block.

    - This causes the first always block to trigger and both the updates to 'a' are made. Finally 'a' gets the value 0.

    - Update to 'a' causes second always block to trigger. First update to 'b' is the value 0 and the second update is the value 1. Note that 'b' old value at this point was 1.

    - This glitch in the second always block (from 1 it goes to 0 and then back to 1) triggers the first block again.

    If you cannot change the code to avoid the glitches, use the -delay_trigger option in situations such as the above, where two combinational always blocks that form a combinational loop connected by variables (not nets) glitch their outputs, resulting in repeated re-triggering of the blocks that reference these signals. This option causes an event control to filter out glitches that are too narrow to be seen by the event control itself, and then double-checks to see if signals in the sensitivity list have in fact changed values. If the value change created by the glitch goes away before the check (as it does for two writes in the same evaluation of another process), then the event control does not wake up, and the always block is not executed.

    This compile time switch has been documented from version 08.20-s017 of ncvlog onwards.

    NC-Verilog Simulator Help

      Compiling Verilog Source Files with ncvlog

        ncvlog Command Syntax

          -DELay_trigger

     

    Here is some of the description of this switch in the NCVlog Help:

    -DELay_trigger

    Filter out glitches that are too narrow to be seen by an always block event control by checking to see if a variable in the event control expression has a different value from when the block was last executed.A Verilog always block executes when an object in the event control expression for the block has changed value from when the block was last executed. This default wait mechanism is sensitive to zero-width glitches on the variables the block is waiting on. These glitches are usually created when a writer process assigns a default value to the variable and then overwrites it with a different value. Even if the writer changes the variable back to the old value, there was a change in the value of the variable before it was changed back to the old value, and that is sufficient to wake up the waiting block.

    When such glitches are combined with a combinational loop in the design, they can stall the simulation.

    ...

    If you cannot change the code to avoid the glitches, use the -delay_trigger option in situations such as the above, where two combinational always blocks that form a combinational loop connected by variables (not nets) glitch their outputs, resulting in repeated re-triggering of the blocks that reference these signals.

    This option causes an event control to filter out glitches that are too narrow to be seen by the event control itself, and then double-checks to see if signals in the sensitivity list have in fact changed values. If the value change created by the glitch goes away before the check (as it does for two writes in the same evaluation of another process), then the event control does not wake up, and the always block is not executed.

    Note: The -delay_trigger option has a small negative impact on performance.

    Note: An always @* construct that is on a statement containing an array or unpacked structure reference adds all elements of the array or unpacked structure to the sensitivity list.

    For performance reasons, the -delay_trigger option is ignored with a warning for these event controls.

    Shalom

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Shalom B
    Shalom B over 15 years ago

    If you run HAL on your example, you will get the following warning:

     always @(*)
    |
    halcheck: *W,TRRACE (./test.v,41|0): A trigger-propagation race exists between 'd' and 'b'.

    Shalom

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Rony Ross
    Rony Ross over 15 years ago

    Thank you for the prompt reply.

    My original code did not produce this warning. When I tried to create a small example I failed to create a clean example and this message appeared. However, Cadence's example that you posted is much simpler and does not produce this warning. As I wrote before, I strongly believe that in this case HAL warning should be generated and the simulator should not hang in infinite loop (hanging in infinite loop is usually a poor practice...).

    Regards,

    Rony

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • mkapil
    mkapil over 15 years ago

    Hi Rony,

    To enable race condition checks, you need to pass the switch "-races" to HAL.

    i.e.

    hal -races test.v 

    Hope this helps.

    Regards,
    -Kapil 

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information