@@ -0,0 +1,56 @@ | |||
module counter_assertion(clk, rst, data, updown, load, count); | |||
input logic clk, rst; | |||
input logic updown, load; | |||
input logic [3:0] data, count; | |||
property reset_prpty; | |||
@(posedge clk) rst |=> (count == 4'b0); | |||
endproperty | |||
sequence up_seq; | |||
!load && updown; | |||
endsequence | |||
sequence down_seq; | |||
!load && !updown; | |||
endsequence | |||
property up_count_prpty; | |||
@(posedge clk) disable iff(rst) | |||
up_seq |=> (count == ($past(count, 1) + 1'b1)); | |||
endproperty | |||
property down_count_prpty; | |||
@(posedge clk) disable iff(rst) | |||
down_seq |=> (count == ($past(count, 1) - 1'b1)); | |||
endproperty | |||
property count_Fto0_prpty; | |||
@(posedge clk) disable iff(rst) | |||
(!load && updown) && (count == 4'hF) |=> (count == 4'b0); | |||
endproperty | |||
property count_0toF_prpty; | |||
@(posedge clk) disable iff(rst) | |||
(!load && !updown) && (count == 4'b0) |=> (count == 4'hF); | |||
endproperty | |||
property load_prpty; | |||
@(posedge clk) disable iff(rst) | |||
load |=> (count == $past(data, 1)); | |||
endproperty | |||
RST: assert property (reset_prpty); | |||
UP_COUNT: assert property (up_count_prpty); | |||
DOWN_COUNT: assert property (down_count_prpty); | |||
F2O: assert property (count_Fto0_prpty); | |||
O2F: assert property (count_0toF_prpty); | |||
LOAD: assert property (load_prpty); | |||
endmodule | |||
@@ -0,0 +1,69 @@ | |||
class counter_env; | |||
virtual counter_if.WR_BFM wr_if; | |||
virtual counter_if.WR_MON wrmon_if; | |||
virtual counter_if.RD_MON rdmon_if; | |||
mailbox #(counter_trans) gen2wr = new; | |||
mailbox #(counter_trans) wrmon2rm = new; | |||
mailbox #(counter_trans) rm2sb = new; | |||
mailbox #(counter_trans) rdmon2sb = new; | |||
counter_gen gen_h; | |||
counter_wr_bfm wr_h; | |||
counter_wr_mon wrmon_h; | |||
counter_rd_mon rdmon_h; | |||
counter_rm rm_h; | |||
counter_sb sb_h; | |||
function new( virtual counter_if.WR_BFM wr_if, | |||
virtual counter_if.WR_MON wrmon_if, | |||
virtual counter_if.RD_MON rdmon_if); | |||
this.wr_if = wr_if; | |||
this.wrmon_if = wrmon_if; | |||
this.rdmon_if = rdmon_if; | |||
endfunction | |||
task build(); | |||
gen_h = new(gen2wr); | |||
wr_h = new(wr_if, gen2wr); | |||
wrmon_h = new(wrmon_if, wrmon2rm); | |||
rdmon_h = new(rdmon_if, rdmon2sb); | |||
rm_h = new(wrmon2rm, rm2sb); | |||
sb_h = new(rm2sb, rdmon2sb); | |||
endtask | |||
task reset(); | |||
@(wr_if.wr_cb); | |||
wr_if.wr_cb.rst <= 1; | |||
@(wr_if.wr_cb); | |||
@(wr_if.wr_cb); | |||
@(wr_if.wr_cb); | |||
@(wr_if.wr_cb); | |||
@(wr_if.wr_cb); | |||
wr_if.wr_cb.rst <= 0; | |||
endtask | |||
task start(); | |||
gen_h.start(); | |||
wr_h.start(); | |||
wrmon_h.start(); | |||
rdmon_h.start(); | |||
rm_h.start(); | |||
sb_h.start(); | |||
endtask | |||
task stop(); | |||
wait(sb_h.DONE.triggered); | |||
endtask | |||
task run(); | |||
reset(); | |||
start(); | |||
stop(); | |||
sb_h.report(); | |||
endtask | |||
endclass: counter_env |
@@ -0,0 +1,33 @@ | |||
class counter_gen; | |||
counter_trans trans_h; | |||
counter_trans trans2wr_h; | |||
mailbox #(counter_trans) gen2wr; | |||
function new(mailbox #(counter_trans) gen2wr); | |||
this.gen2wr = gen2wr; | |||
trans_h = new; | |||
endfunction | |||
virtual task start(); | |||
fork | |||
begin | |||
trans_h.trans_id++; | |||
trans_h.load = 1; | |||
trans_h.data = 0; | |||
trans2wr_h = new trans_h; | |||
gen2wr.put(trans2wr_h); | |||
for(int i = 0; i < (no_of_transaction - 1); i++) | |||
begin | |||
trans_h.trans_id++; | |||
assert(trans_h.randomize()); | |||
trans2wr_h = new trans_h; | |||
gen2wr.put(trans2wr_h); | |||
end | |||
end | |||
join_none | |||
endtask | |||
endclass: counter_gen |
@@ -0,0 +1,25 @@ | |||
interface counter_if(input logic clk); | |||
logic rst, updown, load; | |||
logic [3:0] data; | |||
logic [3:0] data_out; | |||
clocking wr_cb@(posedge clk); | |||
output load, updown, rst; | |||
output data; | |||
endclocking | |||
clocking wrmon_cb@(posedge clk); | |||
input data; | |||
input load, rst, updown; | |||
endclocking | |||
clocking rdmon_cb@(posedge clk); | |||
input data_out; | |||
endclocking | |||
modport WR_BFM(clocking wr_cb); | |||
modport WR_MON(clocking wrmon_cb); | |||
modport RD_MON(clocking rdmon_cb); | |||
endinterface: counter_if |
@@ -0,0 +1,14 @@ | |||
package counter_pkg; | |||
int no_of_transaction; | |||
`include "counter_trans.sv" | |||
`include "counter_gen.sv" | |||
`include "counter_wr_bfm.sv" | |||
`include "counter_wr_mon.sv" | |||
`include "counter_rd_mon.sv" | |||
`include "counter_rm.sv" | |||
`include "counter_sb.sv" | |||
`include "counter_env.sv" | |||
endpackage |
@@ -0,0 +1,37 @@ | |||
class counter_rd_mon; | |||
virtual counter_if.RD_MON rdmon_if; | |||
mailbox #(counter_trans) rdmon2sb; | |||
counter_trans trans_h; | |||
counter_trans rd2sb_h; | |||
function new( virtual counter_if.RD_MON rdmon_if, | |||
mailbox #(counter_trans) rdmon2sb); | |||
this.rdmon_if = rdmon_if; | |||
this.rdmon2sb = rdmon2sb; | |||
trans_h = new; | |||
endfunction | |||
task monitor(); | |||
@(rdmon_if.rdmon_cb) | |||
trans_h.data_out = rdmon_if.rdmon_cb.data_out; | |||
if($isunknown(rdmon_if.rdmon_cb.data_out)) | |||
trans_h.data_out = 0; | |||
endtask | |||
task start(); | |||
fork | |||
forever | |||
begin | |||
monitor(); | |||
trans_h.display("DATA FROM READ MONITOR"); | |||
rd2sb_h = new trans_h; | |||
rdmon2sb.put(rd2sb_h); | |||
end | |||
join_none | |||
endtask | |||
endclass: counter_rd_mon | |||
@@ -0,0 +1,47 @@ | |||
class counter_rm; | |||
mailbox #(counter_trans) rm2sb, wrmon2rm; | |||
counter_trans wrmon2rm_h, temp_h; | |||
int count; | |||
function new(mailbox #(counter_trans) wrmon2rm, mailbox #(counter_trans) rm2sb); | |||
this.rm2sb = rm2sb; | |||
this.wrmon2rm = wrmon2rm; | |||
temp_h = new(); | |||
endfunction | |||
task model(); | |||
++count; | |||
if(count > 1) | |||
begin | |||
temp_h.rst = wrmon2rm_h.rst; | |||
temp_h.load = wrmon2rm_h.load; | |||
temp_h.updown = wrmon2rm_h.updown; | |||
temp_h.data = wrmon2rm_h.data; | |||
if(wrmon2rm_h.rst) | |||
temp_h.data_out = 0; | |||
else if(wrmon2rm_h.load) | |||
temp_h.data_out = wrmon2rm_h.data; | |||
else if(wrmon2rm_h.updown) | |||
temp_h.data_out = ++temp_h.data_out; | |||
else if(!wrmon2rm_h.updown) | |||
temp_h.data_out = --temp_h.data_out; | |||
end | |||
endtask | |||
task start(); | |||
fork | |||
forever | |||
begin | |||
wrmon2rm.get(wrmon2rm_h); | |||
rm2sb.put(temp_h); | |||
temp_h = new temp_h; | |||
model(); | |||
end | |||
join_none | |||
endtask | |||
endclass :counter_rm | |||
@@ -0,0 +1,69 @@ | |||
class counter_sb; | |||
mailbox #(counter_trans) rm2sb, rdmon2sb; | |||
event DONE; | |||
int count_transaction, data_verified; | |||
counter_trans cov_h, rcvd_h; | |||
covergroup counter_cov; | |||
option.per_instance = 1; | |||
RST: coverpoint cov_h.rst {bins r[] = {0,1};} | |||
LD: coverpoint cov_h.load {bins l[] = {0,1};} | |||
UD: coverpoint cov_h.updown {bins ud[] = {0,1};} | |||
DATA: coverpoint cov_h.data {bins d[] = {[0:15]};} | |||
DOUT: coverpoint cov_h.data_out {bins dout[] = {[0:15]};} | |||
LDxDATA: cross LD, DATA; | |||
UDxDOUT: cross UD, DOUT; | |||
RSTxLDxDATA: cross RST, LD, DATA; | |||
RSTxLDxUD: cross RST, LD, UD; | |||
endgroup | |||
function new(mailbox #(counter_trans) rm2sb, mailbox #(counter_trans) rdmon2sb); | |||
this.rm2sb = rm2sb; | |||
this.rdmon2sb = rdmon2sb; | |||
counter_cov = new(); | |||
endfunction | |||
task start; | |||
fork | |||
forever | |||
begin | |||
rm2sb.get(rcvd_h); | |||
cov_h = rcvd_h; | |||
counter_cov.sample(); | |||
//--------------------// | |||
rdmon2sb.get(cov_h); | |||
check(rcvd_h); | |||
end | |||
join_none | |||
endtask | |||
task check(counter_trans rcvd_h); | |||
count_transaction++; | |||
if(cov_h.compare(rcvd_h)) | |||
begin | |||
counter_cov.sample(); | |||
data_verified++; | |||
end | |||
if(count_transaction >= no_of_transaction) | |||
->DONE; | |||
endtask | |||
function void report; | |||
$display("--------------SCOREBOARD REPORT----------------"); | |||
$display("Number of transactions received : %0d", count_transaction); | |||
$display("Number of transactions verified : %0d", data_verified); | |||
$display("-----------------------------------------------"); | |||
endfunction | |||
endclass :counter_sb |
@@ -0,0 +1,41 @@ | |||
class counter_trans; | |||
rand bit [3:0] data; | |||
rand bit rst; | |||
rand bit load; | |||
rand bit updown; | |||
bit [3:0] data_out; | |||
static int trans_id; | |||
//Constraints to control frequency of reset and load | |||
constraint r1{rst dist {0:=50, 1:=1};} | |||
constraint l1{load dist {0:=20, 1:=1};} | |||
function void post_randomize(); | |||
this.display("RANDOMIZED DATA"); | |||
endfunction | |||
function void display(string message); | |||
$display("-------------------------------------------------"); | |||
$display("%s",message); | |||
$display("\tTransaction ID: %d", trans_id); | |||
$display("\tRESET = %d\n\tLOAD = %d\n\tUP-DOWN = %d\n\tDATA = %d", rst, load, updown, data); | |||
$display("-------------------------------------------------"); | |||
endfunction | |||
function bit compare(counter_trans rcvd); | |||
compare = 1'b1; | |||
if(this.data_out != rcvd.data_out) | |||
begin | |||
compare = 1'b0; | |||
$display("DATA MISMATCH"); | |||
$display(this.data_out, " != ", rcvd.data_out); | |||
$stop; | |||
end | |||
endfunction | |||
endclass: counter_trans | |||
@@ -0,0 +1,35 @@ | |||
class counter_wr_bfm; | |||
virtual counter_if.WR_BFM wr_if; | |||
mailbox #(counter_trans) gen2wr; | |||
counter_trans trans_h; | |||
function new( virtual counter_if.WR_BFM wr_if, | |||
mailbox #(counter_trans) gen2wr); | |||
this.wr_if = wr_if; | |||
this.gen2wr = gen2wr; | |||
this.trans_h = new; | |||
endfunction | |||
task drive(); | |||
@(wr_if.wr_cb); | |||
wr_if.wr_cb.rst <= trans_h.rst; | |||
wr_if.wr_cb.load <= trans_h.load; | |||
wr_if.wr_cb.updown <= trans_h.updown; | |||
wr_if.wr_cb.data <= trans_h.data; | |||
endtask | |||
task start(); | |||
fork | |||
forever | |||
begin | |||
gen2wr.get(trans_h); | |||
drive(); | |||
end | |||
join_none | |||
endtask | |||
endclass: counter_wr_bfm | |||
@@ -0,0 +1,39 @@ | |||
class counter_wr_mon; | |||
virtual counter_if.WR_MON wrmon_if; | |||
mailbox #(counter_trans) wrmon2rm; | |||
counter_trans trans_h, wrmon2rm_h; | |||
function new( virtual counter_if.WR_MON wrmon_if, | |||
mailbox #(counter_trans) wrmon2rm); | |||
this.wrmon_if = wrmon_if; | |||
this.wrmon2rm = wrmon2rm; | |||
this.trans_h = new; | |||
endfunction | |||
task monitor(); | |||
@(wrmon_if.wrmon_cb) | |||
begin | |||
trans_h.rst = wrmon_if.wrmon_cb.rst; | |||
trans_h.load = wrmon_if.wrmon_cb.load; | |||
trans_h.updown = wrmon_if.wrmon_cb.updown; | |||
trans_h.data = wrmon_if.wrmon_cb.data; | |||
trans_h.display("DATA FROM WRITE MONITOR"); | |||
end | |||
endtask | |||
task start(); | |||
fork | |||
forever | |||
begin | |||
monitor(); | |||
wrmon2rm_h = new trans_h; | |||
wrmon2rm.put(wrmon2rm_h); | |||
end | |||
join_none | |||
endtask | |||
endclass: counter_wr_mon | |||
@@ -0,0 +1,37 @@ | |||
`include "test.sv" | |||
module top; | |||
reg clk; | |||
counter_if intf(clk); | |||
counter DUV( .clk(clk), | |||
.rst(intf.rst), | |||
.load(intf.load), | |||
.updown(intf.updown), | |||
.data(intf.data), | |||
.data_out(intf.data_out)); | |||
bind DUV counter_assertion C_A( .clk(clk), | |||
.rst(intf.rst), | |||
.load(intf.load), | |||
.updown(intf.updown), | |||
.data(intf.data), | |||
.count(intf.data_out)); | |||
test test_h; | |||
initial | |||
begin | |||
test_h = new(intf, intf, intf); | |||
test_h.build_and_run(); | |||
end | |||
initial | |||
begin | |||
clk = 0; | |||
forever #10 clk = ~clk; | |||
end | |||
endmodule: top |
@@ -0,0 +1,25 @@ | |||
////////////////////////////////////////////////////////////// | |||
// 4-bit loadable up-down counter ////// | |||
////////////////////////////////////////////////////////////// | |||
module counter(clk, rst, data, updown, load, data_out); | |||
input clk, rst, load; | |||
input updown; | |||
input [3:0] data; | |||
output reg [3:0] data_out; | |||
always@(posedge clk) | |||
begin | |||
if(rst) | |||
data_out <= 4'b0; | |||
else if(load) | |||
data_out <= data; | |||
else | |||
data_out <= ((updown)?(data_out + 1'b1):(data_out -1'b1)); | |||
end | |||
endmodule | |||
@@ -0,0 +1,10 @@ | |||
modelsim.* | |||
transcript* | |||
vlog.* | |||
work/ | |||
counter_cov* | |||
fcover* | |||
covhtml* | |||
vcover* | |||
*.log | |||
*.wlf |
@@ -0,0 +1,81 @@ | |||
# Makefile for Memory - Regression Testing | |||
RTL= ../rtl/counter.v | |||
work= work #library name | |||
COVOP= -coveropt 3 +cover +acc | |||
SVTB1= ../env/counter_if.sv ../env/counter_assertion.sv ../env/top.sv | |||
INC = +incdir+../env +incdir+../test | |||
SVTB2 = ../env/counter_pkg.sv | |||
TEST = ../test/test.sv | |||
#TEST1 = ../test/test1.sv | |||
#TEST2 = ../test/test2.sv | |||
VSIMOPT= -coverage -novopt -sva -sv_seed 2475652473 work.top | |||
VSIMCOV= coverage save -onexit -assert -directive -cvg -codeAll counter_cov | |||
VSIMBATCH= -c -do "$(VSIMCOV); run -all; exit" | |||
VSIMBATCH1 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov1;run -all;exit" | |||
VSIMBATCH2 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov2;run -all;exit" | |||
VSIMBATCH3 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov3;run -all;exit" | |||
VSIMBATCH4 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov4;run -all;exit" | |||
VSIMBATCH5 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov5;run -all;exit" | |||
VSIMBATCH6 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov6;run -all;exit" | |||
VSIMBATCH7 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov7;run -all;exit" | |||
VSIMBATCH8 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov8;run -all;exit" | |||
VSIMBATCH9 = -c -do "coverage save -onexit -assert -directive -cvg -codeAll counter_cov9;run -all;exit" | |||
html: | |||
firefox covhtmlreport/menu.html | |||
sv_cmp: | |||
vlib $(work) | |||
vmap work $(work) | |||
vlog -work $(work) $(COVOP) $(RTL) $(SVTB2) $(SVTB1) $(INC) #$(TEST) | |||
run_sim: | |||
vsim $(VSIMBATCH1) $(VSIMOPT) -l test1_sim.log +TEST1 +nowarn3829 | |||
run_testg: | |||
vsim -novopt -sva -sv_seed random work.top +TEST1 | |||
clear | |||
clean: | |||
rm -rf modelsim.* transcript* vlog.* work vsim.wlf counter_cov* fcover* covhtml* vcover* *.log | |||
clear | |||
TC2: | |||
vsim $(VSIMBATCH2) -coverage -novopt -sva -sv_seed 598761566 -l test2_sim.log work.top +TEST2 | |||
TC3: | |||
vsim $(VSIMBATCH3) -coverage -novopt -sva -sv_seed 74473697 -l test3_sim.log work.top +TEST3 | |||
TC4: | |||
vsim $(VSIMBATCH4) -coverage -novopt -sva -sv_seed 4275076933 -l test4_sim.log work.top +TEST4 | |||
TC5: | |||
vsim $(VSIMBATCH5) -coverage -novopt -sva -sv_seed 3868229417 -l test5_sim.log work.top +TEST5 | |||
TC6: | |||
vsim $(VSIMBATCH6) -coverage -novopt -sva -sv_seed 749764269 -l test6_sim.log work.top +TEST6 | |||
TC7: | |||
vsim $(VSIMBATCH7) -coverage -novopt -sva -sv_seed 1982889551 -l test7_sim.log work.top +TEST7 | |||
TC8: | |||
vsim $(VSIMBATCH8) -coverage -novopt -sva -sv_seed 1987083824 -l test8_sim.log work.top +TEST8 | |||
TC9: | |||
vsim $(VSIMBATCH9) -coverage -novopt -sva -sv_seed 1987083824 -l test8_sim.log work.top +TEST9 | |||
report: | |||
vcover merge counter_cov counter_cov1 counter_cov2 #counter_cov3 counter_cov4 counter_cov5 counter_cov6 counter_cov7 | |||
vcover report -html counter_cov | |||
regress: clean run_test TC2 report html # TC3 TC4 TC5 TC6 TC7 report html | |||
gui: | |||
vsim $(VSIMOPT) -l test1_sim.log +TEST1 +nowarn3829 | |||
run_gui: clean sv_cmp gui | |||
run_test: clean sv_cmp run_sim | |||
@@ -0,0 +1,60 @@ | |||
import counter_pkg::*; | |||
class counter_trans_load extends counter_trans; | |||
randc logic [3:0] data; | |||
constraint r1 {rst inside {0, 1};} | |||
constraint l1 {load inside {0, 1};} | |||
constraint d1{super.data == data;} | |||
endclass | |||
class test; | |||
virtual counter_if.WR_BFM wr_if; | |||
virtual counter_if.WR_MON wrmon_if; | |||
virtual counter_if.RD_MON rdmon_if; | |||
counter_env env; | |||
counter_trans_load trans_ld_h; | |||
function new( virtual counter_if.WR_BFM wr_if, | |||
virtual counter_if.WR_MON wrmon_if, | |||
virtual counter_if.RD_MON rdmon_if); | |||
this.wr_if = wr_if; | |||
this.wrmon_if = wrmon_if; | |||
this.rdmon_if = rdmon_if; | |||
env = new(wr_if, wrmon_if, rdmon_if); | |||
endfunction | |||
task build_and_run; | |||
if($test$plusargs("TEST1")) | |||
begin | |||
no_of_transaction = 250; | |||
env.build(); | |||
env.run(); | |||
$finish; | |||
end | |||
if($test$plusargs("TEST2")) | |||
begin | |||
trans_ld_h = new(); | |||
no_of_transaction = 250; | |||
env.build(); | |||
env.gen_h.trans_h = trans_ld_h; | |||
env.run(); | |||
$finish; | |||
end | |||
endtask | |||
endclass :test | |||