Part 3 · Constraint Randomization · Intermediate

dist: Weighted Distributions

:= vs :/ weight semantics with exact probability math, dist vs inside, and dist over ranges.

dist constrains AND weights

The dist operator does two jobs at once, and interviewers test both. First, like inside, it constrains the variable to the listed set — a value not in the dist list is illegal. Second, it assigns relative weights so the solver no longer picks uniformly. The probability of each item is its weight divided by the sum of all weights. Weights are relative, not percentages — { a := 1, b := 3 } and { a := 25, b := 75 } are identical distributions.

systemverilog
class arb_txn;
  rand bit [1:0] grant;

  // grant ∈ {0,1,2} only (3 is now ILLEGAL — dist constrains the set)
  constraint grant_c {
    grant dist { 0 := 1, 1 := 2, 2 := 5 };
  }
endclass
// Total weight = 1 + 2 + 5 = 8
// P(grant==0) = 1/8 = 12.5%
// P(grant==1) = 2/8 = 25%
// P(grant==2) = 5/8 = 62.5%
// P(grant==3) = 0   — not in the dist set, never produced

The “dist constrains” half is the trap: people read dist as “prefer these values” and are surprised when other values vanish entirely, or when a dist contradicts another constraint and randomize() fails.


:= vs :/ — the semantics that decide the interview

On a single value, := and :/ behave identically. The difference appears on ranges : := gives the weight to each value in the range , while :/ gives the weight to the range as a whole , divided equally among its members. Same syntax shape, completely different total weight.

systemverilog
rand bit [7:0] x;

// Case A: := on a range — weight PER VALUE
constraint a_c { x dist { [1:5] := 10, 9 := 50 }; }
// [1:5] contributes 5 values × 10 = 50 weight; 9 contributes 50
// Total = 100
// P(x==1) = 10/100 = 10%   (each of 1..5 is 10%)
// P(x==9) = 50/100 = 50%

// Case B: :/ on a range — weight for the WHOLE range
constraint b_c { x dist { [1:5] :/ 10, 9 := 50 }; }
// [1:5] contributes 10 TOTAL, split as 2 per value; 9 contributes 50
// Total = 10 + 50 = 60
// P(x==1) = 2/60 ≈ 3.33%   (each of 1..5)
// P(x==9) = 50/60 ≈ 83.3%
diagram
WEIGHT ACCOUNTING:  [1:5] with weight 10, plus 9 with weight 50

  := (per value)                      :/ (per range)
  ─────────────────                   ─────────────────
  1 ──► 10                            1 ──► 10/5 = 2
  2 ──► 10                            2 ──► 2
  3 ──► 10        range total = 50    3 ──► 2     range total = 10
  4 ──► 10                            4 ──► 2
  5 ──► 10                            5 ──► 2
  9 ──► 50                            9 ──► 50
  ─────────────                       ─────────────
  sum = 100                           sum = 60
  P(9) = 50%                          P(9) ≈ 83.3%

Mnemonic: “:= equals each, :/ divides.” Whenever a dist contains a range, recompute the total weight before quoting any probability — the range silently multiplies (:=) or splits (:/).


dist vs inside, and combining them

inside gives a uniform pick over a set; dist gives a weighted pick over a set. Because dist also constrains, combining dist with other constraints intersects as usual: weights apply only to values that survive the intersection, and the surviving weights renormalize.

systemverilog
class err_txn;
  rand bit [3:0] resp;

  // 90% OKAY traffic, ~10% spread over error codes
  constraint resp_c {
    resp dist { 0 :/ 90, [1:3] :/ 10 };   // 0=OKAY, 1..3 = error kinds
  }

  // A test adds: resp != 2  (intersection removes value 2)
  // Surviving weights: 0 → 90, 1 → 10/3, 3 → 10/3   (total ≈ 96.67)
  // P(resp==0) = 90/96.67 ≈ 93.1%  — renormalized, not still exactly 90%
endclass

This renormalization is worth saying out loud in an interview: dist weights are relative within the final legal set, so removing values shifts every remaining probability. A dist is never a guarantee of exact percentages once other constraints intersect with it. Also note dist applies only to rand variables — it is illegal on randc, whose cycling semantics already dictate the distribution.


Worked interview problem

The most common form of the question: “Given this constraint, what is the exact probability of each value?” Practice the three-step routine — expand ranges, sum weights, divide.

systemverilog
rand bit [7:0] v;
constraint q_c { v dist { 1 := 40, [2:4] := 60, [5:6] :/ 40 }; }

// Step 1 — expand:
//   1            → 40
//   2, 3, 4      → 60 EACH  (:= is per value)  → 180 from the range
//   5, 6         → 40 TOTAL (:/ splits)        → 20 each
// Step 2 — total weight = 40 + 180 + 40 = 260
// Step 3 — divide:
//   P(1) = 40/260  ≈ 15.4%
//   P(2) = P(3) = P(4) = 60/260 ≈ 23.1% each
//   P(5) = P(6) = 20/260 ≈ 7.7% each
//   All other values of v: probability 0 (dist constrains the set)

Interview angle

What interviewers ask

  • “Difference between := and :/?” — identical on single values; on ranges, := is per element and :/ is split across the range. Always demonstrate with a numeric example.

  • “Difference between dist and inside?” — both constrain to a set; dist additionally weights. inside is uniform.

  • “Exact probability of each value?” — expand, sum, divide. Showing the arithmetic matters more than the answer.

  • “Can you use dist with randc?” — no; randc cycles through all values, so weighting is meaningless and illegal.

  • “Is dist a soft preference?” — no; values outside the dist list are illegal, and contradictions with other constraints fail randomize().

Key takeaways

  • dist both constrains the set and weights the pick — values not listed have probability zero.

  • := assigns weight per value in a range; :/ splits the weight across the range.

  • Probability = item weight / total weight; weights are relative, not percentages.

  • Other constraints intersect with dist and renormalize the surviving weights.

  • dist is legal only on rand variables, never randc.

Common pitfalls

  • Reading := on a range as a total weight — a wide range silently dominates the distribution.

  • Treating dist as a preference — it removes unlisted values from the solution set entirely.

  • Quoting dist percentages after another constraint pruned the set — weights renormalize.

  • Applying dist to a randc variable — a compile error many people only meet in interviews.

  • Putting weight 0 on a value and expecting it to remain legal — weight 0 means never generated.