第十一段:功能覆盖率/随机化 functional coverage功能 (持续更新)

这篇博客介绍了如何在SystemVerilog中实现功能覆盖率,通过创建covergroup和coverpoint来跟踪和分析设计的行为。作者在monitor中定义了一个covergroup,并设置了自动分组限制。在测试过程中,使用随机数生成transaction并进行采样,最后展示了覆盖率结果,并讨论了如何根据统计学原理确定足够的采样次数。
摘要由CSDN通过智能技术生成

 

最近项目中需要function覆盖率,所以就专门看了这部分知识,那么开始了!

       主要是声明一个covergroup,让这个covergroup随着事件sample_trans响应,sample_trans在monitor的main函数中触发。systemverilog默认是把coverpoint分成64组,我在第一句里面通过{option.auto_bin_max = 10;}把分组数改成10试试效果。       

       在transaction和generator那里改下随机化:

`ifndef TRANSACTION
`define TRANSACTION
class transaction;
  
  //declaring the transaction items
   rand bit [63:0] a;
   rand bit [63:0] b;
   rand bit [63:0] return_value;
   constraint set_to_0 {return_value == 64'h0000000000000000;}
  function void display(string name);
    $display("-------------------------");
    $display("- %s ",name);
    //$display("-------------------------");
    $display("- a = %0h, b = %0h",a,b);
    $display("- return_value = %0h",return_value);
    $display("-------------------------");
  endfunction
endclass

`endif

        首先是直接在monitor里改出functional coverage功能

`include "transaction.sv"
`include "scoreboard.sv"

class monitor;
  
  virtual intf vif;
      transaction trans;
      event sample_trans;

  
  mailbox mon2scb;
  scoreboard sb;

 covergroup cover_trans @(sample_trans);
	  a:coverpoint trans.a {option.auto_bin_max = 10;}
	  b:coverpoint trans.b;
	  return_value:coverpoint trans.return_value;
	  //{option.auto_bin_max = 10;}
  endgroup

  function new(virtual intf vif,mailbox mon2scb,scoreboard sb);
    this.vif = vif;
    this.mon2scb = mon2scb;
    this.sb = sb;
    this.cover_trans = new();
  endfunction
  
  task main;
    begin
      trans = new();//这里没有用FIFO来.get,所以要new;
      @(posedge vif.clk);
      trans.a   = vif.a;
      trans.b   = vif.b;
      @(posedge vif.clk);
      trans.return_value   = vif.return_value;
      @(posedge vif.clk);
      mon2scb.put(trans);
      trans.display("[ Monitor: transaction from interface to Monitor ]");
      @(posedge vif.clk);
      sb.check_output;
      ->sample_trans;
    end
  endtask

endclass

        接下来在env的主循环后加上显示采样结果的语句:

`include "transaction.sv"
`include "generator.sv"
`include "driver.sv"
`include "monitor.sv"
`include "input_monitor.sv"
`include "scoreboard.sv"
class environment;
  generator 	gen;
  scoreboard	scb;
  driver    	driv;
  monitor   	mon;
  input_monitor in_mon;
  
  mailbox gen2driv;
  mailbox mon2scb;
  mailbox in_mon2scb;
  mailbox driv2in_mon;
  
  virtual intf vif;
  
  function new(virtual intf vif);
    this.vif = vif;
    
    gen2driv = new();
    mon2scb  = new();
    in_mon2scb  = new();
    driv2in_mon  = new();
    
    gen  = new(gen2driv);
    scb  = new(mon2scb,in_mon2scb);
    driv = new(vif,gen2driv,driv2in_mon);
    mon  = new(vif,mon2scb,scb);
    in_mon  = new(vif,driv2in_mon,in_mon2scb,scb);
    //cover_trans = new;
  endfunction
  
  task pre_test();
    $display("pre_test:driv.reset:begin");
    driv.reset();//在driver中,控制interface来实现reset
    $display("pre_test:driv.reset:end");
    in_mon.main();
    #1000;
    mon.main();    
  endtask

 integer i;
  
  task test();
	  
      gen.read_input_output;
      for(i=1;i<=45;i++)
      begin
    $display("i:%d",i);
      gen.main(i);//生成一个trans,给a和b赋值,放入gen2driv_mailbox中
      driv.main();//从gen2driv_mailbox中取ab数放自己肚子里,再传给interface,等1000ns,然后从interface中取return_value出来用display显示
      //driver的main中有1000ns延时
      in_mon.main();
      mon.main();//从interface中取数出来,先放自己肚子里,然后把结果put进mon2scb_mailbox
      //加入sample
      end
      //$display("Coverage = %0.2f %%",mon.cover_trans.get_inst_coverage());
      $display("Coverage = %0.2f %%",mon.cover_trans.a.get_inst_coverage());
      $display("Coverage = %0.2f %%",mon.cover_trans.b.get_inst_coverage());
      $display("Coverage = %0.2f %%",mon.cover_trans.return_value.get_inst_coverage());
  endtask
  
  task post_test();
  endtask  
  
  //run task
  task run;
	  $display("pre_test");
    pre_test();
	  $display("test");
    test();
	  $display("post_test");
    post_test();
	  $display("finish");
    $finish;
  endtask
  
endclass

        在generator里也很简单地改一改。

`include "transaction.sv"

class generator;
  parameter NUMBER = 46;
  //declaring transaction class 
  transaction trans;
reg [63:0] a_input[0:NUMBER-1];
reg [63:0] b_input[0:NUMBER-1];
reg [63:0] z_output[0:NUMBER-1];

task read_input_output;
begin
	$readmemh("a_input.txt",a_input);
	$readmemh("b_input.txt",b_input);
	$readmemh("z_output.txt",z_output);
end
endtask
  
  mailbox gen2driv;
  
  event ended;
  
  function new(mailbox gen2driv);
    this.gen2driv = gen2driv;
  endfunction
  task main(integer i);
	  
   trans = new();
   /*
   trans.a = a_input[i];
   trans.b = b_input[i];
   trans.return_value = z_output[i];
   */
    trans.randomize();
   trans.display("[ Generator: transaction generated in Generator");
    gen2driv.put(trans);
    //-> ended; //triggering indicatesthe end of generation
  endtask
  
endclass

        结果:

                       

        这里有个情况,就是我这边没有专门写计算64位浮点运算的程序,所以随机化后没法比对计算结果,不过这个DUT也在FPGA上测试过了,肯定是没有问题的,就给自己省点事,把return_value设成0,直接不在scoreboard比较就好了。咱们主要是试下functional coverage。

        其实我们用久违的统计学思考一下,一个64长度的平均分布,要出现取样1000次某个区间都取不到值的P值,肯定是无比地小。

        反过来想,如何确定我们的随机次数该为多少比较合适呢?这个情况完全就是数理统计里中心极限那一章的很基础的计算题。我们设置一个P值比如为0.01%,反过来求要达到这个P值水平下,长度64的平均分布的采样次数就可以了。乌拉,中心极限定律无处不在!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃辣椒的年糕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值