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?
-
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– Mat2021年08月27日 10:14:05 +00:00Commented 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– Andrew2021年08月27日 10:31:06 +00:00Commented 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– DonFusili2021年08月27日 10:51:13 +00:00Commented 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\$user16324– user163242021年08月27日 12:19:50 +00:00Commented 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– Mitu Raj2021年08月27日 13:02:53 +00:00Commented Aug 27, 2021 at 13:02
3 Answers 3
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.
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.
-
2\$\begingroup\$ Best explanation I've ever seen on the topic, at least for me. \$\endgroup\$Uncle Dino– Uncle Dino2021年08月28日 16:53:31 +00:00Commented 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– Andrew2021年08月29日 00:56:47 +00:00Commented Aug 29, 2021 at 0:56
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.