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
      • Stage 1: Specification
      • Stage 2: CSR and Control
      • Stage 3: Buffered Streams
      • Stage 4: CDC and Reset
      • Stage 5: Arithmetic and Reliability
      • Stage 6: Verification
      • Stage 7: Constraints and Implementation
      • Stage 8: Signoff Review
    • Principal Design Review
    • Senior RTL Interview Questions & Model Answers
  • Glossary and Notation
Loading lesson

‹Capstone: Resilient Streaming Peripheral
  1. Topics
  2. RTL Design
  3. Senior & Interview
  4. Capstone: Resilient Streaming Peripheral
  5. Stage 2: CSR and Control

Part 9 · Senior · Senior

Stage 2: CSR and Control

Implement the software contract, sticky status, interrupt aggregation, and a command FSM with timeout and abort.

On this page

    Why this matters

    A command stored in a register retriggers, or needs software to clear it. A bus response that claims success before the design has decided can mislead software for the whole operation.

    After this lesson you can: turn a bus write into a one-cycle internal command, keep configuration stable during an operation, and say what the response does and does not report.

    Stage 2 turns bus writes into commands. Software sees a register map; the datapath sees only one-cycle pulses, a frozen configuration snapshot and status events.

    Register map

    Byte offset / register

    CP-1 fields and semantics

    0x00 CONTROL

    bit0 enable RW only on non-command writes while idle; bit1 START WO pulse; bit2 ABORT WO pulse; bit3 RECOVER WO pulse. Command writes do not rewrite enable. Other bits reserved zero; unsupported mode writes return SLVERR.

    0x04 FORMAT

    RO 0x00030F0F: input fractional bits [4:0]=15, output [12:8]=15, nearest-even bit16=1, saturate bit17=1. Writes return SLVERR; selectable modes are an extension.

    0x08 COEFF

    RW signed Q1.15 in [15:0], upper bits read zero; reset 0x4000. Busy writes return SLVERR with no update; byte strobes apply.

    0x0C STATUS

    busy bit0 RO; done bit1 W1C; error bit2 W1C; aborted bit3 W1C; recovery_ready bit4 RO; final_counter_snapshot_valid bit5 RO. Hardware set wins simultaneous clear; clearing error does not clear an unresolved fault.

    0x10 IRQ_ENABLE / 0x14 IRQ_STATUS

    bits0/1/2 correspond to done/error/aborted; enable RW, pending W1C and hardware-set dominant. A pending bit retains a cause, not the number of events.

    0x18 ACCEPTED / 0x1C DELIVERED / 0x20 STALLS

    RO 32-bit operation snapshots, published together after drain and DP acknowledgement; accepted/delivered count IO handshakes; STALLS counts output valid&&!ready IO cycles.

    0x24 CE / 0x28 UE / 0x2C DISCARDED

    RO aligned final snapshots. CE/UE count delivered beats carrying the respective flag, once per output handshake, not all physical faults or storage-read events. DISCARDED counts accepted input owners cancelled by coordinated reset. IO-owned accounting survives local DP/interface flush.

    0x30 PACKETS

    RW count 1..16, reset 1; busy writes and out-of-range values return SLVERR. Frozen with COEFF at START.

    Commands become one-cycle pulses

    Each command field is write-only. An accepted write becomes one internal pulse, committed on one edge; the FSM decides whether to accept it.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    // snippet: command acceptance is a one-cycle internal event
    assign abort_accept = abort_pulse && !recover_pulse && busy_q;
    assign start_accept = start_pulse && !abort_pulse && !recover_pulse && !busy_q &&
                          enable_q && recovery_ready && config_valid;
    assign recover_accept = recover_pulse && !start_pulse && !abort_pulse &&
                            fault_q && admission_closed && cancellation_complete &&
                            peer_clock_qualified;
    assign irq_o = |(irq_pending_q & irq_enable_q);
    • The FSM owns operation lifetime. The bus adapter never reaches into datapath state.

    • Pulses are committed operations. They come pre-edge from a one-shot adapter, not as levels held through APB wait states or AXI backpressure.

    • The response reports ownership, not completion. OKAY or SLVERR says whether the command was accepted; status and IRQ report completion later. A posted response must not claim success before rejection is decided.

    Command FSM

    State diagram: IDLE goes to LAUNCH on START, LAUNCH to BUSY on DP ack, LAUNCH or BUSY to DRAINING on ABORT, BUSY to IDLE when done, DRAINING to IDLE when drain is done, BUSY to FAULTED on a fault, DRAINING to FAULTED when the watchdog expires, FAULTED to RECOVERING on RECOVER, and RECOVERING back to IDLE when the barrier succeeds or to FAULTED when the retry fails.
    The operation lifetime. LAUNCH holds the configuration snapshot until the datapath acknowledges it; ABORT always drains; only RECOVER leaves FAULTED.

    Read each arrow as one committed event. STATUS.busy is high in every state except IDLE.

    • LAUNCH exists because stream acceptance may begin only after the datapath has the snapshot.

    • DRAINING finishes the open packet and every accepted beat; busy clears only after drain and the final counter return.

    • FAULTED is left only through RECOVERING, and a failed barrier returns there.

    Command truth table

    Every row is decided at the commit edge. Combinations not listed are not legal commands.

    Command / state at commit edge

    Response and action

    START idle, enabled, configured, recovered

    OKAY; capture pre-edge COEFF/PACKETS into operation snapshot, allocate operation ID, set busy, clear snapshot-valid, hold snapshot until DP handshake acknowledges it; stream acceptance begins only then

    START busy, disabled, invalid or not recovered

    SLVERR; no launch, no snapshot change; latch command-error cause without cancelling existing work

    ABORT busy

    OKAY; latch abort_requested once, stop new packet ownership, finish any open packet and drain; repeated ABORT is idempotent; busy clears only after drain and final counter return

    ABORT idle

    OKAY no-op; no new completion interrupt

    START and ABORT in one committed write

    ABORT wins; no start snapshot or new operation ID. Busy: graceful abort; idle: no-op. Response OKAY under this explicit policy

    RECOVER alone, fault latched and admission closed

    OKAY only if old owners are already delivered/cancelled, shared cancellation is complete and peer clock health is qualified. Start a fresh supervisor flush/release barrier; bus OKAY acknowledges this request, not recovery completion

    RECOVER while peer stopped, cancellation incomplete or no fault

    SLVERR; remain closed/faulted, do not invent peer acknowledgement or discard an offered beat

    RECOVER combined with START or ABORT

    SLVERR; no command action or new snapshot. This invalid combination is separate from the legal START+ABORT priority above

    COEFF/PACKETS/enable configuration while busy

    SLVERR, no change; a STATUS/IRQ W1C remains legal and cannot restore recovery readiness

    A START, a rejected write, then ABORT

    The trace below follows one operation: idle COEFF = 0x4000, START at C0, a COEFF = 0x2000 write at C1, DP acknowledgement at C4, and START+ABORT in one write at C5.

    Each slot shows the values just before edge C0 to C6, so a pulse in slot k is what edge Ck commits. state: 0 IDLE, 1 LAUNCH, 2 BUSY, 3 DRAINING.

    • C0: START commits while idle. The snapshot takes 0x4000 and state becomes 1 after the edge.

    • C1: the COEFF write commits while busy. It gets SLVERR, so coeff_q stays 4000 in every later slot.

    • C4: the DP acknowledgement (not drawn) commits; state becomes 2 and the first stream beat uses the 0x4000 snapshot.

    • C5: START and ABORT arrive in one write. ABORT wins: state 3 (drain), no second launch and no new snapshot.

    A later idle write of 0x2000 affects only the next accepted START. Same-edge hardware status set beats W1C, so a newly completed cause stays pending.

    Recovery

    RECOVER is the software-visible retry input to the always-on supervisor. It is accepted only from FAULTED with admission closed.

    • cancellation_complete means archived old-owner retirement and the shared interface-reset acknowledgement, not empty flags alone.

    • peer_clock_qualified is approved clock-health status, not one stale alive bit.

    • During the barrier, busy/fault containment stays in force.

    • On success: clear the active fault/busy state, set recovery_ready, keep old error/IRQ/accounting records and invalidate the old operation. Nothing launches automatically.

    • After success: software reads status, clears sticky causes as needed, then issues a separate START.

    • On failure: the block stays faulted and closed and needs another eligible RECOVER.

    Rules handed to later stages

    • Stage 3 receives accepted start and abort pulses, a stable configuration snapshot, status events and counters. No AXI-Lite or APB channel signal crosses into the streaming datapath.

    • Accepted, delivered, stall, flagged-delivery and discard counts live in IO-owned state that survives local DP and stream-link recovery.

    • DP counter snapshots are separately identified diagnostic fields, not replacements for IO handshakes.

    • Final publication waits for processing/drain acknowledgement; a stopped peer leaves snapshot-valid low.

    • A whole-system POR is a new external session, outside the retained local-reset epoch contract.

    Check yourself Why is START a pulse field rather than a stored RW enable?

    A command is an event. Storing it risks retriggering or requiring software to clear it; the CSR converts an accepted write into one internal cycle.

    Remember

    • A command is an event: the CSR turns one accepted write into one internal pulse.

    • The response reports acceptance, not completion. Status and the interrupt report completion later.

    • A configuration snapshot is taken at START; a write while busy is rejected.

    Rule of thumb: the bus adapter never reaches into datapath state; it hands over pulses, a snapshot and status events.

    Keep going

    • Practice: Design a memory-mapped register interface with read and write support

    • Interview: run a mock interview on this topic

    Related topics

    • Register-map RTL

    • Stage 3: Buffered streams

    Previous

    304 / 350

    Next: Stage 3: Buffered Streams

    Up next

    Up nextStage 3: Buffered Streams

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Stage 4: CDC and Reset
    • Stage 5: Arithmetic and Reliability
    • Stage 6: Verification
    clkstartabortcoeff_wrcoeff_q4000state0123
    START snapshots 0x4000, a COEFF write while busy is rejected, the DP acknowledgement moves LAUNCH to BUSY, and START+ABORT in one write starts a drain