In reply to diving:
A few comments:
- The DUT should not have an initialblock; this is for the testbench.
- I strongly recommend that you use assertions in your design as that will reaffirm your understanding of the requirements, it is a tool used for reviews of the design and the requirements, and is a good debugging resource. My SVA Handbook explans SVA and provides many many examples along with guidelines; check the TOC.
- For quick and dirty verification code of assertions or small partition, i use the following code, which is stored as an abbreviation in my Download PhraseExpress from the official source (an excellent abbreviation tool)
I modified the template accordingly
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
timeunit 1ns; timeprecision 100ps;
bit clk, a, b;
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
initial begin
$timeformat(-9, 1, "ns", 8);
$display("%t", $realtime);
end
always @(posedge clk) begin
end
// Assertions here
// Simple subpartiton instanced here
initial begin
bit va, vb;
repeat(200) begin
@(posedge clk);
if (!randomize(va, vb) with
{ va dist {1'b1:=1, 1'b0:=3};
vb dist {1'b1:=1, 1'b0:=2};
}) `uvm_error("MYERR", "This is a randomize error")
a <= va;
b <= vb;
end
$stop;
end
endmodule
- If you don’t want to use UVM and its library, then follow the UVM spirit by including the following: data_item, transaction, sequence, Below is a model and testbench for a very funky counter with weird (on purpose for demo of assertions).
package counter_pkg;
timeunit 1ns; timeprecision 100ps;
`define TOP counter_tb
typedef enum {CT_LOAD, CT_RESET, CT_WAIT, CT_DONE} ct_scen_e;
endpackage : counter_pkg
/**********************************************************************************/
// requirements:
// Loadable counter, reset to 0 if reset_n==0,
// Min count -2, Max count ==5
// This is an activity counter, thus count must change at least
// every 8 cycles
module counter_max #(MAX_COUNT=9, MIN_COUNT=2)( // parameter port list
input logic[3:0] data_in,
input logic ld,
output logic[3:0] counter,
input logic clk, rst_n) ;
int cover_count=0;
int fail_count=0;
// ap_P: assert property(@ (posedge clk) P )
// parameter MIN_COUNT=2; // module item parameter
// If use of parameter port list, then can't use defparam
default disable iff !rst_n;
property p_load;
logic[3:0] v_data_in; // local variable to property
(ld, v_data_in=data_in) |=> counter==v_data_in;
endproperty : p_load
ap_load: assert property ( @(posedge clk) p_load);
ap_count: assert property(@(posedge clk)
!ld && (counter!=MAX_COUNT) |=> counter==$past(counter)+1'b1);
ap_hold: assert property(@(posedge clk)
counter==MAX_COUNT |=> counter==$past(counter));
ap_min_load: assume property(@(posedge clk) disable iff (!rst_n)
ld |-> not(data_in<MIN_COUNT));
ap_max_load: assume property(@ (posedge clk) disable iff(!rst_n)
ld |-> not(data_in > MAX_COUNT))
cover_count++; else fail_count++ ;
ap_statble8: assume property(@(posedge clk)
$stable(counter)|-> ##[1:8] !$stable(counter));
always_ff @(posedge clk) begin : counter1
if(!rst_n) counter <= 0;
else if (ld) counter <= data_in;
else begin : counter2
counter <= counter + 1'b1;
end : counter2
end : counter1
endmodule : counter_max
/**************************************************************/
import uvm_pkg::*; `include "uvm_macros.svh"
import counter_pkg::*;
class data_item;
rand logic[3:0] data;
endclass : data_item
class transaction extends data_item;
rand logic ld=0;
int reset_cycles, idle_cycles;
rand ct_scen_e kind;
// constraint values { ld dist {1'b0 := 80, 1'b1 := 20}; } // 0 80% of time
constraint data_range { data > 2 && data <=9; }
constraint cst_xact_kind {
kind dist {
CT_LOAD := 5,
CT_RESET := 2,
CT_WAIT := 97,
CT_DONE := 1
};
} // cst_xact_kind
endclass : transaction
class simple_random_sequence;
transaction tx=new();
// randomize
virtual task run();
if (!randomize(tx)) `uvm_error("COUNTER", "This is a randomize error")
// ap_rand_seq: assert(randomize(tx));
endtask : run
endclass : simple_random_sequence
module counter_max_tb_simple;
parameter MAX_COUNT_TB=6, MIN_COUNT_TB=3;
// defparam counter_max1.MIN_COUNT=3;
// illegal because have parameter port list
logic[3:0] data_in=0, data=0;
logic ld=0;
logic[3:0] counter, counter2;
logic clk=1'b1, rst_n=1'b1;
simple_random_sequence seq=new();
counter_max #(.MAX_COUNT(MAX_COUNT_TB),
.MIN_COUNT(MIN_COUNT_TB)) counter_max1(.*);
// counter_max counter_max2(.counter(counter2), .*);
initial forever #10 clk=!clk;
// test using simple_random_sequence
always @ (negedge clk) begin : random1
rst_n <= 1'b1; ld <=1'b0;
repeat(3) @ (negedge clk) rst_n <= 1'b0;
repeat(3) @ (negedge clk)rst_n <= 1'b1;
// dada and load
for (int i=0; i<100; i++) begin : for1
@ (negedge clk);
seq.run();
case (seq.tx.kind)
CT_LOAD : begin
load_task(seq.tx.data);
end
CT_RESET : begin
reset_task();
end
CT_WAIT : begin
idle_task(seq.tx.data);
end
CT_DONE : begin
done_task();
end // seq.tx.idle_cycles);
endcase
// @ (negedge clk);
end : for1
$display("End of test");
$finish;
end : random1
// load counter
task load_task(int data);
data_in <= data;
ld <= 1'b1;
@ (negedge clk)ld <= 1'b0;
endtask : load_task
// reset
task reset_task();
ld <= 1'b0;
repeat(1) rst_n <= 1'b0;
@ (negedge clk)rst_n <= 1'b1;
endtask : reset_task
// IDLE
task idle_task(int data);// for now, make idle for 4 cycles
automatic logic[3:0] v=data;
for (int i=0; i<4; i++) begin
ld <= 1'b0;
if (!randomize(v)) `uvm_error("COUNTER", "This is a randomize error")
// assert(randomize(v));
data_in <= v;
@ (negedge clk);
end
endtask : idle_task
// DONE, for now, a do nothing
task done_task();
@ (negedge clk);
endtask : done_task
endmodule : counter_max_tb_simple
//compilation_command_multiple_files counter_pkg.sv counter_max.sv counter_max_tb_simple.sv
//simulation_command counter_max_tb_simple
- Above code has “flavors” or “styles” of UVM, but is not UVM; however, the use of classes and style allows you to easily migrate to UVM.
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr
See Paper: VF Horizons:PAPER: SVA Alternative for Complex Assertions | Verification Academy