Hello , welcome back in this post we will see example on SystemVerilog randomization and constraints. Randomization means making something random , in this case it is variables or objects.and constraint means controlling randomization.
SystemVerilog Randomization:
Random variables
The class variables which get random values on randomization are
called random variables. In order to make variables as random
variables, Class variables need to be declared using the rand and
randc type-modifier keywords.
Following
types can be declared as rand and randc,
rand keyword
Variables declared with the rand keyword are standard random
variables. Their values are uniformly distributed over their range.
rand
bit
[3:0]
addr;
addr is a 4-bit unsigned integer with a range of 0 to 15. on
randomization this variable shall be assigned any value in the range
0 to 15 with equal probability.
randc keyword
randc is random-cyclic. For the variables declared with the randc
keyword, on randomization variable values don’t repeat a random
value until every possible value has been assigned.
randc
bit
[3:0]addr;
i
n order to
randomize the object variables, the user needs to call randomize()
method.
example
object.randomize();
Example on rand and randc:
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
function void print(); // prints data,addr,rdn_wr
$display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(20) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data=1001 addr=1100 rdn_wr=1
# KERNEL: data=1101 addr=0110 rdn_wr=0
# KERNEL: data=1011 addr=1010 rdn_wr=1
# KERNEL: data=0000 addr=1001 rdn_wr=0
# KERNEL: data=0001 addr=0101 rdn_wr=1
# KERNEL: data=1011 addr=0111 rdn_wr=0
# KERNEL: data=0101 addr=0001 rdn_wr=1
# KERNEL: data=1101 addr=1101 rdn_wr=0
# KERNEL: data=0011 addr=1110 rdn_wr=1
# KERNEL: data=1001 addr=1000 rdn_wr=0
# KERNEL: data=0000 addr=0100 rdn_wr=0
# KERNEL: data=1000 addr=1011 rdn_wr=1
# KERNEL: data=0000 addr=1111 rdn_wr=1
# KERNEL: data=1101 addr=0011 rdn_wr=0
# KERNEL: data=0101 addr=0010 rdn_wr=1
# KERNEL: data=0011 addr=0000 rdn_wr=0
# KERNEL: data=0001 addr=0010 rdn_wr=1
# KERNEL: data=1011 addr=1100 rdn_wr=0
# KERNEL: data=0000 addr=0001 rdn_wr=0
# KERNEL: data=1011 addr=0000 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
rand_mode method
The rand_mode() method is used to disable the randomization of a
variable declared with the rand/randc keyword.
rand_mode(1) means randomization
enabled
rand_mode(0) means randomization
disabled
The default value of rand_mode is
1, i.e enabled
Once the randomization is
disabled, it is required to make rand_mode(1) enable back the
randomization
rand_mode can be called as
SystemVerilog method, the randomization enables/disable status of a
variable can be obtained by calling vairble.rand_mode().
the rand_mode method returns 1 if randomization is enabled
else returns 0
syntax : object_handle.variable_name.rand_mode(0);
Example:
// example 2: rand_mode() -> disable randomization
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
function void print(); // prints data,addr,rdn_wr
$display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
pkt.addr.rand_mode(0);
$display("pkt.data.rand_mode() status = %0b",pkt.data.rand_mode());
$display("pkt.addr.rand_mode() status = %0b",pkt.addr.rand_mode());
$display("pkt.rdn_wr.rand_mode() status = %0b \n",pkt.rdn_wr.rand_mode());
$display("---------------------------------------------");
repeat(20) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: pkt.data.rand_mode() status = 1
# KERNEL: pkt.addr.rand_mode() status = 0
# KERNEL: pkt.rdn_wr.rand_mode() status = 1
# KERNEL:
# KERNEL: ---------------------------------------------
# KERNEL: data=1001 addr=0000 rdn_wr=0
# KERNEL: data=1101 addr=0000 rdn_wr=1
# KERNEL: data=1101 addr=0000 rdn_wr=1
# KERNEL: data=1111 addr=0000 rdn_wr=0
# KERNEL: data=0000 addr=0000 rdn_wr=1
# KERNEL: data=0001 addr=0000 rdn_wr=0
# KERNEL: data=1011 addr=0000 rdn_wr=1
# KERNEL: data=1101 addr=0000 rdn_wr=0
# KERNEL: data=1101 addr=0000 rdn_wr=1
# KERNEL: data=1111 addr=0000 rdn_wr=0
# KERNEL: data=1001 addr=0000 rdn_wr=0
# KERNEL: data=1000 addr=0000 rdn_wr=1
# KERNEL: data=1000 addr=0000 rdn_wr=0
# KERNEL: data=1111 addr=0000 rdn_wr=1
# KERNEL: data=1101 addr=0000 rdn_wr=1
# KERNEL: data=0111 addr=0000 rdn_wr=0
# KERNEL: data=0011 addr=0000 rdn_wr=1
# KERNEL: data=1101 addr=0000 rdn_wr=0
# KERNEL: data=1011 addr=0000 rdn_wr=0
# KERNEL: data=1110 addr=0000 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
pre randomize and post randomize methods
On calling randomize(),
pre_randomize() and post_randomize() functions will get called
before and after the randomize call respectively
Users can override the pre_randomize() and post_randomize()
functions
// example 3: pre_randomize() and post_randomize() methods
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
function void pre_randomize();
$display("=============================================");
$display("\tdata.rand_mode() status = %0b", data.rand_mode());
$display("\taddr.rand_mode() status = %0b", addr.rand_mode());
$display("\trdn_wr.rand_mode() status = %0b",rdn_wr.rand_mode());
$display("=============================================");
endfunction
function void post_randomize(); // prints data,addr,rdn_wr
$display("\t data=%4b addr=%4b rdn_wr=%0b\n",data,addr,rdn_wr);
endfunction
endclass
module ex1;
packet pkt;
int loop_count=10;
initial begin
pkt=new();
$display("---------------------------------------------");
for(int i=0;i<loop_count;i++) begin
pkt.randomize(); //randomize variable declare as rand or randc
if(i>5) begin
pkt.rand_mode(0); //disable randomization
end
end
$display("---------------------------------------------");
end
endmodule
/*output
# KERNEL: ---------------------------------------------
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=1001 addr=1100 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=1101 addr=0110 rdn_wr=0
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=1011 addr=1010 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=0000 addr=1001 rdn_wr=0
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=0001 addr=0101 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=1011 addr=0111 rdn_wr=0
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 1
# KERNEL: addr.rand_mode() status = 1
# KERNEL: rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL: data=0101 addr=0001 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 0
# KERNEL: addr.rand_mode() status = 0
# KERNEL: rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL: data=0101 addr=0001 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 0
# KERNEL: addr.rand_mode() status = 0
# KERNEL: rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL: data=0101 addr=0001 rdn_wr=1
# KERNEL:
# KERNEL: =============================================
# KERNEL: data.rand_mode() status = 0
# KERNEL: addr.rand_mode() status = 0
# KERNEL: rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL: data=0101 addr=0001 rdn_wr=1
# KERNEL:
# KERNEL: ---------------------------------------------
*/
SystemVerilog : Constraints
As the name says random variable will get random value on
randomization. In some situations it is required to control the
values getting assigned on randomization, this can be achieved by
writing constraints.
Constraint blocks
Constraint blocks are class
members like tasks, functions, and variables
Constraint blocks will have a
unique name within a class
Constraint blocks consist of
conditions or expressions to limit or control the values for a
random variable
Constraint blocks are enclosed
within curly braces { }
Constraint blocks can be defined inside the class or outside
the class like extern methods, constraint block defined outside the
class is called as extern constraint block
syntax:
constraint <constraint_block_name> { <condition/expression>;
......
<condition/expression> }
// example 4 : basic constraint example
class packet;
rand bit [3:0] data;
rand bit [3:0] addr;
randc bit rdn_wr;
function void print(); // prints data,addr,rdn_wr
$display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
endfunction
constraint data_range{data>5; // on randomization value of data is between 6 and 11
data<12;
}
constraint addr_range{addr<10;} // on randomization value of addr will always <10
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(20) begin
pkt.randomize(); // randomize variable declare as rand or randc
pkt.print(); // print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data=1000 addr=0100 rdn_wr=1
# KERNEL: data=0110 addr=0100 rdn_wr=0
# KERNEL: data=0110 addr=1000 rdn_wr=1
# KERNEL: data=1001 addr=0010 rdn_wr=0
# KERNEL: data=0110 addr=0101 rdn_wr=1
# KERNEL: data=0111 addr=0011 rdn_wr=0
# KERNEL: data=1010 addr=0000 rdn_wr=0
# KERNEL: data=1010 addr=0011 rdn_wr=1
# KERNEL: data=1011 addr=0011 rdn_wr=0
# KERNEL: data=0111 addr=0000 rdn_wr=1
# KERNEL: data=1010 addr=1001 rdn_wr=0
# KERNEL: data=0110 addr=1001 rdn_wr=1
# KERNEL: data=1001 addr=0111 rdn_wr=0
# KERNEL: data=0110 addr=0101 rdn_wr=1
# KERNEL: data=1000 addr=0001 rdn_wr=1
# KERNEL: data=0111 addr=0011 rdn_wr=0
# KERNEL: data=1001 addr=0100 rdn_wr=1
# KERNEL: data=1001 addr=0011 rdn_wr=0
# KERNEL: data=1001 addr=1000 rdn_wr=0
# KERNEL: data=0110 addr=0101 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
inside operator
During randomization, it might require
to randomize the variable within a range of values or within set of
values or other than a range of values. this can be achieved by using
constraint inside operator.
Syntax:
constraint constraint_name {variable
inside{...};}
// example 5 : inside operator
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
endfunction
constraint addr_range {addr inside{[10:15]};}
// on randomization value of addr remains between 10 and 15
constraint data_range {data inside{[1:5]}; }
// on randomization value of data remains between 1 and 5
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(10) begin
pkt.randomize(); // randomize variable declare as rand or randc
pkt.print(); // print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data= 2 addr=12 rdn_wr=1
# KERNEL: data= 2 addr=11 rdn_wr=0
# KERNEL: data= 2 addr=15 rdn_wr=1
# KERNEL: data= 2 addr=13 rdn_wr=0
# KERNEL: data= 1 addr=10 rdn_wr=1
# KERNEL: data= 3 addr=14 rdn_wr=0
# KERNEL: data= 1 addr=11 rdn_wr=1
# KERNEL: data= 1 addr=12 rdn_wr=0
# KERNEL: data= 5 addr=15 rdn_wr=0
# KERNEL: data= 3 addr=13 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
if else constraint
// example 6 : if else constraint
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
string range;
function void print(); // prints data,addr,rdn_wr
$display("\t range=%s data=%d addr=%d rdn_wr=%0b",range,data,addr,rdn_wr);
endfunction
// addr_range :: if range is low then addr<8
// if range is high then addr>8
// else addr is between 5 and 9
constraint addr_range {if(range=="low")
addr<8;
else{
if(range=="high")
addr>8;
else{
addr inside{[5:9]};
}
}
}
endclass
module ex1;
packet pkt1,pkt2;
initial begin
pkt1=new();
pkt2=new();
pkt1.range = "low";
pkt2.range = "high";
$display("---------------------------------------------");
repeat(10) begin
pkt1.randomize(); // randomize variable declare as rand or randc
pkt1.print(); // print values of variables
end
$display("\n---------------------------------------------\n");
repeat(10) begin
pkt2.randomize(); // randomize variable declare as rand or randc
pkt2.print(); // print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
---------------------------------------------
| range=low | data= 9 addr= 2 rdn_wr=1
| range=low | data=11 addr= 3 rdn_wr=0
| range=low | data=10 addr= 6 rdn_wr=1
| range=low | data= 7 addr= 4 rdn_wr=0
| range=low | data= 0 addr= 7 rdn_wr=1
| range=low | data= 3 addr= 5 rdn_wr=0
| range=low | data=10 addr= 1 rdn_wr=0
| range=low | data= 3 addr= 0 rdn_wr=1
| range=low | data= 0 addr= 5 rdn_wr=0
| range=low | data= 9 addr= 3 rdn_wr=1
---------------------------------------------
| range=high | data= 7 addr=12 rdn_wr=0
| range=high | data= 2 addr=15 rdn_wr=1
| range=high | data=14 addr=11 rdn_wr=0
| range=high | data= 9 addr= 9 rdn_wr=1
| range=high | data= 6 addr=13 rdn_wr=0
| range=high | data= 4 addr=14 rdn_wr=1
| range=high | data= 5 addr=10 rdn_wr=0
| range=high | data=15 addr=13 rdn_wr=1
| range=high | data= 5 addr=11 rdn_wr=0
| range=high | data=11 addr=10 rdn_wr=1
---------------------------------------------
Note : Aldec Rivia Pro gives error so use VCS
*/
foreach constraints
SystemVerilog supports using the foreach loop inside a constraint
block. using the foreach loop within the constraint block will make
easy to constrain an array.
// example 7 : foreach constraint-> array in assending order
// elements of array1 should increment by 1
// elements of array2 should increment by 2
class packet;
rand int array1[];
rand int array2[];
constraint array1_size {array1.size == 10;}
constraint array2_size {array2.size == 15;}
constraint order_array1 {foreach(array1[i]){
if(i==0){
array1[i] inside{[1:5]};
}
else{
array1[i]==array1[i-1]+1;
}
}
}
constraint order_array2 {foreach(array2[i]){
if(i==0){
array2[i] inside{[1:5]};
}
else{
array2[i]==array2[i-1]+2;
}
}
}
function void print();
$display("\t array1=%p ",array1);
$display("\t array2=%p ",array2);
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(5) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ----------------------------------------------------------------------------
# KERNEL: array1='{4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
# KERNEL: array2='{3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}
# KERNEL: array1='{3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
# KERNEL: array2='{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29}
# KERNEL: array1='{5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
# KERNEL: array2='{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}
# KERNEL: array1='{5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
# KERNEL: array2='{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}
# KERNEL: array1='{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
# KERNEL: array2='{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29}
# KERNEL: ----------------------------------------------------------------------------
Interview question link : https://www.edaplayground.com/x/VAs4
*/
Disable constraint
Constraints in a class can be disabled
using the constraint_mode method call. By default all the constraints
will be enabled, during the randomization constraint solver will not
consider the disabled constraints. the constraint disables method is
similar to rand_mode() method.
constraint_mode()
method
The constraint_mode() method can be used to disable any particular
constraint block.
constraint_mode(1) means
constraint block is enabled
constraint_mode(0) means
constraint block is disabled
default value of constraint_mode
is 1, i.e enabled
once the constraint block is
disabled, it is required to make constraint_mode(1) enable back the
constraint block
constraint_mode can be called as like SystemVerilog method,
which returns the enable/disable status of a constraint block
syntax:
object_handle.constraint_block_name.constraint_mode(mode);
mode==1 : constraint block enable
mode==0 : constraint block disable
// example 8 : constraint_mode()
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
constraint addr_range{addr inside{2,4,8};}
constraint data_range{data inside{2,4,8};}
constraint rdn_wr_cb{rdn_wr==0;}
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
endfunction
function void constraint_status();
$display("---------------------------------------------");
$display("\tconstraint :: addr_range=%0b",addr_range.constraint_mode());
$display("\tconstraint :: data_range=%0b",data_range.constraint_mode());
$display("\tconstraint :: rdn_wr_cb =%0b", rdn_wr_cb.constraint_mode());
$display("---------------------------------------------");
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
pkt.constraint_status();
$display("---------------------------------------------");
repeat(5) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
pkt.addr_range.constraint_mode(0);
pkt.rdn_wr_cb.constraint_mode(0);
pkt.constraint_status();
repeat(5) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: constraint :: addr_range=1
# KERNEL: constraint :: data_range=1
# KERNEL: constraint :: rdn_wr_cb =1
# KERNEL: ---------------------------------------------
# KERNEL: ---------------------------------------------
# KERNEL: data= 2 addr= 8 rdn_wr=0
# KERNEL: data= 2 addr= 2 rdn_wr=0
# KERNEL: data= 4 addr= 4 rdn_wr=0
# KERNEL: data= 4 addr= 8 rdn_wr=0
# KERNEL: data= 4 addr= 4 rdn_wr=0
# KERNEL: ---------------------------------------------
# KERNEL: constraint :: addr_range=0
# KERNEL: constraint :: data_range=1
# KERNEL: constraint :: rdn_wr_cb =0
# KERNEL: ---------------------------------------------
# KERNEL: data= 2 addr=15 rdn_wr=1
# KERNEL: data= 8 addr= 4 rdn_wr=0
# KERNEL: data= 2 addr= 9 rdn_wr=1
# KERNEL: data= 2 addr= 5 rdn_wr=0
# KERNEL: data= 8 addr=12 rdn_wr=0
# KERNEL: ---------------------------------------------
*/
static constraints
SystemVerilog static constraints are
similar to static class properties. A constraint block can be defined
as static by including the static keyword in its definition.
constraint block with the static keyword followed by constraint
keyword is called as a static constraint. the static constraint is
shared across all the class instances.
only the mode change of static
constraint will get affected in all the instances of a class
mode change is enable or disable
of a constraint by constrain_mode() method
a static class can be enabled or disabled by any object
handle of its class, mode change with one object handle will reflect
all other objects of same class type
syntax:
static
constraint
constraint_name {
....;
}
// example 9 : static constraint
class packet;
rand bit [7:0] data;
randc bit [7:0] addr;
randc bit rdn_wr;
static constraint data_range {data inside{2,4,8,16,32,64,128};}
static constraint addr_range {addr inside{2,4,8,16,32,64,128};}
static constraint rdn_wr_cb {rdn_wr==1;}
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
endfunction
function void constraint_status();
$display("---------------------------------------------");
$display("\tconstraint :: addr_range=%0b",addr_range.constraint_mode());
$display("\tconstraint :: data_range=%0b",data_range.constraint_mode());
$display("\tconstraint :: rdn_wr_cb =%0b", rdn_wr_cb.constraint_mode());
$display("---------------------------------------------");
endfunction
endclass
module ex1;
packet pkt1,pkt2;
initial begin
pkt1=new();
pkt2=new();
pkt1.constraint_status();
$display("---------------------------------------------");
repeat(5) begin
pkt1.randomize(); //randomize variable declare as rand or randc
pkt1.print(); //print values of variables
end
pkt1.constraint_mode(0);
pkt2.constraint_status();
repeat(5) begin
pkt1.randomize(); //randomize variable declare as rand or randc
pkt1.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: constraint :: addr_range=1
# KERNEL: constraint :: data_range=1
# KERNEL: constraint :: rdn_wr_cb =1
# KERNEL: ---------------------------------------------
# KERNEL: ---------------------------------------------
# KERNEL: data= 32 addr= 4 rdn_wr=1
# KERNEL: data= 2 addr= 2 rdn_wr=1
# KERNEL: data= 64 addr=128 rdn_wr=1
# KERNEL: data= 2 addr= 8 rdn_wr=1
# KERNEL: data= 8 addr= 32 rdn_wr=1
# KERNEL: ---- pkt1.constraint_mode(0) -------
# KERNEL: ---------------------------------------------
# KERNEL: constraint :: addr_range=0
# KERNEL: constraint :: data_range=0
# KERNEL: constraint :: rdn_wr_cb =0
# KERNEL: ---------------------------------------------
# KERNEL: data=206 addr= 44 rdn_wr=0
# KERNEL: data= 77 addr= 59 rdn_wr=1
# KERNEL: data= 99 addr=229 rdn_wr=0
# KERNEL: data=120 addr=254 rdn_wr=1
# KERNEL: data=207 addr= 24 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
inline constraint
Constraints will be written inside the class. inline constraint
allows the user to add extra constraints to existing constraints
written inside the class. inline constraints will be written outside
the class i.e along with the randomize method call.
the inline constraint is written
using with keyword
during randomization, constraint
solver will consider both inline constraints and constraints written
inside the class
the inline constraint will not
override the constraints written inside the class
the inline constraint shouldn’t
conflict with the constraint written inside the class, else it will
lead to randomization failure
syntax : object.randomize()
with{....};
// exaxmple 10 : inline constraint
class packet;
rand bit [3:0] data;
randc bit [3:0] addr;
randc bit rdn_wr;
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
endfunction
constraint data_range {data inside{10:15};}
constraint addr_range {addr<10;}
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(10) begin
//randomize variable declare as rand or randc
pkt.randomize()with{pkt.addr<4; pkt.data==12; pkt.rdn_wr==1;};
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data=12 addr= 0 rdn_wr=1
# KERNEL: data=12 addr= 1 rdn_wr=1
# KERNEL: data=12 addr= 2 rdn_wr=1
# KERNEL: data=12 addr= 3 rdn_wr=1
# KERNEL: data=12 addr= 3 rdn_wr=1
# KERNEL: data=12 addr= 1 rdn_wr=1
# KERNEL: data=12 addr= 0 rdn_wr=1
# KERNEL: data=12 addr= 2 rdn_wr=1
# KERNEL: data=12 addr= 1 rdn_wr=1
# KERNEL: data=12 addr= 0 rdn_wr=1
# KERNEL: ---------------------------------------------
*/
Functions
inside Constraints
In some cases constraint can’t be
expressed in a single line, in such cases function call can be used
to constrain a random variable. calling the function inside the
constraint is referred to as function in constraints.
The function will be written
outside the constraint block
Constraint logic shall be written
inside the function as function definition and function call shall
be placed inside the constraint block
Functions shall be called before constraints are solved, and
their return values shall be treated as state variables.
constraint constraint_name
{var=function_call();}
// example 11 : function inside constrtaint
// description : if enable==1 then data should increment by 2
// continously , else data should increment by 1
// continously
class packet;
rand bit [7:0] data;
randc bit enable;
constraint data_range{data == f_enable(enable);}
function bit[7:0] f_enable(bit enable);
static int unsigned count1=0;
static int unsigned count2=2;
if(enable==1) begin
f_enable=count2+2;
count2=count2+2;
end
else begin
f_enable=count1+1;
count1++;
end
endfunction:f_enable
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d enable=%0b",data,enable);
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(20) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data= 4 enable=1
# KERNEL: data= 1 enable=0
# KERNEL: data= 2 enable=0
# KERNEL: data= 6 enable=1
# KERNEL: data= 8 enable=1
# KERNEL: data= 3 enable=0
# KERNEL: data= 10 enable=1
# KERNEL: data= 4 enable=0
# KERNEL: data= 12 enable=1
# KERNEL: data= 5 enable=0
# KERNEL: data= 14 enable=1
# KERNEL: data= 6 enable=0
# KERNEL: data= 7 enable=0
# KERNEL: data= 16 enable=1
# KERNEL: data= 18 enable=1
# KERNEL: data= 8 enable=0
# KERNEL: data= 20 enable=1
# KERNEL: data= 9 enable=0
# KERNEL: data= 22 enable=1
# KERNEL: data= 10 enable=0
# KERNEL: ---------------------------------------------
*/
Soft
constraints
SystemVerilog constraints declared
with the keyword soft is called as soft constraints. any conflict
between class constraint and inline constraint leads to a
randomization failure, from this it is clear that it is not possible
to override the class constraint by inline constraint. Some test
scenarios demand to override the constraints, this can be done by
writing a soft keyword in class constraint.
A soft constraint is a constraint on a random variable, which
allows overriding the constraint.
constraint constraint_name {soft
variable {condition}; }
// example 12 : soft constraint
class packet;
rand bit [7:0] data;
randc bit [7:0] addr;
randc bit rdn_wr;
constraint data_addr {soft data==addr;}
constraint rdn_wr_cb {soft rdn_wr==1;}
function void print(); // prints data,addr,rdn_wr
$display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
endfunction
endclass
module ex1;
packet pkt;
initial begin
pkt=new();
$display("---------------------------------------------");
repeat(10) begin
pkt.randomize(); //randomize variable declare as rand or randc
pkt.print(); //print values of variables
end
$display("overriding constraints");
$display("---------------------------------------------");
repeat(10) begin
//randomize variable declare as rand or randc
pkt.randomize()with{pkt.rdn_wr==0; pkt.addr==pkt.data+1;};
pkt.print(); //print values of variables
end
$display("---------------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL: data=188 addr=188 rdn_wr=1
# KERNEL: data=151 addr=151 rdn_wr=1
# KERNEL: data=110 addr=110 rdn_wr=1
# KERNEL: data=158 addr=158 rdn_wr=1
# KERNEL: data=192 addr=192 rdn_wr=1
# KERNEL: data=162 addr=162 rdn_wr=1
# KERNEL: data=221 addr=221 rdn_wr=1
# KERNEL: data=238 addr=238 rdn_wr=1
# KERNEL: data= 19 addr= 19 rdn_wr=1
# KERNEL: data= 56 addr= 56 rdn_wr=1
# KERNEL: overriding constraints
# KERNEL: ---------------------------------------------
# KERNEL: data=215 addr=216 rdn_wr=0
# KERNEL: data= 6 addr= 7 rdn_wr=0
# KERNEL: data=107 addr=108 rdn_wr=0
# KERNEL: data= 30 addr= 31 rdn_wr=0
# KERNEL: data= 66 addr= 67 rdn_wr=0
# KERNEL: data=228 addr=229 rdn_wr=0
# KERNEL: data= 13 addr= 14 rdn_wr=0
# KERNEL: data= 59 addr= 60 rdn_wr=0
# KERNEL: data= 46 addr= 47 rdn_wr=0
# KERNEL: data=224 addr=225 rdn_wr=0
# KERNEL: ---------------------------------------------
*/
Unique
constraints
SystemVerilog constraint defined with
the keyword unique is called as a unique constraint. On
randomization, unique values to set of variables or unique elements
to an array can be generated by using unique constraints.
Unique constraint allows us to,
Generate unique values across the
variables
Generate unique elements in an array (Fixed Size Array,
Dynamic Array, Associative array and Queue)
constraint c_name {unique
{variables/array}; }
// example 13 : unique constraints
class packet;
rand int unsigned array1[];
rand int unsigned array2[];
constraint array1_size{array1.size==10;}
constraint array2_size{array2.size==10;}
constraint c_array1{unique{array1};
foreach(array1[i])
array1[i]<10;
}
constraint c_array2{foreach(array2[i])
array2[i]<10;
}
function void print();
$display("\t array1[Unique]=%p",array1);
$display("\t array2[Normal]=%p",array2);
endfunction
endclass
module ex13;
packet pkt;
initial begin
pkt=new();
repeat(10) begin
pkt.randomize(); // randomize variable
pkt.print(); // print array
end
end
endmodule
/* output
# KERNEL: array1[Unique]='{2, 9, 0, 7, 3, 8, 1, 5, 6, 4}
# KERNEL: array2[Normal]='{7, 1, 8, 3, 0, 5, 9, 8, 8, 7}
# KERNEL: array1[Unique]='{9, 4, 7, 5, 1, 8, 3, 6, 0, 2}
# KERNEL: array2[Normal]='{4, 1, 6, 3, 6, 5, 2, 5, 7, 7}
# KERNEL: array1[Unique]='{6, 9, 2, 3, 0, 5, 8, 4, 1, 7}
# KERNEL: array2[Normal]='{9, 6, 8, 3, 0, 2, 3, 1, 1, 7}
# KERNEL: array1[Unique]='{8, 9, 1, 2, 6, 5, 7, 3, 4, 0}
# KERNEL: array2[Normal]='{6, 5, 5, 0, 1, 1, 2, 1, 6, 8}
# KERNEL: array1[Unique]='{8, 9, 1, 5, 7, 2, 0, 6, 4, 3}
# KERNEL: array2[Normal]='{7, 5, 9, 6, 5, 5, 6, 5, 3, 0}
# KERNEL: array1[Unique]='{9, 8, 2, 5, 4, 3, 7, 6, 1, 0}
# KERNEL: array2[Normal]='{3, 1, 8, 5, 8, 4, 3, 6, 3, 7}
# KERNEL: array1[Unique]='{2, 5, 3, 9, 7, 6, 8, 0, 1, 4}
# KERNEL: array2[Normal]='{2, 2, 5, 5, 1, 0, 9, 3, 6, 9}
# KERNEL: array1[Unique]='{1, 7, 6, 0, 9, 5, 8, 2, 3, 4}
# KERNEL: array2[Normal]='{6, 8, 2, 9, 2, 0, 9, 8, 5, 0}
# KERNEL: array1[Unique]='{9, 8, 2, 7, 3, 6, 0, 4, 1, 5}
# KERNEL: array2[Normal]='{2, 6, 4, 5, 5, 8, 7, 3, 2, 8}
# KERNEL: array1[Unique]='{9, 0, 6, 7, 8, 4, 1, 5, 3, 2}
# KERNEL: array2[Normal]='{7, 4, 0, 7, 5, 3, 1, 9, 0, 2}
*/
Bidirectional
constraints
SystemVerilog constraints are solved
bidirectionally, which means constraints on all random variables will
be solved parallel.
Consider a constraint example,
constraint
c_name { if(a
== 0) b
== 1;
else
b == 0;
}
|
We see that ‘b’ is dependent on ‘a’.
but constraint
solver see’s it as ‘a’ is dependent on ‘b’ and ‘b’ is
dependent on ‘a’.
i.e if ‘b’ is inline constrained as
‘1’, in order to satisfy, ‘a’ should take the value ‘0’.
// example 14 : bidirectional constraint
class example;
rand bit a;
rand bit b;
constraint c_block{if(a==1) b==0;
else b==1;
}
function void print();
$display("\t a=%0b b=%0b",a,b);
endfunction
endclass
module ex14;
example pkt;
initial begin
pkt=new();
$display("---------------------------------------");
repeat(10) begin
pkt.randomize();
pkt.print();
end
$display("---------------------------------------");
repeat(10) begin
pkt.randomize()with{pkt.b==0;};
pkt.print();
end
$display("---------------------------------------");
end
endmodule
/* output
# KERNEL: ---------------------------------------
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=0 b=1
# KERNEL: a=0 b=1
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=0 b=1
# KERNEL: a=0 b=1
# KERNEL: a=1 b=0
# KERNEL: a=0 b=1
# KERNEL: ---------------------------------------
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: a=1 b=0
# KERNEL: ---------------------------------------
*/
solve
before
Solve before is the constraint
property. solve before is used inside the constraint block to specify
the order of constraint solving. If the variables are dependent, due
to the bidirectional nature of constraints value of one variable will
influence the value of another variable.
solve before constraints are used
to force the constraint solver to choose the order in which
constraints are solved.
constraint solver will give equal weight-age to all the
possible values. i.e On multiple randomization solver should assign
all the possible values.
class
pakcet;
rand
bit a;
rand
bit [3:0]
b;
constraint
a_b { (a ==
1) -> b ==
0; }
endclass
|
Possible value of,
a
-> 0 and 1; // 2 possible values
b -> 0 to 15; // 16 possible values
|
As ‘b’ value ranges 0:15, Probability of getting b == 0 is
very less.
so it will impact the value of a, i.e if value
of b != 0, which will lead to value of ‘a’ to become ‘0’.
What if in some situations it is required to generate a value of
‘a’ to ‘1’ more frequently. by using ‘solve before’ it
can be done.
Writing below constraint will direct solver to solve ‘a’
first, so more frequently a will take value of 1.
constraint
sab { solve
a before b;}
|
// example 15 : solve before
class packet;
rand bit a;
rand bit [3:0] b;
constraint sab { solve a before b;}
constraint a_b { (a == 1) -> b == 0;}
endclass
module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(10) begin
pkt.randomize();
$display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
end
end
endmodule
Thank You for reading have a nice day 😀😀😇.
You Might Also Like