diff --git a/4-bit-counter-SV-UVM/env/counter_assertion.sv b/4-bit-counter-SV-UVM/env/counter_assertion.sv new file mode 100644 index 0000000..6d49bba --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_assertion.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/counter_env.sv b/4-bit-counter-SV-UVM/env/counter_env.sv new file mode 100644 index 0000000..26d73bf --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_env.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/env/counter_gen.sv b/4-bit-counter-SV-UVM/env/counter_gen.sv new file mode 100644 index 0000000..d7fdbe8 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_gen.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/env/counter_if.sv b/4-bit-counter-SV-UVM/env/counter_if.sv new file mode 100644 index 0000000..67f53cb --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_if.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/env/counter_pkg.sv b/4-bit-counter-SV-UVM/env/counter_pkg.sv new file mode 100644 index 0000000..e0f5212 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_pkg.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/env/counter_rd_mon.sv b/4-bit-counter-SV-UVM/env/counter_rd_mon.sv new file mode 100644 index 0000000..01f6069 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_rd_mon.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/counter_rm.sv b/4-bit-counter-SV-UVM/env/counter_rm.sv new file mode 100644 index 0000000..0fb8a67 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_rm.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/counter_sb.sv b/4-bit-counter-SV-UVM/env/counter_sb.sv new file mode 100644 index 0000000..27bd7a6 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_sb.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/env/counter_trans.sv b/4-bit-counter-SV-UVM/env/counter_trans.sv new file mode 100644 index 0000000..31dcdc4 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_trans.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/counter_wr_bfm.sv b/4-bit-counter-SV-UVM/env/counter_wr_bfm.sv new file mode 100644 index 0000000..6730c4f --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_wr_bfm.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/counter_wr_mon.sv b/4-bit-counter-SV-UVM/env/counter_wr_mon.sv new file mode 100644 index 0000000..cff30d7 --- /dev/null +++ b/4-bit-counter-SV-UVM/env/counter_wr_mon.sv @@ -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 + diff --git a/4-bit-counter-SV-UVM/env/top.sv b/4-bit-counter-SV-UVM/env/top.sv new file mode 100644 index 0000000..92b3aff --- /dev/null +++ b/4-bit-counter-SV-UVM/env/top.sv @@ -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 diff --git a/4-bit-counter-SV-UVM/rtl/counter.v b/4-bit-counter-SV-UVM/rtl/counter.v new file mode 100644 index 0000000..43da38e --- /dev/null +++ b/4-bit-counter-SV-UVM/rtl/counter.v @@ -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 + diff --git a/4-bit-counter-SV-UVM/sim/.gitignore b/4-bit-counter-SV-UVM/sim/.gitignore new file mode 100644 index 0000000..06aa683 --- /dev/null +++ b/4-bit-counter-SV-UVM/sim/.gitignore @@ -0,0 +1,10 @@ +modelsim.* +transcript* +vlog.* +work/ +counter_cov* +fcover* +covhtml* +vcover* +*.log +*.wlf diff --git a/4-bit-counter-SV-UVM/sim/Makefile b/4-bit-counter-SV-UVM/sim/Makefile new file mode 100644 index 0000000..75fce18 --- /dev/null +++ b/4-bit-counter-SV-UVM/sim/Makefile @@ -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 + + diff --git a/4-bit-counter-SV-UVM/test/test.sv b/4-bit-counter-SV-UVM/test/test.sv new file mode 100644 index 0000000..997cd81 --- /dev/null +++ b/4-bit-counter-SV-UVM/test/test.sv @@ -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 + + +