Skip to content

An APB-slave RTL interview is not testing whether you have read the spec — it is testing whether you can write the seven-piece slave on a whiteboard without dropping the one term that makes a write fire once instead of twice. Module 17 has walked the register bank, the address decoder, the read-data mux, the write logic, PREADY generation, and reset behaviour. This chapter is the question bank that turns that knowledge into code under pressure — the questions a senior RTL lead actually asks, each answered with short, correct, synthesizable SystemVerilog using the real signal names. The single idea to carry: almost every APB-slave RTL question resolves to one of three disciplines — gate every committing action on the full completion term psel && penable && pwrite && pready, derive PREADY from a registered, reset-known state, and give every combinational output a defined default so no latch infers. Hold those three and the bank below collapses into restatements.

1. What this chapter covers

This is the code-heavy interview tier: the APB-slave RTL questions where a verbal answer is not enough and the interviewer hands you a marker. It covers the PREADY-generation FSM (combinational versus registered, and how to insert N wait states); the golden write-enable term wr_en = psel && penable && pwrite && pready and why dropping pready makes a wait-extended write fire on every wait cycle; the read-data mux and registered PRDATA; address decode and one-hot select; the register-bank patterns — RW, RO, WO, and W1C; reset strategy (synchronous versus asynchronous, and guaranteeing a known PREADY out of reset); latch avoidance in combinational decode; and parameterised register maps.

Every answer here is anchored to one APB fact from the spec: a transfer completes on the cycle where PSEL, PENABLE, and PREADY are all high (APB IHI 0024C §2.1) — and that conjunction is the qualifier on which every write commit, every read return, and every status update depends.

2. Why this matters now

You have built each slave piece in isolation and each is correct on its own. But an interview never asks you to recite a piece — it asks you to write it, fast, and the failure mode is never the piece, it is the integration term you drop while writing under time pressure. The classic example: you know the write commits in the access phase, so you write if (psel && penable && pwrite) reg <= pwdata; — clean, readable, and wrong, because on a wait-extended access PENABLE stays high for every wait cycle and your register is written on each of them. The bug is invisible in a zero-wait directed test and ships.

The interview tests exactly this gap between knowing the piece and writing the composed circuit correctly. Three things separate a strong candidate:

  • They reach for the full completion term reflexively. Every committing action — write, W1C clear, WO strobe — carries pready, because completion is psel && penable && pready, never a subset. They never write penable-alone gates.
  • They drive PREADY from a known, registered state. They can say what PREADY is the cycle after reset deasserts, because an undriven or X PREADY out of reset is a hang waiting to happen.
  • They give every combinational block a default. A read mux or a decode without a default infers a latch, and a lead asks "where's the latch?" precisely to see if you anticipated it.

So the skill to add is not another piece — it is writing the composition correctly the first time, with the qualifier, the reset-known PREADY, and the no-latch default baked in by habit.

3. Mental model

The model: answer every APB-slave RTL question by asking which of three disciplines it tests, then write the smallest correct snippet that honours it. The three disciplines are the spine of the whole bank.

  • Gate every commit on the completion conjunction. Completion is psel && penable && pready (APB IHI 0024C §2.1). Any action that changes state — a register write, a W1C clear, a WO pulse, a side-effect-on-read — must be qualified by that term (plus pwrite for writes), so it happens on exactly the one completing cycle and never during a wait. The golden form is wr_en = psel && penable && pwrite && pready.
  • Derive PREADY from a registered, reset-known state. PREADY is the bit the manager samples to decide completion, so it must be glitch-free at the sampling edge and defined the instant reset deasserts. A registered PREADY that resets to a known value (high for an always-ready slave, or low-then-rising for a wait-capable FSM) is the safe default; a combinational PREADY off a rippling decode is the classic glitch hazard.
  • Default every combinational output. A read mux, a decode, or any always_comb that does not assign its output on every path infers a latch. Give PRDATA a '0 default, use unique case with a default, and the design is latch-free by construction.

Three refinements sharpen the model:

  • The write-enable term is the single most-tested line in the whole bank. If you remember nothing else, remember that the commit qualifier is the four-way conjunction psel && penable && pwrite && pready, and that dropping pready is what fires the write twice.
  • Reads have no side effects by default, but PRDATA must still be valid the cycle PREADY is high. A registered PRDATA with a tied-high PREADY ships stale reads; keep the two phase-aligned (combinational PRDATA with always-ready PREADY, or both registered together).
  • Reset is a property of every flop in the slave, and PREADY is the one flop whose reset value is load-bearing. A slave that powers up with PREADY undriven can hang the very first access; reset it explicitly on the correct polarity.
