← RTL Design Interviews

Interview Question · Concept

Unique Case vs Priority Case

L2 Mid-LevelL3 Seniorcase statementsuniquesynthesis

The Question

The interviewer asks

What do unique case and priority case promise, who checks the promise, and what can go wrong?

Reveal the Model Answer

Both promise that some arm matches when there is no default. unique also promises at most one arm matches, so synthesis may ignore the order. priority keeps the order, and the first match wins. The simulator checks the promise each time the statement runs, while synthesis simply assumes it. If the promise is false, RTL and gates can disagree.

The Chain, and the Netlist of the Unique RewriteOne request per cycle, except cycle 5, where req[1] and req[2] are both 1. Each data word has a single bit set: d0 = 0001, d1 = 0010, d2 = 0100, d3 = 1000.
0123456clkreq0001001001001000000001100001y (chain)0001001001001000000000100001y (unique, gates)0001001001001000000001100001
  1. Cycle 0

    One request: both circuits pass d0. Every one-request cycle looks like this, and so does the cycle with no request.

  2. Cycle 5

    Two requests. The chain tests req[1] before req[2], so it passes d1, 0010, as the brief says.

  3. Cycle 5

    The unique netlist ANDs every word with its request and ORs the results: 0010 | 0100 = 0110. The RTL simulation of the same code shows 0010.

Measured in lesson R1.5. The RTL keeps the order, but the netlist built from unique case mixes two data words when two requests arrive.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Mid-Level)

A good mid-level answer states both promises. It says the simulator checks them and synthesis assumes them, and it keeps a default arm.

Cross-Questions

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

