Solution ZynqMP PL Programming

Introduction‍


The Zynq UltraScale+ MPSoC Programmable Logic (PL) can be programmed either using First Stage Boot-loader(FSBL), U-Boot or through Linux.
This page provides details about programming the PL from the Linux world using the Linux FPGA Manager framework.

Flow:


HW IP Features


  • Full Bitstream and Partial Bitstream loading
  • Encrypted and Authenticated Full/Partial Bitstream loading
  • Readback of Configuration Registers
  • Readback of Bitstream(Configuration Data)
  • Compressed Bitstream

Features supported in the driver

  • Full Bitstream Support 
    • Non Secure Bitstream
    • Encrypted  Bitstream
    • Authenticated Bitstream 
    • Authenticated and Encrypted Bitstream
    • Compressed Bitstream
    • Loading Bitstream using Devicetree overlay 
  • Partial Bitstream Support that doesn't require PL drivers 
    • Non Secure Partial Bitstream
    • Encrypted Partial Bitstream 
    • Authenticated Partial Bitstream 
    • Authenticated and Encrypted Partial Bitstream 
  • Readback 
    • Configuration Registers Readback
    • Configuration Data Readback 

Known Issues for PL Programming

A few considerations that users should be aware of in programming the PL/FPGA are as follows.

  • If the user tries to load the un-aligned bit/bin file the PL configuration takes a longer time when compared with aligned(word-aligned) bit/bin files.
  • If the design has AXI INTC IP, the PL configuration stress test may lead to the kernel crash due to the memory leak issues that exist with the AXI INT driver.
  • Using overlays we can add a new node or add/update the existing node properties. But it will not allow replacing the existing nodes which is already part of the live tree. 
  • If the PL design has axi-intc IP, the relevant DT node should be the top node in the overlay.dtsi or pl.dtsi file before it is actually being referenced in any other nodes.
    • Also, IRQCHIP Xilinx Intc driver module support must be enabled in the kernel configuration.
  • Apply overlay change sets will occur from top to bottom and Removal of overlay change sets will occur in the opposite order of apply(the most recently applied overlay change set must be removed first). So if the overlay has any internal dependency one on another those need to be taken care of while creating the overlay files. (Like: Interrupt controllers, clock nodes.....etc).
  • The existing Overlay fame-work allows the removal of overlay' only if it's the top-most one. So please follow the LIFO order to remove overlays from live tree.

Example DT node.

/dts-v1/;
/plugin/;
/ {
	fragment@0 {
		target = <&fpga_full>;
		overlay0: __overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			firmware-name = "system.bin";
			resets = <&zynqmp_reset 116>;
		};
	};
	fragment@1 {
		target = <&amba>;
		overlay1: __overlay__ {
			afi0: afi0 {
				compatible = "xlnx,afi-fpga";
				config-afi = < 0 0>, <1 0>, <2 0>, <3 0>, <4 0>, <5 0>, <6 0>, <7 0>, <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0xa00>, <15 0x000>;
			};
		};
	};
	fragment@2 {
		target = <&amba>;
		overlay2: __overlay__ {
			#address-cells = <2>;
			#size-cells = <2>;
			axi_intc_1: interrupt-controller@a00d0000 { /* Top node */
				#interrupt-cells = <2>;
				clock-names = "s_axi_aclk";
				clocks = <&clk_wiz_0 0>;
				compatible = "xlnx,axi-intc-4.1", "xlnx,xps-intc-1.00.a";
				interrupt-controller ;
				interrupt-names = "irq";
				interrupt-parent = <&axi_intc_0>;
				interrupts = <1 2>;
				reg = <0x0 0xa00d0000 0x0 0x10000>;
				xlnx,kind-of-intr = <0x360>;
				xlnx,num-intr-inputs = <0xe>;
			};
			axi_iic_0: i2c@a0000000 {
				#address-cells = <1>;
				#size-cells = <0>;
				clock-names = "s_axi_aclk";
				clocks = <&clk_wiz_0 0>;
				compatible = "xlnx,axi-iic-2.1", "xlnx,xps-iic-2.00.a";
				interrupt-names = "iic2intc_irpt";
				interrupt-parent = <&gic>;
				interrupts = <0 91 4>;
				reg = <0x0 0xa0000000 0x0 0x1000>;
			};
			axi_iic_1: i2c@a0008000 {
				#address-cells = <1>;
				#size-cells = <0>;
				clock-names = "s_axi_aclk";
				clocks = <&clk_wiz_0 0>;
				compatible = "xlnx,axi-iic-2.1", "xlnx,xps-iic-2.00.a";
				interrupt-names = "iic2intc_irpt";
				interrupt-parent = <&axi_intc_1>;
				interrupts = <1 2>;
				reg = <0x0 0xa0008000 0x0 0x1000>;
			};
		};
	};
};


