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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
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
On this page

    Part 9 of 9, lesson 31 of 76Part 9 of 9/Senior/Lesson 31 of 76Senior

    Stage 2: CSR and Control

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

    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

    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.

    • 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.

    • 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 lessonPrevious 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