← Design Verification Interviews

Interview Question · Code Writing

A Permutation Built by Constraints

L0 FresherL1 Juniorsystemverilograndomizationpuzzles
  • Asked at Micron
  • Asked at Intel

The Question

The interviewer asks

Write constraints for an array of four integers that is always a permutation of 0, 1, 2 and 3. Then tell me how you would check your answer.

Reveal the Model Answer

Keep every element in range and make them all different: foreach (a[i]) a[i] inside {[0:3]}; and unique {a};. Four distinct values from a set of four must be a permutation. Check it by randomizing many times and OR-ing 1 << a[i] over the elements: the mask must be 4'b1111 on every call.

Two Rules Make a PermutationCandidate arrays checked against the two constraints. Arrows show candidates moving; a candidate that breaks a rule goes to Ruled out.
Two rules make a permutationCandidate arrays checked against the two constraints. Arrows show candidates moving; a candidate that breaks a rule goes to Ruled out. component Candidates a[0] to a[3], any intvalues component a[i] inside{[0:3]} every element inrange component unique {a} no two elements equal component Legal set the 24 orderings of0, 1, 2, 3 component Ruled out for example 7, 0, 1, 2or 0, 0, 3, 3 component Check every call OR of 1 << a[i] mustbe 4'b1111 holdsholdsbreaks rangebreaks unique
Read the diagram as text
  • Candidates: a[0] to a[3], any int values
  • a[i] inside {[0:3]}: every element in range
  • unique {a}: no two elements equal
  • Legal set: the 24 orderings of 0, 1, 2, 3
  • Ruled out: for example 7, 0, 1, 2 or 0, 0, 3, 3
  • Check every call: OR of 1 << a[i] must be 4'b1111
  • Candidates → a[i] inside {[0:3]}
  • a[i] inside {[0:3]} → unique {a}: holds
  • unique {a} → Legal set: holds
  • a[i] inside {[0:3]} → Ruled out: breaks range
  • unique {a} → Ruled out: breaks unique
  • Legal set → Check every call

Either rule alone is not enough. Four different values from a set of four must be a permutation.

Two small constraint blocks, so a test can switch either off.
class perm;
  rand int a[4];
  constraint in_range { foreach (a[i]) a[i] inside {[0:3]}; }
  constraint distinct { unique {a}; }
endclass

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Fresher)

A good fresher answer writes the range rule and the unique rule. It checks the result in a loop instead of trusting one call.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

What IfProve ItBreak ItCompare

  1. A Permutation Built by Constraints
  2. What IfA One-Hot Value Without the Onehot FunctionL0 FresherL1 Junior

    Constrain an 8-bit x to have exactly one bit set, without using $onehot.

    Reveal the Model Answer

    Write x != 0 && (x & (x - 1)) == 0;. Subtracting 1 clears the lowest set bit and sets the bits below it. So the AND is zero only when at most one bit was set. x != 0 removes the zero case. $countones(x) == 1 says the same thing more readably.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    "(x & (x - 1)) == 0 alone means exactly one bit set."

    It means at most one bit set; zero passes too. The twin generates zeros until x != 0 is added.

    Run It

    200 calls with only the power-of-two test.

    RUNVerilator · simulator service
    Edit the code, then run it
    Expected: FAIL: x = 0 also satisfies (x & (x - 1)) == 0, so zero was generated
    See the Fix
    class onehot_gen;
      rand bit [7:0] x;
      constraint c { x != 0 && (x & (x - 1)) == 0; }   // the fix: also exclude 0
    endclass
    module tb;
      onehot_gen g = new;
      int zeros = 0, bad = 0;
      initial begin
        repeat (200) begin
          void'(g.randomize());
          if (g.x == 0) zeros++;
          if ($countones(g.x) != 1) bad++;
        end
        if (bad == 0) $display("PASS: every value had exactly one bit set");
      end
    endmodule
    

    Prints: PASS: every value had exactly one bit set

  3. CompareUnique Versus Pairwise InequalityL1 Junior

    Compare unique {a}; with foreach (a[i]) foreach (a[j]) if (i < j) a[i] != a[j];.

    Reveal the Model Answer

    They allow exactly the same solutions. unique states the intent in one line and also accepts a mix of scalars and arrays, such as unique {a, b, c};. You write the nested loop on an older tool. Its i < j guard stops it from comparing an element with itself.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    Writes the nested loop without the i < j (or i != j) guard.

    Then a[i] != a[i] is required for every element, which is impossible, and every call fails.

    Source IEEE 1800-2017 §18.5.8.1

  4. What IfA Strictly Increasing Random ArrayL1 Junior

    Asked if they finish quickly

    Constrain a five-element array to be strictly increasing, with every element between 1 and 20.

    Reveal the Model Answer

    Use a range plus a guarded neighbour rule: foreach (a[i]) { a[i] inside {[1:20]}; if (i > 0) a[i] > a[i-1]; }. The guard keeps index 0 from referring to an element that does not exist. The solver then picks uniformly among all increasing sequences, rather than sorting random values afterwards.

    Self-Check

    Tick each key point you covered in your answer.

  5. Break ItA Sum Constraint That WrapsL1 JuniorL2 Mid-Level

    Now make the elements bit [4:0] and add a.sum() == 50. What can go wrong?

    Reveal the Model Answer

    The sum() method returns the element type, so the total is computed in 5 bits and wraps at 32. The solver may then satisfy the constraint with a sum that is 50 modulo 32, or fail to find one. Write a.sum() with (int'(item)) == 50 so the addition happens in 32 bits.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    "It worked on Verilator, so the narrow sum is fine."

    Verilator 5.052 widens the uncast form, so the bug cannot appear there; the standard result has the element width.

    Source Lesson 2.4 simulator note (Verilator 5.052 widens the uncast sum)

  6. Prove ItSolve 5.7.1: Aligned Burst RequestSimulator-graded

    Show it, don't just say it: this Silicon Lab problem is graded by the simulator.

    Open Problem 5.7.1

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"unique {a} alone gives a permutation of 0..3."

It only makes the four values distinct; with int elements they can be anything. The twin counts results that are not permutations.

Run It

Fifty calls with unique {a} and no range constraint.

RUNVerilator · simulator service
Edit the code, then run it
Expected: FAIL: unique only makes the values distinct; nothing kept them inside 0..3
See the Fix
class perm;
  rand int a[4];
  constraint c { foreach (a[i]) a[i] inside {[0:3]}; unique {a}; }   // range plus distinct values
endclass
module tb;
  perm p = new;
  int bad = 0;
  initial begin
    repeat (50) begin
      int mask;
      void'(p.randomize());
      mask = 0;
      foreach (p.a[i]) if (p.a[i] >= 0 && p.a[i] <= 3) mask |= 1 << p.a[i];
      if (mask != 4'b1111) bad++;
    end
    $display("non-permutations in 50 calls: %0d", bad);
    if (bad == 0) $display("PASS: every result was a permutation of 0..3");
  end
endmodule

Prints: non-permutations in 50 calls: 0 PASS: every result was a permutation of 0..3

Missed Corner

"Check the result by testing that the sum is 6."

Different multisets share a sum: 0, 0, 3, 3 also adds to 6. The twin uses the sum as the constraint and gets repeats.

Run It

The range plus a.sum() == 6 instead of unique.

RUNVerilator · simulator service
Edit the code, then run it
Expected: FAIL: a sum of 6 also allows repeats such as 0, 0, 3, 3

Half-Truth

"Fill 0..3 in post_randomize() and shuffle it."

That works for this array, but the solver no longer controls it. A test's inline with constraint on a is then silently ignored.

Learn It, Then Prove It