The MicroZed is an FPGA developement board with a Zynq-7000 FPGA. The Zynq-7000 is a complete SoC system from Xilinx that contains a FPGA fabric and several ARM cores. The FPGA fabric is referred to as a Processing Logic (PL) and the ARM core is the Processing System (PS). The PS allows one to run programs ranging from simple software programs to a full-blown Linux distribution. PetaLinux is a Linux distribution aimed at such embeded system maintained by Xilinx. This tutorial gives an example that covers:
The instructions should be largely independent of the version of the Xilinx tools used. For reference, version 2017.4 was used to write this tutorial.
Use the Create Project item in the Vivado Quick Start launcher to create a new project.
The New Project wizard window will pop-up. The first page will inform you that you are creating a new project. Click Next to start filling out the need information.
The second page will ask you to fill-out a project name and location. The example project will be called petazed. The location is where the project directory will be created. If you plan to share IP cores among several Vivado projects (ie: different FPGA boards), the location should be the directory that contains them.
The third page will ask you to fill out the project type. Specify "RTL Project". Also "Do not specify sources at this time." should be checked.
The fourth page will ask you to specify the target FPGA. This example uses the MicroZed 7020 Board. It can be found under the Boards tab. Selecting the Vendor filter to em.avnet.com will help in locating it. If you do not see it, make sure that you have installed the MicroZed board definition files.
The last page is the summary. Review the information and click Finish to create the project.
This section outlines how to add a Zynq-7000 Processing System IP Core to a Vivado project. It is the bare minimum to run Linux (or a simple software block) on the FPGA.
The Vivado IDE will now open with the project definition. The default target language is Verilog. If you prefer VHDL, change it via the Target language link.
To create a top level entity, use the Create Block Design link found under the IP Integrator section of the left-hand toolbar. Give the entity a name (ie: TopLevel).
Use the + button in the Diagram section to add the ZYNQ7 Processing System IP core. This represents the ARM core on the FPGA.
Use the Run Block Automation to auto-configure the PS and create all external connections.
Use the default settings in the window that will pop up. Notably, Apply board presets should be checked.
Create the VHDL Wrapper by going into the Sources section of the Block Design and right-clicking on the TopLevel entity. In the pop-up window, make sure that Let Vivado manage wrapper and auto-update to cause Vivado auto-update the wrapper anytime you add a new IP Core block.
The resulting project can now be compiled and results in firmware that can run Linux on the Zynq FPGA. The next steps add a custom IP Core block that implement use-functionality in the Processing Logic.
This section outlines how to enable AXI support in the Zynq PS IP block and create a custom IP Core with a dummy read/write AXI registers.
First enable AXI support inside the Zynq PS IP Core by double-clicking on its block to start the IP re-customization wizard. AXI support can be unabled by checking the M AXI GP0 interface found under the PS-PL Configuration tab. This enables a master AXI block in the Processing System that can be used to control AXI slaves. Click OK to apply the changes.
Create a custom slave AXI IP Core by using the Create and Package New IP... tool found under the Tools window menu. A wizard will pop-up with the first page telling you that you started the tool. Click Next to move on.
Select the Create a new AXI4 peripheral. checkbox to create a new AXI4 slave.
Name the IP Core and set its location. This example uses axihelloworld for the name. By default, the location is a directory called ip_repo located one up from the Vivado project. Storing the IP Core outside of the Vivado project is recommended if you plan to share it among several projects. You should always plan to do this!
Next configure the AXI registers generated for the core. By default, you will be given 4 registers, each containing a 32-bit word. Keep the defaults for this example.
The last page is the summary. Check that you settings are correct and click Finish to create the IP Core!
Add the axihelloworld IP to the TopLevel block design using the + button.
Use the Run Connection Automation helper tool to automatically connect the axihelloworld block to the Zynq Processing System block.
The default settings in the Run Connection Automation wizard can be used.
The assigned addresses of the AXI registers can be checked (and edited) in the Address Editor tab of the block design. The Offset Address columns gives the address of the first register, with the subsequent registers being sequential. The example IP address space starts at 0x43C00000.
The firmware project is now complete! You can prepare the .bit file containing the firmware bistream via the Generate Bitstream link at the bottom of the left-hand sidebar. You can use the default answers in the resulting dialog windows.
Export the hardware definition files. This is used by the software compiler to pick the right configuration for your device. The tool is found under File > Export > Export Hardware.... In the resulting dialog, choose to Include bitstream in the export. This makes it easier to find the firmware bitsream by the PetaLinux tools. The resulting definition is located inside petazed/petazed.sdk/.
You can now close the Vivado project.
The PetaLinux project is created, configured and build using several command line tools. They are available once the PetaLinux installation settings.sh is sourced.
A PetaLinux project is associated with the hardware definition exported from the Vivado project. Thus the two are closely tied and should be stored in the same directory. To create a PetaLinux project, run the following command inside the petazed Vivado project directory.
petalinux-create -t project -n petazed.linux --template zynq
It creates a PetaLinux project called petazed.linux using the zynq
template. A zynqMP
template is also available for a multi-core configuration, but it does not seem to compile. There is also a microblaze
template for firmware implemeting the MicroBlaze processor instead of a Zynq.
The petalinux-configure
tool should be run next to configure the hardware specific part. It takes the Hardware Definition exported from Vivado as an argument.
petalinux-config -p petazed.linux/ --get-hw-description petazed.sdk/
A Linux kernel menuconfig-style tool will pop-up that allows one to further configure the compilation of the PetaLinux project. The default settings can be accepted by using the Exit button.
The configuration of the PetaLinux distribution can only be changed via the PetaLinux tools. This section shows how to change the root password and enable the peekpoke
application.
Use the petalinux-config
tool to configure the rootfs component. This will launch a Linux kernel menuconfig-style tool.
petalinux-config -p petazed.linux/ -c rootfs
To change the root password, change the following menu entry.
PetaLinux RootFS Settings --->
(root) Root password
To enable the peekpoke
application, used to test simple AXI register read/writes, enable the following menu entry.
apps --->
[*] peekpoke
Several useful Linux programs can also be included through the Filesystem Packages section. For example, it is useful to include a text editor. PetaLinux does not come with emacs, but vim is a (barely) good replacement. It can be enabled under the following menu entry.
Filesystem Packages --->
console --->
utils --->
vim --->
[*] vim
[*] vim-syntax
A fully configured PetaLinux project can be built usign the petalinux-build
tool.
petalinux-build -p petazed.linux/
The first use will take a while, because all of the requested packages need to be build from scratch.
The resulting binaries can be found inside petazed.linux/images/linux
. This includes the firmware bistream, first stage boot-loader, u-boot and the root filesystem image. The bootloaders can be turned into a simple package using the petalinux-package
tool.
petalinux-package -p petazed.linux/ --boot --fpga petazed.linux/images/linux/TopLevel_wrapper.bit --fsbl petazed.linux/images/linux/zynq_fsbl.elf --u-boot -o petazed.linux/images/linux/BOOT.bin
The resulting PetaLinux distribution can be booted from an MicroSD card inserted into the MicroZed board. The SD card should have the first partition formatted usign the FAT32 filesystem. The following files should be copied there:
BOOT.bin
image.ub
The SD card should then be inserted into the MicroSD slot in the MicroZed board. It is located near the USB connector. This should be done while the MicroZed has no power.
The boot pin-connectors should be put indo SD Card mode. They are located close beside the USB connector .
The MicroZed should be connected to a PC using a USB to microUSB cable. Use the dmesg
tool to see what device the MicroZed is associated with. In this case, the MicroZed is located at /dev/ttyUSB2
.
[kkrizka@carl-pc petazed]$ dmesg | grep cp210
[17460.715851] usb 1-1.4: cp210x converter now attached to ttyUSB2
Start a serial console program (ie: screen
) connected to the device.
screen /dev/ttyUSB2 115200
Reset the MicroZed using the RST button.
See Linux bootup in the screen
program. You can login using the root
user and password set during rootfs
configuration.
The default PetaLinux rootfs image is unpacked into temporary memory. The downside of this approach is that any modifications will not be pernament. This can be solved by having a second, large, partition on the SD card formatted with ext4 to store the root file system. The PetaLinux project can be configured to generate an tarball with rootfs by running petalinux-config
and making sure that the following is enabled.
Image Packaging Configuration --->
Root filesystem type (SD card) --->
(/dev/mmcblk0p2) Device node of SD device
If custom boot arguments are used, make sure to add the root=/dev/mmcblk0p2
argument. The /dev/mmcblk0p2
should be replaced with the partition where the root image will be stored.
Rebuild the PetaLinux project and create a new package.
petalinux-build -p petazed.linux/
petalinux-package -p petazed.linux/ --boot --fpga petazed.linux/images/linux/TopLevel_wrapper.bit --fsbl petazed.linux/images/linux/zynq_fsbl.elf --u-boot -o petazed.linux/images/linux/BOOT.bin
You need to unpack the contents of rootfs.tar.bz2
on the ext4 partition. You can find the tarball inside the petazed.linux/images/linux
directory, alonside BOOT.bin
and image.ub
. Those two files still need to be copied to FAT partition,.
You can store the file system on a remote computer and boot via network. The advantage here is that you have a more reliable pernament storage than an SD card. Also it allows you to cross-compile your test programs on a more powerful PC. You will still have to copy the image.ub
and BOOT.bin
to an SD card. However the image now only contains the basic kernel needed to initialize the network boot procedure. This documentation assumes that you are already familiar how to setup an NFS server.
The first step is to tell petalinux-config
that the file system will be stored on NFS. The v4
after the address is needed if your NFS server is using NFSv4.
Image Packaging Configuration --->
Root filesystem type (NFS) --->
(/path/to/rootfs/onremote) Location of NFS root directory
(nfsserveraddress.com,v4) NFS Server IP address
Then add NFSv4 support to the PetaLinux kernel by running petalinux-config -p petazed.linux -c kernel
and making sure the following is enabled.
File systems --->
[*] Network File Systems --->
<*> NFS client support
<*> NFS client support for NFS version 4
[*] NFS client support for NFSv4.1
[*] NFS client support for NFSv4.2
Makre sure to build and package everything after running the abvoe steps
Finally you need to unpack the contents of rootfs.tar.bz2
on the NFS server at /path/to/rootfs/onremote
. You can find the tarball inside the petazed.linux/images/linux
directory, alonside BOOT.bin
and image.ub
. Those two files still need to be copied to a FAT partition on the SD card.
Tip: You can mount the NFS file system on your local PC. This allows you to inspect and edit files using tools not readily available on PetaLinux. If you plan to do this, make sure that the uid of your MicroZed user matches that of your local user. This will prevent issues with access permissions.
A big advantage of using NFS-mounted file system is the abilty to develop your applications on a computer that is not the MicroZed. This allows you to develop your application using tools not necessarily available on the MicroZed and use a more powerful processor to speed up the compilation. The computer used for developement does not necessarily have to be the NFS server nor does it require that you boot using NFS. However storing the code and compilation products directly on NFS is very useful as it makes them automatically available on your MicroZed for testing.
There are two ingredients necessary for cross-compilation; the compiler that can output ARM binaries and a copy of your PetaLinux file system containing the developement version of all your dependencies. This file system does not have to be the same as the one used during production.
Start by installing the Xilinx SDK. The cross-compilers for the MicroZed can then be found at {PATHTOSDK}/{SDKVERSION}/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin
.
Next enable the packagegroup-core-buildessential
package and any dependencies in your PetaLinux project. The packagegroup-core-buildessential
contains all of the low level libraries and headers necessary for compiling a Linux application. It will also install a compiler that can be used on your MicroZed, but will not be used here. This package can be enabled by running petalinux-config -c rootfs
. Do not forget to build and package your project after completing this step.
Filesystem Packages --->
misc --->
packagegroup-core-buildessential --->
[*] packagegroup-core-buildessential
You can now cross-compile your application using the following example command:
{PATHTOSDK}/{SDKVERSION}/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-g++ main.cpp -o testapp --sysroot=/path/to/nfs
If your project is compiled using CMake, you can use the xilinx toolchain definition file: xilinx.cmake. It takes the following options
XILINX_SDK_PATH
: path to the installed SDK (default: /opt/Xilinx/SDK/2019.1
)ROOTFS_PATH
: path to the root file system (default: blank)More details on how to use it can be found in the CMake documentation on cross-compiling. But the summary is to use the following command when generating your build scripts:
cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/xilinx.cmake
Try the following commands after you have booted the PetaLinux distribution and can control it using the serial console (or ssh).
Use the peekpoke
program to write and read from the AXI registers in the axihelloworld
entity.
root@petazed:~# poke 0x43C00000 0xDEADBEA7
root@petazed:~# peek 0x43C00000
0xdeadbea7
root@petazed:~# peek 0x43C00004
0x00000000