Part 3 · Constraint Randomization · Intermediate
Constraint Randomization — Interview-Critical Deep Dive
Constrained-random stimulus from first principles: rand/randc, constraint operators, solver semantics, array randomization, debug, transaction modeling, and the interview drill modules.
Why constrained-random verification exists
Directed tests prove the scenarios you thought of . Constrained-random tests find the scenarios you did not — corner-case combinations of address, length, alignment, and timing that no engineer would enumerate by hand. You declare the legal space with constraints, and the solver picks random points inside it. Coverage then tells you which parts of that space were actually visited.
This section is interview-critical : constraint randomization and SVA are the two most heavily probed areas in verification interviews. Interviewers test not just syntax but solver semantics — why solve...before changes distribution but not the solution set, why a null handle silently skips randomization, why randc cycles restart. Every topic below explains the WHY, not just the syntax.
Directed vs constrained-random
DIRECTED TESTING CONSTRAINED-RANDOM TESTING
engineer writes each case engineer writes RULES (constraints)
│ │
▼ ▼
test_write_addr0.sv constraint c_legal {
test_write_addr4.sv addr inside {[0:1023]};
test_read_burst16.sv len inside {1, 4, 8, 16};
... (one file per scenario) addr % 4 == 0;
│ }
▼ │
covers N scenarios ▼
(N = number of tests written) solver picks random legal points
every seed = new scenario set
│ │
▼ ▼
effort grows linearly coverage closes the loop:
with scenarios "what did random actually hit?"
Directed: high effort per scenario, zero surprise
Random: low effort per scenario, finds unplanned corner casesTopic map
Nine topics build from basic semantics up to interview drills. Topics 1–7 are the technical ladder; topics 8 and 9 are explicit interview drill modules.
┌─────────────────────────────────────────────────────────────────────────┐
│ CONSTRAINT RANDOMIZATION — topic map │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. RANDOMIZATION BASICS │
│ rand vs randc │ randomize() │ pre/post │ std::randomize │ stability │
│ │
│ 2. CONSTRAINT OPERATORS │
│ inside │ dist │ -> and if-else │ solve-before │ soft │ functions │
│ │
│ 3. DYNAMIC CONTROL │
│ constraint_mode │ rand_mode │ inline with {} │ disable + override │
│ │
│ 4. ARRAY RANDOMIZATION │
│ dynamic arrays │ size constraints │ foreach │ unique │ sum/element │
│ │
│ 5. SOLVER DEEP DIVE │
│ solution space │ uniformity │ ordering │ bidirectionality │ failures │
│ │
│ 6. RANDOMIZATION DEBUG │
│ failure triage │ check-only mode │ contradictions │ tool messages │
│ │
│ 7. TRANSACTION MODELING │
│ packet/bus txn classes │ layered constraints │ knobs │ reuse │
│ │
│ 8. INTERVIEW CONSTRAINT PATTERNS ◄── interview drill module │
│ classic puzzles: unique, sorted, sum-to-N, alignment, one-hot ... │
│ │
│ 9. INTERVIEW Q&A ◄── interview drill module │
│ rapid-fire semantics questions with model answers │
│ │
└─────────────────────────────────────────────────────────────────────────┘Topics
Randomization Basics — rand/randc semantics, the randomize() call, pre/post hooks, std::randomize, nested objects, and random stability.
Constraint Operators — inside, dist, implication, if-else, solve-before, soft constraints, and functions in constraints.
Dynamic Control — constraint_mode(), rand_mode(), inline randomize-with, and constraint override by inheritance.
Array Randomization — sizing, foreach element constraints, unique, sum(), and array-of-objects patterns.
Solver Deep Dive — how the solver builds the solution space, uniformity guarantees, and bidirectional constraint semantics.
Randomization Debug — triaging randomize() failures, check-only mode, finding contradicting constraints.
Transaction Modeling — building realistic bus/packet transaction classes with layered, reusable constraints.
Interview Constraint Patterns — the classic write-a-constraint puzzles asked in interviews, with worked solutions.
Interview Q&A — rapid-fire semantics questions (return values, randc cycles, soft priority) with model answers.
How the solver thinks
Every randomize() call is a constraint-satisfaction problem. The solver gathers all active constraints simultaneously (they are declarative, not sequential), intersects them into a legal solution space, and picks one point with uniform probability over that space — unless dist or solve-before reshapes the distribution. Holding this mental model is what separates a syntax-level answer from a senior-level answer in interviews.
HOW THE SOLVER THINKS
rand bit [7:0] a, b;
constraint c1 { a < 100; }
constraint c2 { a + b == 120; } all constraints considered
constraint c3 { b inside {[20:80]}; } AT THE SAME TIME
│
▼
┌──────────────────────────────┐
│ 1. COLLECT active constraints│ constraint_mode(0) ones excluded
│ + inline with {} clauses │ rand_mode(0) fields become state vars
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ 2. INTERSECT into │ (a,b) pairs satisfying ALL of:
│ SOLUTION SPACE │ a<100, a+b==120, 20<=b<=80
│ │ → a in [40,99], b = 120 - a
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ 3. PICK uniformly at random │ every legal (a,b) equally likely
│ (dist / solve-before │ unless distribution is reshaped
│ reshape the weighting) │
└──────────────┬───────────────┘
▼
success: fields updated, returns 1
no legal point exists: fields UNCHANGED, returns 0Interview drill modules
Topics 8 and 9 are deliberately structured as drill modules , not theory. Topic 8 walks through the classic write-a-constraint puzzles (unique values, sorted arrays, sum-to-N, address alignment, one-hot) with solver-level explanations of each solution. Topic 9 is a rapid-fire Q&A bank covering the semantics traps interviewers use to separate candidates. Work topics 1–7 first; then drill 8–9 until the answers are reflexive.
Key takeaways
Constraints are declarative: the solver sees all active constraints at once and solves them simultaneously — order in the class is irrelevant.
randomize() returns 1 on success and 0 on contradiction; on failure the fields keep their old values — always check the return.
The solver picks uniformly over the legal solution space; dist and solve-before reshape probability without changing what is legal.
Topics 1–7 build the mental model; topics 8–9 are interview drills — practice until constraint puzzles are reflexive.
Common pitfalls
Treating constraints as sequential code — they are simultaneous equations, and writing them as 'steps' leads to wrong expectations about distribution.
Ignoring the randomize() return value — a contradictory constraint silently leaves stale data in the transaction.
Assuming a rand field of a null class handle gets randomized — null handles are silently skipped, a classic interview trap.
Memorizing syntax without solver semantics — interviews probe WHY solve-before changes distribution, not just how to type it.