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.