Part 23 - Create a cascading Video TPG design for VGA 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 VGA 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.
Starting from this point is possible but requires a few pre-requisites.
Vivado 2022.2 & PetaLinux 2021.2 are installed & set-up (ideally in /opt/Xilinx).
The other support applications are installed and set-up; minicom, git, sublime-text & sshpass. See Part 1 for more information.
The (remote) SpaceWire UK Tutorial repository is present on your server at say git@192.168.2.20:swuk_tutorial.git or at say ${HOME}/repos/swuk_tutorial.git.
Note: Only perform the following if not continuing from the previous tutorial.
Example: Setup the remote repository (on the local machine). This is required to perform GIT push commands.
The (global) shell initialisation script has been sourced (so it sources the SWUK local SIS).
steve@Desktop:~$ source ~/.bashrc
Vivado & Vitis are setup to use the 2022.2 version (due to an end-of-year bug in the Video IP generation of 2021.2). PetaLinux is setup to use the (existing) 2021.2 version (due to later versions not being backwards compatible).
steve@Desktop:~$ swuk_xilinx 2022.2 2021.2
Tools are as follows :-
Vivado @ /opt/Xilinx/Vivado/2022.2/bin/vivadoSDK @ Not available!Vitis @ /opt/Xilinx/Vitis/2022.2/bin/vitisPetaLinux-build @ /opt/Xilinx/PetaLinux/2021.2/tool/tools/common/petalinux/bin/petalinux-build
Plugged into the ZedBoard is a FAT32 formatted SD card containing the PetaLinux v14.0 (or higher) boot files (generated in Part 20).
The Zedboard boot mode jumpers are configured for SD Card boot.
The Zedboard hardware is connected up for comms, internet & VGA video.
1. Xubuntu PC USB ⇄ Zedboard USB JTAG/Debug.
2. Xubuntu PC USB ⇄ Zedboard USB UART.
3. Zedboard Ethernet ⇄ Router.
4. Xubuntu PC Ethenet ⇄ Router.
5. Router ⇄ Internet.
6. Zedboard ⇄ Monitor (VGA).
The Zedboard is now powered-up & present on the LAN.
steve@Desktop:~$ ping -c 1 ${swuk_zedboard_ip}
PING 192.168.2.87 (192.168.2.87) 56(84) bytes of data.
64 bytes from 192.168.2.87: icmp_seq=1 ttl=64 time=0.149 ms
--- 192.168.2.87 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.149/0.149/0.149/0.000 ms
The debug terminal emulator is up and running (optional).
steve@Desktop:~$ swuk_terminal
Welcome to minicom 2.7.1
OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port /dev/ttyACM0, 06:34:25
Press CTRL-A Z for help on special keys
PetaLinux 2021.2 petalinux /dev/ttyPS0
petalinux login:
#### 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_vga --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 VGA
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_vga
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ swuk_create_vivado_project
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ 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 icon. Resize the canvas to obtain a better view of the design and click on the Regenerate Layout icon to obtain a better layout.
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 (brief) :-
AXI GPIO ZED
AXI Interconnect
Additional IP & RTL blocks required :-
Clocking Wizard
2x Video Test Pattern Generator
Video Timing Controller
AXI4-Stream to Video Out
3x Slice
Concat
Heartbeat
Changes required to existing IP & RTL blocks (more detail) :-
Step 1 - To add VGA video capability to the existing design the following Xilinx IP components are required.
1x Clocking Wizard - To provide a 148.5MHz video clock from the 100MHz board clock
1x Processor System Reset - To provide a reset for the video clock domain
2x Video Test Pattern Generator - To provide a video test pattern
1x Video Timing Controller - To provide video timing signals
1x AXI-Stream to Video Out - To provide a RGB video output
3x Slice - To cut down the 8-bit RGB to 4-bit RGB
Step 2 - The following two additions are to add indicators on the top two LEDs to show Video Locked & Video Clock.
1x Concat - To combine 8 separate signals into an 8-bit bus
1x heartbeat - To provide a video clock heartbeat
Step 3 - Some of the new additions need customisation.
Clocking Wizard - Remove reset input & set clk_out1 to 148.5MHz
2nd Video Test Pattern Generator - Add AXIS Slave to allow video pass-through
Video Timing Controller - Disable AXI4-Lite interface, disable Detection & set Video Format to 1080p
Red Slice - Set Din Width to 24 and Din Range to 7:4 (4-bit red MSB)
Green Slice - Set Din Width to 24 and Din Range to 15:12 (4-bit green MSB)
Blue Slice - Set Din Width to 24 and Din Range to 23:20 (4-bit blue MSB)
Concat - Set Number of Ports to 8
heartbeat - Set Clock Frequency to 148500000 Hz & Beat Frequency to 1 Hz
axi_gpio_zed - Set LEDs Mask to "11000000" to enable pass-through on LEDs 7:6
Step 4 - Add an extra two ports on the Interconnect to deal with the new Test Pattern Generators.
Step 5 - Add the newly required external I/O.
sys_clock - Input board clock at 100MHz
vid_data_r - Output red video (4-bit)
vid_data_g - Output green video (4-bit)
vid_data_b - Output blue video (4-bit)
vid_hsync - Output horizontal video sync
vid_vsync - Output vertical video sync
Step 6 - Create port connections.
The sys_clock input port to the clk_wiz_0/clk_in1 input
The clk_wiz_0/locked output to the proc_sys_reset_1/ext_reset_in input
The clk_wiz_0/clk_out1 output to the other 8 unconnected clock inputs
The proc_sys_reset_1/peripheral_aresetn output to the other 7 unconnected reset inputs
The v_axi4s_vid_out_0/vid_data outputs to the 3 xlslice_r|g|b/Din inputs
The 3 xlslice_r|g|b/Dout outputs to the 3 vid_data_r|g|b output ports
The v_axi4s_vid_out_0/vid_hsync|vsync outputs to the vid_hsync|vsync output ports
The v_axi4s_vid_out_0/vtg_ce output to the v_tc_0/gen_clken input
The heartbeat_0/led & v_axi4s_vid_out_0/locked outputs to the xlconcat_0/In7|8 inputs
The xlconcat_0/dout output to the axi_gpio_zed_0/leds_bypass input
Step 7 - Create interface connections.
The two new axi_interconnect_0 masters to the v_tpg_0 & v_tpg_1 slaves
The tpg_0 master to the v_tpg_2 slave
The tpg_1 master to the v_axi4s_vid_out_0 slave
The v_tc_0 timings output to the v_axi4s_vid_out_0 timings input
Step 8 - Create address segments.
Put v_tpg_0 at address 0x40030000 with a 64Kb range.
Put v_tpg_1 at address 0x40040000 with a 64Kb range.
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'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
zedboard_video_tpg_vga/.gitignore zedboard_video_tpg_vga/fw/project.txt zedboard_video_tpg_vga/fw/src/constraint/zedboard_video_tpg_vga.xdc zedboard_video_tpg_vga/fw/src/design/zedboard_video_tpg_vga.sv zedboard_video_tpg_vga/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 VGA."
steve@Desktop:~/swuk_tutorial$ git push
steve@Desktop:~/swuk_tutorial$ git tag -a my_zedboard_video_tpg_vga_v1.0 -m "ZYNQ & Cascading TPG's with VGA output"
steve@Desktop:~/swuk_tutorial$ git push origin my_zedboard_video_tpg_vga_v1.0
#### Part 4 - Firmware Development - 2 ####
9. Create production release
Create a potential production release for the Zedboard Video TPG VGA (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_vga
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ rm -rf fw/vivado
Double check GIT status.
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ git status -u
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
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.
The Operating System Information table should show Zedboard PetaLinux Example Design description along with a version of 14.0.
The Firmare Information table should show Zedboard LEDs & Switches Example Design description along with a version of 5.0.
In the Loadable Firmware table click on Load next to the newly uploaded binary to load the new firmware into the PL.
The Firmare Information table should now show the new Zedboard Video TPG VGA Example Design description along with a version of 1.0.
There should be no unsavoury comments after the version numbers!
The Timestamp & Hash shown from GIT should marry up perfectly with the Firmware Information.
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ git log -1
commit a6212153bd0a72eec48c0b132f31a2ee8478ec73(HEAD -> my_master, tag: my_zedboard_video_tpg_vga_v1.0,origin/my_master)
Author: Steve Haywood <steve@spacewire.co.uk>
Date: Mon Jan 26 11:31:45 2026 +0000
Basic Zedboard design consisting of a ZYNQ7 Processing System controlling a pair of cascading Test Pattern Generators that output video via VGA.
To get some video out of the Zedboard's VGA connector the two TPG's need to be configured and enabled. Lets aim for a colour bar background with two moving box overlays, one green and one blue.
Test Pattern Generator 1
Set Resolution to 1920 x 1080
Set Colour Format to RGB
Set Background Pattern to Colour bars
Set Box Color to green, Box Size to 256 & Motion Speed to 10
Set Foreground Pattern to Moving Box
Start the TPG with auto-restart (continuous frames)
Test Pattern Generator 2
Set Resolution to 1920 x 1080
Set Colour Format to RGB
Set Background Pattern to Pass through
Set Box Color to blue, Box Size to 175 & Motion Speed to 8
Set Foreground Pattern to Moving Box
Start the TPG with auto-restart (continuous frames)
Enable video input
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. For an opening gambit a simple 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.
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 VGA connector.
LED 7 should illuminate to indicate video lock & the following should be seen on the screen attached to the VGA port of the Zedboard. The color bars are 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.
Note the glitch in the video when either box hits the right hand edge of the screen. To see how bad this is make one of the boxes small and then when it gets close to the right hand edge make it much larger.
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 monitor!
Various elements of the TPG's can easily be controlled on-the-fly using the webpage widgets.
Sadly some of the background patterns do not work as expected due to the RGB lines only being 4-bits wide instead of 8-bits wide. Not sure what is causing the right hand side artefact, this is something not seen in the HDMI version of this design!
#### Part 6 - Revision Control - 2 ####
13. Block design vs. scripted options
Two options now exist for committing the zedboard_video_tpg_vga project (and others) to the repository.
Block design with no script execution - commit fw/src/diagram/system/system.bd.
Purely scripted - do not commit fw/src/diagram/system/system.bd.
If this design was built from the repository source using only the scripts (common/fw/src/script/swuk_create_system_bd.tcl & zedboard_video_tpg_vga/fw/src/script/user_update_system_bd.tcl), i.e. the block design was not present in the repository (zedboard_video_tpg_vga/fw/src/diagram/system/system.bd) then a new block design will be created (from the scripts) at zedboard_video_tpg_vga/fw/vivado/project.srcs/sources_1/bd/system/system.bd.
If the newly created block design (zedboard_video_tpg_vga/fw/vivado/project.srcs/sources_1/bd/system/system.bd) is manually edited then it MUST be copied to zedboard_video_tpg_vga/fw/src/diagram/system/system.bd so it can be committed to the repository and used for the next iteration of the design. Once the block design is safely committed it is best to clean the project directory using git clean -fdx and recreate a clean project using swuk_create_vivado_project. This will now use the block design from zedboard_video_tpg_vga/fw/src/diagram/system/system.bd instead of the two scripts.
If an existing block design from the repository (zedboard_video_tpg_vga/fw/src/diagram/system/system.bd) is manually edited then it will automatically be included in any commit to the repository.
14. Final checks (BD build)
Sanity check the block design (not purely scripted) build process.
Close Vivado.
The previous build used the two scripts to create the block design (zedboard_video_tpg_vga/fw/vivado/zedboard_video_tpg_vga.srcs/sources_1/bd/system/system.bd).
If this block design had been manually edited then it would be copied to zedboard_video_tpg_vga/fw/src/diagram/system/system.bd for inclusion in the repository and thus used to build a fresh design.
Copy the block design to the acceptable location (zedboard_video_tpg_vga/fw/src/diagram/system/system.bd) so it will be used instead of the scripts. Remove the existing vivado directory.
Check GIT status, which should now show the block design is part of the file set.
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ git status -u
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
fw/src/diagram/system/system.bd
nothing added to commit but untracked files present (use "git add" to track)
Create the project from fresh source, now using the block design instead of the scripts.
Check all is well by expanding zedboard_video_tpg_vga under Design Sources. Click on system.bd and examine the Location under Source File Properties. The location should be ${swuk_tutorial}/zedboard_video_tpg_vga/fw/src/diagram/system.
If the current files were now committed to the repository then going forward the block design would be used instead of the scripts.
Since we don't really want that at the moment, quit Vivado and do a clean to get back to the previous state.
steve@Desktop:~/swuk_tutorial/zedboard_video_tpg_vga$ git status -u
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean