Part 3 · Factory & Configuration · Intermediate
Static-to-UVM Bridge: Why Virtual Interfaces Exist
The HDL/UVM boundary problem, virtual interface semantics, interface vs virtual interface, and why config_db is the transport layer.
The boundary problem
SystemVerilog interface constructs exist in the static elaboration hierarchy — modules, interfaces, and wires. UVM class objects are created dynamically at simulation time inside build_phase. A class cannot contain an interface instance as a member — the language forbids it.
[HDL] elaboration-time [UVM] run-time
─────────────────────── ────────────────
interface apb_if { signals } class driver {
module top; // ILLEGAL:
apb_if bus(); apb_if vif; ✗
endmodule virtual apb_if vif; ✓
}Virtual interface semantics
A virtual interface is a handle — a pointer to an interface instance that already exists in the HDL hierarchy. It carries no signals itself; dereferencing it accesses the real interface instance's signals.
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
class apb_driver extends uvm_driver #(apb_item);
virtual apb_if vif; // handle, not instance
task run_phase(uvm_phase phase);
@(vif.pclk);
vif.psel <= 1'b1;
vif.paddr <= req.addr;
endtask
endclass[HDL][CONFIG][UVM] handle lifecycle
elaboration: apb_if apb_if_i exists in top module
top initial: config_db stores virtual handle to apb_if_i
build_phase: driver.vif = handle from config_db
run_phase: driver drives vif.psel (same signals as apb_if_i)Why config_db is the bridge
There is no direct path from a UVM class constructor to an HDL interface instance. The top module's initial block is the only place that can see both the interface instance and the UVM startup. config_db stores the handle in a globally accessible typed pool keyed by path.
top.sv initial block has access to interface instances.
config_db.set(null, ...) works without a UVM component context.
UVM components get() the handle in build_phase — after UVM hierarchy exists.
Field name "vif" is convention — any string works if set/get agree.
module top;
logic clk;
apb_if apb_if_i(.pclk(clk));
initial begin
// [HDL] bridge point — only place with both if instance and UVM access
uvm_config_db#(virtual apb_if)::set(
null, "uvm_test_top.env.apb.*", "vif", apb_if_i);
run_test();
end
endmoduleKey takeaways
Virtual interface = handle to static interface instance, not a copy.
Classes use virtual if; modules instantiate real interface.
config_db transports the handle from top initial into UVM build_phase.
Common pitfalls
Trying to new() an interface inside a class — compile error.
Passing interface through module ports into UVM — wrong layer.
Assuming virtual if copies signals — it aliases the same instance.