ZCU104 Programmable Logic VCU Demo
This page describes an AMD EDF demo for the ZCU104 evaluation board. The demo uses dynamically loaded programmable logic firmware together with a containerized VCU application flow on top of the EDF Linux BSP.
Overview
The demo combines two pieces that ship through the
meta-amd-edf-demos Yocto layer:
A container application that bundles the VCU components and applications (
vcu-ctrlsw,vcu-firmware,libvcu-omxil, andkernel-module-vcu). The container also includesdfx-mgr-clientsupport so that it can drive PL firmware that the host loads dynamically.A PL firmware recipe that packages the VCU PL design for the ZCU104. The recipe uses the
dfx_user_dtsmechanism so thatdfx-mgrcan discover and load the firmware at runtime through the AMD Dynamic Function eXchange (DFX) manager.
Together, these pieces show how EDF can run a containerized validation application on top of a dynamically loaded PL design on the ZCU104.
The recipes referenced by this page (zcu104-pl-vcu-fw
and container-app-zcu104-vcu) live in the
meta-amd-edf-demos layer; see References
for the upstream recipe URLs.
Demo Components
The following table summarizes the two recipes that make up the demo and the role each one plays.
Recipe |
Type |
Purpose |
|---|---|---|
|
PL firmware |
Packages the VCU PL design for ZCU104 and
installs it under |
|
Container application |
Builds a container image that bundles
|
Programmable Logic Firmware Recipe
The PL firmware recipe zcu104-pl-vcu-fw provides the
ZCU104 VCU PL design as a loadable firmware package.
The recipe inherits dfx_user_dts, which:
compiles the recipe-supplied
pl.dtsiinto an overlay.dtbo;installs the bitstream and the overlay under
/lib/firmware/xilinx/<package-name>/; andregisters the package with
dfx-mgrso thatdfx-mgr-client -listPackageenumerates it on the target.
The recipe is compatible with the ZCU104 EDF target machine.
The firmware package contains the required PL artifacts for
dynamically loading the VCU design through the AMD dfx-mgr.
For background on the dfx_user_dts flow and how it fits into
the EDF segmented build, refer to:
Container Application Recipe
The container application recipe
container-app-zcu104-vcu builds a container image
on top of the base container image flow. The container rootfs includes:
vcu-ctrlsw– standalone command-line executable for enc and dec.vcu-firmware– firmware package loaded onto the VCU hard block.kernel-module-vcu– contains the source code of al5r drivers.libvcu-omxil– contains the AllegroDVT OpenMax Integration Layer (OMXIL) implementation.dfx-mgr-client– so the container can list and load PL firmware packages that the host’sdfx-mgrexposes.
For the general container application packaging pattern, refer to the Application Deployment page.
Building the Demo
BitBake builds the container application from a Yocto build environment. The
environment must include the meta-amd-edf-demos layer and
target the ZCU104 machine. The firmware is included through CONTAINER_APP.
Clone meta-amd-edf-demos layer:
$ cd ../sources $ git clone https://github.com/AMD-AECG-SSW-PUBLIC/meta-amd-edf-demos.git
Add meta-amd-edf-demos layer
$ cd build/ $ bitbake-layers add-layer ../sources/meta-amd-edf-demos/
Build the container application:
$ MACHINE=amd-cortexa53-mali-common bitbake container-app-zcu104-vcu
The generated container rootfs tarball is available under:
${TMPDIR}/deploy/images/amd-cortexa53-mali-common/....
Alternatively, copy the generated container rootfs tarball
to the running target.
Manually Removing Reserved Memory Nodes
To manually remove the reserved memory nodes:
Remove the existing CMA reserved nodes, CMA reserved symbols, and phandles from the system.dtb.
Obtain
system.dtbfrom the soc-prebuilt-firmware repository and convert it to DTS:$ dtc -I dtb -O dts -o system.dts system.dtb
Remove the following node from system.dts:
cma_reserved@00000000 { phandle = <0x123>; label = "cma_reserved_0"; compatible = "shared-dma-pool"; reusable; linux,cma-default; reg = <0x00 0x00 0x00 0x2ee00000>; };
Also remove this symbol and phandle:
cma_reserved_0 = "/reserved-memory/cma_reserved@00000000";
From APU_Linux node remove the cma_reserved phandle address.
reserved-memory = <0x123>;
Convert the dts back to dtb and regenerate
boot.bin. Use the updatedboot.binwith the WIC image.$ dtc -@ -I dts -O dtb -o system.dtb system.dts
Source the Vivado settings script from your local installation, replacing
2026.1with the version directory of your Vivado installation:$ source /opt/Xilinx/Vivado/2026.1/settings64.sh $ bootgen -arch zynqmp -image bootgen.bif -w -o bg.bin
Copy
bg.bininto the bootable partition of the EDF WIC image and boot the board with the updated image.$ wic cp bg.bin <edf-image>.rootfs.wic:1
Increasing CMA
The default CMA pool on ZCU104 is capped at 750 MB, which is
insufficient for the VCU encoder and decoder pipelines running
concurrently. Validated on ZCU104 with the reserved node removed.
Increase the CMA size to 1700M at the U-Boot level using
boot arguments. While booting, interrupt at the U-Boot prompt and
run the following commands. For SD boot, set the boot
arguments in U-Boot as follows:
ZynqMP> setenv sdboot "mmc dev 0 && mmcinfo && load mmc 0:auto 0x200000 Image && booti 0x200000 - 0x100000"
ZynqMP> setenv bootargs "earlycon clk_ignore_unused earlyprintk consoleblank=0 root=/dev/mmcblk0p3 rw rootwait debug cma=1700M"
ZynqMP> run sdboot
Verify the CMA allocation:
root@amd-edf:~# cat /proc/meminfo | grep -i cma
CmaTotal: 1740800 kB
Running the Demo on the Target
The following steps assume the ZCU104 has booted an EDF image
with dfx-mgr and a container runtime (for example docker
or podman) installed. The steps also assume that the
preceding container image is present on the target.
Extract and Import the Container Image
List the available PL firmware packages:
$ sudo dfx-mgr-client -listPackage
Extract the generated rootfs tarball:
$ bunzip2 container-app-zcu104-vcu-amd-cortexa53-mali-common.rootfs-<date>.tar.bz2
Import the container image into Docker:
$ sudo docker import \ container-app-zcu104-vcu-amd-cortexa53-mali-common.rootfs-<date>.tar
List the available container images:
$ sudo docker images
Create Docker Volume and Run the Application from the Container Image
Create Firmware directory
$ sudo mkdir -p /lib/firmware/xilinx/zcu104-pl-vcu-fw
Create a Docker volume that bind-mounts the firmware directory.
$ sudo docker volume create --name producer_consumer \ --driver local --opt type=none --opt o=bind \ --opt device=/lib/firmware/xilinx/zcu104-pl-vcu-fw
Verify the created volume:
$ sudo docker volume ls
Run the container with the firmware volume and dfx-mgr socket mounted.
$ sudo docker run -it \ --privileged \ -v /dev:/dev \ -v producer_consumer:/lib/firmware/xilinx/zcu104-pl-vcu-fw \ -v /var/run/dfx-mgrd.socket:/var/run/dfx-mgrd.socket \ <image-id> bash
From inside the container, load the VCU firmware package:
$ dfx-mgr-client -loadByName zcu104-pl-vcu-fw
Verify that the firmware package is loaded successfully by re-running
dfx-mgr-client -listPackage.Run the VCU application from inside the container.
$ ctrlsw_decoder -avc -i AIR_1080p30_nv12.avc --noyuv
The container communicates with the host dfx-mgr daemon through the mounted socket and dynamically loads the VCU programmable logic design at runtime.
Unloading the Programmable Logic Firmware
When the demo finishes, unload the firmware from the host:
$ sudo dfx-mgr-client -unloadByName zcu104-pl-vcu-fw