IC验证学习笔记(AHB-RAM)08addr、bsize都随机,主要做地址偏移操作

代码示例展示了在内存模型测试中,针对地址未对齐的随机化写操作,可能导致scoreboard中的数据被覆盖。为了解决这个问题,需要在scoreboard中进行地址对齐处理,确保每个写入的数据都能正确存储。代码中通过调整存储地址并处理数据偏移来实现这一目标。
摘要由CSDN通过智能技术生成

rkv_ahbram_haddr_word_unaligned_virt_seq:

 对addr和bsize都随机化操作

`ifndef RKV_AHBRAM_HADDR_WORD_UNALIGNED_VIRT_SEQ_SV
`define RKV_AHBRAM_HADDR_WORD_UNALIGNED_VIRT_SEQ_SV


class rkv_ahbram_haddr_word_unaligned_virt_seq extends rkv_ahbram_base_virtual_sequence;
  `uvm_object_utils(rkv_ahbram_haddr_word_unaligned_virt_seq)

  function new (string name = "rkv_ahbram_haddr_word_unaligned_virt_seq");
    super.new(name);
  endfunction

  virtual task body();
    bit [31:0] addr, data;
    burst_size_enum bsize;
    super.body();
    `uvm_info("body", "Entered...", UVM_LOW)
    for(int i=0; i<100; i++) begin
      std::randomize(bsize) with {bsize inside {BURST_SIZE_8BIT, BURST_SIZE_16BIT, BURST_SIZE_32BIT};};
      std::randomize(addr) with {addr inside {['h1000:'h1FFF]};
                                 bsize == BURST_SIZE_16BIT -> addr[0] == 0;//为了地址对齐
                                 bsize == BURST_SIZE_32BIT -> addr[1:0] == 0;
                                };
      std::randomize(wr_val) with {wr_val == (i << 24) + (i << 16) + (i << 8) + i;};//使每一个byte位都有数据
      data = wr_val;
      `uvm_do_with(single_write, {addr == local::addr; data == local::data; bsize == local::bsize;})
      `uvm_do_with(single_read, {addr == local::addr; bsize == local::bsize;})
    end
    `uvm_info("body", "Exiting...", UVM_LOW)
  endtask

endclass


`endif 

monitor获取过来原始数据给scb;但是scoreboard没有做地址对齐,需要修改

问题在于:按之前的情况如果存入`h10=`hFFAABBCC;

                  之后如果在`h11中存入`h11=`hEE;

                  则输出保存的结果为`h10`=`hFFAAEECC;会被覆盖掉

所以要做地址操作,保证传输过来的数据都被保存在scoreboard中:

`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];

  // 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);
        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);
    // TODO implementation in child class
    case(tr.burst_type)
      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);
    // TODO implementation in child class
    case(tr.burst_type)
      SINGLE: begin 
                check_data_with_hburst = (check_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
    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)//1:0位不管补0,地址最少相差4字节往里写,不会有覆盖现象
      BURST_SIZE_8BIT   : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);//mem接收到偏移处理后的mdata
      BURST_SIZE_16BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_32BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      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[31:0] tdata = extract_valid_data(tr.data[beat], tr.addr, tr.burst_size);
    bit[31:0] mdata = extract_valid_data(mem[{tr.addr[31:2],2'b00}],  tr.addr, tr.burst_size);
    check_data_with_hsize = tdata == mdata ? 1 : 0;
    cfg.scb_check_count++;
    if(check_data_with_hsize)
      `uvm_info("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x = actual 'h%0x", tr.addr, mdata, tdata), UVM_HIGH)
    else begin
      cfg.scb_check_error++;
      `uvm_error("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x != actual 'h%0x", tr.addr, mdata, tdata))
    end
  endfunction

  function bit [31:0] extract_current_beat_mem_data(lvc_ahb_transaction tr, int beat);//数据进行偏移处理
    bit [31:0] mdata = mem[{tr.addr[31:2],2'b00}];
    bit [31:0] tdata = tr.data[beat];//存入data
    case(tr.burst_size)	//8BIT mdata如果addr为0存放在7:0位,addr为1存放在15:8位,addr为2存放在23:16位,addr为3存放在31:24位
      BURST_SIZE_8BIT   : mdata[(tr.addr[1:0]*8 + 7) -:  8] = tdata >> (8*tr.addr[1:0]);//不管tdata多少位只拾取低八位
	  //16BIT mdata如果addr[1]为0tdata存放在16:0位,addr[1]为1存放在31:17位
      BURST_SIZE_16BIT  : mdata[(tr.addr[1]*16 + 15) -: 16] = tdata >> (16*tr.addr[1]);
      BURST_SIZE_32BIT  : mdata = tdata;
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
    return mdata;//输出mdata给mem
  endfunction

endclass

`endif 

