UVM Driver and Sequencer Communication

In UVM, there is a mechanism to be followed when we want to send the transactions from the sequencer to the Driver in order to provide stimulus to the DUT. Since we know that the whole intelligence of different type of transactions is imbibed into the sequences and Sequencers are being used as the physical component to execute those Sequences.

A particular Sequence is directed to run on a Sequencer which in turns further breaks down into a series of transaction items and these transaction items are needs to be transferred to the Driver where these transaction items are converted into cycle based signal/pin level transitions.

Note: Transaction is a class of data members to be sent to the DUT, control knobs & constraints information. Transaction item is the object of type Transaction class.

Having said that, sending a transaction/sequence_item from a Sequencer to a Driver is a 4 step process which is listed below:

Sequencer side operation:
  1. Creating the “transaction item” with the declared handle using factory mechanism.
  2. Calling start_item(<transaction_item_handle>). This call blocks the Sequencer till it grants the Sequence and transaction access to the Driver.
  3. Randomizing the transaction OR randomizing the transaction with in-line constraints. Now the transaction is ready to be used by the Driver.
  4. Calling finish_item(<transaction_item_handle>). This call which is blocking in nature waits till Driver transfer the protocol related transaction data.

These are the operational steps from a Sequence which we want to execute using a Sequencer that is connected to a Driver inside an “Agent”. Whole of this process is shown in the Figure 1 & Figure 2 below:


Figure 1: Driver & Sequencer Interaction for Transaction Exchange


Figure 2: Transaction Execution Flow Between a Sequencer , Driver & Virtual Interface

If we talk about the actions taken by the Driver, then the following steps are made by the Driver in order to complete the communication with Sequencer(Sequence):

Driver side operation:
  1. Declaring the “transaction item” with a handle.
  2. Calling the get_next_item(<transaction_item_handle>). Default transaction_handle is “req”. “get_next_item()” blocks the processing until the “req” transaction object is available in the sequencer request FIFO & later “get_next_item” returns with the pointer of the “req” object.
  3. Next, Driver completes its side protocol transfer while working with the virtual interface.
  4. Calling the item_done()” OR “item_done(rsp)“. It indicates to the sequencer the completion of the process. “item_done” is a non-blocking call & can be processed with an argument or without an argument. If a response is expected by the Sequencer/Sequence then item_done(rsp) is called. It results in Sequencer response FIFO is updated with the “rsp” object handle.

The above mentioned handshaking behavior is shown by the written UVM code below:

Sequence Code:

////////// Sequence Declaration

class my_seq extends uvm_sequence #(my_txn);


// Constructor

function new (string name = “”);


endfunction: new

// Body Task

task body;



my_txn txn;

// Step 1


// Step 2

txn = my_txn::type_id::create(“txn”, this);

// Step 3

assert(txn.randomize() with (cmd == 0) );

// Step 4



endtask: body

endclass: my_seq

Following code is part of Driver code.

/////// Driver class

class my_driver extends uvm_driver #(my_txn);




// Run Task

task run_phase (uvm_phase phase);

// Step 1

my_txn txn;

forever begin

// Step 2


// Step 3

@ (posedge vif.clk)


vif.addr = txn.addr;

vif.data = txn.data;

vif.we = txn.we;


// Step 4



endtask: run_phase


endclass: my_driver

I hope it will provide the introductory idea about the concept. For further details, you may refer various available sources..Thank you for your time.



4 thoughts on “UVM Driver and Sequencer Communication

Leave a Reply

Your email address will not be published. Required fields are marked *