【SV练习】MCDF实验5

这篇博客详细介绍了Verilog验证中关于覆盖率的几个关键概念,包括iff条件、数据采样、覆盖点、交叉覆盖率等。讲解了如何在设计中定义和使用covergroup,以及如何在Questasim环境中进行编译、仿真、合并和分析覆盖率。文中还给出了具体的covergroup实例,如寄存器读写、稳定性、通道开关和优先级测试等,展示了如何设置覆盖条件和交叉覆盖以确保全面的验证覆盖率。

知识点:

iff:在时间控制中添加修饰词iff,只有当iff后面的条件为真的时候,@时间才会触发。

数据采样:SV会默认为某个covergroup创建bin,用户也可以自己定义,如果采样变量的范围过大而有没有指定bin,那么系统会自动的分配64个bin,可以使用auto_bin_max来指定创建最大bin的数目。条件覆盖率:可以使用关键词iff给covergroup添加条件,这种做法经常用于在复位期间关闭覆盖以忽略不合理的触发条件,可以使用start和stop来控制各个covergroup各个独立实例。

覆盖点:一个覆盖组可以包含多个覆盖点,覆盖点元素可以包含显示bins和隐示bins 

覆盖点的交叉覆盖率

交叉覆盖名:cross 交叉覆盖点1,交叉覆盖点2;

忽略bin:可以使用ignore_bins来排除那些不计算功能的值域,最终他们并不会计入covergroup的覆盖率中

非法bin:使用illegal_bins对特定的bin进行标示。

排除部分cross bin:通过使用ignore_bins 、binsof和intersect分别指定covergroup和值域,这样可以清除很多不关心的cross bin。

1、编译:

选择与设计相关的文件.v

点击右键,选择 compile -> compile properties,在弹出设置栏的 coverage 一栏中, 如图选择以下选项,然后点击 OK。(只收集与设计相关的覆盖率)

2、仿真:

仿真命令:

vsim -i -classdebug -solvefaildebug -coverage -coverstore D:/questasim_file/lab5/coverage -testname mcdf_full_random_test -sv_seed random +TESTNAME=mcdf_full_random_test -l mcdf_full_random_test.log work.tb

-coverage:会在仿真时产生代码覆盖率数据,功能覆盖率数据则默认会生成,与此选项无关.

-coverstore COVERAGE_ STORAGE_ PATH:这个命令是用来在仿真在最后结束时,生成覆盖率数据并且存储到 COVERAGE_ STORAGE_ PATH.你可以自己制定 COVERAGE_STORAGE_ PATH,但需要注意路径名中不要包含中文字符。

-testname. TESTNAME:这个选项是你需要添加本次仿真的 test 名称,你可以使用 同+TESTNAME 选项一样的 test 名称。仿真结束后 , 将在 COVERAGE_STORAGE_PATH 下产生一个覆盖率数据文件 { TESTNAME}_{SV_SEED}.data 

 仿真命令:

run -all

利用仿真器直接查看代码覆盖率或者功能覆盖率:选中 View -> Coverage -> "Code Coverage Analysys"和” Covergroups"。

查看代码覆盖率:那么选择新添加的 Analysis 窗口,然后逐个点击Sim 窗口中 DUT 层次中的个别模块。

功能覆盖率:

3、合并覆盖率:

统一把生成在 COVERAGE_STORAGE_PATH下面生成的 xxx.data 覆盖率数据做合并。

 

vcover merge -out merged_coverage.ucdb D:/questasim_file/lab5/coverage

 合并多个数据,功能覆盖率和代码覆盖率明显提高。

4、分析覆盖率:

 选择 Tools -> Coverage Report-> HTML,按照下图所示进行勾选

忽略寄存器中高位没有翻转的位:参考路科验证MCDF_svlab5笔记_Hardworking_IC_boy的博客-优快云博客_合并覆盖率

5、总体分析:

 实验五是在实验四的基础上,添加了一个组件mcdf_coverage, 定义了五个covergroup,然后在new里面分别例化,四个采样任务,对五个covergroup进行采样。

