【【简单systyem verilog 语言学习使用三--- 新新adder加法器-覆盖率测试】】
顶层文件 adder.v
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文件
// 输入 常规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