Lesson 12 of 1410 minBeginner

Advanced Constrained Random

solve-before, dist, soft constraints, and shaping the spread

Basic constraints get you legal values. Advanced constraints get you the right spread of values, where the bugs actually live - extreme sizes, rare combinations, biased mixes. The difference between a verifier who closes coverage and one who does not is almost always constraint craft.

dist - shaping the probability

The dist operator assigns relative weights so common cases dominate while rare cases still appear. With := every value in a set or range gets that weight each; with :/ the whole range shares the weight, split across its values. In the example below small lengths dominate, a band of medium lengths appears occasionally, and the maximum value is rare but never absent.

dist weights: small lengths dominate (70), medium band occasional (25), the max value is rare but never absent (5) (click to enlarge)
systemverilog
rand bit [7:0] len;
constraint len_c {
  len dist { [1:4]  :/ 70,   // the range 1..4 TOGETHER gets weight 70
             [5:64] :/ 25,   // 5..64 together gets weight 25
             255    := 5 };  // exactly 255 gets weight 5
}

solve-before and soft constraints

When one field depends on another, the order the solver picks them changes the distribution even though both orders are legal. solve A before B tells the solver to choose A first, then constrain B. Without it, the solver weighs all legal pairs equally, which biases the controlling field toward whichever value leaves its partner more freedom. A soft constraint, by contrast, expresses a preference rather than a law: it holds unless another constraint contradicts it, in which case it is silently dropped instead of failing randomization. That is how a base sequence sets defaults that a derived test overrides without editing the base - write soft addr == 0 in the base, and an inline addr inside {[16:32]} in the test simply wins.

systemverilog
rand bit       is_burst;
rand bit [7:0] len;
constraint c_dep {
  is_burst -> len > 16;       // bursts must be long
  solve is_burst before len;  // decide burst/not FIRST, then pick len
}
// Without solve-before the solver flattens over all legal (is_burst, len)
// pairs. is_burst==0 allows len 0..255 (256 values) but is_burst==1 allows
// only 17..255 (239 values), so is_burst==1 ends up LESS than 50%. Solving
// is_burst first makes burst vs not a fair coin before len is chosen.
Pro tip

Inline constraints written as randomize() with {...} ADD to the class constraints for that call; they do not replace them. To switch a class constraint off temporarily use constraint_mode(0) on it, and to stop a field randomizing use rand_mode(0). Knowing the difference between layering (with), softening so a rule yields (soft), disabling a constraint (constraint_mode), and freezing a field (rand_mode) is a classic interview separator - each changes the solver in a distinct way.

Watch out

solve-before changes the distribution but never the legal set, and it cannot rescue contradictory hard constraints. It also slows the solver. Reach for it only when a real dependency is skewing coverage, confirm the skew in the coverage report first, and prefer dist for plain weighting where no inter-field dependency exists.

Finished reading?

Mark it complete to track your progress through the path.

Get new lessons by email

New lessons, interview prep and real EDA tool workflows. No spam.

PrevNext