3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ It will use the "old" value. But you know that already. What is ambiguous here? \$\endgroup\$ – Eugene Sh. Jun 7 '18 at 15:00
  • \$\begingroup\$ Google "verilog event regions" and take a look at the flowcharts and/or papers. Then, if you are still interested, replace "verilog" with "systemverilog" to see the event regions that were added (you will get SV hits with the word Verilog too). And, you can add "Cliff Cummings Sunburst Design" to your search and follow the links to some really good papers he has written or co-authored regarding this subject. In the past, I have had the flowchart(s) printed out on my wall as a quick reference, for those times that it mattered \$\endgroup\$ – CapnJJ Jun 7 '18 at 15:43
  • \$\begingroup\$ Also, if you never have, it is worth checking out Stu Sutherland (sutherland-hdl.com) for some useful Verilog "gotchas" \$\endgroup\$ – CapnJJ Jun 7 '18 at 15:53
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

It will use the current value of count.

As to 'finding it ambiguous' is just a matter of perception. HDL programmers have a different view of the world.

Try to think of it this way:

We have a signal count. Count is a set of wires.

  • You have a piece of hardware (Lets call it HwA) using count.
  • You have a second piece of hardware (HwB) changing count.

The hardware that changes 'count' works in parallel with whatever is using count.

No matter where I place HwA, before, after or adjacent to HwB it always uses the wires of count, whatever is on those wires at this moment.

\$\endgroup\$
0
\$\begingroup\$

The value of "count" won't be updated until each statement in the block has been evaluated...thus, it will evaluate the old value. Imagine the actual counter...the output doesn't update immediately on the clock edge, but some finite time later, preserving causality. With the if statement inside the always block, you're implying that the output of the comparison is registered as well, so the simulation accurately reflects this configuration. If you intend for the comparison do be done asynchronously, take it out of that block.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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