代码分解:write操作存入mem

 function void store_data_with_hsize(lvc_ahb_transaction tr, int beat);
    case(tr.burst_size)//1:0位不管补0,如195d和195e都写在同一地址195c,但是不同偏移量
      BURST_SIZE_8BIT   : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);//mem接收到偏移处理后的mdata
      BURST_SIZE_16BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      BURST_SIZE_32BIT  : mem[{tr.addr[31:2],2'b00}] = extract_current_beat_mem_data(tr, beat);
      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 [31:0] extract_current_beat_mem_data(lvc_ahb_transaction tr, int beat);//数据进行偏移处理
    bit [31:0] mdata = mem[{tr.addr[31:2],2'b00}];
    bit [31:0] tdata = tr.data[beat];//存入data
    case(tr.burst_size)	//8BIT mdata如果addr为0存放在7:0位,addr为1存放在15:8位,addr为2存放在23:16位,addr为3存放在31:24位
      BURST_SIZE_8BIT   : mdata[(tr.addr[1:0]*8 + 7) -:  8] = tdata >> (8*tr.addr[1:0]);//不管tdata多少位只拾取低八位
	  //16BIT mdata如果addr[1]为0tdata存放在16:0位,addr[1]为1存放在31:17位
      BURST_SIZE_16BIT  : mdata[(tr.addr[1]*16 + 15) -: 16] = tdata >> (16*tr.addr[1]);
      BURST_SIZE_32BIT  : mdata = tdata;
      BURST_SIZE_64BIT  : begin `uvm_error("TYPEERR", "burst size not supported") end
      default : begin `uvm_error("TYPEERR", "burst size not supported") end
    endcase
    return mdata;//输出mdata给mem
  endfunction

        为了防止出现覆盖,mem中存放的地址为写入地址的后两位取0,如195d和195e都在同一地址195c,但是具有不同偏移量。(先地址统一再进行偏移存放)

在8BIT中,如果后两位地址为0,则数据存放在mem的7:0位;

                  如果后两位地址位1,则数据存放在mem的15:8位;

                  如果后两位地址为2,则数据存放在mem的23:16位;

                  如果后两位地址为3,则数据存放在mem的31:24位;

在16BIT中,如果addr[1]为0,则数据存放在mem的15:0位;

                    如果addr[1]为1,则数据存放在mem的31:16位;

例子:

        195d 8BIT 数据02020202

               地址统一为195c开始存放,后两位地址为1,则存放在15:8位,为00000200;

        195e 16BIT 数据03030303

              地址统一为195c开始存放,后两位地址为3,则存放在31:16位,为03030200;

        113c 16BIT 数据04040404

              地址统一为113c开始存放,后两位地址为0,则存放在15:0位,为00000404

        17f3 8BIT   数据05050505:

              地址统一为17f0开始存放,后两位地址为3,则存放在31:24位,为05000000;

read:check_data

function bit check_data_with_hsize(lvc_ahb_transaction tr, int beat);
    bit[31:0] tdata = extract_valid_data(tr.data[beat], tr.addr, tr.burst_size);
    bit[31:0] mdata = extract_valid_data(mem[{tr.addr[31:2],2'b00}],  tr.addr, tr.burst_size);
    check_data_with_hsize = tdata == mdata ? 1 : 0;
    cfg.scb_check_count++;
    if(check_data_with_hsize)
      `uvm_info("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x = actual 'h%0x", tr.addr, mdata, tdata), UVM_HIGH)
    else begin
      cfg.scb_check_error++;
      `uvm_error("DATACHK", $sformatf("ahbram[%0x] data expected 'h%0x != actual 'h%0x", tr.addr, mdata, tdata))
    end
  endfunction
function bit [31:0] extract_valid_data([`LVC_AHB_MAX_DATA_WIDTH - 1:0] data
                                        ,[`LVC_AHB_MAX_ADDR_WIDTH - 1 : 0] addr
                                        ,burst_size_enum bsize);
  
    case(bsize)
      BURST_SIZE_8BIT   : return (data >> (8*addr[1:0])) & 8'hFF;
      BURST_SIZE_16BIT  : return (data >> (16*addr[1]) ) & 16'hFFFF;
      BURST_SIZE_32BIT  : return data & 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

将监测的读数据与mem的数据都进行函数extract_valid_data处理:

如读回来195d中的数据应为00000200;右移8位并&FF得到00000002;             

    mem中195d地址统一为195c,其中数据为03030200(有195e的16bit0303);右移8位 并&FF得到00000002 

        最后两个数进行对比,结果相同;                       

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值