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

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
    • Low-Power RTL Hub
    • DFT and Scan Hub
    • Physical Awareness Hub
    • Waveform Debug Hub
    • STA and ECO Hub
    • RTL-to-Implementation Closure
    • DFT-Ready RTL
    • Capstone: Resilient Streaming Peripheral
    • Principal Design Review
    • Senior RTL Interview Questions & Model Answers
      • Interview: Combinational and Arithmetic
      • Interview: Sequential and Pipelines
      • Interview: FSM and Control
      • Interview: Timing and STA
      • Interview: CDC and Reset
      • Interview: Memories and Buses
      • Interview: Low-Power Design
      • Interview: Debug and ECO
      • Interview: Coding and Whiteboard
        • Whiteboard: a synchronous FIFO
        • Whiteboard: a priority mux
        • An RTL review in 30 minutes
        • Framing area, speed and power trade-offs
        • What senior answers sound like
  • Glossary and Notation
Loading lesson

‹Interview: Coding and Whiteboard
  1. Topics
  2. RTL Design
  3. Senior & Interview
  4. Senior RTL Interview Questions & Model Answers
  5. Interview: Coding and Whiteboard
  6. Whiteboard: a priority mux

Part 9 · Senior · Senior Prep

Whiteboard: a priority mux

A parameterized priority mux with a valid flag, checked against a reference over all request patterns.

On this page

    Why this matters

    If index 0 can mean both requester 0 and no request, an idle bus looks like a grant to master 0. This question tests arbitration plus steering, with the idle case as the trap.

    After this lesson you can: write a lowest-index-wins priority mux with a valid flag, and derive grant and data from one decision.

    The question

    “Four masters request a shared bus. Grant the lowest-numbered requester and steer its data out. Flag idle.”

    The question tests arbitration plus steering. The trap is the idle case: index 0 cannot mean both requester 0 and no request.

    Model answer

    State the interface first: one request bit per master, one data word per master, grant index, data out, and a valid flag. Then name the invariant: valid means some request is active, and the index names the lowest active one.

    A loop from the high index down lets each active request overwrite the result, so the lowest active index wins. The loop unrolls into a chain of overrides in hardware.

    The loop for req = 4'b1010, one box per iteration from i = 3 down to i = 0. Active requests (highlighted) overwrite the result, so the last one written, index 1, wins.

    Read the boxes top to bottom as loop iterations; each box shows the result after that iteration.

    • Only the highlighted iterations write. Index 3 writes first and index 1 overwrites it, so the lower index wins.

    • idx, valid and y are written together in each box, so grant and data cannot disagree.

    • If no bit were set, nothing would write and the start values would come out, with valid = 0.

    N may be 1 (a single requester): the index width is guarded as localparam int SW = (N > 1) ? $clog2(N) : 1; because $clog2(1) is 0.

    Input

    valid

    idx / y

    No bits set

    0

    Don't care (0)

    Bit 0 set

    1

    0, data word 0

    Bits 1 and 2 set

    1

    1, data word 1 (lowest wins)

    All bits set

    1

    0, data word 0

    The data path is part of the answer. The winning index selects the winning data word in the same block, so grant and data can never disagree.

    Follow-ups

    “Highest-numbered requester wins instead. What changes?” Scan from low to high (for (int i = 0; i < N; i++)) with the same overwrite-on-request body, so the highest active index overwrites last. For 4'b1010, index 1 is selected first and index 3 replaces it.

    “64 requesters at speed. What changes?” The linear chain grows with N. Split the request vector into halves, encode each half, then combine with the halves valid flags for logarithmic depth.

    “Add a mask input. What does it do?” Each request is qualified with its mask bit before encoding. A masked requester can never win, which is how software parks a faulty master.

    Common wrong answers

    Common pitfall

    Dropping the valid output and treating index 0 as requester 0 makes an idle bus look like a grant to requester 0. Always carry the valid flag with the index.

    A weaker answer writes a priority case without a default and without covering every select value. The missing cases hold state and synthesize a latch.

    Another weak answer encodes the index in one block and muxes the data in another with different priority. Grant and data then disagree on overlapping requests.

    Check yourself Requests read 4'b1010 with lowest-index priority. Who wins, and what changes with highest-index priority?

    Lowest-first grants index 1. Highest-first grants index 3.

    Check yourself Why does the data mux live in the same always block as the encoder?

    So one priority decision drives both outputs. Separate blocks can encode different winners for the same request pattern.

    Testbench

    The full priority mux plus a regression checking all 16 binary request patterns against a first-set-bit reference under two data fills.

    prio_mux.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
    `timescale 1ns/1ps
    module prio_mux #(
      parameter int N = 4,   // must be at least 1
      parameter int W = 8
    ) (
      input  logic [N-1:0]          req,
      input  logic [N*W-1:0]        d,
      output logic [(N > 1 ? $clog2(N) : 1)-1:0] idx,
      output logic                  valid,
      output logic [W-1:0]          y
    );
      // N = 1 guard ($clog2(1) is 0, so [$clog2(N)-1:0] would be [-1:0]).
      localparam int SW = (N > 1) ? $clog2(N) : 1;
      always_comb begin
        idx = '0; valid = 1'b0; y = '0;
        for (int i = N-1; i >= 0; i--) begin     // scan from the high end so the lowest index wins last
          if (req[i]) begin
            idx = i[SW-1:0];
            valid = 1'b1;
            y = d[i*W +: W];
          end
        end
      end
    endmodule
    

    Remember

    • Always carry a valid flag with the index. Valid means some request is active.

    • A loop from the high index down lets the lowest active request overwrite last, so it wins.

    • Select the data in the same block as the index, so grant and data cannot disagree.

    Rule of thumb: one priority decision drives every output.

    How this was checked

    Regression Run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It checks all 16 binary request patterns against a first-set-bit reference under two data fills. It is not evidence for every N or four-state input.

    Keep going

    • Practice: Priority encoder with parameterised width and valid output

    • Practice: Fixed-priority arbiter

    • Code lab: 4:2 priority encoder

    • Interview: run a mock interview on this topic

    Related topics

    • Priority encoder

    Previous

    346 / 350

    Next: An RTL review in 30 minutes

    Up next

    Up nextAn RTL review in 30 minutes

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Framing area, speed and power trade-offs
    • What senior answers sound like