Direct Memory Access (DMA)

The SEP DMA copies data between addressable memories and peripheral registers, with optional inline SHA-256, SHA-384 or SHA-512 hashing, and fills memory with zeros. It uses the OpenTitan DMA Controller inside an AXI wrapper, with the zero fill added. The integration below defines which upstream ports and hardware triggers are available in SEP. The Programmer’s Guide gives the programming guidance for this block.

Source and destination addresses independently support incrementing, fixed address and wrap-at-chunk-boundary operation. Use incrementing addresses for memory and a fixed address for a peripheral FIFO. Transfers use 1-, 2- or 4-byte accesses; inline hashing requires 4-byte transfers. The core issues individual TL-UL transactions, so the AXI wrapper does not turn a copy into a burst transfer. Hash results are read from the DMA digest registers.

OpenTitan DMA core and inline hashing reference architecture
Figure 1. OpenTitan DMA core and inline hashing reference architecture

OpenTitan DMA core and inline hashing reference architecture shows the upstream DMA core. SEP adapts the host register interface to its AXI fabric as described below.

1. OCAH Modifications

SEP secure DMA integration shows how sep_dma_wrap connects the DMA core to the SEP local crossbar. The register path runs left to right along the top and the host path right to left along the bottom; green boxes are converters, and the dashed ports are tied off.

sep_dma_wrap with the secure_dma core, its register-path and host-path converters, the local alias remap and the tied-off CTN and SYS ports
Figure 2. SEP secure DMA integration

The wrapper exposes separate AXI4 register-slave and DMA-master interfaces, both with 32-bit addresses and 64-bit data. Internally, the register path converts AXI4 to 32-bit AXI4-Lite and then TL-UL; the data path converts the core’s TL-UL host port back to AXI4. A local-alias remapper precedes the SEP crossbar and leaves the CPU TCM backdoor range available to DMA.

Address-space ID 0x7 selects the core’s internal host port, the only route in this wrapper. The upstream SoC control and system ports are tied off; their ASIDs do not provide additional SEP routes. Reachability is governed by the SEP fabric and filters.

The master path leaves AxUSER at zero and drives AxPROT 0b001 (privileged, secure, data), the value the SEP CPU’s LSU drives; TL-UL carries no protection attributes, so the wrapper sets it. The register and host bridges latch faults on dma_reg_bus_err_o and dma_host_intg_err_o, cleared through DMA_BUS_ERR_CLEAR; local alert receivers aggregate the core alerts into dma_alert_o. Selecting the tied-off CTN or SYS address space does not complete.

Only handshake input 0 is connected, to the SPI host’s LSIO trigger. All other trigger inputs are tied low; SEP does not wire UART or I3C handshake paths. This does not prevent software-initiated accesses to reachable peripheral registers.

1.1. Configuration Taken at Each Start

A start is a write of CONTROL.GO while STATUS.BUSY is clear: the first chunk of a transfer, with INITIAL_TRANSFER set, or a later chunk, with GO alone. The engine takes OPCODE and DIGEST_SWAP at the first start of a transfer and keeps them for its later chunks. It takes HARDWARE_HANDSHAKE_ENABLE, RANGE_VALID, ENABLED_MEMORY_RANGE_BASE and ENABLED_MEMORY_RANGE_LIMIT at every start, so a range narrowed or locked between chunks bounds the next chunk. The upstream DMA takes all of them at the first start only.

1.2. Zero Fill

CONTROL.OPCODE 4 (ZERO) is an operation the upstream DMA does not have. A zero fill writes zeros to TOTAL_DATA_SIZE bytes from the destination address and never reads the source, so erasing memory needs no buffer of zeros that software prepares and that another initiator could change during the fill. Destination address modes, transfer widths, chunking, completion and error reporting, interrupts and CONTROL.ABORT behave as they do for a copy.

  • The fill writes only inside the enabled memory range, from ENABLED_MEMORY_RANGE_BASE to ENABLED_MEMORY_RANGE_LIMIT inclusive, whatever the address spaces. The engine checks each write before it issues it, so the bound holds across chunks and in every address mode. The first write that would leave the range is not issued: the fill stops with STATUS.ERROR and ERROR_CODE.DST_ADDR_ERROR, and the writes before it remain. Every start takes the range again (Configuration Taken at Each Start), so locking it with RANGE_REGWEN, also between chunks, fixes this erase window until reset. The range does not bound a copy between internal addresses.

  • The source registers are not used, but they are validated as for a copy, so program SRC_ADDR_LO and SRC_ADDR_HI as 0 with source address-space ID 0x7.

  • A zero fill cannot run in hardware handshake mode. With HARDWARE_HANDSHAKE_ENABLE set at any start, a later chunk included, it ends in ERROR_CODE.OPCODE_ERROR when the first trigger arrives.

  • When the size is not a multiple of the transfer width, the last write covers only the remaining bytes.

  • A zero fill writes no byte past TOTAL_DATA_SIZE. A start with no bytes left, such as GO alone after the last chunk, ends in ERROR_CODE.SIZE_ERROR without a write.

  • ICCM and DCCM take only whole 32-bit words from the DMA. A zero fill there needs 4-byte transfers, a 4-byte-aligned destination and a size that is a multiple of 4; any other write ends in ERROR_CODE.BUS_ERROR and sets the host-path fault in DMA_BUS_ERR_STATUS.

  • The internal register that carries a word from the read to the write of a copy holds zero after a zero fill, so the engine keeps no word of an earlier copy.

