2. 实现UVM寄存器模型RAL集成
任务目标
在已有UVM验证环境中集成RAL(Register Abstraction Layer)模型,实现对DUT中寄存器组的前门(Frontdoor)与后门(Backdoor)访问,并通过自检机制验证读写操作的正确性。本案例聚焦于RAL模型创建、集成到UVM环境、前门/后门访问路径的建立以及读写自检。
环境与依赖
- UVM-1.2或UVM-1.1d库
- DUT提供APB接口(前门访问通道)
- DUT内部寄存器实例路径:
dut.top_reg_block.reg_a(用于后门访问) - 需要VCS、Questa或Xcelium等支持UVM的仿真器
RAL模型实现
以下代码定义了一个包含两个寄存器(CTRL和STATUS)的寄存器块,并集成到UVM环境中。CTRL寄存器支持前门和后门访问,STATUS寄存器仅通过后门访问以验证路径差异。
// 文件: ral_model.svh
class reg_ctrl extends uvm_reg;
rand uvm_reg_field ctrl_en;
rand uvm_reg_field mode;
function new(string name = "reg_ctrl");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
virtual function void build();
ctrl_en = uvm_reg_field::type_id::create("ctrl_en");
mode = uvm_reg_field::type_id::create("mode");
ctrl_en.configure(this, 1, 0, "RW", 0, 1'b0, 1, 0, 0);
mode.configure(this, 2, 1, "RW", 0, 2'b00, 1, 0, 0);
endfunction
`uvm_object_utils(reg_ctrl)
endclass
class reg_status extends uvm_reg;
rand uvm_reg_field ready;
rand uvm_reg_field error;
function new(string name = "reg_status");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
virtual function void build();
ready = uvm_reg_field::type_id::create("ready");
error = uvm_reg_field::type_id::create("error");
ready.configure(this, 1, 0, "RO", 0, 1'b0, 1, 0, 0);
error.configure(this, 1, 1, "RO", 0, 1'b0, 1, 0, 0);
endfunction
`uvm_object_utils(reg_status)
endclass
class reg_block extends uvm_reg_block;
rand reg_ctrl ctrl;
rand reg_status status;
function new(string name = "reg_block");
super.new(name, UVM_NO_COVERAGE);
endfunction
virtual function void build();
ctrl = reg_ctrl::type_id::create("ctrl");
ctrl.configure(this, null, "");
ctrl.build();
status = reg_status::type_id::create("status");
status.configure(this, null, "");
status.build();
// 默认映射(前门APB)
default_map = create_map("default_map", 0, 4, UVM_LITTLE_ENDIAN, 1);
default_map.add_reg(ctrl, 32'h0, "RW");
default_map.add_reg(status, 32'h4, "RO");
// 后门路径配置
ctrl.add_hdl_path("dut.top_reg_block.reg_a");
status.add_hdl_path("dut.top_reg_block.reg_b");
lock_model();
endfunction
`uvm_object_utils(reg_block)
endclass
UVM环境集成与读写自检
以下代码展示了如何将RAL模型集成到UVM环境中,并通过前门和后门执行读写操作及自检。测试序列在run_phase中执行:先通过前门写入CTRL寄存器并回读验证,再通过后门写入并回读,最后通过后门读取STATUS寄存器验证硬件更新。
// 文件: ral_integration_test.sv
class ral_test extends uvm_test;
`uvm_component_utils(ral_test)
reg_block ral;
uvm_reg_sequence reg_seq;
function new(string name = "ral_test", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
ral = reg_block::type_id::create("ral");
ral.configure(null, "");
ral.build();
uvm_reg_model::set_sequencer(ral.default_map, null, null); // 实际项目中替换为APB sequencer
uvm_config_db#(reg_block)::set(this, "*", "ral_model", ral);
endfunction
virtual task run_phase(uvm_phase phase);
uvm_status_e status;
uvm_reg_data_t read_val;
uvm_reg_data_t expected;
phase.raise_objection(this);
// ===== 前门访问测试 =====
expected = 32'h5; // ctrl_en=1, mode=2'b01
ral.ctrl.write(status, expected, UVM_FRONTDOOR);
ral.ctrl.read(status, read_val, UVM_FRONTDOOR);
if (status != UVM_IS_OK || read_val !== expected)
`uvm_error("RAL_TEST", $sformatf("前门读写失败: exp=0x%0h got=0x%0h", expected, read_val))
else
`uvm_info("RAL_TEST", "前门读写CTRL通过", UVM_LOW)
// ===== 后门访问测试 =====
expected = 32'h7; // ctrl_en=1, mode=2'b11
ral.ctrl.write(status, expected, UVM_BACKDOOR);
ral.ctrl.read(status, read_val, UVM_BACKDOOR);
if (status != UVM_IS_OK || read_val !== expected)
`uvm_error("RAL_TEST", $sformatf("后门读写失败: exp=0x%0h got=0x%0h", expected, read_val))
else
`uvm_info("RAL_TEST", "后门读写CTRL通过", UVM_LOW)
// ===== 后门读STATUS(验证硬件更新) =====
ral.status.read(status, read_val, UVM_BACKDOOR);
if (status != UVM_IS_OK)
`uvm_error("RAL_TEST", "后门读STATUS失败")
else
`uvm_info("RAL_TEST", $sformatf("后门读STATUS = 0x%0h", read_val), UVM_LOW)
phase.drop_objection(this);
endtask
endclass
运行方式
# 使用VCS编译运行(需替换为实际DUT与接口文件)
vcs -sverilog +acc+1 +define+UVM_NO_DPI \
-f dut.f ral_model.svh ral_integration_test.sv \
-l compile.log
./simv -l run.log
验证方法与通过条件
- 前门访问验证:通过APB总线向CTRL寄存器写入0x5,再回读。若回读值等于0x5且状态为
UVM_IS_OK,则前门读写路径正确。 - 后门访问验证:通过HDL路径直接写入CTRL寄存器0x7,再回读。若回读值等于0x7,说明后门路径已正确映射到
dut.top_reg_block.reg_a。 - 硬件更新验证:后门读取STATUS寄存器,若返回非零值(表示DUT内部逻辑已更新状态),说明后门读路径有效。
- 判定标准:仿真日志中出现“前门读写CTRL通过”和“后门读写CTRL通过”且无
UVM_ERROR,即判定为通过。
常见问题
- 后门访问失败:检查
add_hdl_path中的路径是否与DUT层次结构完全一致,且路径中的信号必须为寄存器类型(reg),不能是wire。 - 前门访问超时:确认
uvm_reg_model::set_sequencer已正确绑定到APB sequencer,且APB agent已启动。 - 寄存器字段位宽不匹配:确保
configure中的位宽与DUT寄存器定义一致,否则读写数据会被截断或扩展。