Skip to main content

FPGA Zero to Hero Vol 5 EBAZ4205 Chronicles

·2697 words·13 mins· loading ·
Table of Contents

FPGA Zero to Hero Vol 5 EBAZ4205 Chronicles
#

In my previous blog Link I created a basic Verilog module and used the JTAG to test it. It was great demonstration for testing the board but first I did not fully utilized the powerful Zync FPGA and second I glossed over many details. I will fix that in this blog. As I told you that this board had multiple quirks and need some soldering work to use all the features. I will discuss some of the hardware changes needed to use it to its full potential. Also depending on the seller you might be missing some components and you need to change the software accordingly. In this blog post I will cover only hardware tweaks, FPGA Software to run Linux and Petalinux configuration and compilation to boot up the Linux.

NOTE: My current system configuration is:

  • OS: Ubuntu 22.04
  • VIVADO Version: Vivado v2024.2 (64-bit)
  • PETALINUX Version: Petalinux 2024.2

So if you are using any other version then everything described here might or might not work. Also there are some changes from Petalinux older version to current 2024.2 version. So you might need to different commands if you are using older version .

Hardware
#

  1. Powering the Board: Powering this board is not as easy as it seems to be as some of the components lik Diode D24 is missing from most board. If you have this Diode mounted on the board then you can use J4 connector to power the board else you need to use 12v and GND pins on port marked DATA1 or DATA2 or DATA3.
Power
  1. SD Card Boot: By default most boards come with NAND FLash boot config registers. You need to check the Resister R2577 and Resistor R2584. If the resistor R2584 is present and resistor 2577 is not present then the hardware is configured to boot from NAND. You need to remove resistor R2584 and solder it on silkscreen marked with resistor R2577.

The configuration is done using resistors combination and can be checked in schematic as shown below:

Schematic

Shown above in the schematic is config for NAND, SD and JTAG boot. That is MIO5 that is Multiplexed Input/Output 5 connected to GND and MIO4 that is Multiplexed Input/Output 4 connected to VCC. To configure boot from SD Card we need to connect both MIOs to VCC.

EBAZ4205

Vivado HW Description and Synthesis
#

From my last blog you already know how to create a new project. We will use it as base for our further development. We need to configure the Xilinx® Integrated PS (Processing System) to use the Ethernet, DRAM and other Peripherals.

Enable Ethernet PHY
#

EBAZ4205 uses IP101GA chip as Ehernet PHY. See schematic. In the schematic you can see the Xilinx IO ports that are connected to the PYH. Shown below is part of PHY pins and its connections to Xilinx IO:

PHY

Now we will continue to connect the PHY to the Vivado® Ethernet IP in the Xilinx® Vivado® Design Software. Double click on Zynq7 Processing System IP and it should open Re-customize IP following window:

Zynq1

As you can see the Ethernet PHY is connected to EMIO. In Xilinx’s Zynq UltraScale+ devices, EMIO (Extended Multiplexed I/O) refers to a set of I/O pins on the Processing System (PS) that can be routed to the Programmable Logic (PL) for extended peripheral access. EMIO provides a way to connect peripherals to the PS when the number of available MIO pins is insufficient. More Details Link

Now as the ports are routed through EMIO we need to connect them in the constraints file and also create ports both RX & TX from and to IP101GA. To create a port on Vivado block design Right click and Create a port/bus as shown below:

Port creation

For clock you should define it as Clock for input clock port as shown below:

Port Clk

But there is a catch in the software side that needs to be considered. The catch is GMII interface is has 8 bit wide bus for both RX and TX but the chip IP101GA supports only 4 bit wide RX and TX. So we use only lower 4 bits of the GMII Interface. That means this chip doesnt support full bandwidth of GMII interface: Read more here. To use lower nibble of the port we need to use Slice and Concat IP blocks provided by Vivado.

From Ethernet PS IP i.e. ENET0_GMII_TXD[7:0] we need to reduce the number of ports so we use Slice IP. Right click on the block diagram. Add IP and search for Slice. Configure the IP as shown below:

Slice

Similarly for the ENET0_GMII_RXD[7:0] expects 8 bit bus input so we use Concat to make 4 bit RX input into a 8 bit bus as shown below:

Concat

Now as I told you this board has some quirks. One of it is the Crystal Occilator for the Ethernet PHY. In some boars the two capacitors are missing and the Zynq PL is used to create the Clock Signal. You can easily create a clock out as described in my previous blog. We need 25 MHz clock for the PHY

