2. UVM环境组件层次化连接
任务目标
在UVM验证环境中,按照标准层次结构实例化并连接driver、monitor、agent、env与test组件,通过uvm_config_db完成virtual interface从test到driver/monitor的传递,最终在test中启动sequence以驱动DUT接口信号,验证组件间通信链路完整可用。
环境依赖
- 仿真器:支持UVM-1.2或UVM-1.1d(如VCS、QuestaSim)
- UVM库文件:
uvm_pkg已编译 - DUT接口:一个简单的同步接口(时钟+数据+有效信号)
关键完整代码
// 接口定义:simple_bus_if.sv
interface simple_bus_if(input bit clk);
logic [7:0] data;
logic valid;
clocking drv_cb @(posedge clk);
output data, valid;
endclocking
clocking mon_cb @(posedge clk);
input data, valid;
endclocking
modport DRV(clocking drv_cb);
modport MON(clocking mon_cb);
endinterface
// 组件定义:uvm_components.sv
`include "uvm_macros.svh"
import uvm_pkg::*;
class driver extends uvm_driver #(uvm_sequence_item);
`uvm_component_utils(driver)
virtual simple_bus_if.DRV vif;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual simple_bus_if.DRV)::get(this, "", "vif", vif))
`uvm_fatal("DRV", "virtual interface not found")
endfunction
task run_phase(uvm_phase phase);
vif.drv_cb.data <= 0;
vif.drv_cb.valid <= 0;
forever begin
seq_item_port.get_next_item(req);
// 驱动接口
if ($cast(req, req)) begin
vif.drv_cb.data <= req.get_data();
vif.drv_cb.valid <= 1;
end
seq_item_port.item_done();
repeat (2) @(vif.drv_cb);
vif.drv_cb.valid <= 0;
end
endtask
endclass
class monitor extends uvm_monitor;
`uvm_component_utils(monitor)
virtual simple_bus_if.MON vif;
uvm_analysis_port #(uvm_sequence_item) ap;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ap = new("ap", this);
if (!uvm_config_db#(virtual simple_bus_if.MON)::get(this, "", "vif", vif))
`uvm_fatal("MON", "virtual interface not found")
endfunction
task run_phase(uvm_phase phase);
forever begin
@(vif.mon_cb);
if (vif.mon_cb.valid) begin
uvm_sequence_item item = new("item");
item.set_data(vif.mon_cb.data);
ap.write(item);
end
end
endtask
endclass
class agent extends uvm_agent;
`uvm_component_utils(agent)
driver drv;
monitor mon;
uvm_sequencer #(uvm_sequence_item) sqr;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
sqr = uvm_sequencer#(uvm_sequence_item)::type_id::create("sqr", this);
drv = driver::type_id::create("drv", this);
mon = monitor::type_id::create("mon", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction
endclass
class env extends uvm_env;
`uvm_component_utils(env)
agent agt;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agt = agent::type_id::create("agt", this);
endfunction
endclass
// 简单sequence item(为演示最小化)
class simple_item extends uvm_sequence_item;
`uvm_object_utils(simple_item)
rand bit [7:0] data;
function new(string name = "simple_item");
super.new(name);
endfunction
function bit [7:0] get_data();
return data;
endfunction
function void set_data(bit [7:0] d);
data = d;
endfunction
endclass
class simple_seq extends uvm_sequence #(uvm_sequence_item);
`uvm_object_utils(simple_seq)
function new(string name = "simple_seq");
super.new(name);
endfunction
task body();
simple_item item = simple_item::type_id::create("item");
start_item(item);
assert(item.randomize());
finish_item(item);
endtask
endclass
class test extends uvm_test;
`uvm_component_utils(test)
env e;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
e = env::type_id::create("e", this);
// 从test层传递virtual interface
uvm_config_db#(virtual simple_bus_if.DRV)::set(this, "e.agt.drv", "vif", top_if.DRV);
uvm_config_db#(virtual simple_bus_if.MON)::set(this, "e.agt.mon", "vif", top_if.MON);
endfunction
task run_phase(uvm_phase phase);
simple_seq seq = simple_seq::type_id::create("seq");
phase.raise_objection(this);
seq.start(e.agt.sqr);
#100;
phase.drop_objection(this);
endtask
endclass
// 顶层模块:top.sv
module top;
bit clk;
always #5 clk = ~clk;
simple_bus_if bus_if(clk);
// 将接口连接到DUT(此处用简单逻辑代替)
// 实际DUT连接省略,仅演示UVM组件连接
initial begin
uvm_config_db#(virtual simple_bus_if.DRV)::set(null, "uvm_test_top.e.agt.drv", "vif", bus_if.DRV);
uvm_config_db#(virtual simple_bus_if.MON)::set(null, "uvm_test_top.e.agt.mon", "vif", bus_if.MON);
run_test("test");
end
endmodule
运行方式
# 编译(以QuestaSim为例)
vlog -sv -uvm simple_bus_if.sv uvm_components.sv top.sv
vsim -c -do "run -all; quit" top
# 或使用VCS
vcs -sverilog -ntb_opts uvm simple_bus_if.sv uvm_components.sv top.sv
./simv
验证方法与通过条件
- 编译通过:无语法错误,UVM组件类型注册成功。
- config_db传递成功:仿真日志中无
FATAL级别的"virtual interface not found"报错,说明driver和monitor均成功从config_db获取到virtual interface。 - sequence执行:仿真日志显示sequence的body执行完成,driver成功驱动接口信号。
- monitor采样:monitor在valid有效时成功采样数据,并通过analysis port写出(可在monitor中加打印验证)。
- 无UVM警告/错误:仿真结束时UVM报告无
UVM_ERROR或UVM_FATAL。
若以上条件全部满足,说明agent、env、test的层次化实例化与连接正确,config_db的virtual interface传递链路完整,组件间通信正常。