Problem with multiple DMAs

Hi everyone,

I am doing some experiments with DMA. I could get one DMA to work by simply sending the data to a FIFO and reading it back (haven’t used any of the send/recvchannel.wait() functions).
Now I want to try 2 DMAs, again by simply using 2 FIFOs to loop back the data.
But I get the following (first) error after running dma.recvchannel.transfer().
Also, if I use the dma.sendchannel.wait() function (to possibly fix the first error) after dma.sendchannel.transfer(), I get the second error message. Do you have any idea what is causing the issue? Thank you!

First error message:

RuntimeError                              Traceback (most recent call last)
Input In [31], in <cell line: 1>()
----> 1 dma.recvchannel.transfer(output_buffer)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/lib/dma.py:136, in _SDMAChannel.transfer(self, array, start, nbytes)
    107 """Transfer memory with the DMA
    108 
    109 Transfer must only be called when the channel is idle.
   (...)
    133 
    134 """
    135 if not self.running:
--> 136     raise RuntimeError("DMA channel not started")
    137 if not self.idle and not self._first_transfer:
    138     raise RuntimeError("DMA channel not idle")

RuntimeError: DMA channel not started

Second error message:

RuntimeError                              Traceback (most recent call last)
Input In [34], in <cell line: 3>()
      1 dma = overlay.axi_dma_0 #create alias for DMA object
      2 dma.sendchannel.transfer(input_buffer) #automatically includes the physical address
----> 3 dma.sendchannel.wait()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/lib/dma.py:169, in _SDMAChannel.wait(self)
    167 """Wait for the transfer to complete"""
    168 if not self.running:
--> 169     raise RuntimeError("DMA channel not started")
    170 while True:
    171     error = self._mmio.read(self._offset + 4)

RuntimeError: DMA channel not started

I am using Vivado 2022.2 version and Pynq Z2 board.
Here is my Python code and block design:

from pynq import Overlay
from pynq import allocate
import numpy as np

overlay = Overlay("/home/xilinx/pynq/overlays/multi_dma/multi_dma.bit")

data_size = 1000000
input_buffer = allocate(shape=(data_size,), dtype=np.uint32) #~4MB

for i in range (data_size):
    input_buffer[i] = i + 0xcafe0000

dma = overlay.axi_dma_0 
dma.sendchannel.transfer(input_buffer) 
#dma.sendchannel.wait()

output_buffer = allocate(shape=(data_size,), dtype=np.uint32) #~4MB

dma.recvchannel.transfer(output_buffer)
#dma.recvchannel.wait()

My final goal is to use 2 DMA to transfer the input vector to the vector dot product accelerator IP. If anyone has done the same project, I would be thankful if you could share your Python code and your block design.

Hi,

Did you try to start the DMA channel via overlay.axi_dma_0.sendchannel.start() [or dma.sendchannel.start() ] ?
Why did you comment the wait functions?

Did you check Running FFT with axi dma channel wait “DMA channel not started”?

You can obtain indications via help(overlay.axi_dma_0.sendchannel) or help(overlay.axi_dma_0) for example.

Sincerely

Hi @zara,

data_size = 1000000

What is the depth of the FIFO? Can you try with less elements?

I think you should start the receive channel first before sending.

Mario