0
\$\begingroup\$

Consider HDL code below:

module top_module ();

reg [2:0] a, b, c;

initial begin
   a = 3'b001; b = 3'b010; c = 3'b011; 
end

initial begin
    #5 $display ("a = %d, b = %d, c = %d", a, b, c);
end

initial begin
    a <= b;
    b <= c;
    // b <= a;
    $display ("a = %d, b = %d, c = %d", a, b, c);
    #50 $finish;            // Quit the simulation
end    
endmodule

The output is:

Running Icarus Verilog simulator...
a = 1, b = 2, c = 3
VCD info: dumping is suppressed.
a = 2, b = 3, c = 3
Hint: Total mismatched samples is 0 out of 0 samples

Simulation finished at 50 ps
Mismatches: 0 in 0 samples

In the above code: (a = 1, b = 2, c = 3) initially: Scene-1:

a <= b;
b <= c;

I get: a = 2, b = 3, c = 3; Hence initial, un-updated value of b. (a = 1, b = 2, c = 3) initially:

Scene-2:

a <= b;
b <= c;
a <= c;

I get: a = 3, b = 3, c = 3;

Even more, if I do this:

Scene-3:

a <= b;
b <= c;
a <= b;

then too I get: a = 2, b = 3, c = 3;

In scene-1 and 3, a is getting the value as per the older assignment of b, but in scene-2, it is getting the latest value as per the latest assignment of c. I'm trying to wrap my head around this, need to get better understanding of this.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Here's how I think of it: there is a "current" state and a "next" state. When you write a <= b;, you're not changing a, you're saying "the next value of a will be the current value of b". If then you write a <= c;, it's like you've changed your mind and would rather have the next value of a be the current value of c instead. Only when the next tick happens (in your scenario) do the values actually change - and they take up whatever the last assignment you wrote say they should. \$\endgroup\$
    – Mat
    Commented May 26, 2022 at 16:06
  • 1
    \$\begingroup\$ @Mat I love this convention and I'll keep it in mind! BTW this comment is as powerful as an answer. \$\endgroup\$
    – lousycoder
    Commented May 27, 2022 at 3:04

1 Answer 1

2
\$\begingroup\$

First of all, your code has a race condition at time 0. There is no guarantee that the first initial block executes before the third initial block. The second initial block will guarantee to execute the $display statement last because of the #5 delay.

Non-blocking assignments evaluate the RHS of the assignment at the point in time when the statement gets executed, and the updates to the LHS get scheduled for a later region of time. So the values used on the RHS for a, b, and c will either be 1, 2, and 3, or all X's. By sheer luck, iverilog chooses to execute initial blocks in the order they appear in the source. This gets much harder to manage when there are multiple instances of multiple modules.

When you have multiple non-blocking assignments to the same variable, last assignment wins. In scene-2, you assign the old value of b to a, then you assign the old value of c to a. So a gets updated with the old value of c.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.