How does #delay work for Verilog non-blocking statements?

Viewed 1978

What will be printed for A and B in the second $display statement?

module blocking;

reg[0:7] A, B;

initial begin
   A = 3;
   #1 A = A + 1; 
   B = A + 1;
   $display("Blocking: A= %d B= %d", A, B ); // A = 4, B = 5
   A = 3;
   #1 A <= A + 1;
   B <= A + 1;
   #1 $display("Non-blocking: A= %d B= %d", A, B ); // A = ?, B = ?
end
endmodule

How does event scheduling in Verilog work with respect to delays and non-blocking statements?

2 Answers

In the 2nd $display, since you have put the display in another timeslot (with #1), the updated value of A & B will be printed.

module blocking;
   reg[0:7] A, B;
   
   initial begin
     A = 3;
#1   A = A + 1; 
     B = A + 1;
     $display("Blocking: A = %0d B = %0d", A, B ); // A = 4, B = 5
     A = 3;
#1   A <= A + 1;
     B <= A + 1;
#1   $display("Non-blocking: A = %0d B = %0d", A, B ); // A = ?, B = ?
   end
endmodule

Output:

Blocking: A = 4 B = 5
Non-blocking: A = 4 B = 4

But if you put the $display in the same timeslot (without #1), then the unupdated values of A & B will be printed.

module blocking;
   reg[0:7] A, B;
   
   initial begin
     A = 3;
#1   A = A + 1; 
     B = A + 1;
     $display("Blocking: A = %0d B = %0d", A, B ); // A = 4, B = 5
     A = 3;
#1   A <= A + 1;
     B <= A + 1;
     $display("Non-blocking: A = %0d B = %0d", A, B ); // A = ?, B = ?
   end
endmodule

Output:

Blocking: A = 4 B = 5
Non-blocking: A = 3 B = 5

The reason for that is scheduling of events in Verilog.

$display is scheduled in the active region, which is before the NBA (Non Blocking Assignment) region and hence it will have the original values of the nonblocking assigned signals in the same timeslot.

Because you have #1 before the second $display statement, it will be executed in the next cycle after A and B are settled.

Say we are at cycle #1.

A = 3; // at #1
#1 // (does not matter) --> #2
A <= A + 1; // #2 will do A + 1 and wait till the end of the cycle 
B <= A + 1; // #2 same as above
// at the end of the cycle #2 (nba scheduling bucket) before switching to #3 
//    A and B will be assigned '4'
#1 // --> #3
// new values of A and B are available here (4)
$display("Non-blocking: A= %d B= %d", A, B );
Related