14
\$\begingroup\$

I was reading this page http://www.asic-world.com/verilog/verilog_one_day3.html when I came across the following:

We normally have to reset flip-flops, thus every time the clock makes the transition from 0 to 1 (posedge), we check if reset is asserted (synchronous reset), then we go on with normal logic. If we look closely we see that in the case of combinational logic we had "=" for assignment, and for the sequential block we had the "<=" operator. Well, "=" is blocking assignment and "<=" is nonblocking assignment. "=" executes code sequentially inside a begin / end, whereas nonblocking "<=" executes in parallel.

I was fairly sure that nonblocking assignments were sequential while blocking assignments were parallel. After all, you can make blocking assignments with assign statements outside of always blocks, and those all run in parallel. Is this a mistake, or is the behavior different inside an always block? And, if the behavior IS different inside an always block, can nonblocking assignments be made outside an always block?

\$\endgroup\$
21
\$\begingroup\$

was fairly sure that nonblocking assignments were sequential while blocking assignments were parallel.

Blocking assignment executes "in series" because a blocking assignment blocks execution of the next statement until it completes. Therefore the results of the next statement may depend on the first one being completed.

Non-blocking assignment executes in parallel because it describes assignments that all occur at the same time. The result of a statement on the 2nd line will not depend on the results of the statement on the 1st line. Instead, the 2nd line will execute as if the 1st line had not happened yet.

\$\endgroup\$
  • \$\begingroup\$ So what about assign statements? Are they just in a whole class of their own? \$\endgroup\$ – Void Star Nov 24 '13 at 4:25
  • 4
    \$\begingroup\$ Yes, assign statements occur outside of always blocks and are generally used to describe to combinatorial (un-latched) logic (while always blocks, with some exceptions, describe sequential logic). AFAIK, assign statements always execute "in parallel" whenever their LHS has a value change. \$\endgroup\$ – The Photon Nov 24 '13 at 4:28
  • \$\begingroup\$ Okay... I'm starting to get the impression that Verilog just isn't the most elegantly designed language. This is gonna be like learning C was. \$\endgroup\$ – Void Star Nov 24 '13 at 5:30
  • 1
    \$\begingroup\$ Verilog was designed to "describe" hardware that already exists. Using it as a language to design (synthesize) hardware is a hack. \$\endgroup\$ – The Photon Nov 24 '13 at 6:02
  • 4
    \$\begingroup\$ if Verilog "like learning C" is a problem, take a look at VHDL. Some people have fairly strong preferences for one or the other. To some, VHDL is just too verbose. To me, it's much better thought out. (signal/variable assignment semantics are much clearer than blocking/non for example). stackoverflow.com/questions/13954193/… and sigasi.com/content/vhdls-crown-jewel You may prefer it or hate it. But it's worth a look. \$\endgroup\$ – Brian Drummond Nov 24 '13 at 10:20
5
\$\begingroup\$

Assign statements are neither "blocking" or "nonblocking", they are "continuous". The output of an assign statement is always equal to the specified function of it's inputs. "blocking" and "nonblocking" assignments only exist within always blocks.

A blocking assignment takes affect immediately it is processed. A nonblocking assignment takes place at the end of processing the current "time delta".

always blocks can be used to model either combinatorial or sequential logic (systemverilog has always_comb and always_ff to make this explicit). When modeling combinatorial logic it's usually more efficient to use = but it typically doesn't really matter.

When modelling sequential logic (e.g. always @(posedge clk) ) you normally use nonblocking assingments. This allows you to deterime the "state after the clock edge" in terms of "the state before the clock edge".

It is sometimes useful to use blocking assignments in sequential always blocks as "variables". If you do this then there are two key rules to bear in mind.

  1. Do not access a reg that is set with blocking assignments inside a sequential always block from outside the always block it is assigned in.
  2. Do not mix blocking and nonblocking assignments to the same reg.

Breaking these rules is likely to result in synthesis failures and/or behaviour differences between simulation and synthesis.

\$\endgroup\$
  • \$\begingroup\$ ""Do not access a reg that is set with blocking assignments inside a sequential always block from outside the always block it is assigned in."" Can you please explain it? \$\endgroup\$ – user125575 Oct 4 '16 at 6:44
  • \$\begingroup\$ Different sequential always blocks do not have a defined order. So reading a "reg" set with a blocking assingment in one always block from another always block will lead to unpredicable behaviour. \$\endgroup\$ – Peter Green Oct 4 '16 at 15:23
  • \$\begingroup\$ And even if it appears to work in simulation, a synthesis tool should look at that and say "nope". I use local regs for those intermediate vars, and make sure that they are always assigned to on every clock before being read, so that no 'storage' is implied. \$\endgroup\$ – greggo Mar 30 '17 at 11:57
  • \$\begingroup\$ IIRC at least in quartus it is only considered a warning not an error. \$\endgroup\$ – Peter Green Mar 30 '17 at 11:59
4
\$\begingroup\$

The term Blocking assignment confuses people because the word blocking would seem to suggest time-sequential logic. But in synthesized logic it does not mean this, because everything operates in parallel.

Perhaps a less confusing term would be immediate assignment, which would still differentiate the intermediate results of combinational logic from the inputs to non-transparent memory elements (for example clocked registers), which can have delayed assignment.

From a legalistic standpoint, it all works out very nicely. You can, in fact, consider the = to be a blocking (time-sequential) operation even within always_comb sequences. However, the distinction between time-sequential and parallel makes absolutely no difference in this case because the always_comb block is defined to repeat until the instruction sequence converges on a stable state -- which is exactly what the hardware circuitry will do (if it meets the timing requirements).

The synthesizable subset of Verilog (and especially SystemVerilog) is extremely simple and easy to use -- once you know the necessary idioms. You just have to get past the clever use of terminology associated with the so-called behavioral elements in the language.

\$\endgroup\$
  • \$\begingroup\$ In behavioral coding styles (as compared to RTL), the distinction between blocking and non-blocking can be relevant. In some cases, the synthesis tool may be able to infer functionally equivalent RTL from behavioral component designs. \$\endgroup\$ – nobar Jul 21 '15 at 17:28
  • \$\begingroup\$ Of course the procedural mode of SystemVerilog, applicable especially to initial statements within program blocks, uses (time-sequential) blocking assignment exclusively. This is useful for testbench design, but generally not for RTL specification. \$\endgroup\$ – nobar Dec 18 '15 at 18:58

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.