A block diagram of an APB subordinate: APB inputs on the left feed an address decoder producing a one-hot select, which drives a write-enable gate labelled wr_en = psel and penable and pwrite and pready into a typed register bank; a PREADY FSM along the bottom qualifies the commit and completion; the same select drives a read-data mux onto a registered PRDATA, and the slave outputs PRDATA, PREADY and PSLVERR on the right.
Figure 1 — the APB-slave datapath an interviewer asks you to draw. PSEL, PENABLE, PWRITE, PADDR and PWDATA/PSTRB enter on the left; an access-phase qualifier (access = psel & penable) and a latch-free address decoder produce a one-hot per-register select and a decode_err flag. The decode feeds the write-enable gate whose golden term is wr_en = psel & penable & pwrite & pready, which drives the typed register bank (RW/RO/W1C/WO, reset on every flop). A registered PREADY-generation FSM runs across the bottom — known out of reset, inserting N wait states — and qualifies both the write commit and the read completion. The same one-hot select feeds the read-data mux, which selects one register onto a registered PRDATA with a defined zero default. The slave drives out PRDATA, PREADY and PSLVERR (decode_err qualified by the access phase). This is the picture to reproduce from memory before writing any RTL.

4. Real SoC / hardware context

These are not academic snippets — each maps to a peripheral that ships in real silicon. Consider a GPIO block with a control register (RW), a pin-state register (RO, hardware-owned), an interrupt-flag register (W1C), and a command-strobe register (WO). Every one of those four kinds has a distinct RTL pattern, and an interviewer probes whether you know them apart: a candidate who writes the W1C flag as a plain RW register ships a peripheral whose interrupt can never be cleared without clobbering a flag the hardware set on the same cycle.

The write-enable term is the most expensive thing to get wrong in practice. A timer peripheral whose reload register is written on penable alone — without the pready qualifier — writes the reload value on every wait cycle of a wait-extended access; on a slow APB segment that means the same value is written two or three times, which is harmless until the day someone makes that register a counter that increments on write, and now it increments once per wait state instead of once per access. The bug surfaced in a write-corruption lab exactly this way: a register that "counted writes" counted wait cycles instead, because the commit was gated on penable and not on the completion term. The fix in every case is the same one line: gate the commit on psel && penable && pwrite && pready so it fires on the single completing edge.

PREADY out of reset is the other silicon-grade trap. A subordinate whose PREADY flop is left undriven on the reset path comes up X in gate-level simulation and can hang the first access after reset deasserts — a bug that a zero-delay RTL run hides because X propagates differently there. The discipline that prevents it is structural: reset PREADY to a known value on the correct polarity, every time.

5. Weak vs strong answers

This is the interview-grading table: each row is an APB-slave RTL question, the weak answer a junior gives, the strong answer a senior gives, and the RTL reason that decides it. Read it as the spine of the bank.

RTL questionWeak answerStrong answerRTL reason
"What qualifies a register write?""psel && penable && pwrite — it's the write access phase.""psel && penable && pwrite && pready — the completing cycle, not just the access phase."On a wait-extended access penable is high for every wait cycle; without pready the write commits on each one.
"How do you build PREADY for N wait states?""Tie a counter to pready combinationally.""A registered FSM/counter: load on access start, count down, assert pready on the last cycle, drop after completion."A combinational PREADY off a rippling counter glitches into the sample window; registered PREADY is glitch-free at the edge.
"What is PREADY the cycle after reset?""Whatever the logic settles to.""A known reset value — 1'b1 for always-ready, 1'b0 for a wait FSM — driven on the reset path."An undriven/X PREADY out of reset can hang the first access; reset every flop on the correct polarity.
"How do you avoid a latch in the read mux?""Assign prdata in each case branch.""Default prdata = '0 first, then unique case with a default branch."A combinational block that misses a path infers a latch; a leading default covers every unlisted select.
"How do you implement a W1C status bit?""Make it RW and let software clear it.""Hardware-set wins; software write-1 clears only the bits it targets, on the completing edge."W1C has joint ownership — a plain RW lets a software clear and a hardware set on the same cycle race and lose the event.
"Should PRDATA be registered or combinational?""Register it — registered outputs are always safer.""Either, but PREADY and PRDATA must agree on the completing cycle."A registered PRDATA with a tied-high PREADY asserts ready a cycle before data is valid — stale reads.

The throughline: every weak answer drops a condition — the pready qualifier, the register on PREADY, the reset value, the latch default, the ownership rule, or the phase alignment — and the strong answer restores the full term. The interview is, in every row, a test of whether you compose the pieces with all their conditions intact.

6. Common RTL mistakes / red flags

