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.