← RTL Design Interviews

Interview Question · Code Writing

A Priority Encoder with Wildcard Case Items

L1 JuniorL2 Mid-Levelcase statementscasezpriority encoder
  • Asked at Micron

The Question

The interviewer asks

Write a 4-bit priority encoder. idx is the number of the highest set bit of req, and valid says any bit is set.

Reveal the Model Answer

Give idx and valid defaults first, so there is no latch. Then list wildcard items from the top bit down: 4'b1???, 4'b01??, 4'b001?, 4'b0001. Items are checked in order, so the first match gives the highest set bit. Use case inside, or casez if your tools lack it, and never casex. Test all 16 values.

Wildcard Items, Tried in OrderArrows show the order the items are tried for one value of req. A match ends the search.
Wildcard items, tried in orderArrows show the order the items are tried for one value of `req`. A match ends the search. component req[3:0] the input component 4'b1??? idx = 3 component 4'b01?? idx = 2 component 4'b001? idx = 1 component 4'b0001 idx = 0 component No match defaults: valid = 0 component idx, valid the highest set bit tried firstno matchno matchno matchno matchmatchmatch
  1. Top bit first

    With req = 0110, item 1??? fails because bit 3 is 0.

  2. First match wins

    Item 01?? matches, so idx is 2. Bit 1 is also set, but the search has stopped.

  3. Nothing set

    With req = 0000 no item matches. The defaults give valid = 0 and no latch.

Read the diagram as text
  • req[3:0]: the input
  • 4'b1???: idx = 3
  • 4'b01??: idx = 2
  • 4'b001?: idx = 1
  • 4'b0001: idx = 0
  • No match: defaults: valid = 0
  • idx, valid: the highest set bit
  • req[3:0] → 4'b1???: tried first
  • 4'b1??? → 4'b01??: no match
  • 4'b01?? → 4'b001?: no match
  • 4'b001? → 4'b0001: no match
  • 4'b0001 → No match: no match
  • 4'b1??? → idx, valid: match
  • 4'b001? → idx, valid: match
  • No match → idx, valid

The ? bits in an item are ignored, so one item covers every value with that top bit.

The casez version, checked against all 16 inputs, and its size on the pinned Yosys flow.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: 16 request patterns, 0 wrong

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Junior)

A good junior answer writes the four wildcard items from the top bit down and adds a valid output. It then checks all 16 input values.

Cross-Questions

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

