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.
Usage
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);
endfunction
endclass