System-level flow
The SEC module connects a firmware-facing APB interface to an authenticated storage path. The Main FSM coordinates ASCON, a nonce counter, FIFOs, and the Quad-SPI master. Plaintext is accepted through the APB write path; external flash stores associated data, ciphertext, and authentication tags.
The diagram on the right updates with each section. Highlighted modules indicate which part of the implementation is active in the described phase.
Reading the colours: ■ plaintext / APB traffic · ■ ciphertext · ■ metadata, counters, AD · ■ key material, tags, control
APB request format
The SoC talks to the SEC module through a plain AMBA APB slave port. Each transfer
carries an address (PADDR, the lower 10 bits select one of the SEC
registers), a direction (PWRITE), and on writes a 32-bit payload
(PWDATA).
- Writes complete with zero wait states. Side effects occur only in the ACCESS phase, when
PSELandPENABLEare both asserted. - Status reads are forwarded to the Main FSM; the gateway holds
PREADYlow for the round trip. PSLVERRis never raised — errors are reported through status registers instead, and reads of invalid targets return the sentinel0xDEAD_BEEF.
Encrypt request
Page address → 0x064, trigger 0x044, 58 plaintext words → 0x068…0x14C, trigger 0x044 again.
Decrypt request
A single write to 0x048 with the 24-bit flash page address.
Gateway decoding and request staging
status_ctrl is the only block that ever touches the bus. It decodes
the address into four regions: status registers, trigger registers, the
debug-key window, and the 58-word data window.
During a write sequence, it counts exactly
58 consecutive word addresses into the TX FIFO and remembers every
violation — a gap in the addresses, a 59th word, a full FIFO. When software closes
the sequence at 0x044, the result is binary:
- Valid sequence → a one-cycle
tx_validpulse posts a pending write request to the Main FSM. - Invalid sequence →
seq_erroris latched and the FIFO is flushed.
One request at a time. A single request slot holds the pending
write or read request. A second request while one is outstanding is
rejected and latches the sticky req_dropped bit (0x030[23]).
Main FSM sequencing
The Main FSM is the top-level controller for the module. It validates requests, decides when the flash is erased, when the counter increments, which command ASCON runs, and when status flips back to ready.
Its control fan-out, visible on the right, reaches every subsystem:
- ASCON — gets one of three commands:
KEY_VALIDATE,ENCRYPT,DECRYPT. - Counter —
RESTOREat boot,INCREMENTper encryption. - QSPI — atomic FIFO entries: erase sector, program word, read word.
- Fuzzy Extractor — only during boot (separate page).
While it is active, busy is high and new requests wait on the request slot.
Every state is observable at 0x008 — the full map lives on the
Main FSM page.
Address validation and erase decision
The FSM first checks the target: the page address must lie in the application
area (≥ 0x002000) and be 256-byte aligned. A bad address ends the
request immediately with ERR_BAD_SECTOR — no flash access happens.
Flash programming requires an erased target region. To limit erase cycles, a 4 KB sector erase is issued only when the target is the first page of its sector. The 15 following pages program straight into the already-erased space.
- Erase command travels as one atomic FIFO entry to the QSPI master.
- The master runs Sector Erase (
0x20) and polls the flash's busy flag until the sector reads blank. - The FSM waits for
qspi_idlebefore touching the counter.
Nonce and associated data
AEAD encryption requires nonce uniqueness, so every encryption increments a 39-bit
counter. Writing the counter to flash on every
increment would increase wear; instead counter_control keeps a
reservation ceiling in NVM: only once every 100 increments does it persist
a new ceiling, always before the nonce is used. An interrupted operation can
skip reserved values, but it does not reuse them.
From counter + address, the module derives ASCON's metadata:
nonce = { addr[23:0], 65'b0, counter[38:0] } // 128 bit, unique per record
AD = { backdoor_flag, counter[38:0], addr[23:0] } // 64 bit
The two AD words are written to the page in plaintext because they must be read before decryption. They are still authenticated by the ASCON tag.
ASCON processing and flash programming
Now the FSM issues CMD_ENCRYPT and steps aside. ASCON pulls the 58
plaintext words out of the TX FIFO one by one, runs ASCON-AEAD128 with the
PUF-derived key, and pushes each 32-bit ciphertext word straight into the QSPI
command FIFO — addressed word-precisely into the page's ciphertext field.
- The TX FIFO drains as ASCON consumes data; QSPI programming proceeds as ASCON produces ciphertext. Plaintext is not written to flash.
- After the last message word, the core emits the 128-bit tag — four more words, landing at page offset
0xF0. - Back-pressure is wired through: if the QSPI FIFO fills, ASCON simply stalls.
No separate commit marker is used. A page is accepted only if its ASCON tag authenticates. Blank or modified pages fail the same check.
Completion and status update
The FSM counts outstanding QSPI commands and waits until the flash has physically
committed every word (pending == 0 and the master idle). Only then:
operation_donepulses; if enabled, irq_3 fires.- The state returns to
M_READY—0x000reads ready=1, busy=0. - The request slot is free; the next request may start.
Software that skipped the interrupt simply polls 0x000 until
ready reappears, then checks error/0x004 for the
result.
Read request format
A read request is a single APB write to 0x048, carrying the 24-bit
page address in PWDATA[23:0]. No payload follows — the request
bypasses the data FIFO and lands directly in the request slot as
rd_pending.
When the FSM is ready it validates the address with the same rules as a write (application area, page-aligned), then starts fetching.
vs. encryption
No erase, no counter increment, no TX data — the stored record already fixes nonce and AD.
read flow
Fetch AD → check metadata → fetch ciphertext+tag → decrypt → authenticate → release.
Fetch and metadata checks
The FSM reads the record in two passes. First the two AD words: they tell it which address and counter were used, and whether the record was written under the debug/fallback key. Two inexpensive checks run before decryption:
- the address stored in the AD must equal the requested page, and
- the record's key-source flag must match the key currently loaded — a record written under the PUF key is rejected in debug-key mode, and vice versa.
A mismatch aborts with ERR_AUTH before the flash is read any
further. Otherwise the FSM streams all 62 ciphertext+tag words into an
internal buffer, ready to feed ASCON.
Decryption before release
CMD_DECRYPT starts ASCON with the nonce rebuilt from the
record's own AD — the stored counter and address, not whatever the
requester claimed. The core consumes the 58 ciphertext words and the 4 tag words,
producing plaintext into an internal buffer.
The release rule is enforced by an SVA assertion in the RTL: plaintext must not leave the internal buffer before the tag authenticates.
- Tag valid → 58 plaintext words stream into the RX FIFO; the data-ready status bit rises.
- Tag invalid → buffer is discarded,
ERR_AUTHis latched, the RX FIFO stays empty.
Effect: a change in ciphertext or associated data causes authentication to fail, so modified records are not released as plaintext.
Software collects the plaintext
The hand-off back to firmware is a two-register protocol:
- Poll
0x038(RX_READY) until it reads 1. - Pop
0x03C(RX_DATA) — each read returns one word and advances the FIFO; 58 reads drain the record.
Required order: A read of 0x03C while no data is valid
returns 0xDEAD_BEEF and raises rd_fail — which the FSM
treats as a protocol error: it flushes the FIFOs and reports
ERR_MC_PROTOCOL. Firmware should poll first, then pop data.
Summary of the complete flow
Plaintext crosses the hardware boundary only at the APB interface: inbound for encryption and outbound after authenticated decryption. Data stored in flash is encrypted and covered by an authentication tag.
Two kinds of failure exist, and they are deliberately different:
request errors (bad address, protocol error, failed authentication) flush
the FIFOs, report a code and return to M_READY; fatal errors
(key recovery failure, flash address violation, counter corruption) move the
module to M_FATAL_ERROR until reset.
Continue with:
- Startup & Enrollment — how the key is reconstructed without storing it in NVM.
- Main FSM — all 47 states, mapped.
- Flash & QSPI — how the records reach the NVM flash.
- Verification — simulation, assertions, and FPGA validation.
- Register reference — the firmware writer's view.