Clock

Finally the complete design should look something like shown below:

Complete

Enable SD card and UART
#

To enable SD card and UART we need to select SD0 and UART1 and select the appropriate GPIO Numbers which should match the Hardware connection as described in Schematic.

Zynq2

Enable DDR3 controller
#

Select the MT41K128M16 HA-15E Memory part to configure the DRAM

RAM

Create a constraints file
#

We now need to create the constraints file that maps all the Output and Input soft ports to the real GPIOs on the Zynq Chip. The process was described in my earlier blog. I will just provide the contraints file this time.

# Clocks
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports FCLK_CLK3_0]
set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports CLOCK_OUT]

# Ethernet GMII clocks
set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports ENET0_GMII_RX_CLK_0]
set_property -dict {PACKAGE_PIN U15 IOSTANDARD LVCMOS33} [get_ports ENET0_GMII_TX_CLK_0]

# Ethernet GMII RX data[3:0]
set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_rxd[3]}]
set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_rxd[2]}]
set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_rxd[1]}]
set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_rxd[0]}]

# Ethernet GMII RX_DV
set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports ENET0_GMII_RX_DV_0]

# Ethernet GMII TX enable + data[3:0]
set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports ENET0_GMII_TX_EN_0]
set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_txd[3]}]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_txd[2]}]
set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_txd[1]}]
set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {enet0_gmii_txd[0]}]

# MDIO interface
set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports MDIO_ETHERNET_0_0_mdc]
set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports MDIO_ETHERNET_0_0_mdio_io]

# LEDs
set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {LED[1]}]
set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports {LED[0]}]

With this we are ready for our Petalinux build just Run Synthesis , Run Implemention and Generate Bitstream.

Go to File -> Export -> Export Hardware -> Include bitstream.

This will generate design file with .xsa extension that Petalinux can use to configure the Device Tree

Petalinux configuration and Compilation
#

Once we have the design we can use it to configure the Petalinux.

Installing Petalinux
#

Here is the complete guide to install Petalinux by Xilinx with troubleshooting Link

Once you have installed Petalinux you can source the toolchain setting script from the folder using following command considering you installed it in your HOME folder under /xilinx/petalinux

source ~/xilinx/petalinux/setting.sh

This should have following output on terminal

PetaLinux environment set to '/home/phnx/xilinx/petalinux'
[WARNING] This is not a supported OS
[INFO] Checking free disk space
[INFO] Checking installed tools
[INFO] Checking installed development libraries
[INFO] Checking network and other services
[WARNING] No tftp server found - please refer to "UG1144 2024.2 PetaLinux Tools Documentation Reference Guide" for its impact and solution

Creating a New Project
#

A new petalinux project for Zynq series of FPGA can be created using following command on terminal

petalinux-create -t project --name ebaz4205 --template zynq

This should show following output on terminal:

[INFO] Create project: ebaz4205
[INFO] New project successfully created in /home/phnx/projects/petalinux/ebaz4205

Configuring Project with Design file for first time
#

Use following command to configure the Petalinux project for the first time.

cd ebaz4205
petalinux-config --get-hw-description=/home/YOUR_USERNAME/ebaz4205

Note: The path is where you exported the .xsa file. I have created the project in my ~/ebaz4205 folder in my HOME folder path.

In my case I run

petalinux-config --get-hw-description=/home/phnx/ebaz4205

This should open a configuration menuconfig window like shown below:

config

Now we need to configure a very important parameter in u-boot Configuration. As we have only 256 MB of DDR RAM we need to configure our u-boot such that it search for the Linux Kernel Image within this RAM space but by default its set to way higher the RAM address. You can set a lower RAM address by setting following config::

u-boot Configuration  --->
        u-boot script configuration  --->
                JTAG/DDR image offsets  --->
                        (0x10000000) Fit image offset

As you can see it is currently set to way above 256 MB address space. We need to set it to 0x06000000. <Select> the (0x10000000) Fit image offset and Se it to (0x06000000) Fit image offset. After the change it should look like this:

u-boot Configuration  --->
        u-boot script configuration  --->
                JTAG/DDR image offsets  --->
                        (0x100000) Devicetree offset
                        (0x200000) Kernel offset
                        (0x4000000) Ramdisk image offset
                        (0x6000000) Fit image offset
                        (0x3000000) Boot script offset

