SpaceWire UK
Specialist providers of VHDL Intellectual Property & Design Services
Missing Image!
Part 5 - Create & build 2nd firmware project (without BSP)


This tutorial details the steps required to create a Zedboard project without the support of a BSP. The project will demonstrate how to connect up the Processor System (PS) to the LED's & Switches on the Zedboard via a GPIO module. Although it is convenient to use BSP's to get evaluation boards up and running quickly it removes the user from the details they require when using custom hardware. This tutorial goes cold turkey early on the belief the extra effort put in now will pay off in the long run and hopefully provide a fuller understanding of what is truly going on under the hood.


The aims of this tutorial are as follows :-
  1. Setup environment
  2. Create project area
  3. Launch Vivado
  4. Create project
  5. Create block design
  6. Add ZYNQ to block design
  7. Apply Zedboard presets to ZYNQ
  8. Re-customize ZYNQ
  9. Add AXI GPIO to block design
  10. Re-customize AXI GPIO
  11. Run connection automation
  12. Rename external ports
  13. Edit address map
  14. Validate block design
  15. Create HDL wrapper
  16. Create pin constraints
  17. Generate bitstream
  18. Export Hardware Platform
  19. Archive project
  20. Commit to repository

1. Setup environment

Setup Xilinx design environment for the 2021.2 toolset.
steve@Linux-Steve:/home/steve$ source
Xilinx tools available tools at /opt/Xilinx :-
1) 2021.2 - Vivado - SDK - Vitis - PetaLinux
0) Exit
Please select tools required or exit : 1

Tools are as follows :-
vivado @ /opt/Xilinx/Vivado/2021.2/bin/vivado
vitis @ /opt/Xilinx/Vitis/2021.2/bin/vitis
petalinux-build @ /opt/Xilinx/PetaLinux/2021.2/tool/tools/common/petalinux/bin/petalinux-build

2. Create project area

Create the project directory structure and change the Present Working Directory (PWD) to fw.
steve@Linux-Steve:/home/steve$ mkdir -p /home/steve/projects/leds_switches/{fw,usr/con}
steve@Linux-Steve:/home/steve$ cd /home/steve/projects/leds_switches/fw

3. Launch Vivado

Launch Vivado quietly from a Terminal.
steve@Linux-Steve:/home/steve/projects/leds_switches$ vivado -nojournal -nolog -notrace &

4. Create project

The Vivado start window will now appear. Create a project by clicking on Create Project within the Vivado 2021.2 window. Missing Image! Review the information the in the New Project : Create a New Vivado Project window and then click Next. Missing Image! In the New Project : Project Name window set Project Name to project, Project location to /home/steve/projects/leds_switches/fw & untick Create project subdirectory. Click Next to proceed. Missing Image! No additional source files are required for this project so in the New Project : Project Type window tick the Do not specify sources at this time check box and then click Next. Missing Image! In the Parts tab enter xc7z020clg484 inside the Search element, select the xc7z020clg484-1 part from the parts list and click Next to continue. Missing Image! Look over the project details in the New Project : New Project Summary window and then click Finish. Missing Image! The Vivado project window now appears.

5. Create block design

Create a block design by clicking on Create Block Design under the IP INTEGRATOR heading inside the Flow Navigator section. Missing Image! Tip: The buttons in the top menu bar of a pane provide a very useful way of expanding the working area of that pane. Maximize Missing Image! expands a pane within the project window. Float Missing Image! expands the pane beyond the project window. Restore Missing Image! reverses Maximise. Dock Missing Image! reverses Float.

The Create Block Design dialog now appears. Change the Design name to system and then click OK Missing Image! The Vivado project window now changes to reflect the addition of the Diagram pane. Expand the Diagram pane outside of the Vivado window by clicking on its Float icon Missing Image!. Missing Image!

6. Add ZYNQ to block design

Add IP to the block design by clicking on the Missing Image! button. Missing Image! Scroll down to the ZYNQ7 Processing System in the pop-up dialog and add this to the block design by double clicking on it. Missing Image! The ZYNQ7 Processing System IP is now added to the block design. Missing Image! Let Vivado automate some of the connections by clicking on Run Block Automation. Missing Image! Review the connections proposed in the Run Block Automation dialog (note the missing Apply Board Preset checkbox) and then click OK. Missing Image! Some of the connections are now made in the block design. Missing Image!

7. Apply Zedboard presets to ZYNQ

Having gone down the FPGA part selection route and not the board selection route leaves the ZYNQ7 Processing System configured using its default settings.

The Zedboard settings applied by selecting the Apply Board Preset (if it were present) are as shown below. Note there are some very important settings that MUST be applied, to name a few, the Bank 1 voltage and the DDR configuration. These settings can be applied through the ZYNQ7 Processing System re-customization dialog but this time around the script below shall be used to configure the PS in exactly the same way as if the Zedboard presets were applied.


  1. # Peripheral I/O Pins
  2. set_property -dict [list \
  7. CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \
  9. CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \
  20. ] [get_bd_cells processing_system7_0]

  21. # MIO Configuration
  22. set_property -dict [list \
  23. CONFIG.PCW_MIO_0_PULLUP {disabled} \
  24. CONFIG.PCW_MIO_1_PULLUP {disabled} \
  25. CONFIG.PCW_MIO_1_SLEW {fast} \
  26. CONFIG.PCW_MIO_2_SLEW {fast} \
  27. CONFIG.PCW_MIO_3_SLEW {fast} \
  28. CONFIG.PCW_MIO_4_SLEW {fast} \
  29. CONFIG.PCW_MIO_5_SLEW {fast} \
  30. CONFIG.PCW_MIO_6_SLEW {fast} \
  31. CONFIG.PCW_MIO_8_SLEW {fast} \
  32. CONFIG.PCW_MIO_9_PULLUP {disabled} \
  33. CONFIG.PCW_MIO_10_PULLUP {disabled} \
  34. CONFIG.PCW_MIO_11_PULLUP {disabled} \
  35. CONFIG.PCW_MIO_12_PULLUP {disabled} \
  36. CONFIG.PCW_MIO_13_PULLUP {disabled} \
  37. CONFIG.PCW_MIO_14_PULLUP {disabled} \
  38. CONFIG.PCW_MIO_15_PULLUP {disabled} \
  39. CONFIG.PCW_MIO_16_PULLUP {disabled} \
  40. CONFIG.PCW_MIO_16_SLEW {fast} \
  41. CONFIG.PCW_MIO_17_PULLUP {disabled} \
  42. CONFIG.PCW_MIO_17_SLEW {fast} \
  43. CONFIG.PCW_MIO_18_PULLUP {disabled} \
  44. CONFIG.PCW_MIO_18_SLEW {fast} \
  45. CONFIG.PCW_MIO_19_PULLUP {disabled} \
  46. CONFIG.PCW_MIO_19_SLEW {fast} \
  47. CONFIG.PCW_MIO_20_PULLUP {disabled} \
  48. CONFIG.PCW_MIO_20_SLEW {fast} \
  49. CONFIG.PCW_MIO_21_PULLUP {disabled} \
  50. CONFIG.PCW_MIO_21_SLEW {fast} \
  51. CONFIG.PCW_MIO_22_PULLUP {disabled} \
  52. CONFIG.PCW_MIO_22_SLEW {fast} \
  53. CONFIG.PCW_MIO_23_PULLUP {disabled} \
  54. CONFIG.PCW_MIO_23_SLEW {fast} \
  55. CONFIG.PCW_MIO_24_PULLUP {disabled} \
  56. CONFIG.PCW_MIO_24_SLEW {fast} \
  57. CONFIG.PCW_MIO_25_PULLUP {disabled} \
  58. CONFIG.PCW_MIO_25_SLEW {fast} \
  59. CONFIG.PCW_MIO_26_PULLUP {disabled} \
  60. CONFIG.PCW_MIO_26_SLEW {fast} \
  61. CONFIG.PCW_MIO_27_PULLUP {disabled} \
  62. CONFIG.PCW_MIO_27_SLEW {fast} \
  63. CONFIG.PCW_MIO_28_PULLUP {disabled} \
  64. CONFIG.PCW_MIO_28_SLEW {fast} \
  65. CONFIG.PCW_MIO_29_PULLUP {disabled} \
  66. CONFIG.PCW_MIO_29_SLEW {fast} \
  67. CONFIG.PCW_MIO_30_PULLUP {disabled} \
  68. CONFIG.PCW_MIO_30_SLEW {fast} \
  69. CONFIG.PCW_MIO_31_PULLUP {disabled} \
  70. CONFIG.PCW_MIO_31_SLEW {fast} \
  71. CONFIG.PCW_MIO_32_PULLUP {disabled} \
  72. CONFIG.PCW_MIO_32_SLEW {fast} \
  73. CONFIG.PCW_MIO_33_PULLUP {disabled} \
  74. CONFIG.PCW_MIO_33_SLEW {fast} \
  75. CONFIG.PCW_MIO_34_PULLUP {disabled} \
  76. CONFIG.PCW_MIO_34_SLEW {fast} \
  77. CONFIG.PCW_MIO_35_PULLUP {disabled} \
  78. CONFIG.PCW_MIO_35_SLEW {fast} \
  79. CONFIG.PCW_MIO_36_PULLUP {disabled} \
  80. CONFIG.PCW_MIO_36_SLEW {fast} \
  81. CONFIG.PCW_MIO_37_PULLUP {disabled} \
  82. CONFIG.PCW_MIO_37_SLEW {fast} \
  83. CONFIG.PCW_MIO_38_PULLUP {disabled} \
  84. CONFIG.PCW_MIO_38_SLEW {fast} \
  85. CONFIG.PCW_MIO_39_PULLUP {disabled} \
  86. CONFIG.PCW_MIO_39_SLEW {fast} \
  87. CONFIG.PCW_MIO_40_PULLUP {disabled} \
  88. CONFIG.PCW_MIO_40_SLEW {fast} \
  89. CONFIG.PCW_MIO_41_PULLUP {disabled} \
  90. CONFIG.PCW_MIO_41_SLEW {fast} \
  91. CONFIG.PCW_MIO_42_PULLUP {disabled} \
  92. CONFIG.PCW_MIO_42_SLEW {fast} \
  93. CONFIG.PCW_MIO_43_PULLUP {disabled} \
  94. CONFIG.PCW_MIO_43_SLEW {fast} \
  95. CONFIG.PCW_MIO_44_PULLUP {disabled} \
  96. CONFIG.PCW_MIO_44_SLEW {fast} \
  97. CONFIG.PCW_MIO_45_PULLUP {disabled} \
  98. CONFIG.PCW_MIO_45_SLEW {fast} \
  99. CONFIG.PCW_MIO_46_PULLUP {disabled} \
  100. CONFIG.PCW_MIO_47_PULLUP {disabled} \
  101. CONFIG.PCW_MIO_48_PULLUP {disabled} \
  102. CONFIG.PCW_MIO_49_PULLUP {disabled} \
  103. CONFIG.PCW_MIO_50_PULLUP {disabled} \
  104. CONFIG.PCW_MIO_51_PULLUP {disabled} \
  105. CONFIG.PCW_MIO_52_PULLUP {disabled} \
  106. CONFIG.PCW_MIO_53_PULLUP {disabled} \
  107. ] [get_bd_cells processing_system7_0]

  108. # Clock Configuration
  109. set_property -dict [list \
  110. CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {533.333313} \
  116. CONFIG.PCW_EN_CLK1_PORT {0} \
  117. ] [get_bd_cells processing_system7_0]

  118. # DDR Configuration
  119. set_property -dict [list \
  130. ] [get_bd_cells processing_system7_0]

Save the zedboard_presets.tcl script into /home/steve/projects/common/fw and run the script from the Tcl Console using source /home/steve/projects/common/fw/zedboard_presets.tcl. Missing Image! After execution of the script the ZYNQ7 Processing System should reflect the applied changes. Missing Image!

8. Re-customize ZYNQ

Double click on the ZYNQ7 Processing System module to begin re-customization.

Remove the USB 0 connection from the ZYNQ7 Processing System as it is not required for this design. Click on MIO Configuration, expand I/O Peripherals and untick USB 0. Missing Image! Remove the Timer connection from the ZYNQ7 Processing System as it is not required for this design. Click on MIO Configuration, expand Application Processor Unit and untick Timer 0. Missing Image! Click OK to commit the changes.

9. Add AXI GPIO to block design

In the floating Diagram window click on the Add IP Missing Image! icon and select AXI GPIO from the menu. The diagram now shows two unconnected IP modules. Missing Image!

10. Re-customize AXI GPIO

Connections to both the LED's and Slide Switches on the ZedBoard are required for this design. Double click on the AXI GPIO module to begin re-customization. Missing Image! Under GPIO tick All Outputs, set the GPIO Width to 8 and set the Default Output Value to 0x00000018. Tick Enable Dual Channel, then under GPIO 2 tick All Inputs and set the GPIO Width to 8. Missing Image! Click OK to commit the changes.

11. Run connection automation

The Diagram now contains all the I/O connections required by the two IP modules but these are totally unconnected. Let Vivado automate the connections by clicking on Run Connection Automation. Missing Image! Review each connection by selected GPIO, GPIO2 & S_AXI respectively. Once reviewed tick All Automation to enable all the suggested connections and then click OK to commit the changes. Missing Image! The extra modules of Processor System Reset & AXI Interconnect are now added to the block design to make connecting up the ZYNQ7 Processing System & AXI GPIO possible. Resize the canvas to obtain a better view of the design and click on the Regenerate Layout Missing Image! icon to obtain a better layout. Missing Image!

12. Rename external ports

Rename the external ports that GPIO & GPIO2 are connected to so they have more meaningful names. Highlight gpio_rtl_0 and goto the Vivado cockpit window, in the External Interface Properties under BLOCK DESIGN change the Name field from gpio_rtl_0 to leds. Missing Image! Using the same process rename gpio_rtl_1 to switches. Missing Image! The block design should now reflect the changes. Missing Image!

13. Edit address map

Check the address map assignment inside the Address Editor under the BLOCK DESIGN section. The axi_gpio_0 module should have a Master Base Address of 0x4120_0000 , if not change it. Change the Range to 4k Missing Image!

14. Validate block design

Verify the block design is error free by clicking on the Validate Design Missing Image! icon. All being well the Validation successful dialogue should now appear. Missing Image! Once validated return the floating Diagram pane back to Vivado by clicking on the Dock Missing Image! icon. Save the Diagram.

15. Create HDL wrapper

Create a top-level wrapper for the block design since block designs cannot be the top-level of a design. Right click on and select Create HDL Wrapper... from the menu. Missing Image! The Create HDL Wrapper dialog now appears. Select Let Vivado manage wrapper and auto-update and then click OK. Missing Image!

16. Create pin constraints

Using the zedboard_master_XDC_RevC_D_v3.xdc from /home/steve/projects/common/fw as a reference constraints can be constructed for the design. Right click on Constraints under Sources within BLOCK DESIGN and select Add Sources... from the context menu. Missing Image! In the Add Sources dialogue select Add or create constraints and then click Next. Missing Image! In the Add Sources - Add or Create Constraints dialogue click on Create File. Missing Image! In the Create Constraints File dialogue set the File name to zedboard, set the File location to /home/steve/projects/leds_switches/usr/con and then click Next. Missing Image! In the Add Sources - Add or Create Constraints dialogue click on Finish. Missing Image! Double click on the newly created constraints zedboard.xdc within Sources » Constraints » constrs_1 to edit. Missing Image! Add the following to zedboard.xdc and save the file.


  1. # LED's - Bank 33
  2. set_property PACKAGE_PIN T22 [get_ports {leds_tri_o[0]}];  # "LD0"
  3. set_property PACKAGE_PIN T21 [get_ports {leds_tri_o[1]}];  # "LD1"
  4. set_property PACKAGE_PIN U22 [get_ports {leds_tri_o[2]}];  # "LD2"
  5. set_property PACKAGE_PIN U21 [get_ports {leds_tri_o[3]}];  # "LD3"
  6. set_property PACKAGE_PIN V22 [get_ports {leds_tri_o[4]}];  # "LD4"
  7. set_property PACKAGE_PIN W22 [get_ports {leds_tri_o[5]}];  # "LD5"
  8. set_property PACKAGE_PIN U19 [get_ports {leds_tri_o[6]}];  # "LD6"
  9. set_property PACKAGE_PIN U14 [get_ports {leds_tri_o[7]}];  # "LD7"

  10. # Slide Switches - Bank 34 & 35
  11. set_property PACKAGE_PIN F22 [get_ports {switches_tri_i[0]}];  # "SW0"
  12. set_property PACKAGE_PIN G22 [get_ports {switches_tri_i[1]}];  # "SW1"
  13. set_property PACKAGE_PIN H22 [get_ports {switches_tri_i[2]}];  # "SW2"
  14. set_property PACKAGE_PIN F21 [get_ports {switches_tri_i[3]}];  # "SW3"
  15. set_property PACKAGE_PIN H19 [get_ports {switches_tri_i[4]}];  # "SW4"
  16. set_property PACKAGE_PIN H18 [get_ports {switches_tri_i[5]}];  # "SW5"
  17. set_property PACKAGE_PIN H17 [get_ports {switches_tri_i[6]}];  # "SW6"
  18. set_property PACKAGE_PIN M15 [get_ports {switches_tri_i[7]}];  # "SW7"

  19. # Banks
  20. set_property IOSTANDARD LVCMOS33 [get_ports -of_objects [get_iobanks 33]];
  21. set_property IOSTANDARD LVCMOS18 [get_ports -of_objects [get_iobanks 34]];
  22. set_property IOSTANDARD LVCMOS18 [get_ports -of_objects [get_iobanks 35]];

17. Generate bitstream

Generate the programmable logic bitstream by clicking on Generate Bitstream under the PROGRAM AND DEBUG heading inside the Flow Navigator section.

18. Export Hardware Platform

Export the hardware platform by selecting File » Export » Export Hardware... from the main menu. Include the bitstream in the exported hardware file and save as /home/steve/projects/leds_switches/fw/system_wrapper.xsa.

19. Archive project

Create a project regeneration script by selecting File » Project » Write Tcl... from the main menu. Tick the Copy sources to new project & Recreate Block Designs using Tcl options and set the Output file to /home/steve/projects/leds_switches/fw/project.tcl.

Review the script paying particular attention to any files listed below the following section of the header. There are no additional files listed for this project.
  1. # NOTE: In order to use this script for source control purposes, please make sure that the
  2. #       following files are added to the source control system:-
Prevent the script from creating a project directory by removed this option from the create_project command.
steve@Linux-Steve:/home/steve/projects/leds_switches/fw$ sed -i 's/create_project ${_xil_proj_name_} .\/${_xil_proj_name_}/create_project ${_xil_proj_name_}/g' project.tcl

20. Commit to repository

To commit the minimum set of files into repository the following steps are required :-
  1. Create a SVN repository in the repos area.
  2. Checkout the empty repository into the project area.
  3. Add the fw/project.tcl file to the change list.
  4. Add the usr/con/zedboard.xdc file to the change list.
  5. Commit the changes along with a comment.
steve@Linux-Steve:/home/steve/projects/leds_switches/fw$ cd ..
steve@Linux-Steve:/home/steve/projects/leds_switches$ svnadmin create /home/steve/repos/leds_switches
steve@Linux-Steve:/home/steve/projects/leds_switches$ svn checkout file:///home/steve/repos/leds_switches .
steve@Linux-Steve:/home/steve/projects/leds_switches$ svn add --parents fw/project.tcl
steve@Linux-Steve:/home/steve/projects/leds_switches$ svn add --parents usr/con/zedboard.xdc
steve@Linux-Steve:/home/steve/projects/leds_switches$ svn commit -m "Basic Zedboard design consisting of a ZYNQ7 Processing System controlling & monitoring LED's & Slide Switches via a GPIO"