zoukankan      html  css  js  c++  java
  • UVM Primer

    tinyalu_pkg.sv

    在搭建基于对象的验证平台的时候,我们把所有的类定义和共享资源都放在SystemVerilog 包里。用了package就可以在多个module中共享类和变量定义了。当你引入package时,你可以访问package中所有的定义和声明的数据

    package tinyalu_pkg;
          typedef enum bit[2:0] {no_op  = 3'b000,
                                 add_op = 3'b001, 
                                 and_op = 3'b010,
                                 xor_op = 3'b011,
                                 mul_op = 3'b100,
                                 rst_op = 3'b111} operation_t;
    
    
    `include "coverage.svh"
    `include "tester.svh"
    `include "scoreboard.svh"
    `include "testbench.svh"
    endpackage : tinyalu_pkg

    tinyalu_bfm.sv

    interface tinyalu_bfm;
       import tinyalu_pkg::*;
    
       byte         unsigned        A;
       byte         unsigned        B;
       bit          clk;
       bit          reset_n;
       wire [2:0]   op;
       bit          start;
       wire         done;
       wire [15:0]  result;
       operation_t  op_set;
    
       assign op = op_set;
    
       initial begin
          clk = 0;
          forever begin
             #10;
             clk = ~clk;
          end
       end
    
    
       task reset_alu();
          reset_n = 1'b0;
          @(negedge clk);
          @(negedge clk);
          reset_n = 1'b1;
          start = 1'b0;
       endtask : reset_alu
       
      task send_op(input byte iA, input byte iB, input operation_t iop, output shortint alu_result);
         
          if (iop == rst_op) begin
             @(posedge clk);
             reset_n = 1'b0;
             start = 1'b0;
             @(posedge clk);
             #1;
             reset_n = 1'b1;
          end else begin
             @(negedge clk);
             op_set = iop;
             A = iA;
             B = iB;
             start = 1'b1;
             if (iop == no_op) begin
                @(posedge clk);
                #1;
                start = 1'b0;           
             end else begin
                do
                  @(negedge clk);
                while (done == 0);
                start = 1'b0;
             end
             alu_result = result;
          end // else: !if(iop == rst_op)
          
       endtask : send_op
    
    endinterface : tinyalu_bfm

    tester类

    tb_classes/tester.svh

    class tester;   //注意此处用的是类的定义,原来是module
    
       virtual tinyalu_bfm bfm;   //定义了操作BFM的变量,这个变量在构造函数里赋值
    
       function new (virtual tinyalu_bfm b);
           bfm = b;
       endfunction : new
    
    
       protected function operation_t get_op();
          bit [2:0] op_choice;
          op_choice = $random;
          case (op_choice)
            3'b000 : return no_op;
            3'b001 : return add_op;
            3'b010 : return and_op;
            3'b011 : return xor_op;
            3'b100 : return mul_op;
            3'b101 : return no_op;
            3'b110 : return rst_op;
            3'b111 : return rst_op;
          endcase // case (op_choice)
       endfunction : get_op
    
       protected function byte get_data();
          bit [1:0] zero_ones;
          zero_ones = $random;
          if (zero_ones == 2'b00)
            return 8'h00;
          else if (zero_ones == 2'b11)
            return 8'hFF;
          else
            return $random;
       endfunction : get_data
       
       task execute();   //注意此处是execute方法,原来是initial块
          byte         unsigned        iA;
          byte         unsigned        iB;
          shortint     unsigned        result;
          operation_t                  op_set;
          bfm.reset_alu();
          op_set = rst_op;
          iA = get_data();
          iB = get_data();
          bfm.send_op(iA, iB, op_set, result);
          op_set = mul_op;
          bfm.send_op(iA, iB, op_set, result);
          bfm.send_op(iA, iB, op_set, result);
          op_set = rst_op;
          bfm.send_op(iA, iB, op_set, result);
          repeat (10) begin : random_loop
             op_set = get_op();
             iA = get_data();
             iB = get_data();
             bfm.send_op(iA, iB, op_set, result );
             $display("%2h %6s %2h = %4h",iA, op_set.name(), iB, result);
          end : random_loop
          $stop;
       endtask : execute
       
    endclass : tester

    tb_classes/scoreboard.svh

    class scoreboard;
          virtual tinyalu_bfm bfm;
    
       function new (virtual tinyalu_bfm b);
         bfm = b;
       endfunction : new
    
       task execute();
          shortint predicted_result;
          forever begin : self_checker    //注意此处用forever, wait语句代替原来的always
             @(posedge bfm.done) 
               case (bfm.op_set)
                 add_op: predicted_result = bfm.A + bfm.B;
                 and_op: predicted_result = bfm.A & bfm.B;
                 xor_op: predicted_result = bfm.A ^ bfm.B;
                 mul_op: predicted_result = bfm.A * bfm.B;
               endcase // case (op_set)
             
             if ((bfm.op_set != no_op) && (bfm.op_set != rst_op))
               if (predicted_result != bfm.result)
                 $error ("FAILED: A: %0h  B: %0h  op: %s result: %0h",
                         bfm.A, bfm.B, bfm.op_set.name(), bfm.result);
             
          end : self_checker
       endtask : execute
       
       
    endclass : scoreboard

    tb_classes/coverage.svh

    class coverage;
    
       virtual tinyalu_bfm bfm;
       
       
       byte         unsigned        A;
       byte         unsigned        B;
       operation_t  op_set;
    
       covergroup op_cov;
    
          coverpoint op_set {
             bins single_cycle[] = {[add_op : xor_op], rst_op,no_op};
             bins multi_cycle = {mul_op};
    
             bins opn_rst[] = ([add_op:no_op] => rst_op);
             bins rst_opn[] = (rst_op => [add_op:no_op]);
    
             bins sngl_mul[] = ([add_op:xor_op],no_op => mul_op);
             bins mul_sngl[] = (mul_op => [add_op:xor_op], no_op);
    
             bins twoops[] = ([add_op:no_op] [* 2]);
             bins manymult = (mul_op [* 3:5]);
    
    
          }
    
       endgroup
    
       covergroup zeros_or_ones_on_ops;
    
          all_ops : coverpoint op_set {
             ignore_bins null_ops = {rst_op, no_op};}
    
          a_leg: coverpoint A {
             bins zeros = {'h00};
             bins others= {['h01:'hFE]};
             bins ones  = {'hFF};
          }
    
          b_leg: coverpoint B {
             bins zeros = {'h00};
             bins others= {['h01:'hFE]};
             bins ones  = {'hFF};
          }
    
          op_00_FF:  cross a_leg, b_leg, all_ops {
             bins add_00 = binsof (all_ops) intersect {add_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins add_FF = binsof (all_ops) intersect {add_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins and_00 = binsof (all_ops) intersect {and_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins and_FF = binsof (all_ops) intersect {and_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins xor_00 = binsof (all_ops) intersect {xor_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins xor_FF = binsof (all_ops) intersect {xor_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins mul_00 = binsof (all_ops) intersect {mul_op} &&
                           (binsof (a_leg.zeros) || binsof (b_leg.zeros));
    
             bins mul_FF = binsof (all_ops) intersect {mul_op} &&
                           (binsof (a_leg.ones) || binsof (b_leg.ones));
    
             bins mul_max = binsof (all_ops) intersect {mul_op} &&
                            (binsof (a_leg.ones) && binsof (b_leg.ones));
    
             ignore_bins others_only =
                                      binsof(a_leg.others) && binsof(b_leg.others);
    
          }
    
    endgroup
       
       function new (virtual tinyalu_bfm b);
         op_cov = new();
         zeros_or_ones_on_ops = new();
         bfm = b;
       endfunction : new
    
       
    
       task execute();
          forever begin  : sampling_block
             @(negedge bfm.clk);
             A = bfm.A;
             B = bfm.B;
             op_set = bfm.op_set;
             op_cov.sample();
             zeros_or_ones_on_ops.sample();
          end : sampling_block
       endtask : execute
          
    endclass : coverage

    tb_classes/testbench.svhclass testbench;

       virtual tinyalu_bfm bfm;
    //在OOP 里这个相当于module里的端口列表
    //回顾基于module的代码,我们知道SystemVerilog接口是在验证平台的module间传递信号的独立的编译单元。tester,scoreboard和coverage module通过模块的端口列表得到BFM的拷贝
    //对象可以通过SystemVerilog接口的句柄来用同样的方式访问信号。virtual声明指示编译器这个变量会得到一个接口的句柄。virtual关键字指示了编译时接口句柄是不在bfm变量里
    //的,后面有人要仿真这些信号的时候会把句柄放进变量里
    tester tester_h; //我们声明了三个变量tester_h,coverage_h和scoreboard_h来存放三个验证平台对象 coverage coverage_h; scoreboard scoreboard_h;
    //有很多方式可以把接口的句柄存入bfm变量里。这个例子里,我们用new()方法来做。 function new (virtual tinyalu_bfm b); bfm = b; endfunction : new task execute(); //execute()方法例化了三个验证平台对象,每个都传入了bfm拷贝 tester_h = new(bfm); coverage_h = new(bfm); scoreboard_h = new(bfm); fork tester_h.execute(); coverage_h.execute(); scoreboard_h.execute(); join_none endtask : execute endclass : testbench

    top.sv

    module top;
      import   tinyalu_pkg::*;   //我们的package叫tinyalu_pkg。里面定义了所有的类,我们通过在module中引入package来访问所有的定义
    `include "tinyalu_macros.svh"
       
       tinyalu DUT (.A(bfm.A), .B(bfm.B), .op(bfm.op), 
                    .clk(bfm.clk), .reset_n(bfm.reset_n), 
                    .start(bfm.start), .done(bfm.done), .result(bfm.result));
    
       tinyalu_bfm     bfm();  //例化接口
    
       testbench    testbench_h;
       //上面的代码跟基于module的代码有相似之处,除了我们把激励,自检,功能覆盖模块换成了testbench类。我们现在有存放testbench对象的testbench_h变量了
    
       initial begin
          testbench_h = new(bfm);
          testbench_h.execute();
       end
       
    endmodule : top
  • 相关阅读:
    Java8 Stream
    一个轻量级的基于RateLimiter的分布式限流实现
    常用限流算法与Guava RateLimiter源码解析
    Java学习之socket网络编程篇
    Java学习之文件io流篇
    Java学习之异常篇
    Java学习之多线程篇
    Java学习之集合篇
    Java学习之常用类篇
    Java学习之final与匿名内部类篇
  • 原文地址:https://www.cnblogs.com/yiyedada/p/12368898.html
Copyright © 2011-2022 走看看