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.
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, but as others have mentioned this is not guaranteed or covered by the verilog spec.
Usage of this might be a FSM which sparsely defines its outputs:
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.
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).
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:And a test bench:
During simulation both updates
a <= 0
anda <= 1
are pushed to the NBA events region and are executed in-order, soa
always ends up being set. However, as thea <= 0
is executed as well, there is a negative pulse with zero width ona
for every clock cycle. This pulse triggers the 2nd always block. This is the simulation output (tested with Icarus Verilog and Modelsim):However, in synthesis this will simply assign
a
the constant value 1 andb
the constant value zero. (Tested with Yosys and Xilinx Vivado.) So the post-synthesis simulation output looks like this:(Theoretically the first line could still say
a=x
, but every decent synthesis tool would optimize thea
-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/orcase
).