Axi-s dma pl->ps

The PYNQ Z2 is a wonderful device. At the moment I’m trying to get AXI DMA to work, however, and it does not really want to.
My setup:
Pynq Z2
Linux 4.14-xilinx-v2018.3
Vivado 2019.1
pynq v2.5
numpy 1.17.2
matplotlib 3.1.1

I’m trying to feed a memory stream through a data FIFO that I will later replace with a custom HLS block. For now, the block design looks like this:

Note the interrupt pins from the 2 DMA blocks, mm2s_introut and s2mm_introut being connected through a Concat block to the IRQ_F2P port of the PS.

This leads to an error when trying to talk DMA with this block design:

Python code i’m running:

import numpy as np
import pynq
from pynq import Overlay, MMIO
from pynq.lib import DMA
import pynq.lib.dma
from pynq import allocate

ol = Overlay('./11-tochwel.bit')
dma_send = ol.axi_dma_ps_to_pl
dma_recv = ol.axi_dma_pl_to_ps


from pynq import Xlnk
data_size = 15
xlnk = Xlnk()
input_buffer = xlnk.cma_array(shape=(data_size,), dtype=np.uint32)
output_buffer = xlnk.cma_array(shape=(data_size,), dtype=np.uint32)
for i in range(data_size):
    input_buffer[i] = i + 0xcafe0000

dma_send = DMA(ol.ip_dict['axi_dma_ps_to_pl'])
dma_recv = DMA(ol.ip_dict['axi_dma_pl_to_ps'])

dma_send.sendchannel.start()
dma_recv.recvchannel.start()

dma_send.sendchannel.transfer(input_buffer)
dma_recv.recvchannel.transfer(output_buffer)

# dma_send.sendchannel.wait()
# dma_recv.recvchannel.wait()
for i in range(10):
    print(hex(output_buffer[i]))

The error:

<ipython-input-45-b53b94401f56> in <module>()
      1 import pynq.lib.dma
      2 
----> 3 dma_send = ol.axi_dma_ps_to_pl
      4 dma_recv = ol.axi_dma_pl_to_ps

/usr/local/lib/python3.6/dist-packages/pynq/overlay.py in __getattr__(self, key)
    335         """
    336         if self.is_loaded():
--> 337             return getattr(self._ip_map, key)
    338         else:
    339             raise RuntimeError("Overlay not currently loaded")

/usr/local/lib/python3.6/dist-packages/pynq/overlay.py in __getattr__(self, key)
    735         elif key in self._description['ip']:
    736             ipdescription = self._description['ip'][key]
--> 737             driver = ipdescription['driver'](ipdescription)
    738             setattr(self, key, driver)
    739             return driver

/usr/local/lib/python3.6/dist-packages/pynq/lib/dma.py in __init__(self, description, *args, **kwargs)
    188                                'has been deprecated and moved to '
    189                                'pynq.lib.deprecated')
--> 190         super().__init__(description=description)
    191 
    192         if 'parameters' in description and \

/usr/local/lib/python3.6/dist-packages/pynq/overlay.py in __init__(self, description)
    600             self._gpio = {}
    601         for interrupt, details in self._interrupts.items():
--> 602             setattr(self, interrupt, Interrupt(details['fullpath']))
    603         for gpio, entry in self._gpio.items():
    604             gpio_number = GPIO.get_gpio_pin(entry['index'])

/usr/local/lib/python3.6/dist-packages/pynq/interrupt.py in __init__(self, pinname)
     96         self.number = PL.interrupt_pins[pinname]['index']
     97         self.parent = weakref.ref(
---> 98             _InterruptController.get_controller(parentname))
     99         self.event = asyncio.Event()
    100         self.waiting = False

/usr/local/lib/python3.6/dist-packages/pynq/interrupt.py in get_controller(name)
    157             if con.name == name:
    158                 return con
--> 159         ret = _InterruptController(name)
    160         _InterruptController._controllers.append(ret)
    161         return ret

/usr/local/lib/python3.6/dist-packages/pynq/interrupt.py in __init__(self, name)
    175         """
    176         self.name = name
