Professional Documents
Culture Documents
for Verification
100%
Random
Coverage
Test
Directed
Test
Time
Coverage convergence
Constrained
Random tests Many runs,
different seeds
Add
Directed
constraints
testcase Functional
Coverage
Minimal code
Identify
modifications
holes
What should you randomize?
Device Configuration
Environment Configuration
Input Data
Protocol exceptions
Delays
Errors and violations
Layered Architecture -
SystemVerilog
Test
Environment
Scenario Generator
Functional Coverage
Functional Agent Scoreboard Checker
Signal DUT
Data Types
Data Types
initial
begin
bit [31:0] src[5], dst[5];
for (int i=0; i< $size(src); i++)
src[i] = i;
foreach (dst[j])
dst[j] = src[j] * 2; // dst doubles src values
end
For multidimensional arrays, use
foreach (md[i,j])
Multi-dimensional Array
New value:
md[0][0] = 9
md[0][1] = 8
md[0][2] = 7
md[1][0] = 5
md[1][1] = 5
md[1][2] = 5
Basic array operations
copy and compare
Without using loops
initial
begin
bit [31:0] src[5] = {0,1,2,3,4},
dst[5] = {5,4,3,2,1};
// Aggregate compare the two arrays
if (src == dst)
$display(src == dst);
else
$display(src != dst);
// Aggregate copy all src values to dst
dst = src ;
end Comparison limited to
equality and inequality
Packed and Unpacked Arrays
initial begin
logic [63:0] assoc[*], idx = 1;
// Initialize widely scattered values
repeat (64) begin
assoc[idx] = idx ;
idx = idx << 1;
end
// step through all index values with foreach
foreach (assoc[i])
$display(assoc[%h] = %h,i, assoc[i]);
Associative Array Example
(contd.)
// step through all index values with functions
if (assoc.first(idx))
begin
do
$display(assoc[%h] = %h,idx,assoc[idx]);
while (assoc.next(idx));
end
// Find and delete first element
assoc.first(idx);
assoc.delete(idx);
end
Array Methods
string s;
initial begin
s = SystemVerilog;
$display(s.getc(0)); // Display : 83
$display(s.toupper()); // Display : SYSTEMVERILOG
s = {s,3.1b}; // SystemVerilog3.1b
s.putc(s.len()-1,a); // change b -> a
$display(s.substr(2,5)); // Display : stem
my_log( $psprintf(%s %5d,s,42));
end
task my_log (string message);
$display(@%0d: %s,$time,message);
endtask
Expression Width
initial
begin
parity_out = 0;
data = 0;
Pass by reference
Example cntd.
for (int i=250; i<256; i++) begin
#5;
data = i;
$display(" BEFORE : Data = %b == %3d, Parity = %d",
data, data, parity_out);
parity_out = parity (data);
$display (" AFTER : DATA = %b == %3d, Parity = %d",
data, data, parity_out);
end
#30 $finish;
end
endmodule
Pass by reference
Example Output
Output of above Example is :
Basic OOP
Connecting the Testbench and Design
Randomization
Basic OOP
Introduction
class BusTran;
static int count = 0; // Number of objects created
int id ; // unique instance id
function new ;
id = count++;
endfunction
endclass : BusTran
BusTran b1, b2;
initial begin
b1 = new ; // First instance, id=0
b2 = new ; // Second instance, id=1
$display(Second id=%d,count=%d,b2.id,b2.count);
$display(First id=%d,count=%d,b1.id,b1.count);
end // Display : Second id=1,count=2
// Display : First id=0,count=2
Class Routines
class BusTran;
bit [31:0] addr, crc, data[8];
extern function void display();
endclass : BusTran
function void BusTran::display();
$display(@%0d: BusTran addr=%h, crc=%h, addr,crc);
$write(\tdata[0-7]=);
foreach (data[i]) $write(%d ,data[i]);
$display();
endfunction : display
Scoping Rules
class BusTran;
bit [31:0] addr, crc, data[8];
statistics stats;
endclass : BusTran class Statistics;
time startT, stopT;
static int ntrans = 0;
static time total_elapsed_time;
endclass : Statistics
Understanding Dynamic Objects
id=3
src
stats startT=42
dst id=3
stats
id=3
src
stats startT=84
dst id=3
stats
Copying Objects
id=3
src
stats startT=42
dst id=4
stats startT=84
Connecting the
Testbench and Design
Separating the Testbench and
Design
Testbench
request[1:0] grant[1:0]
Arbiter clk
reset
Communication with ports
module top;
logic [1:0] request, grant;
logic reset;
bit clk;
always #5 clk = ~clk;
arb_port a1 (grant, request, reset, clk);
test t1 (grant, request, reset, clk);
endmodule : top
The Interface Construct
arb_if arbif(clk);
arb a1 (arbif);
test t1 (arbif);
endmodule : top
Testbench using simple
arbiter interface
module test (arb_if arbif);
initial begin
@(posedge arbif.clk)
arbif.request <= 2b01;
$display(@%0d : Drove req=01,$time);
repeat(2) @ (posedge arbif.clk);
if (arbif.grant != 2b01)
$display(@%0d: a1: grant != 2b01,$time);
$finish;
end
endmodule : test
Arbiter using interface
interface mii_if;
clocking mtx @(posedge tx_clk);
output txd, tx_en, tx_err;
endclocking : mtx
clocking mrx @(posedge rx_clk);
input rxd, rx_dv, rx_err;
endclocking : mrx
Clocking block name can be just used for waiting to its edge as follows
@ (this.sigs.mtx);
this.sigs.mtx.txd <= nibble;
class Packet;
// The random variables
rand bit [31:0] src, dst, data[8];
randc bit [7:0] kind;
// Limit the values for src
constraint c {src >10;
src <15;}
endclass : Packet
Packet p;
initial begin
p = new;
assert(p.randomize());
transmit(p);
end
Constraint Details
class Packet;
rand int length ;
constraint c_short {length inside {[1:32]}; }
constraint c_long {length inside {[1000:1023]}; }
endclass : Packet
Packet p;
initial begin
p = new ;
p.c_short.constraint_mode(0);
assert (p.randomize());
end
In-line Constraints
class Transaction;
rand bit [31:0] addr, data;
constraint c1 { addr inside {[0:100],[1000:2000]};}
endclass
Transaction t ;
initial begin
t = new;
// addr is 50-100, 1000-1500, data < 10
assert(t.randomize() with {addr >= 50;addr <=1500;
data <10;});
driveBus(t);
end
pre_randomize and
post_randomize
Sum of elements
parameter MAX_TRANSFER_LEN=10;
class StrobePat;
rand bit strobe[MAX_TRANSFER_LEN];
constraint c_set_four {strobe.sum == 3h4;}
endclass
Atomic Stimulus Generation vs
Scenario Generation
// Command generator using randsequence
initial begin
for (int i=0;i<=15;i++) begin
randsequence (stream)
stream : cfg_read := 1 |
io_read := 2 |
mem_read := 5;
cfg_read : ;
io_read : ;
mem_read : ;
endsequence
end // for
end
Random Control
class Generator;
event done;
function new (event done); // Pass event from TB
this.done = done;
endfunction
task run;
fork
begin
-> done; // Tell that test is done
end
join_none
endtask
endclass : Generator
Passing events (cntd.)
generator
mailbox
driver
Mailbox in a testbench
program mailbox_example;
class Generator;
Transaction tr;
mailbox mbx;
function new(mailbox mbx);
this.mbx = mbx;
endfunction
task run;
repeat(10) begin
tr = new;
assert(tr.randomize());
mbx.put(tr); // Send out transaction
end
endtask : run
endclass : Generator
Mailbox in a testbench (cntd.)
class Driver;
Transaction tr;
mailbox mbx;
function new(mailbox mbx);
this.mbx = mbx;
endfunction
task run;
repeat(10) begin
mbx.get(tr); // Fetch next transaction
@(posedge busif.cb.ack);
busif.cb.kind <= tr.kind;
end
endtask : run
endclass : Driver
Mailbox in a testbench (cntd.)
mailbox mbx; // Mailbox connecting gen & drv
Generator gen;
Driver drv;
initial begin
mbx = new;
gen = new(mbx);
drv = new(mbx);
fork
gen.run();
drv.run();
join
end
endprogram : mailbox_example
Advanced OOP
Inheritance
class Transaction;
rand bit [31:0] src, dst, data[8]; // Variables
bit [31:0] crc;
virtual function void calc_crc;
crc = src ^ dst ^ data.xor;
endfunction
virtual function void display;
$display(Tr: src=%h, dst=%h, crc=%h,
src,dst,crc);
endfunction
endclass
Extended Transaction class
Blueprint
Generator copy
(from test)
Generated
stream
Factory Patterns
Blueprint
Generator copy
(from test)
Generated
stream
Generator class using
Factory Patterns
class Generator;
mailbox gen2drv;
Transaction blueprint;
function new(mailbox gen2drv);
this.gen2drv = gen2drv;
endfunction
function build;
blueprint = new;
endfunction
Generator class using
Factory Patterns (cntd.)
task run;
Transaction tr;
forever begin
assert(blueprint.randomize);
tr = blueprint.copy;
gen2drv.put(tr);
end
endtask
endclass : Generator
Using the extended Transaction
class
program automatic test;
Environment env;
initial begin
env = new;
env.build; // Construct the blueprint
BadTr bad;
bad = new; // Create a bad transaction
env.gen.blueprint = bad; // Replace the blueprint
// with bad one
env.run; // Run the test
env.wrap_up; // Cleanup afterwards
end
endprogram
Callbacks
To create a verification environment that you can use for all
tests with no changes.
The key requirement is that the testbench must provide a hook
where the test program can inject new code without modifying
the original classes.
Driver may want to do: inject errors, drop the transaction, delay
the transaction, synchronize this transaction with others, put the
transaction in scoreboard, gather functional coverage data.
Driver just needs to call back a routine defined in the top-level
test.
The beauty of this technique is that the callback routine can be
defined differently in every test.
The test can add new functionality to the driver using callbacks
without editing Driver class.
Callback flow
class Driver;
Driver_cbs cbs[$]; // Queue of callbacks
task run;
bit drop;
Transaction tr;
forever begin
agt2drv.get(tr);
foreach(cbs[i]) cbs[i].pre_tx(tr,drop);
if(!drop) transmit(tr);
foreach(cbs[i]) cbs[i].post_tx(tr);
end
endtask
endclass
Using callback for randomly
dropping a packet
class Driver_cbs_drop extends Driver_cbs;
virtual task pre_tx(Transaction tr, ref bit drop);
// Randomly drop 1 out of every 100 transactions
drop = ( $urandom_range(0,99) == 0);
endtask
endclass : Driver_cbs_drop
program automatic test;
Driver_cbs_drop dcd;
dcd = new;
env.drv.cbs.push_back(dcd);
env.run;
endprogram
Advanced Interfaces
Virtual Interfaces
class Driver;
virtual cntr_if ci;
int id;
function new(virtual cntr_if.TB ci, int id);
this.ci = ci;
this.id = id;
endfunction
task load;
fork begin
##1 ci.cb.load <= 1;
end join_none
endtask
endclass : Driver
Day 3 - Summary
fork join, fork_join_none, fork join_any
Events, semaphores and mailboxes
Inheritance, factory pattern generation and callbacks
Interfaces to virtual interfaces
ThankYou
Day 4 - Agenda
Assertions
Functional Coverage
Assertions
Assertions
time t;
always @(posedge clk)
if (state == REQ)
assert (req1 || req2)
else begin
t = $time;
#5 $error("assert failed at time %0t",t);
end
Similar to $error, $fatal, $warning and $info are available.
Concurrent Assertions
initial begin
repeat (2) @ (posedge clk); req <= 1'b1 ;
@ (posedge clk); gnt <= 1'b1 ; @ (posedge clk); req <=
1'b0 ;
repeat (2) @ (posedge clk);
$finish;
end
sequence s1;
req ##1 gnt ##1 !req;
endsequence : s1
property rule_s1 ;
@ (posedge clk) s1;
endproperty
assert property (rule_s1);
endmodule
req-gnt waveform Example 1
0 5 10 15 20 25 30 35 40 45 50 55
req
gnt
$finish
Assertions Example 1 - Output
initial begin
repeat (2) @ (posedge clk); req <= 1'b1 ;
@ (posedge clk); gnt <= 1'b1 ; @ (posedge clk); req <=
1'b0 ;
repeat (2) @ (posedge clk);
$finish; Overlapping
end
sequence s1;
req ##1 gnt ##1 !req;
endsequence : s1
property rule_s1 ;
@ (posedge clk) req |-> s1;
endproperty
assert property (rule_s1);
endmodule
req-gnt waveform Example 2
0 5 10 15 20 25 30 35 40 45 50 55
req
gnt
$finish
Assertions Example 2 - Output
initial begin
repeat (2) @ (posedge clk); req <= 1'b1 ;
@ (posedge clk); gnt <= 1'b1 ;
@ (posedge clk); req <= 1'b0 ; gnt <= 1b0;
repeat (2) @ (posedge clk);
$finish;
end Non-overlapping
sequence s1;
gnt ##1 !req;
endsequence : s1
property rule_s1 ;
@ (posedge clk) req |=> s1;
endproperty
assert property (rule_s1);
endmodule
req-gnt waveform Example 3
0 5 10 15 20 25 30 35 40 45 50 55
req
gnt
$finish
Failed at
Assertions Example 3 - Output
(a ##2 b) [*5]
is equivalent to
a ##1 ((!b[*0:$] ##1 b) [*2:10]) ##1 c
Go to Repetition Example
property data_check_p;
int x;
a ##1 !a, x = data_in |=> !b[*0:$] ##1
b && (data_out == x);
endproperty
A disable iff clause can be attached to a property_expr to
yield a property_spec
disable iff (expression_or_dist) property_expr
Assume statement
class Transactor;
Transaction tr;
mailbox mbx_in;
covergroup CovPort;
coverpoint tr.port;
endgroup
function new(mailbox mbx_in);
CovPort = new; // Instantiate covergroup
this.mbx_in = mbx_in;
endfunction
Covergroup in a class (cntd.)
task main;
forever begin
tr = mbx_in.get; // Get the next trans.
ifc.cb.port <= tr.port; // Send into DUT
ifc.cb.data <= tr.data;
CovPort.sample(); //Gather coverage
end
endtask : main
endclass : Transactor
Triggering a Cover Group
class Transaction;
rand bit [2:0] hdr_len; // range: 0:7
rand bit [3:0] payload_len; // range: 0:15
endclass
Transaction tr;
covergroup CovLen;
len: coverpoint (tr.hdr_len + tr.payload_len + 5b0)
{bins len[] = {[0:22]};}
endgroup
Naming the coverpoint bins
covergroup CovPortKind;
port: coverpoint tr.port
{bins port[] = {[0:$]};}
kind: coverpoint tr.kind
{bins zero = {0};
bins lo = {[1:3]};
bins hi[] = {[8:$]};
bins misc = default;}
cross kind, port {
ignore_bins hi = binsof(port) intersect {7};
ignore_bins md = binsof(port) intersect {0} &&
binsof(kind) intersect {[9:10]};
ignore_bins lo = binsof(kind.lo);
}
endgroup
Day 4 - Summary
Immediate assertions, concurrent assertions
Sequences, declaration of sequences
Repetition specification (consecutive, goto and non-consecutive)
Sampled value functions ($sampled, $rose, $fell, $stable, $past)
and, intersect, or, first_match, throughout, within and ended operations
Assigning variables in sequence specification and checking
Property declaration : syntax, Implication properties
assert, assume and cover statements
Functional coverage example
coverpoint, covergroup, triggering the covergroup
Controlling the number of bins, naming the bins
Conditional coverage, transition coverage
Ignore_bins and cross coverage
ThankYou