Another configuration that we need to change at this point is Image Packaging Configuration ---> Root filesystem type

This need to be changed to SD Card

Image Packaging Configuration  --->
        Root filesystem type (INITRAMFS)  --->  
              ( ) INITRAMFS                               
              ( ) INITRD                   
              ( ) UBI/UBIFS                
              ( ) NFS                      
              (X) EXT4 (SD/eMMC/SATA/USB)
              ( ) other

Configuring the u-boot
#

This is the first component that you need to run a linux embedded system. It is a bootloader that is used to load the Linux kernel.

To configure the u-boot bootloader we need to run following

petalinux-config -c u-boot

But it seems there is a bug in the build system for verisons Petalinux 2024.1 that I am using and the configuration fails at parsing the device tree system.dtsi* file. This might lead to failed build like shown below:

petalinux-config -c u-boot
[INFO] Bitbake is not available, some functionality may be reduced.
[INFO] Using HW file: /home/phnx/projects/petalinux/ebaz4205/project-spec/hw-description/system.xsa
[INFO] Getting Platform info from HW file
[INFO] Silentconfig project
[INFO] Silentconfig rootfs
[INFO] Generating configuration files
[INFO] Generating workspace directory
NOTE: Starting bitbake server...
...
...
ERROR: device-tree-xilinx-v2024.2+git-r0 do_compile: Error executing a python function in exec_func_python() autogenerated:
...
File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
     0001:
 *** 0002:devicetree_do_compile(d)
...
...
     0573:    return CompletedProcess(process.args, retcode, stdout, stderr)
...
...
Subprocess output:
Error: /home/phnx/projects/petalinux/ebaz4205/components/plnx_workspace/device-tree/device-tree/system-conf.dtsi:25.1-12 Label or path ps7_nand_0 not found
FATAL ERROR: Syntax error parsing input tree

ERROR: Logfile of failure stored in: /home/phnx/projects/petalinux/ebaz4205/build/tmp/work/
...
NOTE: Tasks Summary: Attempted 945 tasks of which 889 didn't need to be rerun and 1 failed.

Summary: 1 task failed:
  /home/phnx/projects/petalinux/ebaz4205/components/yocto/layers/meta-xilinx/meta-xilinx-core/recipes-bsp/device-tree/device-tree.bb:do_compile
Summary: There was 1 WARNING message.
Summary: There was 1 ERROR message, returning a non-zero exit code.
[ERROR] Command bitbake virtual/bootloader -c menuconfig failed

To fix it we need to rename the &ps7_nand_0 to &nfc0 or if you dont need the nand controller just remove it out completly the complete &ps7_nand_0 block as shown below

vim /home/phnx/projects/petalinux/ebaz4205/components/plnx_workspace/device-tree/device-tree/system-conf.dtsi
&ps7_nand_0 {
        nand@0 {
                partition@0 {
                        label = "nand-boot";
                        reg = <0x0 0x00000000 0x00500000>;
                };
                partition@1 {
                        label = "nand-kernel";
                        reg = <0x0 0x00500000 0x00a80000>;
                };
                partition@2 {
                        label = "nand-bootenv";
                        reg = <0x0 0x00f80000 0x00020000>;
                };
        };
};

Change it to by changing ps7_nand_0 to nfc0 as shown below:

&nfc0{
        nand@0 {
                partition@0 {
                        label = "nand-boot";
                        reg = <0x0 0x00000000 0x00500000>;
                };
                partition@1 {
                        label = "nand-kernel";
                        reg = <0x0 0x00500000 0x00a80000>;
                };
                partition@2 {
                        label = "nand-bootenv";
                        reg = <0x0 0x00f80000 0x00020000>;
                };
        };
};

And Re-run

petalinux-config -c u-boot

After this fix you should see this menuconfig window

Note: IF you still dont see the window then check this Technical FAQs

u-boot config

One thing we need to update is boot option and boot media. <Select> the following path

Boot options --->
        Boot media  --->
                [*] Support for booting from NAND flash
                [*] Support for booting from SD/EMMC

and once both items are selected <Exit> all menu till you see u-boot config then press <Yes> to save the new configuration.

If you dont want specific Linux config or some rootfs packages. Now we can build the u-boot kernel and rootfs using following command

petalinux-build