Two stacked APB-slave write-enable RTL fragments. The top, in red and labelled WRONG, gates the register write on psel and penable and pwrite only and is marked as firing on every wait cycle. The bottom, in green and labelled CORRECT, adds the pready term so the write fires once. A timing strip on the right shows PENABLE high across three access cycles, PREADY high only on the third, the wrong write-enable pulsing on all three and the correct write-enable pulsing only on the completing cycle.
Figure 2 — the whiteboard 'spot the bug' an interviewer puts up: an ungated write-enable that fires twice. Top (wrong, red): the register commit is gated on psel && penable && pwrite with no pready term, so on a wait-extended write PENABLE is held high across every wait cycle and the write-enable pulses on each one — the register is written more than once, committing intermediate or stale PWDATA. Bottom (correct, green): wr_en = psel && penable && pwrite && pready, which is true on exactly the one completing cycle, so the register is written exactly once. The timing strip on the right shows PENABLE high for three access cycles with PREADY low, low, then high; the wrong write-enable pulses on all three cycles while the correct write-enable pulses only on the third, the completing cycle. The task is to name the missing pready qualifier as the cause of the double write and state that completion is psel & penable & pready (APB IHI 0024C §2.1).

7. Interview framing

APB-slave RTL is the most code-heavy APB topic, and the questions are deliberately open: "design a single-register slave," "make PREADY for N wait states," "why does your write fire twice." A weak candidate describes the answer in prose; a strong one writes the snippet, names the qualifier or default that makes it correct, and points to the failure mode of the wrong version.

The framing that lands every time is write the snippet, then name the term that makes it correct, then state the bug the wrong version ships. When asked for the write-enable, do not just write the line — write it and say "the pready term is load-bearing: drop it and a wait-extended write fires once per wait cycle, which is the double-write bug." When asked for PREADY, write the registered FSM and say "it resets to a known value on presetn, so the first access can't hang on an X." When asked for the read mux, write the '0 default first and say "this is what keeps it latch-free." The strongest single move is to volunteer the unifying point: every APB-slave RTL bug is either a missing completion qualifier, an unknown/glitchy PREADY, or a missing combinational default — and you fix all three by habit, not by debugging. If you can also sketch the datapath of Figure 1 from memory and the double-write of Figure 2, the interviewer knows you have built slaves, not just read about them.

8. Q&A

9. Practice

  1. Write the single-register slave. From a blank page, write the §8 apb_single_reg from memory — the four-way wr_en, the reset-known PREADY, and the defaulted read mux — without looking. Then state the bug each of the three lines prevents.
  2. Build PREADY for N=3. Write the registered wait-state FSM/counter that inserts exactly three wait cycles, asserting PREADY on the completing cycle and dropping after. Confirm PREADY is known out of reset and never combinationally glitches.
  3. Spot the double-write. From Figure 2, name the missing qualifier, predict the exact waveform of wr_en on a two-wait-state write, and write the one-line fix. Then explain why a zero-wait directed test would never catch it.
  4. Implement the four register kinds. Write the RTL for one RW, one RO (hardware-owned), one W1C (hardware-set wins), and one WO (one-cycle strobe, reads 0) register, each sharing the same wr_en. State what each reads back.
  5. Fix the stale read. Given a slave with a registered PRDATA and pready = 1'b1, predict the waveform on a back-to-back read of two different registers, write the SVA assert property that catches a completing read returning the wrong register, and write the corrected phase-aligned RTL.

10. Key takeaways

  • Gate every committing action on psel && penable && pwrite && pready. Completion is psel && penable && pready (APB IHI 0024C §2.1); dropping the pready qualifier makes a wait-extended write fire on every wait cycle — the double-write that is the single most-tested red flag in the bank.
  • Derive PREADY from a registered, reset-known state. A registered PREADY is glitch-free at the sampling edge, and an explicit reset value (high for always-ready, low for a wait FSM) means the first access after reset never hangs on an X.
  • Default every combinational output. Lead the read-mux always_comb with prdata = '0, use unique case with a default, and decode only when psel is high — so no latch infers and an unmapped read returns 0.
  • Know the four register kinds apart. RW commits on wr_en; RO follows a hardware source and ignores wr_en; W1C clears only written bits with a same-cycle hardware set winning; WO pulses one cycle and reads back 0.
  • Keep PREADY and PRDATA phase-aligned. Combinational PRDATA with always-ready PREADY, or both registered on the same edge — never a flopped PRDATA with a tied-high PREADY, which ships stale reads.
  • Every APB-slave RTL bug is one of three: a missing completion qualifier, an unknown or glitchy PREADY, or a missing combinational default. Write the snippet, name the term that makes it correct, and state the bug the wrong version ships.