Lab 04
Lab 04
Objectives
After completing this lab, you will be able to:
Use the Create IP feature of Vivado to create a custom peripheral
Modify the functionality of the IP
Use the IP Packager feature of Vivado to package the custom peripheral
Add the custom peripheral to your design
Add pin location constraints
Procedure
This lab is separated into steps that consist of general overview statements that provide information on
the detailed instructions that follow. Follow these detailed instructions to progress through the lab.
Design Description
You will extend the Lab 3 hardware design by creating and adding an AXI peripheral (refer to LED_IP in
Figure 1) to the system, and connecting it to the LEDs on the target board. You will use the IP Packager
to generate the custom IP. Next, you will connect the peripheral to the system and add pin location
constraints to connect the LED display controller peripheral to the on-board LED display. You will then
generate the bitstream. The generated bitstream is then exported to SDK and then you will develop a
software application and analyze the generated application’s object code.
1-1-1. Open Vivado by selecting Start > All Programs > Xilinx Design Tools > Vivado 2015.2 >
Vivado 2015.2
1-1-2. Click Manage IP, select New IP Location, and click Next in the New IP Location window
1-1-3. Select Verilog as the Target Language, Verilog as the Simulator language, and for IP location,
type <2015_2_zynq_labs>/led_ip (you will have to type /led_ip in the location field) and click
Finish (leave other settings as defaults)
A Virtex 7 part is chosen for this project, but later compatibility for other devices will be added to
the packaged IP later.
Name: led_ip
Description: My LED
1-2-7. Leave the other settings as default and click Next (Lite interface, Slave mode, Data Width 32,
Registers 4)
This file contains the HDL code for the interface(s) selected above. The top level file contains a
module which implements the AXI interfacing logic, and an example design to write to and read
from the number of registers specified above. This template can be used as a basis for creating
custom IP. A new output port to the LEDs will be created at the top level of the design, and the
AXI write data in the sub-module will be connected back up to the external LED port.
The Zedboard has 8 LEDs, and the ZyBo has 4 LEDs. We will create a user configurable IP with
LED port width. Scroll down to line 7 where users configuration parameter space is provided.
1-3-2. Enter the following in line 7 to define the configuration parameter (note a comma at the end of the
line):
1-3-3. Scroll down to line 18 where instruction to add user defined ports is identified.
1-3-5. Insert the following at line ~48 to pass the configuration parameter to the lower-level module:
. C_LED_WIDTH (C_LED_WIDTH),
1-3-6. Insert the following at line ~52 to make a port connection with the lower-level module:
. LED(LED),
1-3-8. Expand led_ip_v1_0 in the sources view if necessary, and open led_ip_v1_0_S_AXI.v
1-3-9. Add the configuration parameter definition and LED port to this file too as shown below:
1-3-10. Scroll down to ~line 393 and insert the following code to instantiate the user logic for the LED IP
(This code can be typed directly, or copied from the user_logic_instantiation.txt file in the
<2015_2_zynq_sources>\lab4_zed or <2015_2_zynq_sources>\lab4_zybo source folder.)
Check all the signals that are being connected and where they originate.
1-3-12. Click on the Add Sources in the Flow Navigator pane, select Add or Create Design Sources,
browse to <2015_2_zynq_sources>\lab4_zed or <2015_2_zynq_sources>\lab4_zybo, select the
lab4_user_logic.v file and click OK, make sure that Copy sources into IP Directory is checked
and then click Finish to add the file.
Check the contents of this file to understand the logic that is being implemented. Notice the
formed hierarchy.
1-3-13. Click Run Synthesis and Save if prompted. (This is to check the design synthesizes correctly
before adding it to the main design.
1-3-14. Check the Messages tab for any errors and correct if necessary before moving to the next
step
1-4-2. For the IP to appear in the IP catalog in particular categories, the IP must be configured to be part
of those categories. To change which categories the IP will appear in the IP catalog click the
Green Plus on the Categories line. This opens the Choose IP Categories window.
1-4-3. For the exercise purpose, uncheck the AXI Peripheral box and check the Basic Elements and
click OK.
1-4-4. Fill in the Vendor display name and the Company url if desired.
1-4-5. Select Compatibility. This shows the different Xilinx FPGA Families that the IP supports. The
value is inherited from the device selected for the project.
1-4-6. Right click in the Family Support table and select Add Family Explicitly… from the menu.
1-4-7. Select the Zynq family as we will be using this IP on the target board with the Zynq device, and
click OK.
1-4-8. Click on File Groups, notice that there are 2 verilog synthesis files mentioned. Click Merge
changes from IP File Groups Wizard
This will update the IP Packager with the changes that were made to the IP and add the
lab4_user_logic.v file that was added to the project.
1-4-9. Do the same on the Customization Parameters category. Expand the Hidden Parameters
category, right click C_LED_WIDTH and click Import IP Parameters… and click OK in the new
dialog window. You will see C_LED_WIDTH parameter being added with the default value of 8.
Notice that the Ports and Interfaces view shows the user created LED port with C_LED_WIDTH
parameter
Figure 7. IP Ports
1-4-11. Click on the GUI Customization pane, and see the IP symbol on the left side and
C_LED_WIDTH as a parameter on the right side of the window.
This will create led_ip_1.0 directory under the <2015_2_zynq_labs>\led_ip\ip_repo directory. The
created directory will have all the components of the IP-XACT compliant IP with what you have
provided.
1-4-13. Click Yes to close the current project, and then in the remaining Vivado window click File > Close
Project
2-1-1. Start Vivado if necessary and open either the lab3 project you created in the previous lab or the
lab3 project in the labsolution directory
2-1-2. Select File > Save Project As … to open the Save Project As dialog box. Enter lab4 as the
project name. Make sure that the Create Project Subdirectory option is checked, the project
directory path is <2015_2_zynq_labs>\ and click OK.
This will create the lab4 directory and save the project and associated directory with lab4 name.
3-1-1. Click Open Block Design under IP Integrator in the Flow Navigator pane to open the design.
3-1-2. Click the Add IP icon and search for led_ip_v1.0 in the catalog by typing “led” in the search
field.
3-1-4. Select the IP in the block diagram and change the instance name to led_ip in the properties view.
3-1-5. Double-click on the led_ip instance to see the configuration parameter. Leave the default value of
C_LED_WIDTH for the ZedBoard but change to 4 for the Zybo and click OK.
3-1-6. Click on Run Connection Automation, select /led_ip/S_AXI and click OK to automatically make
the connection from the AXI Interconnect to the IP.
3-1-8. Select the LED port of the led_ip instance (by clicking on its pin), right-click and select Make
External.
Figure 10. LED external port added and connected for ZedBoard
Figure 10. LED external port added and connected for Zybo
3-1-9. Select the Address Editor tab and verify that an address has been assigned to lep_ip.
3-1-10. Select Tools > Validate Design to run the design rules checker. There should not be any
violations.
3-2. Reset the output product and regenerate the output product which will also
update the top-level wrapper. Add the provided lab4_system.xdc
constraints file from <2015_2_zynq_sources>\lab4_zed for the ZedBoard or
from <2015_2_zynq_sources>\lab4_zybo for the Zybo.
3-2-1. In the sources view, right-click on the block diagram file, system.bd, and select Reset Output
Products… to delete the generated output products from the previous lab. Click Reset.
3-2-2. In the sources view, right-click on the block diagram file, system.bd, and select Generate
Output Products… to generate the IP-level HDL and associated files. Click Generate.
This will also update the system_wrapper.v file with LED port included at the top-level.
3-2-3. Click Add Sources in the Flow Navigator pane, select Add or Create Constraints, and click
Next.
3-2-4. Click the Green Plus button then Add Files…, browse to the <2015_2_zynq_sources>\
lab4_zed folder for the ZedBoard or <2015_2_zynq_sources>\lab4_zybo folder for the Zybo,
select lab4_system.xdc
3-2-6. Expand Constraints folder in the Sources pane, and double-click lab4_system.xdc file entry to
see its content. This file contains the pin locations and IO standards for the LEDs on the target
board. This information can usually be found in the manufacturer’s datasheet for the board.
3-2-7. Click on the Generate Bitstream in the Flow Navigator to run the synthesis, implementation, and
bitstream generation processes. (Click Save if prompted.)
3-2-8. Click Yes to run the synthesis process again as the design has changed.
4-1-2. Make sure that Include Bitstream option is selected and click OK, leaving the target directory set
to local project directory.
Note that system_wrapper.hdf file will be updated in the lab4.sdk directory and
system_wrapper_hw_platform_1 (since system_wrapper_hw_platform_0 folder already was present) folder
will be created when the SDK program opens. The system_wrapper_hw_platform_1 folder will have the
latest design (including led_ip) whereas system_wrapper_hw_platform_0 has the previous design.
4-2-1. To tidy up the workspace and save unnecessary building of a project that is not being used, right
click on the TestApp, standalone_bsp_0 and the system_wrapper_hw_platform_0 projects
from the previous lab, and click Close Project, as these projects will not be used in this lab. They
can be reopened later if needed.
4-2-3. Enter lab4 as the Project Name, choose system_wrapper_hw_platform_1 as the Target
Hardware since that has the latest hardware, for Board Support Package choose Create New
(lab4_bsp will be displayed).
Figure 12. Creating new application project with the new target hardware platform and new
bsp
4-2-4. Click Next, and select Empty Application and click Finish
4-2-5. Expand lab4 in the project view and right-click in the src folder and select Import.
4-2-8. Select lab4.c and click Finish to add the file to the project (Ignore any errors for now).
4-2-10. Since our led_ip is very similar to GPIO, we look at the GPIO documentation. Click on
Documentation link corresponding to the buttons peripheral under the Peripheral Drivers section
to open the documentation in a default browser window.
4-2-11. View the various C and Header files associated with the GPIO by clicking Files at the top of the
page.
The following steps must be performed in your software application to enable reading from the
GPIO: 1) Initialize the GPIO, 2) Set data direction, and 3) Read the data
InstancePtr is a pointer to an XGpio instance. The memory the pointer references must be pre-
allocated by the caller. Further calls to manipulate the component through the XGpio API must
be made with this pointer.
DeviceId is the unique id of the device controlled by this XGpio component. Passing in a device
id associates the generic XGpio instance to a specific device, as chosen by the caller or
application developer.
DirectionMask is a bitmask specifying which bits are inputs and which are outputs. Bits set to 0
are output and bits set to 1 are input.
4-2-13. Double-click on lab4.c in the Project Explorer view to open the file. This will populate the Outline
tab. Open the header file xparameters.h by double-clicking on xparameters.h in the Outline tab
The xparameters.h file contains the address map for peripherals in the system. This file is
generated from the hardware platform description from Vivado. Find the following #define used to
identify the dip peripheral:
ZedBoard:
Note: The number might be
#define XPAR_SW_8BIT_DEVICE_ID 1 different
Notice the other #define XPAR_SW_8BIT* statements in this section for the 8 bit SW peripheral,
and in particular the address of the peripheral defined by: XPAR_SW_8BIT_BASEADDR
Zybo:
4-2-14. Modify line 14 of lab4.c to use this macro (#define) in the XGpio_Initialize function.
Figure 15. Highlighting the code to initialize the SW_8BIT as input, and read from it
4-2-15. Do the same for the BTNS_5BIT for ZedBoard or the BTNS_4BIT for Zybo; find the macro
(#define) for the peripheral in xparameters.h, and modify line 17 in lab4.c, and save the file.
The project will be rebuilt. If there are any errors, check and fix your code. Your C code will
eventually read the value of the switches and output it to the led_ip.
4-3-2. Close led_ip.c and open the header file led_ip.h and notice the macros:
LED_IP_mWriteReg( … )
LED_IP_mReadReg( … )
/**
*
* Write a value to a LED_IP register. A 32 bit write is performed.
* If the component is implemented in a smaller width, only the least
* significant data is written.
*
* @param BaseAddress is the base address of the LED_IP device.
* @param RegOffset is the register offset from the base to write to.
* @param Data is the data written to the register.
*
* @return None.
*
* @note
* C-style signature:
* void LED_IP_mWriteReg(Xuint32 BaseAddress, unsigned RegOffset,
Xuint32 Data)
*
*/
#define LED_IP_mWriteReg(BaseAddress, RegOffset, Data) \
Xil_Out32((BaseAddress) + (RegOffset), (Xuint32)(Data))
For this driver, you can see the macros are aliases to the lower level functions Xil_Out32( ) and
Xil_Out32( ). The macros in this file make up the higher level API of the led_ip driver. If you are
writing your own driver for your own IP, you will need to use low level functions like these to read
and write from your IP as required. The low level hardware access functions are wrapped in your
driver making it easier to use your IP in an Application project.
4-3-3. Modify your C code (see figure below, or you can find modified code in lab4_soln.c from either
<2015_2_zynq_sources>\lab4_zed folder for the ZedBoard or <2015_2_zynq_sources>\
lab4_zybo folder for the Zybo) to echo the dip switch settings on the LEDs by using the led_ip
driver API macros, and save the application.
#include "led_ip.h"
4-3-5. Include the function to write to the IP (insert before the for loop):
LED_IP_mWriteReg(XPAR_LED_IP_S_AXI_BASEADDR, 0, dip_check);
Remember that the hardware address for a peripheral (e.g. the macro
XPAR_LED_IP_S_AXI_BASEADDR in the line above) can be found in xparameters.h
4-3-6. Save the file and the program will be compiled again.
5-1-1. Zybo only: Make sure that the JP7 is set to select USB power.
5-1-2. ZedBoard: Connect the Micro-USB cable to the UART port of the ZedBoard. Turn ON the power.
Zybo: Make sure that a micro-USB cable is connected to the JTAG PROG connector (next to the
power supply connector). Turn ON the power.
5-1-3. Select the tab. If it is not visible then select Window > Show view > Terminal.
Figure 17. Programming the FPGA with the appropriate hardware platform
5-1-7. Select lab4 in Project Explorer, right-click and select Run As > Launch on Hardware (GDB) to
download the application, execute ps7_init, and execute lab4.elf
Flip the DIP switches and verify that the LEDs light according to the switch settings. Verify that
you see the results of the DIP switch and Push button settings in SDK Terminal.
Figure 16. DIP switch and Push button settings displayed for ZedBoard in the terminal
Figure 16. DIP switch and Push button settings displayed for Zybo in the terminal
Note: Setting the DIP switches and push buttons will change the results displayed.
5-1-8. When finished, click on the Terminate button in the Console tab.
Conclusion
Manage IP feature was used to create an AXILite IP. The created IP was modified to add the desired
functionality. Vivado IP packager was used to update the IP and then the custom IP block was imported
into the IP library. The IP block was then added to the system. Connection automation was run, where
available, to speed up the design of the system by allowing Vivado to automatically make connections
between IP. Pin location constraints were added to the design. The design bitstream was generated.
SDK was used to define, develop, and integrate the software components of the embedded system. The
device driver was assigned to the custom IP. The peripheral-specific functional software was created and
the executable file was generated.