Objective: This writeup will guide you on how to create your first project targeting the Ultra96-V2 board and using the Vitis and Vivado 2019.2 environments. It will be a detailed step by step guide and will focus on providing an overview of the whole development cycle.
Recommended prerequisite articles to read:
Board Design Files
Before we can get into the hardware and software development phase, we need to obtain the Ultra96-V2 Board Design Files (BDF). These are the files defining amongst other things, the physical connection of onboard peripherals to the FPGA chip, clock speed, clock pins utilized etc. You can consider them to be closely akin to the User Constraints Files (UCF). Such files are usually provided by the board designer and we can download the Avnet BDF files from their GitHub account. Here you will basically download all the BDFs as a single archive file.
After extracting, you will find the ultra96v2 directory which is our interest. Copy it to the Vivado board files installation folder as shown below:
Now launch Vivado (as detailed in the Vivado and Vitis installation tutorial). Click through the project creation and naming tabs appropriately.
Select RTL Project as the project type since we want to utilize FPGA design building blocks such as IPs and HDL such as Verilog. Select Do not specify sources at this time option (we’ve got none anyway).
The next option is to specify our board, which is Ultra96v2 Evaluation Platform (recognized from the BDF file we copied in the first step).
The Ultra96 has both a Processing System (PS) and Programmable Logic (PL). The PS is based on the Quad-core Arm Cortex-A53. Hence form the Vivado side, we need to make it “aware” of this physical processor on the Ultra96. Since Xilinx and Avnet are partners, they have availed an IP that handles this. When dealing with IPs, the Block Design approach is the most convenient way to add these IPs to an RTL design.
In the IP Integrator, select Create Block Design.
In the Diagram window that opens, click the Add IP button and search for Zynq UltraScale+ MPSoC. Double click on it to add it to the block design. Click the Run Block Automation option and OK in the next window.
We now need to connect the maxihpm (PS) clocks to the PL clock by clicking and dragging a line between them as shown. Validate and save the design.
We now need to convert the block design into a lower level RTL design that is fully captured in Verilog/VHDL. Vivado provides a seamless way of doing this. Go to the sources tab and right click on the block design file (design_1.bd) we just created.
Select Create HDL Wrapper and let Vivado manage wrapper and auto-update in the next window.
You can double click on the design_1.v file that is generated to view the Verilog code generated.
We can now generate the bitstream for this design by clicking Generate Bitstream under Program and Debug. The bitstream generation (and synthesis) will take a couple of minutes.
The whole purpose for the above process was to provide a connection between the PS and PL parts of the ZU+ MPSoC platform, especially the clock signals.
With the bitstream generation successful, we now have a ZU+ Hardware Platform that we can build software on. Go to File -> Export Hardware and select Include Bitstream. Name the XSA file appropriately and choose its location.
After the export step, we can now use the Vitis Unified Software Platform to develop the software that can run on the ZU+ PS platform.
Software Development for ZU+ MPSoC on Vitis 2019.2
Launch Vitis, select the workspace directory and create a platform project as shown below:
Select Create from hardware specification (XSA) since we just built our hardware design in Vivado. This will prompt you to navigate to the location in which we saved the XSA file.
From the Platform Project Specification, we select a standalone application for the psu_cortexa53_0.
On finishing this set-up process, we are ushered into the Eclipse-based IDE from where we can develop our applications (C/C++).
The project at this point will indicate out-of-date and we can perform an initial build by going to Project-> Build Project. This should compile with no errors (warnings can be ignored) if everything was set up correctly.
We want to compile a simple program that is sufficient to demonstrate software development on Vitis.
Before proceeding, it’s important to point out here that Xilinx provides some examples for many of the peripherals on their boards. You can check them out at this stage by going to the platform navigation window as shown in the following pictures. Under the target device (psu_cortexa53_0), click on the BSP and each peripheral driver has accompanying examples.
Nevertheless, we will create a new application from scratch by going to File->New->Application Project. Select the platform that we just created in the previous steps as the target platform
Select the empty template option. We can now rebuild the project.
We can now add a source file to our new application by going to File -> New -> Other -> C/C++ -> Source File and name it main.c.
We will program the user LEDs on the Ultra96-V2 board. The first thing we need to know is the physical pin that the LEDs are connected to the PS chip i.e. the cortex A53. This Zedboard Ultra96-V2 HW User Guide indicates that the LEDs are connected to PS_MIO[17..20]. With this information, we can go to the Vivado Design Block that we created to see which bank/port these pins belong to in the PS chip. Double click on the Zynq MPSoC Block.
From the above, we can see that the pins PS_MIO[17..20] are part of the GPIO_0 bank. With this information, we can configure this bank appropriately. To get an idea of how to configure the GPIOs, you can explore the examples that Xilinx provides, and which can be accessed as indicated earlier in this article.
The following code is designed to flash all the 4 user LEDs.
Connect the Ultra96 board (through the JTAG&UART adapter) to the computer and set the boot switch SW3 to JTAG as shown below:
Plug the board to a power supply and press SW4 to power up the board. We can now program the FPGA by going to Xilinx->Program FPGA.
After we have programmed the FPGA with the bitstream, we can run the application by right clicking on the application project and selecting Run As -> Launch on Hardware.
This should blink the LEDs.
You should take time to understand the code we just demonstrated and how the various header and source files are linked together and utilized.