26
\$\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\$

3 Answers 3

28
\$\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\$
7
  • \$\begingroup\$ So what about assign statements? Are they just in a whole class of their own? \$\endgroup\$
    – Void Star
    Nov 24, 2013 at 4:25
  • 6
    \$\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, 2013 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, 2013 at 5:30
  • 2
    \$\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, 2013 at 6:02
  • 6
    \$\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\$
    – user16324
    Nov 24, 2013 at 10:20
11
\$\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\$
5
  • \$\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, 2016 at 6:44
  • 1
    \$\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\$ Oct 4, 2016 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, 2017 at 11:57
  • \$\begingroup\$ IIRC at least in quartus it is only considered a warning not an error. \$\endgroup\$ Mar 30, 2017 at 11:59
  • \$\begingroup\$ You should not be using nonblocking assignment in combinational logic, it can lock up the simulation. For more details, refer this answer: electronics.stackexchange.com/a/506047/238188 \$\endgroup\$ Oct 5, 2020 at 14:55
9
\$\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\$
2
  • \$\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\$ Jul 21, 2015 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\$ Dec 18, 2015 at 18:58

Your Answer

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

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