1
\$\begingroup\$

In most intros to Verilog, it's basically stated as a law that "blocking is for combinational and nonblocking is for sequential". That turns out to be a good rule of thumb because of how blocking and nonblocking statements work, but that's not a priori what blocking and nonblocking mean.

In Stuart Sutherland's RTL Modeling with SystemVerilog, he writes that one of the prohibitions enforced by synthesis compilers on always procedural blocks aimed at achieving FF synthesis is that

(6) A variable assigned a value in a sequential logic procedure cannot have a mix of blocking and nonblocking assignments. For example, the reset branch cannot be modeled with a blocking assignment and the clocked branch modeled with a non- blocking assignment.

Thus, for instance, the code below for an active-low asynchronous-reset DFF would apparently not synthesize (correctly?):

always @(posedge clk or negedge rstN)
  if (!rstN) q = 0; // NB the blocking statement made here
  else q <= d;

There is no problem from a simulation perspective given that the two branches of the if-else do not interact. Thus, my question is why doesn't synthesis accept/interpret this correctly? As far as I know, the point (6) above is also enforced by the always_ff block. Now that makes sense as a matter of good practice (since, as far as I know, always_ff etc. is meant to be for synthesis), but it still doesn't explain to me why in a general always block the above wouldn't work?

I follow that this is outside of what is a synthesizable construct but I am hoping to understand why that is. That is, I'm hoping to understand why the compiler would struggle with synthesizing this?

\$\endgroup\$
4
  • \$\begingroup\$ Does this answer your question? <Verilog> Mixed blocking & non-blocking assignment \$\endgroup\$ Commented Feb 8 at 18:44
  • \$\begingroup\$ There's no benefit in allowing this. If this behaviour is desired, it can be realized with an additional variable, but in general it is not, and the diagnostic is more useful than having an output file. \$\endgroup\$ Commented Feb 8 at 19:04
  • \$\begingroup\$ @TomCarpenter I don't think it does, no. My question is not about understanding blocking vs nonblocking but rather understanding why the design choice of not allowing mixed statements. \$\endgroup\$
    – EE18
    Commented Feb 8 at 19:17
  • \$\begingroup\$ Fair enough, thank you! @SimonRichter I wasn't sure if there was some deep reason related to hardware modelling that I was missing, rather than just a choice in order to simplify things from the compilation perspective. \$\endgroup\$
    – EE18
    Commented Feb 8 at 19:18

2 Answers 2

1
\$\begingroup\$

Synthesis software varies in what Verilog syntax is supported and what is not supported. Some software may synthesize your code into the logic that you expect, while other software may generate errors and fail to synthesize the code.

I do not have access to the book, but it is reasonable to assume the author intends this to be a guideline for good coding style, rather than a claim that all synthesis tools will prohibit this syntax.

Following the coding style recommendation increases your chance of success: success that you will infer the intended synthesized logic, and success that the simulation will match pre- and post-synthesis.

\$\endgroup\$
3
  • \$\begingroup\$ Understood, thank you as always toolic! Linking this question too which is a related answer (electronics.stackexchange.com/questions/700700/…). \$\endgroup\$
    – EE18
    Commented Feb 8 at 19:22
  • \$\begingroup\$ This answer is does not correctly answer the question. There are specific problems this coding style generates for simulation \$\endgroup\$
    – dave_59
    Commented Feb 11 at 7:42
  • \$\begingroup\$ This answer does correctly answer the question. There are no incorrect statements in the answer. \$\endgroup\$
    – toolic
    Commented Feb 14 at 11:43
0
\$\begingroup\$

In general synthesis tools don't care if you use blocking or nonblocking assignments to variables unless you try to read the same variable after writing to it in the same block. That determines if you need to use the old or new value of the variable. There are no problems doing multiple assignments to the same variable is the same always block as long as you use the same kind of assigment--last write wins.

However there are problems mixing blocking and nonblocking assignments to the same variable that will create functional problems.

The original example mixes synchronous and asynchronous in a single always block. If the posedge clk occurs first, a non-blocking assignment to q gets scheduled. But then a negedge rstN occurs the same time (a race in the same event region), q is set to 0. However the nonblocking assignment to q is still pending. The asynchronous reset gets ignored.

This is an unfortunate consequence of current synthesis tool modeling styles requiring a variables be assigned from only a single always block. Verilog was originally designed to handle this with two seperate `always blocks.

always @(posedge clk) begin // synchronous behavior 
   q <= d;
end
always @(rstN) begin asynchronous behavior
   if (!rstN)
      assign q = 0;  // procedural continuous assignment
   else
      deassign q;
end

A number of synthesis tools used to support this modeling style, but they are now obsolete.

Another problem is much simpler to describe

always @(posedge clk) begin
   flag <=0; // default value
   if (condition)
      flag = 1; // will be overwritten by NBA
end

This is syntactically legal, but will never behave correctly. Synthesis tools flag this as an error because it cannot set the flag to 1. Both assignments should be nonblocking.

\$\endgroup\$
5
  • \$\begingroup\$ Can an always block be entered twice in the Active region of the same simulation time \$t\$? If so, how does changing the reset to a nonblocking assignment fix this? Won't whichever of posedge clk and negedge rstN which happens list "win out" in this case? Perhaps I am not understanding. \$\endgroup\$
    – EE18
    Commented Feb 11 at 15:50
  • \$\begingroup\$ Yes, an always block can be entered for each event in the sensitivity list. When the reset comes first, the if statement prevents overwriting. But the overwriting problem comes in when the clk comes first. \$\endgroup\$
    – dave_59
    Commented Feb 11 at 17:44
  • \$\begingroup\$ I'm sorry that I'm really struggling to follow, but can you explain that a bit more? If the reset comes first then won't we initially set q = 0, but then since we enter again beccause of clk won't we get q = d by the end of the nonblocking active region? \$\endgroup\$
    – EE18
    Commented Feb 11 at 17:53
  • \$\begingroup\$ If reset goes low first (active low), then it doesn't matter which assignment (blocking or nonblocking) you use when the clock rises because only the q assignment to 0 statement gets executed. It might help if you made a table of the 8 possible scenarios with clk or reset coming first to gether with the 4 combinations of assignments to q=0/q=d., q=0/q<=d, etc. \$\endgroup\$
    – dave_59
    Commented Feb 12 at 6:27
  • \$\begingroup\$ Ah I follow now. I missed that (of course) when rstN goes low, it remains there (and so is low for when we enter the always block because of Clk too). Thanks again! \$\endgroup\$
    – EE18
    Commented Feb 12 at 15:49

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.