Randomization is a process of producing random values of the mentioned data type.

As SystemVerilog also deals with objects, the $random method from Verilog is not sufficient for randomizing an object.

Need for Randomization

As per the increasing complexity of the design, there are high chances to have more bugs in the design when it is written for the first time. To verify DUT thoroughly, a verification engineer needs to provide many stimuli. There can be multiple cross combinations of variables in a real system. So, it is not possible practically to write directed cases to verify every possible combination. So, it is very much required to have randomization in the verification testbench.

Advantages of Randomization

  1. It has the capability of finding hidden bugs with some random combination.
  2. Constraint-based randomization provides possible random values instead of a complete random range.
  3. It provides flexibility to have random values based on user-defined probability.
  4. SystemVerilog randomization provides flexibility to disable randomization for a particular variable in a class as well as disable particular constraints based on the requirement.
  5. It saves time and effort in verification instead of writing a test for every possible scenario.

    rand and randc keywords

    To randomize a class object, the following keywords are used while declaring class variables.

    1. rand
    2. randc

    rand Keyword

    On randomizing an object, the rand keyword provides uniformly distributed random values.

    rand bit [4:0] value;

    On randomizing, any values within 5’h0 to 5’h1F will be generated with equal probability

    randc Keyword

    On randomizing an object, the randc keyword provides random value without repeating the same value unless a complete range is covered. Once all values are covered, the value will repeat. This ensures that to have all possible values without repeating the same value unless every value is covered.

    randc bit [1:0] value;   // Possible values = 0, 1, 2, 3

    Possible random value generated:  2, 3, 1, 0, 3, 2, 0, 1..

    Constraints in randomization

    In a design-specific scenario, DUT works only for a particular range of inputs as per feature. To satisfy this need, constraint becomes extremely important in randomization. Constraint block represents constraints for random variables. 

    Syntax for constraint block:

    constraint <constraint_name> {<expression/ condition>; }
    1. Constraints block must have a unique name within a class.
    2. Constraint block can call a function to get constraint values as the return value from the function.
    3. Constraints are written inside curly braces.
    4. For a particular class, constraint blocks can be written inside a class or outside a class using extern keywords.
    5. Expressions or conditions can be written inside a constraint block.

    Inside keyword in constraints

    The inside keyword is helpful when randomized values have to be in the provided range.

    The provided range in a bracket can be constant, parameter, define, or variable.

    Syntax:

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

    To specify range of values

    constraint <constraint_name> {<variable> inside {[10:20]}; }

    To specify set of values

    constraint <constraint_name> {<variable> inside {40, 70, 80}; }

    Combination of set of values and range

    constraint <constraint_name> {<variable> inside {4, 7, 8, [10:20], 25, 30, [40:70]}; }

    Define based range in constraint

    constraint <constraint_name> {<variable> inside {[`START_RANGE:`END_RANGE]}; }

    Variable based range in constraint

    constraint <constraint_name> {<variable> inside {[<var1>:<var2>]}; }

    Parameter based range in constraint

    constraint <constraint_name> {<variable> inside {[<param1>:<param2>]}; }

    Inverted inside constraint

    constraint <constraint_name> { !(<variable> inside {[10:20]}); }

    Inside constraint Example

    All various patterns of the inside keyword are mentioned in the below example.

    `define START_RANGE 35
    `define END_RANGE 45
    
    class seq_item #(parameter int p1 = 10, p2 = 20);
      rand bit [7:0] value1;
      rand bit [7:0] value2;
      rand bit [7:0] value3;
      rand bit [7:0] value4;
      rand bit [7:0] value5;
      rand bit [7:0] value6;
      rand bit [7:0] value7;
      
      constraint value1_c {value1 inside {[10:20]};} // constant value based range
      constraint value2_c {value2 inside {40,70, 80};} // Set of values
      constraint value3_c {value3 inside {[10:20], 21, 23, [25:30], 40, 70, 80};} // Mix
      constraint value4_c {!(value4 inside {[100:200]});} // Inverted Range
      constraint value5_c {value5 inside {[value1:value2]};} // range using variable 
      constraint value6_c {value6 inside {[`START_RANGE:`END_RANGE]};} // Define based range
      constraint value7_c {value7 inside {[p1:p2]};} // parameter based range
    endclass
    
    module constraint_example;
      seq_item #(100, 200) item;
      
      initial begin
        item = new();
        
        repeat(3) begin
          item.randomize();
          $display("value1 = %0d, value2 = %0d, value3 = %0d, value4 = %0d, value5 = %0d, value6 = %0d, value7 = %0d", item.value1, item.value2, item.value3, item.value4, item.value5, item.value6,  item.value7);
        end
      end
    endmodule

    Output:

    value1 = 16, value2 = 80, value3 = 16, value4 = 207, value5 = 24, value6 = 37, value7 = 111
    value1 = 20, value2 = 70, value3 = 20, value4 = 222, value5 = 69, value6 = 37, value7 = 184
    value1 = 14, value2 = 80, value3 = 14, value4 = 96, value5 = 29, value6 = 42, value7 = 149

    Implement 'randc' function in SystemVerilog

    In the below implementation, the my_randc function is used to mimic randc behavior for 3 bits ‘data‘  variable. The ‘mask‘ having a width of 8 bits (= 2^3) is used to check whether the data value has been covered already or not.

    module tb;
      bit [2:0] data;  // variable which provide random value
      bit [7:0] mask;
    
      function bit [2:0] my_randc;
        while(1) begin
          data = $random;
          if(!mask[data]) begin
            mask[data] = 1;
            return data;
          end
          else if(&mask) begin 
            mask = 0;
            mask[data] = 1;
            break;
          end
        end
        return data;
      endfunction
      
      initial begin
        repeat(3) begin
          repeat(8)
            $display("data = %0d", my_randc());
          $display("------------");
        end
      end
    endmodule
    data = 4
    data = 1
    data = 3
    data = 5
    data = 2
    data = 6
    data = 7
    data = 0
    ------------
    data = 5
    data = 4
    data = 3
    data = 2
    data = 0
    data = 6
    data = 7
    data = 1
    ------------
    data = 0
    data = 1
    data = 3
    data = 6
    data = 4
    data = 2
    data = 5
    data = 7
    ------------

    System Verilog Tutorials