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
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
    • Senior Debug Playbook
    • Reviewing Verification Code
    • Verification Strategy: Spec to Sign-Off
    • SystemVerilog Interview Q&A Bank
      • Q&A: Language Core
      • Q&A: Testbench Plumbing
      • Q&A: Classes and Interfaces
      • Q&A: Constraint and Assertion Fire-Drill
      • Q&A: Scenario and Design Questions
    • Capstone: Verify a Parameterized FIFO
  • Principal-Level Verification28
Loading lesson

‹SystemVerilog Interview Q&A Bank
  1. Topics
  2. SystemVerilog
  3. Senior & Interview Preparation
  4. SystemVerilog Interview Q&A Bank
  5. Q&A: Scenario and Design Questions

Part 8 · Senior & Interview Prep · Intermediate

Q&A: Scenario and Design Questions

FIFO plans, arbiter checks, CDC layers, hang triage and tapeout-eve decisions.

On this page

    Scenario answers show planning before components. Each answer below states the plan first, then the environment, then the checks that close it.

    Verify a FIFO end to end

    Q: How would you verify a FIFO, the full senior answer

    Structure the answer as plan, environment, checks, coverage, closure. Plan extracts features and risk-ranks the full, empty and reset corners highest.

    The environment pairs an interface with clocking blocks, a generator-mailbox-driver chain, independent monitors and a queue reference model. Three checkers divide the work: scoreboard for data, assertions for protocol, coverage for proof of exercise.

    Diagram
    gen ─mb─► drv ─┐                  ┌─► in_mon ──► ┌────────────┐
                   fifo_if ──► DUT ──► fifo_if ─► out_mon ─► │ scoreboard │
     assertions bound to DUT ▲                               │ (queue mdl)│
     (full/empty/count/data) │                               └────────────┘
                         coverage: boundaries, crosses, backpressure

    Name the corner inventory explicitly: exact boundary levels, flag transitions, simultaneous push and pop near full and empty, a push offered at full, and reset mid-traffic. Closure is a seed sweep with merged coverage and hole analysis.

    Contention: the four-master arbiter

    Q: Design a testbench for a four-master arbiter

    Four active agents drive, one passive checker watches. The scoreboard checks three property families: exclusivity, legality and fairness within the documented bound.

    Stimulus engineers contention instead of hoping for it: all-request bursts, staggered arrivals, one hogging master, and randomized priorities where programmable. Exact rotation needs a policy model; bounds alone cannot prove it.

    The properties below are fragments, so this course's checks do not run them. Placed in a module with the signals declared, they run under verilator --assert.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    // snippet
    // a_excl:  assert property (@(posedge clk) disable iff (!rst_n)
    //            $onehot0(gnt));
    // a_legal: assert property (@(posedge clk) disable iff (!rst_n)
    //            |gnt |-> |(gnt & req));
    // a_starv: assert property (@(posedge clk) disable iff (!rst_n)
    //            (req[0] && !gnt[0]) |-> ##[1:64] gnt[0]);

    The same two safety properties run here as procedural checks over all 16 request patterns. Exclusivity is a one-bit trick: a one-hot value ANDed with itself minus one is zero.

    prio_arb4.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
    29
    30
    module prio_arb4 (
      input  logic [3:0] req,
      output logic [3:0] gnt
    );
      always_comb begin
        gnt = 4'b0;
        if (req[0]) gnt = 4'b0001;
        else if (req[1]) gnt = 4'b0010;
        else if (req[2]) gnt = 4'b0100;
        else if (req[3]) gnt = 4'b1000;
      end
    endmodule
    
    module tb_prio_arb4;
      timeunit 1ns; timeprecision 1ps;
      logic [3:0] req, gnt;
      prio_arb4 dut (.*);
      int errors = 0;
      initial begin
        for (int r = 0; r < 16; r++) begin
          req = r[3:0]; #1;
          if ((gnt & (gnt - 1)) !== 4'b0) errors++;   // at most one grant
          if ((gnt & ~req) !== 4'b0) errors++;        // grant implies request
          if ((req == 4'b0) !== (gnt == 4'b0)) errors++;
        end
        if (errors == 0) $display("PASS: all 16 request patterns grant at most one requester");
        else $fatal(1, "FAIL: arbiter grant wrong");
        $finish;
      end
    endmodule

    Crossing clock domains

    Q: How would you verify a CDC path

    Layer

    Tool

    What it proves

    Structural

    CDC lint

    Every crossing has a legal synchronizer

    Protocol

    Assertions

    Stability, handshake hold, one-bit gray steps

    Dynamic

    Async ratios plus injection

    Tolerance to real skew and metastability

    Simulation alone is structurally blind here: RTL has no metastability, so a violated window still resolves cleanly and deterministically. That sentence is the senior marker.

    The contracts below are fragments, so this course's checks do not run them. Placed in a module with the signals declared, they run under verilator --assert.

    design.sv
    1
    2
    3
    4
    5
    // snippet
    // a_gray: assert property (@(posedge wr_clk) disable iff (!rst_n)
    //   $countones(wr_ptr_gray ^ $past(wr_ptr_gray)) <= 1);
    // a_hold: assert property (@(posedge src_clk) disable iff (!rst_n)
    //   (req && !ack_sync) |=> req);

    The gray-code contract runs here as a plain loop: all 16 counter steps, including the wrap, change exactly one bit.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    module tb_gray_step;
      int errors = 0;
      function automatic logic [3:0] to_gray(input logic [3:0] b);
        return (b >> 1) ^ b;
      endfunction
      initial begin : main
        logic [3:0] g_now, g_next, diff;
        int w, ones;
        for (int v = 0; v < 16; v++) begin
          w = (v + 1) % 16;
          g_now = to_gray(v[3:0]);
          g_next = to_gray(w[3:0]);
          diff = g_now ^ g_next;
          ones = 0;
          for (int b = 0; b < 4; b++) if (diff[b]) ones++;
          if (ones !== 1) errors++;
        end
        if (errors == 0) $display("PASS: all 16 gray steps change exactly one bit");
        else $fatal(1, "FAIL: gray step wrong");
        $finish;
      end
    endmodule

    Debug under pressure

    Q: A test hangs forever, how do you debug it

    Locate first, then classify. Frozen sim time means a zero-delay loop; advancing time means something blocks eternally. The blocking checklist is short: mailbox get, missed event triggers, stuck fork branches, leaked semaphore keys, or a DUT handshake with no ack.

    Diagram
    HANG TRIAGE TREE
    
      sim time frozen?
       ├─ YES → zero-delay loop: comb feedback, wait that never yields
       └─ NO  → blocking wait:
                ├─ mailbox get: producer dead?
                ├─ event wait: same-step missed trigger?
                ├─ join: which branch is stuck?
                ├─ semaphore: key leaked by disable fork?
                └─ DUT handshake: req with no ack?

    Pause in the debugger and inspect process states, or bisect with timestamped prints at component boundaries. Ship every bench with a global watchdog plus per-component heartbeats, so hangs arrive as reports naming the stuck part.

    Q: One day to tapeout, a bug report lands, what do you check

    Question

    Decides

    Reproducible on the tapeout RTL, seed pinned

    Real bug or artifact

    DUT behavior or checker artifact

    Who owns the fix

    Trigger conditions in real traffic

    Field likelihood

    Workaround in software or straps

    Ship-with-erratum option

    RTL delta blast radius

    Re-verification cost

    Triage for decision-grade facts in hours, not a fix. The deliverable is a decision package with options and risk: fix-and-slip, ship-with-erratum, or respin. Heroics are not the answer.

    Common pitfall

    Claiming simulation verifies CDC invites the follow-up that ends the interview. Jumping to prints before classifying the hang type wastes the first hour.

    Interview

    The CDC answer is three layers plus the blindness sentence. The tapeout answer is a triage process, never a promise to fix it fast.

    Check yourself The watchdog fires with time frozen and one process spinning. What class of bug is it?

    A zero-delay loop: combinational feedback or a wait that never yields time. Pause and profile the spinning process.

    Check yourself An arbiter grant lights with no matching request. Which property family caught it, and what does the scoreboard add?

    Legality caught it. The scoreboard adds the policy model: whether the right requester won under rotation.

    Related topics

    • Senior: verification strategy

    • Senior: capstone FIFO

    • Senior: debug playbook

    • Senior: code review checklist

    Previous

    227 / 259

    Next: Capstone: Verify a Parameterized FIFO

    Up next

    Up nextCapstone: Verify a Parameterized FIFO

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Q&A: Language Core
    • Q&A: Testbench Plumbing
    • Q&A: Classes and Interfaces