Using a Peripheral with a Hierarchical Block in Vivado IPI and Vitis
In Vivado, a Hierarchical Block is a block design within a block design. These blocks allow engineers to partition their designs into separate functional groups. This guide steps through the process of adding a pre-existing hierarchical block to a block design, recreating its example software application, and running the design in hardware.
Note: Screenshots presented in this guide may not have been taken with your version of the tools. The workflow presented here has been verified in Vivado 2020.1. While there are some differences between 2020.1 and older versions of the tools, older screenshots have been checked, and contain the same user interfaces that are seen in 2020.1.
- A Digilent FPGA development board.
- A computer with Vivado installed.
- See the Installing Vivado, Vitis, and Digilent Board Files guide for more information.
- Familiarity with Vivado IP Integrator and a base block design to work from.
- Following the Getting Started with Vivado and Vitis for Baremetal Software Projects guide will result in a design that fits all requirements.
Setting Up Dependencies
A ZIP archive including all required IP, software examples, and hierarchy scripts for each peripheral this guide supports can be downloaded from Github here: vivado-library-hierarchies.zip.
Download this file, and extract it to somewhere memorable on your computer.
Some users may wish to get access to these files through git, which provides a way to pull in any updates or fixes Digilent may apply to these files in future. Cloning these sources with git is detailed in the dropdown below.
- Getting Sources through Git
Note: In order to use git commands, git must be installed on the computer. There are various different applications which can be used to interact with the git tools. The code blocks below detail the commands used in a bash shell.
Check if vivado-library is already included in the Vivado project, if it is not, then it should be cloned:
cd (somewhere memorable) git clone https://github.com/digilent/vivado-library -b hierarchies
Otherwise (if a separate clone of vivado-library is already included in the project), use git tools to check out the branch:
Warning! If IP from the library are already included in the project, checking out a different branch may cause changes to them. Be careful!
cd (path)/vivado-library git checkout hierarchies
Adding a Hierarchical Block to a Hardware Design
Launch Vivado, then open the Vivado Project the hierarchical block is to be used in, and open the project's Block Design.
Note: The design must contain a processor and a peripheral that can be used for stdout. In the case of Microblaze, a UART IP must be connected to the board's USBUART interface. In the case of Zynq, the PS UART is used by default.
Completing the Getting Started with Vivado and Vitis for Baremetal Software Projects guide will result in a design that fits the requirements for using these hierarchical blocks.
In Vivado's TCL Console, enter the following command:
source (path)/vivado-library/hierarchies/(hierarchy of choice)/create_hier.tcl
When the script is finished running, the block design will contain a Hierarchical Block with several IP inside of it. The IP will be connected to one another and to the block's ports and pins. The contents of the hierarchy can be viewed and changed by expanding it with the “+” button.
Check the README.txt file, which can be found in the hierarchical block's folder in vivado-library/hierarchies, for additional information about how the ports of the Hierarchy must be connected to the rest of the design. With this information in mind:
- Connect all of the hierarchical block's AXI interfaces to the processor in the design by clicking on Run Connection Automation, and checking the appropriate boxes. These interfaces may appear more than once in the connection automation dialog. Select only one entry for each interface.
- Connect any interrupts the Hierarchy may have to the appropriate interrupt controller: an AXI Interrupt Controller IP (for Microblaze designs), the Zynq Processing System's irq_f2p port (for Zynq designs).
- Connect any additional clocks to clocks generated by a Memory Interface Generator or a Clocking Wizard (for Microblaze designs), or a Zynq Processing System (for Zynq designs).
The next step, constraining the Hierarchy's external port/s, has two different Workflows:
- If a board was selected when creating the project, the Board Flow can be used for this step.
- If a part was selected instead of a board, or the Board Flow cannot be used for whatever reason, the Manual Constraint Flow should be used instead.
Creating an External Pmod Port
Open the dropdown for the chosen Workflow, below, and follow the instructions.
Note: This step is only required for Pmod hierarchical blocks. Zmod hierarchical scripts automatically create their external ports. For the purposes of this guide, consider the Zmod's external ports to have been created using the Manual Constraint Flow.
- Board Flow
Go to Vivado's Board tab and select a Pmod connector to connect to the hierarchical block. Right click on the connector's entry, typically named something like “Connector JA”, and select Connect Board Component. In the popup window, under Connect to existing IP, select the “Pmod_out” interface of the Hierarchy's Pmod Bridge IP. Click OK.
- Manual Constraint Flow
Select the Pmod_out port, then right click on it and select Make External. Select the newly created external interface port (named something like “Pmod_out_0”) in the design, and give it a memorable name.
Validating the Design and Creating a Wrapper File
Regardless of the chosen workflow, validate the block design by clicking the Validate button ( ) and save it.
Then create an HDL wrapper file, if one doesn't already exist, by right clicking on the design in the Sources pane and selecting “Create HDL Wrapper”.
Constraining the Design
This step works a little differently depending on whether the peripheral targeted by the hierarchical block is a Zmod or a Pmod. Select the dropdown for the chosen peripheral:
If the Board Flow was chosen, open the README.txt file in the hierarchical block's folder in vivado-library-hierarchies to determine whether any additional constraints are required. If there are none, skip the rest of this section.
When the Hierarchy was created, a constraint file, named “(Hierarchy Name)_Pmod_out.xdc”, was imported into the Vivado project. This file contains a template for all required constraints, regardless of the flow used. Open it now from the Sources pane, by finding it under Constraints and double clicking on it.
Constraints required for the Board Flow are left uncommented by default.
If the Manual Constraint Flow was chosen, uncomment any commented out lines that start with “set_property”, by removing the “#” symbol at the start of each of these lines.
The text “FIXME” is used in the constraint file to indicate places where values specific to the board and design must be manually entered.
Two types of manually entered values are typical of constraint files in these Hierarchies:
These FIXMEs come after the text “get_ports”. The correct values for these FIXMEs can be found by reviewing the HDL wrapper file created in the previous step. Find the names of the ports of the Pmod_out interface that is connected to the hierarchy within the port map of the HDL wrapper. Enter these names into the corresponding places in the hierarchy's constraints file.
These FIXMEs come after the text “PACKAGE_PIN”, and are only required in the Manual Constraint Flow. The correct values for these FIXMEs can be found by reviewing the master XDC file for the target board. Master XDC files for Digilent boards can be found in the digilent-xdc repository on Github. Find the LOC property values that correspond to the Pmod connector that the hierarchical block's Pmod_out port is to be connected to. Enter these values into the corresponding places in the hierarchy's constraint file.
When create_hier.tcl is run for a Zmod Hierarchical Block, a constraint file is imported which contains template constraints for each external port created by the script. The constraint file is named after the hierarchical block created by the script, followed by the name of the particular Zmod, for example: “ZmodADC_0_ZmodADC.xdc”. The constraint file can be found under the Constraints section of Vivado IP Integrato's Sources pane.
At time of writing, each Zmod Hierarchical Block provides template constraints for each of the Eclypse Z7's Zmod Ports. By default, the Zmod ADC is connected to the Eclypse Z7's Zmod Port A, and the Zmod DAC is connected to Zmod Port B. To connect to a different port, the user need only comment out the section of the xdc corresponding to the default port, and uncomment the section corresponding to the chosen port.
For other boards, the user must replace the PACKAGE_PIN location constraints for the Zmod ports with the corresponding locations found in the chosen board's master XDC file, which can be obtained through the digilent-xdc repository on GitHub.
Build the Hardware
Click Generate Bitstream. This process may take some time, depending on the complexity of the project.
Zmod Hierarchical Blocks are supported in software by the Zmod Library. If using a Zmod, see the Zmod Base Library User Guide, and skip the rest of this guide. If Petalinux support for the added hierarchy is desired, first see the Zmod Petalinux Configuration Guide
This section covers creating a baremetal software application from example source files in Vitis.
- Export Hardware
Once the project has been built, the design must be exported from Vivado so that Vitis has access to information about the hardware that a software application is being developed for. This includes the set of IP connected to the processor, their drivers, their addresses, and more. Exporting hardware after the bitstream has been generated allows you to program your board directly from within Vitis.
The wizard that pops up guides you through the options available for hardware export. The first screen allows you to select a Fixed or Expandable platform. In this case, choose a Fixed platform and click Next to continue.
This screen is not present in Vivado 2022.1, proceed to the next
The Output screen allows you to select whether only the hardware specification (Pre-synthesis) should be exported, or whether the bitstream should be included. Since the bitstream has already been generated, it should be included in the platform so that Vitis can automatically figure out where it is when programming a board. Select Include bitstream and click Next to continue.
The Files screen gives you the option to choose a name for the Xilinx Shell Architecture (XSA) file, and provide a path to a folder that the file will be placed within. Give your XSA file a name, and choose a memorable location to place it in. This file will later be imported into Vitis, so take a note of where it is placed and what it is called.
Important: Do not use spaces in the file name or export path. Underscores or camelCase are recommended instead.
Click Next to continue.
- Launch Vitis
Select the dropdown corresponding to your operating system, below.
Open a terminal and run the following commands. The install path is /opt/Xilinx by default.
source <install_path>/Vitis/2020.1/settings64.sh vitis
Note: Regardless of OS, if Vivado is open, Vitis can also be launched through the Tools → Launch Vitis toolbar option.
Upon launching Vitis, a dialog will appear where a workspace must be chosen. The workspace is the directory where all of the projects and files for the application being developed will live. If a folder that does not currently exist is chosen, it will be created. Choose a workspace and click Launch to finish launching Vitis.
- Create an Empty Application
With Vitis open, an application project must be created to hold your source files. In creating an application project, a hardware platform will also be created from an XSA file previously exported from Vivado.
On Vitis' welcome screen, click Create Application Project. The wizard that launches will be used to create and configure a new application.
The first screen of the wizard is a welcome page, which summarizes what each of the components of a software design are. Click Next to continue.
Next, the platform that the application targets must be created. Open the Create a new platform… tab.
Browse your file system to find the Xilinx Shell Architecture previously exported from Vivado. With the XSA file highlighted, click Open to select it and return to the Platform screen of the wizard.
Once you have found the XSA file and opened it, make sure that it is selected in the Hardware Specification list. Give your platform a name (the default uses whatever the name of the XSA file is and will work fine). The Generate boot components box can be used to automatically build all of the additional components necessary to boot the application from flash memory or an SD card. Leaving this box checked is recommended. Click Next to continue.
The next screen is used to set some options for the application project and the system project. The names of both projects can be set, as well as which processor core will be used to run the application. All settings can be left as defaults. Click Next to continue.
Note: A system project can contain multiple application projects, which can all be run at once.
Next, the domain that the application project operates in will be defined. In this case all default settings will be used. Click Next to continue.
Lastly, a template project will be chosen. Each template pre-configures the application project for a different purpose. Depending on the whether your application will be written in C or C++, choose Empty Application or Empty Application (C++). You will be adding an example main source file later, as opposed to working from and editing an example.
Click Finish to finish creating the project.
- Add Example Sources to the Application
Copy all of the files from the selected hierarchical block's sdk_sources folder (in the vivado-library-hierarchies folder), then paste them into the application project's src folder.
- Launch the Application
Launch a Vitis Baremetal Software Application
Make sure your board is set to boot from JTAG before it's powered on. JTAG programming can override other boot modes on some devices, but it's easier to tell when a project is programmed into the board if there isn't already one in there.
First, many applications require that a serial console is connected to the board, so that standard output (from print statements) can be viewed. For this purpose, a serial terminal should be used. Use a serial terminal application to connect to the board's serial port. Unless otherwise stated, Zynq designs use a baud rate of 115200 and Microblaze designs with an AXI UART Lite IP use a baud rate of 9600. Flow control should be set to NONE.
Note: While Vitis has a built in serial terminal included in its Debug view, it sends characters to a board on a line-by-line basis. Some software examples require the use of character-by-character reception of data. Tera Term or PuTTY are recommended if you are not sure what will work.
In the Explorer pane at the left side of the screen, right click on the application or system project that is to be run, and select Run as → 1 Launch on Hardware (Single Application Debug). The FPGA will be programmed with the bitstream, the ELF file created by the software build is loaded into system memory, and the application project will begin to run. You will need to click back over to the Vitis Serial Terminal from the Console tab.
Note: Once the project has been run at least once, you can use the green run button () in the toolbar at the top of the screen to program the board instead.
Now that the hierarchical block's example design is running, modifications can easily be made to the hardware or software.
The Vitis sources provided with the hierarchical blocks are set up such that they can be easily included in any design using that block. The subfolder below sdk_sources contains all necessary drivers for the block.
For more reference materials and guides on the Digilent products being used, navigate to their resource centers, which can be found through this wiki's Programmable Logic page.
For technical support, please visit the Digilent Forums.