WhyWhat IfProve ItCompareScale It

  1. A Priority Encoder with Wildcard Case Items
  2. WhyWhy Casex Matches an Unknown InputL2 Mid-Level

    Why does casex match x001 against 4'b1???? And what does this casez version print for a floating top bit?

    systemverilog
    module prienc4 (input logic [3:0] req, output logic [1:0] idx, output logic valid);
      always_comb begin
        idx = 2'd0; valid = 1'b1;
        casez (req)
          4'b1???: idx = 2'd3;      // the highest set bit wins
          4'b01??: idx = 2'd2;
          4'b001?: idx = 2'd1;
          4'b0001: idx = 2'd0;
          default: valid = 1'b0;    // no request
        endcase
      end
    endmodule
    module tb;
      logic [3:0] req; logic [1:0] idx; logic valid;
      prienc4 dut (.req(req), .idx(idx), .valid(valid));
      initial begin
        req = 4'bz001; #1;      // the top request line is left floating
        $display("req=z001: idx=%0d valid=%b", idx, valid);
      end
    endmodule
    
    Reveal the Model Answer

    Wildcard case statements mask bits on both sides of the comparison. casex ignores X and Z wherever they appear, so the X in req matches the 1. casez does the same for Z, so z001 matches 1??? and this prints idx=3. In silicon the floating line is a real 0 or 1, so the gates may do something else.

    RUNIcarus Verilog · in your browser
    Edit the code, then run it
    Expected: req=z001: idx=3 valid=1

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Wildcards apply only to the bits written as ? in the items."

    That is the rule for case inside. In casex and casez, unknown bits in the case expression are wildcards too.

    Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. appendix C.3.3 Casex, casez and case...inside statements

  3. CompareCase Inside vs CasezL2 Mid-Level

    Compare case inside with casez for the same encoder.

    Reveal the Model Answer

    case inside compares with the wildcard equality operator, so only X, Z or ? bits in the items are masked. An unknown bit in req then fails every item and falls to default. It synthesizes to the same 5 cells as the casez version on this flow. Icarus 12 does not parse case inside, so check your tools first.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "case inside is not synthesizable."

    Synthesis supports it. On this site's flow the case inside encoder gives the same 5 cells and 2 levels as casez.

    Source Measured: the encoder rewritten with case inside, Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff

    Tool as Truth

    "Our simulator rejected case inside, so the standard does not have it."

    It is in the standard. Icarus 12 reports a syntax error on it, while Verilator 5.052 and the synthesis front end accept it.

    Source Measured: case inside compiled on each tool, Icarus Verilog 12; Verilator 5.052; Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff

  4. What IfA Priority Encoder for Any WidthL2 Mid-Level

    Asked if the request bus is wide or parameterized

    What if the request bus is 16 bits, or a parameter? Write the encoder without listing every item.

    Reveal the Model Answer

    Use a for loop that walks from bit 0 up and overwrites idx on every set bit. The last write wins, so the highest set bit wins. Set the defaults before the loop. Synthesis unrolls the loop into a chain. On this flow the 16-bit version is 40 cells and 12 levels, so depth grows with width.

    RUNIcarus Verilog · in your browser
    Edit the code, then run it
    Expected: 65536 request patterns, 0 wrong

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "A loop in RTL runs over several clock cycles."

    A synthesizable loop is unrolled into logic that settles in one cycle. Its depth is what costs you.

    Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 6.3 Looping statements

  5. Scale ItCutting the Depth of a Wide Priority EncoderL2 Mid-LevelL3 Senior

    The 16-bit encoder is too deep for your clock. Restructure it.

    Reveal the Model Answer

    Split the bus into four groups of four. Each group has a small encoder and a "busy" bit. A top encoder picks the highest busy group, and its number forms the upper bits of idx. The run proves the two versions equal on all inputs. On this flow the grouped one has 8 levels instead of 12, for about the same cells.

    RUNIcarus Verilog · in your browser
    Edit the code, then run it
    Expected: 65536 requests: 0 differences between the loop and the grouped encoder

    Self-Check

    Tick each key point you covered in your answer.

    What Interviewers Listen For (Senior)

    A good senior answer proves the restructured encoder equal to the original before measuring it. It also says when to stop restructuring and add a pipeline stage instead.

    Half-Truth

    "Synthesis will find the tree on its own."

    Sometimes it does, often it does not: on this flow the loop stayed at 12 levels. Measure, and restructure the RTL when the report says so.

    Source Measured: the loop and grouped encoders, Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff

  6. Prove ItSolve R1.5.1: A Priority Encoder with a Collision FlagSimulator-graded

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

    Open Problem R1.5.1

What People Get Wrong

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

Misconception

"casex and casez are the same thing."

casex also treats X bits in the case expression as wildcards. The twin feeds req = x001 and casex grants requester 3.

Run It

The encoder written with casex, fed an unknown top bit, then the casez form.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: req=x001: idx=3 valid=1 FAIL: casex is not the same as casez; it matched the unknown bit and granted requester 3
See the Fix
module prienc4 (input logic [3:0] req, output logic [1:0] idx, output logic valid);
  always_comb begin
    idx = 2'd0; valid = 1'b1;
    casez (req)
      4'b1???: idx = 2'd3;      // the highest set bit wins
      4'b01??: idx = 2'd2;
      4'b001?: idx = 2'd1;
      4'b0001: idx = 2'd0;
      default: valid = 1'b0;    // no request
    endcase
  end
endmodule
module tb;
  logic [3:0] req; logic [1:0] idx; logic valid;
  prienc4 dut (.req(req), .idx(idx), .valid(valid));
  initial begin
    req = 4'bx001; #1;      // the top request bit is unknown, e.g. an unreset flop
    $display("req=x001: idx=%0d valid=%b", idx, valid);
    if (idx == 2'd3) $display("FAIL: casez is not the same as casez; it matched the unknown bit and granted requester 3");
    else $display("PASS: casez did not match the unknown bit against 1???");
  end
endmodule

Prints: req=x001: idx=0 valid=0 PASS: casez did not match the unknown bit against 1???

Tool as Truth

"Verilator agrees with casex, so the code is safe."

Verilator is two-state, so it turned the X into 0 and gave idx=0 for the same casex code. It cannot show this hazard at all.

Source Measured: the twin's casex program on Verilator: idx=0 valid=1, Verilator 5.052

Half-Truth

"casez is completely safe."

casez still masks Z bits in the case expression. A floating request line, req = z001, gives idx=3 on Icarus. case inside masks only bits in the items.

Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 6.2.2.2 The obsolete casex and casez statements

Learn It, Then Prove It