Part 3 · Factory & Configuration · Intermediate
Single-Instance vif Pattern: Top → Env → Agent → Driver
The canonical four-step pattern for one interface instance — define, instantiate, publish from top, forward through agent, consume in driver/monitor.
Four-step canonical flow
Define interface with signals and modports.
Instantiate interface in top, connect to DUT.
Publish vif from top initial before run_test().
Agent gets vif, forwards to children; driver/monitor get in build_phase.
[HDL][CONFIG][UVM] single-instance flow
Step 1-2 [HDL]:
apb_if apb_if_i in top → dut.apb(apb_if_i)
Step 3 [HDL→CONFIG]:
set(null, "uvm_test_top.env.apb.*", "vif", apb_if_i)
Step 4 [UVM]:
agent: get("", "vif") → set("*", "vif", vif)
drv: get("", "vif") → use in run_phaseStep 1 — interface and top module
interface apb_if(input logic pclk);
logic [31:0] paddr, pwdata, prdata;
logic pwrite, psel, penable, pready;
modport drv_mp (clocking cb @(posedge pclk));
modport mon_mp (clocking cb @(posedge pclk));
endinterface
module top;
logic clk, rst_n;
apb_if apb_if_i(.pclk(clk));
dut u_dut(.apb(apb_if_i));
initial begin
clk = 0; forever #5 clk = ~clk;
end
initial begin
uvm_config_db#(virtual apb_if)::set(
null, "uvm_test_top.env.*", "vif", apb_if_i);
run_test();
end
endmoduleStep 2 — agent forwards, driver consumes
class apb_agent extends uvm_agent;
virtual apb_if vif;
apb_driver drv;
apb_monitor mon;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif))
`uvm_fatal("NOVIF", "apb_if not set for agent")
uvm_config_db#(virtual apb_if)::set(this, "*", "vif", vif);
drv = apb_driver::type_id::create("drv", this);
mon = apb_monitor::type_id::create("mon", this);
endfunction
endclass
class apb_driver extends uvm_driver #(apb_item);
virtual apb_if vif;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif))
`uvm_fatal("NOVIF", "virtual apb_if not set for driver")
endfunction
task run_phase(uvm_phase phase);
@(vif.pclk);
vif.psel <= 1'b1;
endtask
endclass[CONFIG] agent fan-out pattern
top sets on env.* or env.apb.*
agent gets once: get(this, "", "vif", vif)
agent forwards: set(this, "*", "vif", vif)
children get: get(this, "", "vif", vif)
agent is the vif distribution point for its subtreeKey takeaways
Top publishes once before run_test(); agent fans out to children.
Driver and monitor get vif in build_phase — fatal if missing.
Use consistent field name "vif" across the agent subtree.
Common pitfalls
Creating driver before forwarding vif — child get fails.
Top sets on env.drv directly — bypasses agent, breaks reuse.
Using run_phase for first vif access — no early failure.