Summary Table for Partial Reconfiguration / Dynamic Function Exchange Feature Support

Partial Reconfiguration / Dynamic Function Exchange (DFX) is an advanced feature of Xilinx Zynq UltraScale+ MPSoC devices.  Refer to the table below for details.  For PetaLinux releases prior to 2018.3 or for building Linux system images manually, please refer to the Linux OSL Flow page.

Release \ FeatureVivado RTL Design FlowVivado IPI Design FlowLinux Device Tree GeneratorLinux Programming Framework
<= 2018.3SupportedNot SupportedAutomation Not Supported - Hand CraftedFPGA Manager
2019.1 - 2020.2SupportedDFX LoungeDFX LoungeFPGA Manager / fpgautil






Kernel Configuration

The following config options have to be enabled in order to use FPGA Manager, Please note that these options are enabled by default through xilinx_zynqmp_defconfig except for the fpga debugfs option. If the user wants to test the readback feature they have to enable it.

Zynq UltraScale+ MPSoC FPGA Manager Configuration:

Select: Device Drivers → FPGA Configuration Framework →   Xilinx Zynq UltraScale+ MPSoC FPGA 

In order to test readback feature user needs to enable FPGA debug fs 

Select: Device Drivers →  FPGA Configuration Framework -->   FPGA debug fs 



DT overlay ConfigFS Interface Configuration:
In order to load Bitstream with DTBO user needs to enable the below options

Select: Device Drivers --> Device Tree and Open Firmware support


Contiguous Memory Allocator Configuration:

CONFIG_CMA

Select: Kernel Features --> Contiguous Memory Allocator

CONFIG_DMA_CMA

Select: Device Drivers --> Generic Driver Options → DMA Contiguous Memory Allocator 


Devicetree

pcap {
       compatible = "xlnx,zynqmp-pcap-fpga";
       clocks = <&clk 41>;
};

fpga_full: fpga-full {
       compatible = "fpga-region";
       fpga-mgr = <&pcap>;
       #address-cells = <2>;
       #size-cells = <2>;
	   power-domains = <&zynqmp_firmware PL_PD>;
};


For more details about  devicetree bindings Reference the Below link: Devicetree

Note: The above devicetree node is by default present in the zynqmp.dtsi file

Bitstream Format

From the 2018.3 release onwards FPGA Manager supports loading of vivado and bootgen generated Bitstream and Bin files vivadobootgen[1]

Note: For releases earlier to 2018.3 FPGA Manager was capable of loading only bootgen generated bin files. bootgen

 .Bit Format 

  • Generated by Vivado 

 .Bin Format

  • Generated by Vivado 
  • Generated by Bootgen by converting vivado generated bit file
    Bootgen Command to generate bin file:
    # bootgen -image Bitstream.bif -arch zynqmp -o ./Bitstream.bin -w (2018.1 or later releases)
    # bootgen -image Bitstream.bif -arch zynqmp -process_Bitstream bin (2017.4 and earlier releases)
    Bitstream.bif file should contains the below lines:
all:
{
        [destination_device = pl] Full.bit (or)  Partial.bit /* Bitstream file name */
}

Building Software Images

Xilinx tools (Petalinux, Yocto) provide an option with the name FPGA Manager which if enabled builds the device tree overlay fragments automatically and copies the Bitstream and DTBO files into root file system. 

PetaLinux Flow

 PetaLinux setup and build:  PetaLinux

  1. Source the PetaLinux tool.source /opt/petalinux/petalinux-v<petalinux-version>/settings.sh
  2. Create a Versal template project or bsp project.
    petalinux-create -t project -n zynqmp-dfx  --template versal
    petalinux-create -t project -s <bsp path> -n zynqmp-dfx