1.3. Completion Reporting

The core reports transaction completion, chunk completion and error separately. Chunk completion applies to multi-chunk transfers without hardware handshake; it is not a per-trigger interrupt in handshake mode. Status completion and error bits are write-one-to-clear; the detailed register map defines each bit. Inline hashing requires 4-byte transfers, and DIGEST_SWAP controls byte order within each digest register, not register order. The SEP DMA section of the Programmer’s Guide gives the copy, hashing, handshake and abort sequences.

2. Future Enhancements

The following are proposals, not capabilities of the current SEP integration:

  • Inline AES encryption or decryption (with/without inline hashing)

  • Inline hashing with only digest written to target slave

  • Optimize implementation by using cryptographic resources (AES, HMAC-SHA2) engines inside the cryptographic subsystem and adding streaming interfaces

  • Replace the FSM controller with a microsequencer or simple CPU, potentially shared with the Key Manager

3. Memory Map and Register Reference

3.1. Memory Map

Register offsets are relative to the block base in the subsystem memory map. The detailed map below defines each register and its fields.

3.2. Detailed Register Map

DMA Controller

DMA Controller for the integrated OpenTitan.

Register Arrays:

  • SHA2_DIGEST_0[16]: 16 registers, base 0x58, stride 0x4
  • INTR_SRC_ADDR_0[11]: 11 registers, base 0xA4, stride 0x4
  • INTR_SRC_WR_VAL_0[11]: 11 registers, base 0x124, stride 0x4

Register List:

AddressNameAccessDescription
0x0INTR_STATER-
0x4INTR_ENABLERW-
0x8INTR_TESTW-
0xCALERT_TESTW-
0x10SRC_ADDR_LORW-
0x14SRC_ADDR_HIRW-
0x18DST_ADDR_LORW-
0x1CDST_ADDR_HIRW-
0x20ADDR_SPACE_IDRW-
0x24ENABLED_MEMORY_RANGE_BASERW-
0x28ENABLED_MEMORY_RANGE_LIMITRW-
0x2CRANGE_VALIDRW-
0x30RANGE_REGWENRW-
0x34CFG_REGWENR-
0x38TOTAL_DATA_SIZERW-
0x3CCHUNK_DATA_SIZERW-
0x40TRANSFER_WIDTHRW-
0x44CONTROLRW-
0x48SRC_CONFIGRW-
0x4CDST_CONFIGRW-
0x50STATUSRW-
0x54ERROR_CODER-
0x58 - 0x94SHA2_DIGEST_0[16]R-
0x98HANDSHAKE_INTR_ENABLERW-
0x9CCLEAR_INTR_SRCRW-
0xA0CLEAR_INTR_BUSRW-
0xA4 - 0xCCINTR_SRC_ADDR_0[11]RW-
0x124 - 0x14CINTR_SRC_WR_VAL_0[11]RW-

Register Details:

INTR_STATE

BitsFieldAccessResetDescription
31:3Reserved--Reserved
2DMA_ERRORR0x0DMA error has occurred. DMA_STATUS.error_code register shows the details.
1DMA_CHUNK_DONER0x0Indicates the transfer of a single chunk has been completed.
0DMA_DONER0x0DMA operation has been completed.

INTR_ENABLE

BitsFieldAccessResetDescription
31:3Reserved--Reserved
2DMA_ERRORRW0x0Enable interrupt when !!INTR_STATE.dma_error is set.
1DMA_CHUNK_DONERW0x0Enable interrupt when !!INTR_STATE.dma_chunk_done is set.
0DMA_DONERW0x0Enable interrupt when !!INTR_STATE.dma_done is set.

INTR_TEST

BitsFieldAccessResetDescription
31:3Reserved--Reserved
2DMA_ERRORW0x0Write 1 to force !!INTR_STATE.dma_error to 1.
1DMA_CHUNK_DONEW0x0Write 1 to force !!INTR_STATE.dma_chunk_done to 1.
0DMA_DONEW0x0Write 1 to force !!INTR_STATE.dma_done to 1.

