VEK280 Programmable Logic Video Decoder Unit Demo

This page describes an AMD EDF demo for the VEK280 evaluation board. The demo uses dynamically loaded programmable logic firmware together with a containerized VDU 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 VDU components and applications (vdu-ctrlsw, vdu-firmware, libvdu-omxil, and kernel-module-vdu). The container also includes dfx-mgr-client support so that it can drive PL firmware that the host loads dynamically.

  • A PL firmware recipe that packages the VDU PL design for the VEK280. The recipe uses the dfx_user_dts mechanism so that dfx-mgr can 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 VEK280.

The recipes referenced by this page (vek280-pl-vdu-fw and container-app-vek280-vdu) 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

vek280-pl-vdu-fw

PL firmware

Packages the VDU PL design for VEK280 and installs it under /lib/firmware/xilinx using the dfx_user_dts mechanism so that dfx-mgr-client can load it at runtime.

container-app-vek280-vdu

Container application

Builds a container image that bundles vdu-ctrlsw, vdu-firmware, libvdu-omxil, and kernel-module-vdu, together with dfx-mgr-client so the container can interact with the loaded PL firmware.

Programmable Logic Firmware Recipe

The PL firmware recipe vek280-pl-vdu-fw provides the VEK280 VDU PL design as a loadable firmware package.

The recipe inherits dfx_user_dts, which:

  • compiles the recipe-supplied pl.dtsi into an overlay .dtbo;

  • installs the bitstream and the overlay under /lib/firmware/xilinx/<package-name>/; and

  • registers the package with dfx-mgr so that dfx-mgr-client -listPackage enumerates it on the target.

The recipe is compatible with the VEK280 EDF target machine. The firmware package contains the required PL artifacts for dynamically loading the VDU 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-vek280-vdu builds a container image on top of the base container image flow. The container rootfs includes:

  • vdu-ctrlsw – standalone command-line executable for enc.

  • vdu-firmware – firmware package loaded onto the VDU hard block.

  • kernel-module-vdu – contains the source code of al5r drivers.

  • libvdu-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’s dfx-mgr exposes.

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 VEK280 machine. The firmware is included through CONTAINER_APP.

  1. Clone meta-amd-edf-demos layer:

    $ cd ../sources
    $ git clone https://github.com/AMD-AECG-SSW-PUBLIC/meta-amd-edf-demos.git
    
  2. Add meta-amd-edf-demos layer

    $ cd build/
    $ bitbake-layers add-layer ../sources/meta-amd-edf-demos/
    
  3. Build the container application:

    $ MACHINE=amd-cortexa72-common bitbake container-app-vek280-vdu
    

The generated container rootfs tarball is available under: ${TMPDIR}/deploy/images/amd-cortexa72-common/.... Alternatively, copy the generated container rootfs tarball to the running target.

Manually Adding Reserved Memory Nodes

To manually add the reserved memory nodes:

  1. Remove the existing CMA reserved nodes, CMA reserved symbols, and phandles from the DTS.

    Obtain cortexa72-linux.dtb from the soc-prebuilt-firmware repository and convert it to DTS:

    $ dtc -I dtb -O dts -o cortexa72-linux.dts  cortexa72-linux.dtb
    

    Remove the following nodes from cortexa72-linux.dts:

    cma_reserved@50000000000 {
            phandle = <0x18e>;
            label = "cma_reserved_50000000000";
            compatible = "shared-dma-pool";
            reusable;
            linux,cma-default;
            reg = <0x500 0x00 0x00 0xc0000000>;
    };
    cma_reserved@60000000000 {
            phandle = <0x18f>;
            label = "cma_reserved_60000000000";
            compatible = "shared-dma-pool";
            reusable;
            linux,cma-default;
            reg = <0x600 0x00 0x00 0xc0000000>;
    };
    
    cma_reserved_50000000000 = "/reserved-memory/cma_reserved@50000000000";
    cma_reserved_60000000000 = "/reserved-memory/cma_reserved@60000000000";
    

    From APU_Linux node remove the cma_reserved phandle address.

    reserved-memory = <0x18e 0x18f 0x190 0x191 0x192 0x193>;
    
  2. Add the VDU reserved memory nodes in the cortexa72-linux.dts.

    mem_reg_0: myddr1@50000000000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0x500 0x00 0x00 0x80000000>;
            phandle = <0x555>;
    };
    mem_reg_1: myddr2@50080000000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0x500 0x80000000 0x00 0x80000000>;
            phandle = <0x556>;
    };
    mem_reg_2: myddr3@60000000000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0x600 0x00 0x00 0x80000000>;
            phandle = <0x557>;
    };
    mem_reg_3: myddr4@60080000000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0x600 0x80000000 0x00 0x80000000>;
            phandle = <0x558>;
    };
    
  3. Convert the dts back to dtb and regenerate boot.bin. Use the updated boot.bin with the WIC image.

    Convert DTS back to DTB:

    $ dtc -@ -I dts -O dtb -o cortexa72-linux.dtb  cortexa72-linux.dts
    

    Source the Vivado settings script from your local installation, replacing 2026.1 with the version directory of your Vivado installation:

    $ source /opt/Xilinx/Vivado/2026.1/settings64.sh
    $ bootgen -arch versal -image bootgen.bif -w -o bg.bin
    
  4. Copy bg.bin into 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
    

