2. 223223
Introduction
• Constraint-driven test generation allows users to
automatically generate tests for functional verification.
• Random testing can be more effective than a traditional,
directed testing approach.
• By specifying constraints one can easily create tests that can
find hard-to-reach corner cases.
3. 224224
Introduction
• SystemVerilog allows users to specify constraints in a
compact, declarative way.
• The constraints are then processed by a solver that generates
random values that meet the constraints.
• The random constraints are typically specified on top of an
object oriented data abstraction. that models the data to be
randomized as objects that contain random variables and
user-defined constraints.
4. 225225
Randomization
• The constraints determine the legal values
that can be assigned to the random variables.
• Objects are ideal for representing complex
aggregate data types and protocols such as
Ethernet packets.
5. 226226
Why Random?
• Historically,verification engineers used directed test bench to
verify the functionality of their design.
• Rapid changes have occurred during the past decades in
design and verification.
• High Level Verification Languages (HVLS) such as e,
System c,Vera,SystemVerilog have become a necessity for
verification environments
6. 227227
Constrained Random verification
• Constraint Random stimulus generation is not new.
• Everybody uses verilog and VHDL at very low level
abstraction for this purpose.
• HVLS provide constructs to express specification of
stimulus at high level of abstraction and constraint solver
generates legal stimulus.
7. 228228
Constrained Random verification
Writing constraints at higher level of absctraction,makes the
programming closer to spec.
A constraint language should support:
1)Expressions to complex scenarios.
2)Flexibility to control dynamically.
3)Combinational and sequential constraints.
9. 230230
Constrained Random Stimulus Generation In
System Verilog
– System Verilog has system function $random(),
which can be used to generate random input
vectors.
10. 231231
Example 1
• module Tb_mem();
reg clock;
reg read_write;
reg [31:0] data;
reg [31:0] address;
initial
begin
clock = 0;
forever #10 clock = ~clock;
end
initial
begin
repeat(5)@(negedge clock)
begin
read_write = $random() ; data = $random(); address = $random();
$display ($time," read_write = %d ; data = %d ; address =
%d;",read_write,data,address);
end
#10 $finish;
end
• $random() system function returns a new 32-bit random number each time it is
called. The random number is a signed integer; it can be positive or negative.
11. 232232
Example 2
• module Tb();
integer address;
initial
begin
repeat(5)
#1 address = $random;
end
initial
$monitor ("address = %0d;",address);
endmodule
12. 233233
Example 3
• module Tb();
integer add_2;
reg [31:0] add_1;
integer add_3;
initial
begin
repeat(5)
begin
#1;
add_1 = $random % 10;
add_2 = {$random} %10 ;
add_3 = $unsigned ($random) %10 ;
end
end
initial
$monitor("add_3 = %0d;add_2 = %0d;add_1 =
%0d",add_3,add_2,add_1);
endmodule
13. 234234
Example 4
• module Tb();
real r_num;
initial
begin
repeat(5)
begin
#1;
r_num = $bitstoreal ({$random, $random});
$display ("r_num = %e", r_num);
end
end
endmodule
• To generate random real number , system function
$bitstoreal can be used.
14. 235235
Seed function
• Random number returned by $random() system function
should be deterministic, i.e. when ever we run with simulator
it should return values in same sequence.
• Otherwise the bug found today cant be found return. For this
purpose it has one argument called seed.
• The seed parameter controls the numbers that $random
returns, such that different seeds generate different random
streams.
• The seed parameter shall be either a reg, an integer, or a time
variable.
• The seed value should be assigned to this variable prior to
calling $random.
15. 236236
Example 5
• module Tb();
integer num,seed,i,j;
initial
begin
for(j = 0;j<4 ;j=j+1)
begin
seed = j;
$display(" seed is %d", seed);
for(i = 0;i < 10; i=i+1)
begin
num = { $random(seed) } % 10;
$write("| num=%2d |",num);
end
$display(" ");
end
end
endmodule
16. 237237
SYSTEMVERILOG CRV
• Following are the features of SystemVerilog which
support Constraint Random Verification (CRV) :
1) Constraints : Purely random stimulus takes too
long to generate interesting scenarios. Specify the
interesting subset of all possible stimulus with
constraint blocks.
• These are features provided by SystemVerilog for
constraining randomness.
• Random variable generated in verilog Boolean
expressions, for each (for constraining elements of
array), set membership, inline constraints, rand case,
rand sequence, Conditional constraints and
implication constraints.
17. 238238
SYSTEMVERILOG CRV
• Randomization : random function, constrained and
unconstrained randomization, uniform distribution,
weighted distribution, weighted range, weighted
case, pre randomization, post randomization,
declaration of random variable and non repeating
sequence.
3) Dynamic constraints : inline constraints, guarded
constraints, disabling/enabling constraints,
disabling/enabling random variables and overriding
of constraint blocks.
4) Random Stability : Thread stability, object
stability and manual seeding.
18. 239239
Random Number Generator System Functions
• module Tb();
integer unsigned address;
initial
begin
repeat(5)
begin
address = $urandom();
$display ("address = %d;", address);
end
end
endmodule
19. 240240
SYSTEMVERILOG CRV
• The seed is an optional argument that determines the
sequence of random numbers generated.
• The seed can be any integral expression. The random number
generator (RNG) shall generate the same sequence of random
numbers every time the same seed is used.
20. 241241
Example 6
• module Tb();
integer num,seed,i,j;
initial
begin
for(j = 0;j<4 ;j=j+1)
begin
seed = 2;
$display(" seed is set %d",seed);
void‗($urandom(seed));
for(i = 0;i < 10; i=i+1)
begin
num = $urandom() % 10;
$write("| num=%2d |",num);
end
$display(" ");
end
end
endmodule
21. 242242
$urandom_range
• The $urandom_range() function returns an
unsigned integer within a specified range.
• The syntax for $urandom_range() is as
follows:
function int unsigned $urandom_range( int
unsigned maxval,int unsigned minval = 0 )
• The function shall return an unsigned integer
in the range of maxval ... minval.
22. 243243
Example 7
• module Tb();
integer num_1,num_2;
initial
begin
repeat(5)
begin
#1;
num_1 = $urandom_range(25,20);
num_2 = $urandom_range(55,50);
$display("num_1 = %0d,num_2 =
%0d",num_1,num_2);
end
end
endmodule
23. 244244
Example 8
• module Tb();
integer num_1,num_2;
initial
begin
repeat(5)
begin
#1;
num_1 = $urandom_range(3);
num_2 = $urandom_range(5);
$display("num_1 = %0d,num_2 =
%0d",num_1,num_2);
end
end
endmodule
• If minval is omitted, the function shall return a value in the
range of maxval ... 0.
24. 245245
Example 9
• module Tb();
integer num_1,num_2;
initial
begin
repeat(5)
begin
#1;
num_1 = $urandom_range(20,25);
num_2 = $urandom_range(50,55);
$display("num_1 = %0d,num_2 =
%0d",num_1,num_2);
end
end
endmodule
• If maxval is less than minval, the arguments are
automatically reversed so that the first argument is larger than
the second argument.
25. 246246
Scope Randomize Function
• The scope randomize function, randomize(), enables users to
randomize data in the current scope.
• Variables which are passed as arguments are randomized and
there is no limit on the number of arguments.
• For simpler applications,randomize() function leads to
straight forward implementation.
• This gives better control over the $random, as it allows to add
constraints using inline constraints and constraint solver
gives valid solution.
• Variables which are in the constraint block and not passed as
arguments to randomize() function are not randomized
26. 247247
Example 10
• module scope_3;
integer Var;
initial
begin
for ( int i = 0;i<6 ;i++)
if( randomize(Var))
$display(" Randomization successful :
Var = %0d ",Var);
else
$display ("Randomization failed");
$finish;
end
endmodule
27. 248248
Example 11
• module scope_4;
integer Var;
integer MIN;
initial
begin
MIN = 50;
for ( int i = 0;i<100 ;i++)
if( randomize(Var) with { Var < 100 ; Var
> MIN ;})
$display(" Randomization successful : Var =
%0d Min = %0d",Var,MIN);
else
$display("Randomization failed");
$finish;
end
endmodule
28. 249249
Randomizing Objects
• SystemVerilog allows object-oriented
programming for random stimulus generation,
subjected to specified constraints.
• During randomization, variables declared as
rand or randc inside class are only considered
for randomization.
• Built-in randomize() method is called to
generate new random values for the declared
random variables
29. 250250
Example 12
• program Simple_pro_5;
class Simple;
rand integer Var;
endclass
Simple
obj;
initial
begin
obj = new();
repeat(5)
if(obj.randomize())
$display(" Randomization successful : Var = %0d
",obj.Var);
else
$display("Randomization failed");
end
endprogram
30. 251251
Set membership
• Sometimes we want to randomize a variable within a
set of values (inclusive) or sometimes we want to
exclude some values from random values generated
(exclusive).
• [] is used for specifying range.
• The negated form of the inside operator denotes that
expression lies outside the set: !(expression inside {
set }).
• Absent any other constraints, all values (either single
values or value ranges) have an equal probability of
being chosen by the inside operator.
31. 252252
Example 13
program set_membership;
class frame_t;
rand bit [7:0] src_port;
rand bit [7:0] des_port;
constraint c {src_port inside { [8'h0:8'hA],8'h14,8'h18 };
!(des_port inside { [8'h4:8'hFF] }); }
function void post_randomize();
begin $display ("src port : %0x",src_port);
$display ("des port : %0x",des_port);
end
endfunction
endclass
32. 253253
Example 13
initial
begin
frame_t frame = new();
integer i, j = 0;
for (j=0;j < 4; j++) begin
$display("-------------------------------");
$display ("Randomize Value");
$display("-------------------------------");
i = frame. randomize();
end
$display("-------------------------------"); end
endprogram
33. 254254
Randomization methods
• Every class has a virtual predefined function randomize(),
which is provided for generating a new value.
• Randomization function returns 1 if the solver finds a valid
solution.
• We cannot override this predefined function. It is strongly
recommended to check the return value of randomize
function.
• Constraint solver never fails after one successful
randomization, if solution space is not changed.
• For every randomization call, check the return value, solver
may fail due to dynamically changing the constraints
34. 255255
Example 14
• program Simple_pro_13;
class Simple;
rand integer Var;
constraint c1 { Var <100};
constraint c2 { Var >200;}
endclass
initial
begin
Simple obj = new();
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d
",obj.Var);
else
$display("Randomization failed");
end
endprogram
35. 256256
CONSTRAINT BLOCK
• Constraint block contains declarative statements which
restrict the range of variable or defines the relation between
variables.
• Constraint programming is a powerful method that lets users
build generic, reusable objects that can be extended or more
constrained later.
• Constraint solver can only support 2 state values. If a 4 state
variable is used, solver treats them as 2 state variable..
Constraint solver fails only if there is no solution which
satisfies all the constraints.
• Constraint block can also have nonrandom variables, but at
least one random variable is needed for randomization.
Constraints are tied to objects. This allows inheritance,
hierarchical constraints, controlling the constraints of specific
object.
36. 257257
Example 15
• class Base;
rand integer Var;
constraint range { Var < 100 ; Var > 0 ;}
endclass
class Extended extends Base;
constraint range { Var < 100 ; Var > 50 ;} // Overriding the Base class.
endclass
program inhe_31;
Extended obj;
initial
begin
obj = new();
for (int i=0 ; i < 100 ; i++)
if(obj.randomize())
$display(" Randomization successful : Var = %0d ",obj.Var);
else
$display("Randomization failed");
end
endprogram
37. 258258
Example 16
• class Base;
rand integer Var;
constraint range_1 { Var < 100 ; Var > 0 ;}
endclass
class Extended extends Base;
constraint range_2 { Var > 50 ;} // Adding new constraints
• endclass
program inhe_32;
Extended obj;
initial
begin
obj = new();
for(int i=0 ; i < 20 ; i++)
if(obj.randomize())
$write(": Var = %0d :",obj.Var);
else
$display("Randomization failed");
end
endprogram
38. 259259
Example 17
• class Base;
rand integer Var;
constraint range { Var < 100 ; Var > 0 ;}
endclass
class Extended extends Base;
constraint range { Var == 100 ;} // Overriding the Base class constraints.
endclass
program inhe_33;
Extended obj_e;
Base obj_b;
initial
begin
obj_e = new();
obj_b = obj_e;
for(int i=0 ; i < 7 ; i++)
if(obj_b.randomize())
$display(" Randomization sucsessful : Var = %0d ",obj_b.Var);
else
$display("Randomization failed");
end
endprogram
39. 260260
Example 18
• module adder(a,b,c); //DUT code start
input [15:0] a,b;
output [16:0] c;
assign c = a + b;
endmodule //DUT code end
module top(); //Test Bench code start
reg [15:0] a;
reg [15:0] b;
wire [16:0] c;
adder DUT(a,b,c); //DUT Instantiation
initial
repeat(100) begin
a = $random(); //Apply random stimulus
b = $random();
#10 $display(" a=%0d,b=%0d,c=%0d",a,b,c);
end
endmodule //TestBench code end
40. Example using randcase
int x;
initial
begin
for(int i=0;i<16;i++)
begin
randcase
3:x=1;
1:x=2;
4:x=3;
endcase
$display(―%d‖,x);
end
endmodule
261
41. Example using std::randomize
module test;
reg [3:0] r1;
reg [3:0]r2;
initial
begin
std::randomize (r1,r2) with {r1<r2;r1+r2==4;};
$display(―%d %d‖, r1,r2);
end
endmodule
262
42. 263263
Self Checking TestBenches
• A self-checking TestBench checks expected results against
actual results obtained from the simulation.
• Although Self-checking test benches require considerably
more effort during the initial test bench creation phase, this
technique can dramatically reduce the amount of effort
needed to re-check a design after a change has been made to
the DUT.
• Debugging time is significantly shortened by useful error-
tracking information that can be built into the TestBench to
show where a design fails
43. 264264
Self Checking TestBenches
• A self-checking TestBench has two major parts, the input
blocks and output blocks.
Input block consist of stimulus and driver to drive the
stimulus to DUT.
• The output block consists of monitor to collect the DUT
outputs and verify them.
All the above approaches require the test writer to create an
explicit test for each feature of the design.
• Verification approach in which each feature is written in a
separate test case file is called directed verification.
44. 265265
HOW TO GET SCENARIOS WHICH WE
NEVER THOUGHT
• In Directed verification, the Verification Environment has
mechanism to send the Stimulus to DUT and collect the
responses and check the responses.
• The Stimulus is generated in Tests case. Directed test
benches may also use a limited amount of randomization,
often by creating random data values rather than simply
filling in each data element with a predetermined value.
• Each test case verifies specific feature of the design. This
becomes tedious when the design complexity increases. As
circuit complexity increases, it becomes more difficult to
create patterns that fully exercise the design.
• Test case maintenance become harder and time consuming.
45. 266266
Constraint random verification
• Constraint random verification reduces manual effort and
code for individual tests.
• As the scenarios are generated automatically by the
TestBench, the number of test case files gets reduced.
• In Directed verification, some of the tests share similar logic,
if the engineer has to change the logic which is common to
certain group of tests, then he has to edit all the test case files
and it is time consuming.
• But in Constraint random verification, the number of tests
case files will be very less, so changes will be mostly in
environment and minimal.
• With a constrained-random verification environment, there is
an up-front cost that must be invested before the first test can
be run. Constraint-based generators can be easily converted
into checkers if required.
49. 270270
Stimulus
• When building a verification environment, the verification
engineer often starts by modeling the device input stimulus.
• In Verilog, the verification engineer is limited in how to
model this stimulus because of the lack of high-level data
structures
• SystemVerilog provides high-level data structures and the
notion of dynamic data types for modeling stimulus. Using
SystemVerilog randomization, stimulus is generated
automatically.
• Stimulus is also processed in other verification components.
SystemVerilog high-level data structures helps in storing and
processing of stimulus in an efficient way.
50. 271271
Stimulus Generator
• The generator component generates stimulus which are sent
to DUT by driver.
• Stimulus generation is modeled to generate the stimulus
based on the specification.
• For simple memory stimulus generator generates read, write
operations, address and data to be stored in the address if its
write operation.
• Constraints defined in stimulus are combinatorial in nature
where as constraints defined in stimulus generators are
sequential in nature.
• Stimulus generation can be directed or directed random or
automatic and user should have proper controllability from
test case.
51. 272272
Transactor
• Transactor does the high level operations like burst-operations into
individual commands, sub-layer protocol in layered protocol like
PciExpress Transaction layer over PciExpress Data Link Layer, TCP/IP
over Ethernet etc.
• It also handles the DUT configuration operations. This layer also
provides necessary information to coverage model about the stimulus
generated.
• This high level stimulus is converted into low level data using packing.
This low level data is just a array of bits or bytes.
• Packing is an operation in which the high level stimulus values scalars,
strings, array elements and struct are concatenated in the specified
manner.
52. 273273
Driver
• The drivers translate the operations produced by the
generator into the actual inputs for the design under
verification.
• Generators create inputs at a high level of abstraction namely,
as transactions like read write operation.
• The drivers convert this input into actual design inputs, as
defined in the specification of the designs interface.
• If the generator generates read operation, then read task is
called, in that, the DUT input pin "read_write" is asserted.
53. 274274
Monitor
• Monitor reports the protocol violation and identifies all the
transactions.
• Monitors are two types, Passive and active. Passive monitors
do not drive any signals.
• Active monitors can drive the DUT signals. Sometimes this is
also referred as receiver.
• Monitor converts the state of the design and its outputs to a
transaction abstraction level so it can be stored in a 'score-
boards' database to be checked later on.
• Monitor converts the pin level activities in to high level.
54. 275275
Assertion Based Monitor
• Assertions are used to check time based protocols, also
known as temporal checks.
• Assertions are a necessary compliment to transaction based
testing as they describe the pin level, cycle by cycle,
protocols of the design.
• Assertions are also used for functional coverage.
55. 276276
Data Checker
• The monitor only monitors the interface protocol. It doesn't
check the whether the data is same as expected data or not, as
interface has nothing to do with the date.
• Checker converts the low level data to high level data and
validated the data.
• This operation of converting low level data to high level data
is called Unpacking which is reverse of packing operation.
• For example, if data is collected from all the commands of
the burst operation and then the data is converted in to raw
data , and all the sub fields information are extracted from the
data and compared against the expected values.
• The comparison state is sent to scoreboard.
56. 277277
ScoreBoard
• Scoreboard is sometimes referred as tracker. Scoreboard
stores the expected DUT output.
• Scoreboard in Verilog tends to be cumbersome, rigid, and
may use up much memory due to the lack of dynamic data
types and memory allocation.
• Dynamic data types and Dynamic memory allocation makes
it much easier to write a scoreboard in SystemVerilog.
• The stimulus generator generated the random vectors and is
sent to the DUT using drivers.
• These stimuli are stored in scoreboard until the output comes
out of the DUT.
57. 278278
Utilities
• Utilities are set of global tasks which are not related to any
protocol.
• So this module can be reused across projects without any
modification to code.
• Tasks such as global timeout, printing messages control,
seeding control, test pass/fail conditions, error counters etc.
• The tasks defined in utilities are used by all other
components.
58. 279279
Environment and Tests
• Environment contains the instances of all the verification
component and Component connectivity is also done. Steps
required for execution of each component is done in this.
•
Tests contain the code to control the TestBench features.
Tests can communicate with all the TestBench components.
Once the TestBench is in place, the verification engineer now
needs to focus on writing tests to verify that the device
behaves according to specification.