我们模拟了一个简单的加法器DUT,并使用UVM验证环境对其进行功能验证。UVM验证环境包括以下组件:
adder_env
:验证环境,包括了监控器(adder_monitor
)、驱动(adder_driver
)和代理(adder_agent
)。验证环境通过分析端口(trans_analysis_port
)与测试基准(adder_test
)和DUT连接。
在测试中,我们定义了一个测试基准类(adder_sequence
),它构建了一个简单的测试序列,生成了一个加法事务(adder_trans
),将其发送给驱动,并等待测试序列的结束。测试基准类继承自uvm_sequence
。
顶层模块testbench
实例化了测试类adder_test
,并通过UVM配置数据库将接口(virtual interface)vif
、参考模型(reference model)refmod
和DUT连接到验证环境中。
最后,我们在主程序中创建了测试环境、验证环境和DUT对象,并运行UVM测试。
这个示例展示了如何使用UVM验证加法器的功能,包括生成随机测试数据、驱动DUT、监测输出并通过分析端口传递事务对象。通过使用UVM的验证方法,我们可以更好地组织测试代码、自动化测试过程,并提高验证效率和可重用性。
// DUT (Design Under Test) - 加法器
module adder(input [7:0] a, b, output [7:0] sum);
assign sum = a + b;
endmodule
// UVM验证环境
class adder_env extends uvm_env;
// 添加需要的端口和信号声明
uvm_analysis_port#(adder_trans) trans_analysis_port;
adder_monitor monitor;
adder_agent agent;
function new(string name, uvm_component parent);
super.new(name, parent);
trans_analysis_port = new("trans_analysis_port", this);
monitor = adder_monitor::type_id::create("monitor", this);
agent = adder_agent::type_id::create("agent", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 连接验证环境的各个组件
agent.analysis_port.connect(trans_analysis_port);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// 连接DUT和monitor
monitor.a <= agent.driver.a;
monitor.b <= agent.driver.b;
monitor.sum <= agent.driver.sum;
endfunction
endclass
// UVM事务定义
class adder_trans extends uvm_sequence_item;
rand bit [7:0] a;
rand bit [7:0] b;
bit [7:0] sum;
`uvm_object_utils(adder_trans)
function new(string name = "adder_trans");
super.new(name);
endfunction
function void display();
$display("Transaction: a=%d, b=%d, sum=%d", a, b, sum);
endfunction
endclass
// UVM监控器
class adder_monitor extends uvm_monitor;
// 添加需要的端口和信号声明
adder_trans trans;
bit [7:0] a, b, sum;
`uvm_component_utils(adder_monitor)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
forever begin
// 监测DUT的输出并创建一个事务对象
@(posedge dut.sum);
trans = new();
trans.a = a;
trans.b = b;
trans.sum = sum;
trans.display();
// 通过分析端口发送事务对象
trans_analysis_port.write(trans);
end
endtask
endclass
// UVM驱动
class adder_driver extends uvm_driver#(adder_trans);
`uvm_component_utils(adder_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
// 创建事务并驱动DUT
repeat (10) begin
adder_trans trans = new();
trans.randomize(); // 随机生成事务数据
trans.display();
seq_item_port.write(trans);
@(posedge sequencer.seq_item_done);
end
endtask
endclass
// UVM代理
class adder_agent extends uvm_agent;
adder_driver driver;
uvm_analysis_port#(adder_trans) analysis_port;
`uvm_component_utils(adder_agent)
function new(string name, uvm_component parent);
super.new(name, parent);
driver = adder_driver::type_id::create("driver", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
analysis_port = new("analysis_port", this);
endfunction
endclass
// UVM测试
class adder_test extends uvm_test;
adder_env env;
adder_agent agent;
uvm_sequence#(adder_trans) sequence;
`uvm_component_utils(adder_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
sequence = adder_sequence::type_id::create("sequence");
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
env = adder_env::type_id::create("env", this);
agent = adder_agent::type_id::create("agent", this);
env.agent = agent;
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
seq.start(agent, sequence);
phase.drop_objection(this);
endtask
endclass
// UVM测试基准类
class adder_sequence extends uvm_sequence#(adder_trans);
`uvm_object_utils(adder_sequence)
function new(string name = "adder_sequence");
super.new(name);
endfunction
task body();
// 构建具体的测试序列
adder_trans trans = new();
trans.a = 10;
trans.b = 20;
seq_item_port.write(trans);
wait_for_sequence_end();
endtask
endclass
// UVM顶层
class testbench extends uvm_env;
adder_test test;
`uvm_component_utils(testbench)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
test = adder_test::type_id::create("test");
endfunction
endclass
// 主程序
module test;
initial begin
// UVM设置
uvm_config_db#(virtual adder_env)::set(null, "*", "env", "vif", vif);
uvm_config_db#(virtual adder_env)::set(null, "*", "env", "refmod", refmod);
uvm_config_db#(virtual adder_env)::set(null, "*", "env", "dut", dut);
// 创建测试环境、验证环境和DUT对象
testbench tb = new("tb", null);
adder_env env = adder_env::type_id::create("env", tb);
adder_refmod refmod = adder_refmod::type_id::create("refmod");
adder dut();
// 设置验证环境的接口
env.set_interface(refmod.intf);
// 运行UVM测试
run_test();
end
endmodule