Bar
SpaceWire UK
Specialist providers of VHDL Intellectual Property & Design Services
BarBarBarBar
Tutorial
Missing Image!
Part 24 - Create a cascading Video TPG design for HDMI output

Introduction

This tutorial details the steps required to create an overlaying video TPG design using Vivado. The video output will be delivered via the HDMI port on the Zedboard. The tutorial covers quite a range of activities and includes the use of numerous languages; TCL, Verilog, System Verilog & shell scripting. TCL will be used extensively to add elements to an existing Block Design and wire them up.

Note: Everywhere there is a text edit command (subl) there will be a wget below it to fast track the process.

Aims

The aims of this tutorial are as follows :-

    Part 1 - Setup environment

    1. Pre-requisites

    Part 2 - Firmware Development - 1

    1. Create a new firmware project
    2. Open block design
    3. Add video logic to block design
    4. Edit product identification
    5. Edit HDL wrapper
    6. Edit pin constraints

    Part 3 - Revision Control

    1. Commit new & updated files

    Part 4 - Firmware Development - 2

    1. Create production release
    2. Archive build files for later retrieval

    Part 5 - OS Development

    1. Bump version
    2. Update hardware platform
    3. Enable i2c Tools
    4. Create auto-run application

    Part 6 - Revision Control

    1. Commit new & updated files
    2. Create production release

    Part 7 - Hardware Deployment

    1. Copy files to SD Card

    Part 8 - Check everything is working as expected

    1. OS boot & Firmware load
    2. Firmware register setup & TPG operation
    #### Part 1 - Setup environment ####

    1. Pre-requisites

    Starting from this point is possible but requires a few pre-requisites.
    #### Part 2 - Firmware Development - 1 ####

    2. Create a new firmware project

    Create a brand new baseline project that can be expanded upon to include the new features required.
    steve@Desktop:~$ cd ${swuk_tutorial}
    steve@Desktop:~/swuk_tutorial$ swuk_create_project zedboard_video_tpg_hdmi --baseline
    Enter details for the header blocks...
    File .......... zedboard_video_tpg_hdmi
    Author ........ Steve Haywood
    Company ....... SpaceWire UK
    Website ....... http://www.spacewire.co.uk
    Project ....... Zedboard Video TPG HDMI
    Tutorial ...... SpaceWire UK Tutorial
    Date .......... 9 Feb 2026
    Version ....... 1.0
    Creating project directory structure...
    Creating baseline project...
    steve@Desktop:~/swuk_tutorial$ cd zedboard_video_tpg_hdmi
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ swuk_create_vivado_project
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ cd ..
    

    3. Open block design

    Take a peek at the baseline block design by clicking on Open Block Design under IP INTEGRATOR. Get a better view of the Block Design by clicking on its Float Missing Image! icon. 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!

    4. Add video logic to block design

    Instead of poking around on the Block Design a TCL script will be used to make the changes required. The commands used in the script are simply the ones Vivado displays in the Tcl Console when things are changed in the GUI.

    If it is more desirable to edit the Block Design manually then use the comments in the script to assist with the process.

    Changes required to existing IP & RTL blocks :- Additional IP & RTL blocks required :- Create the update script.

    steve@Desktop:~/swuk_tutorial$ subl zedboard_video_tpg_hdmi/fw/src/script/user_update_system_bd.tcl
    

    user_update_system_bd.tcl

    #
    # File .......... user_update_system_bd.tcl
    # Author ........ Steve Haywood
    # Website ....... http://www.spacewire.co.uk
    # Project ....... Zedboard Video TPG HDMI (SpaceWire UK Tutorial)
    # Date .......... 20 Dec 2025
    # Version ....... 1.0
    # Description ...
    #   Add & connect up extra blocks on the baseline top-level block design for
    # the Zedboard. This script adds the required elements to create a cascading
    # video test pattern generator example design with HDMI output.
    #
    
    
    #############################################################################
    # Set block design path
    
    set dir_user        "../src"
    set dir_diagram     "$dir_user/diagram"
    
    
    #############################################################################
    # Get block design name from script filename (xxx_xxx_yyy_xxx.tcl = yyy)
    
    set whoami [file normalize [info script]]
    set fbasename [file rootname [file tail $whoami]]
    set parts [split $fbasename "_"]
    set bdname [lindex $parts 2]
    
    
    ###################
    # Open block design
    
    open_bd_design project.srcs/sources_1/bd/$bdname/$bdname.bd
    
    
    #######################################
    # Adjust existing common design to suit
    
    # - Constant
    #   - Remove from BD
    
    delete_bd_objs [get_bd_nets xlconstant_0_dout] [get_bd_cells xlconstant_0]
    
    # - AXI GPIO ZED
    #   - Set 'C Leds Mask' to "11000000"
    
    set_property CONFIG.c_leds_mask {"11000000"} [get_bd_cells axi_gpio_zed_0]
    
    # - AXI Interconnect
    #   - Set 'Number of Master Interfaces' to 7
    
    set_property CONFIG.NUM_MI {7} [get_bd_cells axi_interconnect_0]
    
    # - ZYNQ7 Processing System
    #   - Peripheral I/O Pins
    #     - Peripherals
    #       - Enable 'I2C 0'
    #   - Clock Configuration
    #     - PL Fabric Clocks
    #       - Set 'FCLK_CLK0' to 162 MHz
    
    set_property CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {162.000000} [get_bd_cells processing_system7_0]
    set_property -dict [list \
      CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {1} \
      CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \
    ] [get_bd_cells processing_system7_0]
    
    
    ###################################
    # Create instances & set properties
    
    # - Clocking Wizard
    #   - Clocking Options
    #     - Enable 'Dynamic Reconfig'
    #     - Set 'Dynamic Reconfig Interface' to AXI4Lite (default)
    #   - Output Clocks
    #     - Set 'clk_out1' frequency to 148.5 MHz
    #   - MMCM Settings
    #     - Enable 'Allow Override Mode'
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0
    set_property -dict [list \
      CONFIG.CLKOUT1_JITTER {217.614} \
      CONFIG.CLKOUT1_PHASE_ERROR {245.344} \
      CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {148.5} \
      CONFIG.MMCM_CLKFBOUT_MULT_F {37.125} \
      CONFIG.MMCM_CLKOUT0_DIVIDE_F {6.250} \
      CONFIG.MMCM_DIVCLK_DIVIDE {4} \
      CONFIG.OVERRIDE_MMCM {true} \
      CONFIG.USE_DYN_RECONFIG {true} \
    ] [get_bd_cells clk_wiz_0]
    
    # - Video Test Pattern Generator 0
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:v_tpg:8.2 v_tpg_0
    
    # - Video Test Pattern Generator 1
    #   - Enable 'HAS AXI4S SLAVE'
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:v_tpg:8.2 v_tpg_1
    set_property CONFIG.HAS_AXI4S_SLAVE {1} [get_bd_cells v_tpg_1]
    
    # - AXI4-Stream Subset Converter
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:axis_subset_converter:1.1 axis_subset_converter_0
    
    # - Video Timing Controller
    #   - Detection/Generation
    #     - Disable 'Enable Detection'
    #   - Default/Constant
    #     - Set 'Video Mode' to 1080p
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:v_tc:6.2 v_tc_0
    set_property -dict [list \
      CONFIG.VIDEO_MODE {1080p} \
      CONFIG.enable_detection {false} \
    ] [get_bd_cells v_tc_0]
    
    # - AXI4-Stream to Video Out
    #   - Section: 'Pixels Per Clock'
    #     - Set 'Video Format' to 'Manual' & 'YUV 4:2:2'
    #   - Section 'Clock Mode'
    #     - Set 'Independent'
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:v_axi4s_vid_out:4.0 v_axi4s_vid_out_0
    set_property -dict [list \
      CONFIG.C_HAS_ASYNC_CLK {1} \
      CONFIG.C_S_AXIS_VIDEO_FORMAT {0} \
    ] [get_bd_cells v_axi4s_vid_out_0]
    
    # - Concat
    #   - Set 'Number of Ports' to 8
    
    create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0
    set_property CONFIG.NUM_PORTS {8} [get_bd_cells xlconcat_0]
    
    # - Heartbeat
    #   - Set 'C Clk Freq' to 148500000
    
    create_bd_cell -type module -reference heartbeat heartbeat_0
    set_property CONFIG.c_clk_freq {148500000} [get_bd_cells heartbeat_0]
    
    
    ##############################
    # Create interface connections
    
    make_bd_intf_pins_external  [get_bd_intf_pins processing_system7_0/IIC_0]
    set_property name IIC_0 [get_bd_intf_ports IIC_0_0]
    
    connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M03_AXI] [get_bd_intf_pins v_tpg_0/s_axi_CTRL]
    connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M04_AXI] [get_bd_intf_pins v_tpg_1/s_axi_CTRL]
    connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M05_AXI] [get_bd_intf_pins v_tc_0/ctrl]
    connect_bd_intf_net -boundary_type upper [get_bd_intf_pins axi_interconnect_0/M06_AXI] [get_bd_intf_pins clk_wiz_0/s_axi_lite]
    
    connect_bd_intf_net [get_bd_intf_pins v_tpg_0/m_axis_video] [get_bd_intf_pins v_tpg_1/s_axis_video]
    connect_bd_intf_net [get_bd_intf_pins v_tpg_1/m_axis_video] [get_bd_intf_pins axis_subset_converter_0/S_AXIS]
    connect_bd_intf_net [get_bd_intf_pins axis_subset_converter_0/M_AXIS] [get_bd_intf_pins v_axi4s_vid_out_0/video_in]
    connect_bd_intf_net [get_bd_intf_pins v_tc_0/vtiming_out] [get_bd_intf_pins v_axi4s_vid_out_0/vtiming_in]
    
    
    #########################
    # Create port connections
    
    make_bd_pins_external  [get_bd_pins clk_wiz_0/clk_in1]
    set_property name sys_clock [get_bd_ports clk_in1_0]
    
    make_bd_pins_external [get_bd_pins clk_wiz_0/clk_out1]
    set_property name vid_clk [get_bd_ports clk_out1_0]
    
    make_bd_pins_external \
      [get_bd_pins v_axi4s_vid_out_0/vid_active_video] \
      [get_bd_pins v_axi4s_vid_out_0/vid_data] \
      [get_bd_pins v_axi4s_vid_out_0/vid_hsync] \
      [get_bd_pins v_axi4s_vid_out_0/vid_vsync]
    set_property name vid_active_video [get_bd_ports vid_active_video_0]
    set_property name vid_hsync [get_bd_ports vid_hsync_0]
    set_property name vid_vsync [get_bd_ports vid_vsync_0]
    set_property name vid_data [get_bd_ports vid_data_0]
    
    connect_bd_net [get_bd_pins heartbeat_0/beat] [get_bd_pins xlconcat_0/In6]
    connect_bd_net [get_bd_pins v_axi4s_vid_out_0/locked] [get_bd_pins xlconcat_0/In7]
    connect_bd_net [get_bd_pins xlconcat_0/dout] [get_bd_pins axi_gpio_zed_0/leds_in]
    
    connect_bd_net [get_bd_pins processing_system7_0/FCLK_CLK0] \
      [get_bd_pins axi_interconnect_0/M03_ACLK] \
      [get_bd_pins axi_interconnect_0/M04_ACLK] \
      [get_bd_pins axi_interconnect_0/M05_ACLK] \
      [get_bd_pins axi_interconnect_0/M06_ACLK] \
      [get_bd_pins axis_subset_converter_0/aclk] \
      [get_bd_pins clk_wiz_0/s_axi_aclk] \
      [get_bd_pins v_axi4s_vid_out_0/aclk] \
      [get_bd_pins v_tc_0/s_axi_aclk] \
      [get_bd_pins v_tpg_0/ap_clk] \
      [get_bd_pins v_tpg_1/ap_clk]
    
    connect_bd_net [get_bd_pins proc_sys_reset_0/peripheral_aresetn] \
      [get_bd_pins axi_interconnect_0/M03_ARESETN] \
      [get_bd_pins axi_interconnect_0/M04_ARESETN] \
      [get_bd_pins axi_interconnect_0/M05_ARESETN] \
      [get_bd_pins axi_interconnect_0/M06_ARESETN] \
      [get_bd_pins axis_subset_converter_0/aresetn] \
      [get_bd_pins clk_wiz_0/s_axi_aresetn] \
      [get_bd_pins v_axi4s_vid_out_0/aresetn] \
      [get_bd_pins v_tc_0/s_axi_aresetn] \
      [get_bd_pins v_tpg_0/ap_rst_n] \
      [get_bd_pins v_tpg_1/ap_rst_n]
    
    connect_bd_net [get_bd_pins clk_wiz_0/clk_out1] \
      [get_bd_pins heartbeat_0/aclk] \
      [get_bd_pins v_axi4s_vid_out_0/vid_io_out_clk] \
      [get_bd_pins v_tc_0/clk]
    
    connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins heartbeat_0/aresetn]
    
    connect_bd_net [get_bd_pins v_axi4s_vid_out_0/vtg_ce] [get_bd_pins v_tc_0/gen_clken]
    
    
    #########################
    # Create address segments
    
    assign_bd_address -offset 0x40030000 -range 0x00010000 -target_address_space [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs v_tpg_0/s_axi_CTRL/Reg] -force
    assign_bd_address -offset 0x40040000 -range 0x00010000 -target_address_space [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs v_tpg_1/s_axi_CTRL/Reg] -force
    assign_bd_address -offset 0x40050000 -range 0x00010000 -target_address_space [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs v_tc_0/ctrl/Reg] -force
    assign_bd_address -offset 0x40060000 -range 0x00010000 -target_address_space [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs clk_wiz_0/s_axi_lite/Reg] -force
    
    
    #################################################
    # Regenerate, validate, save & close block design
    
    #regenerate_bd_layout
    validate_bd_design
    save_bd_design
    #close_bd_design $bdname
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0030/zedboard_video_tpg_hdmi/fw/src/script/user_update_system_bd.tcl -O zedboard_video_tpg_hdmi/fw/src/script/user_update_system_bd.tcl
    
    Run the script from the Tcl Console.
    source ../src/script/user_update_system_bd.tcl
    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.

    Behold the cascading video test pattern example design. Missing Image!

    5. Edit product identification

    Edit the product identification file.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_video_tpg_hdmi/fw/project.txt
    

    project.txt

    Zedboard Video TPG HDMI
    SpaceWire UK
    Steve Haywood
    1.0
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0030/zedboard_video_tpg_hdmi/fw/project.txt -O zedboard_video_tpg_hdmi/fw/project.txt
    

    6. Edit HDL wrapper

    Edit the top-level wrapper for the block design to add the Board Clock, I2C & HDMI Video connections.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_video_tpg_hdmi/fw/src/design/zedboard_video_tpg_hdmi.sv
    

    zedboard_video_tpg_hdmi.sv

    //
    // File .......... zedboard_video_tpg_hdmi.sv
    // Author ........ Steve Haywood
    // Website ....... http://www.spacewire.co.uk
    // Project ....... Zedboard Video TPG HDMI (SpaceWire UK Tutorial)
    // Date .......... 20 Dec 2025
    // Version ....... 1.0
    // Description ...
    //   Top level wrapper for the system block design.
    //
    
    
    timeunit      1ns;
    timeprecision 1ps;
    
    
    module zedboard_video_tpg_hdmi #
    (
      // Parameters
      parameter string id_description = "",  // P:Description ............ Max 128 Characters
      parameter string id_company     = "",  // P:Company ................ Max  64 Characters
      parameter string id_author      = "",  // P:Author ................. Max  64 Characters
      parameter string id_version     = "",  // P:Version ................ Max  32 Characters
      parameter string id_timestamp   = "",  // P:Timestamp .............. Max  32 Characters
      parameter string id_hash        = ""   // P:Hash ................... Max  64 Characters
    )
    (
      // Board Clock (100MHz)
      input         sys_clock,          // I:Clock
      // LEDs
      output [ 7:0] leds,               // O:LEDs
      // DIP Switches
      input  [ 7:0] switches,           // I:DIP Switches
      // Push Buttons
      input  [ 4:0] buttons,            // I:Push Buttons
      // HDMI
      output        vid_clk,            // O:Clock
      output        vid_active_video,   // O:Active
      output [15:0] vid_data,           // O:Data
      output        vid_hsync,          // O:Horizontal Sync
      output        vid_vsync,          // O:Vertical Sync
      // I2C (PS -> ADV7511)
      inout         vid_i2c_scl,        // B:Clock
      inout         vid_i2c_sda,        // B:Data
      // System
      inout  [14:0] DDR_addr,           // B:Address
      inout  [ 2:0] DDR_ba,             // B:Bank Address
      inout         DDR_cas_n,          // B:Column Address Select
      inout         DDR_ck_n,           // B:Clock (Neg)
      inout         DDR_ck_p,           // B:Clock (Pos)
      inout         DDR_cke,            // B:Clock Enable
      inout         DDR_cs_n,           // B:Chip Select
      inout  [ 3:0] DDR_dm,             // B:Data Mask
      inout  [31:0] DDR_dq,             // B:Data Input/Output
      inout  [ 3:0] DDR_dqs_n,          // B:Data Strobe (Neg)
      inout  [ 3:0] DDR_dqs_p,          // B:Data Strobe (Pos)
      inout         DDR_odt,            // B:Output Dynamic Termination
      inout         DDR_ras_n,          // B:Row Address Select
      inout         DDR_reset_n,        // B:Reset
      inout         DDR_we_n,           // B:Write Enable
      inout         FIXED_IO_ddr_vrn,   // B:Termination Voltage
      inout         FIXED_IO_ddr_vrp,   // B:Termination Voltage
      inout  [53:0] FIXED_IO_mio,       // B:Peripheral Input/Output
      inout         FIXED_IO_ps_clk,    // B:System Reference Clock
      inout         FIXED_IO_ps_porb,   // B:Power On Reset
      inout         FIXED_IO_ps_srstb   // B:External System Reset
    );
    
    
      // Function to convert a string to a vector (max 128 characters)
      function automatic [1023:0] fmt(input string str);
        int len;
        bit [1023:0] tmp;
        len = str.len();
        for (int i=0; i<len; i++)
          tmp[8*i +: 8] = str.getc(i);
        fmt = tmp;
      endfunction
    
    
      // Top-Level Block Design
      system system_i
       (
        // Identification Strings
        .id_description    ( fmt(id_description) ),  // P:Description
        .id_company        ( fmt(id_company)     ),  // P:Company
        .id_author         ( fmt(id_author)      ),  // P:Author
        .id_version        ( fmt(id_version)     ),  // P:Version
        .id_timestamp      ( fmt(id_timestamp)   ),  // P:Timestamp
        .id_hash           ( fmt(id_hash)        ),  // P:Hash
        // Board Clock
        .sys_clock         ( sys_clock           ),  // I:Clock
        // LEDs
        .leds              ( leds                ),  // O:LEDs
        // DIP Switches
        .switches          ( switches            ),  // I:DIP Switches
        // Push Buttons
        .buttons           ( buttons             ),  // I:Push Buttons
        // HDMI
        .vid_active_video  ( vid_active_video    ),  // O:Clock
        .vid_clk           ( vid_clk             ),  // O:Active
        .vid_data          ( vid_data            ),  // O:Data
        .vid_hsync         ( vid_hsync           ),  // O:Horizontal Sync
        .vid_vsync         ( vid_vsync           ),  // O:Vertical Sync
        // I2C (PS -> ADV7511)
        .IIC_0_scl_i       ( IIC_0_scl_i         ),  // I:Clock Input
        .IIC_0_scl_o       ( IIC_0_scl_o         ),  // O:Clock Output
        .IIC_0_scl_t       ( IIC_0_scl_t         ),  // O:Clock Tri-state
        .IIC_0_sda_i       ( IIC_0_sda_i         ),  // I:Data Input
        .IIC_0_sda_o       ( IIC_0_sda_o         ),  // O:Data Output
        .IIC_0_sda_t       ( IIC_0_sda_t         ),  // O:Data Tri-state
        // System
        .DDR_addr          ( DDR_addr            ),  // B:Address
        .DDR_ba            ( DDR_ba              ),  // B:Bank Address
        .DDR_cas_n         ( DDR_cas_n           ),  // B:Column Address Select
        .DDR_ck_n          ( DDR_ck_n            ),  // B:Clock (Neg)
        .DDR_ck_p          ( DDR_ck_p            ),  // B:Clock (Pos)
        .DDR_cke           ( DDR_cke             ),  // B:Clock Enable
        .DDR_cs_n          ( DDR_cs_n            ),  // B:Chip Select
        .DDR_dm            ( DDR_dm              ),  // B:Data Mask
        .DDR_dq            ( DDR_dq              ),  // B:Data Input/Output
        .DDR_dqs_n         ( DDR_dqs_n           ),  // B:Data Strobe (Neg)
        .DDR_dqs_p         ( DDR_dqs_p           ),  // B:Data Strobe (Pos)
        .DDR_odt           ( DDR_odt             ),  // B:Output Dynamic Termination
        .DDR_ras_n         ( DDR_ras_n           ),  // B:Row Address Select
        .DDR_reset_n       ( DDR_reset_n         ),  // B:Reset
        .DDR_we_n          ( DDR_we_n            ),  // B:Write Enable
        .FIXED_IO_ddr_vrn  ( FIXED_IO_ddr_vrn    ),  // B:Termination Voltage
        .FIXED_IO_ddr_vrp  ( FIXED_IO_ddr_vrp    ),  // B:Termination Voltage
        .FIXED_IO_mio      ( FIXED_IO_mio        ),  // B:Peripheral Input/Output
        .FIXED_IO_ps_clk   ( FIXED_IO_ps_clk     ),  // B:System Reference Clock
        .FIXED_IO_ps_porb  ( FIXED_IO_ps_porb    ),  // B:Power On Reset
        .FIXED_IO_ps_srstb ( FIXED_IO_ps_srstb   )   // B:External System Reset
       );
    
    
      // Tri-State Buffer (I2C Clock)
      IOBUF IIC_0_0_scl_iobuf
       (
        .I  ( IIC_0_scl_o   ),  // I:Input
        .O  ( IIC_0_scl_i   ),  // O:Output
        .T  ( IIC_0_scl_t   ),  // I:Tri-State
        .IO ( vid_i2c_scl   )   // B:Result
       );
    
    
      // Tri-State Buffer (I2C Data)
      IOBUF IIC_0_0_sda_iobuf
       (
        .I  ( IIC_0_sda_o   ),  // I:Input
        .O  ( IIC_0_sda_i   ),  // O:Output
        .T  ( IIC_0_sda_t   ),  // I:Tri-State
        .IO ( vid_i2c_sda   )   // B:Result
       );
    
    
    endmodule
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0030/zedboard_video_tpg_hdmi/fw/src/design/zedboard_video_tpg_hdmi.sv -O zedboard_video_tpg_hdmi/fw/src/design/zedboard_video_tpg_hdmi.sv
    

    7. Edit pin constraints

    Edit the pin constraints to add the Board Clock, I2C & HDMI Video connections.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_video_tpg_hdmi/fw/src/constraint/zedboard_video_tpg_hdmi.xdc
    

    zedboard_video_tpg_hdmi.xdc

    #
    # File .......... zedboard_video_tpg_hdmi.xdc
    # Author ........ Steve Haywood
    # Website ....... http://www.spacewire.co.uk
    # Project ....... Zedboard Video TPG HDMI (SpaceWire UK Tutorial)
    # Date .......... 20 Dec 2025
    # Version ....... 1.0
    # Description ...
    #   Top level pin & timing constraints.
    #
    
    
    # Clock Source - Bank 13
    set_property PACKAGE_PIN Y9 [get_ports {sys_clock}];  # "GCLK"
    
    
    # User LEDs - Bank 33
    set_property PACKAGE_PIN T22 [get_ports {leds[0]}];  # "LD0"
    set_property PACKAGE_PIN T21 [get_ports {leds[1]}];  # "LD1"
    set_property PACKAGE_PIN U22 [get_ports {leds[2]}];  # "LD2"
    set_property PACKAGE_PIN U21 [get_ports {leds[3]}];  # "LD3"
    set_property PACKAGE_PIN V22 [get_ports {leds[4]}];  # "LD4"
    set_property PACKAGE_PIN W22 [get_ports {leds[5]}];  # "LD5"
    set_property PACKAGE_PIN U19 [get_ports {leds[6]}];  # "LD6"
    set_property PACKAGE_PIN U14 [get_ports {leds[7]}];  # "LD7"
    
    
    # HDMI Output - Bank 33
    set_property PACKAGE_PIN W18  [get_ports {vid_clk}];           # "HD-CLK"
    set_property PACKAGE_PIN Y13  [get_ports {vid_data[0]}];       # "HD-D0"
    set_property PACKAGE_PIN AA13 [get_ports {vid_data[1]}];       # "HD-D1"
    set_property PACKAGE_PIN AA14 [get_ports {vid_data[2]}];       # "HD-D2"
    set_property PACKAGE_PIN Y14  [get_ports {vid_data[3]}];       # "HD-D3"
    set_property PACKAGE_PIN AB15 [get_ports {vid_data[4]}];       # "HD-D4"
    set_property PACKAGE_PIN AB16 [get_ports {vid_data[5]}];       # "HD-D5"
    set_property PACKAGE_PIN AA16 [get_ports {vid_data[6]}];       # "HD-D6"
    set_property PACKAGE_PIN AB17 [get_ports {vid_data[7]}];       # "HD-D7"
    set_property PACKAGE_PIN AA17 [get_ports {vid_data[8]}];       # "HD-D8"
    set_property PACKAGE_PIN Y15  [get_ports {vid_data[9]}];       # "HD-D9"
    set_property PACKAGE_PIN W13  [get_ports {vid_data[10]}];      # "HD-D10"
    set_property PACKAGE_PIN W15  [get_ports {vid_data[11]}];      # "HD-D11"
    set_property PACKAGE_PIN V15  [get_ports {vid_data[12]}];      # "HD-D12"
    set_property PACKAGE_PIN U17  [get_ports {vid_data[13]}];      # "HD-D13"
    set_property PACKAGE_PIN V14  [get_ports {vid_data[14]}];      # "HD-D14"
    set_property PACKAGE_PIN V13  [get_ports {vid_data[15]}];      # "HD-D15"
    set_property PACKAGE_PIN U16  [get_ports {vid_active_video}];  # "HD-DE"
    set_property PACKAGE_PIN V17  [get_ports {vid_hsync}];         # "HD-HSYNC"
    set_property PACKAGE_PIN AA18 [get_ports {vid_i2c_scl}];       # "HD-SCL"
    set_property PACKAGE_PIN Y16  [get_ports {vid_i2c_sda}];       # "HD-SDA"
    set_property PACKAGE_PIN W17  [get_ports {vid_vsync}];         # "HD-VSYNC"
    
    
    # User Push Buttons - Bank 34
    set_property PACKAGE_PIN P16 [get_ports {buttons[0]}];  # "BTNC"
    set_property PACKAGE_PIN R16 [get_ports {buttons[1]}];  # "BTND"
    set_property PACKAGE_PIN N15 [get_ports {buttons[2]}];  # "BTNL"
    set_property PACKAGE_PIN R18 [get_ports {buttons[3]}];  # "BTNR"
    set_property PACKAGE_PIN T18 [get_ports {buttons[4]}];  # "BTNU"
    
    
    # User DIP Switches - Bank 34 & 35
    set_property PACKAGE_PIN F22 [get_ports {switches[0]}];  # "SW0"
    set_property PACKAGE_PIN G22 [get_ports {switches[1]}];  # "SW1"
    set_property PACKAGE_PIN H22 [get_ports {switches[2]}];  # "SW2"
    set_property PACKAGE_PIN F21 [get_ports {switches[3]}];  # "SW3"
    set_property PACKAGE_PIN H19 [get_ports {switches[4]}];  # "SW4"
    set_property PACKAGE_PIN H18 [get_ports {switches[5]}];  # "SW5"
    set_property PACKAGE_PIN H17 [get_ports {switches[6]}];  # "SW6"
    set_property PACKAGE_PIN M15 [get_ports {switches[7]}];  # "SW7"
    
    
    # Banks
    set_property IOSTANDARD LVCMOS33 [get_ports -of_objects [get_iobanks 13]];
    set_property IOSTANDARD LVCMOS33 [get_ports -of_objects [get_iobanks 33]];
    set_property IOSTANDARD LVCMOS18 [get_ports -of_objects [get_iobanks 34]];
    set_property IOSTANDARD LVCMOS18 [get_ports -of_objects [get_iobanks 35]];
    
    
    # False Paths
    set_false_path -to [get_pins {system_i/axi_gpio_zed_0/inst/leds_meta_reg[*]/D}]
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0030/zedboard_video_tpg_hdmi/fw/src/constraint/zedboard_video_tpg_hdmi.xdc -O zedboard_video_tpg_hdmi/fw/src/constraint/zedboard_video_tpg_hdmi.xdc
    
    #### Part 3 - Revision Control ####

    8. Commit new & updated files

    Check GIT status to make sure all is well and there are no spurious elements.
    steve@Desktop:~/swuk_tutorial$ git status -u
    On branch my_master
    Your branch is behind 'origin/my_master' by 2 commits, and can be fast-forwarded.
      (use "git pull" to update your local branch)
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            zedboard_video_tpg_hdmi/.gitignore      
            zedboard_video_tpg_hdmi/fw/project.txt      
            zedboard_video_tpg_hdmi/fw/src/constraint/zedboard_video_tpg_hdmi.xdc      
            zedboard_video_tpg_hdmi/fw/src/design/zedboard_video_tpg_hdmi.sv      
            zedboard_video_tpg_hdmi/fw/src/script/user_update_system_bd.tcl      
    
    nothing added to commit but untracked files present (use "git add" to track)
    
    Looks good! Commit the updates, create an annotated tag and push the commit & tag up to the remote repository.
    steve@Desktop:~/swuk_tutorial$ git add -A
    steve@Desktop:~/swuk_tutorial$ git commit -a -m "Basic Zedboard design consisting of a ZYNQ7 Processing System controlling a pair of cascading Test Pattern Generators that output video via HDMI."
    steve@Desktop:~/swuk_tutorial$ git push
    steve@Desktop:~/swuk_tutorial$ git tag -a my_zedboard_video_tpg_hdmi_v1.0 -m "ZYNQ & Cascading TPG's with HDMI output"
    steve@Desktop:~/swuk_tutorial$ git push origin my_zedboard_video_tpg_hdmi_v1.0
    
    #### Part 4 - Firmware Development - 2 ####

    9. Create production release

    Create a potential production release for the Zedboard Video TPG HDMI (v1.0) project using pure repository source.

    Close Vivado.

    Clear out all the superfluous files from the project area (non-tracked files).
    steve@Desktop:~/swuk_tutorial$ cd zedboard_video_tpg_hdmi
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ rm -rf fw/vivado
    
    Double check GIT status.
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    
    nothing to commit, working tree clean
    
    Build the design from clean repository source.
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ swuk_create_vivado_project --build
    

    10. Archive build files for later retrieval

    Archive the generated hardware platform & bitstream for safe keeping. These files are not held in the repository as they can be recreated from source.
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ cp fw/vivado/system_wrapper.xsa ${swuk_user}/hardware/zedboard_video_tpg_hdmi_v1.0.xsa
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ cp fw/vivado/zedboard_video_tpg_hdmi.runs/impl_1/zedboard_video_tpg_hdmi.bit ${swuk_user}/firmware/zedboard_video_tpg_hdmi_v1.0.bit
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ cd ..
    
    #### Part 5 - OS Development ####

    11. Bump version

    Change the version (or revision) number for this new development, this prevents ghost (post-release, same version) builds from appearing. Also remove Example Design from the Project line.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/project.txt
    

    project.txt

    Zedboard PetaLinux
    SpaceWire UK
    Steve Haywood
    15.0
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0031/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/project.txt -O zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/project.txt
    
    Check out the changes.
    steve@Desktop:~/swuk_tutorial$ git difftool zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/project.txt
    

    12. Update hardware platform

    Configure the PetaLinux project to use the exported hardware platform from the zedboard_video_tpg_hdmi Vivado project.
    steve@Desktop:~/swuk_tutorial$ cd zedboard_linux/os/petalinux
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ petalinux-config --get-hw-description ../../../zedboard_video_tpg_hdmi/fw/vivado/zedboard_video_tpg_hdmi.xsa
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ petalinux-config --get-hw-description ../../../zedboard_video_tpg_hdmi/fw/vivado/system_wrapper.xsa
    
    The configuration menu now appears.

    Select Save to save the configuration.Missing Image!Select Ok to confirm the save.Missing Image!Select Exit to continue.Missing Image!Select Exit to exit the menu.Missing Image!Check the config file (line 117) to ensure the PS i2c has been enabled.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git difftool project-spec/configs/config
    
    CONFIG_SUBSYSTEM_I2C_PS7_I2C_0_SELECT=y

    13. Enable i2c Tools

    Launch the PetaLinux configuration tool.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ petalinux-config -c rootfs
    
    Navigate the menu selecting Filesystem Packages » base » i2c-tools, enable i2c-tools and then save the configuration and exit the tool.

    Check the rootfs_config file to ensure i2c-tools has been enabled. (line 159).
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git difftool project-spec/configs/rootfs_config
    
    CONFIG_i2c-tools=y

    14. Create auto-run application

    Create a blank application component (auto enabled) to configure the ADV7511 HDMI Transmitter IC at boot time.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ petalinux-create --type apps --template install --name adv7511-config --enable
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ cd ../../..
    
    Edit the newly created auto-run application to include the ADV7511 configuration commands.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/files/adv7511-config
    

    adv7511-config

    #!/bin/sh
    
    #
    # File .......... adv7511-config
    # Author ........ Steve Haywood
    # Website ....... http://www.spacewire.co.uk
    # Project ....... Zedboard Linux (SpaceWire UK Tutorial)
    # Date .......... 22 Dec 2025
    # Version ....... 1.0
    # Description ...
    #   Script to configure the ADV7511 HDMI Transmitter IC.
    #
    
    ADV7511_I2C_ADDR=0x39    # ADV7511
    
    VTPG_IP_BASE=0x40040000  # Video Test Pattern Generator
    VTC_IP_BASE=0x40050000   # Video Timing Controller
    CW_IP_BASE=0x40030000    # Clocking Wizard
    
    # [7:4] I2S Sampling Frequency (CS bits 27-24) ... 44.1 KHz
    # [3:0] Input ID ................................. 16, 20, 24 bit YCbCr 4:2:2 (separate syncs)
    i2cset -y 0 $ADV7511_I2C_ADDR 0x15 0x01
    
    # [ 7 ] Output Format ....................... 4:4:4
    # [ 6 ] Reserved ............................ 0
    # [5:4] Color Depth ......................... 8-bit
    # [3:2] Input Style ......................... Style 1
    # [ 1 ] DDR Input Edge ...................... Falling edge
    # [ 0 ] Output Colorspace for Black Image ... RGB
    i2cset -y 0 $ADV7511_I2C_ADDR 0x16 0x38
    
    # [ 7 ] Reserved .................... 0
    # [ 6 ] Input Video Bus Reverse ..... Normal Bus Order
    # [ 5 ] DDR Alignment ............... DDR input is D[17:0]
    # [4:3] Video Input Justification ... Left justified
    # [2:0] ??? ......................... ???
    i2cset -y 0 $ADV7511_I2C_ADDR 0x48 0x08
    
    # [ 7 ] ??? ...................... ???
    # [ 6 ] Power Down ............... All circuits powered up
    # [ 5 ] Fixed .................... 0
    # [ 4 ] Reserved ................. 1
    # [3:2] Fixed .................... 00
    # [ 1 ] Sync Adjustment Enable ... Disabled
    # [ 0 ] Fixed .................... 0
    i2cset -y 0 $ADV7511_I2C_ADDR 0x41 0x10
    
    # Fixed registers that must be set on power up
    i2cset -y 0 $ADV7511_I2C_ADDR 0x98 0x03
    i2cset -y 0 $ADV7511_I2C_ADDR 0x9A 0xE0
    i2cset -y 0 $ADV7511_I2C_ADDR 0x9C 0x30
    i2cset -y 0 $ADV7511_I2C_ADDR 0x9D 0x61
    i2cset -y 0 $ADV7511_I2C_ADDR 0xA2 0xA4
    i2cset -y 0 $ADV7511_I2C_ADDR 0xA3 0xA4
    i2cset -y 0 $ADV7511_I2C_ADDR 0xE0 0xD0
    i2cset -y 0 $ADV7511_I2C_ADDR 0xF9 0x00
    
    # Color Space Conversion # CSC Enabled (YCbCr to RGB) 11100111
    # [ 7 ] (0) CSC Enable .................................................. CSC Enabled
    # [6:5] (10) CSC Scaling Factor ......................................... +/- 4.0, -16384 - 16380
    # [4:0] (00110) Color space Converter (CSC) coefficient for equations ... ?
    i2cset -y 0 $ADV7511_I2C_ADDR 0x18 0xE7
    
    # Set RGB in AVinfo Frame
    i2cset -y 0 $ADV7511_I2C_ADDR 0x55 0x00
    
    # Aspect Ration
    i2cset -y 0 $ADV7511_I2C_ADDR 0x56 0x28
    
    # HPD Control always high
    i2cset -y 0 $ADV7511_I2C_ADDR 0xD6 0xC0
    
    # DVI Mode, no HDCP
    i2cset -y 0 $ADV7511_I2C_ADDR 0xAF 0x04
    
    # Fixed I2C Address
    i2cset -y 0 $ADV7511_I2C_ADDR 0xF9 0x00
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0031/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/files/adv7511-config -O zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/files/adv7511-config
    
    Change the BitBake recipe to make it suitable for an auto-start application.
    steve@Desktop:~/swuk_tutorial$ subl zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/adv7511-config.bb
    

    adv7511-config.bb

    #
    # File .......... adv7511-config.bb
    # Author ........ Steve Haywood
    # Website ....... http://www.spacewire.co.uk
    # Project ....... Zedboard Linux (SpaceWire UK Tutorial)
    # Date .......... 22 Dec 2025
    # Version ....... 1.0
    # Description ...
    #   Recipe for an autostart application.
    #
    
    SUMMARY = "Simple adv7511-config application"
    SECTION = "PETALINUX/apps"
    LICENSE = "MIT"
    LIC_FILES_CHKSUM ="file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
    
    SRC_URI = "file://adv7511-config"
    
    S = "${WORKDIR}"
    
    FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
    
    inherit update-rc.d
    
    INITSCRIPT_NAME = "adv7511-config"
    INITSCRIPT_PARAMS = "start 99 S ."
    
    do_install() {
      install -d ${D}${sysconfdir}/init.d
      install -m 0755 ${S}/adv7511-config ${D}${sysconfdir}/init.d/adv7511-config
    }
    FILES_${PN} += "${sysconfdir}/*"
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/repos/0031/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/adv7511-config.bb -O zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/adv7511-config.bb
    
    #### Part 6 - Revision Control ####

    15. Commit new & updated files

    Check GIT status to make sure all is well and there are no spurious elements.
    steve@Desktop:~/swuk_tutorial$ git status -u
    On branch my_master
    Your branch is up-to-date with 'origin/my_master'.
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   zedboard_linux/os/petalinux/.petalinux/metadata      
            modified:   zedboard_linux/os/petalinux/project-spec/configs/config      
            modified:   zedboard_linux/os/petalinux/project-spec/configs/rootfs_config      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init.c      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init.h      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init.html      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init.tcl      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init_gpl.c      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/ps7_init_gpl.h      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/system.xsa      
            modified:   zedboard_linux/os/petalinux/project-spec/hw-description/system_wrapper.bit      
            modified:   zedboard_linux/os/petalinux/project-spec/meta-user/conf/user-rootfsconfig      
            modified:   zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/project.txt      
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/.gdbinit      
            zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/README      
            zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/adv7511-config.bb      
            zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/adv7511-config/files/adv7511-config      
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    Looks good!

    Commit the updates, create an annotated tag and push the commit & tag up to the remote repository.
    steve@Desktop:~/swuk_tutorial$ git add -A
    steve@Desktop:~/swuk_tutorial$ git commit -a -m "Added ADV7511 configuration auto-start application. This version of PetaLinux includes the XSA from zedboard_video_tpg_hdmi v1.0."
    steve@Desktop:~/swuk_tutorial$ git push
    steve@Desktop:~/swuk_tutorial$ git tag -a my_zedboard_linux_v15.0 -m "PetaLinux, Peek/Poke, LED Runner, LAMP (Apache, SQLite, PHP & myLiteAdmin), Peek/Poke CGI, Load Firmware CGI, PL Access, Style Sheet, Register Bank, ID Strings & ADV5711 configuration with XSA from zedboard_video_tpg_hdmi v1.0"
    steve@Desktop:~/swuk_tutorial$ git push origin my_zedboard_linux_v15.0
    

    16. Create production release

    Create a potential production release for the PetaLinux (v15.0) project using pure repository source. .

    This new release will include the Zedboard Video TPG HDMI files and also the ADV7511 configuration.

    (optional) Clear out all the superfluous files from the project area (non-tracked files).
    steve@Desktop:~/swuk_tutorial$ cd zedboard_linux/os/petalinux
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git clean -fdx
    
    (optional) Clear out the transfer area.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ rm -rf /tftpboot/*
    
    Double check GIT status.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    
    nothing to commit, working tree clean
    
    Build/rebuild PetaLinux.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ swuk_petalinux-build
    
    Note: A fresh build of PetaLinux takes a long time to complete and can be prone to failure due to internet downloads. If the build process fails, firstly check the GIT status & difftool for any noddy file changes, restore these file changes and then execute the build command again until it finally completes. Example below :-
    ::
    ::
    ERROR: Failed to build project. Check the ~/swuk_tutorial/zedboard_linux/os/petalinux/build/build.log file for more details...
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git status -u
    On branch my_master
    Your branch is up-to-date with 'origin/my_master'.
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   .petalinux/metadata      
            modified:   project-spec/configs/config      
    
    no changes added to commit (use "git add" and/or "git commit -a")
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git difftool
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ git restore .petalinux/metadata project-spec/configs/config
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ swuk_petalinux-build
    ::
    ::
    INFO: Successfully copied built images to tftp dir: /tftpboot
    [INFO] Successfully built project
    
    Package PetaLinux to produce the boot image BOOT.BIN, this will include the first stage boot loader zynq_fsbl.elf, the programmable logic system.bit, the Linux boot loader u-boot.elf and the device tree blob system.dtb.
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ petalinux-package --boot --force --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --uboot images/linux/u-boot.elf
    steve@Desktop:~/swuk_tutorial/zedboard_linux/os/petalinux$ cd ../../..
    
    Archive the generated files for safe keeping. These files are not held in the repository as they can be recreated from source.
    steve@Desktop:~/swuk_tutorial$ mkdir -p ${swuk_user}/petalinux/v15.0
    steve@Desktop:~/swuk_tutorial$ cp /tftpboot/{BOOT.BIN,boot.scr,image.ub} ${swuk_user}/petalinux/v15.0
    
    #### Part 7 - Hardware Deployment ####

    17. Copy files to SD Card

    Upload the newly created PetaLinux Boot & OS files. Select 0 or 6.
    steve@Desktop:~/swuk_tutorial$ swuk_upload_boot ${swuk_zedboard_ip}
    
    Boot files @ /tftpboot :-
    
    0) - BOOT.BIN - boot.scr - image.ub
    
    Boot files @ /home/steve/Documents/swuk_tutorial/petalinux :-
    
    1) v10.0 - BOOT.BIN - boot.scr - image.ub
    2) v11.0 - BOOT.BIN - boot.scr - image.ub
    3) v12.0 - BOOT.BIN - boot.scr - image.ub
    4) v13.0 - BOOT.BIN - boot.scr - image.ub
    5) v14.0 - BOOT.BIN - boot.scr - image.ub
    6) v15.0 - BOOT.BIN - boot.scr - image.ub
    
    q) Quit
    
    Select boot files for upload or quit : 6
    
    Remote reboot (wait): 30 / 30s
    Remote reboot (ping): 4 / 30s
    Remote reboot (ssh): 10 / 30s
    
    Uploaded BOOT.BIN, boot.scr & image.ub to /media/sd-mmcblk0p1 @ 192.168.2.87.
    
    Remote system credentials :-
    Zedboard PetaLinux
    SpaceWire UK
    Steve Haywood
    15.0
    28-Jan-2026 - 03:48:32
    e45fe0077ecd8c622f43eeef4d20a0096b9c1ce2
    
    Looks good!
    #### Part 8 - Check everything is working as expected ####

    18. OS boot & Firmware load

    Access the webserver running on the Zedboard using a browser pointing at the Zedboard's IP address (192.168.2.87).

    Select System from the menu bar (refresh page if already open).

    The Operating System Information table should show Zedboard PetaLinux description along with a version of 15.0.

    The Firmare Information table should now show Zedboard Video TPG HDMI description along with a version of 1.0.

    There should be no unsavoury comments after the version numbers! Missing Image! The Timestamp & Hash shown from GIT (first entry) should marry up perfectly with the displayed Operating System Information. All being well the second GIT entry should marry up perfectly with the displayed Firmware Information.
    steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_hdmi$ git log -2
    commit 8e3e56bf4c1a60533cf96186c94650db98839ac9 (HEAD -> my_master, tag: my_zedboard_linux_v15.0, origin/my_master)
    Author: Steve Haywood <steve@spacewire.co.uk>
    Date:   Sat Feb 7 09:00:38 2026 +0000
    
        Added ADV7511 configuration auto-start application. This version of PetaLinux includes the XSA from zedboard_video_tpg_hdmi v1.0.
    
    commit 404c5ae2ca1015d767fcde2cf00aa8bb24a11ef6 (tag: my_zedboard_video_tpg_hdmi_v1.0)
    Author: Steve Haywood <steve@spacewire.co.uk>
    Date:   Sat Feb 7 08:40:30 2026 +0000
    
        Basic Zedboard design consisting of a ZYNQ7 Processing System controlling a pair of cascading Test Pattern Generators that output video via HDMI.
    
    
    Looks good!

    19. Firmware register setup & TPG operation

    To get some video out of the Zedboard's HDMI connector the two TPG's need to be configured and enabled. Lets aim for a combined V & H ramp background with two moving box overlays, one green and one blue.

    Test Pattern Generator 1 Test Pattern Generator 2 There are quite a lot of registers that need to be configured for the above setup to work. Many ways to go about this, a shell script or compiled C running on PetaLinux for example. As an opening gambit a simple set of Peek & Poke Addresses configuration file will be created. Although this looks a little involved it is simply a list of address locations with default values associated. The widgets add a little complication but the effort is worth it in the end as it makes the bit-bashing very much more user friendly.
    steve@Desktop:~/swuk_tutorial$ subl ${swuk_user}/configuration/zedboard_video_tpg_hdmi.txt
    

    zedboard_video_tpg_hdmi.txt

    sec|Test Pattern Generator 0
    reg|0x40030010|false|true|1080|true|Active Height
    reg|0x40030018|false|true|1920|true|Active Width
    select|0x40030040|false|true|2#0^RGB#1^YUV 444#2^YUV 422#3^YUV 420|true|Color Format
    select|0x40030020|false|true|14#0^Pass through#1^Horizontal Ramp#2^Vertical Ramp#3^Temporal Ramp#4^Solid red#5^Solid green#6^Solid blue#7^Solid black#8^Solid white#9^Color bars#10^Zone Plate#11^Tartan Color Bars#12^Cross hatch pattern#13^Color sweep pattern#14^Combined V & H ramp#15^B & W checker board#16^Pseudorandom pattern#17^DP color ramp#18^DP B & W vertical lines#19^DP color square|true|Background Pattern ID
    reg|0x40030000|true|true|0x81|true|Control
    range|0x40030078|false|true|256#0#511|true|Box Size
    range|0x40030080|false|true|105#0#255|true|Box Color (Y)
    range|0x40030088|false|true|68#0#255|true|Box Color (U)
    range|0x40030090|false|true|52#0#255|true|Box Color (V)
    range|0x40030038|false|true|10#0#31|true|Motion Speed
    select|0x40030028|false|true|1#0^No overlay#1^Moving box#2^Cross hairs|true|Forground Pattern ID
    range|0x40030048|false|true|960#0#1919|true|Cross hair horizontal
    range|0x40030050|false|true|540#0#1079|true|Cross hair vertical
    
    sec|Test Pattern Generator 1
    reg|0x40040010|false|true|1080|true|Active Height
    reg|0x40040018|false|true|1920|true|Active Width
    select|0x40040040|false|true|2#0^RGB#1^YUV 444#2^YUV 422#3^YUV 420|true|Color Format
    select|0x40040020|false|true|0#0^Pass through#1^Horizontal Ramp#2^Vertical Ramp#3^Temporal Ramp#4^Solid red#5^Solid green#6^Solid blue#7^Solid black#8^Solid white#9^Color bars#10^Zone Plate#11^Tartan Color Bars#12^Cross hatch pattern#13^Color sweep pattern#14^Combined V & H ramp#15^B & W checker board#16^Pseudorandom pattern#17^DP color ramp#18^DP B & W vertical lines#19^DP color square|true|Background Pattern ID
    reg|0x40040000|true|true|0x81|true|Control
    range|0x40040078|false|true|175#0#511|true|Box Size
    range|0x40040080|false|true|18#0#255|true|Box Color (Y)
    range|0x40040088|false|true|208#0#255|true|Box Color (U)
    range|0x40040090|false|true|114#0#255|true|Box Color (V)
    range|0x40040038|false|true|8#0#31|true|Motion Speed
    select|0x40040028|false|true|1#0^No overlay#1^Moving box#2^Cross hairs|true|Forground Pattern ID
    range|0x40040048|false|true|960#0#1919|true|Cross hair horizontal
    range|0x40040050|false|true|540#0#1079|true|Cross hair vertical
    reg|0x40040098|false|true|1|true|Enable input
    
    sec|VTC - Set timings for 1080p
    reg|0x40050060|true|true|0x04380780|false|Horizontal and Vertical Frame Size (without blanking) for field 0
    reg|0x40050070|true|true|0x00000898|false|Horizontal Frame Size (with blanking)
    reg|0x40050074|true|true|0x04650465|false|Vertical Frame Size (with blanking)
    reg|0x40050078|true|true|0x080407D8|false|Start and end cycle index of HSync
    reg|0x4005007C|true|true|0x07D807D8|false|Start and end cycle index of VBlank for field 0
    reg|0x40050080|true|true|0x0440043B|false|Start and end line index of VSync for field 0
    reg|0x40050084|true|true|0x07D807D8|false|Start and end cycle index of VSync for field 0
    reg|0x40050088|true|true|0x07D807D8|false|Start and end cycle index of VBlank for field 1
    reg|0x4005008C|true|true|0x0440043B|false|Start and end line index of VSync for field 1
    reg|0x40050090|true|true|0x07D807D8|false|Start and end cycle index of VSync for field 1
    reg|0x40050094|true|true|0x04380780|false|Horizontal and Vertical Frame size for field 1
    reg|0x40050000|true|true|0x00000004|true|General Control
    
    sec|CW - Set clock to 148.5MHz for 1080p@60Hz (Full HD)
    reg|0x40060200|true|true|0x047D2504|false|Clock Configuration Register 0
    reg|0x40060208|true|true|0x0004FA06|false|Clock Configuration Register 2
    reg|0x4006025C|true|true|0x00000003|false|Clock Configuration Register 23
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/documents/swuk_tutorial/configuration/zedboard_video_tpg_hdmi.txt -O ${swuk_user}/configuration/zedboard_video_tpg_hdmi.txt
    
    Access the webserver running on the Zedboard using a browser pointing at the Zedboard's IP address (192.168.2.87). Select Peek & Poke from the menu bar.

    Browse for the above configuration file and open it. Although this looks complicated in reality it isn't. With the register values defined all that is now required is to click on Poke All to fire up both TPG's and output video via the HDMI connector. Missing Image! LED 7 should illuminate to indicate video lock & the following should be seen on the screen attached to the HDMI port of the Zedboard. The combined V & H ramp is provided from TPG 0 along with the larger green moving box. This video is then passed through TPG 1 and overlaid with the second smaller blue moving box.

    The hardware used for the following video captures was the Zedboard's HDMI output connected to a HDMI to USB video capture card.

    The software used to display the video from the HDMI to USB video capture card was Guvcview (Frame Rate: 60fps & Resolution: 1280x720). The window/screen area capture was done using Kazam (Frame rate: 60, Record with: VP8 (WEBM)).

    Note: The video looks much better on a HDMI monitor!



    Various elements of the TPG's can easily be controlled on-the-fly using the webpage widgets.



    The configuration file above can be split into smaller configurations that perform more specific actions.
    steve@Desktop:~/swuk_tutorial$ subl ${swuk_user}/configuration/zedboard_video_tpg_hdmi_1080p_60hz.txt
    

    zedboard_video_tpg_hdmi_1080p_60hz.txt

    sec|Test Pattern Generator 0 - Set resolution for 1080p
    reg|0x40030010|false|true|1080|true|Active Height
    reg|0x40030018|false|true|1920|true|Active Width
    
    sec|Test Pattern Generator 1 - Set resolution for 1080p
    reg|0x40040010|false|true|1080|true|Active Height
    reg|0x40040018|false|true|1920|true|Active Width
    
    sec|Video Timing Controller - Set timings for 1080p
    reg|0x40050060|true|true|0x04380780|true|Horizontal and Vertical Frame Size (without blanking) for field 0
    reg|0x40050064|true|true|0x00000898|false|Generator Timing Status Register
    reg|0x40050068|true|true|0x00000898|true|Generator Encoding
    reg|0x4005006C|true|true|0x00000898|true|Generator Polarity
    reg|0x40050070|true|true|0x00000898|true|Horizontal Frame Size (with blanking)
    reg|0x40050074|true|true|0x04650465|true|Vertical Frame Size (with blanking)
    reg|0x40050078|true|true|0x080407D8|true|Start and end cycle index of HSync
    reg|0x4005007C|true|true|0x07D807D8|true|Start and end cycle index of VBlank for field 0
    reg|0x40050080|true|true|0x0440043B|true|Start and end line index of VSync for field 0
    reg|0x40050084|true|true|0x07D807D8|true|Start and end cycle index of VSync for field 0
    reg|0x40050088|true|true|0x07D807D8|true|Start and end cycle index of VBlank for field 1
    reg|0x4005008C|true|true|0x0440043B|true|Start and end line index of VSync for field 1
    reg|0x40050090|true|true|0x07D807D8|true|Start and end cycle index of VSync for field 1
    reg|0x40050094|true|true|0x04380780|true|Horizontal and Vertical Frame size for field 1
    reg|0x40050000|true|true|0x00000006|true|General Control
    
    sec|Clocking Wizard - Set clock to 148.5MHz for 1080p@60Hz
    reg|0x40060200|true|true|0x047D2504|true|Clock Configuration Register 0
    reg|0x40060208|true|true|0x0004FA06|true|Clock Configuration Register 2
    reg|0x4006025C|true|true|0x00000003|true|Clock Configuration Register 23
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/documents/swuk_tutorial/configuration/zedboard_video_tpg_hdmi_1080p_60hz.txt -O ${swuk_user}/configuration/zedboard_video_tpg_hdmi_1080p_60hz.txt
    
    steve@Desktop:~/swuk_tutorial$ subl ${swuk_user}/configuration/zedboard_video_tpg_hdmi_1080p_30hz.txt
    

    zedboard_video_tpg_hdmi_1080p_30hz.txt

    sec|Test Pattern Generator 0 - Set resolution for 1080p
    reg|0x40030010|false|true|1080|true|Active Height
    reg|0x40030018|false|true|1920|true|Active Width
    
    sec|Test Pattern Generator 1 - Set resolution for 1080p
    reg|0x40040010|false|true|1080|true|Active Height
    reg|0x40040018|false|true|1920|true|Active Width
    
    sec|Video Timing Controller - Set timings for 1080p
    reg|0x40050060|true|true|0x04380780|true|Horizontal and Vertical Frame Size (without blanking) for field 0
    reg|0x40050064|true|true|0x00000898|false|Generator Timing Status Register
    reg|0x40050068|true|true|0x00000898|true|Generator Encoding
    reg|0x4005006C|true|true|0x00000898|true|Generator Polarity
    reg|0x40050070|true|true|0x00000898|true|Horizontal Frame Size (with blanking)
    reg|0x40050074|true|true|0x04650465|true|Vertical Frame Size (with blanking)
    reg|0x40050078|true|true|0x080407D8|true|Start and end cycle index of HSync
    reg|0x4005007C|true|true|0x07D807D8|true|Start and end cycle index of VBlank for field 0
    reg|0x40050080|true|true|0x0440043B|true|Start and end line index of VSync for field 0
    reg|0x40050084|true|true|0x07D807D8|true|Start and end cycle index of VSync for field 0
    reg|0x40050088|true|true|0x07D807D8|true|Start and end cycle index of VBlank for field 1
    reg|0x4005008C|true|true|0x0440043B|true|Start and end line index of VSync for field 1
    reg|0x40050090|true|true|0x07D807D8|true|Start and end cycle index of VSync for field 1
    reg|0x40050094|true|true|0x04380780|true|Horizontal and Vertical Frame size for field 1
    reg|0x40050000|true|true|0x00000006|true|General Control
    
    sec|Clocking Wizard - Set clock to 74.25MHz for 1080p@30Hz
    reg|0x40060200|true|true|0x047D2504|true|Clock Configuration Register 0
    reg|0x40060208|true|true|0x0005F40C|true|Clock Configuration Register 2
    reg|0x4006025C|true|true|0x00000003|true|Clock Configuration Register 23
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/documents/swuk_tutorial/configuration/zedboard_video_tpg_hdmi_1080p_30hz.txt -O ${swuk_user}/configuration/zedboard_video_tpg_hdmi_1080p_30hz.txt
    
    steve@Desktop:~/swuk_tutorial$ subl ${swuk_user}/configuration/zedboard_video_tpg_hdmi_720p_60hz.txt
    

    zedboard_video_tpg_hdmi_720p_60hz.txt

    sec|Test Pattern Generator 0 - Set resolution for 720p
    reg|0x40030010|false|true|720|true|Active Height
    reg|0x40030018|false|true|1280|true|Active Width
    
    sec|Test Pattern Generator 1 - Set resolution for 720p
    reg|0x40040010|false|true|720|true|Active Height
    reg|0x40040018|false|true|1280|true|Active Width
    
    sec|Video Timing Controller - Set timings for 720p
    reg|0x40050060|true|true|0x02D00500|true|Horizontal and Vertical Frame Size (without blanking) for field 0
    reg|0x40050064|true|true|0x00000898|false|Generator Timing Status Register
    reg|0x40050068|true|true|0x00000898|true|Generator Encoding
    reg|0x4005006C|true|true|0x00000898|true|Generator Polarity
    reg|0x40050070|true|true|0x00000672|true|Horizontal Frame Size (with blanking)
    reg|0x40050074|true|true|0x02EE02EE|true|Vertical Frame Size (with blanking)
    reg|0x40050078|true|true|0x0596056E|true|Start and end cycle index of HSync
    reg|0x4005007C|true|true|0x056E056E|true|Start and end cycle index of VBlank for field 0
    reg|0x40050080|true|true|0x02D902D4|true|Start and end line index of VSync for field 0
    reg|0x40050084|true|true|0x056E056E|true|Start and end cycle index of VSync for field 0
    reg|0x40050088|true|true|0x056E056E|true|Start and end cycle index of VBlank for field 1
    reg|0x4005008C|true|true|0x02D902D4|true|Start and end line index of VSync for field 1
    reg|0x40050090|true|true|0x056E056E|true|Start and end cycle index of VSync for field 1
    reg|0x40050094|true|true|0x02D00500|true|Horizontal and Vertical Frame size for field 1
    reg|0x40050000|true|true|0x00000006|true|General Control
    
    sec|Clocking Wizard - Set clock to 74.25MHz for 720p@60Hz
    reg|0x40060200|true|true|0x047D2504|true|Clock Configuration Register 0
    reg|0x40060208|true|true|0x0005F40C|true|Clock Configuration Register 2
    reg|0x4006025C|true|true|0x00000003|true|Clock Configuration Register 23
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/documents/swuk_tutorial/configuration/zedboard_video_tpg_hdmi_720p_60hz.txt -O ${swuk_user}/configuration/zedboard_video_tpg_hdmi_720p_60hz.txt
    
    steve@Desktop:~/swuk_tutorial$ subl ${swuk_user}/configuration/zedboard_video_tpg_hdmi_control.txt
    

    zedboard_video_tpg_hdmi_control.txt

    sec|Test Pattern Generator 0
    select|0x40030040|false|true|2#0^RGB#1^YUV 444#2^YUV 422#3^YUV 420|true|Color Format
    select|0x40030020|false|true|2#0^Pass through#1^Horizontal Ramp#2^Vertical Ramp#3^Temporal Ramp#4^Solid red#5^Solid green#6^Solid blue#7^Solid black#8^Solid white#9^Color bars#10^Zone Plate#11^Tartan Color Bars#12^Cross hatch pattern#13^Color sweep pattern#14^Combined V & H ramp#15^B & W checker board#16^Pseudorandom pattern#17^DP color ramp#18^DP B & W vertical lines#19^DP color square|true|Background Pattern ID
    reg|0x40030000|true|true|0x81|true|Control
    range|0x40030078|false|true|125#0#511|true|Box Size
    range|0x40030080|false|true|206#0#255|true|Box Color (Y)
    range|0x40030088|false|true|55#0#255|true|Box Color (U)
    range|0x40030090|false|true|157#0#255|true|Box Color (V)
    range|0x40030038|false|true|5#0#31|true|Motion Speed
    select|0x40030028|false|true|1#0^No overlay#1^Moving box#2^Cross hairs|true|Forground Pattern ID
    range|0x40030048|false|true|960#0#1919|true|Cross hair horizontal
    range|0x40030050|false|true|540#0#1079|true|Cross hair vertical
    
    sec|Test Pattern Generator 1
    select|0x40040040|false|true|2#0^RGB#1^YUV 444#2^YUV 422#3^YUV 420|true|Color Format
    select|0x40040020|false|true|0#0^Pass through#1^Horizontal Ramp#2^Vertical Ramp#3^Temporal Ramp#4^Solid red#5^Solid green#6^Solid blue#7^Solid black#8^Solid white#9^Color bars#10^Zone Plate#11^Tartan Color Bars#12^Cross hatch pattern#13^Color sweep pattern#14^Combined V & H ramp#15^B & W checker board#16^Pseudorandom pattern#17^DP color ramp#18^DP B & W vertical lines#19^DP color square|true|Background Pattern ID
    reg|0x40040000|true|true|0x81|true|Control
    range|0x40040078|false|true|175#0#511|true|Box Size
    range|0x40040080|false|true|18#0#255|true|Box Color (Y)
    range|0x40040088|false|true|208#0#255|true|Box Color (U)
    range|0x40040090|false|true|114#0#255|true|Box Color (V)
    range|0x40040038|false|true|8#0#31|true|Motion Speed
    select|0x40040028|false|true|2#1^No overlay#1^Moving box#2^Cross hairs|true|Forground Pattern ID
    range|0x40040048|false|true|960#0#1919|true|Cross hair horizontal
    range|0x40040050|false|true|540#0#1079|true|Cross hair vertical
    reg|0x40040098|false|true|1|true|Enable input
    
    Direct download available here :-
    steve@Desktop:~/swuk_tutorial$ wget https://spacewire.co.uk/tutorial/shared/documents/swuk_tutorial/configuration/zedboard_video_tpg_hdmi_control.txt -O ${swuk_user}/configuration/zedboard_video_tpg_hdmi_control.txt
    
    Access the webserver running on the Zedboard using a browser pointing at the Zedboard's IP address (192.168.2.87). Select Peek & Poke from the menu bar.

    Browse for the zedboard_video_tpg_hdmi_720p_60hz.txt configuration file and open it. Simply click on Poke All to change the current video output from 1080p @ 60Hz to 720p @ 60Hz. Missing Image! Right click on Peek & Poke from the menu bar and select Open Link in New Tab. Browse for the zedboard_video_tpg_hdmi_control.txt configuration file and open it. Simply click on Poke All to configure both of the two TPG's (different setup).

    The default configuration setup is as follows.

    Test Pattern Generator 1 Test Pattern Generator 2 Missing Image! Note: The cross hairs are not dead centre (expected), this is due to their coordinates being set for 1080p but the current resolution is 720p.

    Use the zedboard_video_tpg_hdmi_1080p_60hz.txt and zedboard_video_tpg_hdmi_1080p_30hz.txt for different screen resolutions and frame rates.

    Below is a useful RGB / YUV colour space converter to help ease with any conversion calculations.

    Colour Space Converter
    Red : Y :
    Green : U :
    Blue : V :