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.
<Use_When>
<Do_Not_Use_When>
rtl-p5s-func-verify skillsystemverilog-assertion skillsystemverilog skill
</Do_Not_Use_When><Why_This_Exists> 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:
<Execution_Policy>
templates/uvm-env-template.sv as the starting point for new environmentsexamples/uvm-smoke-test-example.sv for basic smoke test structureuvm_component_utils / uvm_object_utils)| 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 |
| 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 |
m_prefix rule: UVM class member handles usem_prefix per industry convention. This is separate from the RTLu_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);
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)
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
| 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 |
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
| 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
// 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")
* supported)uvm_fatal is mandatoryclass 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
| 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) |
<Tool_Usage> 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. </Tool_Usage>
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
<Escalation_And_Stop_Conditions>
<Final_Checklist>
uvm_component_utils / uvm_object_utils)uvm_fatal on config_db get failure{proto}_agent, {proto}_driver, m_ prefix instances