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

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 

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

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: ahb-sram指的是高级外围总线(AHB)和静态随机存储器(SRAM)之间的接口设计和验证AHB-SRAM设计验证主要关注于确保AHB总线和SRAM之间的通信正常和可靠。设计验证的过程包括以下几个关键步骤: 1. 规划设计验证策略:在开始验证之前,需要明确定义验证目标和计划。确定验证所需资源、验证方法和验证环境等。 2. 静态验证:进行静态验证以评估设计的一致性和正确性。这可以通过使用模拟和仿真工具来完成,以验证设计的逻辑功能是否符合规格要求。 3. 动态验证:通过建立高级仿真模型或使用硬件描述语言(HDL)编写测试程序,进行动态验证。这些测试程序模拟了实际使用AHB-SRAM接口的情况,验证了设计和实现是否能够正确地处理各种读写操作和异常情况。 4. 性能验证:通过使用性能评估工具和技术,测试和验证设计在处理大量数据时的吞吐量、延迟和带宽等性能指标。这有助于确保AHB-SRAM设计能够满足系统需求。 5. 集成验证:将AHB-SRAM设计与其他子系统和外设集成,验证设计在整个系统中的功能和性能。这涉及到集成测试和系统级仿真,以确保整个系统的一致性和稳定性。 6. 错误排查和调试:在设计验证过程中,可能会发现各种问题和错误。需要进行适当的排查和调试,以找出问题的原因,并修复设计中的错误。 通过上述步骤的设计验证过程,可以最大程度地确保AHB-SRAM设计在实际应用中的正确性和可靠性。这样可以提高系统的稳定性和性能,并降低后续开发和维护的风险和成本。 ### 回答2: AHB(SRAM)设计验证是对AHB(SRAM)的硬件设计进行验证的过程。AHB指的是高级外设总线(Advanced High-performance Bus),是一种用于处理器与外设之间的通信的总线协议。SRAM指的是静态随机存取存储器(Static Random-access Memory),是一种常见的计算机内存存储单元。 AHB-SRAM的设计验证旨在确保这个硬件设计符合AHB协议,并能够正确地存储和读取数据。验证过程一般包括以下几个步骤: 1. 设计规划:确定设计验证的目标和范围,编写验证计划和验证测试案例。 2. 功能验证:通过对设计电路进行功能仿真,验证设计的各项功能是否满足需求。通过使用一些特定的设计验证工具,对设计电路进行输入和输出的模拟,以验证逻辑电路的正确性。 3. 性能验证:通过对设计电路进行性能仿真,验证设计的时序和时钟频率是否满足要求。通过模拟各种情况下的数据存储和读取操作,检测潜在的性能瓶颈。 4. 物理验证:通过对设计电路进行物理验证验证设计的布局和连线是否符合物理设计规范和约束条件。通过使用专业的物理验证工具,检查电路中是否存在物理故障,如电气连接问题、时序冲突等。 5. 集成验证:将设计电路与其他相关组件进行集成,验证整个系统的功能和性能。 AHB-SRAM设计验证是一个非常关键的步骤,它能够检测和纠正设计中的错误和问题,确保最终设计的可靠性和稳定性。只有通过了验证的设计才能进行后续的制造和生产。同时,设计验证还能够提供设计改进和优化的反馈,以便进一步提高设计的性能和效果。 ### 回答3: AHB(SRAM)是一种特定类型的静态随机存取存储器设计,用于在系统总线上进行数据传输和存储。设计验证是确保设计的功能和性能符合规范和需求的过程。 AHB-SRAM设计验证的目标是验证AHB-SRAM的功能正确性、数据的一致性和性能方面的指标。验证过程通常包括以下几个步骤: 1. 功能验证:通过编写测试用例,验证AHB-SRAM在不同的读写操作下是否能够正确地读写数据。测试用例需要覆盖各种读写情况,包括随机读写、顺序读写等。同时还需要测试错误情况下的处理机制,比如写入冲突、读取无效地址等。通过功能验证可以确保AHB-SRAM能够按照规定的操作进行数据的读写。 2. 数据一致性验证:在多核系统中,多个处理器可能同时访问AHB-SRAM。数据一致性验证的目标是验证在多个处理器同时读写AHB-SRAM时,数据的一致性是否能够保持。验证过程中需要考虑读写操作的时序和数据同步机制,确保在多个处理器之间进行数据交换时不会出现数据冲突或数据丢失的情况。 3. 性能验证AHB-SRAM的性能指标包括读写延迟和带宽。性能验证的目标是通过测试用例和性能评估工具来验证AHB-SRAM能够在规定的时钟周期内完成读写操作,并能够满足带宽需求。性能验证可以帮助确定系统中AHB-SRAM的使用限制和资源分配。 通过上述验证步骤,可以确保AHB-SRAM设计的正确性和性能符合预期。验证过程需要仔细设计测试用例和评估工具,同时需要对设计进行仿真和调试,以确保设计的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值