对于连续地址的读写,需用uvm_mem;
分两种情况:
情况1:总线支持一次性读写多个寄存器地址;
情况2:总线不支持一次性读写多个寄存器地址
对于情况1,仍然用write和read,只是在参数传递时用extension,value仍然是单个数值
对于情况2,用burst write和burst read,value用队列或数组的形式,寄存器模型会自动拆分成多次读写单个寄存器,比如连续读16个寄存器,value的数组或队列的大小定为16,寄存器模型会自动拆成16个tr发给driver
以下是针对情况1的编写
reg_model编写:
class data_fifo extends uvm_mem;
function new(string name = "data_fifo");
super.new(name,14,8);//一共14个地址,地址宽度8bit
endfunction
`uvm_object_utils(data_fifo)
endclass
class reg_model extends uvm_reg_block;
`uvm_object_utils(reg_model)
rand data_fifo mm;
virtual function void build();
`uvm_info(get_name(),"build function is called",UVM_LOW)
default_map = create_map("default_map",0,1,UVM_BIG_ENDIAN,0);
mm = data_fifo::type_id::create("mm", , get_full_name());
mm.configure(this,"top_e.regs");//hdl路径
default_map.add_mem(mm,8'h00);//从偏移地址00开始
endfunction
endclass
adapter reg2bus编写:
function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
uart_transaction ext,tr;
uvm_reg_item reg_item = get_item();
tr = new("tr");
if (reg_item.extension != null && $cast(ext, reg_item.extension)) begin
tr.addr = rw.addr;
tr.wr_pro = (rw.kind == UVM_READ) ? 1'b0 : 1'b1;
if(tr.wr_pro)begin
tr.reg_len = ext.reg_len;
tr.w_data = new[tr.reg_len];
foreach(tr.w_data[i])
tr.w_data[i] = ext.w_data[i];
end
end
tr.frame_head = 16'h55AA;
tr.crc_cal();
tr.print();
return tr;
endfunction
在参考模型的main phase里发起一次写14个寄存器
uart_transaction ext;
uvm_status_e status;
uvm_reg_data_t value;
ext = new();
ext.wr_pro = 1;
ext.reg_len = 14;
ext.w_data = new[14];
// 准备要写入的数据
for (int i = 0; i < 14; i++)
ext.w_data[i] = i;
p_rm.mm.write(
.status(status),
.offset(0),
.value(value),
.fname(""),
.extension(ext),
.path(UVM_FRONTDOOR)
);
2714

被折叠的 条评论
为什么被折叠?



