【【简单systyem verilog 语言学习使用三--- 新新adder加法器-覆盖率测试】】

顶层文件 adder.v

c 复制代码
module  adder (
    input                    clk      ,
    input                    rst_n    ,
    input         [3 : 0]    in_0     ,
    input         [3 : 0]    in_1     ,
    input                    sel      ,   // 判断信号 
    output        [4 : 0]    out0     ,
    output        [4 : 0]    out1     ,
    output   reg  [4 : 0]    out2
  );

  always@(posedge clk or negedge rst_n )
  begin
    if(rst_n == 0)
    begin
      out2  <=  0    ;
    end
    else
    begin
      out2  <=  in_0 + in_1 ;
    end
  end


  assign  out1   = sel?  in_1 : 0  ;  
  assign  out0   = sel?  in_0 : 0  ; 

endmodule  

tb文件

c 复制代码
// 输入 常规class的定�? -- 仅仅为了好玩
class play;
  static int count = 0;
  int id;
  logic [2:0] ina;
  logic [5:0] func_a;
  int arr[6] = '{0, 1, 2, 3, 4, 5};

  // 构�?�函�?
  function new();
    this.id = count++;
  endfunction

  // 打印数组�?
  task showk();
    foreach (arr[i])
    begin
      int k = arr[i];
      $write("%d\n", k);
    end
  endtask

  // 功能函数
  function int shown_a(int a);
    func_a = a + a;
    $display("function shown_a number is %d", func_a);
    return func_a;
  endfunction
endclass

//------------------------------------------------
// Transaction 类定�?
class Transaction;
  rand bit [3:0] ina; // 输入信号a
  rand bit [3:0] inb; // 输入信号b
  rand bit sel;       // 选择信号

  function new();
    ina = 0;
    inb = 0;
    sel = 0;
  endfunction
endclass

// 定义覆盖�?
covergroup CovPort(ref Transaction tr, input logic [3:0] in_0, input logic [3:0] in_1);
  coverpoint tr.ina; // �?�? ina
  coverpoint tr.inb; // �?�? inb
  coverpoint tr.sel; // �?�? sel
  coverpoint in_0  ;
  coverpoint in_1  ;
endgroup

// 定义基类
virtual class driver_back;
          virtual task post_tx(ref Transaction tr, input logic [3:0] in_0, input logic [3:0] in_1);
                  endtask
                endclass

                // 扩展 driver_back,添加覆盖组逻辑
                class CoverageCallback extends driver_back;
                  CovPort cov;

                  // 构造函数,初始化覆盖组
                  function void init_cov(ref Transaction tr, input logic [3:0] in_0, input logic [3:0] in_1);
                    cov = new(tr,in_0,in_1);
                  endfunction

                  // 回调任务:触发采样
                  virtual task post_tx(ref Transaction tr, input logic [3:0] in_0, input logic [3:0] in_1);
                            cov.sample();  // 触发覆盖组采样
                            $display("Coverage sampled: ina=%0d, inb=%0d, sel=%0d", tr.ina, tr.inb, tr.sel);
                          endtask

                          // 打印单个点的覆盖率
                          function void report_coverage();
                            real coverage_in_0, coverage_in_1;

                            // 获取整个覆盖组的覆盖率
                            coverage_in_0 = cov.get_coverage();  // 获取整个CovPort的覆盖率
                            coverage_in_1 = cov.get_coverage();  // 可以重复同样的方式获取每个coverpoint的覆盖

                            // 打印覆盖率

                            $display("Coverage for in_0: %0.2f%%", coverage_in_0 );
                            $display("Coverage for in_1: %0.2f%%", coverage_in_1 );
                          endfunction
                        endclass
                        // 定义模块
                        module test();
                          // 端口定义
                          logic clk;
                          logic rst_n;
                          logic [3:0] in_0;
                          logic [3:0] in_1;
                          logic sel;         // 判断信号
                          logic [4:0] out0;
                          logic [4:0] out1;
                          logic [4:0] out2;
                          logic [5 : 0] result_b ;
                          logic [5 : 0] result_a ;
                          // 类定义
                          Transaction tr;
                          CoverageCallback cb;
                          play inst_a, inst_b;


                          // 时钟生成
                          initial
                          begin
                            clk = 0;
                            forever
                              #5 clk = ~clk;
                          end

                          // DUT(设备模块)
                          adder u_adder (
                                  .clk(clk),
                                  .rst_n(rst_n),
                                  .in_0(in_0),
                                  .in_1(in_1),
                                  .sel(sel),
                                  .out0(out0),
                                  .out1(out1),
                                  .out2(out2)
                                );

                          // 驱动 Transaction 信号到 DUT
                          always @(posedge clk or negedge rst_n)
                          begin
                            if (!rst_n)
                            begin
                              in_0 <= 0;
                              in_1 <= 0;
                              sel  <= 0;
                            end
                            else
                            begin
                              in_0 <= tr.ina;
                              in_1 <= tr.inb;
                              sel  <= tr.sel;
                            end
                          end

                          // 测试逻辑
                          initial
                          begin
                            rst_n = 0;
                            inst_a = new();
                            inst_b = new();
                            $display("inst_a id = %d", inst_a.id);
                            $display("inst_b id = %d", inst_b.id);

                            // 调用 showk 打印数组
                            inst_a.showk();
                            inst_b.showk();

                            // 调用 shown_a 进行测试
                            result_a = inst_a.shown_a(5); // 示例输入值为 5
                            $display("inst_a.shown_a(5) result = %d", result_a);

                            result_b = inst_b.shown_a(10); // 示例输入值为 10
                            $display("inst_b.shown_a(10) result = %d", result_b);

                            #20 rst_n = 1;

                            // 实例化 Transaction 和 CoverageCallback
                            tr = new();
                            cb = new();
                            cb.init_cov(tr,in_0,in_1);

                            // 随机化并进行覆盖率采样
                            repeat (10)
                            begin
                              assert(tr.randomize());
                              cb.post_tx(tr,in_0,in_1);  // 触发采样
                              #20;  // 增加延迟以等待 DUT 输出稳定
                              $display("DUT Outputs: out0=%0d, out1=%0d, out2=%0d", out0, out1, out2);
                            end

                            // 打印覆盖率报告
                            cb.report_coverage();

                          end
                        endmodule
相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
ZPC82106 天前
docker 镜像备份
人工智能·算法·fpga开发·机器人
ZPC82106 天前
docker 使用GUI ROS2
人工智能·算法·fpga开发·机器人
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms7 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下7 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。7 天前
2026.2.25监控学习
学习