确定scoreboard接收data的地址范围,从tb可以看到DUT是16位,所以也最多接受16位。
在rkv_ahbram_config中定义起始和结束地址:
bit [31:0] addr_start;
bit [31:0] addr_end;
int data_width;
在rkv_ahbram_base_test中确定地址值(每个test可能不一样):
// do parameter configuration
cfg.addr_start = 32'h0;
cfg.addr_end = 32'h0000_FFFF;
rkv_ahbram_scoreboard:
创建32位无符号关联数组存放write数据
确定地址是否在范围内,再判断读写
写:判断burst类型(SINGLE)再确定位宽并存入mem
读:检查读过来地址的数据是否等于mem存放相同地址的数据,相等返回1,并添加计数
`ifndef RKV_AHBRAM_SCOREBOARD_SV
`define RKV_AHBRAM_SCOREBOARD_SV
class rkv_ahbram_scoreboard extends rkv_ahbram_subscriber;
// events of scoreboard
bit [31:0] mem [int unsigned];//先按照32位无符号关联数组来存放数据
// typedef enum {CHECK_LOADCOUNTER} check_type_e;
`uvm_component_utils(rkv_ahbram_scoreboard)
function new (string name = "rkv_ahbram_scoreboard", uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
do_data_check();
endtask
virtual function void write(lvc_ahb_transaction tr);
if(is_addr_valid(tr.addr)) begin//如果地址在范围内就判断是读还是写
case(tr.xact_type)
WRITE : store_data_with_hburst(tr);//如果是写就把数据存放mem
READ : check_data_with_hburst(tr);//如果是读就对比数据
endcase
end
endfunction
task do_listen_events();
endtask
virtual task do_data_check();
endtask
function bit is_addr_valid(bit [31:0] addr);//首先判断传进来的地址在不在我们的范围 注意传入参数上下一致
if(addr >= cfg.addr_start && addr <= cfg.addr_end)
return 1;
endfunction
function void store_data_with_hburst(lvc_ahb_transaction tr);//write时调用
// TODO implementation in child class
case(tr.burst_type)//判断burst_type类型 目前只支持SINGLE操作
SINGLE: begin
store_data_with_hsize(tr, 0);//调用判断位宽函数
end
INCR : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
default: begin `uvm_error("TYPEERR", "burst type not defined") end
endcase
endfunction
function bit check_data_with_hburst(lvc_ahb_transaction tr);//read时调用 注意bit是有返回值
// TODO implementation in child class
case(tr.burst_type)
SINGLE: begin
check_data_with_hburst = (check_data_with_hsize(tr, 0));//如果对比结果返回1则整体返回1
end
INCR : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR4 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR8 : begin `uvm_error("TYPEERR", "burst type not supported yet") end
WRAP16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
INCR16: begin `uvm_error("TYPEERR", "burst type not supported yet") end
default: begin `uvm_error("TYPEERR", "burst type not defined") end
endcase
if(check_data_with_hburst)
`uvm_info("DATACHK", $sformatf("ahbram[%0x] hburst[%s] is as expected", tr.addr, tr.burst_type), UVM_HIGH)
else
`uvm_error("DATACHK", $sformatf("ahbram[%0x] hburst[%s] is NOT as expected", tr.addr, tr.burst_type))
endfunction
function void store_data_with_hsize(lvc_ahb_transaction tr, int beat);
case(tr.burst_size)//目前只支持8、16、32bit 将数据存放mem中
BURST_SIZE_8BIT : mem[tr.addr] = tr.data[beat] & 32'h0000_00FF;
BURST_SIZE_16BIT : mem[tr.addr] = tr.data[beat] & 32'h0000_FFFF;
BURST_SIZE_32BIT : mem[tr.addr] = tr.data[beat] & 32'hFFFF_FFFF;
BURST_SIZE_64BIT : begin `uvm_error("TYPEERR", "burst size not supported") end
default : begin `uvm_error("TYPEERR", "burst size not supported") end
endcase
endfunction
function bit check_data_with_hsize(lvc_ahb_transaction tr, int beat);
bit[63:0] data;//声明一个data存放读过来的数据
case(tr.burst_size)//如果读过来地址的数据等于mem存放的相同地址数据,则返回1
BURST_SIZE_8BIT : begin data = tr.data[beat] & 32'h0000_00FF; if(mem[tr.addr] == data) check_data_with_hsize = 1; end
BURST_SIZE_16BIT : begin data = tr.data[beat] & 32'h0000_FFFF; if(mem[tr.addr] == data) check_data_with_hsize = 1; end
BURST_SIZE_32BIT : begin data = tr.data[beat] & 32'hFFFF_FFFF; if(mem[tr.addr] == data) check_data_with_hsize = 1; end
BURST_SIZE_64BIT : begin `uvm_error("TYPEERR", "burst size not supported") end
default : begin `uvm_error("TYPEERR", "burst size not supported") end
endcase
cfg.scb_check_count++;//计数
if(check_data_with_hsize)//如果对比后返回1说明相等
`uvm_info("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x = actual 'h%0x", tr.addr, mem[tr.addr], data), UVM_HIGH)
else begin
cfg.scb_check_error++;//否则说明错误
`uvm_error("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x != actual 'h%0x", tr.addr, mem[tr.addr], data))
end
endfunction
endclass
`endif