芯片验证中寄存器模型的验证写法
(3)中的reg_file1是寄存器模型中的block 块.(2)adapter的写法,以axi接口的adapter为例。(3) 使用uvm自带的seq来验证寄存器模型。(1) ral环境搭建。
·
(1) ral环境搭建
class test_env extends uvm_env;
ral ral_model;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
ral_model = ral::type_id::create("ral_model");
ral_model.configure(null,"");
ral_model.build();
ral_model.lock_model();
ral_model.set_coverage(UVM_CVR_FILED_VALS);
ral_model.default_map.set_auto_predict(1);
cfg.ral_model = ral_model;
endfunction
virtual function void connect_phase(uvm_phase phase);
ral_model.default_map.set_sequencer(this.vseqr.seqr, reg_adapter);
endfunction
virtual task reset_phase(uvm_phase phase);
phase.raise_objection(phase);
ral_model.reset();
phase.drop_objection(phase)
endtask
endclass
(2) adapter的写法,以axi接口的adapter为例
class reg2axi_adapter extends uvm_reg_adapter;
`uvm_object_utils(reg2axi_adapter)
function new(string name="reg2axi_adapter");
super.new(name);
provides_responses = 1;
endfunction
virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
global_cfg glb_cfg;
svt_axi_port_configuration cfg;
svt_axi_master_transaction reg_item;
uvm_reg_addr_t addr_i;
glb_cfg = global_cfg::get_instance();
reg_item = svt_axi_master_transaction::type_id::create("axi_reg_item");
reg_item.port_cfg = glb_cfg.axi_sys_cfg.master_cfg[1];
addr_i = rw.addr;
reg_item.randomize() with {
xact_type = (rw.kind == UVM_WRITE)?svt_axi_master_transaction::WRITE:svt_axi_master_transaction::READ;
addr == addr_i;
burst_length == 1;
id == 'h0;
burst_size == svt_axi_master_transaction::BURST_SIZE_32BIT;
burst_type == svt_axi_master_transaction::INCR;
};
reg_item.wstrb[0] = 'hf;
reg_item.data[0] = (rw.kind == UVM_WRITE)? rw.data:'h0;
return reg_item;
endfunction
virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
svt_axi_master_transaction reg_item;
if(!$cast(reg_item, bus_item)) begin
`uvm_fatal(get_full_name(), "NOT AXI MASTER TRANSACTION")
return;
end
rw.kind = (reg_item.xact_type == svt_axi_master_transaction::WRITE)?UVM_WRITE:(reg_item.xact_type == svt_axi_master_transaction::READ)? UVM_READ:UVM_READ;
rw.addr = reg_item.addr;
rw.data = (ret_item.xact_type == svt_axi_master_transaction:WRITE)?'h0:(reg_item.xact_type == svt_axi_master_transaction::READ)?reg_item.data[0]:0;
rw.status = (reg_item.rresp[0][1] == 0)?UVM_IS_K:UVM_NOT_OK;
endfunction
endclass
(3) 使用uvm自带的seq来验证寄存器模型
如下code中可以对某个reg进行操作NO_REG_TESTS.
class ral_sequence extends vum_sequence;
task body();
uvm_reg_hw_reset_seq hw_rst;
uvm_reg_bit_bash_seq bit_bash_seq;
uvm_reg_access_seq acc_seq;
uvm_resource_db#(bit)::set({"REG::", cfg.ral_model.fpga_reg_file.xxx_reg.get_full_name()}, "NO_REG_TESTS", 1, this);
hw_rst = uvm_reg_hw_reset_seq::type_id::create("hw_rst");
bit_bash_seq = uvm_reg_bit_bash_seq::type_id::create("bit_bash_seq");
acc_seq = uvm_reg_access_seq::type_id::create("acc_seq");
hw_rst.model = cfg.ral_model.reg_file1;
hw_rst.start(p_sequencer.seqr);
bit_bash_seq.model = cfg.ral_model.reg_file1;
bit_bash_seq.start(p_sequencer.seqr);
acc_seq.model = cfg.ral_model.reg_file1;
acc_seq.start(p_sequencer.seqr);
endtask
enclass
(4)中的reg_file1是寄存器模型中的block 块.
class ral_model extends uvm_reg_block;
rand ral_reg_file reg_file;
function void build();
this.default_map = create_map("", 0, 4, UVM_LITLE_ENDIAN, 0);
this.reg_file.configure(this, "");//TODO add path
this.reg_file.build();
this.default_map.add_submap(this.reg_file.default_map, UVM_REG_ADDR_WIDTH'h0);
endfunction
enclass
(5) 读写单个reg的方法
task write_reg(string core_id, string module_name, string reg_name, uvm_reg_data_t val, string subsys_name = "APU0", uvm_verbosity verb=UVM_LOW);
uvm_reg_block ralmdl;
uvm_reg_block subsys_reg_blk
uvm_reg_block module_reg_blk;
uvm_reg reg_i;
uvm_status_e status;
uvm_reg_data_t rdata;
apu_glb_cfg.cr_cfg.core_id = core_id;
ralmdl = glb_cfg.ral_model;
subsys_reg_blk = ralmdl.get_block_by_name(subsys_name);
modeule_reg_blk= subsys_reg_blk.get_block_by_name(module_name);
reg_i = module_reg_blk.get_reg_by_name(reg_name);
reg_i.write(status, val);
endtask
task read_reg(string core_id, string module_name, string reg_name, uvm_reg_data_t val, string subsys_name = "APU0", uvm_verbosity verb=UVM_LOW);
uvm_reg_block ralmdl;
uvm_reg_block subsys_reg_blk
uvm_reg_block module_reg_blk;
uvm_reg reg_i;
uvm_status_e status;
uvm_reg_data_t rdata;
apu_glb_cfg.cr_cfg.core_id = core_id;
ralmdl = glb_cfg.ral_model;
subsys_reg_blk = ralmdl.get_block_by_name(subsys_name);
modeule_reg_blk= subsys_reg_blk.get_block_by_name(module_name);
reg_i = module_reg_blk.get_reg_by_name(reg_name);
reg_i.read(status, val);
endtask
(6) 如何验证寄存器
(3)中能够验证寄存器的读写正确性,但是不能验证reg到module之间的正确传递,所以可以把(3)中case关闭,跑验证中已经写好的case,看code coverage,来查看哪些reg没有验到从reg到module,然后再逐个去验证,这样寄存器的验证就比较完善
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)