13

Say the following code section (same block):

A <= 1
A <= 2

Will variable A always be assigned 2? or will there be a race condition and 1 or 2 will be assigned ?

My understanding of non blocking assignment is that it is up to the hardware to assign the variable A at a future time so it could be a random result. However, this is non intuitive. Simulations show that 2 always get assigned, but I would like to know if this is definitely the case for hardware synthesis.

0

4 Answers 4

15

A would be 2 in simulation, the last defined value takes effect. If they are not in the same block then there could be a race condition depending on the simulator scheduler as to which was defined last in simulation.

I have seen this technique used quite a lot and never seen any unexpected results after synthesis.

From Verilog IEEE 1364-2005 Section 11.4.1 Determinism

Statements within a begin-end block shall be executed in the order in which they appear in that begin-end block. Execution of statements in a particular begin-end block can be suspended in favor of other processes in the model; however, in no case shall the statements in a begin-end block be executed in any order other than that in which they appear in the source.

This is also in SystemVerilog-IEEE1800 2012 as section 4.6 Determinism

Usage of this might be a FSM which sparsely defines its outputs:

always @(posedge clk) begin
  out_one <= 1'b0;
  out_two <= 1'b0;
  out_thr <= 1'b0;
  case (state)
    2'd1 : out_one <= 1'b1;
    2'd2 : out_two <= 1'b1;
    2'd3 : out_thr <= 1'b1;
  endcase
end
Sign up to request clarification or add additional context in comments.

2 Comments

yeah this is essentially what I was asking this question for, cause I had default outputs that change only on certain states
"... this is not guaranteed or covered by the verilog spec". Not true: SystemVerilog IEEE1800-2017 section 4.6 states "Statements within a begin-end block shall be executed in the order in which they appear in that begin-end block"
9

There is nothing nondeterministic about the final value of A in your code, not for simulation, not for synthesis.

However, to be absolutely exact, there is a possible simulation-synthesis-mismatch if the design contains a trigger on A. Consider the following example:

module test(input clk, output reg a, b);
  always @(posedge clk) begin
    a <= 0;
    a <= 1;
  end

  initial b = 0;
  always @(posedge a) begin
    b <= !b;
  end
endmodule

And a test bench:

module tb;
  reg clk = 0;
  always #5 clk = ~clk;

  wire a, b;
  test uut (clk, a, b);

  initial begin
    $monitor("clk=%b a=%b b=%b", clk, a, b);
    repeat (100) @(posedge clk);
    $finish;
  end
endmodule

During simulation both updates a <= 0 and a <= 1 are pushed to the NBA events region and are executed in-order, so a always ends up being set. However, as the a <= 0 is executed as well, there is a negative pulse with zero width on a for every clock cycle. This pulse triggers the 2nd always block. This is the simulation output (tested with Icarus Verilog and Modelsim):

clk=0 a=x b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
...

However, in synthesis this will simply assign a the constant value 1 and b the constant value zero. (Tested with Yosys and Xilinx Vivado.) So the post-synthesis simulation output looks like this:

clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0

(Theoretically the first line could still say a=x, but every decent synthesis tool would optimize the a-flip-flop away, as both tools in the test did.)

Other than that there is no potential issue with that code, and as @Morgan pointed out correctly in his answer, this is a very usual coding technique for defining the "default values" of output signals before encoding the special cases using conditional assignments (using if and/or case).

Comments

1

According to the "Determinism" section in the IEEE Std (1800-2009, for example), if those statements are in a begin-end block, A will always be assigned the value 2 in simulation.

However, the Std does not guarantee how the code will be synthesized. The resultig gates probably depend on the synthesis tool. But, a good RTL linting tool will identify such bad coding. Cadence's Hal lint tool issues a warning.

Comments

-5

from RTL point of view. "A" will be assigned 1 and 2 ,it can be first 1 and then 2 or vice versa, but you can't really know which value will be assigned in the end of begin-end block it can be 1 or 2 (as the second value which was assigned).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.