uvm

star 32

UVM (Universal Verification Methodology) coding convention and methodology guideline skill. Covers class hierarchy, factory patterns, sequence/sequencer, TLM ports, coverage integration, and naming conventions for UVM testbenches.

babyworm By babyworm schedule Updated 3/2/2026

name: uvm description: "UVM (Universal Verification Methodology) coding convention and methodology guideline skill. Covers class hierarchy, factory patterns, sequence/sequencer, TLM ports, coverage integration, and naming conventions for UVM testbenches." user-invocable: false

UVM coding standards and methodology guidelines. All agents building or modifying UVM-based verification environments must follow the rules in this skill. Based on the IEEE 1800.2-2020 UVM Standard. - When writing UVM testbenches, agents, sequences, or scoreboards - When building UVM environments for the rtl-p5s-uvm-verify skill - During Phase 5 (Verification) — UVM-based verification work - Agents: testbench-dev - When doing cocotb Python-based verification → use `rtl-p5s-func-verify` skill - When writing only SVA assertions → use `systemverilog-assertion` skill - When writing RTL synthesizable code → use `systemverilog` skill UVM is an industry-standard verification methodology, but its high degree of freedom easily leads to inconsistent code. Following consistent naming conventions, class structure, and factory usage patterns ensures: - Maximum environment reusability (agents reusable across multiple projects) - Ease of debugging (predictable structure) - Natural coverage integration - Applies to all agents generating UVM environments - Use `templates/uvm-env-template.sv` as the starting point for new environments - Review `examples/uvm-smoke-test-example.sv` for basic smoke test structure - All UVM components must be registered with the factory (`uvm_component_utils` / `uvm_object_utils`) - Follow the phase callback order precisely

1. Naming Conventions

1.1 Filenames

Type Pattern Example
Agent {proto}_agent.sv axi_agent.sv
Driver {proto}_driver.sv axi_driver.sv
Monitor {proto}_monitor.sv axi_monitor.sv
Sequencer {proto}_sequencer.sv axi_sequencer.sv
Sequence Item {proto}_seq_item.sv axi_seq_item.sv
Sequence {proto}_{name}_seq.sv axi_write_seq.sv
Scoreboard {module}_scoreboard.sv cabac_scoreboard.sv
Environment {module}_env.sv cabac_env.sv
Test {module}_{name}_test.sv cabac_smoke_test.sv
Package {module}_tb_pkg.sv cabac_tb_pkg.sv
Top tb_{module}_top.sv tb_cabac_top.sv

1.2 Class Naming

Target Pattern Example
Agent {proto}_agent axi_agent
Driver {proto}_driver axi_driver
Monitor {proto}_monitor axi_monitor
Sequencer {proto}_sequencer axi_sequencer
Sequence Item {proto}_seq_item axi_seq_item
Sequence (base) {proto}_base_seq axi_base_seq
Sequence (specific) {proto}_{name}_seq axi_write_burst_seq
Scoreboard {module}_scoreboard cabac_scoreboard
Environment {module}_env cabac_env
Test (base) {module}_base_test cabac_base_test
Coverage {module}_coverage cabac_coverage

1.3 Instance Naming (create)

m_ prefix rule: UVM class member handles use m_ prefix per industry convention. This is separate from the RTL u_ prefix rule and applies to UVM TBs only.

// Instance name matches the variable name
m_driver  = axi_driver::type_id::create("m_driver", this);
m_monitor = axi_monitor::type_id::create("m_monitor", this);
m_seqr    = axi_sequencer::type_id::create("m_seqr", this);

2. UVM Class Hierarchy

uvm_test
 └── cabac_base_test
      └── cabac_smoke_test
           └── cabac_random_test

uvm_env
 └── cabac_env
      ├── axi_agent (m_axi_agt)
      │    ├── axi_driver (m_driver)
      │    ├── axi_monitor (m_monitor)
      │    └── axi_sequencer (m_seqr)
      ├── cabac_scoreboard (m_scoreboard)
      └── cabac_coverage (m_coverage)

3. Factory Registration (Mandatory)

All UVM components/objects must be registered with the factory:

class axi_driver extends uvm_driver #(axi_seq_item);
  `uvm_component_utils(axi_driver)

  function new(string name = "axi_driver", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  // ...
endclass

class axi_seq_item extends uvm_sequence_item;
  `uvm_object_utils(axi_seq_item)

  function new(string name = "axi_seq_item");
    super.new(name);
  endfunction
  // ...
endclass

4. Phase Callback Order

Phase Purpose Notes
build_phase Component create, config_db get Only create here
connect_phase TLM port connections After build completes
end_of_elaboration_phase Final structure check Optional
run_phase Simulation execution raise/drop objection required
extract_phase Collect results Optional
check_phase pass/fail determination Optional
report_phase Report results Scoreboard summary

Objection Rules

task cabac_base_test::run_phase(uvm_phase phase);
  phase.raise_objection(this, "Test started");
  // ... test body (start sequences)
  phase.drop_objection(this, "Test completed");
