Register Map¶
Note
The tables on this page are generated at docs-build time from
docs/regs.yaml (docs/gen_regmap.py) — the YAML file is the single
source of truth. The same generator also produces the C header
sw/include/qspi_regs.h (register offsets, bit fields, field
encodings), which is checked into the repository so software can consume it
without running the generator; CI fails if it is out of date. Register
changes must be made in the YAML file (and in the RTL, src/qspi_pkg.sv),
never in this page or the header.
Base address: 0x2000_0000 (hatch SoC, window UserQspiCfg)
Offset |
Register |
Reset |
Description |
|---|---|---|---|
|
|
Control Register |
|
|
|
Device Configuration Register |
|
|
|
Status Register (read-only) |
|
|
|
Flag Clear Register |
|
|
|
Data Length Register |
|
|
|
Communication Configuration Register (frame format + functional mode) |
|
|
|
Address Register |
|
|
|
Alternate Bytes Register |
|
|
— |
Data Register (FIFO port) |
|
|
|
Write Communication Configuration Register (frame format for memory-mapped WRITES) |
CR — offset 0x00¶
Control Register.
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
EN |
RW |
Controller enable. 0 = all commands/mmap accesses rejected. |
|
ABORT |
RW |
Abort the running transfer; flushes the FIFO. Self-clearing once the sequencer is idle. Mandatory flow for leaving memory-mapped mode. |
|
PRESCALER |
RW |
SCK divider: SCK = clk / (2*(PRESCALER+1)). |
DCR — offset 0x04¶
Device Configuration Register.
Reset: 0x00000010
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
FSIZE |
RW |
Device size = 2^(FSIZE+1) bytes. Reset 16 -> 128 KiB (23LC1024). W25Q128JV flash: 23 -> 16 MiB. Change only while SR.BUSY=0. |
|
CSHT |
RW |
Minimum CS-high time between two commands, in SCK cycles. Change only while SR.BUSY=0. |
SR — offset 0x08¶
Status Register (read-only).
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
TEF |
RO |
Transfer Error Flag: indirect command with address+length beyond FSIZE (the command was not started). Clear via FCR.CTEF. |
|
TCF |
RO |
Transfer Complete Flag: all DLR+1 data bytes transferred. Clear via FCR.CTCF; cleared automatically when the next command starts. |
|
BUSY |
RO |
Sequencer active (incl. CS tail and CSHT). Permanently 1 in memory-mapped mode (the prefetch stream is running). |
|
FLEVEL |
RO |
Data-FIFO fill level in bytes (0…32). |
FCR — offset 0x0C¶
Flag Clear Register.
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
CTEF |
W1C |
Writing 1 clears SR.TEF. |
|
CTCF |
W1C |
Writing 1 clears SR.TCF. |
DLR — offset 0x10¶
Data Length Register.
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
DL |
RWnb |
Data length - 1 in bytes for indirect transfers (0 = 1 byte). Ignored in memory-mapped mode. |
CCR — offset 0x14¶
Communication Configuration Register (frame format + functional mode).
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
INSTRUCTION |
RWnb |
Opcode of the instruction phase. |
|
IMODE |
RWnb |
Lanes of the instruction phase: 00 skip / 01 single / 10 dual / 11 quad. |
|
ADMODE |
RWnb |
Lanes of the address phase (same encoding as IMODE). |
|
ADSIZE |
RWnb |
Address bytes - 1 (2 = 24-bit address, both target chips). |
|
ABMODE |
RWnb |
Lanes of the alternate-byte phase (e.g. the mode byte of 0xEB). |
|
ABSIZE |
RWnb |
Alternate bytes - 1. |
|
DCYC |
RWnb |
Dummy cycles in SCK clocks (0 = none). SRAM SQI read: 2 / flash 0x6B/0x0B: 8 / flash 0xEB: 4. |
|
DMODE |
RWnb |
Lanes of the data phase (00 = no data phase). |
|
FMODE |
RWnb |
Functional mode: 00 indirect write / 01 indirect read / 11 memory-mapped. |
AR — offset 0x18¶
Address Register.
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
ADDRESS |
RWnb |
Chip address for indirect commands. A write triggers the command if ADMODE!=00 and (FMODE=01 or DMODE=00). |
ABR — offset 0x1C¶
Alternate Bytes Register.
Reset: 0x00000000
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
ALTERNATE |
RWnb |
Alternate bytes (MSByte sent first). Also used for the read frames in memory-mapped mode. |
DR — offset 0x20¶
Data Register (FIFO port). Reset: —
Bits |
Field |
Access |
Description |
|---|---|---|---|
|
DATA |
RW |
Direct FIFO access. Transfer width = asserted byte enables (sb->1, sh->2, sw->4 bytes). A write pushes (and triggers the command when FMODE=00, DMODE!=00, BUSY=0); a read pops. Contract: push exactly DLR+1 bytes; check SR.FLEVEL before reading. |
WCCR — offset 0x24¶
Write Communication Configuration Register (frame format for memory-mapped WRITES).
Reset: 0x00000000
Identical field layout to CCR; FMODE is ignored. WCCR.DMODE=00 blocks mmap writes (bus error) – mandatory for read-only devices (flash).
Fields: see CCR.
Command triggers (indirect mode)¶
A command starts only with SR.BUSY = 0 and CR.EN = 1, triggered by the
last required CSR write:
Write to |
Condition |
Typical case |
|---|---|---|
CCR |
|
instruction-only (EQIO, RSTIO, WREN) or read without address (JEDEC ID, status register) |
AR |
|
read with address; write without data phase |
DR |
|
write with data (the first DR write starts) |
So the order is: configure DLR/CCR/AR first, the trigger write comes last.
Software contracts¶
DR width = byte enables.
sbpushes/pops 1 byte,sh2,sw4. ExactlyDLR+1bytes must be pushed — excess bytes stay in the FIFO and corrupt the next command (remedy:CR.ABORTflushes).No reconfiguration while BUSY. Writes to DLR/CCR/AR/ABR/WCCR are silently ignored while
SR.BUSY=1. PollSR.BUSYfirst or assertCR.ABORT.Leaving mmap only via ABORT. In memory-mapped mode the prefetch stream runs forever (
BUSYstays 1);CR.ABORTends it, flushes the FIFO, and only then does a CCR write (e.g. changingFMODE) take effect.Reads: check
SR.FLEVELbefore reading DR (enough bytes in the FIFO);SR.TCFsignals the end of the whole transfer.Error picture: indirect out-of-range →
SR.TEF(no start); mmap out-of-range /EN=0/FMODE≠11/ write withWCCR.DMODE=00→ OBIerrresponse.Endianness: the chip byte at address A sits on byte lane A mod 4 (little-endian, RISC-V-conformant); the first byte received is the LSB.