SV 覆盖率验证

代码覆盖率

  • 行覆盖率(line coverage):记录程序的各行代码被执行的情况。
  • 条件覆盖率(condition coverage):记录各个条件中的逻辑操作数被覆盖的情况。
  • 跳转覆盖率(toggle coverage):记录单bit信号变量的值为0/1跳转情况,如从0到1,或者从1到0的跳转。
  • 分支覆盖率(branch coverage):又称路径覆盖率(path coverage),指在if,case,for,forever,while等语句中各个分支的执行情况。
  • 状态机覆盖率(FSM coverage):用来记录状态机的各种状态被进入的次数以及状态之间的跳转情况。

功能覆盖率

  • 面向数据的覆盖率(Data-oriented Coverage)-对已进行的数据组合检查.我们可以通过编写覆盖组coverage groups)、覆盖点coverage points)和交叉覆盖cross coverage)获得面向数据的覆盖率.
  • 面向控制的覆盖率(Control-oriented Coverage)-检查行为序列sequences of behaviors)是否已经发生.通过编写SVA来获得断言覆盖率(assertion coverage).

覆盖组——covergroup

	使用**覆盖组结构(covergroup)定义覆盖模型**,覆盖组结构(covergroup construct)是一种**用户自定义**的结构类型,一旦被定义就可以创建多个实例就像类(class)一样,也是`通过new()来创建实例`的。覆盖组可以定义在module、program、interface以及class中。

​ 一个类可以包含多个covergroup;每个covergroup可以根据需要自行使能或者禁止,每个covergroup可以定义单独的触发采样事件,允许从多个源头收集数据。covergroup必须被例化才可以用来收集数据。

每一个覆盖组(covergroup)都必须明确一下内容:

  • 一个时钟事件以用来同步对覆盖点的采样;
  • 一组覆盖点(coverage points),也就是需要测试的变量
  • 覆盖点之间的交叉覆盖;
  • 可选的形式参数;
  • 覆盖率选项;
covergroup cov_grp @(posedge clk);    //用时钟明确了覆盖点的采样时间,上升沿采样覆盖点,也可省略clk,在收集覆盖率时在根据情况注明
  cov_p1: coverpoint a;//定义覆盖点,cov_p1为覆盖点名,a为覆盖点中的变量名,也就是模块中的变量名
endgroup
 
cov_grp cov_inst = new();//实例化覆盖组

上述例子用时钟明确了覆盖点的采样时间,上升沿采样覆盖点,也可省略clk,在收集覆盖率时在根据情况注明,通过内建的sample()方法来触发覆盖点的采样,如下示例:

covergroup cov_grp;
  cov_p1: coverpoint a;//cov_p1为覆盖点名,a为覆盖点中的变量名,也就是模块中的变量名
endgroup
 
cov_grp cov_inst = new();
cov_inst.sample();          //sample函数收集覆盖率

使用事件触发与直接调用sample()相比,好处在于你能够借助已有的事件。

覆盖点——coverpoint

  • 隐式或自动bin:覆盖点变量,其取值范围内的每一个值都会有一个对应的bin,这种称为自动或隐式的bin。例如,对于一个位宽为nbit的覆盖点变量,若不指定bin个数,2^n个bin将会由系统自动创建,需要注意的是 自动创建bin的最大数目由auto_bin_max内置参数决定,默认值64
program automatic test(busifc.TB ifc);        //接口例化
   class Transaction;
      rand bit [3:0]  data;
      rand bit [2:0]  port;
   endclass

   covergroup Cov;           //定义覆盖组,未添加时钟信号,此时需要使用sample()函数采集覆盖率
      coverpoint  tr.port;     //设置覆盖点
   endgroup

   initial begin
      Transaction  tr=new();     //例化数据包
      Cov          ck=new();     //例化覆盖组
      repeat(32) begin
         tr.randomize();
         ifc.cb.port <= tr.port;
         ifc.cb.data <= tr.data;
         ck.sample();            //采集覆盖率
         @ifc.cb;
      end
   end
   
endprogram   

对于覆盖点tr.port,如果覆盖率达到100%,那么将会有auto[0],auto[1],auto[2] … auto[7]等8个bin被自动创建。其实际功能覆盖率报告如下:

