Virtual Sequencer in UVM

A virtual sequencer is used to coordinate activity across multiple sequencers. This page explains the concept from scratch using a simple and practical example.

1. The Problem We Want to Solve

In a simple UVM environment, a sequence communicates with a single sequencer, which then sends transactions to the driver.


sequence → sequencer → driver → DUT

This works well when only one interface exists. However, real designs usually contain multiple interfaces such as memory, interrupts, configuration buses, or debug interfaces.

Each interface has its own agent and sequencer. The challenge appears when a test must coordinate activity across multiple interfaces.

2. Why a Normal Sequencer Is Not Enough

A normal sequencer controls only one driver and one interface. System-level scenarios require:

  • Multiple sequencers running together
  • Ordering between operations
  • Synchronization between interfaces

For example:


1. Send write transaction
2. Wait for interrupt
3. Read status register

This coordination cannot be handled cleanly by a single agent sequence.

3. What Is a Virtual Sequencer?

A virtual sequencer is a central object that contains handles to multiple real sequencers.

  • It does not connect to a driver
  • It does not send transactions to the DUT
  • It only provides access to other sequencers

        Virtual Sequencer
           /         \
   Write Sequencer  Read Sequencer

It acts as a coordinator between different interfaces.

4. Virtual Sequencer vs Virtual Sequence

Virtual Sequencer

A container that stores references to other sequencers.


class virtual_sequencer extends uvm_sequencer;

  write_sequencer wr_seqr;
  read_sequencer  rd_seqr;

endclass
Virtual Sequence

The virtual sequence is the brain. It runs on the virtual sequencer and controls multiple sequences.


wseq.start(p_sequencer.wr_seqr);
rseq.start(p_sequencer.rd_seqr);

5. Basic Example Environment

The virtual sequencer allows one test to control both interfaces.

Virtual Sequencer Block Diagram

6. Virtual Sequencer Implementation


class virtual_sequencer extends uvm_sequencer;

  `uvm_component_utils(virtual_sequencer)

  write_sequencer wr_seqr;
  read_sequencer  rd_seqr;

  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction

endclass

Notice that no driver or transaction handling exists here.

7. Connecting Sequencers in the Environment


class my_env extends uvm_env;

  `uvm_component_utils(my_env)

  write_agent        wr_agent;
  read_agent         rd_agent;
  virtual_sequencer  vseqr;

  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    wr_agent = write_agent::type_id::create("wr_agent", this);
    rd_agent = read_agent::type_id::create("rd_agent", this);
    vseqr    = virtual_sequencer::type_id::create("vseqr", this);
  endfunction

  function void connect_phase(uvm_phase phase);

    vseqr.wr_seqr = wr_agent.seqr;
    vseqr.rd_seqr = rd_agent.seqr;

  endfunction

endclass

This step allows the virtual sequence to access both sequencers.

8. Virtual Sequence Example


class virtual_sequence extends uvm_sequence;

  `uvm_object_utils(virtual_sequence)
  `uvm_declare_p_sequencer(virtual_sequencer)

  function new(string name = "virtual_sequence");
    super.new(name);
  endfunction

  task body();

    write_seq wseq;
    read_seq  rseq;

    wseq = write_seq::type_id::create("wseq");
    rseq = read_seq::type_id::create("rseq");

    `uvm_info("VSEQ", "Starting WRITE", UVM_LOW)
    wseq.start(p_sequencer.wr_seqr);

    `uvm_info("VSEQ", "Starting READ", UVM_LOW)
    rseq.start(p_sequencer.rd_seqr);

  endtask

endclass

The virtual sequence defines the system behavior by controlling multiple sequencers.

9. Execution Flow

  1. The test starts the virtual sequence.
  2. The virtual sequence runs on the virtual sequencer.
  3. The virtual sequence starts sequences on real sequencers.
  4. Drivers execute transactions on the DUT.
Key Takeaway
  • Sequencer → controls one interface
  • Virtual sequencer → holds multiple sequencers
  • Virtual sequence → coordinates system behavior

Complete Source Code

This page explains the architecture and concepts behind the virtual sequencer example. To explore the full SystemVerilog and UVM implementation, including environment setup, sequences, and test configuration, visit the repository below.

View on GitHub