System Verilog Distribution Constraints

In SystemVerilog, distribution constraints allow precise control over the randomization of variables by assigning weights to specific values or ranges of values. The dist operator is central to this capability, with two forms—:= and :/—each offering distinct ways of distributing weights.

This article explains the difference between the := and :/ operators, how they work with values and ranges, and provides examples to illustrate their behavior in real-world scenarios.

Overview of the dist Operator

The dist operator is used in constraints to assign weights to values or ranges. The value and weights can be constant or variables. This determines how likely a random variable is to take on certain values or fall within specific ranges. The difference between := and :/ lies in how weights are distributed across ranges. The default weight for an unspecified value should be 1.

Syntax:

variable dist { value_or_range := weight, value_or_range :/ weight };

:= (Weighted Distribution):

  • Assigns the entire weight to a value or to each value in a range.

:/ (Proportional Distribution):

  • Splits the weight equally across all values in a range.

Difference Between := and :/

Feature:= (Weighted Distribution):/ (Proportional Distribution)
Weight for Single ValueWeight is assigned directly to the valueWeight is assigned directly to the value
Weight for RangeEntire weight is applied to each value in the rangeWeight is divided equally among all values in the range
Use CaseWhen every value in the range should have equal weightWhen the weight should be shared among values in the range

Examples using := operator

class InclusiveDistExample;
  rand int value;

  constraint value_dist {
    value dist {
      10 := 5,  // Assign weight 5 to value 10
      20 := 8,  // Assign weight 8 to value 20
      [30:40] := 3  // Assign weight 3 to values in range 30 to 40
    };
  }
endclass

module test();
  
  initial begin
    repeat(10) begin
      InclusiveDistExample obj = new();
      obj.randomize();
      $display("Random value: %0d", obj.value);
    end
  end
  
endmodule

Explanation:

  • 10 := 5: Value 10 will have a weight of 5.
  • 20 := 8: Value 20 will have a weight of 8.
  • [30:40] := 3: Each value in the range 30-40 has a weight of 3.
  • The value will be chosen based on these weights.

Output:

Random value: 10
Random value: 31
Random value: 31
Random value: 20
Random value: 35
Random value: 10
Random value: 20
Random value: 20
Random value: 40
Random value: 37

Examples using :/ operator

class InclusiveDistExample;
  rand int value;

  constraint value_dist {
    value dist {
      10 :/ 5,  // Assign weight 5 to value 10
      20 :/ 8,  // Assign weight 8 to value 20
      [30:40] :/ 10  // Assign weight 10/11 to each value in range 30 to 40
    };
  }
endclass

module test();
  
  initial begin
    repeat(10) begin
      InclusiveDistExample obj = new();
      obj.randomize();
      $display("Random value: %0d", obj.value);
    end
  end
  
endmodule

Explanation:

  • 10 :/ 5: Value 10 will have a weight of 5.
  • 20 :/ 8: Value 20 will have a weight of 8.
  • [30:40] :/ 10: Each value in the range 30-40 has a weight of 10/11 as there is total 11 elements.
  • The value will be chosen based on these weights.

Output:

Random value: 10
Random value: 31
Random value: 31
Random value: 20
Random value: 35
Random value: 10
Random value: 20
Random value: 20
Random value: 20
Random value: 37

Best Practices for Using dist Operators

  1. Choose := for Uniformity in Ranges: Use := when you want every value in a range to have the same weight as a single value.
  2. Use :/ for Proportional Sharing: Use :/ when the weight should be distributed proportionally among values in a range.
  3. Mix Wisely: Combine := and :/ carefully to meet specific distribution requirements.
  4. Test for Balance: Simulate and verify that the distribution matches your expectations.