First Build
This tutorial is the end-to-end build procedure for the
Simple-ZCU111-Example firmware on the Xilinx ZCU111 evaluation board
(FPGA part xczu28dr-ffvg1517-2-e, firmware version v3.0.0.0 /
PRJ_VERSION = 0x03000000). It documents only the commands that differ
between this board and the platform-shared workflow; for host-prep details,
build-output redirection, the bare-metal-vs-Docker decision, and the
serial-console snippet — all of which are board-agnostic — sections below
deep-link to the corresponding anchors in the platform docs site
(tutorial/first_soc_bringup.html).
Reference toolchain
This walkthrough was authored against:
Vivado:
v2025.2(64-bit)OS: Ubuntu 22.04 LTS (x86_64)
Firmware version:
v3.0.0.0(PRJ_VERSION = 0x03000000)Target FPGA part:
xczu28dr-ffvg1517-2-eConda env:
rogue_v6.6.1
Approximate end-to-end build time on a typical Linux build host with the firmware tree on local-disk storage: ~60 min total — firmware (~17 min) plus Yocto (~45 min).
Output filenames embed the build timestamp, the building user’s username,
and the current git short-SHA, following the schema
<TargetName>-<PRJ_VERSION>-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>. The
<full-name> placeholder is used below wherever the exact filename is
build-specific.
Clone
Install git-lfs in your shell profile (one-time per environment) before cloning, so any LFS-tracked binaries are fetched correctly:
git lfs install
Clone the repository with all submodules:
git clone --recursive https://github.com/slaclab/Simple-ZCU111-Example.git
The --recursive flag initialises the
firmware/submodules/surf,
firmware/submodules/axi-soc-ultra-plus-core,
firmware/submodules/ruckus, and
firmware/submodules/aes-stream-drivers submodules in one step. Omitting
it leaves the firmware build unable to find the required RTL and TCL sources.
Setup environment
Source the Vivado 2025.2 environment, then activate the rogue_v6.6.1 conda
environment:
source firmware/vivado_setup.sh
source software/setup_env_slac.sh
The first script sets PATH, LD_LIBRARY_PATH, and the Xilinx licence
server variables required by make. The second activates the
rogue_v6.6.1 conda environment used by the Python control layer.
For host-package prerequisites, the non-SLAC Vivado/conda install path, Yocto host-package list, and the build-output redirection step required before the Yocto build, see tutorial/first_soc_bringup.html#setup-environment.
Firmware build
Change into the target directory and run make:
source firmware/vivado_setup.sh
cd firmware/targets/SimpleZcu111Example/
make
Approximate timing: ~17 min on a typical Linux build host with Vivado 2025.2.
After a successful build, the .bit and .xsa artifacts are written to
firmware/targets/SimpleZcu111Example/images/ using the schema
SimpleZcu111Example-0x03000000-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>:
firmware/targets/SimpleZcu111Example/images/SimpleZcu111Example-0x03000000-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>.bit
firmware/targets/SimpleZcu111Example/images/SimpleZcu111Example-0x03000000-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>.xsa
Note
Your filename will differ — the build embeds the build timestamp, your
username, and the current git short-SHA. PRJ_VERSION = 0x03000000
corresponds to firmware version v3.0.0.0 and is tracked in
firmware/targets/shared_version.mk.
To review Vivado results in GUI mode after a successful build:
make gui
For the platform-level firmware-build narrative (Vivado strategy, log locations, common build failures), see tutorial/first_soc_bringup.html#firmware-build.
Yocto build
The Yocto build produces the embedded Linux boot images (BOOT.BIN,
image.ub, boot.scr, system.bit) that run on the RFSoC Processing
System. From the target directory, pass the .xsa file produced by the
firmware build to BuildYoctoProject.sh:
cd firmware/targets/SimpleZcu111Example/
./BuildYoctoProject.sh -f images/SimpleZcu111Example-0x03000000-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>.xsa
Approximate timing: ~45 min on a typical Linux build host with the firmware tree on local-disk storage (~7200 bitbake tasks).
After a successful build, the boot images are in
firmware/build/YoctoProjects/SimpleZcu111Example/linux/ and a packaged
tarball is also produced at
firmware/targets/SimpleZcu111Example/images/<full-name>.linux.tar.gz.
For the bare-metal-vs-Docker decision, the Yocto host-package list, the Dockerfile defect callout, and the deploy-path layout, see tutorial/first_soc_bringup.html#yocto-build.
SD card
Once the Yocto build is complete, write the boot images to an SD card. The
verified procedure — covering both the manual mount-and-copy recipe and the
scripted CreateDiskImage.sh path
(how-to/sd_card_imaging.html) — is documented on the platform
docs site at tutorial/first_soc_bringup.html#sd-card. The four files to
copy live under
firmware/build/YoctoProjects/SimpleZcu111Example/linux/
(BOOT.BIN, image.ub, boot.scr, system.bit).
Boot
Power down the ZCU111 board.
Confirm
Mode SW6 [4:1] = 1110(switch OFF = 1 = High; ON = 0 = Low) to select SD boot mode.Insert the SD card written in the previous step.
Power up the board.
Confirm the board is reachable on the default DHCP IP
10.0.0.10:ping 10.0.0.10
For the serial-console snippet (USB-to-serial bridge, baud rate, terminal program selection on Linux/Windows) and troubleshooting steps for boot or network failures, see tutorial/first_soc_bringup.html#boot.
Run the Rogue GUI
Once the board is reachable on the network, launch the PyDM GUI from the host:
python software/scripts/devGui.py --ip 10.0.0.10
This connects to the on-board ZMQ server, builds the PyRogue device tree, and opens the default PyDM dashboard.
For installing Rogue on a non-SLAC host, see how-to/rogue_install.html. For the platform-level GUI launch how-to (advanced flags, alternative entry points, headless operation), see how-to/rogue_gui_launch.html.
Next steps
Update the bitstream on a running board without rebooting: how-to/remote_bitstream_update.html.
Flash the boot images to QSPI for SD-cardless boot: how-to/qspi_flash.html.
Recover from a bricked QSPI image using XSCT JTAG boot mode: how-to/xsct_boot_mode.html.