Let there be light

To get started you are going to build a hardware design that brings on the LEDs of the PYNQ Z2 board. The architecture is very simple and should look something link the image below.

Describing the hardware

For the computer to understand what you are building, a Hardware Description Language (HDL) is required. In this lab, this will be VHDL. The environment that you are going to use to make the design is Vivado. This software suite, made available by Xilinx (the FPGA vendor), can be used for multiple purposes:

  • hardware designing
  • simulation of designs
  • generation of hardware IP component
  • running the FPGA toolchain
  • insert/handle debugging features
  • configuring the FPGA

Install the Vivado software

The Vivado software can be downloaded through the Xilinx website. You will need an account at the website, but you can make one for free. The software can be downloaded for free, but certainly isn’t free. A license is required to enjoy all the features of the design suite, but The FPGA on the PYNQ Z2 is free to use. Make sure to install Vitis, because we will be using it during the labs.

Know that during the installation the only devices you will need for this lab is under SoCs the Zynq-7000 devices. By not installing all the other devices you can save large amounts of disk space.

Install the PYNQ Z2 board drivers

Vivado is board aware. Alas, the PYNQ Z2 board is not by default known by the software. Additional metadata is to be added to your Xilinx Installation. To do this you need to download the board files from here. Later we also require the “Master XDC” file. You need to extract the board files archive in “\Vivado<version>\data\boards\board_files”, if the directory doesn’t exist you need to create it. After extracting you should have a folder called pynq-z2 inside the board_files directory. For old Vivado versions you can follow the instructions here. Note that the download links are dead.

Example project

Let us start with a very simple example project. These PYNQ Z2 boards have LEDs and pushbuttons. We want to use a push button to turn on the LED. One thing is that we want to do this Synchronusly. This means that LED lights up if the pushbutton is pressed and a rising edge of a clock comes in. It turns back off when the pushbutton is not pressed and there is again a rising edge. In practice we will not see this delay, because our clock is 125MHz.

Schematic of example project

How do you code this? First you will create a VHDL design source in Vivado, then you see it gives a nice template to write your beautiful code. It is expected that you already know the basics of VHDL from previous year(s). Here is the example code of this schematic. Be happy with the code below, because this is one of the only times you will get example design code during this course.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity example_project is
  Port (clock: in STD_LOGIC;
        pushbutton: in STD_LOGIC;
        LED: out STD_LOGIC );
end example_project;

architecture Behavioral of example_project is

begin

SEQ: process(clock) begin

    if rising_edge(clock) then -- clock'event and clock = '1' is the same as rising_edge(clock)
        LED <= pushbutton;
    end if;

end process;

end Behavioral;

Now you try to understand this code. It creates a process called SEQ, which has an if statement that defines that when there is a rising edge of the clock the pushbutton should be read and the output should be put on the LED. Note that this if statement does not include an else statement because it needs to remember the value until the next rising edge of the clock.

From RTL design to bitstream

The example above is very simple. The design holds nothing more that a 1-bit register. Making a drawing of the architecture is not really required. PROTIP: If designs get more complex, actually making this type of drawings like the one above, helps enormously !!

Once you described your design in VHDL the FPGA toolchain can run synthesis. During this part a netlist is generated of your design. The netlist is one input for the next step.

The second part that is required is a “how-do-I-map-this-to-the-outside-world” file. Your netlist has toplevel ports (inputs and outputs). For FPGA design with Xilinx tools, the mapping of these ports to physical pins is done through a constraint file. The extension of these files is: .xdc (Xilinx Design Constraint). Another important aspect that is covert by the xdc-file is constraints on timing. An example is shown below.

set_property -dict { PACKAGE_PIN H16   IOSTANDARD LVCMOS33 } [get_ports { clock }]; #IO_L13P_T2_MRCC_35 Sch=sysclk
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clock}];

set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { LED }]; #IO_L6N_T0_VREF_34 Sch=led[0]

set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { pushbutton }]; #IO_L4P_T0_35 Sch=btn[0]

The first line in the example above maps the sysclk port to pin H16 of the FPGA. The IO standard is LVCMOS33. The second line creates an internal clock signal on port sysclk. The name is sys_clk_pin and it has a 125 MHz frequency with a 50% duty cycle.

The third line of code maps pin R14 to the LED pin of the design. While the fourth one maps pin D19 to the pushbutton pin. Both are of the IOSTANDARD LVCMOS33, which means that it is using 3.3V logic.

An example xdc file for the PYNQ Z2 can be found here

Do it yourself

Now that you have an example, let’s start with an easy exercise. This is just to refresh your memory and your VHDL.

Describe the design depicted below in VHDL. In the first iteration you can simply ignore everything in green. Although there are only 2 DIP switches, there are 4 LEDS. Just repeat both bits twice to form a 4 bit register.

The architecture for the exercises

One single bit is … well … a bit. Eight bits is a byte and four bits is a nibble.

If you group 1024 bits, this is called a kibibit. Yes !! That is the correct name according to the International Electrotechnical Commission (IEC). A kilobit is 1000 bits.

When this works, surprise surprise, add the part in green. Through the use of a pushbutton you should be able to switch between the inverted and the non-inverted nibble.

The result should look something like this:

Exercise 1

Exercise 2

Exercise 3

Now we are going to use the pushbuttons to turn on the LEDs. If you press a pushbutton the corresponding LED needs to be toggle. If it is off it needs to turn on until the pushbutton is pressed again. You need to detect the rising edge of the pushbutton input.

Don’t use the pushbutton as the clock input of a flip-flop. The flip-flop clock input is always reserved for a clock. The FPGA has dedicated routing internally for the clock.