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
      • The Solution-Space Mental Model
      • Bidirectional Solving
      • randc Internals & Limits
      • Solver Performance
      • Solver FAQ: Determinism & Vendor Differences
    • Debugging Randomization Failures
    • Interview Drills — Constraints and Randomization Q&A
  • 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

‹How the Constraint Solver Works
  1. Topics
  2. SystemVerilog
  3. Constraint Randomization — Interview-Critical Deep Dive
  4. How the Constraint Solver Works
  5. randc Internals & Limits

Part 3 · Constraint Randomization · Intermediate

randc Internals & Limits

Constrained cycles, covering pairs, randc beside rand, and history windows past the width cap.

On this page

    Why this matters

    A sweep meant to hit every slot-data pair hit only some of them. Two randc fields cycled independently, so pairs repeated before all of them came round.

    After this lesson you can: predict a constrained randc cycle, cover pairs with one wide randc, keep randc apart from rand rules, and replace randc with a history window when needed.

    rand vs randc showed the cycle on a plain field: every value once before any repeat. Real fields carry constraints and sit beside rand fields, and that is where the cycle gets interesting.

    A constrained randc cycles its legal values

    Constraints still apply to a randc field. The cycle is a permutation of the values that are legal, not of the whole type: a 4-bit field limited to 2 to 6 deals cycles of five.

    Cycles of five over 2 to 6.

    The standard also says the cycle restarts when the constraints on the field change. A test that switches a range mid-cycle should expect a fresh permutation, not the rest of the old one.

    Pairs need one wide randc

    Each randc field owns its own cycle. Two 2-bit randc fields each visit 0 to 3 every four calls, but nothing coordinates them, so sixteen calls do not cover all sixteen pairs. Verilator covered 12.

    Concatenate the pair into one 4-bit randc field and slice it. One cycle of sixteen calls then covers every pair exactly once.

    design.sv
    1
    2
    3
    4
    // snippet
    randc bit [1:0] a, b;          // 16 calls: some pairs repeat, some never come
    randc bit [3:0] ab;            // 16 calls: all 16 pairs, once each
    //   a = ab[3:2];  b = ab[1:0];

    randc beside rand

    The standard solves randc fields first and alone, then solves the rand fields with the randc values fixed. A rule linking the two can only bend the rand side, so when the dealt value leaves no legal partner, the call fails.

    design.sv
    1
    2
    3
    4
    5
    // snippet
    randc bit [3:0] slot;          // standard: dealt first, then fixed
    rand  bit [3:0] data;
    constraint c { data > slot; }  // slot == 15 leaves no 4-bit data
    // Standard: once per 16 calls the cycle deals 15 and randomize() returns 0.
    Predict first Under the standard's order, how many of 64 calls to the class above fail? What did Verilator 5.048 do?

    About 4: the cycle deals 15 once per 16 calls. Verilator solved slot together with data, never dealt 15, and failed none. Its cycle had quietly shrunk to 15 values.

    Neither behaviour is what you want. Keep a randc field free of rules that tie it to rand fields, or limit it directly with slot inside {[0:14]} so every tool cycles the same set.

    Past the width cap

    A cycle needs memory for every value, so the standard lets tools cap randc width; the cap must be at least 8 bits. Beyond it, and whenever you need weights, keep a history queue and exclude it with inside. The window can slide, and the field stays an ordinary rand field.

    Need

    Choice

    Every value of one narrow field

    randc on that field

    Every pair of two fields

    One wider randc field, sliced

    Wide values, or weights, with no recent repeats

    rand plus a history queue and !(v inside {used})

    Weighted values

    rand plus dist; dist is illegal on randc

    The bench runs all four cases: four cycles of the constrained field, the pair coverage, the randc and rand trap, and a history window of 8 over 200 calls.

    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
    24
    25
    26
    27
    28
    class sub_cycle;
      randc bit [3:0] v;
      constraint c { v inside {[2:6]}; }          // the cycle covers the 5 legal values
    endclass
    
    class two_cyclers;
      randc bit [1:0] a, b;                       // two independent cycles
    endclass
    
    class one_cycler;
      randc bit [3:0] ab;                         // one cycle over all 16 pairs
    endclass
    
    class slot_trap;
      randc bit [3:0] slot;
      rand  bit [3:0] data;
      constraint c { data > slot; }               // no data value works when slot == 15
    endclass
    
    class no_repeat8;                             // history window in place of randc
      rand bit [3:0] v;
      bit [3:0] used[$];
      constraint c_new { !(v inside {used}); }
      function void post_randomize();
        used.push_back(v);
        if (used.size() > 8) void'(used.pop_front());
      endfunction
    endclass
    
    Terminal
    randc in 2..6: 6 5 3 4 2 | 5 4 2 6 3 | 6 4 5 3 2 | 3 4 6 2 5 |
    two 2-bit randc, 16 calls: 12 of 16 pairs
    one 4-bit randc, 16 calls: 16 of 16 pairs
    slot_trap, 64 calls: 0 failed, slot == 15 dealt 0 times
    history window of 8: 200 calls, no repeat inside the window
    PASS: constrained randc cycles over its legal values, one wide randc covers every pair, and the history window holds

    Common pitfall

    Tying a randc field to a rand field with a tight inequality gives intermittent failures under the standard and a silently shrunken cycle on Verilator. Both hide the bug; neither reports it clearly.

    Interview

    The favourite follow-up is the data > slot trap. It tests whether you know the cycle is dealt first and fixed, not negotiated with the rand side. Say what the standard does, then say you would keep the two apart.

    Check yourself Why is dist illegal on a randc field?

    Weights contradict once-per-cycle visiting. The cycle already fixes each value's long-run share at exactly once per cycle, so there is nothing left to weight.

    Remember

    • A constrained randc cycles over its legal values only.

    • Every pair of two fields needs one wider randc, sliced.

    • The standard deals randc first and fixed; a rule tying it to rand can fail.

    Rule of thumb: keep randc fields free of rules that tie them to rand fields.

    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.

    Two 2-bit randc fields covered 12 of 16 pairs in 16 calls; one 4-bit field covered 16. With data > slot, Verilator never dealt slot == 15 and never failed, where the standard deals it once per cycle and fails.

    Related topics

    • Solver Performance

    Previous

    85 / 259

    Next: Solver Performance

    Up next

    Up nextSolver Performance

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • The Solution-Space Mental Model
    • Solver FAQ: Determinism & Vendor Differences