ALERT_TEST

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0FATAL_FAULTW0x0Write 1 to trigger one alert event of this kind.

SRC_ADDR_LO

BitsFieldAccessResetDescription
31:0SRC_ADDR_LORW0x0Lower 32 bits of the source address.
Must be aligned to the transfer width.

SRC_ADDR_HI

BitsFieldAccessResetDescription
31:0SRC_ADDR_HIRW0x0Upper 32 bits of the physical or virtual address of memory location within SoC memory address map or physical address within OT non-secure memory space.
Must be aligned to the transfer width.
Source and destination address must have the same alignment.

DST_ADDR_LO

BitsFieldAccessResetDescription
31:0DST_ADDR_LORW0x0Lower 32 bits of the destination address.
Must be aligned to the transfer width.
Source and destination address must have the same alignment.

DST_ADDR_HI

BitsFieldAccessResetDescription
31:0DST_ADDR_HIRW0x0Upper 32 bits of the physical or virtual address of memory location within SoC memory address map or physical address within OT non-secure memory space.
Must be aligned to the transfer width.
Source and destination address must have the same alignment.

ADDR_SPACE_ID

BitsFieldAccessResetDescription
31:8Reserved--Reserved
7:4DST_ASIDRW0x7Target address space that the destination address pointer refers to.
3:0SRC_ASIDRW0x7Target address space that the source address pointer refers to.

ENABLED_MEMORY_RANGE_BASE

BitsFieldAccessResetDescription
31:0BASERW0x0Base Address to mark the start of the DMA enabled memory range within the OT internal memory space.

ENABLED_MEMORY_RANGE_LIMIT

BitsFieldAccessResetDescription
31:0LIMITRW0x0Limit Address to mark the end of the DMA enabled memory range within the OT internal memory space; inclusive.

RANGE_VALID

BitsFieldAccessResetDescription
31:1Reserved--Reserved
0RANGE_VALIDRW0x0Once set the enabled memory base and limit registers are valid.

RANGE_REGWEN

BitsFieldAccessResetDescription
31:4Reserved--Reserved
3:0REGWENRW0C0x6Used by firmware to lock the DMA enabled memory range configuration registers from further modification.
Once this register is set to kMultiBitBool4False, it can only be set to kMultiBitBool4True through a reset event.

Default Value = kMultiBitBool4True -> Unlocked at reset.

CFG_REGWEN

BitsFieldAccessResetDescription
31:4Reserved--Reserved
3:0REGWENR0x6Used by hardware to lock the DMA configuration registers.
This register is purely managed by hardware and only software readable.

TOTAL_DATA_SIZE

BitsFieldAccessResetDescription
31:0DATA_SIZERW0x0Total size (in bytes) of the data to be transferred. The complete transfer operation
may consist of multiple chunks of data as specified by the CHUNK_DATA_SIZE register.

Minimum: 1 byte.
Maximum: May be restricted to a maximum pre-defined size based on OT DMA enabled memory space allocation.
Works in conjunction with the TRANSFER_WIDTH register.

CHUNK_DATA_SIZE

BitsFieldAccessResetDescription
31:0DATA_SIZERW0x0Size (in bytes) for a single DMA transfer.
In hardware handshake mode, the DMA reads in chunks of CHUNK_DATA_SIZE from the peripheral.
For a single memory transfer CHUNK_DATA_SIZE and TOTAL_DATA_SIZE are set to the same value.

Minimum: 1 byte.
Maximum: May be restricted to a maximum pre-defined size based on OT DMA enabled memory space allocation.
Works in conjunction with the TRANSFER_WIDTH register.

TRANSFER_WIDTH

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1:0TRANSACTION_WIDTHRW0x2Denotes the width of each transaction that the DMA shall issue during the data movement.

Multiple transactions of this width will be issued until TOTAL_DATA_SIZE bytes have been transferred.
Note that firmware may need to set a different value if a receiving IP supports a read / write transaction width that is less than 1 DWORD.
This does not affect the wrap-around mechanism.
Note that the value 3 for this register represents an invalid configuration that leads to an error.

CONTROL

