SystemVerilog: Use of non-blocking while driving stimulus

This post is about a generally seen practice in any testbench driver. Ever thought that why it is better to use Non-Blocking Assignments (NBA’s) in driver? Let’s see what difference does it create.

As we know that every simulation in Verilog/SV executes according to a pre-defined set of steps known as stratified event queues. These steps are repeated for each an every entity and every time stamp. Let’s first understand the term known as simulation time and time stamp/time slot.

The term simulation time is used to refer to the time value maintained by the simulator to model the actual time it would take for the system description being simulated. The term time is used interchangeably with simulation time.

A time slot encompasses all simulation activity that is processed in the event regions for each simulation time.

Following are the event regions that are executed in each timestamp:


Image courtesy Cummings Paper on SV Event regions

Now let’s consider a D flipflop made using NBA’s and a driver class driving the stimulus. The overall architecture in the code below is as follows:


module dff(input D, input clk, input rst, output reg Q);
always @(posedge clk or negedge rst) begin
if(~rst) begin
Q <=0;
end else begin

Also consider the driver part as follows:

interface interfc(input clk);
logic rst,d,q;

class driver;

virtual interfc intf;

task reset();
intf.d = 0;
#1 intf.rst = 1;
#1 intf.rst = 0;
#1 intf.rst = 1;

task run();
forever begin
@(posedge intf.clk);
intf.d <= $random; // Why use NBA over here?


And the top module that instantiates everything:

module testbench();

logic clk;
driver dr;

always #5 clk = ~clk;

initial begin
clk = 0;
#500 $finish;

dff df(.D(intf.d),.clk(intf.clk),.rst(intf.rst),.Q(intf.q));

interfc intf (clk);

initial begin
dr = new;
dr.intf = intf;


Please remember that all the blocking assignments and the RHS of NBA of modules executes in Active region.

In the given example, the RTL assignment Q<=D evaluates the RHS (i.e. the value of D) in Active region of module and schedules that assignment for NBA region. In the same region, d=$random also gets executed. So there is a race condition that which statement is executed first.

  • If Q<=D executes first then Q  will be scheduled to get previous value of D in the NBA region of same time slot. (No issues 🙂 )
  • If d=$random executes first then the Q<=D gets updated value of D and Q will be scheduled to get updated value in NBA region of same time slot. (Big Problem!! 😦 )

Waveforms for Blocking assignments:


As we can see, while using blocking assignments to drive D, there happens a race condition between the code in testbench module and dff module. The value of Q is updated on the same clock pulse when D is updated. Henceforth the concept of flip-flop is compromised even though the RTL code seems to be correct! 

Now, in order to tackle the situation, we use NBA while driving the stimulus.


By using NBA’s, we minimize the race condition between the TB and RTL. Here, it becomes certain that Q<=D is scheduling previous value of D in the Active region. Also, in the NBA region, the previous value of D is assigned to Q and D gets a new/updated random value.

Waveforms using Non-Blocking assignments:


Thus, using NBA’s, the actual intent of flip-flop is simulated correctly.

Using NBA’s is a good practice and simplest solution. There can be some alternatives to this:

  • Use program block and drive everything in Reactive region set. This is not preferred option since in UVM based testbench, we may use module block as well.
  • Use clocking blocks in interface. I personally don’t prefer clocking blocks due to complexity in understanding the wavedumps.

Note that NBA’s only minimizes the races, and it depends on the code about eliminiting races completely. The sample code is available on EDAPlayground here. Hope that the mystery of using NBA’s in drivers is now unleashed. Feel free to post in the comments section.


profile for sharvil111 at Stack Overflow, Q&A for professional and enthusiast programmers

4 responses

  1. Nice explanation. I have one doubt do correct me,
    1) most of design verilog module’s inputs are wire in that case BA or NBA does it make difference.
    2) Some of the inputs wire might be an input to Flop because most of design take the approach to register the Input because of CDC or .. in that case NBA is must.


    1. Thanks Harsh!

      The inputs to any module are always wire (Refer

      The Point-2 is correct since flopping stage in RTL will have NBA assignments. And driving those inputs via NBA’s will help in settling down the RTL values at the clock edge.

      Now, when there is some combo logic on inputs in the RTL, still NBA is preferable to avoid races in Active region.

      In a nutshell, the TB should not depend on the type of logic inside RTL, so use NBA’s while driving inputs independent of RTL coding schema.

      Liked by 1 person

  2. Hi Sharvil,

    At time of posting comment, one piece of code came in mind.. where BA assignment was used and it worked fine.. but then after some ponder recalled that clocking block was present in same TB setup.
    Similar situation you already pointed in post related to clocking block, hence doubt is cleared.


    Liked by 1 person

    1. Correct. Nice to see that the doubt is gone. The clocking blocks can be used to sample the input values by providing skew.

      One thing to note that this is a race two modules. This can be simulator dependent, since all the initial/always blocks are executing concurrently.

      Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: