Bar
SpaceWire UK
Specialist providers of VHDL Intellectual Property & Design Services
BarBarBarBar
Tutorial
Missing Image!
Part 1 - Installation of tools, setup of environment and creation of project area

Introduction

This tutorial details the steps required for downloading, installing and setting up the Vitis, Vivado, Vitis HLS & PetaLinux tools.

Aims

The aims of this tutorial are as follows :-

    Part 1 - Customize tutorial

    1. Change instructions & commands to match the tutorial to the readers own system (optional)

    Part 2 - Download, install & setup design tools

    1. Download tools
    2. Create installation directories
    3. Install Vitis, Vivado & Vitis HLS
    4. Install PetaLinux dependencies
    5. Install PetaLinux
    6. Install 3rd party tools

    Part 2 - Create common project & useful assistance scripts

    1. Create common project area
    2. Create scripts for initial root project creation, Vivado project recreation & Vitis project recreation
    3. Create scripts for setting up the Xilinx design tools
    4. Setup shell initialization script

    Part 3 - Setup revision control environment

    1. Setup revision control tools & environment

    Part 3 - Perform housekeeping

    1. Cleanup downloads
    2. Remove startup programs

    Part 2 - Revision Control

    1. Create repository & commit files

    Part 6 - Quickstart

    1. Obtain tutorial files from Bitbucket for the common project
    #### Part 1 - Customize tutorial ####

    1. Change instructions & commands to match the tutorial to the readers own system (optional)

    The pages in this tutorial are dynamically reconfigurable to allow marrying up instructions and commands to the readers own system. The options below can be used to change directory locations, IP addresses, usernames and host details. This allows commands to be directly copied into the readers own terminal and executed without the need to edit. Cookies are used to store the modifications such that they are applied to all pages within the same browser session. Note the screenshots will not dynamically change and may not reflect the instructions, the instructions take precedence.

    : Downloads location

    : Projects location

    : SWUK Tutorial location

    : Repositories location

    : Linux user (whoami)

    : Linux host (hostname)

    : Zedboard location

    #### Part 2 - Download, install & setup design tools ####

    2. Download tools

    Download the following files from Xilinx & Avnet into ~/Downloads.
    1. Xilinx Unified Installer 2021.2 SFD (71.9 GB)
    2. ZED BSP (117.4 MB)
    3. ZedBoard Master XDC Rev C_D v3 (3.9 KB)

    3. Create installation directories

    Create Xilinx installation directory structure and change its ownership for user installation.
    steve@Desktop:~$ sudo mkdir /opt/Xilinx
    steve@Desktop:~$ sudo chown $(id -un):$(id -gn) /opt/Xilinx
    

    4. Install Vitis, Vivado & Vitis HLS

    Unzip the tarball & kick off the installation process.
    steve@Desktop:~$ tar -xzf ~/Downloads/Xilinx_Unified_2021.2_1021_0703.tar.gz -C ~/Downloads
    steve@Desktop:~$ ~/Downloads/Xilinx_Unified_2021.2_1021_0703/xsetup
    
    In the Welcome dialog click Next to proceed. Missing Image! In the Select Product to Install dialog select Vitis and click Next to proceed. Missing Image! In the Vitis Unified Software Platform dialog, expand the menu items and select only what is required based on licensing and disk space. The default is to install everything which uses 192.89 Gb of disk space. The following shows the minimum required to use the ZedBoard with a WebPack license. Once happy with the selections click Next to proceed. Missing Image! In the Accept License Agreements dialog, tick both I Agree boxes and click Next to proceed. Missing Image! In the Select Destination Directory dialog, enter /opt/Xilinx for the installation directory, untick the Create program group entries, untick the Create desktop shortcuts and click Next to proceed. Note the location of DocNav, this is not versioned like Vitis, Vivado & Vitis HLS, hence any existing DocNav installation at this location will be overwritten. Missing Image! In the Installation Summary dialog, review the details provided and click Install to proceed. Missing Image! The Installation Progress dialog will now appear showing the progress of the installation (takes around 45 minutes to complete). Missing Image! Once installation is complete the Xilinx Software Install dialog will appear, click OK to proceed. Missing Image! Depending on what devices were selected for installation will ultimately determine whether or not further dialogs appear regarding licensing arrangements. With just Zynq-7000 selected no further dialogs appear and the WebPack license will be used as default.

    Install the cable drivers to gain access to the Zedboard hardware.
    steve@Desktop:~$ cd /opt/Xilinx/Vivado/2021.2/data/xicom/cable_drivers/lin64/install_script/install_drivers
    steve@Desktop:/opt/Xilinx/Vivado/2021.2/data/xicom/cable_drivers/lin64/install_script/install_drivers$ sudo ./install_drivers
    steve@Desktop:~$ cd ~
    

    5. Install PetaLinux dependencies

    PetaLinux has a number of dependencies that the installer does not automatically install. These can be found in the 2020.2 PetaLinux Package List spreadsheet along with the command required to install them. To make the installation run smoother the auto-approve option (-y) can be added to the command. For Xubuntu an extra package (libncurses5) is also required. Execute the modified install command to install the dependencies.
    steve@Desktop:~$ sudo apt-get install -y iproute2 gawk python3 python build-essential gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat chrpath socat xterm autoconf libtool tar unzip texinfo zlib1g-dev gcc-multilib automake zlib1g:i386 screen pax gzip cpio python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 libncurses5
    

    6. Install PetaLinux

    Kick off the installation process.
    steve@Desktop:~$ ~/Downloads/Xilinx_Unified_2021.2_1021_0703/xsetup
    
    In the Welcome dialog click Next to proceed. Missing Image! In the Select Product to Install dialog select PetaLinux (Linux only) and click Next to proceed. Missing Image! In the Select Edition to Install dialog select PetaLinux arm and click Next to proceed. Missing Image! In the Accept License Agreements dialog, tick both I Agree boxes and click Next to proceed. Missing Image! In the Select Destination Directory dialog, enter /opt/Xilinx for the installation directory, untick the Create program group entries, untick the Create desktop shortcuts and click Next to proceed. Missing Image! In the Installation Summary dialog, review the details provided and click Install to proceed. Missing Image! Once installation is complete the Xilinx Software Install dialog will appear, click OK to proceed. Missing Image!

    7. Install 3rd party tools

    Although Vitis does have a terminal emulator built in having a standalone tool kicking around is very desirable. Quite a few are available, however for this tutorial MiniCom will be the tool of choice. If not already installed install it as shown below. Access to the serial port requires superuser privileges, to remove this restriction the user must be added to the dialout group as shown below (log out and back in for this to take effect).
    steve@Desktop:~$ sudo apt-get install minicom
    steve@Desktop:~$ sudo adduser $(id -un) dialout
    
    Communicating with the Zedboard via MiniCom is achieved as shown below.
    steve@Desktop:~$ minicom -D /dev/ttyACM0 -b 115200
    
    Squirreling projects away for later retrieval is a must have capability. There are many RCS tools available, however for this tutorial GIT will be the tool of choice. If not already installed install as shown below.
    steve@Desktop:~$ sudo apt-get install -y git
    
    A decent text editor is a must have, ideally something with good column editing capabilities. There are loads of editors to choose from, however for this tutorial Sublime will be the tool of choice. If not already installed install it as shown below.
    steve@Desktop:~$ wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -
    steve@Desktop:~$ sudo apt-add-repository "deb https://download.sublimetext.com/ apt/stable/"
    steve@Desktop:~$ sudo apt install -y sublime-text
    
    To add Verilog & VHDL syntax highlighting to Sublime, launch the tool and firstly install Package Control by going to Menu » Tools » Install Package Control.... Now goto Menu » Preferences » Package Control » Install Package and select SystemVerilog. Do the same for VHDL but select Smart VHDL at the end instead of SystemVerilog.

    To achieve remote command line URL access to the Zedboard Client URL (curl) will be used. If not already installed, install as shown below.
    steve@Desktop:~$ sudo apt-get install -y curl
    
    To copy files to PetaLinux Secure Copy (scp) will be used. To make this easier SSH Password (sshpass) will be used to provided the password to the Secure Copy command. If not already installed, install as shown below.
    steve@Desktop:~$ sudo apt-get install -y sshpass
    
    #### Part 2 - Create common project & useful assistance scripts ####

    8. Create common project area

    Create root projects directory and a common project to hold shared and general files used across multiple projects (sudo & 2nd command may not be necessary depending on location).
    steve@Desktop:~$ sudo mkdir -p ~/projects
    steve@Desktop:~$ sudo chown $(id -un):$(id -gn) ~/projects
    steve@Desktop:~$ mkdir -p ~/projects/common/{fw/src/{constraint,script},sw/src/{bsp,script},other/src/script}
    steve@Desktop:~$ cd ~/projects/common
    
    Copy Zedboard master constrains into common firmware area.
    steve@Desktop:~/projects/common$ unzip ~/Downloads/zedboard_master_XDC_RevC_D_v3.zip -d ~/projects/common/fw/src/constraint
    
    Move Zedboard BSP into common software area.
    steve@Desktop:~/projects/common$ mv ~/Downloads/avnet-digilent-zedboard-v2021.2-final.bsp ~/projects/common/sw/src/bsp
    

    9. Create scripts for initial root project creation, Vivado project recreation & Vitis project recreation

    Create a simple shell script to create a new project containing a consistent directory structure that will be used on all new projects.
    steve@Desktop:~/projects/common$ subl other/src/script/create_project_structure.sh
    

    create_project_structure.sh

    #!/bin/bash
    
    
    #
    # File .......... create_project_structure.sh
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 29 December 2021
    # Description ...
    #   Simple script to create a possible project directory structure for combined
    # firmware, hardware, operating system & software development. Very much work
    # in progress and by all means not a golden solution to anything.
    #
    
    
    # Print instructions
    function print_args {
      printf "\n"
      printf "Create project (FW, HW, OS & SW) directory structure\n"
      printf "\n"
      printf "Usage: %s dir\n" $1
      printf "\n"
      printf "Where: dir .... Project directory to create & populate\n"
      printf "\n"
      printf "Example: %s ~/projects/example_project\n" $1
      printf "Example: %s /usr/projects/hello_world\n" $1
      printf "\n"
      exit 1
    }
    
    
    # Deal with command line arguments
    if [ $# != 1 ]; then
      print_args $0
    fi
    
    
    # Get project base directory
    base=$1
    
    
    # Echo operation
    echo "Creating project directory structure @ ${base}"
    
    
    # Project directories
    declare -a dirs=(
      # Firmware
      "fw/src/constraint"
      "fw/src/design"
      "fw/src/diagram"
      "fw/src/document"
      "fw/src/ip"
      "fw/src/ip_repo"
      "fw/src/other"
      "fw/src/script"
      "fw/src/testbench"
      "fw/vivado"
      # Hardware
      "hw/src/schematic"
      # Operating System
      "os/src/other"
      # Software
      "sw/src/c"
      "sw/src/other"
      "sw/src/script"
      "sw/vitis"
    )
    
    
    # Iterate through directories
    for dir in "${dirs[@]}"
    do
    #  echo "Creating ... ${base}/${dir}"
      mkdir -p "${base}/${dir}"
    done
    
    
    # Create C source starter file
    touch "${base}/sw/src/c/$(basename $base).c"
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/other/src/script/create_project_structure.sh -O other/src/script/create_project_structure.sh
    
    Create a shell script and a Tcl script that recreates a Vivado project from base source files.
    steve@Desktop:~/projects/common$ subl fw/src/script/create_vivado_project.sh
    

    create_vivado_project.sh

    #!/bin/bash
    
    #
    # File .......... create_vivado_project.sh
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 03 May 2021
    # Description ...
    #   Very simple script to launch Vivado and run the TCL script. Should be run
    # in the project host directory that contains the fw & sw subdirectories, for
    # example :-
    #
    # user@host:~/projects/project$ create_vivado_project.sh
    # user@host:~/projects/project$ create_vivado_project.sh build
    #
    
    # Get command line arguments
    if [ $# == 1 ]; then
      arg1=$1
    else
      arg1=""
    fi
    
    # Get script location
    dir_script=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
    
    # Get present working directory
    dir_pwd=$(pwd)
    
    # Set directory structure
    dir_base="fw"
    dir_fw_project="vivado"
    
    # Sanity check directory structure
    if [ -d "${dir_pwd}/${dir_base}" ]; then
      if [ ! -e "${dir_pwd}/${dir_base}/${dir_fw_project}" ]; then
    
        # Launch Vivado
        if [ "$arg1" == "build" ]; then
          vivado -nojournal -nolog -notrace -mode gui -source "${dir_script}/create_vivado_project.tcl" -tclargs build &
        else
          vivado -nojournal -nolog -notrace -mode gui -source "${dir_script}/create_vivado_project.tcl" &
        fi
    
      else
        echo "Error: Firmware project directory \"${dir_base}/${dir_fw_project}\" already exists, exiting."
      fi
    else
      echo "Error: Firmware base directory \"${dir_base}\" does not exists, exiting."
    fi
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/fw/src/script/create_vivado_project.sh -O fw/src/script/create_vivado_project.sh
    
    steve@Desktop:~/projects/common$ subl fw/src/script/create_vivado_project.tcl
    

    create_vivado_project.tcl

    #
    # File .......... create_vivado_project.tcl
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 23 December 2021
    # Description ...
    #   Simple Tcl script to create a new Vivado project, import external
    # sources and (optionally) generate the bitstream & export the hardware.
    #
    
    puts "Set Global variables"
    set dir_firmware    "fw/vivado"
    set dir_user        "../src"
    set dir_diagram     "$dir_user/diagram"
    set dir_design      "$dir_user/design"
    set dir_ip          "$dir_user/ip"
    set dir_ip_repo     "$dir_user/ip_repo"
    set dir_constraint  "$dir_user/constraint"
    set dir_testbench   "$dir_user/testbench"
    set dir_script      "$dir_user/script"
    
    puts "NOTE: Create project directory, project & change PWD"
    create_project project $dir_firmware -part xc7z020clg484-1
    cd $dir_firmware
    
    puts "NOTE: Add local IP Repository"
    if {[file exist $dir_ip_repo]} {
      set_property  ip_repo_paths  $dir_ip_repo [current_project]
      update_ip_catalog
    }
    
    puts "NOTE: Add scripts"
    add_files -quiet -norecurse -fileset utils_1 $dir_script
    set tcls [get_files *.tcl]
    foreach tcl $tcls {
      set tcl_name [file tail $tcl]
      switch $tcl_name {
        "pre_synth.tcl" {
          set_property STEPS.SYNTH_DESIGN.TCL.PRE [ get_files $tcl -of [get_fileset utils_1] ] [get_runs synth_1]
        }
        "post_bit.tcl" {
          set_property STEPS.WRITE_BITSTREAM.TCL.POST [ get_files $tcl -of [get_fileset utils_1] ] [get_runs impl_1]
        }
        default {
          puts "NOTE: Unfamiliar tcl script found - $tcl_name"
        }
      }
    }
    
    puts "NOTE: Add block designs"
    add_files -quiet -norecurse [glob -nocomplain "$dir_diagram/*/*.bd"]
    
    puts "NOE: Add design sources"
    add_files -quiet -norecurse $dir_design
    
    puts "NOTE: Add IPs"
    add_files -quiet [glob -nocomplain "$dir_ip/*/*.xci"]
    
    puts "NOTE: Add constraints"
    add_files -quiet -norecurse -fileset constrs_1 $dir_constraint
    
    puts "NOTE: Add testbench sources"
    add_files -quiet -norecurse -fileset sim_1 $dir_testbench
    
    puts "NOTE: Recreate (by opening) all block designs..."
    set bds [glob -nocomplain "$dir_diagram/*/*.bd"]
    foreach bd $bds {
      puts "NOTE: Open \"$bd\" block design"
      open_bd_design $bd
    }
    
    puts "NOTE: Generate all (none-overwrite) block designs wrappers..."
    set bds [get_bd_designs -quiet]
    foreach bd $bds {
      puts "NOTE: Generate \"$bd\" block design wrapper"
      set bd_file [get_files $bd.bd]
      set bd_path [file dirname $bd_file]
      set wrapper_files [glob -nocomplain $bd_path/hdl/${bd}_wrapper.*]
      if {[llength $wrapper_files] == 0} {
        set wrapper_file [make_wrapper -files $bd_file -top]
      }
      add_files -quiet -norecurse $bd_path/hdl
    }
    
    puts "NOTE: Close all block designs..."
    set bds [get_bd_designs -quiet]
    foreach bd $bds {
      puts "NOTE: Close \"$bd\" block design"
      close_bd_design $bd
    }
    
    puts "NOTE: Check for build argument..."
    if { $argc == 1 } {
      set arg0 [lindex $argv 0]
      if { $arg0 == "build" } {
        puts "NOTE: Generate bitstream & export hardware"
        launch_runs impl_1 -to_step write_bitstream -jobs 4
        wait_on_run impl_1
        write_hw_platform -fixed -include_bit -force -file ../system_wrapper.xsa
      }
    }
    
    puts "NOTE: That's all folks!"
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/fw/src/script/create_vivado_project.tcl -O fw/src/script/create_vivado_project.tcl
    
    Create a shell script and a Tcl script that recreates a Vitis project from base source files.
    steve@Desktop:~/projects/common$ subl sw/src/script/create_vitis_project.sh
    

    create_vitis_project.sh

    #!/bin/bash
    
    #
    # File .......... create_vitis_project.sh
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 03 May 2021
    # Description ...
    #   Very simple script to launch the Xilinx software command-line tool,
    # run the TCL script and launch Vitis. Should be run in the project host
    # directory that contains the fw & sw subdirectories, for example :-
    #
    # user@host:~/projects/project$ create_vitis_project.sh
    # user@host:~/projects/project$ create_vitis_project.sh build
    #
    
    # Get command line arguments
    if [ $# == 1 ]; then
      arg1=$1
    else
      arg1=""
    fi
    
    # Get script location
    dir_script=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
    
    # Get present working directory
    dir_pwd=$(pwd)
    
    # Set directory structure
    dir_base="sw"
    dir_sw_project="vitis"
    
    # Sanity check directory structure
    if [ -d "${dir_pwd}/${dir_base}" ]; then
      if [ ! -e "${dir_pwd}/${dir_base}/${dir_sw_project}" ]; then
    
        # Get last element of path (project name)
        dir_project=${dir_pwd##*/}
    
        # Call Xilinx Software Commandline Tool
        if [ "$arg1" == "build" ]; then
          xsct "${dir_script}/create_vitis_project.tcl" "${dir_project}" build
        else
          xsct "${dir_script}/create_vitis_project.tcl" "${dir_project}"
        fi
    
        # Launch Vitis
        vitis -workspace "${dir_base}/${dir_sw_project}" &
    
      else
        echo "Error: Software project directory \"${dir_base}/${dir_sw_project}\" already exists, exiting."
      fi
    else
      echo "Error: Software base directory \"${dir_base}\" does not exists, exiting."
    fi
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/sw/src/script/create_vitis_project.sh -O sw/src/script/create_vitis_project.sh
    
    steve@Desktop:~/projects/common$ subl sw/src/script/create_vitis_project.tcl
    

    create_vitis_project.tcl

    #
    # File .......... create_vitis_project.tcl
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 21 Dec 2021
    # Description ...
    #   Simple Tcl script to create a new Vitis application, import external
    # sources and (optionally) build the application.
    #
    
    # Check for project name argument, exit if not found.
    if { $argc == 0 } {
      puts "Error: No project name provided, exiting..."
      exit 1
    }
    set project [lindex $argv 0]
    
    # Create and build new project.
    setws sw/vitis
    app create -name $project -hw fw/system_wrapper.xsa -os standalone -proc ps7_cortexa9_0 -template {Empty Application(C)}
    set abs_path [file normalize sw/src/c]
    importsources -name $project -path $abs_path -soft-link
    if { $argc > 1 } {
      set arg1 [lindex $argv 1]
      if { $arg1 == "build" } {
        app build -name $project
      }
    }
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/sw/src/script/create_vitis_project.tcl -O sw/src/script/create_vitis_project.tcl
    
    Set execute permission on the shell scripts.
    steve@Desktop:~/projects/common$ chmod +x other/src/script/create_project_structure.sh
    steve@Desktop:~/projects/common$ chmod +x fw/src/script/create_vivado_project.sh
    steve@Desktop:~/projects/common$ chmod +x sw/src/script/create_vitis_project.sh
    

    10. Create scripts for setting up the Xilinx design tools

    Create a simple shell script to setup the PetaLinux, Vitis & Vivado 2021.2 tool paths.
    steve@Desktop:~/projects/common$ subl other/src/script/xilinx_2021_2.sh
    

    xilinx_2021_2.sh

    #!/bin/bash
    
    # Setup Vitis, Vivado, Vitis HLS & DocNav environment
    source /opt/Xilinx/Vivado/2021.2/settings64.sh
    # Setup PetaLinux environment
    source /opt/Xilinx/PetaLinux/2021.2/tool/settings.sh
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/other/src/script/xilinx_2021_2.sh -O other/src/script/xilinx_2021_2.sh
    
    If multiple versions of the tools are required then having a more comprehensive shell script that detects and allows the selection of specific tool versions can be very useful. Create this script as shown below.
    steve@Desktop:~/projects/common$ subl other/src/script/xilinx.sh
    

    xilinx.sh

    #!/bin/bash
    
    #
    # File .......... xilinx.sh
    # Author ........ Steve Haywood
    # Version ....... 1.0
    # Date .......... 8 February 2021
    # Description ...
    #   Determine and list which Xilinx tools are available and let the user select
    # the require ones to use. Does not reverse any previously selected tools upon
    # selecting news ones so to is cleaner to use in a new Terminal session.
    #
    
    # Define install base location
    dir_base="/opt/Xilinx"
    #dir_base="/mnt/Xilinx"
    
    # Define number of tools (Vivado, SDK, Vitis & PetaLinux)
    tools=4
    
    # Define tool directories, executables & settings scripts
    dir_tool=("Vivado" "SDK" "Vitis" "PetaLinux")
    exe_tool=("vivado" "xsdk" "vitis" "petalinux-build")
    set_tool=("settings64.sh" "settings64.sh" "settings64.sh" "tool/settings.sh")
    
    
    
    
    
    
    
    # MY OVERRIDE
    #dir_base="/media/secondary/Xilinx"
    #set_tool=("settings64.sh" "settings64.sh" "settings64.sh" "settings.sh")
    
    
    
    
    
    
    
    # Define terminal colours
    col_default=$(tput sgr0)
    col_red=$(tput setaf 1)
    col_green=$(tput setaf 2)
    col_blue=$(tput setaf 4)
    col_fail_pass=(${col_red} ${col_green})
    
    # Exit if script wasn't sourced
    if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
      printf "Script needs to be sourced : source ${BASH_SOURCE[0]}\n"
      exit 1
    fi
    
    # Get array of directories at base location
    readarray -t dirs < <(find "${dir_base}/${dir_tool[0]}" -mindepth 1 -maxdepth 1 -printf '%P\n')
    
    # Sort directories array
    dirs=($(IFS=$'\n'; echo "${dirs[*]}" | sort))
    
    # Determine and list what tools are installed
    declare -A table
    printf "Xilinx tools available tools at ${dir_base} :-\n"
    for ((dir=1; dir<=${#dirs[@]}; dir++)); do
      printf "${dir}) ${dirs[$((dir-1))]}"
      for ((tool=0; tool<${tools}; tool++)); do
        table[${dir}, ${tool}]=$([ ! -d "${dir_base}/${dir_tool[${tool}]}/${dirs[$((dir-1))]}" ]; echo $?)
        printf "${col_default} - "
        printf "${col_fail_pass[${table[${dir}, ${tool}]}]}"
        printf "${dir_tool[${tool}]}"
        printf "${col_default}"
      done
      printf "\n"
    done
    printf "0) Exit\n"
    printf "Please select tools required or exit"
    
    # Obtain user input and source settings for selected tools
    while true; do
      read -p " : " sel
      if ! [[ "${sel}" =~ ^[0-9]+$ ]] ; then
        # User input is not a number
        printf "Invalid choice, select again"
      elif [ ${sel} -ge 1 ] && [ ${sel} -le ${#dirs[@]} ]; then
        # User input is out of range
        printf "\nTools are as follows :-\n" "${sel}"
        for ((tool=0; tool<${tools}; tool++)); do
          if [ ${table[${sel}, ${tool}]} -eq 1 ]; then
            source "${dir_base}/${dir_tool[${tool}]}/${dirs[$((sel - 1))]}/${set_tool[${tool}]}" > /dev/null 2>&1
            printf "${col_blue}${exe_tool[${tool}]}${col_default} @ "
            bin=$(which "${exe_tool[${tool}]}")
            if [ -z ${bin} ]; then
              printf "${col_red}Not found!"
            else
              printf "${col_green}%s" "${bin}"
            fi
            printf "${col_default}\n"
          fi
        done
        break
      elif [ ${sel} -eq 0 ]; then
        printf "Quiting without selection!\n"
        break
      else
        printf "Invalid choice, select again"
      fi
    done
    
    Direct download available here :-
    steve@Desktop:~/projects/common$ wget https://spacewire.co.uk/tutorial/shared/repos/0001/common/other/src/script/xilinx.sh -O other/src/script/xilinx.sh
    
    Set execute permission on the shell scripts.
    steve@Desktop:~/projects/common$ chmod +x other/src/script/xilinx_2021_2.sh
    steve@Desktop:~/projects/common$ chmod +x other/src/script/xilinx.sh
    
    Execution of the above latter script will yield something similar to what is shown below.
    steve@Desktop:~/projects/common$ source ~/projects/common/other/src/script/xilinx.sh
    Xilinx tools available tools at /opt/Xilinx :-
    1) 2013.4 - Vivado - SDK - Vitis - PetaLinux
    2) 2015.2 - Vivado - SDK - Vitis - PetaLinux
    3) 2019.1 - Vivado - SDK - Vitis - PetaLinux
    4) 2020.2 - Vivado - SDK - Vitis - PetaLinux
    5) 2021.2 - Vivado - SDK - Vitis - PetaLinux
    0) Exit
    Please select tools required or exit : 5
    
    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
    

    11. Setup shell initialization script

    Make life easier by adding useful aliases and search paths within the shell initialization script.
    steve@Desktop:~/projects/common$ cd ~
    steve@Desktop:~$ subl ~/.bashrc
    

    .bashrc (partial)

    1. # Aliases
    2. alias xilinx='source xilinx.sh'
    3. alias minized='minicom -D /dev/ttyACM0 -b 115200'

    4. # Paths
    5. PATH="~/projects/common/fw/src/script:"$PATH
    6. PATH="~/projects/common/other/src/script:"$PATH
    7. PATH="~/projects/common/sw/src/script:"$PATH
    #### Part 3 - Setup revision control environment ####

    12. Setup revision control tools & environment

    If GIT provision are not already in place then a GIT server can easily be established. The example below shows the setup for a remote Linux Server (Ubuntu Server 20.04 LTS) and a local Linux Desktop (Xubuntu Desktop 20.04 LTS). The Server will be used to host the repositories and the Desktop used to access them.

    Open up two terminals, one for the Desktop and one for the Server.

    Create a new user on the Server called git and create the SSH directory structure.
    steve@Desktop:~$ ssh 192.168.2.20
    steve@Server:~$ sudo useradd -r -m -U -d /home/git -s /bin/bash git
    steve@Server:~$ sudo su - git
    git@Server:~$ mkdir .ssh
    git@Server:~$ chmod 0700 .ssh
    git@Server:~$ touch .ssh/authorized_keys
    git@Server:~$ chmod 0600 .ssh/authorized_keys
    
    Check for the existence of a SSH key pair on the Desktop.
    steve@Desktop:~$ cat .ssh/id_rsa.pub
    
    If the return from the above is No such file or directory then create a SSH key pair on the Desktop. Press enter at the key location prompt to use the suggested location. Enter a password at the passphase prompt and confirm this at the next passphase prompt.
    steve@Desktop:~$ ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/steve/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    The key fingerprint is:
    SHA256:0l/Upmt2lqfE81I72v5Zm5/mOR3L8/2Mr5Wjwi805Pg steve@Desktop
    The key's randomart image is:
    +---[RSA 4096]----+
    |                 |
    |             .   |
    |            . o  |
    |       .   o o   |
    |      . S + o    |
    |       . o = o oo|
    |          = = O+O|
    |           E ++^@|
    |            ++O&^|
    +----[SHA256]-----+
    
    Copy the already existing or newly generated Public Key to the Server.
    steve@Desktop:~$ scp ~/.ssh/id_rsa.pub steve@192.168.2.20:/home/steve
    
    Add the copied Public Key to the Authorized Keys on the Server and then delete the copied Public Key.
    git@Server:~$ cat /home/steve/id_rsa.pub >> .ssh/authorized_keys
    git@Server:~$ sudo rm /home/steve/id_rsa.pub
    
    Perform a quick check to ensure that everything is working as expected.

    Create an example repository on the Server.
    git@Server:~$ git init --bare example.git
    
    Setup GIT credentials on the Desktop.
    steve@Desktop:~$ git config --global user.email your@email_address
    steve@Desktop:~$ git config --global user.name "Your Name"
    
    Clone the example repository on the Desktop, add a new file, commit the changes to the staging area and then push the changes back to the Server. Check status throughout.
    steve@Desktop:~$ cd /tmp
    steve@Desktop:/tmp$ git clone git@192.168.2.20:example.git
    Cloning into 'example'...
    warning: You appear to have cloned an empty repository.
    steve@Desktop:/tmp$ cd example
    steve@Desktop:/tmp/example$ git status
    On branch master
    
    No commits yet
    
    nothing to commit (create/copy files and use "git add" to track)
    steve@Desktop:/tmp/example$ echo "Some wise words required..." > readme.txt
    steve@Desktop:/tmp/example$ git status
    On branch master
    
    No commits yet
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
      readme.txt
    
    nothing added to commit but untracked files present (use "git add" to track)
    steve@Desktop:/tmp/example$ git add readme.txt
    steve@Desktop:/tmp/example$ git status
    On branch master
    
    No commits yet
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
      new file:   readme.txt
    steve@Desktop:/tmp/example$ git commit -a -m "Added readme file, alas no wise words yet!"
    [master (root-commit) cac7986] Added readme file, alas no wise words yet!
     1 file changed, 1 insertion(+)
     create mode 100644 readme.txt
    steve@Desktop:/tmp/example$ git status
    On branch master
    Your branch is based on 'origin/master', but the upstream is gone.
      (use "git branch --unset-upstream" to fixup)
    
    nothing to commit, working tree clean
    steve@Desktop:/tmp/example$ git push
    Enumerating objects: 3, done.
    Counting objects: 100% (3/3), done.
    Writing objects: 100% (3/3), 258 bytes | 258.00 KiB/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To 192.168.2.20:example.git
     * [new branch]      master -> master
    steve@Desktop:/tmp/example$ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    
    nothing to commit, working tree clean
    
    Clone the repository again, this time into a named directory. Check the new file does indeed exist.
    steve@Desktop:/tmp/example$ cd ..
    steve@Desktop:/tmp$ git clone git@192.168.2.20:example.git example_check
    Cloning into 'example_check'...
    remote: Enumerating objects: 3, done.
    remote: Counting objects: 100% (3/3), done.
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Receiving objects: 100% (3/3), done.
    steve@Desktop:/tmp$ cd example_check
    steve@Desktop:/tmp/example_check$ cat readme.txt
    Some wise words required...
    steve@Desktop:/tmp/example_check$ git log
    commit cac798667af67d2ed245672cb36a786f0c3208ed (HEAD -> master, origin/master, origin/HEAD)
    Author: Steve <steve@Desktop>
    Date:   Thu Dec 30 12:24:54 2021 +0000
    
        Added readme file, alas no wise words yet!
    
    #### Part 3 - Perform housekeeping ####

    13. Cleanup downloads

    Delete the unzipped installer directory and either delete or archive the installer tarball. Delete the constraints archive.
    steve@Desktop:/tmp/example_check$ cd ~
    steve@Desktop:~$ rm -r ~/Downloads/Xilinx_Unified_2021.2_1021_0703
    steve@Desktop:~$ # rm ~/Downloads/Xilinx_Unified_2021.1_0610_2318.tar.gz
    steve@Desktop:~$ rm ~/Downloads/zedboard_master_XDC_RevC_D_v3.zip
    

    14. Remove startup programs

    Remove the Xilinx Information Center from the list of autostart application by going to Xubuntu's Whisper Menu and navigating to Settings » Session and Startup. Click on the Application Autostart tab within the Session and Startup window, untick Xilinx Information Center and then click Close.
    #### Part 2 - Revision Control ####

    15. Create repository & commit files

    Create a new remote repository, create a new local repository and link them together.
    steve@Desktop:~$ ssh -t git@192.168.2.20 'git init --bare common.git'
    steve@Desktop:~$ cd ~/projects/common
    steve@Desktop:~/projects/common$ git init
    steve@Desktop:~/projects/common$ git remote add origin git@192.168.2.20:common.git
    
    Check the GIT status to make sure all is well and there are no spurious elements.
    steve@Desktop:~/projects/common$ git status -u
    On branch master
    
    No commits yet
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            fw/src/constraint/zedboard_master_XDC_RevC_D_v3.xdc      
            fw/src/script/create_vivado_project.sh      
            fw/src/script/create_vivado_project.tcl      
            other/src/script/create_project_structure.sh      
            other/src/script/xilinx.sh      
            other/src/script/xilinx_2021_2.sh      
            sw/src/script/create_vitis_project.sh      
            sw/src/script/create_vitis_project.tcl      
    
    nothing added to commit but untracked files present (use "git add" to track)
    
    Looks good!

    Add the new files, commit the changes and push them up to the remote repository.
    steve@Desktop:~/projects/common$ git add -A
    steve@Desktop:~/projects/common$ git commit -a -m "Initial commit of common files."
    steve@Desktop:~/projects/common$ git push -u origin master
    
    Create an annotated tag and push it up to the remote repository.
    steve@Desktop:~/projects/common$ git tag -a v1.0 -m "Common files"
    steve@Desktop:~/projects/common$ git push origin v1.0
    
    #### Part 6 - Quickstart ####

    16. Obtain tutorial files from Bitbucket for the common project

    The tutorial files can be obtained from Bitbucket for the common project.

    If the common project is not already present, clone it from the repository.
    steve@Desktop:~$ cd ~/projects
    steve@Desktop:~/projects$ git clone https://bitbucket.org/spacewire_firmware/common
    
    If the common project is present, update it to the latest version.
    steve@Desktop:~$ cd ~/projects/common
    steve@Desktop:~/projects/common$ git pull