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.

  1. Random function system
  2. 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 -
  1. We declare more than one constraint with the same name.
  2. 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

Untitled Diagram drawio (20)

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 -

  1. To limit the size of the dynamic array by using the keyword size in the constraint block.
  2. 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 

Lab link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/dyn_arr/dyn_arr.sv

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

lab link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/constraints/queue/queue_code.sv

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.

fff drawio

                          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.

fff-Page-2 drawio

                         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.

fff-Page-3 drawio

                         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.

fff-Page-4 drawio

                     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.

gggg drawio

                           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.

fff-Page-7 drawio

                        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.

fff-Page-6 drawio (2)

                             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.

fff-Page-8 drawio

                                     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:

solve before output 1

    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:
  1. can't use randc variables, as they were always allowed to solve first, if used then without solve-before is not considered.
  2. shouldn't have circular dependency i.e., solve value1 before value2 and solve value2 before value1, if so through error as shown below.

solve before error 1

                  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.

static gif

     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:

static constraint output 1

         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();

randomization diag 1

    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:

randomization 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:

pre randomization 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:

post randomization

    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:

only inline

      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:

class and inline output 1

     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:

conflict with inline

       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

constraint_conflict_error_output

         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
    Untitled Diagram drawio (10)

             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
    Untitled Diagram drawio (11)

             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

Untitled Diagram drawio

         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
Untitled Diagram drawio (12)

              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
Untitled Diagram drawio (13)

           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:

single memory output

single mem

      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:

mem n equal parts

n equal

      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:

mem n var parts output

mem n var parts

      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:

mem with spaces output

mem spaces

     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:

mem prgrm space 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