
TinyDMA-2C is a two-channel byte DMA engine for Tiny Tapeout. It copies data between addresses in an external SPI PSRAM device through a small scheduler, a byte-wide DMA controller, and a single-bit SPI PSRAM controller.
The submitted TinyTapeout-sized build uses 16-bit internal addresses and 8-bit transfer lengths to fit the 1x2 tile budget. The PSRAM controller sends standard SPI read/write commands with a 24-bit address phase; the upper address byte is driven as zero and the internal 16-bit address supplies the lower two bytes.
Configuration enters through the dedicated input bus and two UIO control strobes:
ui_in[7:0]: configuration command or data byteuio_in[0]: cfg_valid strobeuio_in[1]: start strobeuio_in[2]: SPI MISO from the PSRAMThe SPI outputs are on UIO pins 3 through 5:
uio_out[3]: SPI chip select, active lowuio_out[4]: SPI clockuio_out[5]: SPI MOSI to the PSRAMThe bidirectional output-enable mask is fixed at uio_oe = 8'b0011_1000, so only uio[3], uio[4], and uio[5] are driven by the design. Unused UIO outputs are tied low.
Status is reported on uo_out:
uo_out[0]: any DMA channel activeuo_out[1]: done pulse when either channel completesuo_out[2]: channel 0 doneuo_out[3]: channel 1 doneuo_out[4]: channel 0 activeuo_out[5]: channel 1 activeuo_out[6]: configuration adapter is waiting for a data byteuo_out[7]: invalid configuration sequence detectedEach register byte write is sent as two cfg_valid pulses:
Command byte format:
10 for channel 0 and 1 for channel 100 source, 01 destination, 10 length, 11 control0The current build accepts:
The control byte uses:
start pulseThe adapter stores the arm bit separately. When uio_in[1] is pulsed, any armed channel has its internal start bit asserted and the DMA begins.
To configure channel 0 to copy 4 bytes from 0x0010 to 0x0020 with both addresses incrementing, pulse cfg_valid for each byte below:
0x80, payload 0x10: channel 0 source byte 00x84, payload 0x00: channel 0 source byte 10x90, payload 0x20: channel 0 destination byte 00x94, payload 0x00: channel 0 destination byte 10xA0, payload 0x04: channel 0 length0xB0, payload 0x07: channel 0 control, arm plus increment source and destinationThen pulse uio_in[1] to start the armed channel.
The design targets a QSPI PMOD containing APS6404 PSRAM, used here in single-bit SPI mode. The FPGA bring-up used the PMOD connection that maps:
uio[3]uio[4]uio[5]uio[2]The project was checked at several levels:
The GitHub Actions test and gds flows have also been run successfully for the Tiny Tapeout repository.
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | cfg_data[0] | dma_active | cfg_valid |
| 1 | cfg_data[1] | done_pulse | start |
| 2 | cfg_data[2] | ch0_done | spi_miso |
| 3 | cfg_data[3] | ch1_done | spi_cs_n |
| 4 | cfg_data[4] | ch0_active | spi_clk |
| 5 | cfg_data[5] | ch1_active | spi_mosi |
| 6 | cfg_data[6] | cfg_pending | |
| 7 | cfg_data[7] | cfg_error |