1. 搭建最小UVM验证环境
任务目标
搭建一个可编译、可运行的最小UVM验证环境,包含uvm_test、uvm_env、uvm_agent、uvm_driver、uvm_sequencer、uvm_monitor、uvm_scoreboard七个核心组件,并通过一个简单测试用例验证组件间的连接与数据通路。
环境依赖
- 仿真工具:VCS 或 QuestaSim(本案例以VCS为例)
- UVM库:UVM-1.2(随仿真工具发布)
- 文件结构:所有文件置于同一目录,编译顺序由文件列表控制
最小UVM环境实现
以下代码将全部组件定义在单个文件中,便于最小化编译与运行。核心数据通路为:sequencer产生事务 → driver驱动到接口 → monitor采样 → scoreboard比对。
// min_uvm_env.sv
`include "uvm_macros.svh"
import uvm_pkg::*;
// 简单事务
class simple_item extends uvm_sequence_item;
rand bit [7:0] data;
`uvm_object_utils_begin(simple_item)
`uvm_field_int(data, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "simple_item");
super.new(name);
endfunction
endclass
// 接口
interface simple_if(input bit clk);
logic [7:0] data;
logic valid;
endinterface
// 驱动器
class simple_driver extends uvm_driver #(simple_item);
virtual simple_if vif;
`uvm_component_utils(simple_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
@(posedge vif.clk);
vif.data <= req.data;
vif.valid <= 1;
seq_item_port.item_done();
end
endtask
endclass
// 监视器
class simple_monitor extends uvm_monitor;
virtual simple_if vif;
uvm_analysis_port #(simple_item) mon_ap;
`uvm_component_utils(simple_monitor)
function new(string name, uvm_component parent);
super.new(name, parent);
mon_ap = new("mon_ap", this);
endfunction
task run_phase(uvm_phase phase);
forever begin
@(posedge vif.clk);
if (vif.valid) begin
simple_item item = simple_item::type_id::create("item");
item.data = vif.data;
mon_ap.write(item);
end
end
endtask
endclass
// 序列发生器
class simple_sequencer extends uvm_sequencer #(simple_item);
`uvm_component_utils(simple_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
// 代理
class simple_agent extends uvm_agent;
simple_driver driver;
simple_sequencer sequencer;
simple_monitor monitor;
`uvm_component_utils(simple_agent)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
monitor = simple_monitor::type_id::create("monitor", this);
if (get_is_active() == UVM_ACTIVE) begin
driver = simple_driver::type_id::create("driver", this);
sequencer = simple_sequencer::type_id::create("sequencer", this);
end
endfunction
function void connect_phase(uvm_phase phase);
if (get_is_active() == UVM_ACTIVE)
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
// 计分板
class simple_scoreboard extends uvm_scoreboard;
uvm_analysis_imp #(simple_item, simple_scoreboard) sb_export;
int count;
`uvm_component_utils(simple_scoreboard)
function new(string name, uvm_component parent);
super.new(name, parent);
sb_export = new("sb_export", this);
endfunction
function void write(simple_item item);
count++;
`uvm_info("SCB", $sformatf("Received item, data=0x%0h, count=%0d", item.data, count), UVM_LOW)
endfunction
endclass
// 环境
class simple_env extends uvm_env;
simple_agent agent;
simple_scoreboard scoreboard;
`uvm_component_utils(simple_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = simple_agent::type_id::create("agent", this);
scoreboard = simple_scoreboard::type_id::create("scoreboard", this);
endfunction
function void connect_phase(uvm_phase phase);
agent.monitor.mon_ap.connect(scoreboard.sb_export);
endfunction
endclass
// 测试
class simple_test extends uvm_test;
simple_env env;
`uvm_component_utils(simple_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = simple_env::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
simple_item item;
phase.raise_objection(this);
repeat (3) begin
item = simple_item::type_id::create("item");
assert(item.randomize());
env.agent.sequencer.start_item(item);
env.agent.sequencer.finish_item(item);
end
#100;
phase.drop_objection(this);
endtask
endclass
// 顶层模块
module top;
logic clk = 0;
always #5 clk = ~clk;
simple_if if0(.clk(clk));
initial begin
uvm_config_db#(virtual simple_if)::set(null, "uvm_test_top.env.agent.*", "vif", if0);
run_test("simple_test");
end
endmodule
编译与运行
# 编译(VCS)
vcs -sverilog -ntb_opts uvm-1.2 -timescale=1ns/1ps min_uvm_env.sv -o simv
# 运行
./simv +UVM_TESTNAME=simple_test
验证方法与通过条件
- 编译无错误,仿真退出码为0。
- 日志中出现3条来自scoreboard的
Received item信息,且count依次为1、2、3。 - 无UVM_ERROR或UVM_FATAL报告。
满足以上条件即表示最小UVM环境搭建成功,组件连接正确,数据通路完整。