The sequencer controls the flow of uvm_sequence_item based transactions generated by one or more sequences. There are two types of sequencers :

  1. uvm_sequencer #(REQ, RSP) :
  2. When the driver initiates new requests for sequences, the sequencer selects a sequence from a list of available sequences to produce and deliver the next item to execute. In order to do this, this type of sequencer is usually connected to a driver uvm_driver #(REQ, RSP).

  3. uvm_push_sequencer #(REQ, RSP) :
  4. The sequencer pushes new sequence items to the driver, but the driver has the ability to block the item flow when its not ready to accept any new transactions. This type of sequencer is connected to a driver of type uvm_push_driver #(REQ, RSP)

So, basically we have a pull-push scenario. But, note that a sequence-sequencer communication is always initiated by the user-defined sequence, i.e. it follows a push semantic. Now, you might be wondering how the sequencer and the driver are connected together. As with all UVM components, they also use TLM Interfaces to communicate transactions seq_item_port.


Sequences encapsulate user-defined procedures that generate multiple uvm_sequence_item based transactions. Such sequences can be re-used, extended, randomized and combined sequentially and hierarchically in different and interesting ways to produce realistic stimulus to your DUT. For example, users can encapsulate DUT initialization code, bus-based stress tests, network protocol stacks - anything procedural -- then have them all execute in specific or random order to reach more corner cases.

Some of the major classes are
  • uvm_sequence_item
  • uvm_sequence_base
  • uvm_sequence
  • uvm_sequence_library

Was this article helpful ?