The Universal Verification Methodology (IEEE 1800.2) is the industry-standard framework for building reusable, modular verification environments. It provides base classes for every testbench component, a phasing model for ordered execution, a factory for polymorphic object creation, and a unified reporting system.
UVM is a SystemVerilog class library standardized as IEEE 1800.2. It builds on earlier methodologies (Cadence OVM, Synopsys VMM) and provides:
`include "uvm_macros.svh" and import uvm_pkg::*;This is the most fundamental distinction in UVM architecture:
// uvm_component — structural, persistent, has phases // Lives in the hierarchy with a permanent path name class my_driver extends uvm_driver #(my_item); // Registration macro — required for factory `uvm_component_utils(my_driver) // Always pass parent in constructor function new(string name = "my_driver", uvm_component parent = null); super.new(name, parent); endfunction // Phase methods — called by UVM infrastructure virtual function void build_phase(uvm_phase phase); super.build_phase(phase); endfunction virtual task run_phase(uvm_phase phase); // stimulus logic here endtask endclass // uvm_object — transient data, no hierarchy, no phases // Created and destroyed dynamically during the test class my_item extends uvm_sequence_item; `uvm_object_utils_begin(my_item) `uvm_field_int(addr, UVM_ALL_ON) `uvm_field_int(data, UVM_ALL_ON) `uvm_field_int(write, UVM_ALL_ON) `uvm_object_utils_end rand logic [31:0] addr; rand logic [31:0] data; rand logic write; function new(string name = "my_item"); super.new(name); // no parent — objects have no hierarchy endfunction endclass
| Property | uvm_component | uvm_object |
|---|---|---|
| Base class | uvm_component → uvm_report_object → uvm_object | uvm_object directly |
| Constructor | new(name, parent) | new(name) |
| Hierarchy | Fixed path in TB tree | No hierarchy position |
| Phases | Yes — build, connect, run… | No phases |
| Lifetime | Entire simulation | Created/deleted dynamically |
| Examples | Driver, Monitor, Agent, Env, Test | Sequence item, Sequence, Config obj |
uvm_ (e.g., uvm_driver, uvm_env)my_driver, uart_agent, apb_envmy_driver.sv, uart_pkg.sv_utils macros for registration — never skip them or the factory won't work"my_driver", "env"UVM reporting replaces $display. Messages carry ID strings, severity levels, and verbosity settings that can be filtered at runtime:
// `uvm_info — informational, filtered by verbosity // Syntax: `uvm_info(ID_STRING, MESSAGE, VERBOSITY) `uvm_info("DRV", $sformatf("Driving item: addr=%0h", item.addr), UVM_HIGH) `uvm_info("TEST", "run_phase started", UVM_LOW) // `uvm_warning — always printed, yellow in most simulators `uvm_warning("MON", "Unexpected data seen on bus") // `uvm_error — increments error count, simulation continues `uvm_error("SCB", $sformatf("Data mismatch: exp=%0h got=%0h",exp,got)) // `uvm_fatal — stops simulation immediately `uvm_fatal("CFG", "Virtual interface not set in config_db") // Verbosity levels (highest detail → lowest): // UVM_DEBUG (500) > UVM_HIGH (400) > UVM_MEDIUM (200) // > UVM_LOW (100) > UVM_NONE (0) // Default verbosity is UVM_MEDIUM — HIGH messages are hidden
| Macro | Severity | Behavior |
|---|---|---|
`uvm_info | UVM_INFO | Filtered by +UVM_VERBOSITY; no error count |
`uvm_warning | UVM_WARNING | Always printed; increments warning count |
`uvm_error | UVM_ERROR | Printed; increments error count; sim continues |
`uvm_fatal | UVM_FATAL | Printed; immediately stops simulation |
The minimal complete UVM test: a test that extends uvm_test, builds nothing (no env yet), raises an objection in run_phase to keep simulation alive, prints a message, then drops the objection to end:
// hello_test.sv — minimal UVM test `include "uvm_macros.svh" import uvm_pkg::*; class hello_test extends uvm_test; `uvm_component_utils(hello_test) function new(string name = "hello_test", uvm_component parent = null); super.new(name, parent); endfunction virtual function void build_phase(uvm_phase phase); super.build_phase(phase); `uvm_info("HELLO", "build_phase: constructing testbench", UVM_LOW) // In a real test, create env here: // env = my_env::type_id::create("env", this); endfunction virtual task run_phase(uvm_phase phase); // ALWAYS: raise before any time passes, drop at end phase.raise_objection(this, "Starting Hello UVM test"); `uvm_info("HELLO", "Hello from UVM run_phase!", UVM_LOW) #100; // simulate 100 time units of "activity" `uvm_info("HELLO", "run_phase complete", UVM_LOW) phase.drop_objection(this, "Hello UVM test done"); endtask endclass // tb_top.sv — top-level module module tb_top; `include "uvm_macros.svh" import uvm_pkg::*; import hello_test_pkg::*; initial begin // run_test() hands control to UVM — test selected by +UVM_TESTNAME run_test(); end endmodule
raise_objection, the run_phase completes at time 0 and the simulation ends immediately, even if you have delays in run_phase. This is the most common UVM beginner mistake.UVM phases execute in order across all components. Time-consuming phases (tasks) are synchronized via objections. Function phases complete before any component starts the next phase:
// All function phases (zero simulation time): // build_phase — top-down: create child components // connect_phase — bottom-up: wire TLM ports // end_of_elaboration_phase — final config checks // start_of_simulation_phase — print topology, etc. // Time-consuming task phases: // run_phase — all components run concurrently // (12 fine-grain sub-phases within run: reset, configure, // main, shutdown, etc. — used for precise ordering) // Post-simulation function phases: // extract_phase — extract data from DUT/monitors // check_phase — compare expected vs actual // report_phase — print summary // final_phase — close files, databases class my_component extends uvm_component; `uvm_component_utils(my_component) function void build_phase(uvm_phase phase); super.build_phase(phase); // create children, get config endfunction function void connect_phase(uvm_phase phase); // connect TLM ports between components endfunction task run_phase(uvm_phase phase); // stimulus, monitoring — runs concurrently with all others endtask function void check_phase(uvm_phase phase); // verify expected queue is empty, etc. endfunction function void report_phase(uvm_phase phase); `uvm_info("RPT", $sformatf("Total transactions: %0d", cnt), UVM_NONE) endfunction endclass
// Questa/ModelSim vsim -do 'run -all' +UVM_TESTNAME=hello_test +UVM_VERBOSITY=UVM_HIGH tb_top // VCS vcs -sverilog -ntb_opts uvm tb_top.sv simv +UVM_TESTNAME=hello_test +UVM_VERBOSITY=UVM_MEDIUM // Xcelium xrun -uvm tb_top.sv +UVM_TESTNAME=hello_test // Common plusargs: // +UVM_TESTNAME=<class_name> — which test class to run // +UVM_VERBOSITY=UVM_HIGH — message verbosity level // +UVM_TIMEOUT=10000000,YES — override default timeout // +UVM_MAX_QUIT_COUNT=5 — stop after 5 errors // +uvm_set_config_int=uvm_test_top.env.agent,is_active,1