Register Frontend
Register Frontend Role
The register frontend (idma_reg64_2d and siblings) exposes a standard memory-mapped register file through which software configures and launches DMA transfers. It is the most common frontend for general-purpose SoCs.
The register file is described once in SystemRDL (src/frontend/reg/idma_reg.rdl) and generated by PeakRDL regblock. The config-bus attached to the register block is selectable via IDMA_REG_CPUIF (idma.mk):
IDMA_REG_CPUIF | Config bus | Wrapper struct |
|---|---|---|
apb4-flat (default) | APB4 | apb_req_t / apb_rsp_t |
obi-flat | OBI | obi_req_t / obi_rsp_t |
axi4-lite-flat | AXI4-Lite | axi_lite_req_t / axi_lite_rsp_t |
A thin wrapper (src/frontend/reg/tpl/idma_reg.sv.tpl, rendered by MARIO for the selected CPUIF) packs the PeakRDL block’s flat config-bus signals into the matching request/response struct and drives the transfer-ID and launch logic. The register_interface dependency is no longer used.
Parameters
| Parameter | Default | Description |
|---|---|---|
NumRegs | 1 | Number of configuration register ports (parallel access points) |
NumStreams | 1 | Number of independent DMA streams (max 16). Each stream has its own transfer ID counter |
IdCounterWidth | 32 | Width of the transfer ID counter (max 32-bit) |
Programming Sequence
- Write transfer parameters: Set
src_addr,length,dst_addr, and optionallyreps/src_stride/dst_stridefor 2D mode - Write configuration: Set
confwith the desired decouple flags, protocol selection, and ND mode enable. For an on-the-fly compute transfer also setcompute_cfg(see below). Stream selection is implicit in whichnext_id[stream]register you read in the next step - Read
next_id[stream]: This read atomically launches the transfer on the selected stream and returns the assigned transfer ID (0 if the transfer was not set up correctly) - Poll
done_id[stream]: Wait untildone_id >= next_idto confirm completion
Register Map
The register file provides direct access to all fields of the idma_req_t / idma_nd_req_t structs. Software writes the transfer parameters, then reads next_id to atomically submit the request:
Transfer Parameters - set these before launching a transfer:
| Register | Access | Description |
|---|---|---|
src_addr | R/W | Source address for the next transfer |
dst_addr | R/W | Destination address for the next transfer |
length | R/W | Transfer length in bytes |
Configuration - controls decoupling, burst limits, protocol selection, and ND mode:
| Register | Access | Description |
|---|---|---|
conf | R/W | Transfer configuration (see below) |
Control/Status - next_id launches the transfer; done_id signals completion:
| Register | Access | Description |
|---|---|---|
status | RO | Per-stream busy flags |
next_id | RO | Per-stream next transfer ID. Reading launches the transfer |
done_id | RO | Per-stream last completed transfer ID |
ND Mode - only used when enable_nd is set in conf:
| Register | Access | Description |
|---|---|---|
reps | R/W | Number of 2D repetitions (ND mode) |
src_stride | R/W | Source stride between rows (ND mode) |
dst_stride | R/W | Destination stride between rows (ND mode) |
Configuration Register (conf)
| Bits | Field | Description |
|---|---|---|
| 0 | decouple_aw | Enable R-AW coupling (hold write addresses until read data arrives) |
| 1 | decouple_rw | Fully decouple read and write channels |
| 2 | src_reduce_len | Shorten source bursts beyond page-boundary splitting |
| 3 | dst_reduce_len | Shorten destination bursts |
| 6:4 | src_max_llen | Max source burst length as log2(beats) |
| 9:7 | dst_max_llen | Max destination burst length as log2(beats) |
| 10 | enable_nd | Enable ND mode (use previously set reps/src_stride/dst_stride) |
| 13:11 | src_protocol | Source protocol select (protocol_e enum) |
| 16:14 | dst_protocol | Destination protocol select (protocol_e enum) |
Compute Configuration Register (compute_cfg)
Present when on-the-fly compute is elaborated (EnableCompute). The fields are sampled together with the transfer parameters when next_id is read. Leave compute_enable at 0 for a plain copy.
| Bits | Field | Description |
|---|---|---|
| 0 | compute_enable | Enable on-the-fly compute for the launched transfer |
| 4:1 | compute_op | Op selector (idma_pkg::compute_op_e): transpose, mxquant, mxquant_fp16, mxdequant, mxdequant_fp16 |
| 6:5 | transpose_mode | Transpose element size: 1 << transpose_mode bytes (8/16/32/64 bit) |
| 18:7 | transpose_tensor_m | Transpose M dimension in elements (non-zero when transpose enabled) |
| 30:19 | transpose_tensor_n | Transpose N dimension in elements (non-zero when transpose enabled) |
| 31 | - | Reserved |
Multi-Port Arbitration
When NumRegs > 1, multiple register ports can submit transfers concurrently. An internal round-robin arbiter serializes requests to the single backend interface. Each port stalls independently on its next_id read until its request is accepted. This allows multiple cores to share a single DMA without software-level locking.
Worked Example: 1 KiB Transfer
The following register writes launch a 1 KiB AXI-to-AXI transfer from 0x8000_0000 to 0xC000_0000 with R-AW coupling enabled, on stream 0:
// 1. Write transfer parameterswrite(src_addr_low, 0x80000000);write(src_addr_high, 0x00000000);write(dst_addr_low, 0xC0000000);write(dst_addr_high, 0x00000000);write(length_low, 1024);write(length_high, 0);
// 2. Write configuration: decouple_aw=1, everything else default (AXI=0)write(conf, 0x1); // bit 0 = decouple_aw
// 3. Read next_id[0] - launches the transfer, returns transfer IDtid = read(next_id_0);
// 4. Poll for completionwhile (read(done_id_0) < tid);Worked Example: 2D Transfer
The following register writes launch a 2D transfer copying 4 rows of 64 bytes with different source and destination strides:
// 2D example: copy 4 rows of 64 bytes, src stride 256, dst stride 64write(length_low, 64);write(length_high, 0);write(src_addr_low, 0x80000000);write(src_addr_high, 0x00000000);write(dst_addr_low, 0xC0000000);write(dst_addr_high, 0x00000000);write(reps, 4);write(src_stride_low, 256);write(src_stride_high, 0);write(dst_stride_low, 64);write(dst_stride_high, 0);write(conf, 0x401); // bit 0 = decouple_aw, bit 10 = enable_ndtid = read(next_id_0);while (read(done_id_0) < tid);Source Files
- Register description:
src/frontend/reg/idma_reg.rdl(SystemRDL, generated by PeakRDLregblock) - Config-bus wrapper template:
src/frontend/reg/tpl/idma_reg.sv.tpl - CPUIF selection:
IDMA_REG_CPUIFinidma.mk - Generated output:
target/rtl/idma_reg64_2d.sv,target/rtl/idma_reg32_3d.sv,target/rtl/idma_reg64_1d.sv(plus the PeakRDL*_reg_top.sv,*_reg_pkg.sv,*_addrmap_pkg.sv)