By Adam Taylor

Having re-created the base hardware overlay for our PYNQ dev board, we’ll now modify the overlay to add our own memory-mapped peripheral. As we are modifying the base overlay, this will be a new overlay—one that we need to correctly integrate into the PYNQ environment.

While this will be a simple example, we can use the same techniques used here to create as complicated or as simple an overlay as we desire.

To demonstrate how we do this, I am going to introduce a new block memory within the PL that we can read from and write to using the Python environment.

The new blocks are highlighted

To do this we need to do the following in the Vivado design:

Create a new AXI port (port 13) on the AXI Interconnect connected to General Purpose Master 0 Import a new BRAM controller and configure it to have only one port Use the Block Memory Generator to create a BRAM. Set the mode to BRAM Controller, single port RAM Map the new BRAM controller to the Zynq SoC’s PS memory map

With these four things completed, we are ready to build the bit file. Once the file has been generated, we are halfway towards building an overlay we can use in our design. The other half of the way requires generating a TCL script that defines the address map of the bit file. To do this we need to use the command:

write_bd_tcl <name.tcl>

Once we have the TCL and bit files, we can move on to the next stage, which is to import the files and create the drivers and application.

This is where we need to power on the PYNQ dev board and connect to it to the network with our development PC. Once the PYNQ configuration is uploaded, we can connect to it using a program like WinSCP to upload the bit file and the tcl file.

Within the current directory structure on the PYNQ board, there is a bit stream directory we can use at:

/home/Xilinx/pynq/bitstream/

You will find the files needed to support the base overlay under this directory.

Base overlay and modified overlay following upload

Once this has been uploaded, we need to create a notebook to use it. We need to make use of the existing overlay module provided with the PYNQ package to do this. This module will allow us to download the overlay into the PL of the PYNQ. Once it is downloaded, we need to check that it downloaded correctly, which we can do using the ol.is_loaded() function.

Downloading the new overlay

The simplest way to interface with the new overlay is to use the MMIO module within the PYNQ Package. This module allows us to interface directly to memory-mapped peripherals. First however, we need to define a new class within which we can declare the functions to interact with the overlay. For this example, I have called my class part158 to follow the blog numbering.

Looking within the class, we have defined the base address and address range using the line:

mmio = MMIO(0x46000000,0x00002000)

Three function definitions in the above figure define:

The initialization function (in this case, this function merely writes a 0 to address 0)

A function that writes data into the BRAM

Another function that reads data from the BRAM.

(Remember that the address increments by 4 for each address because this is a 32-bit system.)

With the class defined, we can then write a simple script that writes data to and reads data from the BRAM, as we would for any other function. Initially we will write a simple counting sequence followed by writing in random numbers.

When I executed the notebook, I received the results below:

Once we have this new hardware overlay up and running, we can create a more complex overlay and interact with it using the MMIO module.

Code is available on Github as always.

If you want E book or hardback versions of previous MicroZed chronicle blogs, you can get them below.

First Year E Book here

First Year Hardback here

Second Year E Book here

Second Year Hardback here

All of Adam Taylor’s MicroZed Chronicles are cataloged here.