Skip to main content

Yet another EBAZ4205 writeup
#4: PYNQ overlay example

This post will show how to use hardware overlays on our recently uploaded PYNQ system. We will add AXI interface software control for the onboard LEDs and push-button, as well a custom Verilog hardware module. This is a convenient way to interface hardware modules designed in hardware description languages (i.e. Verilog/VHDL) via an easy to use Python interface.

References:

[1] Creating and using hardware designs. Good intros to PYNQ overlays.
[2] More details, including high performance interface and hierarchical hardware blocks.
[3] Adding ready-made IPs to PYNQ overlay.

Pre-requisites:

  • Working Vivado installation. Vivado and version PYNQ versions should match and we installed PYNQ 2.5.x, so we use Vivado 2019.1.
  • EBAZ4205 board with a booting PYNQ image.

1. Zynq PS GPIOs: the Zynq processor has 64 GPIO lines that can be used to control low-speed non timing-critical hardware functions, either by connecting them to PL modules or to physical IO pins. The onboard buttons are connected via GPIO and this is a great video that shows how to use them in a PYNQ overlay. However, for highly configurable hardware modules 64 lines might be insufficient and the interface is more commonly done using AXI lines.

2. AXI: this infrastructure provides a memory mapped interface for complex interaction of the PS with hardware modules (PL or physical IOs). These are banks of 32-bit registers that can be assigned to the processor memory in order to read and write hardware data. While the AXI interface is in fact very complex, we will use this simplified view as a starting point to present the concept and how it can be used with PYNQ. As such some input "buttons" will be defined through PL pins.

3. Generate the overlay hardware design.
Open the base overlay that we used to compile Petalinux. If you lost it or need a working project you can just use this one.
Warning: this Vivado project is specifically built for my crystal-less EBAZ4205 and might not be suitable for other variants of the board.
Improtant: when loading an overlay PYNQ reprograms the hardware bitstream. Since EBAZ4205 has its network interface wired through PL lines and not the PS, make sure that you don't change the ethernet clock or pins for the overlay or ethernet will not work.

Save the base design as a new project with a dedicated name.
Open the Block diagram.
Add an AXI GPIO module to the design to control the board LEDs, give it a meaningful name.
Double-click, define it with length of 2, outputs only.
Add another AXI GPIO to read the online buttons value, set it as length 2 input only (remember, these will NOT be routed from the onboard buttons)
Create IO pins for the LEDs and buttons (right-click and "make external")
Click "Run connection automation" and select the AXI interface to finalize module connection.
4. Add a custom Verilog hardware module: I will create here a simple even-number clock divider. AXI interface to PS can be done "properly" by creating hardware IPs. However, I figured a simplified way to achieve the same goal with GUI-only design by "hacking" the AXI-GPIO module. My method is not memory efficient (AXI module address size is minimum 4kB) and may have other issues that I am unaware of, but is very straightforward and worked for me so far. You are welcome to use either method you'd like.

