A sequencer generates data transactions as class objects and sends it to the Driver for execution. It is recommended to extend uvm_sequencer base class since it contains all of the functionality required to allow a sequence to communicate with a driver. The base class is parameterized by the request and response item types that can be handled by the sequencer.


By default, the response type is the same as the request type, and if required to be different, you may specify it as the second parameter during instantiation. Unless you have additional ports to be included, you should directly instantiate it as a uvm_sequencer parameterized to the required data item.

// class uvm_sequencer #(type REQ = uvm_sequence_item, RSP = REQ) extends uvm_sequencer_param_base #(REQ, RSP);
uvm_sequencer #(my_data, data_rsp) seqr0;            // with    RSP
uvm_sequencer #(my_data)           seqr0;            // without RSP

Generation of objects within the sequencer is very limited in terms of flexibility and re-usability. We'll see how this limitation can be overcome via sequences.

Custom Sequencer

It is not really required to create a custom sequencer to execute every sequence or for every agent. But you can create your version of the UVM sequencer with additional features and create instances of it throughout the testbench.

  class my_sequencer extends uvm_sequencer;
    `uvm_component_utils (my_sequencer)
    function new (string name="m_sequencer", uvm_component parent);
      super.new (name, parent);
Class Hierarchy

Refer to Class Definitions for uvm_sequencer method declarations.

Was this article helpful ?