WhyProve ItCompareScale It

  1. Unique Case vs Priority Case
  2. WhyWhat the Unique Netlist Does with Two RequestsL2 Mid-Level

    Why do the gates and the RTL disagree when two requests arrive at a unique selector?

    Reveal the Model Answer

    The RTL runs the first matching arm, so it passes one data word. The netlist was built on the promise of one request at a time. Each data word is ANDed with its request and the results are ORed. With two requests, two words mix: 0010 | 0100 = 0110. The false promise became a functional bug.

    What Yosys 0.70 Built from Each FormThe same ports, two netlists. The chain tests the requests in order through eight 2:1 muxes and thirteen gates. The unique case ANDs each data word with its request and ORs the four results.
    What Yosys 0.70 built from each formThe same ports, two netlists. The chain tests the requests in order through eight 2:1 muxes and thirteen gates. The unique case ANDs each data word with its request and ORs the four results. manager req[3:0] requests manager d0 .. d3 four 4-bit words bus priority chain 21 cells, 5 levels bus AND-OR 28 cells, 3 levels completer y (if chain) lowest request wins completer y (unique case) all requests mixed tested in orderdataone AND per worddata
    1. The chain

      req[0] is tested first, then req[1], and so on. A word passes only when every lower request is 0. Five levels of logic deep.

    2. The AND-OR

      Every word is gated by its own request, all at once, and the four results are ORed. Three levels deep, but seven cells more.

    3. Two requests

      With req = 0110 the chain passes d1, 0010. The AND-OR passes d1 and d2 together: 0110. unique told the synthesizer this input never happens.

      Follow the calls, values and waits
      1. data req = 0110: req[3:0] → priority chain
      2. data req = 0110: req[3:0] → AND-OR
      3. data 0010: priority chain → y (if chain)
      4. data 0110: AND-OR → y (unique case)
    Read the diagram as text
    • req[3:0]: requests
    • d0 .. d3: four 4-bit words
    • priority chain: 21 cells, 5 levels
    • AND-OR: 28 cells, 3 levels
    • y (if chain): lowest request wins
    • y (unique case): all requests mixed
    • req[3:0] → priority chain: tested in order
    • d0 .. d3 → priority chain: data
    • priority chain → y (if chain)
    • req[3:0] → AND-OR: one AND per word
    • d0 .. d3 → AND-OR: data
    • AND-OR → y (unique case)

    Bigger and shallower: the parallel form pays cells to save levels. Neither shape is smaller by rule; measure.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Overlap just picks one of the two words at random."

    It is not random. The AND-OR passes both words together, giving a value neither source sent.

    Source Lesson R1.5 measurement: the Yosys 0.70 netlist of the unique selector, simulated with req = 0110, outputs 0110

  3. Prove ItCatching a False Unique Promise in RTLL2 Mid-Level

    Prove it: how do you catch that false promise in RTL, before the netlist shows it?

    Reveal the Model Answer

    Run RTL simulation with the unique checks on. The simulator reports a violation when two items match, or when none does. Also assert $onehot0(req) at the block boundary, so the caller's side is checked. Formal can then prove that assertion from the requesters' logic.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    "Synthesis would warn about overlapping items."

    Synthesis takes unique as a promise and builds smaller logic from it. The check lives in simulation, not in synthesis.

    Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 7.4.2 The unique and unique0 decision modifiers

  4. CompareUnique, Unique0 and PriorityL2 Mid-Level

    Compare unique, unique0 and priority. When would you choose each?

    Reveal the Model Answer

    priority keeps the order and only promises that something matches. Use it when overlaps are legal and the spec says who wins. unique promises exactly one match without a default. unique0 promises at most one and allows no match. Use unique0 for a decode where "nothing selected" is normal.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "priority case is the same as a plain case."

    The order is the same, but priority adds a check. With no default, a value that matches no item is reported.

    Source IEEE 1800-2017 §12.5.3

  5. Scale ItA Policy for Unique in a Design TeamL3 SeniorL4 Staff

    As a design lead, when do you allow unique, and how do you make sure the promise holds?

    Reveal the Model Answer

    Allow it only where the inputs are exclusive by construction, such as a one-hot state register or a decoded address. Back each use with a one-hot assertion and a formal proof or a test that tries the overlap. Run regressions on a simulator that checks unique. Treat every violation as a design bug, not a warning.

    Self-Check

    Tick each key point you covered in your answer.

    What Interviewers Listen For (Staff)

    A good staff answer ties the language feature to sign-off. Each use gets an assertion and a proof, regressions use a simulator that checks unique, and any violation blocks the release.

    Wrong Altitude

    "Add unique everywhere for faster logic."

    Every false promise is a hidden RTL-versus-gates mismatch. The speed gain is not worth an unchecked assumption.

  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

"unique always makes the logic smaller."

It makes the logic parallel, not smaller. On this flow the unique selector is 28 cells and 3 levels, against 21 cells and 5 levels for priority.

Run It

The four-way selector as unique case, then as priority case, on the pinned Yosys flow.

module sel4 (input logic [3:0] req, input logic [3:0] d0, d1, d2, d3, output logic [3:0] y);
  always_comb begin
    unique case (1'b1)
      req[0]:  y = d0;
      req[1]:  y = d1;
      req[2]:  y = d2;
      req[3]:  y = d3;
      default: y = 4'b0000;
    endcase
  end
endmodule
See the Fix
module sel4 (input logic [3:0] req, input logic [3:0] d0, d1, d2, d3, output logic [3:0] y);
  always_comb begin
    priority case (1'b1)
      req[0]:  y = d0;
      req[1]:  y = d1;
      req[2]:  y = d2;
      req[3]:  y = d3;
      default: y = 4'b0000;
    endcase
  end
endmodule

Tool as Truth

"Our simulator never reported a unique violation, so the arms never overlap."

Icarus 12 accepts unique but does not check it: with two requests it printed y=0010 and no message. Verilator 5.052 stops with an assertion error.

Source Measured: the selector with req = 0110 on each tool, Icarus Verilog 12; Verilator 5.052

Missed Corner

"With unique I can drop the default arm."

unique assigns nothing. A path where no arm matches still leaves the output unassigned, and that is a latch.

Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 9.3.5 Latch avoidance style 3 (note)

Learn It, Then Prove It