【【Systemverilog学习参考 简单的加法器验证-含覆盖率】】
adder.v
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 )beginif(rst_n == 0)beginout2 <= 0 ;endelsebeginout2 <= in_0 + in_1 ;endendassign out1 = sel? in_1 : 0 ; assign out0 = sel? in_0 : 0 ; endmodule
adder_tb.sv
// 这代码包含的部分是关于覆盖率的测试
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])beginint 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
endclassmodule 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); // 指定波形文件的层次结构和信号范围
endinitial 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