summary:本文主要介绍对在testbench中,对多个sram进行读写测试,确保sram的功能能够实现。
1. 对于单端口sram:
1)需要准备一个待测sram的hierarchy_sp.txt,并且里面包含 hierarchy, depth, addr_width, data_width, 是否支持byte 操作,示例如下:
sp_128x256m8.i_sp_128x256m8 128 7 256 1 (深度:128,地址位宽:7bit,数据位宽:256,支持byte读取)
sp_128x35.i_sp_128x35 128 7 35 0 (深度:128,地址位宽:7bit,数据位宽:35,不支持byte读取)
2)在task body 里面扫描这个hierarchy_sp.txt文件,代码如下:
task sram_check_seq::body();
// ----- SRAM 1 port test -----
sram1p_file_pad = $fopen("./hierarchy_sp.txt", "r");
if(sram1p_file_pad == 0) begin
`uvm_fatal(get_name(),"ERROR!! Cannot open SRAM 1 port file!");
end
do begin
result = $fscanf(sram1p_file_pad, "%s %d %d %d %d\n", sram_param[0], sram_param[1], sram_param[2], sram_param[3], sram_param[4]);
`uvm_info(get_name(),$sformatf("the path is %s, depth is %0d, addr width is %0d, data width is %0d, byte enable is %0d\n", sram_param[0], sram_param[1], sram_param[2], sram_param[3], sram_param[4]),UVM_LOW);
sram1p_rd_wr();
end while(result !== -1);
endtask
3)里面调用的sram1p_rd_wr()函数如下:通过拿到扫描到的参数,按照sram 相应的时序,把数据force到sram里面,再读出来,进行数据比对 。
task sram_check_seq::sram1p_rd_wr();
reg [400*10-1:0] sram_wdata_path ;
reg [400*10-1:0] sram_rdata_path ;
reg [400*10-1:0] sram_addr_path ;
reg [400*10-1:0] sram_cen_path ;
reg [400*10-1:0] sram_wen_path ;
reg [400*10-1:0] sram_bweb_path ;
reg [SRAM_DATA_W-1:0] sram_wdata ;
reg [SRAM_DATA_W-1:0] sram_rdata ;
reg [SRAM_ADDR_W :0] sram_addr ;
reg [SRAM_DATA_W-1:0] tmp_rdata ;
reg [SRAM_DATA_W-1:0] data_index ;
reg [SRAM_DATA_W-1:0] loop_index ;
reg [SRAM_DATA_W-1:0] exp_rdata[0:SRAM_DEPTH-1] ;
begin
sram_wdata_path = {sram_param[0], ".ez_din"};
sram_rdata_path = {sram_param[0], ".ez_dout"};
sram_addr_path = {sram_param[0], ".ez_addr"};
sram_cen_path = {sram_param[0], ".ez_cs"};
sram_wen_path = {sram_param[0], ".ez_we"};
if (sram_param[4]) begin //byte enable signal
sram_bweb_path = {sram_param[0], ".ez_bweb"};
end
$display("SRAM Write and Read TEST START ....");
#10ns;
for(loop_index = 0; loop_index < 2; loop_index = loop_index + 1) begin
for(sram_addr = 0; sram_addr < sram_param[1]; sram_addr = sram_addr + 1) begin
std::randomize(sram_wdata);
exp_rdata[sram_addr] = sram_wdata;
//$display($psprintf("sram_wdata is %0h", sram_wdata));
// ------------------------ write sram --------------------------------------------
@(negedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_force(sram_cen_path, 1'b1);
uvm_hdl_force(sram_wen_path, 16'h1);
uvm_hdl_force(sram_addr_path, sram_addr);
uvm_hdl_force(sram_wdata_path, sram_wdata);
if (sram_param[4]) begin //byte enable signal
uvm_hdl_force(sram_bweb_path, 64'hffff_ffff_ffff_ffff);
end
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_release(sram_cen_path);
uvm_hdl_release(sram_wen_path);
uvm_hdl_release(sram_addr_path);
uvm_hdl_release(sram_wdata_path);
if (sram_param[4]) begin //byte enable signal
uvm_hdl_release(sram_bweb_path);
end
end
for(sram_addr = 0; sram_addr < sram_param[1]; sram_addr = sram_addr + 1) begin
// ------------------------ read sram --------------------------------------------
@(negedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_force(sram_cen_path, 1'b1);
uvm_hdl_force(sram_wen_path, 16'h0);
uvm_hdl_force(sram_addr_path, sram_addr);
@(negedge sub_env_cfg.gpu_misc_vif.clk_skybox);
if(!uvm_hdl_read(sram_rdata_path, sram_rdata)) begin
`uvm_error(get_name(),$sformatf("uvm_hdl_read FAIL!!!"));
end
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_release(sram_cen_path);
uvm_hdl_release(sram_wen_path);
uvm_hdl_release(sram_addr_path);
tmp_rdata = exp_rdata[sram_addr];
for(data_index = 0; data_index < sram_param[3]; data_index = data_index + 1) begin
if(sram_rdata[data_index] !== tmp_rdata[data_index]) begin
`uvm_error(get_name(),$sformatf("[%0s] SRAM Write and Read inconsistent!!!, sram_wdata: %0h, sram_rdata: %0h", sram_param[0], tmp_rdata, sram_rdata));
end
end
`uvm_info(get_name(),$psprintf("SRAM Write data: %0h, SRAM Read data: %0h", tmp_rdata, sram_rdata),UVM_LOW);
end
end
$display("SRAM Write and Read TEST END!!!");
end
endtask
2. 对于双端口sram:
1)需要准备一个待测sram的hierarchy_dp.txt,并且里面包含 hierarchy, depth, addr_width, data_width, 是否支持byte 操作,示例如下:
dpc_3584x32.i_dpc_3584x32 3584 12 32 (深度:3584,地址位宽:12bit,数据位宽:32)
dpc_16x1334.i_dpc_16x1341 16 4 1341 (深度:16,地址位宽:4bit,数据位宽:1314)
2)在task body 里面扫描这个hierarchy_dp.txt文件,代码如下:
task sram_check_seq::body();
// ----- SRAM 2 port test -----
sram2p_file_pad = $fopen("./sram_list_dp.txt", "r");
if(sram2p_file_pad == 0) begin
`uvm_fatal(get_name(),"ERROR!! Cannot open SRAM 2 port file!");
$finish;
end
do begin
result = $fscanf(sram2p_file_pad, "%s %d %d %d\n", sram_param[0], sram_param[1], sram_param[2], sram_param[3]);
`uvm_info(get_name(),$sformatf("the path is %s, depth is %0d, addr width is %0d, data width is %0d\n", sram_param[0], sram_param[1], sram_param[2], sram_param[3]),UVM_LOW);
sram2p_rd_wr();
end while(result !== -1);
endtask
3)里面调用的sram2p_rd_wr() 函数如下:通过拿到扫描到的参数,按照sram 相应的时序,把数据force到sram里面,再读出来,进行数据比对 。
task sram_check_seq::sram2p_rd_wr();
reg [400*10-1:0] sram_wdata_path ;
reg [400*10-1:0] sram_rdata_path ;
reg [400*10-1:0] sram_waddr_path ;
reg [400*10-1:0] sram_raddr_path ;
reg [400*10-1:0] sram_wen_path ;
reg [400*10-1:0] sram_ren_path ;
reg [SRAM_DATA_W-1:0] sram_wdata ;
reg [SRAM_DATA_W-1:0] sram_rdata ;
reg [SRAM_ADDR_W :0] sram_addr ;
reg [SRAM_DATA_W-1:0] tmp_rdata ;
reg [SRAM_DATA_W-1:0] data_index ;
reg [SRAM_DATA_W-1:0] loop_index ;
reg [SRAM_DATA_W-1:0] exp_rdata[0:SRAM_DEPTH-1] ;
begin
sram_wdata_path = {sram_param[0], ".ez_din"};
sram_rdata_path = {sram_param[0], ".ez_dout"};
sram_waddr_path = {sram_param[0], ".ez_addrW"};
sram_raddr_path = {sram_param[0], ".ez_addrR"};
sram_wen_path = {sram_param[0], ".ez_we"};
sram_ren_path = {sram_param[0], ".ez_re"};
$display("SRAM Write and Read TEST START ....");
#10ns;
for (loop_index = 0; loop_index < 2; loop_index = loop_index + 1) begin
for(sram_addr = 0; sram_addr < sram_param[1]; sram_addr = sram_addr + 1)
begin
std::randomize(sram_wdata);
exp_rdata[sram_addr] = sram_wdata;
//$display($psprintf("sram_wdata is %0h", sram_wdata));
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_force(sram_wen_path, 16'hffff);
uvm_hdl_force(sram_waddr_path, sram_addr);
uvm_hdl_force(sram_wdata_path, sram_wdata);
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_release(sram_wen_path);
uvm_hdl_release(sram_waddr_path);
uvm_hdl_release(sram_wdata_path);
end
for (sram_addr = 0; sram_addr < sram_param[1]; sram_addr = sram_addr + 1) begin
// ------------------------ read sram --------------------------------------------
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_force(sram_ren_path, 16'hffff);
uvm_hdl_force(sram_raddr_path, sram_addr);
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
uvm_hdl_release(sram_ren_path);
uvm_hdl_release(sram_raddr_path);
@(posedge sub_env_cfg.gpu_misc_vif.clk_skybox);
if(!uvm_hdl_read(sram_rdata_path, sram_rdata)) begin
`uvm_error(get_name(),$sformatf("uvm_hdl_read FAIL!!!"));
end
tmp_rdata = exp_rdata[sram_addr];
for(data_index = 0; data_index < sram_param[3]; data_index = data_index + 1) begin
if(sram_rdata[data_index] !== tmp_rdata[data_index]) begin
`uvm_error(get_name(),$sformatf("[%0s] SRAM Write and Read inconsistent!!!, sram_wdata: %0h, sram_rdata: %0h", sram_param[0], tmp_rdata, sram_rdata));
end
end
`uvm_info(get_name(),$psprintf("SRAM Write data: %0h, SRAM Read data: %0h", tmp_rdata, sram_rdata),UVM_LOW);
end
end
$display("SRAM Write and Read TEST END!!!");
end
endtask