Running the Demo on the Target

The following steps assume the VEK280 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

  1. List the available PL firmware packages:

    $ sudo dfx-mgr-client -listPackage
    
  2. Extract the generated rootfs tarball:

    $ bunzip2 container-app-vek280-vdu-amd-cortexa72-common-rootfs-<date>.tar.bz2
    
  3. Import the container image into Docker:

    $ sudo docker import \
     container-app-vek280-vdu-amd-cortexa72-common-rootfs-<date>.tar
    
  4. List the available container images:

    $ sudo docker images
    

Create Docker Volume and Run the Application from the Container Image

  1. Create Firmware directory

    $ sudo mkdir -p /lib/firmware/xilinx/vek280-pl-vdu-fw
    
  2. 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/vek280-pl-vdu-fw
    
  3. Verify the created volume:

    $ sudo docker volume ls
    
  4. 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/vek280-pl-vdu-fw \
      -v /var/run/dfx-mgrd.socket:/var/run/dfx-mgrd.socket \
      <image-id> bash
    

    Note

    If you need the reserved memory nodes, update the mem_reg references in the AL5D nodes inside the device tree overlay before running the container. See Manually Adding Reserved Memory Nodes for the complete procedure.

  5. Exit the container bash terminal:

    $ exit
    
  6. Change to the firmware directory on the host:

    $ cd /lib/firmware/xilinx/vek280-pl-vdu-fw
    
  7. Convert the device tree overlay blob to source:

    $ dtc -I dtb -O dts -o temp.dtso vek280-pl-vdu-fw.dtbo
    
  8. Update memory-region references in the AL5D nodes inside temp.dtso to match the new reserved memory nodes from cortexa72-linux.dts. For each AL5D node, set the memory-region property to the phandle of the corresponding reserved memory node:

    al5d0: al5d@a4020000 {
            al,devicename = "allegroDecodeIP0";
            reg = <0x0 0xa4020000 0x0 0x100000>;
            interrupt-names = "vdu_host_interrupt0";
            xlnx,vdu = <&vdu_vdu_0>;
            compatible = "al,al5d";
            interrupt-parent = <&gic>;
            interrupts = <0x0 0x54 0x4>;
            memory-region = <0x555>;
    };
    al5d1: al5d@a4120000 {
            al,devicename = "allegroDecodeIP1";
            reg = <0x0 0xa4120000 0x0 0x100000>;
            interrupt-names = "vdu_host_interrupt1";
            xlnx,vdu = <&vdu_vdu_0>;
            compatible = "al,al5d";
            interrupt-parent = <&gic>;
            interrupts = <0x0 0x55 0x4>;
            memory-region = <0x556>;
    };
    al5d2: al5d@a4220000 {
            al,devicename = "allegroDecodeIP2";
            reg = <0x0 0xa4220000 0x0 0x100000>;
            interrupt-names = "vdu_host_interrupt2";
            xlnx,vdu = <&vdu_vdu_0>;
            compatible = "al,al5d";
            interrupt-parent = <&gic>;
            interrupts = <0x0 0x56 0x4>;
            memory-region = <0x557>;
    };
    al5d3: al5d@a4320000 {
            al,devicename = "allegroDecodeIP3";
            reg = <0x0 0xa4320000 0x0 0x100000>;
            interrupt-names = "vdu_host_interrupt3";
            xlnx,vdu = <&vdu_vdu_0>;
            compatible = "al,al5d";
            interrupt-parent = <&gic>;
            interrupts = <0x0 0x57 0x4>;
            memory-region = <0x558>;
    };
    
  9. Convert the updated source back to dtbo:

    $ dtc -I dts -O dtb -o vek280-pl-vdu-fw.dtbo temp.dtso
    
  10. Remove the temporary dts file:

    $ rm -rf temp.dtso
    

    Run the docker container again (as in the previous step) and continue with the following steps.

  11. From inside the container, load the VDU firmware package:

    $ dfx-mgr-client -loadByName vek280-pl-vdu-fw
    

    Verify that the firmware package is loaded successfully by re-running dfx-mgr-client -listPackage.

  12. Run the VDU 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 VDU 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 vek280-pl-vdu-fw

References