MicroZed Chronicles: PYNQ in Development

How to use PYNQ to debug custom IP and applications.

When I am not creating blogs or projects, I spend most of my time consulting with clients on FPGA and SoC design. I am lucky to be working on several exciting projects from autonomous driving to satellite payloads.

One thing that I notice I keep mentioning to clients using Zynq and Zynq MPSoC devices is how the PYNQ framework can help during commission and testing of the IP and overall system.

With PYNQ, we can load in the bit file and get started quickly and easily accessing the design using the Jupyter environment.

This means we can start testing the IP and overall application without the need in many cases to write a lot of embedded Linux drivers, thanks to the PYNQ Lib.

Let's take a look at a simple example for the Ultra96-V2 where we want to be able to access a BRAM in the PL.

Of course, the PL design could contain a much more complex design for example a VDMA from a camera or DMA from a ADC. Information captured could then be further processed in Jupyter using Python.

To get started, we need to make a new project in Vivado targeting the Ultra96-V2. As we're targeting PYNQ2v5, I will be using Vivado 2019.1.

With the project created, the next step is to create a new block diagram.

On to the block diagram, add the Zynq MPSoC processing system and run the block automation to configure the PS for the Ultra96-V2 configuration.

On to the block diagram, we can add in IP from the Xilinx IP catalog. There are also a number of PYNQ IPs provided with the PYNQ package, which can be accessed by cloning the PYNQ Git repo.

The IP available under the directory PYNQ/boards/ip can then be added into the Vivado as an IP repository.

There are additional IP available under the HLS directory that can be re generated from a script if required.

Once the IP has been added, you will notice we now have a new user IP repo that contains several IP from the PYNQ repository.

However, not all of these may be enabled for the MPSoC architecture.

If you desire to use one which is not currently enabled for the MPSoC architecture, it is a simple exercise to right click on it to edit the IP and repackage it for the MPSoC as well as the Zynq.

With the IP available, we can get started creating the block diagram. For this application, I am just going to add in the BRAM and connect it up to the processor.

We will come back to the remaining IP in a project soon.

With the block diagram created, the next step is to export the block diagram tcl file using the command:

write_bd_tcl — force <name>.tcl

We are then ready to implement the design. Once this is completed, we then need to collate the following files in a directory.

  • Bit file
  • TCL block diagram description
  • Hardware hand off file
  • __init__.py
  • overlay.py - contains the overlay class definition

The bit file, hardware hand off, and TCL description will be provided by Vivado.

The overlay and __init__.py file we need to write by hand. The ones I created are below:


import pynq
from pynq import GPIO
__author__ = "Adam Taylor"
__copyright__ = "Copyright 2020, Adiuvo"
__email__ = "Adam@adiuvoengineering.com"

class u96_bramOverlay(pynq.Overlay):
def __init__(self, bitfile, **kwargs):
super().__init__(bitfile, **kwargs)
if self.is_loaded():


from .u96_bram import u96_bramOverlay

If necessary, we can rename these files to the desired name of the overlay.

We can then connect to the Ultra96 using a file transfer program such a WinSCP.

Upload the directory to the pynq/overlays/<overlayname> directory on the Ultra96. There is a short cut from the home directory to the PYNQ install directory.

Once this is uploaded, we can open a new Jupyter notebook and begin to create our test application.

The first step is to import and download the overlay. Once the overlay has been loaded, we can list the IP blocks and associated drivers by using the command:


Using the defaultIP driver, we are then able to read and write the BRAM in the design.

While this is a simple example, the BRAM could be any custom IP or HLS IP block we have created.

Using PYNQ in this way enables us to quickly and easily begin to test IP blocks and complete applications. This allows us to retire risks earlier and create applications with ease that leverage PYNQ and Python.

Keep an eye on my projects — you will see some interesting PYNQ applications coming up!

See My FPGA / SoC Projects: Adam Taylor on Hackster.io

Get the Code: ATaylorCEngFIET (Adam Taylor)

Access the MicroZed Chronicles Archives with over 300 articles on the FPGA / Zynq / Zynq MpSoC updated weekly at MicroZed Chronicles.

Adam Taylor
Adam Taylor is an expert in design and development of embedded systems and FPGA’s for several end applications (Space, Defense, Automotive)
Latest articles
Sponsored articles
Related articles
Latest articles
Read more
Related articles