MCDF实验4

要求1.1

画出验证化简框图,理解实验验证环境,明白功能测试点的展开位置。

要求1.2 功能点测试

代码完整性测试

该部分不需要修改代码,直接编译所给的文件,但是编译文件若使用Questa需要注意一定的顺序,使用VCS则需要注意文件列表 filelist.f 中文件的排列顺序。
在Verdi中显示波形如下图所示:alt
从图中可见,通道0,1,2以一定的优先级顺序进行发送数据。这在实验0中的控制寄存器描述可知,bit(2:1)是优先级的设置位,0最高,3最低,复位值位3。在代码中可见,通道0,1,2的优先级依次设置为了0,1,2。
带尺寸的图片

寄存器读写测试

测试内容:所有控制寄存器、状态寄存器的读写测试。
测试通过标准:读写值是否正确。

代码

class mcdf_reg_write_read_test extends mcdf_base_test;
    function new(string name = "mcdf_reg_write_read_test");
      super.new(name);
    endfunction

    task do_reg();
      bit[7:0] chnl_rw_addrs[] = '{`SLV0_RW_ADDR,`SLV1_RW_ADDR,`SLV2_RW_ADDR};  
      bit[7:0] chnl_ro_addrs[] = '{`SLV0_R_ADDR,`SLV1_R_ADDR,`SLV2_R_ADDR};
      int pwidth = `PAC_LEN_WIDTH + `PRIO_WIDTH + 1;
      // pwidth = 6,1<<6 - 1 = 63 = 6'b111111 = 32'h0000003f
      bit[31:0] check_pattern[] = '{((1<<pwidth)-1),0,((1<<pwidth)-1)};
      bit[31:0] wr_val, rd_val;

      // read and write test for controlling register
      foreach(chnl_rw_addrs[i]) begin
        foreach(check_pattern[i]) begin
          wr_val = check_pattern[i];
          this.write_reg(chnl_rw_addrs[i],wr_val);
          this.read_reg(chnl_rw_addrs[i],rd_val);
          void'(this.diff_value(wr_val,rd_val));
        end
      end

      // read test for state register
      foreach(chnl_ro_addrs[i]) begin
        this.read_reg(chnl_ro_addrs[i],rd_val);
      end

      // send IDLE command
      this.idle_reg();
    endtask
  endclass:mcdf_reg_write_read_test

仿真结果

在Verdi查看波形,对于控制寄存器的读写测试,数据依次为32’h0000003f, 32’h00000000, 32’h0000003f。接着是对状态寄存器的读测试,数据三次固定随机化为32’h00000020。对于空闲周期的显示,在波形图中没有进行显示得到,但在仿真文件数据中可见。
在这里插入图片描述
在这里插入图片描述

寄存器稳定性测试

测试要求:对控制寄存器的保留位进行非法的读写操作,对状态寄存器的保留位进行非法写入操作,并将数据读出,验证是否能成功写入。

代码

与寄存器读写测试差不多,不同的是写入的数据是非法的。

  class mcdf_reg_illegal_access_test extends mcdf_base_test;
    function new(string name = "mcdf_reg_illegal_access_test");
      super.new(name);
    endfunction

    task do_reg();
      bit[7:0] chnl_rw_addrs[] = '{`SLV0_RW_ADDR,`SLV1_RW_ADDR,`SLV2_RW_ADDR};  
      bit[7:0] chnl_ro_addrs[] = '{`SLV0_R_ADDR,`SLV1_R_ADDR,`SLV2_R_ADDR};
      int pwidth = `PAC_LEN_WIDTH + `PRIO_WIDTH + 1;
      bit[31:0] check_pattern[] = '{3{32'hffff_ffc0}};
      bit[31:0] wr_val, rd_val;

      // illegal write and read for controlling register
      foreach(chnl_rw_addrs[i]) begin
        foreach(check_pattern[i]) begin
          wr_val = check_pattern[i];
          this.write_reg(chnl_rw_addrs[i],wr_val);
          this.read_reg(chnl_rw_addrs[i],rd_val);
          void'(this.diff_value(wr_val,rd_val));
        end
      end

      // illegal write for state register
      foreach(chnl_ro_addrs[i]) begin
        wr_val = 32'hffff_ff00;
        this.write_reg(chnl_ro_addrs[i],wr_val);
        this.read_reg(chnl_ro_addrs[i],rd_val);
        void'(this.diff_value(0,rd_val));
      end

      // send IDLE command
      this.idle_reg();
    endtask    
  endclass:mcdf_reg_illegal_access_test

