Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
    • Randomization Basics: rand, randc & randomize()
    • Constraint Operators & Expressions
    • Dynamic Constraint Control
    • Randomizing Arrays and Queues
    • How the Constraint Solver Works
    • Debugging Randomization Failures
    • Interview Drills — Constraints and Randomization Q&A
      • Even/Odd, Alignment & Divisibility
      • Powers of 2, One-Hot & Bit Games
      • Unique Values & Ordering
      • Sum, Checksum & Distribution Drills
      • Dependent-Field Puzzles
      • Q&A: rand, randc & randomize()
      • Q&A: dist, inside, soft, solve-before
      • Q&A: Controlling Randomization
      • Q&A: Arrays & Nested Objects
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Interview Drills — Constraints and Randomization Q&A
  1. Topics
  2. SystemVerilog
  3. Constraint Randomization — Interview-Critical Deep Dive
  4. Interview Drills — Constraints and Randomization Q&A
  5. Dependent-Field Puzzles

Part 3 · Constraint Randomization · Intermediate

Dependent-Field Puzzles

Drill: a rule with two arms, a product that cannot wrap, and an FSM move table.

On this page

    Why this matters

    A DMA test generated transfers far larger than its buffer. size * count wrapped in 32 bits, and the wrapped product sat comfortably under the limit.

    After this lesson you can: write two-armed rules, products that cannot wrap, and complete state-move tables.

    The three prompts

    Drill 1. rand bit is_read and rand bit [4:0] len: reads are 1 to 4 beats, writes are 8 to 16.

    Drill 2. rand bit [31:0] size, count: both at least 1, and size * count at most 4096.

    Drill 3. rand state_e cur, next over IDLE, REQ, WAIT, DONE: next is a legal move from cur. IDLE goes to IDLE or REQ, REQ to WAIT or IDLE, WAIT to WAIT or DONE, and DONE only to IDLE.

    Write the three answers before opening the reveal. Copy the starter into the Code Lab, fill in each empty answer_c, and run it on Verilator. The grader solves each class hundreds of times and checks every result, then pins a few values that must be legal; it prints ok or the first rule your answer broke.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // Drill starter: write each answer_c, then run it.
    // Drills: fields that depend on each other.
    typedef enum bit [1:0] {IDLE, REQ, WAIT, DONE} state_e;
    
    class drill1;                                   // reads are 1 to 4 beats, writes 8 to 16
      rand bit       is_read;
      rand bit [4:0] len;
      constraint answer_c { /* your answer here */ }
    endclass
    
    class drill2;                                   // size and count at least 1, size * count at most 4096
      rand bit [31:0] size, count;
      constraint answer_c { /* your answer here */ }
    endclass
    
    class drill3;                                   // next is a legal move from cur
      rand state_e cur, next;
      constraint answer_c { /* your answer here */ }
    endclass
    
    Predict first Before you write drill 2: why can size * count <= 4096 pass with size and count both near two billion?

    Both operands are 32 bits, so the product is computed in 32 bits and wraps. A product of 2^32 wraps to 0, which is at most 4096. Widen the operands before multiplying.

    Check yourself Reveal one set of answers (open only after your own run)

    One set of answers, run through the same grader:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // Drills: fields that depend on each other.
    typedef enum bit [1:0] {IDLE, REQ, WAIT, DONE} state_e;
    
    class drill1;                                   // reads are 1 to 4 beats, writes 8 to 16
      rand bit       is_read;
      rand bit [4:0] len;
      constraint answer_c { if (is_read) len inside {[1:4]}; else len inside {[8:16]}; }
    endclass
    
    class drill2;                                   // size and count at least 1, size * count at most 4096
      rand bit [31:0] size, count;
      constraint answer_c { size inside {[1:4096]}; count inside {[1:4096]}; size * count <= 4096; }
    endclass
    
    class drill3;                                   // next is a legal move from cur
      rand state_e cur, next;
      constraint answer_c {
        cur == IDLE -> next inside {IDLE, REQ};
        cur == REQ  -> next inside {WAIT, IDLE};
        cur == WAIT -> next inside {WAIT, DONE};
        cur == DONE -> next == IDLE;
      }
    endclass
    
    Terminal
    drill 1, two-armed length: ok
    drill 2, product that cannot wrap: ok
    drill 3, legal state moves: ok
    PASS: all 3 drills right

    Why these answers

    Spelling

    Arms covered

    Use it when

    if / else

    Both, in one construct

    Two-sided maps like read against write

    Paired implications

    Both, only if you write both

    Spec tables with one row per case

    Single implication

    One: the other side stays free

    Never for two-sided conditions

    A lone is_read -> len inside {[1:4]} leaves writes free to take any length, including 1 to 4 and 17 to 31. The grader's random results catch that within a few calls.

    Two answers are right. Bound each factor first: with both at most 4096, the 32-bit product is at most 2^24 and cannot wrap. Or widen the operands, 64'(size) * 64'(count) <= 4096, unsigned, since 32 by 32 bits always fits in 64. Casting after the multiply is too late, because the wrap has already happened.

    The reveal uses the bounds for a practical reason: Verilator's solver took about 39 seconds on the 64-bit product and under 5 on the bounded form. The grader caught the plain size * count <= 4096 at once, with a true product above 3 × 10^18 that had wrapped to a small number.

    A move table needs a row for every state. A rand enum only takes its named values (IEEE 1800 18.3), so a rand state_e never becomes an unnamed code; the hole appears when states are plain bit [1:0] fields, and then a whitelist such as cur inside {IDLE, REQ, WAIT} closes it.

    Common pitfall

    Three faults share one root: a missing implication arm, a cast applied after the multiply, and a named state with no row in the table. Each compiles cleanly and each corrupts stimulus silently.

    Interview

    The anti-pattern list for this topic: lone implications, late casts, off-by-one wrap guards, partial FSM tables, and unchecked randomize() returns. Name the set before the interviewer asks.

    Remember

    • A lone implication leaves its other arm free.

    • Widen operands before multiplying, never the result after.

    • A move table needs a row for every state.

    Rule of thumb: every condition gets both arms written down.

    How this was checked

    Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown. Verilator prints a harmless WIDTHTRUNC warning for if (!obj.randomize()), because randomize() returns an int, and an UNSATCONSTR warning when a solve fails on purpose. Icarus 13 does not support constraints.

    Each starter was run with its answers left empty, and its grader reported all three drills wrong; each revealed answer passed the same grader. The graders also caught an unwidened size * count and an over-tight even rule when tried.

    Related topics

    • Q&A: rand, randc and randomize()

    Previous

    96 / 259

    Next: Q&A: rand, randc & randomize()

    Up next

    Up nextQ&A: rand, randc & randomize()

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Even/Odd, Alignment & Divisibility
    • Powers of 2, One-Hot & Bit Games
    • Unique Values & Ordering