在testbench中,对sram进行读写操作,验证sram的功能

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


         
        
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值