SysytemVerilog : Randomization And Constraints

       Hello , welcome back in this post we will see example on SystemVerilog randomization and constraints. Randomization means making something random , in this case it is variables or objects.and constraint means controlling randomization.

 
SystemVerilog Randomization: 
 

Random variables

The class variables which get random values on randomization are called random variables. In order to make variables as random variables, Class variables need to be declared using the rand and randc type-modifier keywords. 

Following types can be declared as rand and randc,

  • singular variables of any integral type

  • arrays

  • arrays size

  • object handle’s 

rand keyword

Variables declared with the rand keyword are standard random variables. Their values are uniformly distributed over their range.

rand bit [3:0] addr;

addr is a 4-bit unsigned integer with a range of 0 to 15. on randomization this variable shall be assigned any value in the range 0 to 15 with equal probability.


randc keyword

randc is random-cyclic. For the variables declared with the randc keyword, on randomization variable values don’t repeat a random value until every possible value has been assigned.

randc bit [3:0]addr;

in order to randomize the object variables, the user needs to call randomize() method.

example

object.randomize();

Example on rand and randc:

class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(20) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data=1001 addr=1100 rdn_wr=1
# KERNEL:    data=1101 addr=0110 rdn_wr=0
# KERNEL:    data=1011 addr=1010 rdn_wr=1
# KERNEL:    data=0000 addr=1001 rdn_wr=0
# KERNEL:    data=0001 addr=0101 rdn_wr=1
# KERNEL:    data=1011 addr=0111 rdn_wr=0
# KERNEL:    data=0101 addr=0001 rdn_wr=1
# KERNEL:    data=1101 addr=1101 rdn_wr=0
# KERNEL:    data=0011 addr=1110 rdn_wr=1
# KERNEL:    data=1001 addr=1000 rdn_wr=0
# KERNEL:    data=0000 addr=0100 rdn_wr=0
# KERNEL:    data=1000 addr=1011 rdn_wr=1
# KERNEL:    data=0000 addr=1111 rdn_wr=1
# KERNEL:    data=1101 addr=0011 rdn_wr=0
# KERNEL:    data=0101 addr=0010 rdn_wr=1
# KERNEL:    data=0011 addr=0000 rdn_wr=0
# KERNEL:    data=0001 addr=0010 rdn_wr=1
# KERNEL:    data=1011 addr=1100 rdn_wr=0
# KERNEL:    data=0000 addr=0001 rdn_wr=0
# KERNEL:    data=1011 addr=0000 rdn_wr=1
# KERNEL: ---------------------------------------------

*/

rand_mode method

The rand_mode() method is used to disable the randomization of a variable declared with the rand/randc keyword.

  • rand_mode(1) means randomization enabled

  • rand_mode(0) means randomization disabled

  • The default value of rand_mode is 1, i.e enabled

  • Once the randomization is disabled, it is required to make rand_mode(1) enable back the randomization

  • rand_mode can be called as SystemVerilog method, the randomization enables/disable status of a variable can be obtained by calling vairble.rand_mode().

  • the rand_mode method returns 1 if randomization is enabled else returns 0

syntax :  object_handle.variable_name.rand_mode(0);
Example:

// example 2: rand_mode() -> disable randomization
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        pkt.addr.rand_mode(0);

        $display("pkt.data.rand_mode() status   = %0b",pkt.data.rand_mode());
        $display("pkt.addr.rand_mode() status   = %0b",pkt.addr.rand_mode());
        $display("pkt.rdn_wr.rand_mode() status = %0b \n",pkt.rdn_wr.rand_mode());
        
        $display("---------------------------------------------");
        repeat(20) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule
