4
\$\begingroup\$

As their names imply, Non blocking assignments allow concurrent execution while blocking assignments execute sequentially.

Take Nandland’s explanation for example:

In C, “The second line is only allowed to be executed once the first line is complete.” This is used as an example or analogy to blocking statements in HDL.

He then uses an example of 3 non blocking vs 3 blocking statements inside an always block yet says it will take 3 clock cycles for the non blocking example to execute the third statement whereas the blocking assignments “immediately” confer the their value to the next register.

always @(posedge i_clock)
  begin
   r_Test_1 <= 1'b1;
   r_Test_2 <= r_Test_1;
   r_Test_3 <= r_Test_2;
  end

// versus:

always @(posedge i_clock)
 begin
  r_Test_1 = 1'b1;
  r_Test_2 = r_Test_1;
  r_Test_3 = r_Test_2;
 end

It seems to me like their names should be switched. Where is my misconception? Why name the assignments non blocking in sequential logic when sequential statements patently block succeeding statements from being executed as they are SEQUENTIAL statements?

\$\endgroup\$
6
  • 6
    \$\begingroup\$ "it will take 3 clock cycles for the non blocking example to execute the third statement" - I don't believe that is the right interpretation. It takes 3 cycles for the value to propagate to Test_3, which is not the same thing. \$\endgroup\$
    – Mat
    Aug 27, 2021 at 10:14
  • \$\begingroup\$ Well if we consider the 3rd statement to be r_Test_3 <= r_Test_2; then I’m not sure why you think this is an erroneous interpretation because it certainly does take 3 clock edges to pass before the first statement’s value is passed to the last. Ergo the intermediate statements appear to be “blocking” \$\endgroup\$
    – Andrew
    Aug 27, 2021 at 10:31
  • \$\begingroup\$ @Andrew because if you switch the value of r_Test_1 each clock cycle as well, r_Test_3 will have a steady state value change every clock cycle. "it takes 3 clock cycles to pass before the 3rd statement is executed" implies that would be impossible. \$\endgroup\$
    – DonFusili
    Aug 27, 2021 at 10:51
  • \$\begingroup\$ Synthesise both and note the maximum clock rate. You will notice that one can be clocked faster than the other. \$\endgroup\$ Aug 27, 2021 at 12:19
  • \$\begingroup\$ If you are worried about the term 'blocking' -- In this particular case, Test3's assignment is 'blocked' until the Test2 is evaluated whose assignment is blocked until Test1 is evaluated. \$\endgroup\$
    – Mitu Raj
    Aug 27, 2021 at 13:02

3 Answers 3

5
\$\begingroup\$

It isn't the assignment that's being "blocked", it's the evaluation of the statements within the process.

First of all, in both cases, all of the statements are evaluated on every clock cycle. But as pointed out in a comment, with non-blocking assignment, it takes three clock cycles before the value propagates to the last register.

With non-blocking assignment, the three statements can be executed concurrently (e.g., in hardware), or in any arbitrary order, and always produce the same result. The evaluation of any one statement does not "block" the evaluation of the others.

With blocking assignment, the assignments must be completed in the order in which they appear, just like in C code. Each statement "blocks" the execution of the statements that follow it.

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

Why does “non blocking” assignment in Verilog seem like a misnomer?

Because it is a misnomer.

The term non-blocking was created as a corollary antonym to the prior misnomer blocking.

Better terms for blocking and non-blocking would be ordered evaluation and unordered evaluation or series evaluation and parallel evaluation.

But then there is a cruel twist: The ordered evaluation is synthesised as a parallel circuit whereas the unordered evaluation is synthesised as a series circuit.

"Blocking" misnomer "Non-Blocking" antonym misnomer
Ordered evaluation (source-code order) Unordered evaluation (order determined by simulator)
Series evaluation (source-code order) Parallel evaluation (order determined by simulator)
Parallel synthesis Series synthesis

Here is a Verilog example that I synthesised with Quartus.

module BlockingNonBlocking
(
    input wire clock,
    input wire data,

    output reg R1,
    output reg R2,
    output reg R3,
    output reg R4,
    output reg R5,
    output reg R6
);

    // "Blocking" misnomer
    // Ordered evaluation (source-code order)
    // Series evaluation (source-code order)
    // Parallel synthesis
    always @(posedge clock)
    begin
        R1 = data;
        R2 = R1;
        R3 = R2;
    end

    // "Non-Blocking" antonym misnomer
    // Unordered evaluation (order determined by simulator)
    // Parallel evaluation (order determined by simulator)
    // Series synthesis
    always @(posedge clock)
    begin
        R4 <= data;
        R5 <= R4;
        R6 <= R5;
    end

endmodule

Blocking versus non-blocking synthesis

Figure 1 – Blocking versus non-blocking synthesis.

As you can see, both variants block (in the true sense of the word) the data signal until the positive edge of the clock which means that both are sequential circuits, but R1, R2 and R3 are in parallel while R4, R5 and R6 are in series.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Best explanation I've ever seen on the topic, at least for me. \$\endgroup\$
    – Uncle Dino
    Aug 28, 2021 at 16:53
  • 1
    \$\begingroup\$ really fantastic! I would like to make this the accepted answer but I feel bad taking it from Dave since I already gave it to him. The visual of the synthesized result is absolutely illuminating. Thank you! \$\endgroup\$
    – Andrew
    Aug 29, 2021 at 0:56
1
\$\begingroup\$

The terms blocking and non-blocking have more to do with simulation process execution semantics than synthesis. It is unfortunate that block is also a homonym for a contiguous grouping or area (a begin/end block of statements).

Both blocking and non-blocking assignments are procedural statements that execute sequentially within the scope of a begin/end process. Both statements evaluate the right-hand-side expression as they are encountered, but the difference between them is better shown with intra assignment delays:

initial begin
     #10
     b = #5 a;
     c = #5 b;
end
initial begin
     #10
     b <= #5 a;
     c <= #5 b;
end

Both initial processes start at time 0, then delay for 10 time units. Both assignment statements evaluate the value of a at time 10. But the first blocking assignment suspends the process for 5 time units, does not update b until time 15, and does not start executing the second blocking assignment until time 15. It also suspends the initial process and does not update c until time 20, which is when the first initial process ends.

The first non-blocking assignment in the second initial process schedules and update to b at time 15, but does not suspend the process. So the second non-blocking assignment evaluate b at time 10, which is its 'old' value. It schedules an update to c with the old value of b at time 15. The second initial process ends at time 10.

BTW, you rarely see blocking assignments with intra-assignment delays. It is leftover from very early Verilog before non-blocking assignments were introduced (by me) into the language.

\$\endgroup\$

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.