A simple Verilog frequency divider code.
module clk_div(
    //cell clocking
    input clk_in,
    input rst,
    input [7:0] clk_div, //divide from 2 to 256, by even numbers only.
    output reg clk_out
    );

    reg[7:0] counter=8'd0;
    // clk_out = clk_in/clk_div
    always @(posedge clk_in)
        begin
            if (rst==1'b0)
                begin
                    clk_out <= 1'b0;
                    counter <= 8'd0;
                end
            else
                begin
                    counter <= counter + 8'd1;
                    if(counter>=(clk_div-1)) counter <= 8'd0;
                    clk_out <= (counter<clk_div/2)?1'b1:1'b0;
                end        
        end
endmodule
Create a new design source.
Name the module, finish (click OK without adding IOs. "Yes" when notified that module definitions have not changed).
Double click the new Verilog file and Add divider code. Save.
Double click the block diagram. Drag-drop the divider to block diagram to create a design block.
Add AXI-GPIO cells to interface the custom hardware. We will use a 32-bit output line, even though this is not strictly required in order to show how to split output bits.
Add slice blocks to select the bits that control the different clock definitions. Since we have a single field here it is not strictly required, but if you want to interface many inputs with a single AXI register it's very convenient.
Edit the slice to output only 8 bits, rename to say what they are
Connect the divider input lines, make external port, and connect the AXI GPIO to the divider via the slice block. Note how the divider clock is connected to the Zynq master clock. This is not mandatory. If you want another base frequency you can add another PL clock to the Zynq block.
Finally, run block connection automation and connect the remaining AXI lines.
5. Add IOs to constraint files (pins are taken from the EBAZ4205 schematic).
We will route our input ("buttons") pins through the GPIO connector
This can be done Either
(a) Directly to constraint text file:
Add the following port allocation to your constraint file.
set_property IOSTANDARD LVCMOS33 [get_ports {buttons[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {buttons[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk_out]
set_property PACKAGE_PIN W13 [get_ports {leds[1]}]
set_property PACKAGE_PIN W14 [get_ports {leds[0]}]
set_property PACKAGE_PIN A20 [get_ports clk_out]
set_property PACKAGE_PIN B19 [get_ports {buttons[1]}]
set_property PACKAGE_PIN B20 [get_ports {buttons[0]}]
This can be done by copying these lines directly to constraint file.
Or
(b) By clicking "Run Synthesis", and then assigning pins via GUI:
Start by running synthesis. Confirm pin size mismatch warnings. These were by design.
Open the synthesized design.
If you cannot see an I/O ports tab at the bottom click Layout-> I/O Planning.
Assign the correct ports, directions and I/O standards to our required pins.
Save constraints to file (This will invalidate your synthesis).

6. Run "Generate Bitstream" and gather required files.
Confirm rerun synthesis, select all CPUs
Open the block diagram and export the block design .tcl
find and copy the following files from your projects to a sperate location and rename them all as you desired overlay.
(a) .tcl file in wherever you saved it (default project base directory).
~/Vivado/2019.1/EBAZ4205_Ex_Overlay/Zynq_proc.tcl
(b) .bit file in the run implementation file
~/Vivado/2019.1/EBAZ4205_Ex_Overlay/EBAZ4205_Ex_Overlay.runs/impl_1/Zynq_proc.hwh
(c) .hwh file in the hardware wrapper handoff directory.
~/Vivado/2019.1/EBAZ4205_Ex_Overlay/EBAZ4205_Ex_Overlay.srcs/sources_1/bd/Zync_proc/hw_handoff/Zynq_proc_wrapper.bit

It is highly recommended that you change your PYNQ hostname if you use it on a multi-user network (e.g. university). Then, rename these three files to have the same name and upload to PYNQ.

If all went well, you should have a functional overlay!
If had trouble along the way or unsure of your design, I'm attaching mine here for your convenience.

7. Examine the uploaded overlay.
Make a python 3 file in the same directory as the uploaded overlay files. double click to open the file.
Import overlay content (I use screenshots and not a text box here to show how GUI functions).
Test LEDs functionality.
Test Variable clock (Oscilloscope/logic analyzer needed).
Since we don't have physical buttons, I will connect either 0V or 3.3V taken from serial port VCC to one of the "button" inputs.
WARNING! FPGA ports are much less forgiving than Arduino, for example. If you connect higher voltage than defined they are likely to burn.
And... done!
With custom logic, the sky is the limit. I hope that this little taste of PYNQ capabilities will drive you to move forward to much more complicated implementations. Happy hacking!
 

Comments

Popular posts from this blog

Yet another EBAZ4205 writeup
#2: Petalinux 2019.1 Walkthrough

In order to leverage the capabilities of the EBAZ4205 I want it to run Linux. There are a couple of guides online which didn't work for me, because I have the board variant without a Y3 crystal at the ethernet IC. I'm also not an experienced FPGA developer, so some of the implicit steps were non-trivial for me at all. This was an excellent opportunity to pick up the glove and learn how to build Petalinux myself. So lets get to work! This guide uses 2019.1 toolchain, for two main reasons: It is the last version before Xilinx's migration to Vitis so there is more data online from other users. While the hardware flow is identical to the Vivado 2020.X editions, the Petalinux u-boot build process is different (see  Tux Engineering, Inc. - Home ), and has resulted errors for me, which I currently don't know how to solve. Refences The full writeup puts together bits and pieces are from the following sources: [1]  zynq[1] 矿板helloworld | hhuysqt  (using Google-Translate) [2]  EB

Yet another EBAZ4205 writeup
#3: PYNQ!

In this post we will leverage our basic Petalinux build to install PYNQ on our EBAZ4205 evaluation board. PYNQ is a framework being developed by Xilinx to interface all of a Zynq boards' capabilities (i.e. custom logic, processing, and peripherals) via a Python environment. It is enabled thanks to the Zynq's unique feature compared to other FPGAs, in which the logic fabric (PL) is actually programmed by the processor (PS) on boot. As a result, running PYNQ enables to use custom logic without the need of an external JTAG programmer . References : [1]  PYNQ for Cora-Z7-07S  and  GitHub PYNQ-Cora-Z7-07S . Great walkthrough. I modified it to apply to EBAZ4205 board. [2] Quick Porting of PYNQ . A general purpose introduction to PYNQ porting. Some useful replies. [3]  Load a PYNQ 2.5 bitstream during power-up . The last nail in the coffin: how to make ethernet work. Pre-requisites : Software tools installed and conf

Yet another EBAZ4205 writeup
#1: The Crystal-Less Variant

Once I noticed that cheap Zynq modules can be had for a few dollars I immediately bought one, then started asking questions. Apparently, the first modules in circulation were more populated than the later ones: They have optocouplers and a crystal driving the network interface. The crystal-less modules are cheaper, but I had trouble evaluating and leveraging my Zync-board capabilities. The following posts will detail my steps to install Petalinux OS and boot it from SD card, and and then to install and run PYNQ. This enables to interface the FPGA logic from python code running on the Zynq processor, without needing to use a JTAG programmer . Order of posts Introduction . Board definitions. Build and install  Petalinux 2019.1 on crystal-less EBAZ4205 module. Build and install  PYNQ 2.5.4 on crystal-less EBAZ4205 module. PYNQ overlay example  for verification of functionality. References (for part #1) [1]  GitHub - xjtuecho/EBAZ4205: A 5$ Xilinx ZYNQ development board.  The most exten