DMA Cyclic Mode Operation - Unable to stream data

Hello

I am working with ZCU111 board and quite new to PYNQ especially with DMA. I want to stream some large chunk of data from DDR to PL through MM2S port of DMA and want to play the data cyclically.

I am aware that Cyclic mode requires SG enabled and is not officially supported. So I will try to program the registers. So I made a design as below:

The DMA settings are:

The True Dual Port BRAM write and read widths are 32 and has depth of 2048.
The Address mapping is as follows:

To test initially I generated two buffers as follows:

from pynq import MMIO
mmio_dma=MMIO(ol.ip_dict['axi_dma_0']['phys_addr'],ol.ip_dict['axi_dma_0']['addr_range'])
mmio_bram_ps=MMIO(0x00_A000_0000,8192)
mmio_bram_sg=MMIO(0x0000_0000_A000_0000,8192)

data_size = 100
input_buffer = allocate(shape=(data_size,), dtype=np.uint16)
input_buffer2 = allocate(shape=(data_size,), dtype=np.uint16)
for i in range(data_size):
    input_buffer[i]=i+0x0000
    input_buffer2[i]=0x00C8-i

I thought to use BRAM to hold descriptors. So I am programming the descriptors into BRAM as follows (as per instructions given in PG021 Table 2-25AXI DMA LogiCore IP)

mmio_bram_ps.write(0x00,mmio_bram_ps.base_addr+0x34)
mmio_bram_ps.write(0x04,0)
mmio_bram_ps.write(0x08,input_buffer.physical_address)
mmio_bram_ps.write(0x0C,0)
mmio_bram_ps.write(0x10,0)
mmio_bram_ps.write(0x14,0)
mmio_bram_ps.write(0x18,0x08000100)
mmio_bram_ps.write(0x1C,0)
mmio_bram_ps.write(0x20,0)
mmio_bram_ps.write(0x24,0)
mmio_bram_ps.write(0x28,0)
mmio_bram_ps.write(0x2C,0)
mmio_bram_ps.write(0x30,0)

mmio_bram_ps.write(0x34,mmio_bram_ps.base_addr)
mmio_bram_ps.write(0x38,0)
mmio_bram_ps.write(0x3C,input_buffer2.physical_address)
mmio_bram_ps.write(0x40,0)
mmio_bram_ps.write(0x44,0)
mmio_bram_ps.write(0x48,0)
mmio_bram_ps.write(0x4C,0x04000100)
mmio_bram_ps.write(0x50,0)
mmio_bram_ps.write(0x54,0)
mmio_bram_ps.write(0x58,0)
mmio_bram_ps.write(0x5C,0)
mmio_bram_ps.write(0x60,0)
mmio_bram_ps.write(0x64,0)

After this I am programming the current descriptor according to steps given in PG021 for SG mode and DMA Register Address Map (https://docs.xilinx.com/r/en-US/pg021_axi_dma/AXI-DMA-Register-Address-Map)

mmio_dma.write(0x08,mmio_bram_ps.base_addr)
mmio_dma.write(0x0C,0)
mmio_dma.write(0x00,0x00010013)

mmio_dma.write(0x10,mmio_bram_ps.base_addr+0x34)
#mmio_dma.write(0x10,0x50)
mmio_dma.write(0x14,0)

Even after programming this way following the procedure, I am getting at the output only the contents of first buffer. Second buffer contents are not being streamed.

Where am I making a mistake? Please help.

Thank You

1 Like

Hi sramk

If you are using PYNQ v3.0.1 then you should be able to use cyclic mode with the PYNQ DMA driver.

Although undocumented, you can have a look through the code that implements it (search for “cyclic”).

You can use it in much the same way as you would with other DMA transfers, but explicitly setting the cyclic parameter to True e.g. dma.sendchannel.transfer(buffer, cyclic=True). It is set to False by default.

A few things to note about cyclic mode:

  • It is only available on the sendchannel, not the recvchannel
  • The wait() function it not available.
  • Use the stop() function to halt operation.

Hope this helps,

Josh

2 Likes

Hi @joshgoldsmith

Thank you for the info. But I am using PYNQ 2.7. Can you help me resolve this issue?

1 Like

It might be possible to swap out the v3.0.1 driver for the v2.7 one. I Haven’t tested this, so there might be some issues, but it’s worth trying at least.

Josh

1 Like