Showing results for 
Show  only  | Search instead for 
Did you mean: 

Exploring Python on Zynq UltraScale

Xilinx Employee
Xilinx Employee
4 2 1,892

Python is one of the most common programming languages used today. This is because it is a highly productive, easily deployed, and intuitive language. Also, due to its popularity there are many shared packages that other users can avail of.

This tutorial will show you how to easily get up and running in Python on the ZCU104 Development board.

Users need to have all of the required packages when building the filesystem. They are not listed here as users will have a better idea of what packages are needed for their own application. 

As we are ultimately targeting an embeddedsw system, one of the more practical use-cases is to access the memory/peripheral of the embeddedsw system. Here, we can use the mmap packages to open /dev/mem and gain access. We can then create our own packages here that can then be used across multiple applications or utilities.

We can also use packages such as subprocess to access the file system. I have used this to read the devicetree to see what IP are enabled and how they are configured. 

I have delivered a custom package that users can use as a reference to control the embedded system via python

Hardware Design:

The block design (BD) that is used in this demo can be seen below. I have used a ZCU104 board, but the flow here should be agnostic.


See here for more information on the embedded flow in Vivado 2020.1.

Adding Python support to a PetaLinux project

  • petalinux-create -t project --template zynqMP -n linux_image
  • cd <plnx proj>
  • petalinux-config --get-hw-description=<path to XSA>
    • DTG Settings -> (zcu104-revc) MACHINE_NAME
    • (See the link here for the full list of supported board .dtsi files)
  • petalinux-config -c kernel
    • kernel hacking → [] Filter access to /dev/mem
  • petalinux-config -c rootfs
    • Filesystem Packages → devel →python
      • python-mmap
      • python-shell
      • python-io
      • python-distutils
      • python-pydoc
    • Filesystem Packages → devel →python-numpy → [*] python-numpy
  • petalinux-build
  • cd images/linux
  • petalinux-package --boot --fpga system.bit --u-boot

Using /dev/mem from Python:

Once the Linux image has been created we can attempt to read and write to the peripherals in the hardware design. We can use /dev/mem which allows us physical access to the memory/registers. There is an mmap package in the Python that we will be using:




f ="/dev/mem", os.O_RDWR | os.O_SYNC)
mem = mmap.mmap(f, mmap.PAGESIZE, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE,offset=addr & ~MAP_MASK)




The addr in this case is the memory or register that we want to access.

Creating a Package:

If users want to add their functions to other applications, they can do so by creating a package (see attached).

I have created one such package that allows users to do the following:

  • read registers/memory
  • write register/memory
  • do system commands such as cat, ls, etc.
  • read mdio
  • get phy address
  • mii dump
  • read devicetree nodes
  • get devicetree properties
Using the package to read/write:




import mypackages.myutils as util
xx =




Using the package in a simple LED toggle application:

The example below can be used to toggle the AXI GPIO LEDs:




import mypackages.myutils as util
import time
import sys
def toggle_leds():
    util.write(0x80000000, 0x0)
    while True:
        for x in range(0, 8):
            util.write(0x80000000, x)
if __name__ ==  '__main__':




This will loop forever. Use Ctrl+ Z to stop it.

Using the package to read the MDIO:

Here we can read the PHY over the MDIO using the utilities:




import mypackages.myutils as util
#GEM address, phy address, offset
xx = util.read_mdio(0xff0e0034, 0x0c, 0x00000000)




Using the package to detect a valid PHY address:

Here, we can search for a valid PHY address:




import mypackages.myutils as util
xx = util.get_phy_addr(0xff0e0034)




Using the package to do an MII dump:

There is a mii_dump utility in the package that will search for any enabled GEM IP in the devicetree, auto-detect a valid PHY address, and dump the PHY registers:




import mypackages.myutils as util
xx = util.mii_dump()




Reading the devicetree nodes:

I have created a utility for reading the devicetree nodes in the kernel. This can be really useful when creating a design agnostic script as the user can create/use apps depending on the hardware.

For example, we can return all of the IP in the device tree:




import mypackages.myutils as util
xx = util.get_ip('all_ip')




We can also filter this search for all GEM that are enabled in the device tree:




import mypackages.myutils as util
xx = util.get_ip('ethernet', status='okay')




User can also just search for all device nodes that have the status set to okay:




import mypackages.myutils as util
xx = util.get_ip(status='okay')






One feature that would dramatically increase the value of Python running on Zynq is REPL: having an interactive shell to communicate with Python interpreter. A shell can be standard PuTTY over serial or ethernet link. Even MicroPython and CircuitPython distributions do have REPL.





Xilinx Employee
Xilinx Employee

Have you seen the pynq solution