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
    • SRAM and ROM
    • Register Files
    • Valid/Ready Handshake
    • AXI-Lite
    • AXI-Stream
    • Bus Integration
    • Synchronous FIFO
    • Register-Map and CSR RTL
    • Memory Reliability
    • Peripheral RTL Integration
      • Peripheral Shell
      • Clock, Reset, and Power Contract
      • Interrupts and Events
      • FIFO and DMA Boundary
      • Errors and Integration Signoff
    • Full AXI4: RTL Roadmap
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Peripheral RTL Integration
  1. Topics
  2. RTL Design
  3. Memory & Buses
  4. Peripheral RTL Integration
  5. Peripheral Shell

Part 7 of 9, lesson 51 of 57Part 7 of 9/Memory & Buses/Lesson 51 of 57Intermediate

Peripheral Shell

Partition the block so bus timing, software-visible state, buffering, and pin protocol can be verified independently.

A peripheral whose engine sees bus signals directly is hard to test and hard to reuse. A thin shell with one accepted-request interface keeps bus timing out of the protocol engine.

After this lesson you can: partition a peripheral into transport, CSR bank, control, datapath and IO timing, and define the accepted-request interface between them.

Partition

Owns

Does not own

Bus adapter

Handshake, response, transport errors

Field side effects

CSR bank

Address decode, access types, reset values

AXI/APB timing

Control FSM

Start/stop, sequencing, timeout

Software bus state

Datapath/FIFO

Serialization, buffering, counters

Interrupt policy

IO wrapper

Synchronizers, pin enables, pad-facing timing

Register map

The peripheral shell as five owners: only accepted operations cross each boundary, so the engine never sees a bus signal

Read the picture from the top: each arrow label is the only thing that crosses that boundary.

  • Accepted operations only. The CSR bank turns a bus request into start_pulse or tx_fifo_push after its reject checks; a rejected request crosses nothing.

  • Two sides of each FIFO. Software or DMA pushes the TX FIFO; the engine pops it. The two must never be confused.

  • Pins live at the bottom. Synchronisers and output enables sit in the IO wrapper, away from the register map.

The CSR boundary enqueues TX words; the SPI engine dequeues them when it can serialize and enqueues RX samples. engine_busy is the single busy owner (including start reservation on the acceptance edge); no separate stale busy_q gates commands. Software and DMA arbitrate for each FIFO port before acceptance. The engine never sees AXI-Lite or APB signals.

Request at internal req_take

CSR response

Side effect owner

TX write while tx_fifo_full

Error, no enqueue; software retains/retries word

CSR boundary

TX write with space and port grant

OK

One tx_fifo_push

RX read while rx_fifo_empty

Error, no dequeue

CSR boundary

START while engine_busy or invalid config

Error plus sticky illegal-command event

CSR boundary; engine unchanged

Legal START

OK

One start_pulse; engine reserves busy immediately

Use the linked CSR single-outstanding contract: acceptance is req_valid && req_ready at an edge; full/empty/busy are sampled there. csr_start_write/csr_tx_write/csr_rx_read below are decoded committed one-cycle req_take pulses, even for a request returning error. Error responses are retained until consumed, and no invalid operation is silently reported as success. RX return data additionally needs the FWFT or registered-result adapter described below.

design.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
// snippet: clean internal contracts
assign start_reject = csr_start_write && (engine_busy || !config_valid);
assign tx_reject    = csr_tx_write && tx_fifo_full;
assign rx_reject    = csr_rx_read && rx_fifo_empty;
assign csr_op_error = start_reject | tx_reject | rx_reject;
assign start_pulse = csr_start_write && !start_reject;
assign tx_fifo_push = csr_tx_write && !tx_reject;
assign rx_fifo_pop  = csr_rx_read && !rx_reject;
// TX engine dequeue is distinct from software/DMA enqueue.
assign tx_fifo_pop = engine_tx_take;
assign busy_o      = engine_busy;
assign done_event  = engine_done;
assign error_event = timeout_error | protocol_error | start_reject;

Illustrative edge

Bus/internal ownership

Result

E0

TX write accepted internally while full

Error response saved; zero pushes

E1/E2

APB ACCESS held or AXI response stalled

Same error held; no replay even if engine frees space

E3

Response consumed

One rejected operation completes

E4

Software retry accepted with space

Exactly one enqueue (not engine dequeue)

E5

START accepted while engine_busy=1

One error + illegal-command cause; zero start pulses

The internal interface names accepted FIFO operations and start events instead of leaking bus channel levels into the engine.

Check yourself Where should a write to TXDATA be rejected when the TX FIFO is full?

At the CSR/peripheral contract boundary, with a documented stall or error policy. The protocol engine should only see accepted FIFO pushes.

  • The engine sees accepted FIFO operations and start events, never bus channel levels.

  • engine_busy has a single owner, including the reservation on the accepting edge.

  • An invalid operation returns an error and is never reported as success.

Rule of thumb: decide who owns each piece of state, then draw the boundary around it.

  • Practice: Memory-mapped register interface with read and write support

  • Interview: run a mock interview on this topic

Related topics

  • Register-map RTL

  • Clock, reset, and power contract

Previous

239 / 350

Next: Clock, Reset, and Power Contract

Up next

Up nextClock, Reset, and Power Contract

Sign in to save progress

Practice this lessonPrevious lessonReport an error

See also

  • Interrupts and Events
  • FIFO and DMA Boundary
  • Errors and Integration Signoff