We need to package all into a boot BOOT.bin image file. The BOOT.BIN file typically includes the First Stage Boot Loader (FSBL), Platform Management Unit (PMU) firmware, Trusted Firmware (TF-A), and the Second Stage Boot Loader (U-Boot). Run this on the shell to generate the file:

petalinux-package boot --force --fsbl ./images/linux/zynq_fsbl.elf --fpga ./project-spec/hw-description/ebaz4205_wrapper.bit

Petalinux has powerful suit of commands and I have just scrached the surface. You can learn more here Link

If the build succeed without any errors you can see all the gnerated files in PROJECT_PATH/images/linux folder

phnx@phnx:~/projects/petalinux/ebaz4205/images/linux$ ls
boot.scr  pxelinux.cfg    rootfs.cpio.gz.u-boot  rootfs.qemuboot.conf  rootfs.testdata.json  u-boot.bin      u-boot.elf  zImage
config    rootfs.cpio     rootfs.ext4            rootfs.spdx.tar.zst   system.bit            u-boot-dtb.bin  uImage      zynq_fsbl.elf
image.ub  rootfs.cpio.gz  rootfs.manifest        rootfs.tar.gz         system.dtb            u-boot-dtb.elf  vmlinux

Partion the SD Card
#

We need two partition in the SD Card to run the Petalinux succesfully.

Now how to partition a SD Card is also a few step process and described beautifully in Xilinx documentation in this Link

Once you have partitioned the SD card we need to transfer the boot.scr,BOOT.bin, system.dtb and image.ub to the boot partition.

cd to this mount point in your system via shell. Copy the rootfs.tar.gz compressed rootfile system to the other partition using cp command this (need root access):

sudo cp ~projects/petalinux/ebaz4205/images/linux/rootfs.tar.gz .
sync

In the shell just run the following command to decompress and unzip the rootfile system. It need root access too.

sudo tar -xvpf rootfs.tar.gz
sync

Remove the SD card and insert into the board.

Serial Kernel Boot Log
#

Connect a Serial-2-USB converter to log the boot process. I use Cp2102 based cheap 3 bucks USB to TTL converter shown below: usb -t serial

Please make sure it works at 3.3v TTL as higher level like 5v will destroy the GPIO. And DO NOT USE RS232 USB coverters.

Connect RXD on the converter to TX on the board and TXD on converter to RX on the board. Also connect the ground GND together.

Go to the shell on computer and find out where it is attached on the /dev/ folder. You can check it with sudo dmesg and it should show up like this on the logs (mine is attached on ttyUSB0):

[19128.317021] usb 1-5: SerialNumber: 0001
[19128.326421] cp210x 1-5:1.0: cp210x converter detected
[19128.327354] usb 1-5: cp210x converter now attached to ttyUSB0

Install minicom using sudo apt-get install minicom and run following command:

minicom -D /dev/ttyUSB0

Connect to the power supply as described before. And If all steps were successful there should be a boot log like one shown below:

U-Boot 2024.01 (Oct 24 2024 - 10:42:51 +0000)
CPU:   Zynq 7z010
Silicon: v3.1
DRAM:  ECC disabled 256 MiB
Core:  19 devices, 14 uclasses, devicetree: board
Flash: 0 Bytes
NAND:  0 MiB
MMC:   mmc@e0100000: 0
U-Boot 2024.01 (Oct 24 2024 - 10:42:51 +0000)
CPU:   Zynq 7z010
Silicon: v3.1
DRAM:  ECC disabled 256 MiB
Core:  19 devices, 14 uclasses, devicetree: board
Flash: 0 Bytes
NAND:  0 MiB
MMC:   mmc@e0100000: 0
In:    serial@e0001000
Out:   serial@e0001000
Err:   serial@e0001000
Net:   
ZYNQ GEM: e000b000, mdio bus e000b000, phyaddr 0, interface gmii
eth0: ethernet@e000b000
Hit any key to stop autoboot:  0 
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
3830 bytes read in 19 ms (196.3 KiB/s)
## Executing script at 03000000
Trying to load boot images from mmc0
4919919 bytes read in 435 ms (10.8 MiB/s)
## Loading kernel from FIT Image at 06000000 ...
 ...
 ...
Starting kernel ...

Log in using username as petalinux and it should prompt you to create a new password. And we have succesfully booted a Linux kernel on a EBAZ4205 board. I will continiue our journey in my later blog post where I will access the SPI Peripheral that I created in my earlier blog from within the running Petalinux system