寄存器读写测试:

    covergroup cg_mcdf_reg_write_read;
      addr: coverpoint reg_vif.mon_ck.cmd_addr {
        type_option.weight = 0;
        bins slv0_rw_addr = {`SLV0_RW_ADDR};
        bins slv1_rw_addr = {`SLV1_RW_ADDR};
        bins slv2_rw_addr = {`SLV2_RW_ADDR};
        bins slv0_r_addr  = {`SLV0_R_ADDR };
        bins slv1_r_addr  = {`SLV1_R_ADDR };
        bins slv2_r_addr  = {`SLV2_R_ADDR };
      }
      cmd: coverpoint reg_vif.mon_ck.cmd {
        type_option.weight = 0;
        bins write = {`WRITE};
        bins read  = {`READ};
        bins idle  = {`IDLE};
      }
      cmdXaddr: cross cmd, addr {
        bins slv0_rw_addr = binsof(addr.slv0_rw_addr);
        bins slv1_rw_addr = binsof(addr.slv1_rw_addr);
        bins slv2_rw_addr = binsof(addr.slv2_rw_addr);
        bins slv0_r_addr  = binsof(addr.slv0_r_addr );
        bins slv1_r_addr  = binsof(addr.slv1_r_addr );
        bins slv2_r_addr  = binsof(addr.slv2_r_addr );
        bins write        = binsof(cmd.write);
        bins read         = binsof(cmd.read );
        bins idle         = binsof(cmd.idle );
        bins write_slv0_rw_addr  = binsof(cmd.write) && binsof(addr.slv0_rw_addr);
        bins write_slv1_rw_addr  = binsof(cmd.write) && binsof(addr.slv1_rw_addr);
        bins write_slv2_rw_addr  = binsof(cmd.write) && binsof(addr.slv2_rw_addr);
        bins read_slv0_rw_addr   = binsof(cmd.read) && binsof(addr.slv0_rw_addr);
        bins read_slv1_rw_addr   = binsof(cmd.read) && binsof(addr.slv1_rw_addr);
        bins read_slv2_rw_addr   = binsof(cmd.read) && binsof(addr.slv2_rw_addr);
        bins read_slv0_r_addr    = binsof(cmd.read) && binsof(addr.slv0_r_addr); 
        bins read_slv1_r_addr    = binsof(cmd.read) && binsof(addr.slv1_r_addr); 
        bins read_slv2_r_addr    = binsof(cmd.read) && binsof(addr.slv2_r_addr); 
      }
    endgroup

type_option.weight = 0表示不关心addr:covergroup和cmd:covergroup这两个覆盖组,表示权重为0,然后重新声明。

寄存器稳定性测试:主要是对于非法地址的读写操作。

   covergroup cg_mcdf_reg_illegal_access;
      addr: coverpoint reg_vif.mon_ck.cmd_addr {
        type_option.weight = 0;
        bins legal_rw = {`SLV0_RW_ADDR, `SLV1_RW_ADDR, `SLV2_RW_ADDR};		//合法地址的读写范围
        bins legal_r = {`SLV0_R_ADDR, `SLV1_R_ADDR, `SLV2_R_ADDR};			//合法地址的读范围
        bins illegal = {[8'h20:$], 8'hC, 8'h1C};							//非法地址的范围
      }
      cmd: coverpoint reg_vif.mon_ck.cmd {
        type_option.weight = 0;
        bins write = {`WRITE};
        bins read  = {`READ};
      }
      wdata: coverpoint reg_vif.mon_ck.cmd_data_m2s {						//写数据
        type_option.weight = 0;
        bins legal = {[0:'h3F]};											//00_0000到11_1111是合法的
        bins illegal = {['h40:$]};											//剩下的都是非法的
      }
      rdata: coverpoint reg_vif.mon_ck.cmd_data_s2m {							
        type_option.weight = 0;
        bins legal = {[0:'hFF]};
        illegal_bins illegal = default;										//超过低八位的都是非法的
      }
      cmdXaddrXdata: cross cmd, addr, wdata, rdata {						//组合
        bins addr_legal_rw = binsof(addr.legal_rw);
        bins addr_legal_r = binsof(addr.legal_r);
        bins addr_illegal = binsof(addr.illegal);
        bins cmd_write = binsof(cmd.write);
        bins cmd_read = binsof(cmd.read);
        bins wdata_legal = binsof(wdata.legal);
        bins wdata_illegal = binsof(wdata.illegal);
        bins rdata_legal = binsof(rdata.legal);
        bins write_illegal_addr = binsof(cmd.write) && binsof(addr.illegal);
        bins read_illegal_addr  = binsof(cmd.read) && binsof(addr.illegal);
        bins write_illegal_rw_data = binsof(cmd.write) && binsof(addr.legal_rw) && binsof(wdata.illegal);
        bins write_illegal_r_data = binsof(cmd.write) && binsof(addr.legal_r) && binsof(wdata.illegal);
      }
    endgroup

 数据通道开关测试:特定的通道关闭,en为0,但是vaild为高,测试数据能否写入成功。

    covergroup cg_channel_disable;
      ch0_en: coverpoint mcdf_vif.mon_ck.chnl_en[0] {				//enable为0
        type_option.weight = 0;
        wildcard bins en  = {1'b1};
        wildcard bins dis = {1'b0};
      }
      ch1_en: coverpoint mcdf_vif.mon_ck.chnl_en[1] {				//enable为1
        type_option.weight = 0;
        wildcard bins en  = {1'b1};
        wildcard bins dis = {1'b0};
      }
      ch2_en: coverpoint mcdf_vif.mon_ck.chnl_en[2] {
        type_option.weight = 0;
        wildcard bins en  = {1'b1};
        wildcard bins dis = {1'b0};
      }
      ch0_vld: coverpoint chnl_vifs[0].mon_ck.ch_valid {
        type_option.weight = 0;
        bins hi = {1'b1};
        bins lo = {1'b0};
      }
      ch1_vld: coverpoint chnl_vifs[1].mon_ck.ch_valid {
        type_option.weight = 0;
        bins hi = {1'b1};
        bins lo = {1'b0};
      }
      ch2_vld: coverpoint chnl_vifs[2].mon_ck.ch_valid {
        type_option.weight = 0;
        bins hi = {1'b1};
        bins lo = {1'b0};
      }
      chenXchvld: cross ch0_en, ch1_en, ch2_en, ch0_vld, ch1_vld, ch2_vld {
        bins ch0_en  = binsof(ch0_en.en);
        bins ch0_dis = binsof(ch0_en.dis);
        bins ch1_en  = binsof(ch1_en.en);
        bins ch1_dis = binsof(ch1_en.dis);
        bins ch2_en  = binsof(ch2_en.en);
        bins ch2_dis = binsof(ch2_en.dis);
        bins ch0_hi  = binsof(ch0_vld.hi);
        bins ch0_lo  = binsof(ch0_vld.lo);
        bins ch1_hi  = binsof(ch1_vld.hi);
        bins ch1_lo  = binsof(ch1_vld.lo);
        bins ch2_hi  = binsof(ch2_vld.hi);
        bins ch2_lo  = binsof(ch2_vld.lo);
        bins ch0_en_vld = binsof(ch0_en.en) && binsof(ch0_vld.hi);
        bins ch0_dis_vld = binsof(ch0_en.dis) && binsof(ch0_vld.hi);
        bins ch1_en_vld = binsof(ch1_en.en) && binsof(ch1_vld.hi);
        bins ch1_dis_vld = binsof(ch1_en.dis) && binsof(ch1_vld.hi);
        bins ch2_en_vld = binsof(ch2_en.en) && binsof(ch2_vld.hi);
        bins ch2_dis_vld = binsof(ch2_en.dis) && binsof(ch2_vld.hi);
      }
    endgroup

 优先级测试:不同通道配置不同的优先级。

    covergroup cg_arbiter_priority;						//配置每个channel的priority
      ch0_prio: coverpoint arb_vif.mon_ck.slv_prios[0] {
        bins ch_prio0 = {0}; 
        bins ch_prio1 = {1}; 
        bins ch_prio2 = {2}; 
        bins ch_prio3 = {3}; 
      }
      ch1_prio: coverpoint arb_vif.mon_ck.slv_prios[1] {
        bins ch_prio0 = {0}; 
        bins ch_prio1 = {1}; 
        bins ch_prio2 = {2}; 
        bins ch_prio3 = {3}; 
      }
      ch2_prio: coverpoint arb_vif.mon_ck.slv_prios[2] {
        bins ch_prio0 = {0}; 
        bins ch_prio1 = {1}; 
        bins ch_prio2 = {2}; 
        bins ch_prio3 = {3}; 
      }
    endgroup

 下行从端低带宽测试:测试下行从端的延迟

    covergroup cg_formatter_length;						//真实情况下。还是需要通过cross进行组合
      id: coverpoint fmt_vif.mon_ck.fmt_chid {
        bins ch0 = {0};
        bins ch1 = {1};
        bins ch2 = {2};
        illegal_bins illegal = default; 
      }
      length: coverpoint fmt_vif.mon_ck.fmt_length {
        bins len4  = {4};
        bins len8  = {8};
        bins len16 = {16};
        bins len32 = {32};
        illegal_bins illegal = default;
      }
    endgroup

<think>好的,用户正在寻找与MCDF实验相关的Lab0笔记和课程资料。首先,我需要回顾已有的引用内容,看看是否有相关信息。引用[2]提到了“路科验证MCDF_uvmlab0”,这可能与Lab0相关。其中描述了在UVM测试环境中注释掉raise/drop_objection,并添加了10ns延时和uvm_info的信息。这可能是Lab0中的实验步骤,涉及UVM的基本结构和仿真设置。 用户提到的MCDF实验可能是一系列验证实验,Lab0通常是入门级的实验,介绍基本环境和流程。根据引用[3],MCDF实验涉及寄存器地址和操作,但Lab0可能更侧重于环境搭建和基础验证组件。引用[2]中的代码示例展示了run_phase的任务结构,适合Lab0的内容,可能涉及如何编写测试用例和仿真控制。 此外,用户可能需要知道如何获取完整的课程资料或实验指导。可能需要建议用户参考路科验证的官方资料、课程网站或联系相关教育机构。同时,引用提供的博客链接可能包含更多细节,但需注意版权问题,建议用户通过正规渠道获取材料。 需要确认是否存在其他引用中未提到的Lab0内容,但根据现有信息,引用[2]是最相关的。总结来说,回答应指出引用[2]中的内容与Lab0相关,并建议用户查阅该资料,同时提供可能的获取途径。</think>根据您提供的信息,MCDF实验Lab0的相关内容在引用[2]中有部分涉及,主要与UVM验证框架的基础配置和测试用例设计相关。以下是关键信息整理: ### MCDF实验Lab0相关内容 1. **UVM测试环境配置** Lab0实验展示了基础UVM测试结构,移除了`raise/drop_objection`流程(旧版UVM控制方式),改用`#10ns`延时结合`uvm_info`输出调试信息。这符合UVM1.2版本后对`objection`机制的弱化要求[^2]。 ```systemverilog task run_phase(uvm_phase phase); `uvm_info("UVM_TOP", "test is running", UVM_LOW) #10ns; `uvm_info("UVM_TOP", "test finished after 10ns", UVM_LOW); endtask ``` 2. **仿真时间单位控制** 代码中未显式定义时间单位(如`timescale 1ns/1ps`),默认采用仿真器的最小时间分辨率(通常为1ns)。因此,低于1ns的延时(如`#5ns`)会被忽略。 3. **实验目标推测** 根据代码片段,Lab0可能聚焦于: - UVM测试平台基础结构搭建 - 调试信息输出与仿真控制 - UVM验证组件的初步调用 ### 资料获取建议 1. **课程官方渠道** 建议联系路科验证官方或访问其教学平台获取完整实验指导书。部分公开资料可通过其官网或合作教育平台查询。 2. **参考博客资源** 引用[2]中提到的博客文章(标题含“路科验证MCDF_uvmlab0”)可能包含更详细的实验步骤解析,但需注意第三方资料的准确性验证。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值