Agents & Environments
Build reusable agents that bundle driver/monitor/sequencer, and environments that compose multiple agents.
Agents & Environments
Agents and environments are the organizational backbone of a UVM testbench. They provide structure, reusability, and modularity.
The Agent
A UVM agent encapsulates everything needed to interact with one interface:
systemverilogclass apb_agent extends uvm_agent; `uvm_component_utils(apb_agent) apb_sequencer sequencer; apb_driver driver; apb_monitor monitor; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); // Monitor is ALWAYS created monitor = apb_monitor::type_id::create("monitor", this); // Driver & sequencer only in ACTIVE mode if (get_is_active() == UVM_ACTIVE) begin sequencer = apb_sequencer::type_id::create("sequencer", this); driver = apb_driver::type_id::create("driver", this); end endfunction function void connect_phase(uvm_phase phase); if (get_is_active() == UVM_ACTIVE) driver.seq_item_port.connect(sequencer.seq_item_export); endfunction endclass
Configuring Active vs Passive
systemverilog// In the environment's build_phase: // Make the slave agent passive (monitor only) uvm_config_db#(uvm_active_passive_enum)::set( this, "slave_agent", "is_active", UVM_PASSIVE );
The Environment
The environment composes multiple agents and connects them to verification components:
systemverilogclass soc_env extends uvm_env; `uvm_component_utils(soc_env) apb_agent apb_agt; axi_agent axi_agt; soc_scoreboard scoreboard; soc_coverage coverage; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); apb_agt = apb_agent::type_id::create("apb_agt", this); axi_agt = axi_agent::type_id::create("axi_agt", this); scoreboard = soc_scoreboard::type_id::create("scoreboard", this); coverage = soc_coverage::type_id::create("coverage", this); endfunction function void connect_phase(uvm_phase phase); // Wire monitors to scoreboard apb_agt.monitor.ap.connect(scoreboard.apb_export); axi_agt.monitor.ap.connect(scoreboard.axi_export); // Wire monitors to coverage apb_agt.monitor.ap.connect(coverage.apb_export); endfunction endclass
Hierarchical Environments
Environments can contain other environments for complex SoC verification:
textsoc_env ├── cpu_subsystem_env │ ├── axi_agent (active) │ └── cpu_scoreboard ├── peripheral_env │ ├── apb_agent (active) │ ├── spi_agent (passive) │ └── periph_scoreboard └── soc_scoreboard (top-level checking)
Reusability in Action
Write an APB agent once, use it in every project:
systemverilog// Project A — SoC verification class soc_env extends uvm_env; apb_agent apb_agt; // Same agent reused! // ... endclass // Project B — Peripheral verification class periph_env extends uvm_env; apb_agent apb_agt; // Same agent — zero rework! // ... endclass
Best Practices
| Practice | Why |
|---|---|
| One agent per interface | APB agent, AXI agent, SPI agent, etc. |
| Agent = self-contained | No external dependencies |
| Environment = composition | Connect agents to scoreboards and coverage |
Use config_db for configuration | Active/passive, interface handles |
| Keep hierarchy shallow | 2-3 levels is usually enough |