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.
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.
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.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.
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.
Go further
Preparing for verification interviews? Practice the rounds companies actually run.
Get new lessons by email
New lessons, interview prep and real EDA tool workflows. No spam.