--> 177         self.mmio = MMIO(PL.ip_dict[name]['phys_addr'], 32)
    178         self.wait_handles = [[] for _ in range(32)]
    179         self.event_number = 0

KeyError: ''

This error does not occur if I remove the Concat block and leave the DMA introut ports disconnected, however then I always retrieve the value 0xdec0dee3 back from the DMA.
Is this a bug in the pynq library?

1 Like

I think you should just use

    dma_ip.sendchannel.transfer(in_buffer)
    dma_ip.recvchannel.transfer(out_buffer)
    dma_ip.sendchannel.wait()
    dma_ip.recvchannel.wait()
1 Like

In order to get rid of this error, you should use an AXI Interrupt Controller.
If we assume that:

overlay = Overlay(“path_to_bitstream/bitstream.bit”)

then if you take a look at:

overlay.ip_dict

you can see that the DMA’s S2MM and MM2S have no interrupt controller, something like:

{‘axi_dma_0’:
{‘fullpath’: ‘axi_dma_0’, ‘type’: ‘xilinx.com:ip:axi_dma:7.1’, ‘state’: None, ‘addr_range’: 65536, ‘phys_addr’: 1077936128, ‘mem_id’: ‘S_AXI_LITE’, ‘gpio’: {},
‘interrupts’:
{
‘s2mm_introut’: {‘controller’: ‘’, ‘index’: 0, ‘fullpath’: ‘axi_dma_0/s2mm_introut’},
‘mm2s_introut’: {‘controller’: ‘’, ‘index’: 2, ‘fullpath’: ‘axi_dma_0/mm2s_introut’}
},

}

Instead of connecting the dout from concat directly to IRQ_F2P of the ZYNQ, connect it to the input of AXI Interrupt Controller block, and then connect the output of the AXI Interrupt Controller block to the IRQ_F2P of the ZYNQ.

2 Likes

Because i have the same problem but i am not familiar with interrupts. First i cannot connnect the output of AXI interrupt controller to IRQ_F2P(Vivado does not let me) and i do not know what to change in AXI Interrupt Controller in order to do it . Also when i do validate design vivado shows a message that slave informations has to be written at data/processin_system7 or not to be involved. My project is just a dma(read and write) and i want to put interrupts. Thank you in advance!

Hi @Kwstis,
If you refer to my answer on another thread (link below), you can find a summary of my trials with DMA. The schematic in “6.pdf” shows how the different blocks should be connected with each others.
Probably you need to click on the “+” sign near Interrupt port in the AXI Interrupt Controller block to get the single interrupt lines. Otherwise, you’re actually trying to connect the whole interrupt bus to the IRQ_F2P port of the ZYNQ.

Was that helpful?

1 Like

First thanks for your reply! I am not sure if am i correct but i think from (processor system reset) the ouput interconnect_aresetn[0:0] must go to ARESETN of the two AXI Interconnects of the block design. The others have to stay the same. When i enable PL fabric interrupts i have IR_f2P[2:0] while AXI Interrupt Controller has only one bit line irq so we have mismatch of bits. Also there ase some warnings about s_axi of AXI Interrupt Controller when i do generate bitsream.

1 Like

Can you post some screenshots so that I can better see what’s going on?

If you could check here it will help.It is my current situation. See that IRQ_F2P[1:0] while irq not defined( Type mismatch between connected pins: /axi_intc_0/irq(undef) and /processing_system7_0/IRQ_F2P(intr) )
RuntimeError: DMA channel not started
Finally the problem may occured cause i have done validate design in previous edition with only concat and then i could not change the IRQ_F2P . I create a new project and now it si [0:0] but stil the same warning exist.

1 Like

Hi, did you solve your problem, because we are also facing the same issue?
If you sort this out, can you please help me?

1 Like