Close Menu
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
Instagram LinkedIn WhatsApp Telegram
Instagram LinkedIn WhatsApp Telegram
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
VLSI Web
UVM

UVM Drivers, Monitors and Agents: Building a Reusable Agent

Raju GorlaBy Raju Gorla23 June 2026Updated:11 October 2026No Comments4 Mins Read
UVM drivers, monitors and agents
Share
Facebook Twitter LinkedIn Email Telegram WhatsApp

The short answer: A UVM agent bundles everything for one interface: a sequencer and driver to create stimulus (in active mode) and a monitor to observe the interface (always). The driver pulls items from the sequencer and drives them through a virtual interface; the monitor samples the pins, rebuilds transactions and broadcasts them on an analysis port. A configuration object sets the agent active or passive, so the same agent can drive a block’s inputs at block level and just observe at chip level.

Agents are the reusable unit of UVM. A well-written agent for AXI or a UART can be dropped into any project. This post shows the three classes inside an agent and the agent itself, with the rules that make them reusable.

  1. What’s inside an agent
  2. The driver
  3. The monitor
  4. The agent
  5. Rules for reusable agents

Table of Contents

  • Part 1: What’s inside an agent
  • Part 2: The driver
  • Part 3: The monitor
  • Part 4: The agent
  • Part 5: Rules for reusable agents
  • FAQ
    • What is a UVM agent?
    • What is the difference between an active and a passive agent?
    • Why should the monitor create a new object for every transaction?
    • Where should protocol checks go?

Part 1: What’s inside an agent

A UVM agent: driver, monitor, sequencer and agent configuration, active or passive
Active agents drive; passive agents only observe.

Part 2: The driver

class bus_driver extends uvm_driver #(bus_item);
  `uvm_component_utils(bus_driver)
  virtual bus_if vif;

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

  task run_phase(uvm_phase phase);
    vif.cb.valid <= 0;
    forever begin
      seq_item_port.get_next_item(req);
      repeat (req.delay) @(vif.cb);
      vif.cb.valid <= 1;
      vif.cb.addr  <= req.addr;
      vif.cb.write <= (req.kind == bus_item::WRITE);
      vif.cb.wdata <= req.data;
      do @(vif.cb); while (!vif.cb.ready);
      if (req.kind == bus_item::READ) req.data = vif.cb.rdata;
      vif.cb.valid <= 0;
      seq_item_port.item_done();
    end
  endtask
endclass

Part 3: The monitor

class bus_monitor extends uvm_monitor;
  `uvm_component_utils(bus_monitor)
  virtual bus_if vif;
  uvm_analysis_port #(bus_item) ap;

  function new(string name, uvm_component parent);
    super.new(name, parent);
    ap = new("ap", this);
  endfunction

  task run_phase(uvm_phase phase);
    forever begin
      @(vif.cb);
      if (vif.cb.valid && vif.cb.ready) begin
        bus_item t = bus_item::type_id::create("t");
        t.kind = vif.cb.write ? bus_item::WRITE : bus_item::READ;
        t.addr = vif.cb.addr;
        t.data = vif.cb.write ? vif.cb.wdata : vif.cb.rdata;
        ap.write(t);
      end
    end
  endtask
endclass

A new object for every transaction matters: subscribers may keep the handle, so reusing one object would overwrite their data.

Part 4: The agent

class bus_agent extends uvm_agent;
  `uvm_component_utils(bus_agent)
  bus_agent_cfg              cfg;
  uvm_sequencer #(bus_item)  sqr;
  bus_driver                 drv;
  bus_monitor                mon;

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

  function void build_phase(uvm_phase phase);
    if (!uvm_config_db#(bus_agent_cfg)::get(this, "", "cfg", cfg))
      `uvm_fatal("NOCFG", "agent config not set")
    mon = bus_monitor::type_id::create("mon", this);
    if (cfg.is_active == UVM_ACTIVE) begin
      sqr = uvm_sequencer#(bus_item)::type_id::create("sqr", this);
      drv = bus_driver::type_id::create("drv", this);
    end
  endfunction

  function void connect_phase(uvm_phase phase);
    mon.vif = cfg.vif;
    if (cfg.is_active == UVM_ACTIVE) begin
      drv.vif = cfg.vif;
      drv.seq_item_port.connect(sqr.seq_item_export);
    end
  endfunction
endclass

Here the virtual interface travels inside the agent’s configuration object, which is a common and tidy pattern.

Part 5: Rules for reusable agents

  • Monitors never drive anything and never depend on the driver; they must work in passive mode.
  • No DUT-specific checking inside the agent; put it in the environment’s scoreboard.
  • Protocol checks (assertions) belong in the interface, so they run in both modes.
  • Everything configurable (active/passive, timeouts, coverage on/off) lives in the agent’s config object.
  • Ship the agent with its item, basic sequences and a package, so it’s easy to import.

Practise this on VLSI Forge

I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.

Design Verification problems · Daily challenge

Previous in my UVM series: Sequences and sequencers. Next: Phases and objections.

FAQ

What is a UVM agent?

A component that groups a sequencer, driver and monitor for one interface, configurable as active (drives) or passive (observes only).

What is the difference between an active and a passive agent?

An active agent has a sequencer and driver and generates stimulus; a passive agent has only a monitor and observes.

Why should the monitor create a new object for every transaction?

Subscribers like scoreboards keep the handle. Reusing one object would change data they have already stored.

Where should protocol checks go?

Usually as assertions in the SystemVerilog interface, so they work whether the agent is active or passive.

Share. Facebook Twitter LinkedIn Email Telegram WhatsApp
Previous ArticleUVM Sequences and Sequencers: How Stimulus Reaches the Driver
Next Article UVM Phases and Objections: How a Test Starts, Runs and Ends
Raju Gorla
  • Website

Related Posts

UVM

UVM Reporting and Messaging: Verbosity, Actions and Report Catchers

2 July 2026
UVM

UVM Callbacks: Changing Component Behaviour from a Test

1 July 2026
UVM

The UVM Register Model (RAL): Adapters, Prediction and Access Methods

30 June 2026
Add A Comment
Leave A Reply Cancel Reply

Topics
  • Digital Circuits
  • Informative
  • Interview Questions
  • Physical Design
  • RTL Design
  • STA
  • System Verilog
  • UVM
  • Verilog
Instagram LinkedIn WhatsApp Telegram
  • About
  • Contact
  • Privacy Policy
  • VLSI Forge
  • Courses
  • Feedback
© 2026 VLSI Web

Type above and press Enter to search. Press Esc to cancel.