/* output
# KERNEL: pkt.data.rand_mode() status   = 1
# KERNEL: pkt.addr.rand_mode() status   = 0
# KERNEL: pkt.rdn_wr.rand_mode() status = 1 
# KERNEL: 
# KERNEL: ---------------------------------------------
# KERNEL:    data=1001 addr=0000 rdn_wr=0
# KERNEL:    data=1101 addr=0000 rdn_wr=1
# KERNEL:    data=1101 addr=0000 rdn_wr=1
# KERNEL:    data=1111 addr=0000 rdn_wr=0
# KERNEL:    data=0000 addr=0000 rdn_wr=1
# KERNEL:    data=0001 addr=0000 rdn_wr=0
# KERNEL:    data=1011 addr=0000 rdn_wr=1
# KERNEL:    data=1101 addr=0000 rdn_wr=0
# KERNEL:    data=1101 addr=0000 rdn_wr=1
# KERNEL:    data=1111 addr=0000 rdn_wr=0
# KERNEL:    data=1001 addr=0000 rdn_wr=0
# KERNEL:    data=1000 addr=0000 rdn_wr=1
# KERNEL:    data=1000 addr=0000 rdn_wr=0
# KERNEL:    data=1111 addr=0000 rdn_wr=1
# KERNEL:    data=1101 addr=0000 rdn_wr=1
# KERNEL:    data=0111 addr=0000 rdn_wr=0
# KERNEL:    data=0011 addr=0000 rdn_wr=1
# KERNEL:    data=1101 addr=0000 rdn_wr=0
# KERNEL:    data=1011 addr=0000 rdn_wr=0
# KERNEL:    data=1110 addr=0000 rdn_wr=1
# KERNEL: ---------------------------------------------

*/

pre randomize and post randomize methods

  • On calling randomize(), pre_randomize() and post_randomize() functions will get called before and after the randomize call respectively

  • Users can override the pre_randomize() and post_randomize() functions

// example 3: pre_randomize() and post_randomize() methods
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    function void pre_randomize();
        $display("=============================================");
        $display("\tdata.rand_mode() status   = %0b",  data.rand_mode());
        $display("\taddr.rand_mode() status   = %0b",  addr.rand_mode());
        $display("\trdn_wr.rand_mode() status = %0b",rdn_wr.rand_mode());
        $display("=============================================");
    endfunction

    function void post_randomize(); // prints data,addr,rdn_wr
        $display("\t data=%4b addr=%4b rdn_wr=%0b\n",data,addr,rdn_wr);
    endfunction

endclass

module ex1;
    packet pkt;
    int loop_count=10;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        for(int i=0;i<loop_count;i++) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            if(i>5) begin
                pkt.rand_mode(0); //disable randomization
            end
        end
        $display("---------------------------------------------");
    end
endmodule

/*output
# KERNEL: ---------------------------------------------
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=1001 addr=1100 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=1101 addr=0110 rdn_wr=0
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=1011 addr=1010 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=0000 addr=1001 rdn_wr=0
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=0001 addr=0101 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=1011 addr=0111 rdn_wr=0
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 1
# KERNEL:   addr.rand_mode() status   = 1
# KERNEL:   rdn_wr.rand_mode() status = 1
# KERNEL: =============================================
# KERNEL:    data=0101 addr=0001 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 0
# KERNEL:   addr.rand_mode() status   = 0
# KERNEL:   rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL:    data=0101 addr=0001 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 0
# KERNEL:   addr.rand_mode() status   = 0
# KERNEL:   rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL:    data=0101 addr=0001 rdn_wr=1
# KERNEL: 
# KERNEL: =============================================
# KERNEL:   data.rand_mode() status   = 0
# KERNEL:   addr.rand_mode() status   = 0
# KERNEL:   rdn_wr.rand_mode() status = 0
# KERNEL: =============================================
# KERNEL:    data=0101 addr=0001 rdn_wr=1
# KERNEL: 
# KERNEL: ---------------------------------------------

*/


SystemVerilog : Constraints

As the name says random variable will get random value on randomization. In some situations it is required to control the values getting assigned on randomization, this can be achieved by writing constraints.

Constraint blocks

  • Constraint blocks are class members like tasks, functions, and variables

  • Constraint blocks will have a unique name within a class

  • Constraint blocks consist of conditions or expressions to limit or control the values for a random variable

  • Constraint blocks are enclosed within curly braces { }

  • Constraint blocks can be defined inside the class or outside the class like extern methods, constraint block defined outside the class is called as extern constraint block

syntax:

constraint <constraint_block_name> { <condition/expression>;

                                     ......

                                     <condition/expression>                                              }

