First SoC Bring-up
This tutorial walks through building and booting a SLAC RFSoC SoC platform design from
source. Simple-rfsoc-4x2-Example (board: RealDigital RFSoC 4x2, FPGA part
xczu48dr-ffvg1517-2-e) is used as the verified concrete example throughout. Paths
under firmware/targets/ are parameterised with the <your-target-dir> placeholder;
see the Supported Boards page for the target directory name for your board.
Output filenames embed the build timestamp, user name, and git hash, 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.
Reference toolchain
This walkthrough was authored against:
Vivado:
v2025.2(64-bit)OS: Ubuntu 22.04 LTS (x86_64)
Firmware version:
v3.2.0.0(PRJ_VERSION = 0x03020000)Target FPGA part:
xczu48dr-ffvg1517-2-e
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). See Build-output redirection below for why local-disk storage matters.
Clone
Install git-lfs in your shell profile (one-time step per environment) before cloning, so that any large binary files tracked with LFS are fetched correctly:
git lfs install
Clone the repository with all submodules:
# Replace <board> with the board-specific repo name, e.g. rfsoc-4x2
git clone --recursive https://github.com/slaclab/Simple-<board>-Example.git
Verified example (RFSoC 4x2):
git clone --recursive https://github.com/slaclab/Simple-rfsoc-4x2-Example.git
The --recursive flag initialises all git submodules (surf, axi-soc-ultra-plus-core,
ruckus, aes-stream-drivers) in a single step. Omitting it will leave the firmware
build unable to find required RTL and TCL sources.
Setup environment
Vivado toolchain (firmware build)
Source the Vivado 2025.2 environment script. On SLAC AFS hosts this resolves from
/sdf/group/faders/tools/xilinx/2025.2/:
source firmware/vivado_setup.sh
This sets PATH, LD_LIBRARY_PATH, and the Xilinx licence server variables required
by make. On a non-SLAC host, source the equivalent settings64.sh from your local
Vivado 2025.2 installation instead.
Rogue / PyRogue environment (software)
Activate the rogue_v6.12.0 conda environment:
source software/setup_env_slac.sh
On a non-SLAC host, install Rogue via the Miniforge install guide.
Yocto host packages
The Yocto build script (BuildYoctoProject.sh) verifies that the following host tools
are on PATH before it starts:
bash curl chrpath diffstat git gzip lz4c mkimage
On Ubuntu 22.04 these can be installed with:
sudo apt-get install -y bash curl chrpath diffstat git gzip lz4-tool u-boot-tools
Note
If all eight tools are already present on the host, the bare-metal Yocto path documented below works without Docker. If any are absent, use the Docker path.
Build-output redirection (required before the Yocto build)
The Yocto build produces roughly 133 GB of intermediates and deploy files under
firmware/build/. If firmware/build/ resolves to an NFS home directory or any
partition with less than ~150 GB free, the build will exhaust the quota or run very slowly
over NFS.
Redirect firmware/build to a local-disk partition before building:
rm -rf firmware/build 2>/dev/null
ln -s <your-local-disk-path>/build firmware/build
Replace <your-local-disk-path> with a locally mounted partition on your host that has
at least ~150 GB free (a local NVMe or SSD is strongly recommended).
Note
This symlink is not tracked by git (firmware/build is gitignored). It must be
created once per host and survives across builds. The Vivado firmware build also writes
its intermediates under firmware/build/, so the symlink benefits both steps.
Firmware build
Source the Vivado environment (if not already done), change into the target directory, and
run make:
source firmware/vivado_setup.sh
cd firmware/targets/<your-target-dir>/
make
Verified example (RFSoC 4x2):
source firmware/vivado_setup.sh
cd firmware/targets/SimpleRfSoc4x2Example/
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/<your-target-dir>/images/<full-name>.bit
firmware/targets/<your-target-dir>/images/<full-name>.xsa
Concrete example (RFSoC 4x2; sizes are approximate):
firmware/targets/SimpleRfSoc4x2Example/images/SimpleRfSoc4x2Example-0x03020000-<timestamp>-<user>-<sha>.bit (~33 MiB)
firmware/targets/SimpleRfSoc4x2Example/images/SimpleRfSoc4x2Example-0x03020000-<timestamp>-<user>-<sha>.xsa (~3 MiB)
The filename encodes <PRJ>-<PRJ_VERSION>-<YYYYMMDDHHMMSS>-<user>-<git-short-SHA>.
PRJ_VERSION = 0x03020000 corresponds to firmware version v3.2.0.0
(firmware/targets/shared_version.mk).
To review Vivado results in GUI mode after a successful build:
make gui
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 (PS). Two paths are
documented: bare-metal (recommended; works on any host with the Yocto host package
set installed) and Docker (currently blocked by a Dockerfile defect — see below).
Bare-metal path
From the target directory, pass the .xsa file from the firmware build to
BuildYoctoProject.sh:
cd firmware/targets/<your-target-dir>/
./BuildYoctoProject.sh -f images/<full-name>.xsa
Concrete example (RFSoC 4x2):
cd firmware/targets/SimpleRfSoc4x2Example/
./BuildYoctoProject.sh -f images/SimpleRfSoc4x2Example-0x03020000-<timestamp>-<user>-<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/<your-target-dir>/linux/BOOT.BIN (~35 MiB)
firmware/build/YoctoProjects/<your-target-dir>/linux/image.ub (~120 MiB)
firmware/build/YoctoProjects/<your-target-dir>/linux/boot.scr (~5 KiB)
firmware/build/YoctoProjects/<your-target-dir>/linux/system.bit (~33 MiB)
Note
The deploy path is firmware/build/YoctoProjects/<target>/linux/… — there is
no images/ segment in this path.
A packaged tarball is also produced at:
firmware/targets/<your-target-dir>/images/<full-name>.linux.tar.gz
The tarball contains linux/{BOOT.BIN, boot.scr, image.ub, system.bit} and is
convenient when using the scripted SD-card imaging approach (see SD card below).
Docker path
Warning
The Docker build path is currently blocked by a defect in
dockers/yocto/Dockerfile (line 4).
Root cause: DEBIAN_FRONTEND=noninteractive is set as a bash env-prefix before
apt-get update. This one-shot scope does not propagate to the subsequent chained
apt-get install commands, so xorg and console-setup packages prompt on stdin
and the build hangs indefinitely.
Proposed one-line fix (apply locally — this docs PR does not modify source files per the source-untouchable project constraint):
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
ARG user
ARG uid
Alternatively, try the BuildKit host-side workaround (untested):
DOCKER_BUILDKIT=1 source dockers/yocto/build_docker.sh
Once the Dockerfile defect is resolved, the Docker path is:
# Build the Docker image (one-time step)
cd dockers/yocto
source build_docker.sh
# Launch the container (drops into a shell inside the container)
source run_docker.sh
Inside the container, run BuildYoctoProject.sh pointing at the .xsa file:
cd firmware/targets/<your-target-dir>/
./BuildYoctoProject.sh -f images/<full-name>.xsa
SD card
Once the Yocto build is complete, write the boot images to an SD card. Full instructions
— including manual partitioning and the scripted CreateDiskImage.sh approach — are on
the SD Card Imaging page.
The four files to copy to the SD card FAT32 boot partition are:
firmware/build/YoctoProjects/<your-target-dir>/linux/BOOT.BIN
firmware/build/YoctoProjects/<your-target-dir>/linux/image.ub
firmware/build/YoctoProjects/<your-target-dir>/linux/boot.scr
firmware/build/YoctoProjects/<your-target-dir>/linux/system.bit
Manual copy recipe (SD card FAT32 on /dev/sde1 — adjust device path as needed):
sudo mkdir -p boot
sudo mount /dev/sde1 boot
sudo cp firmware/build/YoctoProjects/<your-target-dir>/linux/system.bit boot/
sudo cp firmware/build/YoctoProjects/<your-target-dir>/linux/BOOT.BIN boot/
sudo cp firmware/build/YoctoProjects/<your-target-dir>/linux/image.ub boot/
sudo cp firmware/build/YoctoProjects/<your-target-dir>/linux/boot.scr boot/
sudo sync boot/
sudo umount boot
Scripted approach (using CreateDiskImage.sh from the platform submodule):
source firmware/submodules/axi-soc-ultra-plus-core/scripts/CreateDiskImage.sh \
path_to_image_file.img \
firmware/targets/<your-target-dir>/images/<full-name>.linux.tar.gz
Boot
Power down the RFSoC board.
Confirm the mode slide switch is in the SD (not JTAG) position.
Insert the SD card.
Power up the board.
Confirm the board is reachable on the network (default IP
10.0.0.10):ping 10.0.0.10
Serial console (for troubleshooting boot failures or network issues):
Connect a USB cable from the host to the board’s serial-to-USB bridge. A serial device
will appear (e.g., /dev/ttyUSB1). Open a terminal at 115200 baud, 8 data bits,
no parity:
cu --line /dev/ttyUSB1 --speed 115200 --parity=none
On Windows, use Tera-Term or PuTTY configured for 115200 8N1.