verilogsystem-verilog

Why does blocking vs. non-blocking matter in this Verilog snippet?


I am trying to get a handle of how simulators treat delay control (via #<delay>) and I am unable to explain the observed difference in the following two snippets:

(1)

module top ();
  reg a,b;
  initial begin
    $monitor("At time %d a=%b b=%b", $time,a,b);
    a = 1'b0;
    b = 1'b0;
    #10 a = 1'b1;
    #10 b = 1'b1;
    a <= #5 1'b0;
    b <= #5 1'b0;
  end
endmodule

(2)

module top ();
  reg a,b;
  initial begin
    $monitor("At time %d a=%b b=%b", $time,a,b);
    a = 1'b0;
    b = 1'b0;
    #10 a = 1'b1;
    #10 b = 1'b1;
    a = #5 1'b0;
    b = #5 1'b0;
  end
endmodule

Note the only difference is between the final two statements in each snippet. The output is such that in the first snippet, both a,b are set to 0 at t=25, whereas in the second we have a=0 at t=25 but b=0 only at t=30. Why is this?

Based on my (clearly limited) understanding, I had thought that a simulator should arrive at the a <= #5 1'b0; statement and then trivially evaluate the 1'b0 RHS, wait 5 time units, and then update a in the non-blocking assignment (NBA) region. In particular, I thought this would mean that the simulator only deals with the b <= #5 1'b0; starting at t=25, as is the case clearly in the blocking case. Why with non-blocking assignments does the simulator proceed onto b <= #5 1'b0; despite the #5 being present in the statement before it? I had thought the difference between blocking and non-blocking assignments was merely that NBA gets done in the NBA region of the stratified Verilog queue, whereas blocking assignment gets done in the active region of the given time slot. Is there another difference of which I am unaware?


Solution

  • The name "blocking assignment" means the next statement in the process gets blocked until the update to the LHS completes. A non-blocking assignment never blocks the process, only the update to the LHS.

    Both nonblocking assignments in your first example execute at time 20 and schedule the update at time 25 without blocking the process.

    In your second example, the last blocking assignment does not start until time 25, and the update happens to the LHS at time 0. In normal coding, you will never use a blocking delay in a blocking assignment (refered to as an intra-assigment blocking delay). It is leftover from pre-historic Verilog from before non-blocking assignments were added to the language in 1989. (I know this date because I was instrumental in adding NBAs to Verilog).