// example 4 : basic constraint example
class packet;

    rand  bit [3:0] data;
    rand  bit [3:0] addr;
    randc bit     rdn_wr;

    function void print();           // prints data,addr,rdn_wr
        $display("\t data=%4b addr=%4b rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

    constraint data_range{data>5;    // on randomization value of data is between 6 and 11
                          data<12;
                         }
    constraint addr_range{addr<10;}  // on randomization value of addr will always <10

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(20) begin
            pkt.randomize();         // randomize variable declare as rand or randc
            pkt.print();             // print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data=1000 addr=0100 rdn_wr=1
# KERNEL:    data=0110 addr=0100 rdn_wr=0
# KERNEL:    data=0110 addr=1000 rdn_wr=1
# KERNEL:    data=1001 addr=0010 rdn_wr=0
# KERNEL:    data=0110 addr=0101 rdn_wr=1
# KERNEL:    data=0111 addr=0011 rdn_wr=0
# KERNEL:    data=1010 addr=0000 rdn_wr=0
# KERNEL:    data=1010 addr=0011 rdn_wr=1
# KERNEL:    data=1011 addr=0011 rdn_wr=0
# KERNEL:    data=0111 addr=0000 rdn_wr=1
# KERNEL:    data=1010 addr=1001 rdn_wr=0
# KERNEL:    data=0110 addr=1001 rdn_wr=1
# KERNEL:    data=1001 addr=0111 rdn_wr=0
# KERNEL:    data=0110 addr=0101 rdn_wr=1
# KERNEL:    data=1000 addr=0001 rdn_wr=1
# KERNEL:    data=0111 addr=0011 rdn_wr=0
# KERNEL:    data=1001 addr=0100 rdn_wr=1
# KERNEL:    data=1001 addr=0011 rdn_wr=0
# KERNEL:    data=1001 addr=1000 rdn_wr=0
# KERNEL:    data=0110 addr=0101 rdn_wr=1
# KERNEL: ---------------------------------------------

*/

 

inside operator

During randomization, it might require to randomize the variable within a range of values or within set of values or other than a range of values. this can be achieved by using constraint inside operator.

Syntax:

constraint constraint_name {variable inside{...};}

 

// example 5 : inside operator
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    function void print();            // prints data,addr,rdn_wr
        $display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

    constraint addr_range {addr inside{[10:15]};}  
    // on randomization value of addr remains between 10 and 15
    constraint data_range {data inside{[1:5]};  } 
    // on randomization value of data remains between 1 and 5
endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(10) begin
            pkt.randomize();       // randomize variable declare as rand or randc
            pkt.print();           // print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data= 2 addr=12 rdn_wr=1
# KERNEL:    data= 2 addr=11 rdn_wr=0
# KERNEL:    data= 2 addr=15 rdn_wr=1
# KERNEL:    data= 2 addr=13 rdn_wr=0
# KERNEL:    data= 1 addr=10 rdn_wr=1
# KERNEL:    data= 3 addr=14 rdn_wr=0
# KERNEL:    data= 1 addr=11 rdn_wr=1
# KERNEL:    data= 1 addr=12 rdn_wr=0
# KERNEL:    data= 5 addr=15 rdn_wr=0
# KERNEL:    data= 3 addr=13 rdn_wr=1
# KERNEL: ---------------------------------------------

*/

if else constraint

// example 6 : if else constraint
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;
    string         range;

    function void print();                        // prints data,addr,rdn_wr
        $display("\t range=%s data=%d addr=%d rdn_wr=%0b",range,data,addr,rdn_wr);
    endfunction

    // addr_range :: if range is low then addr<8
    //               if range is high then addr>8
    //               else addr is between 5 and 9

    constraint addr_range {if(range=="low")
                                addr<8;
                           else{
                               if(range=="high")
                                    addr>8;
                                else{
                                    addr inside{[5:9]};
                                    }
                                }
                           } 
endclass

module ex1;
    packet pkt1,pkt2;
    initial begin
        pkt1=new();
        pkt2=new();
        pkt1.range  =  "low";
        pkt2.range  = "high";
        $display("---------------------------------------------");
        repeat(10) begin
            pkt1.randomize();                      // randomize variable declare as rand or randc
            pkt1.print();                          // print values of variables
        end
        $display("\n---------------------------------------------\n");
        repeat(10) begin
            pkt2.randomize();                      // randomize variable declare as rand or randc
            pkt2.print();                          // print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
---------------------------------------------
 | range=low | data= 9 addr= 2 rdn_wr=1
 | range=low | data=11 addr= 3 rdn_wr=0
 | range=low | data=10 addr= 6 rdn_wr=1
 | range=low | data= 7 addr= 4 rdn_wr=0
 | range=low | data= 0 addr= 7 rdn_wr=1
 | range=low | data= 3 addr= 5 rdn_wr=0
 | range=low | data=10 addr= 1 rdn_wr=0
 | range=low | data= 3 addr= 0 rdn_wr=1
 | range=low | data= 0 addr= 5 rdn_wr=0
 | range=low | data= 9 addr= 3 rdn_wr=1

---------------------------------------------

 | range=high | data= 7 addr=12 rdn_wr=0
 | range=high | data= 2 addr=15 rdn_wr=1
 | range=high | data=14 addr=11 rdn_wr=0
 | range=high | data= 9 addr= 9 rdn_wr=1
 | range=high | data= 6 addr=13 rdn_wr=0
 | range=high | data= 4 addr=14 rdn_wr=1
 | range=high | data= 5 addr=10 rdn_wr=0
 | range=high | data=15 addr=13 rdn_wr=1
 | range=high | data= 5 addr=11 rdn_wr=0
 | range=high | data=11 addr=10 rdn_wr=1
---------------------------------------------

Note : Aldec Rivia Pro gives error so use VCS
*/

foreach constraints

SystemVerilog supports using the foreach loop inside a constraint block. using the foreach loop within the constraint block will make easy to constrain an array. 

// example 7 : foreach constraint-> array in assending order
// elements of array1 should increment by 1 
// elements of array2 should increment by 2
class packet;

    rand int array1[];
    rand int array2[];

    constraint array1_size {array1.size == 10;}
    constraint array2_size {array2.size == 15;}

    constraint order_array1 {foreach(array1[i]){
                                if(i==0){
                                    array1[i] inside{[1:5]};
                                    }
                                else{
                                    array1[i]==array1[i-1]+1;
                                }
                            }
                        }

    constraint order_array2 {foreach(array2[i]){
                                if(i==0){
                                    array2[i] inside{[1:5]};
                                    }
                                else{
                                    array2[i]==array2[i-1]+2;
                                }
                            }
                        }

    function void print(); 
        $display("\t array1=%p ",array1);
        $display("\t array2=%p ",array2);
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(5) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
# KERNEL: ----------------------------------------------------------------------------
# KERNEL:    array1='{4, 5, 6, 7, 8, 9, 10, 11, 12, 13} 
# KERNEL:    array2='{3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31} 
# KERNEL:    array1='{3, 4, 5, 6, 7, 8, 9, 10, 11, 12} 
# KERNEL:    array2='{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29} 
# KERNEL:    array1='{5, 6, 7, 8, 9, 10, 11, 12, 13, 14} 
# KERNEL:    array2='{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30} 
# KERNEL:    array1='{5, 6, 7, 8, 9, 10, 11, 12, 13, 14} 
# KERNEL:    array2='{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30} 
# KERNEL:    array1='{2, 3, 4, 5, 6, 7, 8, 9, 10, 11} 
# KERNEL:    array2='{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29} 
# KERNEL: ----------------------------------------------------------------------------

Interview question link : https://www.edaplayground.com/x/VAs4
*/

 

Disable constraint

Constraints in a class can be disabled using the constraint_mode method call. By default all the constraints will be enabled, during the randomization constraint solver will not consider the disabled constraints. the constraint disables method is similar to rand_mode() method.

constraint_mode() method

The constraint_mode() method can be used to disable any particular constraint block.

  • constraint_mode(1) means constraint block is enabled

  • constraint_mode(0) means constraint block is disabled

  • default value of constraint_mode is 1, i.e enabled

  • once the constraint block is disabled, it is required to make constraint_mode(1) enable back the constraint block

  • constraint_mode can be called as like SystemVerilog method, which returns the enable/disable status of a constraint block

syntax:
object_handle.constraint_block_name.constraint_mode(mode);
mode==1 : constraint block enable
mode==0 : constraint block disable
 
// example 8 : constraint_mode()
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    constraint addr_range{addr inside{2,4,8};}
    constraint data_range{data inside{2,4,8};}
    constraint           rdn_wr_cb{rdn_wr==0;}

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

    function void constraint_status();
        $display("---------------------------------------------");
        $display("\tconstraint :: addr_range=%0b",addr_range.constraint_mode());
        $display("\tconstraint :: data_range=%0b",data_range.constraint_mode());
        $display("\tconstraint :: rdn_wr_cb =%0b"rdn_wr_cb.constraint_mode());
        $display("---------------------------------------------");
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        pkt.constraint_status();
        
        $display("---------------------------------------------");
        
        repeat(5) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end
        
        pkt.addr_range.constraint_mode(0);
        pkt.rdn_wr_cb.constraint_mode(0);
        pkt.constraint_status();
        
        repeat(5) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end

        $display("---------------------------------------------");
    end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL:   constraint :: addr_range=1
# KERNEL:   constraint :: data_range=1
# KERNEL:   constraint :: rdn_wr_cb =1
# KERNEL: ---------------------------------------------
# KERNEL: ---------------------------------------------
# KERNEL:    data= 2 addr= 8 rdn_wr=0
# KERNEL:    data= 2 addr= 2 rdn_wr=0
# KERNEL:    data= 4 addr= 4 rdn_wr=0
# KERNEL:    data= 4 addr= 8 rdn_wr=0
# KERNEL:    data= 4 addr= 4 rdn_wr=0
# KERNEL: ---------------------------------------------
# KERNEL:   constraint :: addr_range=0
# KERNEL:   constraint :: data_range=1
# KERNEL:   constraint :: rdn_wr_cb =0
# KERNEL: ---------------------------------------------
# KERNEL:    data= 2 addr=15 rdn_wr=1
# KERNEL:    data= 8 addr= 4 rdn_wr=0
# KERNEL:    data= 2 addr= 9 rdn_wr=1
# KERNEL:    data= 2 addr= 5 rdn_wr=0
# KERNEL:    data= 8 addr=12 rdn_wr=0
# KERNEL: ---------------------------------------------

*/

static constraints

SystemVerilog static constraints are similar to static class properties. A constraint block can be defined as static by including the static keyword in its definition. constraint block with the static keyword followed by constraint keyword is called as a static constraint. the static constraint is shared across all the class instances.

  • only the mode change of static constraint will get affected in all the instances of a class

  • mode change is enable or disable of a constraint by constrain_mode() method

  • a static class can be enabled or disabled by any object handle of its class, mode change with one object handle will reflect all other objects of same class type

syntax:

static constraint constraint_name { ....; }

 

// example 9 : static constraint 
class packet;

    rand  bit [7:0] data;
    randc bit [7:0] addr;
    randc bit     rdn_wr;

    static constraint data_range {data inside{2,4,8,16,32,64,128};}
    static constraint addr_range {addr inside{2,4,8,16,32,64,128};}
    static constraint rdn_wr_cb  {rdn_wr==1;}
    
    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

    function void constraint_status();
        $display("---------------------------------------------");
        $display("\tconstraint :: addr_range=%0b",addr_range.constraint_mode());
        $display("\tconstraint :: data_range=%0b",data_range.constraint_mode());
        $display("\tconstraint :: rdn_wr_cb =%0b"rdn_wr_cb.constraint_mode());
        $display("---------------------------------------------");
    endfunction


endclass

module ex1;
    packet pkt1,pkt2;
    initial begin
        pkt1=new();
        pkt2=new();
        pkt1.constraint_status();
        
        $display("---------------------------------------------");
        repeat(5) begin
            pkt1.randomize(); //randomize variable declare as rand or randc
            pkt1.print();     //print values of variables
        end

        pkt1.constraint_mode(0);
        pkt2.constraint_status();

        repeat(5) begin
            pkt1.randomize(); //randomize variable declare as rand or randc
            pkt1.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
# KERNEL: ---------------------------------------------
# KERNEL:   constraint :: addr_range=1
# KERNEL:   constraint :: data_range=1
# KERNEL:   constraint :: rdn_wr_cb =1
# KERNEL: ---------------------------------------------
# KERNEL: ---------------------------------------------
# KERNEL:    data= 32 addr=  4 rdn_wr=1
# KERNEL:    data=  2 addr=  2 rdn_wr=1
# KERNEL:    data= 64 addr=128 rdn_wr=1
# KERNEL:    data=  2 addr=  8 rdn_wr=1
# KERNEL:    data=  8 addr= 32 rdn_wr=1
# KERNEL:    ---- pkt1.constraint_mode(0) -------
# KERNEL: ---------------------------------------------
# KERNEL:   constraint :: addr_range=0
# KERNEL:   constraint :: data_range=0
# KERNEL:   constraint :: rdn_wr_cb =0
# KERNEL: ---------------------------------------------
# KERNEL:    data=206 addr= 44 rdn_wr=0
# KERNEL:    data= 77 addr= 59 rdn_wr=1
# KERNEL:    data= 99 addr=229 rdn_wr=0
# KERNEL:    data=120 addr=254 rdn_wr=1
# KERNEL:    data=207 addr= 24 rdn_wr=1
# KERNEL: ---------------------------------------------

*/

inline constraint

Constraints will be written inside the class. inline constraint allows the user to add extra constraints to existing constraints written inside the class. inline constraints will be written outside the class i.e along with the randomize method call.

  • the inline constraint is written using with keyword

  • during randomization, constraint solver will consider both inline constraints and constraints written inside the class

  • the inline constraint will not override the constraints written inside the class

  • the inline constraint shouldn’t conflict with the constraint written inside the class, else it will lead to randomization failure

    • for example, constraint inside the class written as var < 5, and inline constraint written as var > 5

syntax : object.randomize() with{....};

// exaxmple 10 : inline constraint
class packet;

    rand  bit [3:0] data;
    randc bit [3:0] addr;
    randc bit     rdn_wr;

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

    constraint data_range {data inside{10:15};}
    constraint addr_range {addr<10;}

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(10) begin
            //randomize variable declare as rand or randc
            pkt.randomize()with{pkt.addr<4; pkt.data==12; pkt.rdn_wr==1;}; 
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data=12 addr= 0 rdn_wr=1
# KERNEL:    data=12 addr= 1 rdn_wr=1
# KERNEL:    data=12 addr= 2 rdn_wr=1
# KERNEL:    data=12 addr= 3 rdn_wr=1
# KERNEL:    data=12 addr= 3 rdn_wr=1
# KERNEL:    data=12 addr= 1 rdn_wr=1
# KERNEL:    data=12 addr= 0 rdn_wr=1
# KERNEL:    data=12 addr= 2 rdn_wr=1
# KERNEL:    data=12 addr= 1 rdn_wr=1
# KERNEL:    data=12 addr= 0 rdn_wr=1
# KERNEL: ---------------------------------------------


*/

Functions inside Constraints

In some cases constraint can’t be expressed in a single line, in such cases function call can be used to constrain a random variable. calling the function inside the constraint is referred to as function in constraints.

  • The function will be written outside the constraint block

  • Constraint logic shall be written inside the function as function definition and function call shall be placed inside the constraint block

  • Functions shall be called before constraints are solved, and their return values shall be treated as state variables.

constraint constraint_name {var=function_call();}


// example 11  : function inside constrtaint
// description : if enable==1 then data should increment by 2 
//               continously  , else data should increment by 1
//               continously 
class packet;

    rand  bit [7:0] data;
    randc bit     enable;

    constraint data_range{data == f_enable(enable);}

    function bit[7:0] f_enable(bit enable);      
        static int unsigned count1=0;
        static int unsigned count2=2;
        if(enable==1) begin
              f_enable=count2+2;
              count2=count2+2;
        end
          else begin
              f_enable=count1+1;
              count1++;
          end
    endfunction:f_enable

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%d enable=%0b",data,enable);
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(20) begin
            pkt.randomize(); //randomize variable declare as rand or randc
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule
/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data=  4 enable=1
# KERNEL:    data=  1 enable=0
# KERNEL:    data=  2 enable=0
# KERNEL:    data=  6 enable=1
# KERNEL:    data=  8 enable=1
# KERNEL:    data=  3 enable=0
# KERNEL:    data= 10 enable=1
# KERNEL:    data=  4 enable=0
# KERNEL:    data= 12 enable=1
# KERNEL:    data=  5 enable=0
# KERNEL:    data= 14 enable=1
# KERNEL:    data=  6 enable=0
# KERNEL:    data=  7 enable=0
# KERNEL:    data= 16 enable=1
# KERNEL:    data= 18 enable=1
# KERNEL:    data=  8 enable=0
# KERNEL:    data= 20 enable=1
# KERNEL:    data=  9 enable=0
# KERNEL:    data= 22 enable=1
# KERNEL:    data= 10 enable=0
# KERNEL: ---------------------------------------------

*/

Soft constraints

SystemVerilog constraints declared with the keyword soft is called as soft constraints. any conflict between class constraint and inline constraint leads to a randomization failure, from this it is clear that it is not possible to override the class constraint by inline constraint. Some test scenarios demand to override the constraints, this can be done by writing a soft keyword in class constraint.

A soft constraint is a constraint on a random variable, which allows overriding the constraint.

constraint constraint_name {soft variable {condition}; }

// example 12 : soft constraint
class packet;

    rand  bit [7:0] data;
    randc bit [7:0] addr;
    randc bit     rdn_wr;

    constraint data_addr {soft data==addr;}
    constraint rdn_wr_cb {soft rdn_wr==1;}

    function void print(); // prints data,addr,rdn_wr
        $display("\t data=%d addr=%d rdn_wr=%0b",data,addr,rdn_wr);
    endfunction

endclass

module ex1;
    packet pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------------");
        repeat(10) begin
            pkt.randomize();     //randomize variable declare as rand or randc 
            pkt.print();         //print values of variables
        end
        $display("overriding constraints");
        $display("---------------------------------------------");
        repeat(10) begin
              //randomize variable declare as rand or randc
            pkt.randomize()with{pkt.rdn_wr==0; pkt.addr==pkt.data+1;}; 
            pkt.print();     //print values of variables
        end
        $display("---------------------------------------------");
    end
endmodule

/* output
# KERNEL: ---------------------------------------------
# KERNEL:    data=188 addr=188 rdn_wr=1
# KERNEL:    data=151 addr=151 rdn_wr=1
# KERNEL:    data=110 addr=110 rdn_wr=1
# KERNEL:    data=158 addr=158 rdn_wr=1
# KERNEL:    data=192 addr=192 rdn_wr=1
# KERNEL:    data=162 addr=162 rdn_wr=1
# KERNEL:    data=221 addr=221 rdn_wr=1
# KERNEL:    data=238 addr=238 rdn_wr=1
# KERNEL:    data= 19 addr= 19 rdn_wr=1
# KERNEL:    data= 56 addr= 56 rdn_wr=1
# KERNEL:   overriding constraints
# KERNEL: ---------------------------------------------
# KERNEL:    data=215 addr=216 rdn_wr=0
# KERNEL:    data=  6 addr=  7 rdn_wr=0
# KERNEL:    data=107 addr=108 rdn_wr=0
# KERNEL:    data= 30 addr= 31 rdn_wr=0
# KERNEL:    data= 66 addr= 67 rdn_wr=0
# KERNEL:    data=228 addr=229 rdn_wr=0
# KERNEL:    data= 13 addr= 14 rdn_wr=0
# KERNEL:    data= 59 addr= 60 rdn_wr=0
# KERNEL:    data= 46 addr= 47 rdn_wr=0
# KERNEL:    data=224 addr=225 rdn_wr=0
# KERNEL: ---------------------------------------------


*/

Unique constraints

SystemVerilog constraint defined with the keyword unique is called as a unique constraint. On randomization, unique values to set of variables or unique elements to an array can be generated by using unique constraints.

Unique constraint allows us to,

  • Generate unique values across the variables

  • Generate unique elements in an array (Fixed Size Array, Dynamic Array, Associative array and Queue)

constraint c_name {unique {variables/array}; }

// example 13 : unique constraints

class packet;

    rand int unsigned array1[];
    rand int unsigned array2[];

    constraint array1_size{array1.size==10;}
    constraint array2_size{array2.size==10;}

    constraint c_array1{unique{array1};
                        foreach(array1[i])
                            array1[i]<10;
                        }
  
    constraint c_array2{foreach(array2[i])
                            array2[i]<10;
                        }
  
    function void print();
      $display("\t array1[Unique]=%p",array1);
      $display("\t array2[Normal]=%p",array2);
    endfunction

endclass

module ex13;
    packet pkt;
    initial begin
        pkt=new();
        repeat(10) begin
            pkt.randomize(); // randomize variable
            pkt.print();     // print array
        end
    end

endmodule

/* output
# KERNEL:    array1[Unique]='{2, 9, 0, 7, 3, 8, 1, 5, 6, 4}
# KERNEL:    array2[Normal]='{7, 1, 8, 3, 0, 5, 9, 8, 8, 7}
# KERNEL:    array1[Unique]='{9, 4, 7, 5, 1, 8, 3, 6, 0, 2}
# KERNEL:    array2[Normal]='{4, 1, 6, 3, 6, 5, 2, 5, 7, 7}
# KERNEL:    array1[Unique]='{6, 9, 2, 3, 0, 5, 8, 4, 1, 7}
# KERNEL:    array2[Normal]='{9, 6, 8, 3, 0, 2, 3, 1, 1, 7}
# KERNEL:    array1[Unique]='{8, 9, 1, 2, 6, 5, 7, 3, 4, 0}
# KERNEL:    array2[Normal]='{6, 5, 5, 0, 1, 1, 2, 1, 6, 8}
# KERNEL:    array1[Unique]='{8, 9, 1, 5, 7, 2, 0, 6, 4, 3}
# KERNEL:    array2[Normal]='{7, 5, 9, 6, 5, 5, 6, 5, 3, 0}
# KERNEL:    array1[Unique]='{9, 8, 2, 5, 4, 3, 7, 6, 1, 0}
# KERNEL:    array2[Normal]='{3, 1, 8, 5, 8, 4, 3, 6, 3, 7}
# KERNEL:    array1[Unique]='{2, 5, 3, 9, 7, 6, 8, 0, 1, 4}
# KERNEL:    array2[Normal]='{2, 2, 5, 5, 1, 0, 9, 3, 6, 9}
# KERNEL:    array1[Unique]='{1, 7, 6, 0, 9, 5, 8, 2, 3, 4}
# KERNEL:    array2[Normal]='{6, 8, 2, 9, 2, 0, 9, 8, 5, 0}
# KERNEL:    array1[Unique]='{9, 8, 2, 7, 3, 6, 0, 4, 1, 5}
# KERNEL:    array2[Normal]='{2, 6, 4, 5, 5, 8, 7, 3, 2, 8}
# KERNEL:    array1[Unique]='{9, 0, 6, 7, 8, 4, 1, 5, 3, 2}
# KERNEL:    array2[Normal]='{7, 4, 0, 7, 5, 3, 1, 9, 0, 2}

*/

Bidirectional constraints

SystemVerilog constraints are solved bidirectionally, which means constraints on all random variables will be solved parallel.

Consider a constraint example,

constraint c_name { if(a == 0) b == 1;

                    else       b == 0; 

                  }

We see that ‘b’ is dependent on ‘a’.
but constraint solver see’s it as ‘a’ is dependent on ‘b’ and ‘b’ is dependent on ‘a’.
i.e if ‘b’ is inline constrained as ‘1’, in order to satisfy, ‘a’ should take the value ‘0’.

// example 14 : bidirectional constraint
class example;
    rand bit a;
    rand bit b;

    constraint c_block{if(a==1) b==0;
                        else b==1;
                      }
    function void print();
        $display("\t a=%0b b=%0b",a,b);
    endfunction
endclass

module ex14;
    example pkt;
    initial begin
        pkt=new();
        $display("---------------------------------------");
        repeat(10) begin
            pkt.randomize();
            pkt.print();
        end
        $display("---------------------------------------");
        repeat(10) begin
          pkt.randomize()with{pkt.b==0;};
            pkt.print();
        end
        $display("---------------------------------------");
    end
endmodule

/* output
# KERNEL: ---------------------------------------
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=0 b=1
# KERNEL:    a=0 b=1
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=0 b=1
# KERNEL:    a=0 b=1
# KERNEL:    a=1 b=0
# KERNEL:    a=0 b=1
# KERNEL: ---------------------------------------
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL:    a=1 b=0
# KERNEL: ---------------------------------------
*/

solve before

Solve before is the constraint property. solve before is used inside the constraint block to specify the order of constraint solving. If the variables are dependent, due to the bidirectional nature of constraints value of one variable will influence the value of another variable.

  • solve before constraints are used to force the constraint solver to choose the order in which constraints are solved.

  • constraint solver will give equal weight-age to all the possible values. i.e On multiple randomization solver should assign all the possible values.

class pakcet;

rand bit a;

rand bit [3:0] b;

constraint a_b { (a == 1) -> b == 0; }

endclass

Possible value of,

a -> 0 and 1; // 2 possible values

b -> 0 to 15; // 16 possible values

As ‘b’ value ranges 0:15, Probability of getting b == 0 is very less.
so it will impact the value of a,  i.e if value of b != 0, which will lead to value of ‘a’ to become ‘0’.

What if in some situations it is required to generate a value of ‘a’ to ‘1’ more frequently. by using ‘solve before’ it can be done.

Writing below constraint will direct solver to solve ‘a’ first, so more frequently a will take value of 1.

constraint sab { solve a before b;}

 

// example 15 : solve before
class packet;
    rand bit       a;
    rand bit [3:0] b;
   
    constraint sab { solve a before b;}
    constraint a_b { (a == 1) -> b == 0;}
  endclass
   
module inline_constr;
    initial begin
      packet pkt;
      pkt = new();
      repeat(10) begin
        pkt.randomize();
        $display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
      end
    end
endmodule

Thank You for reading have a nice day 😀😀😇.

Share:
Copyright © VLSI Verification Concepts . Designed by OddThemes