14.Constraint - vineethkumarv/SystemVerilog_Course GitHub Wiki
Constraint
The constraint is the way to assign legal value to the random variables. Constraints help us to limit the randomness of the variable by specifying the range. The way to create valid test configurations is by the use of constraints.
To enable the randomization we use rand() and randc() function. For using the constraint first, we need to assign the random variables by using the keyword rand or randc. After that declare the constraint statement.
All the constraint blocks are active at the same time.
- Syntax
constraint constraint_name{random_variable[range];}
Note- If the variable is randomised without any constraints, then any value in the range will be assigned to the variable with equal probability.
Cheat Sheet
S.No. | Constraints |
---|---|
1. | Random Function System |
2. | Random Variables |
3. | Constraint Block |
4. | Array Randomization |
5. | Inside Constraint |
6. | Inverted Inside Constraint |
7. | Weighted Distribution |
8. | Bidirectional Constraint |
9. | Implication Constraint |
10. | if-else constraint |
11. | foreach |
12. | Solve before constraint |
13. | Static Constraint |
14. | Randomization methods |
15. | Inline Constraint |
16. | Soft Constraint |
17. | Disable Constraint |
18. | Disable Randomization |
19. | randcase |
20. | constraint memory examples |
Randomization is done in two ways.
- Random function system
- Random Variables
1.Random Function system
This system function is used to give the pseudorandom numbers. These functions are used inside the "initial begin" block. There are generally two system functions used and these are -
$urandom() | $random() | $urandom_range() |
---|---|---|
Return 32-bit unsigned random number but the number remains the same throughout the simulation unless we change the seed number. For the particular seed number again the random number is fixed and does not change throughout the simulation. Syntax- $urandom() | Returns 32-bit signed random number and same as $urandom() not change the value throughout the simulation unless the seed number changed. Syntax- $random() | Returns the unsigned value for the given specified range and does not change the value throughout the simulation time. Syntax - $urandom(max,min); |
-
Example -
The below example shows the random function code.a = $random(); b = $urandom(); c= $urandom_range(4,2); //GIVING RANGE (MAX,MIN) d = $random(23); // assign some seed value e = $urandom(4); // assign seed value $display ("a=$random() // Return 32 bit signed random variable"); $display("Random Value of a = %0d",a); $display("b = $urandom() // Return 32 bit unsigned random value ."); $display("Random Value of b = %0d",b); $display ("c = $random_range(4,2) // Return the unsigned random number") ; $display(" by giving the range to the variable"); $display("Random value of c = %0d",c); $display(" $random(seed); // assign some seed value, it will display 32 bit "); $display (" signed random value for the given seed value "); $display ("d = $random(23); // Seed value =23"); $display ("Random value of d = %0d",d ); $display ("$urandom(seed); // assign the seed value , it will display 32 bit "); $display (" unsigned random value for the given seed value "); $display ("e = $urandom(4); // Seed value = 4;"); $display ("Random value of e = %0d", e); end
-
Output Snap
The below output, fig -1 shows the $random(),$urandom() value and shows the effect of the seed value.
fig -1 Output - random function
GitHub lab file link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/random_function/random_function.sv
GitHub log file link -https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/random_function/random_function_log.log
2.Random Variables
Generally, a random variable is a variable whose value is unknown or a function that assigns values to each of an experiment's outcomes. The class variables which get random values on randomization are called random variables. The value of the random variable is uniformly distributed for the range.
Purpose of random variables
When we do direct tests, we need some time to think about the possible conditions or scenarios for the test and there is a possibility that we missed some test cases. To solve this random variable concept is introduced.
In a random variable, random values in that particular assigned range will be generated.
The drawback of random functions is, that they cannot change the value throughout the simulation times .
To use, random variables, class variables need to be declared using the rand and randc type-modifier keywords.
rand
rand is non-cyclic in nature. It will randomly give any value and can repeat the value before completing the cycle.
-
Syntax
rand data_type variable_name;
-
Example
The below example is of rand variable.
class rand_function;
rand logic [2:0] a ;
endclass
rand_function raf;
module rand_var;
initial begin
// rand_function ra_f;
raf = new();
$display ("rand - Randomizing the value of the variable in the non-cycling form ");
for (int i =0;i <= 10;i++)begin
void'(raf.randomize ());
$display("Iteration = %0d Random value of a = %0d",i, raf.a);
end
end
In the above code, the class is declared as rand_function inside it the variable declared is 'a '. random variable rand is used to randomize the value of the variable 'a'. Inside the module to randomize the class, randomize() function is used. for loop is used to get the randomised value of the variable 11 times.
- Output Snap
Here, the output shows the randomization of variables using rand.
fig-2 Output - rand
GitHub lab code link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/rand/rand.sv
GitHub lab output link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/rand/rand_log.log
randc
randc is random cyclic and cycles through all the values within their range before repeating any particular value. randc is cyclic in nature. It will give a random value and repeat it after completing the cycle.
-
Syntax
randc data_type variable_name;
-
Example
The below example is for randc variable.
class pack;
randc bit [2:0]a;
endclass
module randc_var;
pack pk=new();
initial begin
$display (" randc - It is cyclic in nature . It will repeat ");
$display (" it's value after completing one cycle .");
for (int i =0; i<=12;i++)begin
void'(pk.randomize ());
$display("Iteration = %0d Random Value = %0d ", i ,pk.a);
end
end
Above code, the class declared is pack inside class variable declared is a. Using the randc, variable a is randomized. Inside module, randomize () is used to randomize the class and for loop is iterating from 0 to 12.
- Output Snap
The below output shows the randomization of variable using the randc.
fig-3 Output- randc
GitHub lab code link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randc/randc_var.sv
GitHub log output link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randc/randc_var_log.log
3.Constraint Block
Constraint blocks are the class methods just like function and task. Constraints have a unique name in the class.
- Syntax
constraint [const_name] {expression 1;
expression 2;
... expression N}
Instead of begin end block, constraint blocks are enclosed with curly braces.
- Conflict in constraint
Conflict in constraint blocks are arise when -
- We declare more than one constraint with the same name.
- If there is non-matching in the given ranges of constraint.
We can declare constraints inside and outside of the class. For declaring the constraint outside the class, use the "extern" keyword.
Declare the constraint outside the class block
If we declare constraint without using the extern keyword, then it will display a warning while compiling.
-
Declare constraints outside the class-
-
Syntax
class class_name;
extern constraint constraint_name;
endclass
constraint class_name ::constraint_name{condition;}
-
Example
The below example will show the constraint declaration with the use of the extern keyword. Here, there are two constraints declared that is cons_name1 and cons_name2. cons_name1 is declared inside the class and cons_name2 is declared outside the class using the extern keyword.
class class_a;
rand byte a;
rand byte x;
constraint const_name1{a<6;
a>2;}
extern constraint cons_name2;
endclass
constraint class_a:: cons_name2{x>7;}
module mod;
class_a pack;
initial begin
pack = new;
for (int i =0;i<=5;i++)begin
void'(pack.randomize());
$display ( "Iteration = %0d Value of a = %0d Value of x = %0d " , i,pack.a,pack.x);
end
end
- Output Snap
The output, fig-4 shows the randomization of a variable using an extern constraint.
fig-4 Output- extern constraint
GitHub Lab file link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/extern_cons/extern_cons.sv
GitHub Lab Output link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/extern_cons/extern_cons_log.log
4.Array Randomization
Randomization can also be done in array data types like static array, dynamic array and queues. The variables have to be declared with the type rand or randc to enable the randomization of the variable.
Static array randomization
In a static array, randomization is possible only for the array elements. As the size is fixed, it is not possible to change it.
Declare the array as the keyword rand or randc; on randomization, the elements of the array will get random values.
-
Example -1
The below example show the randomization of the one-dimensional static array without using the constraint.class static_array; randc byte a[5]; endclass module stat_array; static_array stat_arr; initial begin stat_arr = new(); $display ("Static array - Size is already declared. So, we can only randomize "); $display (" the elements of it . "); $display ("Before randomize the elements of array 'a'"); $display ("Assign by the default value of array data type."); $display (" %0p", stat_arr.a); void '(stat_arr.randomize ()); $display ("After randomize the elements of array 'a'"); $display ("Output = %0p ",stat_arr.a); end
Above code, declared an array 'a[5]' of byte data type. The randomization is done by using the randomization function. Without using void, after compilation, the compiler displays a warning. Here, after the randomization of the class, the randomized array will be displayed.
- Output Snap
Below fig-5 shows the output of randomization of the one array without using constraint.
fig-5 Output-static array randomization
GitHub lab code link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_single/stat_arr_rndm.sv
GitHub lab output link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_single/stat_arr_rndm_log.log
-
Example -2-
The below example shows the randomization of a two-dimensional static array without using constraint.class class_1; rand bit [3:0]a[2][4]; endclass module mod; class_1 pack; initial begin pack = new; $display ("The value elements of array before randomization = %0p",pack.a); for (int i =0;i<=5;i++)begin void'(pack.randomize()); $display ("The value of elements of array after randomization = %0p",pack.a); end end
Above code, the array declared is a[2][4] with each element of size 4 bits. Inside the module, for loop is used to get more iterations.
- Output Snap
The output is shown in fig-6, is the randomization of a two-dimensional array.
fig-6 Output- multidimensional array randomization
GitHub Lab File Link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_multi/stat_arr_multi.sv
GitHub Lab Output Link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_multi/stat_arr_multi_log.log
-
Example -3
The below example show the randomization of the multidimensional static array using the constraint. Inside the constraint, foreach loop is used to give the condition to the variable. Here, the array randomization is done 6 times. As we can see, all the element's value is less than 12.class class_1; rand bit [4:0]a[2:0][3:0]; constraint cons_name1{foreach (a[i,j]) // standard way to represent multidimensional array using a[i][j]<12;} //foreach conditional statement endclass module mod; class_1 pack; initial begin $display ("Randomization of multidimensional array"); $display ("----------------------------------------"); pack=new(); $display ("Before randomization"); $display (" Array = %0p",pack.a); // gives default value of data types . $display ("After randomization"); void'(pack.randomize()); for (int i =0;i<=5;i++)begin void'(pack.randomize()); $display (" Iteration = %0d, Array = %0p",i,pack.a); end end
-
Output Snap
Below fig-7 show the randomization of a multidimensional array using constraint.
fig-7 Output - multidimensional array randomization using constraint
GitHub Lab File Link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_cons/stat_cons.sv
GitHub Lab Output Link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/stat_arr/stat_cons/stat_cons_log.log
Dynamic Array
A dynamic array has no predefined size during array declaration. Generally, the array_name.new() keyword is used to assign the size of the dynamic array.
Constraints are used in two ways -
- To limit the size of the dynamic array by using the keyword size in the constraint block.
- To give the value using operators for the elements of the dynamic array using "foreach" conditional statement in the constraint block.
The below example will show how to randomize the dynamic array.
The output after randomization is an empty array if the size is not constrained.
-
Example
class class_1; randc bit [7:0] dyn_arr[]; // declaring a dynamic array, each element is of 8 bits. constraint dyn_arr_size{dyn_arr.size()>3;dyn_arr.size()<7;} // declare the size of the dyn_arr between 3 to 7 constraint dyn_arr_ele{foreach (dyn_arr[i]) // each element value is square of the index number. dyn_arr[i]==i*i;} endclass module mod; class_1 pack; initial begin pack = new(); for (int i = 0;I<=2;i++)begin void'(pack.randomize()); $display ("Iteration =%0d Array =%0p",i,pack.dyn_arr[i]); end end
Above code, first declaring a dynamic array 'dyn_arr[]'. Inside class declaring a constraint for giving the size range. Inside the module, randomize() function is used to randomize the class. The size of the array is between 3 to 7 using constraint. The output will be displayed after randomization for (size of array +1) times.
- Output Snap
The below output is for dynamic array randomization.
fig-8 Output - dynamic array randomization
log file link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/dyn_arr/dyn_arr_log.log
Queue
Queue size will get randomized based on size constraints, and queue elements will get random values.
The below example will show, how to randomize the elements of the queue.
- Example
The below example shows the randomization of elements of the queue and using constraint declaring the size of the queue.
class class_1;
rand bit [3:0]que[$];
constraint que_const{que.size()==5;}
endclass
module mod;
class_1 pack;
initial begin
pack=new;
for (int i = 0;i<=pack.que.size();i++)begin
void'(pack.randomize());
$display (" Iteration = %0d The value of array =%0p",i,pack.que);
end
end
endmodule
- Output snap
output log file link
5.Inside constraint
The inside keyword is used to check if a given value lies within the range.
The values contained by the inside block can be variable, constant, or range. inside construct includes both upper and lower limits and it gathers all values and chooses between the values with equal probability.
In the inside block, we write inside keyword followed by curly braces{}
- Syntax
constraint const_name { variable inside { values or range };}
-
Example:
Let's take an example of inside constraint for better understanding.// class declaration class PQR; // random variable declared using the rand keyword rand bit [3:0] var1; //constraint block constraint C1 {(var1 inside {[3:9]});} endclass module top; initial begin int i; //Here, we need to create a handle //handle name is pkt PQR pqr; //memory allocation to the handle pqr=new(); $display("-------Output for inside constraint-------"); $display("-------------------------------------------"); for(int i =1; i<7;i++)begin // The .randomize() function is used to randomize properties of an object of a class void'(pqr.randomize()); $display("[%0t] @ iteration: %0d -----> var1=%0d",$time,i,pqr.var1); end $display("-------------------------------------------"); end endmodule
In the above example, we declared a class, the class name is PQR in which variable var1 is declared. In the constraint block, we are declaring a range by the use of an inside keyword and the range lies between 3 and 9.
In this, the random value will be printed between 3 and 9.
- Output snap:
The below figure shows the output of the inside constraint.
Fig:-9 Output of inside constraint
In the above example, we declared a class in which a random variable is declared as var1.
In this,we are declaring a range by the use of an inside keyword and the range lies between 3 and 9. The random value will be printed between 3 and 9.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/inside/inside_const.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/inside/inside_const.sv.log
6.Inverted inside constraint
The inverted inside is the opposite of the inside operator. It can be achieved by just placing a not symbol ! before it.
If we want to generate a value that should not be inside a range of values (range_of_values), here we can use the inside operator with negation
-
Syntax
constraint const_name { !(variable inside { values or range });}
-
Example:
Let's take an example of invert inside constraint for better understanding.// class declaration class PQR; // random variable declared using the rand keyword rand bit [3:0] var2; //constraint block //here we use, not symbol before the inside keyword constraint C1 {!(var2 inside {[3:9]});} endclass module top; initial begin int i; //Here, we need to create a handle //handle name is pkt PQR pqr; //memory allocation to the handle pqr=new(); $display("-----Output for invert inside constraint-----"); $display("---------------------------------------------"); for(int i =1; i<7;i++) begin // The .randomize() function is used to randomize properties of an object of a class void'(pqr.randomize()); $display("[%0t] @ iteration: %0d -----> var2=%0d",$time,i,pqr.var2); end $display("---------------------------------------------"); end endmodule
In the above example, we declared a class, the class name is PQR in which variable var2 is declared. In the constraint block, we are declaring a range by the use of an inside keyword with the negation and the range lies between 3 and 9. If we want to generate a value that should not be inside a range of values, here we can use the inside operator with negation.
In this, the random value will be printed that does not lie in range because of use of inside keyword with negation.
- Output snap:
The below figure shows the output of the inverted inside constraint.
Fig:-10 Output of inverted inside constraint
In the above example, we declared a class in which a random variable is declared as var2.
In this, the random value will be printed that does not lie in range because of use of inside keyword with negation.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/invert_inside/invert_inside.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/invert_inside/invert_inside.sv.log
7.Weighted Distribution
The dist operator allows you to create the weighted distribution. dist is an operator that takes a list of values and weights, separated by := or :/ operator. The value which is more weight, the occurrence of that value in randomization is more. The dist operator is helpful whenever to have weighted distribution during randomization.
There are two types of distribution operators
1. := operator
The := operator assigns the specified weight to the item or, if the item is a range, specified value to every value in the range.
- Syntax
value := weightage
-
Example:
Let's take an example := operator for better understanding.class myWorld; // random variable declared using the rand keyword rand bit [3:0] value1; //constraint block //In this, the weight of 1 is 30, 6 is 70, and 7 is 20 //while 2 through 5 is 40 constraint m_var { value1 dist { 1:=30, [2:5]:=40, 6:=70, 7:=20};} endclass module top; initial begin int i; //Here, we need to create a handle //handle name is world myWorld world; // memory allocation to the handle world = new(); $display("-----Output for := operator-----"); $display("The occurrence of '6' is more as '6' has more weight"); for(int i =0; i<10; i++) begin void'( world.randomize()); $display("[%0t] @ iteration %0d -----> value1=%0d",$time,i,world.value1); end end endmodule
In this example, the weight of 1 is 30, 6 is 70, and 7 is 20 while 2 through 5 is 40, for a total of 280.
Hence the probability of choosing 1 is 30/280, 6 is 70/280, 7 is 20/280 and the probability of choosing a value between 2 and 5 is 40/280. In this 6 have appeared more because they have a higher weight and are chosen more often.
- Output snap:
The below figure shows the output of the weighted distribution with := operator.
Fig-:11 Output of := operator
In the above example, we are using a := operator. In this, the 6 is more weight in comparison to the other ones.
The occurrence of 6 is more because 6 is more weight.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/weight1/weighted_distribution.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/weight1/wighted_distribution.sv.log
2. :/ operator
The :/ operator assigns the specified weight to the item or, if the item is a range, to the range as a whole. If there are n values in the range, the weight of each value is range_weight / n
- Syntax
value :/ weightage
-
Example
Let's take an example of :/ operator for better understanding.//class declaration class myWorld; //random variable declared using the rand keyword rand bit [3:0] value1; //constraint block //In this, the weight of 1 is 30, 6 is 40, and 7 is 20 //while 2 through 5 share a total weight of 60 constraint m_var { value1 dist { 1:/30, [2:5]:/60, 6:/40, 7:/20};} endclass //module name is top module top; initial begin int i; //Here, we need to create a handle //handle name is world myWorld world; //memory allocation to the handle world = new(); $display("-----Output for :/ operator"); $display(" The occurrence of '6' is more as '6' has more weight"); $display("--------------------------------"); for(int i =0; i<10; i++) begin void'( world.randomize()); $display("[%0t] @ iteration %0d -----> value1=%0d",$time,i,world.value1); end end endmodule
In this example, the weight of 1 is 30, 6 is 40, and 7 is 20, while 2 through 5 share a total weight of 60, thus having 60/4 each.
Hence the probability of choosing 1 is 30/150, 6 is 40/150, 7 is 20/150 and the probability of choosing a value between 2 and 5 is 60/150.
In this, 6 has appeared more than the other because it has the highest weight.
- Output Snap:
The below figure shows the output of the weighted distribution with :/ operator.
Fig-:12 Output of :/ operator
In the above example, we are using a :/ operator in which 6 is the highest weight.
In this, The occurrence of '6' is more because '6' has more weight in comparison to others.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/weighted_2/weighted_distribution2.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/weighted_2/weighted_distribution2.sv.log
8.Bidirectional constraint
Constraints are solved bidirectionally, which means constraints on all random variables will be solved parallel.
Constraints solve parallelly for all random variables and make sure no constraint fails.
-
Example:
Let's take an example of bidirectional constraint for better understanding.//class declaration class items; // random variable declared by using rand keyword rand bit [3:0] value1; //constraint block constraint addr_mode1 { value1 > 5; value1 <12;} constraint addr_mode2 {value1>6;} endclass // module name is constraint_top module constraint_top; initial begin int i; //Here, we need to create a handle //handle name is an item items item; //memory allocation to the handle item = new(); $display(" -----Output for bidirectional constraint-----"); $display(" -----constraint 1 & 2 limits the value to 7,8,9,10 and 11-----"); $display("----------------------------------------------------------------"); for (int i =1;i<10;i++) begin void'(item.randomize()); $display("[%0t] @ iteration %0d -----> value1 = %0d",$time, i, item.value1); end $display("----------------------------------------------------------------"); end endmodule
In the above example, we declared a class, the class name is item in which variable value1 is declared. In the constraint blocks, we are giving some conditions in both constraints. Constraints on all random variables will be solved parallel.
In this, constraint 1 & 2 limits the value to 7,8,9,10 and 11.
- Output snap:
The below figure shows the output of the bidirectional constraint.
Fig-:13 Output of bidirectional constraint
In the above example, we declared a class in which a random variable is declared as a value1.
In this, constraint 1 & 2 limits the value to 7,8,9,10 and 11.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/bidirectional/bidirectional_const.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/common_constraint/bidirectional/bidirectional_const.sv.log
9.Implication Constraint
The implication operator is used to declare the conditional relations between two variables. The implication operator is placed between the expression and constraint.
The implication operator is denoted by the symbol ->
Implication operator
The implication operator -> is used in a constraint expression to show the conditional relationship between two variables. The implication operator is placed between the expression and constraint.
If the expression on the LHS of implication operator -> is true, then the constraint expression on the RHS will be satisfied. If the LHS is not true, then the RHS expression is not considered.
-
Syntax:
constraint const_name { (variable1) -> (variable2) }
-
Example:
Let's take an example of an implication operator for better understanding.//class declaration class ABC; // random variable declared using rand keyword rand bit [2:0] value1; rand bit [3:0] value2; //constraint block //implication operator is used to mention conditions between //two variables value1 and value2 constraint c_mode { (value1 inside {[1:5]}) -> (value2 <8);} endclass // module name is top module top; initial begin int i; //Here, we need to declare a handle //handle name is abc ABC abc; // memory allocation to the handle abc = new(); $display("-----Output for implication constraint-----"); $display("-------------------------------------------"); for(int i = 0; i< 10 ; i++) begin void'(abc.randomize()); $display("[%0t] @ iteration %0d -----> value1=%0d , value2=%0d" ,$time,i, abc.value1, abc.value2); end $display("--------------------------------------------"); end endmodule
In the above example, we declared a class, class name is ABC in which two variables value1 and value2 are declared. In the constraint block, value1 has declared the range by using the inside keyword.
In this, if the value1 lies between the range of 1 and 5 then the value2 is always less than 8.
If the value1 does not lie between the range of 1 and 5 then the value2 is always greater than 8.
- Output snap:
The below figure shows the output of the implication constraint.
Fig-:14 Output of implication operator
In the above example, the implication operator is used in which we define two random variables value1 and value2.
In this, if the value1 lies between the range of 1 and 5 then the value2 is always less than 8.
If the value1 does not lie between the range of 1 and 5 then the value2 is always greater than 8.
GitHub Lab file link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/implication/implication/implication_constraint.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/implication/implication/implication_constraint.sv.log
10.if-else Constraint
The if-else block allows conditional execution of constraint. If the expression is true, all the constraints in the first constraint block must be satisfied, otherwise, all the constraints in the optional else constraint must be satisfied.
-
Example:
Let's take an example of the if-else constraint for better understanding.// class declaration class basic; //value1 & value2 are the variables //random variables are created by rand keyword rand bit [3:0] value1; rand bit [2:0] value2; constraint c_var { if(value1 inside {[4'h3:4'h9]}) value2 == 1; else { value2 == 0;} } endclass //module name is top module top; int i=1; initial begin //here, we need to create a handle //handle name is pkt basic pkt; // memory allocation to the handle pkt = new(); $display("-----Output for if else constraint-----"); $display("If the value1 lies between the 3 to 9, "); $display(" then value2 will be 1 otherwise 0 "); $display("-----------------------------------------------"); for (int i=0;i<5;i++)begin void'( pkt.randomize()); $display("[%0t] @ iteration %0d -----> value1=%0d, value2 = %0d",$time,i,pkt.value1,pkt.value2); end $display("-----------------------------------------------"); end endmodule
In the above example, we declared a class, class name is basic in which two variables value1 and value2 are declared. In the constraint block, we are using the if-else condition.
In the if statement, the value1 has declared a range with the use of the inside keyword, and if the range lies between 3 and 9 then the value2 will always be 1 and if the range does not lie between the range of 3 and 9 then the value2 always be 0.
- Output snap:
The below figure shows the output of the if-else constraint.
Fig-:15 Output of if-else constraint
In the above example, we declared a class in which two random variables are declared value1 and value2.
If the range lies between 3 and 9 then the value2 will always be 1 and if the range does not lie between the range of 3 and 9 then the value2 always be 0.
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/implication/implication_ifelse/implication_ifelse.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/implication/implication_ifelse/implication_ifelse.sv.log
11.foreach constraint
The foreach constructs iterate over the elements of an array and assign all the values of each element to that of its index.
The foreach loop iterates over the elements of an array, so constraints with the foreach loop are called Iterative constraints
-
Syntax:
constraint constraint_name { foreach ( variable[iterator] ) variable[iterator] <..conditions..> }
-
Example:
Let's take an example of foreach constraint for better understanding.//class declaration class value; //random variable declared using rand keyword rand bit [3:0] s_array1[4]; rand bit [3:0] s_array2[5]; //constraint block //standard way to represent fixed array using //foreach conditional statement constraint cons {foreach(s_array1[i]) s_array1[i]==i; foreach (s_array2[i]) s_array2[i] == i;} endclass // module name is top module top; initial begin //here,we need to declare handle //handle name is val value val; //memory allocation to the handle val = new(); $display("-------------------------------"); void'(val.randomize()); $display("\t s_array1=%0p" , val.s_array1); $display("\t s_array2=%0p" , val.s_array2); $display("-------------------------------"); end endmdule
In the above example, we declared a class and the class name is value in which two fixed arrays are defined.
two arrays s_array1 and s_array2 are declared inside the class. This constraint will iterate through each of the elements in an array,
and set each element to the value of its particular index
- Output snap:
The below figure shows the output of the foreach constraint.
Fig-:16 Output for foreach constraint
GitHub Lab File link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/foreach_constraint/static_cons.sv
GitHub Lab Output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/implication/foreach_constraint/static_cons.sv.log
12.Solve before Constraint
This constraint property is used inside the constraint block for specifying the constraint solving. If the variables are dependent as the constraint are bidirectional, the value of one variable will influence the other variable. This solve-before can change the probability distribution by forcing the constraint solver to choose the order in which constraints are to be solved.
- syntax:
constraint constraint_name {a==1 -> b==1;solve a before b}
Let's take an example for a better understanding of the solve-before constraint
-
Example:
class without_solve_before; rand bit value1; rand bit [3:0] value2; constraint val {value1==1 -> value2==1;} endclass class with_solve_before; rand bit value1; rand bit [3:0] value2; constraint valu {value1==1 -> value2==1; solve value1 before value2;} endclass module solve_before(); without_solve_before gen1 = new(); with_solve_before gen2 = new(); initial begin $write("%c[1;31m \t------Without solve before----------\n",27); for(int i=1;i<=10;i++) begin void'(gen1.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value1: %0d \t value2: %0d",$time,i,gen1.value1,gen1.value2); end $write("\n%c[1;34m\t -----with solve before--------\n",27); for(int i=1;i<=10;i++) begin void'(gen2.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value1: %0d \t value2: %0d",$time,i,gen2.value1,gen2.value2); end $write("%c[0m",27); end endmodule : solve_before
In the above example, took two classes named without_solve_before and with_solve_before which have objects gen1 and gen2 respectively. Both have the same constraints that if the value1 is 1 then the value2 should be 1. As the constraint solver is bidirectional the probability to choose a value2 also affects the probability to choose value1.
The probability to choose individually.
value1 is 1/2
value2 is 1/16
- output:
Fig-:17 Output of Solve before
In the above output, the first 32 iterations are used without solve-before and the next 10 iterations are used with solve before.
without: both value1 and value2 constraints are taken into consideration i.e., probability of value1 to get 1 is 1/2 and for value2 to be 1 is 1/16,but for getting value1 as 1 & value2 as 1 is (1/2)*(1/16)=1/32. with: here the constraint solver first randomizes value1 and depending upon the value1, value2 is solved. so the probability of getting a value1 as 1 is 1/2.
so in the first 32 iterations, there was only 1 iteration that got value1 of 1 i.e., 0.03%, but using solve before value1 got 1 for every alternative iteration means 50%.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/solve_before_constraint/solve_before.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/solve_before_constraint/solve_before_log.log
- limitations:
- can't use randc variables, as they were always allowed to solve first, if used then without solve-before is not considered.
- shouldn't have circular dependency i.e., solve value1 before value2 and solve value2 before value1, if so through error as shown below.
Fig.18 : Error of solve before
13.Static Constraint
static constraints are shared across all the objects of that class.
A static constraint mode can be enabled or disabled by any object handle of that class which reflects in all the classes.
-
syntax:
static constraint cons_name {constraint1; constraint2; ........ constraintN;}
-
Example:
class class1; rand bit [2:0] value; constraint cons {value==1;} endclass class class2; rand bit [2:0] value; static constraint cons {value==1;} endclass initial begin object_1.cons.constraint_mode(0); for(int i=1;i<=3;i++) begin void'(object_1.randomize()); void'(object_2.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value in object_1: %0d value in object_2: %0d",$time,i,object_1.value,object_2.value); end object_3.cons.constraint_mode(0); for(int i=1;i<=3;i++) begin void'(object_3.randomize()); void'(object_4.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value in object_3: %0d value in object_4: %0d",$time,i,object_3.value,object_4.value); end end
In the above example, there were two classes named class1 & class2 with objects 1&2 for class1 and objects 3&4 for class2. Here the constraint for both classes is the same so the value should be always 1 if the constraint is on.
If the constraint is off then the value will have other than 1.
gif 1. static constraint
From the above gif, can say that if the non-static constraint is turned off/on by using a single object handle then the constraint is applicable to that particular object whereas in static constraint, if the constraint is turned off/on then it is applicable for every object of that class.
- output:
Fig-:19 Output of static constraint output
Class 1 has two objects 1&2 and class2 has objects 3&4.In class1 used non-static constraint, turned off in object 1 but still, the constraint is on in object 2, but used static constraint in class2, and turned off in object 3 then the constraint has been turned off in object 4 as well.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/static_constraint/static_constraint.sv Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/static_constraint/static_constraint_log.log
14.Randomization Methods
In general, there will be three randomize methods:
- randomize();
- pre_randomize();
- post_randomize();
gif 2: Randomization methods
when a randomize function is called generates random values for variables that were declared as rand/randc by considering the constraints. It is a virtual function that is not overridable and on successful completion of randomization returns 1 else 0.
Actually, before performing the actual randomization, the simulator first enters into pre_randomize before randomizing, and then on successful randomization simulator enters into the post_randomize function which is also overridable. If the randomization fails due to any issues like constraint conflicts then the simulator doesn't enter into post_randomize and returns 0.
randomize:
randomize is a virtual function of int type returns 1 on successful completion else 0
-
Example:
class generator; rand bit [2:0] value; constraint cons {value==5;} endclass initial begin $display("\tCalling Randomize...."); check=gen.randomize(); $write("\tvalue: %0d ",gen.value); if(check) $display("\tRandomization successful"); else $display("\tRandomization failed"); $display("\tCalling Randomize...."); check=gen.randomize()with{value==2;}; $write("\tvalue: %0d ",gen.value); if(check) $display("\tRandomization successful"); else $display("\tRandomization failed"); end
-
output:
Fig-:20 Output of Randomization
In the above example calling randomize function and storing the value returned by the function in the check variable, if randomization was done taking constraint that value must be 5 and returned 1 based on the check used to print the randomization status message.
In the first randomization, there is no conflict so randomization completes successfully and returns 1 so if condition satisfies so prints as randomization successful, In the next call conflict between constraints so randomization doesn't complete so returns 0 so prints as randomization failed.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/randomization/randomization.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/randomization/randomization_log.log
pre_randomize:
This is a void function type that can be overridable called before the actual randomization performs.
-
syntax:
function void pre_randomize();
-
Example:
class generator; rand bit [2:0] value; constraint exp { value>5;} function void pre_randomize(); if(i%2==0) begin rand_mode(0); $display("\tstopping randomization"); end else rand_mode(1); i++; endfunction endclass module pre_randomization(); generator gen = new(); initial begin for(int i=1;i<=4;i++) begin $display("\t[%0t]Calling Randomize....",$time); void'(gen.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value: %0d ",$time,i,gen.value); end end endmodule
-
output:
Fig. 21 Output of Pre randomization
In the example, calling pre_randomize function and inside that, if condition satisfies then randomization is stopping in pre_randomize so simulator exits the randomize function without performing the randomization which means rand variables will have previous values. In iterations 1,3 randomization is stopped, so it has previous values but in iterations 2,4 randomization is done.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/pre_randomization/pre_randomization.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/pre_randomization/pre_randomization_log.log
post_randomize:
This is also a void function type that can be overridable runs after the randomization is performed.
-
syntax:
function void post_randomize();
-
Example:
function void pre_randomize(); $display("\tI'm in pre_randomize function"); check=0; endfunction function void post_randomize(); $display("\tI'm in post_randomize function"); check=1; endfunction initial begin $display("\t[%0t]Calling Randomize....",$time); check=gen.randomize(); #1 $display("\t[%0t] @ iteration: 1 -----> value: %0d ",$time,gen.value); if(check==1) $display("%c[1;32m\tRandomization is performed%c[0m",27,27); else $display("%c[1;31m\tRandomization is not performed%c[0m",27,27); $display("\t[%0t]Calling Randomize....",$time); check=gen.randomize()with{value<5;}; #1 $display("\t[%0t] @ iteration: 2 -----> value: %0d ",$time,gen.value); if(check==1) $display("%c[1;32m\tRandomization is performed%c[0m",27,27); else $display("%c[1;31m\tRandomization is not performed%c[0m",27,27); end
-
output:
Fig.22 output of Post randomization
In the first iteration of the example calling randomize function, there was no conflict so entering into both pre as well as post after randomizing so printed as randomization is successful but in the second iteration there was a conflict so randomization doesn't completes and comes back and printing as randomization is failed.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/post_randomization/post_randomization.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randmoization_methods/post_randomization/post_randomization_log.log
15.Inline Constraint
Consider that some variables are needed to be randomized in 100 iterations but in the first 95 iterations user needs the common constraints, and in the last 5 iterations user wants to add some more constraints along with previous constraints, then instead of writing in different classes user can just add those extra constraints from where the randomization function is called using with the keyword as shown.
- syntax:
obj_hndl.randomize()with{extra_constraints};
These inline constraints just act as extra constraints by taking the previous constraints into consideration but not overriding the previous constraints. For example, if variable >5 is declared in class and if added one more inline constraint as variable<10 then the final value of the variable will be between 5 and 10.
- Only inline constraint
- inline constraint along with class constraint
- inline conflict with class constraint
Only inline constraint
-
Example:
class generator; rand bit [2:0] value; endclass module only_inline(); generator gen = new(); initial begin for(int i=1;i<=2;i++) begin void'(gen.randomize()with{value==3;}); #1 $display("\t[%0t] @ iteration: %0d -----> value: %0d",$time,i,gen.value); end end endmodule
In the above example, there were no constraints in class so the value can be anywhere between 0 to 7 as it is 3-bit, but calling the randomize function along with inline constraint that value should be 3.
- output:
Fig.23 output of only inline constraint
As per the inline constraint, the value must be 3 so in both iterations the value is the same.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/only_inline/only_inline.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/only_inline/only_inline_log.log
inline constraint along with class constraint
-
Example:
class generator; rand bit [2:0] value; constraint exp { value>2;} endclass module inline_constraint(); generator gen = new(); initial begin void'(gen.randomize()); #1 $display("\t[%0t] @ iteration: %0d -----> value: %0d",$time,i,gen.value); void'(gen.randomize()with{value==7;}); #1 $display("\t[%0t] @ iteration: %0d -----> value: %0d",$time,i,gen.value); end endmodule
In the above example, the class has one constraint that the value should be greater than 2 and one more constraint is given through inline that the value should be 7.
- output:
Fig.24 output of inline constraint along with class constraint
The initial constraint in class is value >2 so its first iteration value is in the range of 2 to 7, but in the second iteration giving value must be 7 from inline so the value is 7
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/class_and_inline/inline_constraint.sv
Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/class_and_inline/inline_constraint_log.log
inline conflict with class constraint
-
Example:
class generator; rand bit [2:0] value; constraint cons {value==5;}; endclass module conflict_with_inline(); generator gen = new(); int check; initial begin for(int i=1;i<=2;i++) begin check=gen.randomize()with{value==3;}; if(check) $display("\tRandomization Done \t @ iteration: %0d -----> value: %0d",i,gen.value); else $display("\tRandomization Failed \t @ iteration: %0d -----> value: %0d",i,gen.value); end end endmodule
In the above example, the class has a constraint that the value must be 5 and from the inline constraint, there was one more constraint mentioned that value should be 3.
- output:
Fig.25 output of inline conflict with class constraint
Here the constraint solver takes both the constraints into consideration which means there was a conflict between these constraints, in these times randomization will not happen and returns the value 0. so based on the check display message is printed.
Github code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/conflict_with_inline/conflict_with_inline.sv Github output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/inline_constraints/conflict_with_inline/conflict_with_inline_log.log
note:
- Not throwing any error from Questa sim 10.6 version simulator
- In mentor graphics of 2021 version it's throwing an error that constraint conflict arose as shown below
Fig. 26 Constraint conflict error
16.Soft Constraint
Constraints declared with the keyword soft are called as soft constraints.
If any conflict between class constraint and inline constraint leads to a randomization failure, it is clear that it is not possible to override the class constraint by using an inline constraint. So some test-case demand overrides the constraints, this can be done by using a soft keyword in class constraint.
-
Syntax
constraint constraint_name { soft variable_name > range ; }
-
Example
for a better understanding purpose, we are executing the two codes.
First Let's take an example for a better understanding of the normal constraints without using soft constraint
class pack;
rand bit [0:3]a;
constraint addr_a{a>5;}
endclass
module soft_without_conflict;
pack pkh;
initial begin
pkh = new;
$display("without using soft constraint output");
for(int i =0; i<5;i++)
begin
void'(pkh.randomize());
$display("\n \t a=%0d value =%0d",i,pkh.a);
end
pkh = new;
$display("\n \t output of without conflict");
for(int i =0; i<5;i++)
begin
void'(pkh.randomize()with {a<10;});
$display("\n \t a=%0d value =%0d",i,pkh.a);
end
end
endmodule
In the above example, we took a class name as pack which has an object pkh. the class has a constraint name called addr_a in that constraint is displayed from 0 to 5 value. and inside the module we are using inline constraint it will display from 0 to 10 values but we are using here inline constraint so This Constraint addr_a will be overridden.
-
Output Snap
fig.27 Output of without soft constraint
In the above example, in the starting 5 iterations normal constraints are executed so it displays the value from 5 to 15, and another 5 iterations inline constraint is executed so it displays the value from 10 to 0.
GitHub lab file link: https://github.com/muneeb-mbytes/SystemVerilog_Course/tree/b7_Team_SiliconCrew/constraints/soft_without_conflict
GitHub log file link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/soft_without_conflict/soft_without_conflict_output.log
Let's take an example for a better understanding of the Soft constraint
class pack;
rand bit [0:3]a;
constraint addr_a{a>5;}
endclass
module soft_with_conflict;
pack pkh;
initial begin
pkh = new;
$display("output of soft with conflict ");
for(int i =0; i<5;i++)
begin
void'(pkh.randomize()with {a<5;});
$display("\n \t a=%0d value =%0d",i,pkh.a);
end
pkh = new;
$display("\n \t using soft constraint to solve conflict issue");
for(int i =0; i<5;i++)
begin
void'(pkh.randomize()with {soft a<10;});
$display("\n \t a=%0d value =%0d",i,pkh.a);
end
end
endmodule
In the above example, we took a class name as pack which has an object pkh. the class has a constraint name called addr_a in that constraint as to be displayed from 0 to 5 value but it's not displaying anything. and inside the module we are using inline constraint the is also not displaying anything because here the conflict will occur so resolve this conflict we are using a soft constraint. and it displays the value from 10 to 0 values.
-
Output Snap
fig 28. The output of soft with conflict
In the above example, in the starting 5 iterations, normal constraints are executed so it displays the value zero because in the inside code already conflict occurred. another 5 iterations using soft constraints to execute the code, display the value from 10 to 0.
GitHub lab file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/soft_with_conflict/soft_with_conflict.sv
GitHub log file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/soft_with_conflict/soft_with_conflict_output.log
17.Disable constraint
Constraints in a class can be disabled using the constraint_mode method
By default all the constraints will be enabled, during the randomization constraint user will not consider the disabled constraints.
constraint_mode(1) means constraint block is enabled
constraint_mode(0) means constraint block is disabled
The 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.
-
Synatx:
object_hanlde.constraint_block_name.constraint_mode(enable);
enable == 1, constraint block enable
enable == 0, constraint block disable -
Example
Let's take an example for a better understanding of the disabled Constraint
class packet;
rand bit [3:0] data;
constraint data_range { data inside {5,10,15}; }
endclass
module constraint_mode;
packet pkt = new();
initial begin
$display("If constraint is mode is 1 it will display the 5,10,15");
$display("If constraint is mode is 0 it will display the random values");
$display("\t Before Constraint disable");
$display("\t Value of constraint mode = %0d",pkt.data_range.constraint_mode());
void'( pkt.randomize());
$display("\tdata = %0d",pkt.data);
pkt.data_range.constraint_mode(0);
$display("After Constraint disable");
$display("Value of constraint mode = %0d",pkt.data_range.constraint_mode());
repeat(5) begin
void'(pkt.randomize());
$display("\tdata = %0d",pkt.data);
end
end
endmodule
In the above example, we took a class name as packet which has an object pkt. the class has a constraint name called data_range in that constraint will be displayed 5, 10, 15. constraint mode is enabled (1) it displays the values 5, 10, and 15 and if constraint mode is disabled (0) it displays any values.
- Output snap
fig 29. The output of Disable constraint
In the above output, If constraint mode is 1 it displays 5,10,15, and if disabled the constraint using constraint mode is 0 then it displays the any random values.
GitHub lab file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_mode/constraint_mode_code.sv
GitHub log file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_mode/constraint_mode_code_output.log
18.Disable randomization
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 variable.rand_mode().
the rand_mode method returns 1 if randomization is enabled else returns 0
- Syntax
object_hanlde.variable_name.rand_mode(enable);
//enable = 1, randomization enable
//enable = 0, randomization disable
- Example
Let's take an example for a better understanding of the disable randomization
class packet;
rand bit [2:0]data1;
randc bit [1:0]data2;
int state;
function rand_mode1(int a);
if(a==0)
begin
rand_mode(a);
state = a;
end
else if(a==1)
begin
rand_mode(a);
state = a;
end
endfunction
endclass
module randomization_mode;
packet pkt = new();
int c;
initial begin
$display("Before Randomization data1 = %0d data2= %0d",pkt.data1,pkt.data2);
if(pkt.data1.rand_mode())
if (pkt.data2.rand_mode())
pkt.state = 1;
$display("randomization of all variables are enabled");
for(int i = 0;i<5;i++)
begin
c = pkt.randomize();
$display("[%0d] After enable the randomizations data1 =%0d, data2 = %0d",i,pkt.data1,pkt.data2);
$display("[%0d] state = %0d",i,pkt.state);
if(i==3)
begin
pkt.rand_mode1(0);
$display("[%0d] state = %0d",i,pkt.state);
end
$display("[%0d] After disable in the randomization data1 =%0d, data2 = %0d",i,pkt.data1,pkt.data2);
end
end
endmodule
In the above example, we took a class name as packet which has an object pkt. inside the class, we are declaring a function name called rand_mode1 which has the variable is state. if state = 1 randomization enabled, state = 0 randomization disabled.
we were declaring the output 0 to 5 variations, in that 0 to 3, enable randomization and disable randomization both randomization has happened. and remaining 4 & 5 variations only randomization happens.
Output snap
Fig.30 The output of Disable randomization
In the above output, using Randomization mode is 1 to enable the randomization, then it will display the random data . using randomization mode is 0 to disable the randomization, then it displays the zero or previous randomization data. In our output snap, iterations from 0 to 3 both randomization enable disable are happening and in iteration 4 only randomization disable is happening.
GitHub lab file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randomization_mode/randomization_mode_code.sv
GitHub log file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randomization_mode/randomization_mode_code_output.log
19.randcase
The keyword randcase introduces a case statement that randomly selects one its of branches.
The case item expressions are positive integer values that represent the weights associated with each item.
The probability of selecting an item is derived by the division of that item's weight divided by the sum of all weights.
Syntax
randcase
item: statement
endcase
Example
Let's take an example for a better understanding of the randcase
module r_case;
initial begin
$display("Random data will be generated by simulator");
$display("data from 0 to 3 then it will display randcase output");
for(int i =0; i<6;i++)
begin
randcase
0:$display("\t \n output of randcase 0");
1:$display("\t \n output of randcase 1");
2:$display("\t \n output of randcase 2");
3:$display("\t \n output of randcase 3");
endcase
end
end
endmodule
In the above example, we were using randcase, if its expressions match it displays. Each call to randcase retrieves one random number in the range of 0 to the sum of the weights. the weights are then selected in declaration order of small random numbers corresponding to the first (top) weight statements.
Output snap
Fig.31 output of the randcase
In the above output, using randcase to generate the 0 to 3 values if any expressions is match it displays outputs.
In the above-output snap, the sum of all weights is 7; therefore, the probability of taking the first branch is (1/7) i.e. 0.142.
The probability of taking the second is (2/7) i.e. 0.285, and the probability of taking the third is (3/7) i.e. 0.428. Each call to the randcase statement will return a random number in the range from 0 to 3.
GitHub lab file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randcase/randcase_code.sv
GitHub log file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/randcase/randcase_code_output.log
Memory partition using constraints
Memory block randomization
Assume that you have a memory of size 2048 i.e., 2KB in design to store some data, then if we need some block of that 2KB memory for some purpose, for partitioning that memory we can use constraints.
Example:
class memory_block;
bit [31:0] mem_ram_start,mem_ram_end;
rand bit [31:0] mem_start_addr,mem_end_addr;
rand int mem_block_size;
constraint mem {mem_start_addr>=mem_ram_start;
mem_start_addr<mem_ram_end;
mem_start_addr%4==0;
mem_end_addr==mem_start_addr+mem_block_size-1;}
constraint block_size {mem_block_size inside {32,64};}
function void display();
$display("\t----memory block----");
$display("\t RAM start addr : %0d",mem_ram_start);
$display("\t RAM end addr : %0d",mem_ram_end);
$display("\t BLOCK start addr : %0d",mem_start_addr);
$display("\t BLOCK end addr : %0d",mem_end_addr);
$display("\t BLOCK SIZE:%0d",mem_block_size);
endfunction
endclass
module single_memory_block();
memory_block memb =new();
initial
begin
memb.mem_ram_start=32'h0;
memb.mem_ram_end=32'h7ff;
void'(memb.randomize());
memb.display();
end
endmodule
In the above example,we took start address is 0 and end address is 2047, and gave constraints such that the block size should be of either 32, 64(int).The block should start at multiple of 4 and should end depending on the block_size.
output:
Fig. 32. output of the Memory block randomization
The output of the above example is shown in above diagram, for constraint of block size , solver gave 64.Based on this block size the solver will give a start address such that the memory block will be within the range of 2KB. here gave it as 1896 which is multiple of 4 and from there 64 it will be 1959 as end address.
GitHub lab file link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/single_memory_block/single_memory_block.sv
**GitHub log file link ** https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/single_memory_block/single_memory_block_log.log
Memory n equal partitions
Here we will try to divide the given memory into n equal parts of partitions.
Example:
class memory_block;
bit [31:0] mem_ram_start,mem_ram_end;
rand int mem_num_parts,mem_part_size;
rand bit [31:0] mem_part_start[];
constraint parts {mem_num_parts>=2;
mem_num_parts<=8;}
constraint part_size {mem_part_size==(mem_ram_end-mem_ram_start)/mem_num_parts+1;}
constraint patition {mem_part_start.size()==mem_num_parts;
foreach(mem_part_start[i])
if(i)
mem_part_start[i]==mem_part_start[i-1]+mem_part_size;
else
mem_part_start[i]==mem_ram_start;}
function display();
$display("\t RAM start addr : %0d ",mem_ram_start);
$display("\t RAM end addr : %0d ",mem_ram_end);
$display("\t No of Partitions : %0d ",mem_num_parts);
$display("\t Size of each partition : %0d ",mem_part_size);
$display("\n\t -----------partitions----------- ");
foreach(mem_part_start[i])
begin
if(i==mem_num_parts-1)
$display("\t Partition : %0d from %0d to %0d "\
,i+1,mem_part_start[i],mem_ram_end);
else
$display("\t Partition : %0d from %0d to %0d "\
,i+1,mem_part_start[i],mem_part_start[i+1]-1);
end
endfunction
endclass
module memory_n_equal_partitions();
memory_block memb=new();
initial
begin
memb.mem_ram_start=32'h0;
memb.mem_ram_end=32'h7ff;
void'(memb.randomize());
void'(memb.display());
end
endmodule
In the above example, we have taken a memory of 2KB and tried to make it into n equal partitions.
output:
Fig.33. output of the Memory n equal partitions
All the constraints are solved in parallel, here let's say first took a number between 2 & 8 i.e., 7 in this case, and then divide the whole memory by 7 i.e., 293 which will be almost equal to 2KB. Here we tried to assign the start address of every part using the array and each part with space 293 each.
Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_n_equal_partitions/memory_n_equal_partitions.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_n_equal_partitions/memory_n_equal_partitions_log.log
Memory n variable partitions
In the following example, we are trying to divide one block of memory into n partitions but need not to be equal.
Example:
class memory_block;
bit [31:0] mem_ram_start,mem_ram_end;
rand int mem_num_parts,mem_part_size[];
rand bit [31:0] mem_part_start[];
constraint parts {mem_num_parts>=2;
mem_num_parts<=8;}
constraint part_sizes {mem_part_size.size()==mem_num_parts;
mem_part_size.sum()==mem_ram_end-mem_ram_start+1;
foreach(mem_part_size[i])
mem_part_size[i] inside {16,32,64,128,256,512,1024,2048,4096};
}
constraint partition {mem_part_start.size()==mem_num_parts;
foreach(mem_part_start[i])
if(i)
mem_part_start[i]==mem_part_start[i-1]+mem_part_size[i-1];
else
mem_part_start[i]==mem_ram_start;}
function display();
$display("\t RAM start addr : %0d ",mem_ram_start);
$display("\t RAM end addr : %0d ",mem_ram_end);
$display("\t No of Partitions : %0d ",mem_num_parts);
$display("\n\t -----------partitions-----------");
foreach(mem_part_start[i])
begin
if(i==mem_num_parts-1)
$display("\t Partition : %0d with size :%0d from %0d to %0d "\
,i,mem_part_size[i],mem_part_start[i],mem_ram_end);
else
$display("\t Partition : %0d with size :%0d from %0d to %0d "\
,i,mem_part_size[i],mem_part_start[i],mem_part_start[i+1]-1);
end
endfunction
endclass
module memory_n_var_partitions();
memory_block memb=new();
initial
begin
memb.mem_ram_start=32'h0;
memb.mem_ram_end=32'h3fff;
void'(memb.randomize());
void'(memb.display());
end
endmodule
Here the memory size given is 16KB, then taking a constraint to divide by n parts i.e., 8 parts in this example. One more constraint is given such that the total sum of all the n variant partitions and allocated the particular sizes for partitions using foreach constraint.The divisions of the partitions are shown in the following diagram.
output:
Fig.34. the output of the Memory n variable partitions
**Github lab code link: ** https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_n_var_partitions/memory_n_var_partitions.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_n_var_partitions/memory_n_var_partitions_log.log
Memory partitions with spaces in between
In this example, it was similar to the previous example like dividing n variable partitions but here adding space parts also in between the partitions .
Example:
class memory_block;
bit [31:0] mem_ram_start,mem_ram_end;
rand int mem_num_parts,mem_part_size[],mem_space[];
rand bit [31:0] mem_part_start[];
constraint parts {mem_num_parts>4;
mem_num_parts<10;}
constraint part_sizes {mem_part_size.size()==mem_num_parts;
mem_space.size()==mem_num_parts-1;
mem_part_size.sum()+mem_space.sum()==mem_ram_end-mem_ram_start+1;
foreach(mem_part_size[i])
{
mem_part_size[i] inside {256,512,1024,2048};
if(i<mem_space.size())
mem_space[i] inside {64,256,512,1024};
}
}
constraint partition {mem_part_start.size()==mem_num_parts;
foreach(mem_part_start[i])
if(i)
mem_part_start[i]==mem_part_start[i-1]+mem_part_size[i-1];
else
mem_part_start[i]==mem_ram_start;}
function display();
$display("\tRAM start addr : %0d ",mem_ram_start);
$display("\tRAM end addr : %0d ",mem_ram_end);
$display("\tNo of Partitions : %0d ",mem_num_parts);
$display("\tmem_part_size : %0p",mem_part_size);
$display("\tmem_space : %0p",mem_space);
$display("\n\t %c[1;32m-----------%c[1;34mpartitions%c[1;32m------------%c[0m",27,27,27,27);
foreach(mem_part_start[i])
begin
if(i==mem_num_parts-1)
$display("\t%c[0;34m Partition : %0d with size :%0d from %0d to %0d %c[0m\n"
,27,i,mem_part_size[i],mem_part_start[i]+mem_space[i-1],mem_ram_end,27);
else if(i==0)
$display("\t%c[0;34m Partition : %0d with size :%0d from %0d to %0d %c[1;31m
\n\t\tspace_part : %0d bytes ",27,i,mem_part_size[i],mem_part_start[i],
mem_part_start[i+1]-1,27,mem_space[i]);
else
$display("\t%c[0;34m Partition : %0d with size :%0d from %0d to %0d %c[1;31m
\n\t\tspace_part : %0d bytes",27,i,mem_part_size[i],
mem_part_start[i]+mem_space[i-1],mem_part_start[i+1]-1,27,mem_space[i]);
end
endfunction
endclass
module memory_partition_with_spaces();
memory_block memb=new();
initial
begin
memb.mem_ram_start=32'h0;
memb.mem_ram_end=32'h23ff;
void'(memb.randomize()with{mem_num_parts==5;});
void'(memb.display());
end
endmodule
In the above example, memory is 9KB, we have taken 5 memory parts as inline constraints and space partition between every two parts, which means the total will be 9 parts. Here we are taking those all parts sum should be equal to 9215. The starting addresses of the memory partition are stored in one array and assigned different sizes using inside constraints and the same with the parts of the space also. The final memory block looks like the following diagram. If any of the constraints is not satisfying then there will be no randomization done and every value will be having default value i.e., 0
output:
Fig.35. Output of the Memory partitions with spaces in between
**Github lab code link: ** https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_partition_with_spaces/memory_partition_with_spaces.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_partition_with_spaces/memory_partition_with_spaces_log.log
Partitions for program and data
In the following example, memory is made into n partitions of program and data and spaces in between
Example:
class memory_block;
int total_mem;
rand int pgm[],data[],space[];
rand int max_pgms,max_pgm_size,max_data_size;
rand int num_pgm,num_data,num_space;
constraint nums {num_pgm inside {[1:max_pgms]};
num_data inside {[1:10]};
num_space inside {[1:10]};}
constraint maxs {max_pgms==10;
max_pgm_size==512;
max_data_size==128;}
constraint arrays {pgm.size()==num_pgm;
data.size()==num_data;
space.size()==num_space;}
constraint ram {foreach(pgm[i])
{
pgm[i] dist {[128:512]:=75,[32:64]:/20};
pgm[i]%4 ==0;
}
foreach(data[i])
{
data[i] inside {64};
}
foreach(space[i])
{
space[i] inside {64,128,512};
}
total_mem == pgm.sum()+data.sum()+space.sum();
}
function void display();
$display("\tTotal_RAM : %0d ",total_mem);
$display("\tNo.of Programs : %0d ",num_pgm);
$display("\tNo.of data's : %0d ",num_data);
$display("\tNo.of space's : %0d ",num_space);
$display("\tTotal_program_size : %0d , Total_data_size :\
%0d Total_space_size : %0d \n",pgm.sum(),data.sum(),space.sum());
foreach(pgm[i])
$display("\t %c[1;32m Program_%0d is of %0d bytes %c[0m",27,i,pgm[i],27);
foreach(data[i])
$display("\t %c[1;33m data_%0d is of %0d bytes %c[0m",27,i,data[i],27);
foreach(space[i])
$display("\t %c[1;34m space_%0d is of %0d bytes %c[0m",27,i,space[i],27);
endfunction
endclass
module memory_pgm_data();
memory_block mb;
initial
begin
mb =new();
mb.total_mem=6144;
void'(mb.randomize());
mb.display();
end
endmodule
In this, we have used constraints such that the total programs, data, and space of all sizes should be equal to the size of the memory block of 6KB.here we gave the constraints to choose the number of program blocks, data blocks, and space blocks. here it came as 10 programs, 2 data blocks, and 5 space blocks. And also the program, space, and data sizes are assigned using foreach and inside constraints.If any of the constraints fails then the whole randomization will be stopped.
output:
Fig.36. Output of the Partitions for program and data
**Github lab code link: ** https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_program_data/memory_pgm_data.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/constraint_memory_examples/memory_program_data/memory_pgm_data_log.log