PYNQ Linux on ZedBoard

Hi There!

The PYNQ Linux is a fun, easy and maker-friendly Ubuntu 15.04 rootfs. It comes bundled with the PYNQ-Z1 board, and the official documentations doesn’t even utter a word on how to build or port this image on any other Zynq. Maybe because it’s too obvious how to do so.

What you need to run Linux on any ARM board?

  1. BOOT image (BOOT.bin)
  2. kernel image (uImage)
  3. devicetree blob (devicetree.dtb)
  4. rootfs

What we need to worry about? everything but the rootfs.


Write the image file on SD card same as in the pynq tutorial, and replace the files in BOOT partition with these… ZedBoard BOOT files


use older image of pynq from here

Detailed Explanation (as if you asked for it)

0. Set up environment.

You’ll obviously need to do this all a Desktop Linux system. I’ve tried doing onWindows, doesn’t work well with MinGW. Haven’t tried CygWin or Linux Subsystem for Windows, you may give it a try if you’re brave enough.

0.1 Set up the Bash environment to work with Xilinx SDK tools,


For latest SDK version 2017.3 the cross compiler is arm-linux-gnueabihf-gcc.

0.2 SD Card Patitioning

you don’t really need to create partitions of the SD card because loading the image file from the PYNQ linux will do that for you, however you can do it anyways which should look like… (Use GParted or something)


  • Type: fat32
  • Free Space Preceding: 4MB (IMPORTANT!!!)
  • Size: 52MB
  • Label: BOOT (Optional)


  • Type: ext4
  • Size: whatever is left
  • Label: rootfs (Optional)


  • DO NOT REMOVE SD CARD WITHOUT UNMOUNTING IT! Really, don’t. It creates badblocks in the SD card which might cause issues booting up the Zynq.
  • You can check my GitHub @parthpower for the modified u-boot and Linux codes to work around this.

1. Make BOOT.bin

-> To create BOOT.bin, you’ll need 3 things (which you’d have heard everywhere).

  1. First Stage Bootloader to dump the bitstream and call the second stage bootloader
  2. bitstream
  3. Second Stage Bootloader (u-boot.elf)

I’m not going in details of first two things, as they are simple and you can just google them… Come on now! Ok, in short, make Vivado project with only PS, export it to the SDK, create FSLB application project and you’re good!

Let’s get to the main part, MAKING u-boot.elf!!!!

Clone the Xilinx UBoot repo from the Xilinx github, checkout to the latest stable release (I used xilinx-v2016.4) (in case you need code)

Now, you got to change some stuff in u-boot-xlnx/include/configs/zynq-common.h, find this line “sdboot=if mmcinfo;” and make it look like as below


Wait, what did we just messed with? Like what the hell happened?

If you go through the “Ubuntu on ZedBoard” tutorial by Avnet, they explain it’s for using the rootfs from the filesystem instead of a RAM disk.

To make u-boot,

You should add u-boot-xlnx/tools to the PATH. It’ll be useful making the Linux Image later on.

Get the “u-boot” file from the root of the u-boot source directory, rename it to u-boot.elf. Now just make the BOOT.bin, open “Create Boot Image” in SDK use the FSBL.elf, bit file and the u-boot.elf. Mind the order of the files because that’s how the Zynq will be booted. FSBL configures the PL with the bit file then loads the second stage bootloader; u-boot.


2. Make Linux Kernel Image

The Linux Kernel Image is the actual Kernel being loaded by the u-boot and which has the rootfs of pynq distribution. In less technical words, Linux Kernel is the base system which loads the higher-level root filesystem from the mount point. Now we’re done with the theory part, Let’s make the kernel!

Fetch the sources,

Just default config, and make it!

That’s it and you have your Linux kernel image ready at linux-xlnx/arch/arm/boot/uImage save it somewhere safe.

3. Device Tree Blob

What? Device tree blob is a “block-of-binary” which specifies memory location of the peripherals, their compatible driver names, and some configurations of the peripherals. It’s lots of information about the hardware specification of the SoC.

The dtb is compiled from dts (device tree string). For a PS-only design, the dts is already there in the linux-xlnx repository at /linux-xlnx/arch/arm/boot/dts/zynq-zed.dts

We need to modify it a little bit to load the rootfs, (yeah, lots of efforts just to load the rootfs)

find the line starting with bootargs and change it to,

By default, it has bootargs are set to load the rootfs from a ramdisk. But we configured the u-boot not to load the rootfs as ramdisk. So we are mounting it from /dev/mmcblk0p2 (partition 2 of the memory card)

Now go to the root of linux-xlnx and

and you have the dtb file at  /linux-xlnx/arch/arm/boot/dts/zynq-zed.dtb rename it to devicetree.dtb and copy it somewhere safe.

4. rootfs

The root file system we want to use if the one provided by the PYNQ. Download the latest version from // Extract it, and write the image to the sd card. Use dd or Win32DiskImage tool or whatever you wish.


The latest PYNQ distribution has kernel v4.6. You can use older image from,

Mount the SD card, look into the BOOT partition, replace all the files, BOOT.bin, uImage, devicetree.dtb with the ones we’ve created, and you’re done. Seriously, you’re done!

Good thing is, you can put any Linux distribution as long as it is made up on Linux Kernel 3.17 in the rootfs file system and it should work. I tried Linaro , it quite didn’t work well with me. Try playing around, let me know what works and what don’t work!

Happy Hacking!

Some Really Good References,






  1. PYNQ has recently updated their repository and included instructions to make sd card image section.  Thanks to Cathal McCabe for this update.

13 thoughts on “PYNQ Linux on ZedBoard”

  1. Hi, what a great idea. I followed your hints and it worked well. Then i modified the pynq block design, the constraint file and the devicetree and now I can run pmod examples (ie. pmod_ad1, spi) on the zedboard with jupyter notebook. That’s fun!
    Best regards, Andreas

  2. Hi, I followed your tutorial but i cant get it to work.

    I have used your prebuild boot files and it works.. no problem with the PYNQ 1.4 and 2.0 Rootfs.

    But if I build it by my own it always freezes after boot up. The kernel itself is fine, i tested it with your Boot binary and devicetree. I am able to boot the system with your boot.bin and my devicetree but get some strange errors about cpu_freq. cant be changed and other stuff. I guess that is also because the bitsream in in the boot.bin is not the right one….

    I expect the Boot.bin to be the root of the problem and to specific the bitstream since i am able to successfully initialize the PS via FSBL and u-boot is also working.

    You suggested to make a vivado project just with the PS7. I have done this, connected the clock and run the automation to connect the necessary things. I still think that my bitstream is the problem so could you share your vivado steps maybe?

    My final goal is to port it to another zynq platform:


  3. It was the boot_leds script that crashed the system.

    I have mounted the rootfs, searched for boot_leds and deleted the .service from the systemd directory and the .sh from the bin folder.

    it works now….

    1. Good to know! Keep us posted for updates. Link your project if you wish. Sorry for the vivado project, I simply used the PS with default config. nothing else at all! Just check if UART is ticked.

      1. In the end I went with petalinux to create the bootloader, device tree and kernel image. I used the following tutorial:

        I then created the PYNQ SD with dd and then removed all files from the BOOT partition and placed the following from the petalinux image folder in it:
        BOOT.bin (Bootloader)
        image.ub (Kernel)
        system.dtb (Device Tree)

        Then I removed the boot_leds file from the ROOTFS (like described above).

        I still get a lot of errors when using yupiter. I guess I have to make more changes to the FPGA in vivado but I have it at least running now.

Leave a Reply

Your email address will not be published. Required fields are marked *