【【Systemverilog学习参考 简单的加法器验证-含覆盖率】】
adder.v
c
module adder (
input clk ,
input rst_n ,
input [3 : 0] in_0 ,
input [3 : 0] in_1 ,
input sel , // 判断信号
output [3 : 0] out0 ,
output [3 : 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
adder_tb.sv
c
// 这代码包含的部分是关于覆盖率的测试
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];
$display("%d", k);
end
endtask
// 功能函数
function int shown_a( int a) ;
func_a = 6'(a + a) ;
$display("function shown_a number is %d",func_a) ;
return func_a ;
endfunction
endclass
// transaction 类
class transaction ;
rand bit [3 : 0] ina ;
rand bit [3 : 0] inb ;
rand bit sel ;
constraint vaild_range{
ina inside {[0:15]} ;
inb inside {[0:15]} ;
};
function new() ;
ina = 0 ;
inb = 0 ;
sel = 0 ;
endfunction
endclass
//定义覆盖率
covergroup covport(ref transaction tr);
cp_ina: coverpoint tr.ina {
bins ina_values[] = {[0:15]}; // 明确覆盖所有值
option.goal = 100;
}
cp_inb: coverpoint tr.inb {
bins inb_values[] = {[0:15]}; // 明确覆盖所有值
option.goal = 100;
}
cp_sel: coverpoint tr.sel;
endgroup
// 定义一个虚的基类 用以适配回调函数
virtual class driver_back ;
virtual task post_tx(ref transaction tr ) ;
endtask
endclass
// 这里先默认什么都不写 到下面做出适配
class coveragecallback extends driver_back ;
covport cov ;
// 初始化覆盖组
function void init_cov(ref transaction tr) ;
cov = new(tr) ;
endfunction
// 回调函数的编辑
virtual task post_tx(ref transaction tr ) ;
cov.sample() ;
$display("coverage sampled : ina=%d ,inb=%d ,sel=%d",tr.ina,tr.inb,tr.sel) ;
endtask
function void report_coverage() ;
real coverage_ina , coverage_inb , coverage_total ;
// 获取覆盖组覆盖率
coverage_ina = cov.cp_ina.get_coverage();
coverage_inb = cov.cp_inb.get_coverage();
coverage_total = cov.get_coverage(); // 整体覆盖率
$display("Coverage for ina: %0.2f%%", coverage_ina);
$display("Coverage for inb: %0.2f%%", coverage_inb);
$display("Total Coverage: %0.2f%%", coverage_total);
endfunction
endclass
module test ;
logic clk ;
logic rst_n ;
logic [3 : 0] in_0 ;
logic [3 : 0] in_1 ;
logic sel ;
logic [3 : 0] out0 ;
logic [3 : 0] out1 ;
logic [4 : 0] out2 ;
logic [5 : 0] result_a ;
logic [5 : 0] result_b ;
transaction tr ;
coveragecallback cb ;
play inst_a , inst_b ;
// 生成时钟
initial begin
clk = 0 ;
forever
#5 clk = ~clk ;
end
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 )
);
// 开始执行操作
// 先将class内部的操作完成
initial begin
$fsdbDumpfile("novas.fsdb"); // 指定波形文件名
$fsdbDumpvars(0, test); // 指定波形文件的层次结构和信号范围
end
initial begin
rst_n = 0 ;
in_0 = 0 ;
in_1 = 0 ;
sel = 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);
#100 ;
rst_n = 1;
@(posedge clk) ;
tr = new() ;
cb = new() ;
cb.init_cov(tr) ;
// 随机化
repeat(10)
begin
assert(tr.randomize()) ;
in_0 = tr.ina ;
in_1 = tr.inb ;
sel = tr.sel ;
cb.post_tx(tr) ;
#20 ;
$display("DUT Outputs: out0=%0d, out1=%0d, out2=%0d", out0, out1, out2);
end
// 打印覆盖率报告
cb.report_coverage();
$finish ;
end
endmodule
指令 : vcs divide.sv divide_test.sv -timescale=1ns/1ps -full64 -R +vc +v2k -sverilog -debug_access+ -kdb -fsdb -cm line+cond+fsm+tgl -l sim.log
指令2 : verdi verdi -ssf novas.fsdb -dbdir simv.daidir