BitsFieldAccessResetDescription
31GORW0x0Setting this bit triggers the DMA operation.
For normal operation, the DMA engine clears the `go` bit automatically after the configured operation is complete.
For Hardware handshake operation, DMA engine does not auto clear the Go bit.
Firmware shall clear the Go bit when it intends to stop the hardware handshake operation.
30:28Reserved--Reserved
27ABORTW0x0Aborts the DMA operation if this bit is set.
Sets the corresponding bit in the status register once abort operation is complete.
Any OpenTitan-internal transactions are guaranteed to complete, but there are no guarantees on the SoC interface.
26:9Reserved--Reserved
8INITIAL_TRANSFERRW0x0Marks the initial transfer to initialize the DMA and SHA engine for one transfer that can span over multiple single DMA transfers.
Used for hardware handshake and ordinary transfers, in which multiple transfers contribute to a final digest.
Note, for non-handshake transfers with inline hashing mode enabled, this bit must be set to also mark the first transfer.
7:6Reserved--Reserved
5DIGEST_SWAPRW0x0Digest register byte swap.

If 1 the value in each digest output register is converted to big-endian byte order.
This setting does not affect the order of the digest output registers, !!SHA2_DIGEST_0 still contains the first 4 bytes of the digest.
4HARDWARE_HANDSHAKE_ENABLERW0x0Enable hardware handshake mode.
Used to clear FIFOs from low speed IO peripherals receiving data, e.g., I3C receive buffer.
Listen to an input trigger signal.
Read data from source address location.
Copy to destination address.
Number of bytes specified in size register.
Note assumption is the peripheral lowers input once FIFO is cleared.
No explicit clearing necessary.
3:0OPCODERW0x0Defines the type of DMA operations.

SRC_CONFIG

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1WRAPRW0x0When 0: Chunks occupy contiguous ascending addresses.
When 1: Source address wraps back to the starting address when finishing a chunk.
0INCREMENTRW0x0Defines the increment behavior after every DMA read.
When 0: Source address is not changed.
All reads are done from the same address.
When 1: Source address is incremented by transfer_width after each read.

DST_CONFIG

BitsFieldAccessResetDescription
31:2Reserved--Reserved
1WRAPRW0x0When 0: Chunks occupy contiguous ascending addresses.
When 1: Destination address wraps back to the starting address when finishing a chunk.
0INCREMENTRW0x0Defines the increment behavior after every DMA write.
When 0: Destination address is not changed.
All writes are done to the same address.
When 1: Destination address is incremented by transfer_width after each write.

STATUS

BitsFieldAccessResetDescription
31:6Reserved--Reserved
5CHUNK_DONERW1C0x0Transfer of a single chunk is complete.
Only raised for multi-chunk memory-to-memory transfers.
Cleared automatically by the hardware when starting the transfer of a new chunk.
4SHA2_DIGEST_VALIDR0x0Indicates whether the SHA2_DIGEST register contains a valid digest.
This value is cleared on the initial transfer and set when the digest is written.
3ERRORRW1C0x0Error occurred during the operation.
ERROR_CODE register denotes the source of the error.
2ABORTEDRW1C0x0Set once aborted operation drains.
1DONERW1C0x0Configured DMA operation is complete.
Cleared automatically by the hardware when starting a new transfer.
0BUSYR0x0DMA operation is active if this bit is set.
DMA engine clears this bit when operation is complete.
This bit may be set as long as hardware handshake mode is active and triggered.

ERROR_CODE

BitsFieldAccessResetDescription
31:8Reserved--Reserved
7ASID_ERRORR0x0The source or destination ASID contains an invalid value.
6RANGE_VALID_ERRORR0x0The DMA enabled memory range is not configured.
5BASE_LIMIT_ERRORR0x0The base and limit addresses contain an invalid value.
4BUS_ERRORR0x0The bus transfer returned an error.
3SIZE_ERRORR0x0TRANSFER_WIDTH encodes an invalid value, TOTAL_DATA_SIZE or CHUNK_SIZE are zero, or inline hashing is not using 32-bit transfer width
2OPCODE_ERRORR0x0Opcode is invalid.
1DST_ADDR_ERRORR0x0Destination address is invalid.
0SRC_ADDR_ERRORR0x0Source address is invalid.

SHA2_DIGEST_0[16]

BitsFieldAccessResetDescription
31:0DATA_0R0x0SHA2 digest data

HANDSHAKE_INTR_ENABLE

BitsFieldAccessResetDescription
31:11Reserved--Reserved
10:0MASKRW0x7FFEnable bits for incoming handshake interrupt wires.

CLEAR_INTR_SRC

BitsFieldAccessResetDescription
31:11Reserved--Reserved
10:0SOURCERW0x0Source N needs interrupt cleared

CLEAR_INTR_BUS

BitsFieldAccessResetDescription
31:11Reserved--Reserved
10:0BUSRW0x0Bus selection bit for source N.

INTR_SRC_ADDR_0[11]

BitsFieldAccessResetDescription
31:0ADDR_0RW0x0Destination address for interrupt source clearing write.

INTR_SRC_WR_VAL_0[11]

BitsFieldAccessResetDescription
31:0WR_VAL_0RW0x0Write value for interrupt clearing write.