BASE Testbench长这样:
/
// This is a wrapper tb for a dff design
// VERSION: v0.1
// Wrapper TB
// Below are the trial wrapper testbench, able to dump waveforms
/
`define CHECKER(CHKNAME, PROPERTY, ERROR_CODEBLOCK, ERROR_MSG, PASS_CODEBLOCK, PASS_INFO) \
if (!(PROPERTY)) begin \
$error("`CHKNAME`", ": ", ERROR_MSG); \
ERROR_CODEBLOCK \
end \
else begin \
PASS_CODEBLOCK \
$display("`CHKNAME`", ": ", PASS_INFO); \
end \
CHKNAME: assert(PROPERTY);
module test;
parameter PERIOD = 2;
parameter width = 8;
parameter reset_value = 0;
reg [width-1 : 0] data_in;
reg clk;
reg rst_n;
reg enable;
wire [width-1 : 0] data_out;
// test variables
reg [width-1 : 0] expected_result;
// Instance of DW03_reg_s_pl
DW03_reg_s_pl #(width, reset_value)
U0 (.d(data_in), .clk(clk), .reset_N(rst_n),
.enable(enable), .q(data_out));
always #(PERIOD/2) clk=~clk;
initial begin
// Dump waves
$fsdbDumpfile("testname.fsdb");
$fsdbDumpvars("+all");
end
initial begin
#100 $finish;
end
initial begin
$display($time, " <<<<<< Starting the Simulation >>>>>>");
data_in = 0;
rst_n = 1'b1;
clk = 1;
rst_n = 1'b0;
enable = 0;
expected_result = 0;
#PERIOD;
rst_n = 1;
enable = 0;
// RST_VAL_DEFAULT
expected_result = reset_value;
$display("Executing RST_VAL_DEFAULT check");
`CHECKER( RST_VAL_DEFAULT,
expected_result == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// WR_ENABLE
reset_stimulus();
$display("Executing WR_ENABLE check");
#PERIOD;
data_in = 'h10;
enable = 1;
expected_result = data_in;
#PERIOD;
`CHECKER( WR_ENABLE_0,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
reset_stimulus();
data_in = 'h11;
enable = 1;
expected_result = data_in;
#PERIOD;
`CHECKER( WR_ENABLE_1,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// WR_DISABLE
reset_stimulus();
$display("Executing WR_DISABLE check");
#PERIOD enable = 0;
#PERIOD data_in = 'h11; // hold data_in half a clock wait for sample enable at rising edge of clk
#PERIOD data_in = 'h15;
expected_result = 'h11;
#PERIOD;
`CHECKER( WR_DISABLE,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// CONST_D_CONST_Q
reset_stimulus();
$display("Executing CONST_D_CONST_Q check");
#PERIOD enable = 0;
#PERIOD data_in = 'h0f;
#PERIOD;
`CHECKER( CONST_D_CONST_Q_0,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
#PERIOD enable = 1;
#PERIOD data_in = 'h0f;
expected_result = data_in;
#PERIOD;
`CHECKER( CONST_D_CONST_Q_1,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// BURST_TO_WRITE
reset_stimulus();
$display("Executing BURST_TO_WRITE check");
#PERIOD enable = 1;
#PERIOD data_in = 'ha;
#PERIOD data_in = 'hb;
#PERIOD data_in = 'hc;
#PERIOD data_in = 'hd;
#PERIOD data_in = 'he;
expected_result = data_in;
#PERIOD;
`CHECKER( BURST_TO_WRITE,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// RST_SYNC
reset_stimulus();
$display("Executing RST_SYNC check");
#PERIOD enable = 1;
#PERIOD data_in = 'ha;
#(PERIOD/2) rst_n = 'h0;
#(PERIOD/2) rst_n = 'h1;
expected_result = data_in;
#PERIOD;
`CHECKER( RST_SYNC,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
// ENABLE_POS_SENC
reset_stimulus();
$display("Executing ENABLE_POS_SENC check");
#PERIOD enable = 1;
#PERIOD data_in = 'ha;
#(PERIOD/2) enable = 'h0; data_in = 'hf;
#(PERIOD/2) enable = 'h1;
expected_result = 'ha;
`CHECKER( ENABLE_POS_SENC,
data_out == expected_result,
,
("error"),
,
("checked ok")
)
$display("expected_result = %0h, data_out = %0h", expected_result, data_out);
end
task display;
$display("Enable:%0h, Input:%0h, Output:%0h, width = %0h",
enable, data_in, data_out, width);
endtask
task reset_stimulus();
#PERIOD enable = 0;
#PERIOD data_in = 'h0;
$display("Reset the stimulus: enable = %0h, data_in = %0h", enable, data_in);
endtask
endmodule
批量生成tb的PY脚本
import os
import numpy as np
numbers = 32
for number in range(numbers):
count = 1
count_tb = 1
count_rst_val = 1
rst_val = 1
if number > 1:
#print(number)
rst_val = np.random.randint(1, 2**number-1)
#print(rst_val)
file_name = 'tb_width_' + str(number) + '.sv'
with open(file_name, mode='w') as f2:
with open('testbench.sv') as f:
while True:
string = f.readline()
if len(string) == 0:
break
if count_tb == 22:
string = string[:-2] + f'{number};\n'
print(string)
if count == 25:
string = string[:-3] + f'{number};\n'
if count_rst_val == 26:
print("wut")
string = string[:-3] + f'{rst_val};\n'
print(string)
f2.write(string)
count += 1
count_tb += 1
count_rst_val += 1
f2.close()
f.close()
在shell批量跑仿真和编译
#!/bin/sh
# set the variable width
WIDTH="10"
for ((WIDTH=0; WIDTH<=31;WIDTH++))
do
echo "WIDTH is: $WIDTH"
vcs ../tb/tb_width_$WIDTH.sv ../design/dff.v -kdb -debug_access+all -debug_region+cell+encrypt \
+v2k -sverilog -kdb \
-l vcs.log \
-timescale=1ns/1ps \
-o simv \
+vcs+vcdpluson \
-cm line+cond+tgl+branch+assert \
-cm_name test_$WIDTH 这一步是为了在simv.vdb地下生成单独的test data
simv -l ./results/tb_width_$WIDTH.log
done
回到shell merge URG:
urg -full64 -metric line+tgl+cond+fsm+assert+branch -warn none -dbname merged_cov.vdb -dir simv.vdb/