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
      • CSR Contract and Address Map
      • Field Access Types
      • Hardware/Software Arbitration
      • Byte Strobes and Partial Writes
      • Atomic and Shadowed Updates
      • Interrupt Register Pattern
      • Adapter and Signoff
      • Generated Register Workflow
      • The Firmware Side: a C Driver for W1C, RC and Shadow Registers
    • Memory Reliability
    • Peripheral RTL Integration
    • Full AXI4: RTL Roadmap
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Register-Map and CSR RTL
  1. Topics
  2. RTL Design
  3. Memory & Buses
  4. Register-Map and CSR RTL
  5. CSR Contract and Address Map

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

CSR Contract and Address Map

Specify alignment, decode, reset values, permissions, side effects, and unmapped-address behavior before writing RTL.

Software and hardware disagree silently when the register map is vague: a decoder that ignores high address bits aliases registers, and an undocumented reserved bit becomes a bug the day hardware uses it.

After this lesson you can: write a field-level CSR map with reset values, reserved bits and error responses, and decode it without aliasing.

The register specification is an interface

This is the canonical field-level map used by the decoder, driver and expected-value model. All stored fields reset to zero; busy reflects reset-idle hardware. All unlisted bits read zero and ignore writes. Writes apply only strobed bytes; reads return the pre-operation snapshot.

Address

Name

Fields / readback

Write semantics

0x00

CONTROL

[0] enable RW; [2:1] mode RW (0..3); [8] start reads 0

Start on strobed bit 8=1 only if pre-edge enable=1 and busy=0; otherwise error with no CONTROL update. Engine latches pre-edge mode/LIMIT.

0x04

STATUS

[0] busy RO; [1] done; [2] error

done/error W1C, hardware set wins; busy writes ignored

0x08

IRQ_ENABLE

[3:0] RW: done, config_error, timeout, datapath_fault

Mask notification only; capture continues

0x0C

IRQ_STATUS

[3:0] sticky pending in IRQ_ENABLE order

W1C, set wins. Same event drives corresponding STATUS bit: done -> bit 1; any fault -> bit 2. STATUS and IRQ_STATUS acknowledgements are independent.

0x10

LIMIT_LO

[31:0] low shadow word RW

Merge strobed bytes; any nonzero strobe sets shadow_valid[0]

0x14

LIMIT_HI

[31:0] high shadow word RW

Merge strobed bytes; any nonzero strobe sets shadow_valid[1]

0x18

LIMIT_COMMIT

[0] commit reads 0; [2:1] shadow_valid RO

Strobed bit 0=1 with both words touched copies shadow to active atomically and clears validity. Incomplete commit is an OK no-op retaining shadow/validity; software reads validity and retries.

0x1C / 0x20

LIMIT_ACTIVE_LO / HI

[31:0] active low/high word RO

Writes ignored; software serializes commits while reading both halves

LIMIT active and shadow reset to zero. A successful commit retains shadow data, so later partial writes preserve bytes from that value. The single-request map uses a separate commit write; the helper below also supports final-word-plus-commit for a wider internal caller. RC and W1S examples are teaching variants, not additional mapped fields. Disabled/busy START returns an error and sets config_error; unmapped/misaligned requests return error and no register side effect.

  • Addresses are naturally aligned.

  • Unmapped reads return zero plus an error response; unmapped writes have no effect.

  • Reserved bits read as zero and ignore writes.

  • Every reset value is visible to both RTL and software documentation.

design.sv
1
2
3
4
5
6
7
8
9
10
11
12
// snippet: transport-independent CSR request
typedef struct packed {
  logic        write;
  logic [11:0] addr;
  logic [31:0] wdata;
  logic [3:0]  wstrb;
} csr_req_t;

typedef struct packed {
  logic [31:0] rdata;
  logic        error;
} csr_rsp_t;

Concrete internal transport: one outstanding request total, req_take = req_valid && req_ready at a rising edge. The adapter holds request payload stable through that edge. The CSR bank captures read data/error and performs all side effects exactly once on req_take; it raises registered rsp_valid after that edge and holds response payload through rsp_valid && rsp_ready. req_ready stays low until the response retires (no same-edge replacement). sw_write, csr_write, wr_lo/wr_hi and command pulses below mean decoded req_take, never raw bus levels. Reset flushes the owned request/response epoch under coordinated adapter reset. RC variants capture old data and clear on req_take, with simultaneous hardware set winning; response delivery never clears again.

Each slot is one clock cycle, and a request is taken at the edge that ends its slot. The first read is CONTROL, which returns 5 (enable 1, mode 2); the second is STATUS, which returns 2 (done).

  • Slot 0: req_valid and req_ready are both high, so the CONTROL read is taken at the edge ending slot 0.

  • Slots 1 to 3: the response is valid with data 5. rsp_ready is low in slots 1 and 2, so the response is held, and req_ready stays low: the STATUS read waits.

  • Slot 3: rsp_ready is high, so the response retires at the edge ending slot 3. req_ready rises only in slot 4, never on the retiring edge.

  • Slot 4: the STATUS read is taken; its response 2 is valid and ready in slot 5 and retires.

Do not silently alias addresses by decoding too few bits. Compare the complete implemented word address and define the error response for everything else.

Check yourself What should a reserved bit return after software writes one to it?

Zero. Reserved bits ignore writes and read as zero so future hardware can assign them without inheriting undocumented state.

  • Compare the whole implemented word address. Unmapped and misaligned accesses return an error and have no side effect.

  • Reserved bits read zero and ignore writes, so hardware can use them later.

  • Side effects happen once, on the accepted request, never on a raw bus level.

Rule of thumb: the register map is an interface: every reset value and error response is written down once.

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

  • Code lab: GPIO direction register

  • Interview: run a mock interview on this topic

Related topics

  • Field access types

  • Address decode

Previous

223 / 350

Next: Field Access Types

Up next

Up nextField Access Types

Sign in to save progress

Practice this lessonPrevious lessonReport an error

See also

  • Hardware/Software Arbitration
  • Byte Strobes and Partial Writes
  • Atomic and Shadowed Updates
clkreq_validreq_readyrsp_validrsp_readyrdata052
Two CSR reads on the single-outstanding transport: the first response is stalled for two cycles, and the second request waits until it retires