仿真结果

在这里插入图片描述
从结果图中,可以看见对于非法写入,读出来的数据值是寄存器默认值。

数据通道开关测试

测试要求:失能控制状态寄存器的使能端en,测试在此状态下能否进行数据写入。
将监测的信号en传入到checker中,添加了do_channel_disable_test(int id)任务,以及在tb.sv中添加了数据通道连接部分,更改了set_interface函数的配置问题,以及在checker的run函数中调用添加的任务。最后可以仿真程序,没有在仿真文件中打印最后的summary信息。

代码

// mcdf_checker中添加
    task do_channel_disable_check(int id);
      forever begin
        @(posedge this.mcdf_vif.clk iff (this.mcdf_vif.rstn && this.mcdf_vif.mon_ck.chnl_en[id]===0));
        if(this.chnl_vifs[id].mon_ck.ch_valid===1 && this.chnl_vifs[id].mon_ck.ch_ready===1)
          rpt_pkg::rpt_msg("[CHKERR]", 
            $sformatf("ERROR! %0t when channel disabled, ready signal raised when valid high",$time), 
            rpt_pkg::ERROR, 
            rpt_pkg::TOP);
      end
    endtask
    // checker 中添加通道开关任务
    task run();
      fork
        this.do_channel_disable_check(0);
        this.do_channel_disable_check(1);
        this.do_channel_disable_check(2);
        this.do_compare();
        this.refmod.run();
      join
    endtask
  // 在tb.sv中 mcdf interface monitoring MCDF ports and signals
  assign mcdf_if.chnl_en[0] = tb.dut.ctrl_regs_inst.slv0_en_o;
  assign mcdf_if.chnl_en[1] = tb.dut.ctrl_regs_inst.slv1_en_o;
  assign mcdf_if.chnl_en[2] = tb.dut.ctrl_regs_inst.slv2_en_o;

仿真结果

在这里插入图片描述
可以看到,成功比较了一百次信息,且比较的通道为没有失能的数据通道2。
在这里插入图片描述

优先级测试

测试要求:为不同数据通道配置相同或不同的优先级,在通道使能的情况下进行测试。
测试标准:优先级相同时,应该采用轮询机制进行接收;优先级不同时,按照优先级顺序进行接收。

1.优先级不同时的测试

对应于代码完整性测试的代码部分,将优先级设置为不同的数值,进行测试。

    task do_reg();
      bit[31:0] wr_val, rd_val;
      // slv0 with len=8,  prio=1, en=1
      wr_val = (1<<3)+(1<<1)+1;
      this.write_reg(`SLV0_RW_ADDR, wr_val);
      this.read_reg(`SLV0_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV0_WR_REG"));

      // slv1 with len=16, prio=2, en=1
      wr_val = (2<<3)+(2<<1)+1;
      this.write_reg(`SLV1_RW_ADDR, wr_val);
      this.read_reg(`SLV1_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV1_WR_REG"));
      // slv2 with len=32, prio=0, en=1
      wr_val = (3<<3)+(0<<1)+1;
      this.write_reg(`SLV2_RW_ADDR, wr_val);
      this.read_reg(`SLV2_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV2_WR_REG"));
      // send IDLE command
      this.idle_reg();
    endtask

如仿真结果图所示,通道数据发送顺序为优先级顺序,即2,0,1。
在这里插入图片描述

2.优先级相同时的测试(暂未解决)

在将三个数据通道的优先级均设置为0时,通过仿真来看,数据也是按照轮询仲裁的0,1,2进行发送的,但是并没有添加轮询仲裁机制,对代码的修改只是进行了优先级的设置。正确的做法,应该是加入轮询机制,但是在本次实验中,还未解决想明白。

参考链接:

链接: 路科验证MCDF_svlab4笔记

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值