Electronic – Verilog: Comparison after non-blocking assignment

verilog

I've seen Verilog code which looks something like the following:

...

reg [9:0] count;

always @ (posedge clk)

   count <= count + 1
   if (count == 10'b1000) begin
      ...
   end

   ...

end

I'm wondering how this actually behaves; will the comparison use the new, or the old value of count?

I've been told that all the non-blocking assignments occur in parallel, so if there was the line x <= count further down in the same always block, then this would use the old value of count, which is why I find it ambiguous which value the comparison will use.

Best Answer

If you are primarily a software engineer, you can think of Verilog as using internal copies of the assigned variables within the always block. In implementation terms, the "internal variables" are not really there, but it is never the less a good way of visualising how it works.

Consider the following code:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

This is effectively performed as:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = a_int + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Notice how non-blocking statements cause any calculations to be performed on the external (global if you will) variable. However blocking statements cause the calculations to be performed using the internal (local) variable.

At the end of the always block, the resulting value of the internal variable is assigned back to the external one.

In your case, you are using non-blocking assignments for count, so your calculations will use the external variable, which will contain the "old" value, and not the "new" incremented value.


As you become more familiar, you start instead thinking in terms of hardware as @Oldfart describes.


Side note: This is why it is a bad idea to mix blocking and non-blocking. You end up calculating on an unpredictable combination of internal and external values, which can result in very different synthesis vs simulation results.