# DMA engine

Library: | System On Chip components
Introduced: | 4.1

## Behavior

The DMA engine is a simple linear memory-copy DMA controller. It copies data from a source address to a destination address in configurable bursts, driven by a clock signal. This component is primarily intended to be used with the VGA screen component to efficiently copy image data into the VGA framebuffer, but it can be used for any memory-to-memory transfer.

The DMA engine supports three independent bus connections: one for control register access (the DMA acts as a slave on this bus), one for source reads (master-only), and one for destination writes (master-only). This allows routing data transfers across different SoC buses. If the source or destination bus is not explicitly configured, the control bus is used as a fallback.

### Transfer operation

A transfer is initiated by programming the source address, destination address, and length registers, then writing the START bit in the control register. Once started, the DMA engine copies burst size words (32-bit) per clock cycle until all bytes have been transferred. At the end of the transfer the DONE status bit is set, and optionally an interrupt is raised if IRQ_EN was set in the control register.

While a transfer is in progress (BUSY=1), writes to the SRC_ADDR, DST_ADDR, and LENGTH registers are ignored.

### Performance

With the default burst size of 16 words/tick, the DMA engine can transfer data roughly 80× faster than a CPU-driven memcpy loop (which requires ~5 clock cycles per word due to instruction fetch, decode, and execute overhead).

## Pins

On the west side of the DMA component:

- Reset: Active-high reset input. When asserted, all DMA registers are cleared and any in-progress transfer is aborted.
- Clock: Clock input. On each rising edge, the DMA engine transfers up to burst size words if a transfer is in progress.

On the east side of the DMA component:

- IRQ: Active-high interrupt output. Asserted when a transfer completes and IRQ_EN is set in the CONTROL register. Cleared by writing 1 to the DONE bit in the STATUS register.

## MMIO Register Map

Offset | Register | Access | Description
0x00 | SRC_ADDR | R/W | Source address (must be word-aligned). Writes are ignored while BUSY.
0x04 | DST_ADDR | R/W | Destination address (must be word-aligned). Writes are ignored while BUSY.
0x08 | LENGTH | R/W | Transfer length in bytes (must be a multiple of 4). Writes are ignored while BUSY.
0x0C | CONTROL | R/W | bit 0 (START): Write 1 to start a new transfer (ignored if BUSY or LENGTH=0). bit 1 (IRQ_EN): Set to enable interrupt on transfer completion.
0x10 | STATUS | R/W1C | bit 0 (BUSY): Read-only. 1 while a transfer is in progress. bit 1 (DONE): Write-1-to-clear. Set when a transfer has completed. Writing 1 to this bit clears it and de-asserts the IRQ output.
0x14 | BYTES_DONE | RO | Number of bytes transferred so far. Resets to 0 when a new transfer starts.

## Attributes

- Base address: The start address of the MMIO register region (6 registers, 24 bytes total). Must be word-aligned.
- Burst size: Number of 32-bit words transferred per clock tick. Must be a power of 2 (1, 2, 4, 8, 16, 32, 64, 128, or 256). Default is 16.
- Label: An optional label for the component.
- Label font: Font used for the label.
- Label visible: Whether the label is displayed.
- Connected bus: The bus on which the DMA control registers are accessible as a slave. Click to select a bus component.
- Source bus: The bus used for source (read) data transfers. If not configured, the control bus is used. Click to select a bus.
- Destination bus: The bus used for destination (write) data transfers. If not configured, the control bus is used. Click to select a bus.

## Usage with VGA screen

To use the DMA engine to copy an image into the VGA framebuffer:

1. Place a SOC bus, a Memory simulator, a VGA screen, and the DMA engine on the same sheet.
2. Connect all components to the same bus (or configure separate source/destination buses as needed).
3. Ensure the VGA component is registered as a sniffer on the bus that the DMA writes to, so it can observe the writes and update the display in real time.
4. From your CPU program: write the source image address to SRC_ADDR (0x00), the VGA buffer address to DST_ADDR (0x04), the transfer size to LENGTH (0x08), then write START|IRQ_EN to CONTROL (0x0C) to begin the transfer.
5. Poll the STATUS register or wait for the IRQ to know when the transfer is complete.

Note: DMA write transactions are visible to bus sniffers (such as the VGA component), so the VGA display updates in real time during a DMA transfer. DMA read transactions are hidden from the bus trace to reduce noise.

Back to SOC library