文章介绍同时使用Synopsys AXI VIP和寄存器模型的示例。正常使用寄存器模型的流程是:写寄存器模型、写adapter转换、再例化连接,而VIP已经包含adapter,所以直接连接寄存器模型句柄就好。 示例为AXI VIP同时使用寄存器模型,APB VIP大同小异也可以参照。
VIP
adapter和寄存器句柄位于master agent(svt_axi_master_agent类)。
ini
uvm_reg_block axi_regmodel ;
svt_axi_reg_adapter reg2axi_adapter ;
使用前还需要将对应配置类(svt_axi_port_configuration类)中uvm_reg_enable配成1。
ini
bit uvm_reg_enable = 0;
寄存器模型
示例为一个简单的存储的寄存器模型,位宽32,起始地址0。
scala
class ral_mem extends uvm_mem;
function new(string name = "ral_mem");
super.new(name, `UVM_REG_ADDR_WIDTH'h100, 32, "RW", build_coverage(UVM_NO_COVERAGE));
endfunction
`uvm_object_utils(ral_mem)
endclass : ral_mem
class ral_block extends uvm_reg_block;
rand ral_mem ral_mem_0;
function new(string name = "ral_block");
super.new(name, build_coverage(UVM_NO_COVERAGE));
endfunction: new
virtual function void build();
this.default_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN, 0);
this.ral_mem_0 = ral_mem::type_id::create("ral_mem_0",,get_full_name());
this.ral_mem_0.configure(this, "mem");
this.ral_mem_0.build();
this.default_map.add_mem(this.ral_mem_0, `UVM_REG_ADDR_WIDTH'h0, "RW", 0);
endfunction : build
`uvm_object_utils(ral_block)
endclass: ral_block
env
然后在build_phase实例化寄存器模型,并发送句柄至master agent,这里"axi_system_env.master0"是我的环境中master agent的路径,可以根据实际进行修改。 下面set_hdl_path_root()和上小节configure()合起来是HDL中存储的路径tb_top.axi_slave.mem。
scss
regmodel = ral_block::type_id::create("regmodel");
regmodel.build();
regmodel.set_hdl_path_root("tb_top.axi_slave");
regmodel.lock_model();
uvm_config_db#(uvm_reg_block)::set(this,"axi_system_env.master[0]", "axi_regmodel", regmodel);
test_case
在测试用例中分别前门后门读写寄存器模型。
css
for(i=0;i<16;i++)
top_env.regmodel.ral_mem_0.write(status, 4*i , i);
for(i=0;i<16;i++)
top_env.regmodel.ral_mem_0.read(status, 4*i , rdata);
for(i=0;i<16;i++)
top_env.regmodel.ral_mem_0.write(status, i , i+'h16, UVM_BACKDOOR);
for(i=0;i<16;i++) begin
top_env.regmodel.ral_mem_0.read(status, i , rdata, UVM_BACKDOOR);
`uvm_info("tc",$sformatf("read %0h",rdata),UVM_MEDIUM)
end
波形中可以看到前门读写行为。 