Constraint

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.


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.

Note:

  • seed is the value given while randomization saying that for particular seed the values of rand variables should not change and is given using -sv_seed<value> at CMD line.
  • No matter how many times you compile and run the file ,same random values are given again and again.
  • If you want different values at different times the change seed.

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.

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.

3.std::randomize#

std::randomize() is also called a Scope-Randomize Function. Scope randomize gives you the ability to randomize variables that are not members of a Class and even multiple variables can be randomized at the same time with either of the methods shown below.

The scope randomize is generally done for the local variables which are declared without the rand function and also users can specify random constraints for it. Even it can accept the inline constraints using the “with” clause. Below there are some syntaxes for declaring the std::randomize function.

  • Syntax:
std::randomize (variable);
std::randomize (variable) with { constraint's; };

std::randomize (variable-1, variable-2 ... variable-n);
std::randomize (variable-1, variable-2 ... variable-n) with { constraint's; };
  • Example:
module std_random;
bit [3:0]a;
bit [3:0]b;
bit [3:0]c;
bit [3:0]d;
bit [3:0]e;
 initial begin
  repeat(4)begin
  void'( std ::randomize(a));
  $display("value of a  %d",a);
  void'(std::randomize(b) with  {b>6; a<12;});
  $display("value of b :%d",b);
  void'(std::randomize(c,d) with  {c<4; d<3;});
  $display("value of c :%d and d  %d ",c,d);
  void'(std::randomize(e) with  {e inside {[1:4]};});
   $display("value of e :%d ",e);
   end
 end
endmodule

In the above example, we declared 5 local variables. These variables are randomized using std::randomize(), even all the variables can be randomized at the same time by passing multiple variables as arguments to the randomize() function. Even we can specify our own inline constraints to the randomizing variables.

This is an advantage for randomizing the local variables and even in the module we can randomize multiple variables at the same time just like class_handle.randomize();
Output:
std_rand

Using std::randomize inside the class:#

If we randomize the variables using class_handle.randomize only those variables which are of type rand and randc are randomized. In order to overcome this we can use std::randomize(this), which will randomize all the variables of that class. But, the variables which are local to any function are not randomized, this is the main drawback of this std::randomize() function. For this local variables we need to randomize again using std function.

  • Example:
class test;
  int a;
  rand bit [2:0]b;
constraint c1 { a >= 2;a <= 9; }
 function void display();
  int c;
if (std::randomize(this));
  $display("using std_randomize %0d , %d",a,b);
   if (randomize(a))
     $display("randomize(a) %0d",a);
  if (std::randomize(a));
     $display("using std_randomize(a) %0d",a);
  if(std::randomize(b))
    $display("using std_randomize b: %0d",b);
  if (std::randomize(c) with {c>1;
                            c<4;})
     $display("using std_randomize with constraint,c: %0d",c);
 if (this.randomize());
      $display("this randomize %0d %d",a,b);

    endfunction

  endclass

 module tb;
test t;
 initial begin
  t=new();
repeat (3)
t.display();
end
endmodule

In this example, we declared int type ‘a’ and rand bit type ‘b’ variables in the class test and inside the display function we declared local variable ‘c’. So, when we use std::randomize(this) only the ‘a’ and ‘b’ variables are randomized leaving the local variable ‘c. Even we can randomize the local variable and can give inline constraints by using “with” clause.

  • Output: class_rand

From the above output we can see the exact operation of std:randomize(), this function is strictly applicable only to the local variables. Even though there is constraint defined for variable ‘a’ within the class, std::randomize(a) is not considering that global constraint as it is totally dependent on its inline constraint. Since there is no inline constraint for std::randomize(a), the simulator is considering the entire range of ‘a’.

Whereas for variable ‘c’ we have declared a inline construct whose range is between 1 to 4. Hence, the output of c is between this range.

Limitations:

  1. std::randomize(variable) considers only its inline constraint, or else it will consider its declared default range for randomization.
  2. std::randomize(this) is applicable only for randomizing the class variables. But this function will not consider the locally declared variables inside any function, hence there is more chance of missing some data during randomization.
  3. std::randomize(variable) is applicable only for locally declared variables. It cannot be accessed in any other functions or class.

4.Constraint Block#

Constraint blocks are the class methods just like function and task. Constraints have a unique name in the class.

  • Syntax
constraint [constraint_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.

Over-riding Constraints#

Constraints Override

Here in this overriding of constraint, if we have the same constraint name in the parent class and the child class, then we can say that our constraint is overridden in the child class using the child class handle.

  • Example

Let us understand through an example:

class parent;
  rand byte a;
  rand byte b;

  constraint cons{a==0;b==5;}
endclass:parent

class child extends parent;
  constraint cons{a==5;b==8;}
endclass:child


module top;
  initial begin
  child t1;
  t1= new;
  for(int i=0;i<3;i++)
  begin
    if (!t1.randomize()) begin
            $display("Randomization failed");
          end
   else begin
   $display("Iteration = %0d value of the a=%0d value of b=%0d",i,t1.a,t1.b);
end
end
end
endmodule:top   

If you use different constraint names in the parent class and child class, that time randomization is failed. because the child class is extended from the parent so we can’t use different constraint names in the class.

if we want to override the constraint we have to use the same constraint name for both parent and child classes. then we can override the parent things easily from the child class.

In the above example, we declared a class and the name is the parent and we are declaring one more class that extends from the parent class. Inside the parent, were writing constraints that are a=0 and b=5. then inside the child, we write the value to variables a=5 and b=8 and both are the same constraint name. and
were create the handle for the child and doing the randomization now the parent class constraint value is getting the override. the output of child constraint values is executed a=5 & b=8.

  • Output

Untitled Diagram drawio (20)

In the above example, in the 3 iterations, only the child constraints values are executed values are a= 5 and b=8.


5.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.
  • 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.
  • 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.

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.

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

log file link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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/production/constraints/queue/queue_code.sv

output log file link


6.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

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.


7..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

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.


8.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

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.

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

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.


9.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

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.


10.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

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.


11.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)

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.


12.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


13.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 {variable_1==1 -> variable_2==1;solve variable_1 before variable_2}

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

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%.

  • 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


14.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  constraint_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

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.


15.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

module randomization();

   generator gen = new();
  initial
  begin

      $display("\tCalling Randomize....");
      if(gen.randomize())
        $display("\tvalue: %0d \tRandomization successful",gen.value);
      else
        $display("\tvalue: %0d \tRandomization Failed",gen.value);

        $display("\tCalling Randomize....");

      if(gen.randomize()with{value==2;})
        $display("\tvalue: %0d \tRandomization successful",gen.value);
      else
        $display("\tvalue: %0d \tRandomization Failed",gen.value);
  end
endmodule
  • output:

randomization output

In the above example calling randomize function and after randomization was done taking constraint that value must be 5 if randomization is successful else prints randomization failed and the previous random value will be present in the variable.
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 and has the previous random value i.e., 5.

Note: If the randomization fails in the first iteration then the value of the variable will be the default value of the variable. If randomization fails after some successful randomization then the previous randomized value will be present in the variable.

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

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.

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

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.


16.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

As per the inline constraint, the value must be 3 so in both iterations the value is the same.

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

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

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

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.

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

17.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<5;});
       $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)

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.

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)

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.


#

18.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.

  • Syntax:
object_handle.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

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.


19.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)

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.


20.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)

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 6; therefore, the probability of taking the first branch is (1/6) i.e. 0.166. The probability of taking the second is (2/6) i.e. 0.33, and the probability of taking the third is (3/6) i.e. 0.5. Each call to the randcase statement will return a random number in the range from 0 to 3.


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

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.


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

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.


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


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


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

#