Day 06 / 25
← Day 05 Day 07 →
HomeVerificationDay 6 — Introduction to UVM
Track 2 — UVM

Introduction to UVM

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.

⏱ 27 min read📖 Day 6 of 25🎯 UVM · IEEE 1800.2 · Phasing
Contents
  1. What is UVM?
  2. uvm_component vs uvm_object
  3. UVM Class Hierarchy
  4. Naming Conventions
  5. Reporting Macros
  6. Hello UVM Testbench
  7. UVM Phasing Overview
  8. Running UVM Tests

1. What is UVM?

UVM is a SystemVerilog class library standardized as IEEE 1800.2. It builds on earlier methodologies (Cadence OVM, Synopsys VMM) and provides:

IEEE 1800.2: The UVM standard is maintained by Accellera. All major simulators (Questa, VCS, Xcelium) ship a compatible UVM library. Include it with: `include "uvm_macros.svh" and import uvm_pkg::*;

2. uvm_component vs uvm_object

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
Propertyuvm_componentuvm_object
Base classuvm_component → uvm_report_object → uvm_objectuvm_object directly
Constructornew(name, parent)new(name)
HierarchyFixed path in TB treeNo hierarchy position
PhasesYes — build, connect, run…No phases
LifetimeEntire simulationCreated/deleted dynamically
ExamplesDriver, Monitor, Agent, Env, TestSequence item, Sequence, Config obj

3. UVM Class Hierarchy

uvm_void uvm_object uvm_report_object uvm_component uvm_test uvm_env uvm_agent uvm_driver uvm_monitor uvm_sequence_item (extends uvm_object)

4. UVM Naming Conventions

5. Reporting Macros

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
MacroSeverityBehavior
`uvm_infoUVM_INFOFiltered by +UVM_VERBOSITY; no error count
`uvm_warningUVM_WARNINGAlways printed; increments warning count
`uvm_errorUVM_ERRORPrinted; increments error count; sim continues
`uvm_fatalUVM_FATALPrinted; immediately stops simulation

6. Hello UVM Testbench

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
Always raise/drop objections: Without 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.

7. UVM Phasing Overview

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

8. Running UVM Tests

// 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

Key Takeaways — Day 6

Next → Day 07
UVM Testbench Architecture
Agent, driver, monitor, scoreboard, TLM analysis ports — building a complete, connected UVM environment.