• 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 24487
  • 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
Parents
  • 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
Reply
  • 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
Children
No Data

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