Firmware generated with Simulink

I have firmware designed with Simulink, compiled with HDLCoder using Vivado 2020.2. It works with MATLAB calls in their zynq environment.

In MATLAB, here is an example of writing to the “captureCtrl” register:

writePort(hFPGA, “captureCtrl”, false);

where “captureCtrl” is setup like so:

%% AXI4-Lite
addAXI4SlaveInterface(hFPGA, …
“InterfaceID”, “AXI4-Lite”, …
“BaseAddress”, 0xA0000000, …
“AddressRange”, 0x10000);

DUTPort_captureCtrl = hdlcoder.DUTPort(“captureCtrl”, …
“Direction”, “INOUT”, …
“DataType”, “logical”, …
“IsComplex”, false, …
“Dimension”, [1 1], …
“IOInterface”, “AXI4-Lite”, …
“IOInterfaceMapping”, “0x100”);

How would I do this in pynq?

I copied the bit and hwh files and renamed them rdc9.bit and rdc9.hwh and tried this in a notebook:

overlay = Overlay(‘rdc9.bit’)

#the custom IP I want to control is this one:


{‘fullpath’: ‘DataCapture_0’, ‘type’: ‘’, ‘state’: None, ‘addr_range’: 65536, ‘phys_addr’: 2684354560, ‘mem_id’: ‘AXI4_Lite’, ‘gpio’: {}, ‘interrupts’: {}, ‘parameters’: {‘Component_Name’: ‘system_DataCapture_0_0’, ‘EDK_IPTYPE’: ‘PERIPHERAL’, ‘C_BASEADDR’: ‘0xA0000000’, ‘C_HIGHADDR’: ‘0xA000FFFF’}, ‘registers’: {}, ‘device’: <pynq.pl_server.device.XlnkDevice object at 0x7f84ebb940>, ‘driver’: <class ‘pynq.overlay.DefaultIP’>}

I tried this:

dc0 = overlay.DataCapture_0
<pynq.overlay.DefaultIP object at 0x7f6d782438>

but this hang and crashes the kernel:

dc0.write(0x100, 0)

1 Like

Usually the hang is from accessing a wrong AXI address. So I would just double check if the base address is correctly configured. Maybe check your block diagram to see if there is any wrong connection?

@rock, thank you, I think the connections are correct.

Short Version: running pynq 2.7 improves the situation, but I need help getting an IP block instatiated as pynq.lib.dma.DMA

After consulting with a colleague, we decided to try this with pynq2.7 and this met with some success.

After loading the overlay, these two calls set clocks:

xrfclk.set_all_ref_clks(204.8) #first set all clocks to 204.8
xrfclk.xrfclk._set_LMX_clks(102.4, xrfclk.lmx_devices[2]) #this LMX drives the DAC clocks

The AXI4-Lite interfaces work, and the firmware responds by generating the output signal as expected. So far so good!

However, there are problems read via DMA.

When I look at a similar interface for firmware built by directly in Vivado, it looks like this:

overlay = Overlay('./pfb_8x1024_ad_da.bit')

so I’d like this new firmare to expose the same class, pynq.lib.dma.DMA.

Trying this with the firmware as built by Simulink shows trouble with a missing UIO device and the type is DefaultIP, not DMA.

> overlay.axi_dmac_s2mm
/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/ UserWarning: Interrupt irq not created: Could not find UIO device for interrupt pin for IRQ number 122
  warnings.warn('Interrupt {} not created: {}'.format(

<pynq.overlay.DefaultIP at 0xffff9afebca0>

So, this is showing up only as DefaultIP.

Following advice from here: Interrupt error on using two VDMA - #3 by mizan I modified the block diagram in Vivado to add an AXI Interrupt Controller as suggested.

Here is the original block diagram as produced by Simulink:

Here is the modified block diagram:

That build, and I copied the .bit and .hwh files to the ZCU111 and followed the same step. Now this line:

dma = overlay.axi_dmac_s2mm

does NOT cause the warning about “Could not find UIO device…” but it is still of the type pynq.overlay.DefaultIP

The ip_dict information for the IP looks like this:

x = overlay.ip_dict['axi_dmac_s2mm']
for k,v in x.items():
    print("%10s: %s"%(k,v))

  fullpath: axi_dmac_s2mm
    bdtype: None
     state: None
addr_range: 4096
 phys_addr: 2684551168
    mem_id: s_axi
   memtype: REGISTER
      gpio: {}
interrupts: {'irq': {'controller': 'axi_intc_0', 'index': 1, 'fullpath': 'axi_dmac_s2mm/irq'}}
parameters: {'ID': '0', 'DMA_DATA_WIDTH_SRC': '128', 'DMA_DATA_WIDTH_DEST': '128', 'DMA_LENGTH_WIDTH': '24', 'DMA_2D_TRANSFER': 'false', 'DMA_2D_TLAST_MODE': '0', 'ASYNC_CLK_REQ_SRC': 'true', 'ASYNC_CLK_SRC_DEST': 'true', 'ASYNC_CLK_DEST_REQ': 'false', 'AXI_SLICE_DEST': 'false', 'AXI_SLICE_SRC': 'false', 'SYNC_TRANSFER_START': 'false', 'CYCLIC': 'false', 'DMA_AXI_PROTOCOL_DEST': '0', 'DMA_AXI_PROTOCOL_SRC': '0', 'DMA_TYPE_DEST': '0', 'DMA_TYPE_SRC': '1', 'DMA_AXI_ADDR_WIDTH': '32', 'MAX_BYTES_PER_BURST': '512', 'FIFO_SIZE': '32', 'AXI_ID_WIDTH_SRC': '1', 'AXI_ID_WIDTH_DEST': '1', 'DISABLE_DEBUG_REGISTERS': 'false', 'ENABLE_DIAGNOSTICS_IF': 'false', 'ALLOW_ASYM_MEM': '1', 'ENABLE_FRAME_LOCK': 'false', 'MAX_NUM_FRAMES': '8', 'USE_EXT_SYNC': 'false', 'HAS_AUTORUN': 'false', 'DMAC_DEF_FLAGS': '0x00000000', 'DMAC_DEF_SRC_ADDR': '0x00000000', 'DMAC_DEF_DEST_ADDR': '0x00000000', 'DMAC_DEF_X_LENGTH': '0x00000000', 'DMAC_DEF_Y_LENGTH': '0x00000000', 'DMAC_DEF_SRC_STRIDE': '0x00000000', 'DMAC_DEF_DEST_STRIDE': '0x00000000', 'DMAC_DEF_FLOCK_CFG': '0x00000000', 'DMAC_DEF_FLOCK_STRIDE': '0x00000000', 'Component_Name': 'system_axi_dmac_s2mm_0', 'EDK_IPTYPE': 'PERIPHERAL', 'C_BASEADDR': '0xA0030000', 'C_HIGHADDR': '0xA0030FFF'}
 registers: {}
    device: <pynq.pl_server.embedded_device.EmbeddedDevice object at 0xffff850849d0>
    driver: <class 'pynq.overlay.DefaultIP'>
1 Like

Hi @Chris_Stoughton,

PYNQ assigns the DefaultIP driver to IP that do not have a specific driver. See more documentation below.

The pynq.lib.dma.DMA driver is only for the (Xilinx) DMA IP. Unless your custom IP is fully compatible with the DMA driver you would have to write your own driver.


1 Like

@marioruiz Thank you for the explanation. Evidently, the IP written by simulink is not fully compatible with the DMA driver. I marked this as the solution.

1 Like