The sequencer controls the flow of
uvm_sequence_item based transactions generated by one or more sequences. There are two types of sequencers :
- uvm_sequencer #(REQ, RSP) :
- uvm_push_sequencer #(REQ, RSP) :
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).
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
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.