In the last PYNQ edition, we examined how the PYNQ framework enables us to access lower level hardware functions such as function and signal generation and logic analysis.
In this edition, we are going to examine what the PYNQ Input / Output Processor (IOP) is and how we can use it in Python from the Jupyter environment. If you are not familiar with the PYNQ framework, the IOP allows us to exploit the Arduino, Pmod and Raspberry Pi interfaces on the PYNQ Z2 board. It can also be expanded when we create custom overlays to interface with any standard.
This lets us offload lower level, real-time interfacing to the programmable logic, enabling a more responsive solution.
As the IOP is intended to interface with a variety of different sensors and Pmods, each IOP supports a range of interface standards.
Within the IOP structure, support exists for SPI, IIC, GPIO and Timers (for PWM signals) which can be routed to the IO port via a switch.
At the heart of the IOP is the MicroBlaze processor. To ensure a compact footprint, the MicroBlaze processor runs from block RAM in the programmable logic. To allow run time flexibility the block RAM is configured as a dual port memory and the second port is connected to the Processing System. This means at run time we can easily update the program running on the MicroBlazes.
To allow multiple IOP instantiations especially in smaller devices, typically the BRAM memory for each MicroBlaze is limited to 64K.
Of course, to be effective the PS and PL need to be able to share information and communicate beyond the application memory. This is achieved using mailboxes.
Just like we do when we develop traditional MicroBlaze solution, we need both a hardware definition and a Board Support Package (BSP) in addition to the application.
If you clone the PYNQ git repository and examine the IOP elements in the library, you will notice under /lib/pmod the MicroBlaze BSP along with applications for specific Pmods (although not all).
When the PYNQ image is built these files are compiled into a bin file and accessible via a Python wrapper as shown below.
If we want to use a Pmod which is not yet supported in the PYNQ image, we can create our own Pmod driver using an existing Pmod project as a template. This project should be created using Xilinx SDK, with a bin output format, it helps to select one with the right interface e.g. SPI, IIC, GPIO etc.
However to make use of MicroBlaze processors in the programmable logic, we do not have to develop the application in SDK. We can do this using a Jupyter notebook as well.
Normally in Jupyter notebooks we write Python applications; but using iPython Magic commands which are indicated by %% we can compile other languages. This includes C for the MicroBlaze. All we need to do is specify the type of magic and the target MicroBlaze, e.g. %%microblaze base.PMODA.
As we may have several MicroBlaze instantiations, we also need to identify the target MicroBlaze.
Using this approach, we can then write C code, compile it, and execute it on the MicroBlaze. We can interact with the C code running on the MicroBlaze by calling the function from Python as seen in the example below.
This ability to write C and leverage the MicroBlaze ensures we can develop systems using the PYNQ framework, which use each element PS or PL to provide the optimal solution.
It also means we can easily access low level drivers from our Python application.