在这里插入图片描述

  • 显式bins:"bins"关键字被用来显示定义一个变量的bin,用户自定义bin可以增加覆盖的准确度,它属于功能覆盖率的一个衡量单位。在每次采样结束时,生成的数据库中会包含采样后的所有bins,显示其收集到的具体覆盖率值。最终的覆盖率等于采样的bins值除以总的bins值。
covergroup 覆盖组名 @(posedge clk);//时钟可以没有
  覆盖点名1: coverpoint 变量名1{ bins bin名1 = {覆盖点取值范围}(iff(expression));  //iff结构可以指定采样条件
                                bins bin名2 = {覆盖点取值范围};
                                bins bin名3 = {覆盖点取值范围};
                              .......
                              }//一般会将bin的数目限制在8或16
                           。。。。。。
endgroup : 覆盖组名

//iff结构的运用实例如下:
bit[1:0]  s0;
covergroup  g4;
  cover1: coverpoint s0 iff(!reset) ;    //当reset=0时,表达式为真开始采样 
endgroup

注意对coverpoint的bin的声明使用的是{},这是因为bin是声明语句而非程序语句,而且{}后也没有加分号

针对某一变量,我们关心的可能只是某些区域的值或者跳转点,因此我们可以在显示定义的bins中指定一组数值(如3,5,6)或者跳转序列(如3->5->6)操作符(=>)

bit[2:0]     v;
covergroup  sg@(posedge clk);
   coverpoint  v{bins b2=(3 => 4 => 5);   //3 to 5
                 bins b3=(1,5 => 6=>7);   //(1=>6)、(1=>7)、(5=>6)、(5=>7)
                 bins b5=(5[*3]);         //3 consecutive 5's(连续重复,数值5的3次重复连续)
                 bins b6=(3[*3:5]);       //(3=>3=>3)、(3=>3=>3=>3)、(3=>3=>3=>3=>3)
                 bins b7=(4[->3]=>5);     //...=>4...=>4...=>4=>5(跟随重复,4出现3次,可以不连续,但在最后一个4出现后,下一个数值为5)
                 bins b8=(2[=3]=>5);      //...=>2...=>2...=>2...=>5(非连续重复,数值2出现3次)
                 bins anothers=default_sequence;
                 }
endgroup

wildcard覆盖率

使用关键字wildcard来创建多个状态或者翻转。

bit [2:0] port;
covergroup CoverPort;
	coverpoint port{
        wildcard bins even = {3'b??0};
        wildcard bins even = {3'b??1};   
    }

忽略的bin:ignore_bins

非法的bin:illegal_bins

显示定义bins时,可通过关键字default将未分配到的数值进行分配

covergroup  Cov;
   coverpoint  tr.data{             //data变量的取值范围为0~15,不设置显示bins时,理论上会有16个bin
               bins  zero = {0};            //取值:0
               bins  lo = {[1:3],5};        //取值:1,2,3,5
               bins  hi[] = {[8:$]};        //取值:8~15,使用动态数组方法时相当于创建了hi[0],hi[1],...,hi[7]一共8个bins
               bins  misc = default;        //余下的所有值:4,6,7
   }

在这里插入图片描述

交叉覆盖率——cross

​ 交叉覆盖是在覆盖点或变量之间指定的,必须先指定覆盖点,然后通过关键字cross定义覆盖点之间的交叉覆盖

//通过覆盖点来定义交叉覆盖
bit [3:0] a, b;
covergroup cg @(posedge clk);
  c1: coverpoint a;
  c2: coverpoint b;
  c1Xc2: cross c1,c2;    //1. 定义交叉覆盖使用关键字cross,利用**覆盖点名字**定义交叉覆盖
endgroup : cg
 
//通过变量名来定义交叉覆盖
bit [3:0] a, b;
covergroup cov @(posedge clk);
  aXb : cross a, b;      //2. 定义交叉覆盖使用关键字cross,直接利用**变量名字**定义交叉覆盖
endgroup
 
//交叉覆盖的通用定义格式: 
交叉覆盖名:cross 交叉覆盖点名1,交叉覆盖点名2;

由于上面每个覆盖点都有16个bin,所以它们的交叉覆盖总共有256(16*16)个交叉积(cross product),也就对应256个bin

bit [3:0] a, b, c;
covergroup cov @(posedge clk);
  BC  : coverpoint b+c;
  aXb : cross a, BC;
endgroup

上例的交叉覆盖总共有256个交叉积(cross product),也对应256个bin。

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

cross kind,port{
    ignore bins hi = binsof(port) intersect{7};
}
  • 1
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值