endtask
  • Only test raises/drops objection — forbidden in sequences or drivers
  • Without objection, simulation terminates immediately

5. TLM Port Usage

Port Type Direction Purpose
uvm_analysis_port Monitor → Scoreboard/Coverage Broadcast (1:N)
uvm_seq_item_pull_port Driver ↔ Sequencer Auto-connected
uvm_analysis_imp Scoreboard receiver Must implement write()
// Monitor: analysis port declaration and usage
class axi_monitor extends uvm_monitor;
  uvm_analysis_port #(axi_seq_item) m_ap;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    m_ap = new("m_ap", this);
  endfunction

  task run_phase(uvm_phase phase);
    // ... capture transaction
    m_ap.write(txn);  // broadcast to all subscribers
  endtask
endclass

// Scoreboard: analysis imp declaration
class cabac_scoreboard extends uvm_scoreboard;
  `uvm_analysis_imp_decl(_input)
  `uvm_analysis_imp_decl(_output)

  uvm_analysis_imp_input  #(axi_seq_item, cabac_scoreboard) m_input_imp;
  uvm_analysis_imp_output #(axi_seq_item, cabac_scoreboard) m_output_imp;

  function void write_input(axi_seq_item txn);
    // enqueue expected
  endfunction

  function void write_output(axi_seq_item txn);
    // compare with expected
  endfunction
endclass

6. config_db Usage

// Test → Agent: pass virtual interface (build_phase)
uvm_config_db #(virtual axi_if)::set(this, "m_env.m_axi_agt*", "vif", m_vif);

// Agent: retrieve virtual interface (build_phase)
if (!uvm_config_db #(virtual axi_if)::get(this, "", "vif", m_vif))
  `uvm_fatal("NO_VIF", "Virtual interface not set for agent")
  • set/get paths are hierarchy-based (wildcard * supported)
  • On get failure, uvm_fatal is mandatory

7. Coverage Integration

class cabac_coverage extends uvm_subscriber #(axi_seq_item);
  `uvm_component_utils(cabac_coverage)

  covergroup cg_transaction;
    cp_cmd:    coverpoint m_txn.cmd    { bins read = {0}; bins write = {1}; }
    cp_size:   coverpoint m_txn.size   { bins sizes[] = {1, 2, 4, 8}; }
    cross cp_cmd, cp_size;
  endgroup

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

  function void write(axi_seq_item t);
    m_txn = t;
    cg_transaction.sample();
  endfunction
endclass

8. Anti-Patterns

Anti-Pattern Problem Fix
Not registered with factory Cannot override/reuse Add uvm_*_utils to all classes
Objection in driver Phase control confusion Only raise/drop in test
Ignoring config_db get failure Null pointer crash Handle with uvm_fatal
Direct DUT access from sequence Destroys reusability Use sequencer→driver path only
Hard-coded hierarchy path Destroys portability Use config_db wildcard
#delay in run_phase Destroys portability Use @(posedge vif.sys_clk)
This skill is not executed directly. It is referenced by agents that generate UVM environments (e.g., testbench-dev). Agents should follow the conventions defined here. Factory registration, correct naming, config_db usage, analysis port: ```systemverilog class axi_agent extends uvm_agent; `uvm_component_utils(axi_agent) axi_driver m_driver; axi_monitor m_monitor; axi_sequencer m_seqr;

function void build_phase(uvm_phase phase); super.build_phase(phase); m_driver = axi_driver::type_id::create("m_driver", this); m_monitor = axi_monitor::type_id::create("m_monitor", this); m_seqr = axi_sequencer::type_id::create("m_seqr", this); endfunction endclass

</Good>
<Bad>
No factory usage, hard-coded, direct new:
```systemverilog
class my_agent extends uvm_agent;
  // WRONG: no uvm_component_utils
  my_driver drv;
  function void build_phase(uvm_phase phase);
    drv = new("drv", this);  // WRONG: bypasses factory
  endfunction
endclass
- UVM environment compilation error → request fix from testbench-dev - Coverage target not met → write additional sequences or request analysis from coverage-analyst - Scoreboard mismatch → request RTL vs Ref Model comparison from func-verifier - [ ] All UVM classes registered with factory (`uvm_component_utils` / `uvm_object_utils`) - [ ] Objection raised/dropped only in test - [ ] `uvm_fatal` on config_db get failure - [ ] TLM analysis port connects monitor→scoreboard - [ ] Virtual interface passed via config_db - [ ] Naming convention: `{proto}_agent`, `{proto}_driver`, `m_` prefix instances - [ ] Coverage collector subscribes to analysis port - [ ] Port names match RTL (sys_clk, sys_rst_n, i_/o_)
Install via CLI
npx skills add https://github.com/babyworm/rtl-agent-team --skill uvm
Repository Details
star Stars 32
call_split Forks 7
navigation Branch main
article Path SKILL.md
More from Creator