Overview


The TE0950 board has two FPGA devices an AMD Versal AI Edge in role of the main FPGA of the system and AMD Artix FPGA as configurable levelshifter/MUX for FMC and other 3.3 V IOs. These two FPGAs have dedicated up to 14 differential pairs to communicate with. This tutorial describes how to program the FPGAs and provides an example of how to  do AXI4 transactions between the two FPGAs. The procedure described in this text is for a reference design for Vivado 2023.2.1 tools.

Key Features


  • Vivado 2023.2.2

  • Chip2Chip Communication to Versal
  • PWM Fan control via AXI Timer IP Core
  • 3-wire I2C Multiplexer

Requirements


Type

Name

Version

Note

HW

TE0950 board

--

--

Diverse Cable

USB, Power...

--

--

Virtual Machine

Oracle, VMWare or MS WSL

--

optional

OS

Linux

Xilinx Supported OS 

running on VM or native

Reference Design

TE0950-test_board_artix-vivado_2023.2-build_4_*.zip

build 4 or higher to match Vivado 2023.2

Artix™

Reference Design

TE0950-test_board-vivado_2023.2-build_4_*.zip

build 4 or higher to match Vivado 2023.2

Versal™

SW

Vitis

2023.2

--

SW

Vivado

2023.2


SW

Petalinux

2023.2

--

SW

Putty

--

--

Description


To establish a communication between two FPGA devices there is used the Chip2Chip IP core which is included in standard AMD Vivado installation (tested in 2023.2.2 version). A simplified block diagram of the system design is shown in Figure bellow.


The core is configured to transfer full AXI4 transactions including bursts. In case of AXI-Lite transactions, they are mapped into the full AXI4 transactions. In both FPGAs the Chip2Chip core has to be configured almost identically, the only difference is in the Chip2Chip mode choice. The  figure bellow shows the Chip2Chip IP core configuration used in Artix™ device. This particular configuration allows a maximum theoretical throughput of 1525 Mb/s in one direction. Realistically, it is necessary to calculate from 75% of this value, i.e. 1144 Mb/s. This value is perfectly sufficient for AXI-Lite transactions, but for larger data streams, e.g. video, it can be limiting.


It is also necessary to have the address spaces set correctly. This means that on the Versal™ side, the Chip2Chip core must have an address range set such that it includes all the addresses of all the IP cores in Artix™ that we want to communicate with.

Quick Startup


The procedure was tested in AMD tools in version 2023.2.2 running on native Ubuntu 20.04.6 LTS Linux distribution. It is assumed that the AMD Vivado, Vitis and PetaLinux tools are already installed. The example described here builds on the reference design for the TE0950 board. It is based on the reference design, which contains two "independent" designs, one for Versal™ and another one for Artix™. The reference design packages are available for download at TE0950 web page:

All the steps described here are reported and tested for the board TE0950-03-EGBE21A equipped with the original Trenz Electronic cooler, which has a four pin connector allowing PWM regulation of the FAN.

Artix™ HW Compilation


  1. Unpack downloaded package:
    TE0950-test_board_artix-vivado_2023.2-build_4_*.zip
    It creates the test_board_artix folder.
  2. Go to the test_board_artix folder and set all necessary scripts executable. From the command line execute:
    cd test_board_artix
    chmod +x _create_linux_setup.sh console/base_sh/*.sh

    Trenz Electronic Scripts allows posibility change some setup via enviroment variables, which depends on the used OS and PC performace.

    To improve performance on multicore CPU append global envirment:

    export TE_RUNNING_JOBS=24

    to  the user profile file ~/.profile or to the project local configuration file test_board_artix/console/base_sh/design_basic_settings.sh. The number of used CPUs modify up to your system.

  3. Create Vivado design, from the command line execute:
    ./_create_linux_setup.sh
    Select: Module selection guide, project creation...
    0
    Select: TE0950-03-EGBE21A
    5
    Confirm the selected board
    y
    Select: Create vivado project
    1
    It creates a Vivado project and open it.
  4. Compile the design, from the Vivado TCL console execute:
    TE::hw_build_design -export_prebuilt
    When the compilation is finished, Vivado opens the Bitstram Generation Completed dialog. Select Open implemented Design and click OK. The resultant bitstream is in folder test_board_artix/prebuilt/hardware/35_2c_03.
  5. Convert the bitstream to a format suitable for QSPI Flash memory from which the Artix™ FPGA boots automatically on power on. From the Vivado TCL console execute:
    TE::EXT::generate_app_bit_mcs
    It creates file test_board_artix/prebuilt/boot_images/35_2c_03/fpga/fpga.mcs.
  6. Connect the JTAG/UART on the TE0950 board (micro-USB connector J2) to the PC.
  7. Switch the board to use JTAG, set switch S2.1 = 0, S2.2 = 0 and S2.3 = 0.
  8. Set the JTAG chain to include Artix™ (its QSPI Flash memory). Set switch S4.1 = 1, S4.2 = 0 and S4.3 = 1.
  9. Power the board ON.
  10. Program the Artix™ QSPI Flash memory, from the Vivado TCL console execute:
    TE::pr_program_flash -swapp fpga
  11. Close Vivado.
  12. Power the board OFF.

Versal™ HW Compilation


  1. Unpack downloaded package:
    TE0950-test_board-vivado_2023.2-build_4_*.zip
    It creates the test_board folder.
  2. Go to the test_board folder and set all necessary scripts executable. From the command line execute:
    cd test_board
    chmod +x _create_linux_setup.sh console/base_sh/*.sh

    Trenz Electronic Scripts allows posibility change some setup via enviroment variables, which depends on the used OS and PC performace.

    To improve performance on multicore CPU append global envirment:

    export TE_RUNNING_JOBS=24

    to  the user profile file ~/.profile or to the project local configuration file test_board/console/base_sh/design_basic_settings.sh. The number of used CPUs modify up to your system.

  3. Create Vivado design, from the command line execute:
    ./_create_linux_setup.sh
    Select: Module selection guide, project creation...
    0
    Select: TE0950-03-EGBE21A
    3
    Confirm the selected board
    y
    Select: Create vivado project
    1
    It creates a Vivado project and open it.
  4. Compile the design, from the Vivado TCL console execute:
    TE::hw_build_design -export_prebuilt
    When the compilation is finished, Vivado opens the Bitstram Generation Completed dialog. Select Open implemented Design and click OK.
  5. Create the BOOT.bin file, from the Vivado TCL console execute:
    TE::sw_run_vitis -all
    It compiles all necessary components and wraps them together into one booting file test_board/prebuilt/boot_images/23_1lse_8gb/u-boot/BOOT.bin and open Vitis. Close Vitis.
  6. Close Vivado.

Petalinux Compilation


  1. Extend a device tree for Versal™ with Artix™ peripheral definitions.
    1. Modify DTSI file with Artix™ extensions, edit file:
      test_board/os/petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/artix-overlay.dtsi
      1. Remove first two lines defining the DTSI file as an overlay plugin, remove these lines:
        /dts-v1/;
        /plugin/;

        This petalinux project has another “overlay” DTSI files, they are needed for different cameras connected via MIPI SCI2 interface on the TE0950 board. For the purposes of this application note, they are not required and we will leave them as they are without touching them.

      2. Add artix_usr_gpio, artix_hs1_gpio and artix_hs2_gpio blobs  into the amba_pl section:
        artix_usr_gpio: gpio@a8080000 {
          #gpio-cells = <2>;
          clock-names = "s_axi_aclk";
          clocks = <&artix_clk 0>;
          compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
          gpio-controller ;
          reg = <0x0 0xa8080000 0x0 0x10000>;
          xlnx,all-inputs = <0x0>;
          xlnx,all-inputs-2 = <0x0>;
          xlnx,all-outputs = <0x0>;
          xlnx,all-outputs-2 = <0x0>;
          xlnx,dout-default = <0x00000000>;
          xlnx,dout-default-2 = <0x00000000>;
          xlnx,gpio-width = <0x3>;
          xlnx,gpio2-width = <0x20>;
          xlnx,interrupt-present = <0x0>;
          xlnx,is-dual = <0x0>;
          xlnx,tri-default = <0xFFFFFFFF>;
          xlnx,tri-default-2 = <0xFFFFFFFF>;
        };
        
        artix_hs1_gpio: gpio@a80c0000 {
          #gpio-cells = <2>;
          clock-names = "s_axi_aclk";
          clocks = <&artix_clk 0>;
          compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
          gpio-controller ;
          reg = <0x0 0xa80c0000 0x0 0x10000>;
          xlnx,all-inputs = <0x0>;
          xlnx,all-inputs-2 = <0x0>;
          xlnx,all-outputs = <0x0>;
          xlnx,all-outputs-2 = <0x0>;
          xlnx,dout-default = <0x00000000>;
          xlnx,dout-default-2 = <0x00000000>;
          xlnx,gpio-width = <0x2>;
          xlnx,gpio2-width = <0x20>;
          xlnx,interrupt-present = <0x0>;
          xlnx,is-dual = <0x0>;
          xlnx,tri-default = <0xFFFFFFFF>;
          xlnx,tri-default-2 = <0xFFFFFFFF>;
        };
        
        artix_hs2_gpio: gpio@a8100000 {
          #gpio-cells = <2>;
          clock-names = "s_axi_aclk";
          clocks = <&artix_clk 0>;
          compatible = "xlnx,xps-gpio-1.00.a";
          gpio-controller ;
          reg = <0x0 0xa8100000 0x0 0x10000>;
          xlnx,all-inputs = <0x0>;
          xlnx,all-inputs-2 = <0x0>;
          xlnx,all-outputs = <0x0>;
          xlnx,all-outputs-2 = <0x0>;
          xlnx,dout-default = <0x00000000>;
          xlnx,dout-default-2 = <0x00000000>;
          xlnx,gpio-width = <0x2>;
          xlnx,gpio2-width = <0x20>;
          xlnx,interrupt-present = <0x0>; 
          xlnx,is-dual = <0x0>;
          xlnx,tri-default = <0xFFFFFFFF>;
          xlnx,tri-default-2 = <0xFFFFFFFF>;
        };
      3. Define artix_usr_gpio pin names, add artix_usr_gpio blob into the root section of the DTSI file (outside the pl_amba section).
        &artix_usr_gpio {
          gpio-line-names = "A_USR_LED3", "A_USR_LED2", "A_USR_DIPSW_S5_4";
        };
        Already modified artix-overlay.dtsi file.

    2. Include the artix-overlay.dtsi file into the main custom DTSI file, edit:
      test_board/os/petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dsti
      Insert include section on the second line:
      /include/ "artix-overlay.dtsi"
      Already modified system-user.dsti file.

    3. Include the artix-overlay.dtsi file in the compilation procedure, edit:
      test_board/os/petalinux/project-spec/meta-user/recipes-bsp/device-tree/device-tree.bbappend
      Extend the SRC_URI string with path of the artix-overlay.dtsi file:
      SRC_URI:append = "file://system-user.dtsi file://mipi_csi2.dtsi
      file://artix-overlay.dtsi"
      Already modified device-tree.bbappend file.

  2. Set the system path to see petalinux tools, from the command line execute (modify the path according to your working system environment):
    source /opt/petalinux/2023.2/settings.sh
  3. Go to the petalinux project directory and update the project with current hardware specification (XSA file), from the command line execute:
    cd test_board/os/petalinux
    petalinux-config --get-hw-description=../../vivado
    It opens menu config window. There is no need to change anything, close the menu config window, choose Exit.
  4. Build petalinux, from the command line execute:
    petalinux-build

Prepare SD Card and Start the Board


  1. Take an empty micro SD card formatted to FAT32 and copy these files on it:
    test_boardMicro SD CardNote
    prebuilt/boot_images/23_1lse_8gb/u-boot/BOOT.binBOOT.bin-
    os/petalinux/images/linux/bl31.elfbl31.elf-
    os/petalinux/images/linux/boot.scrboot.scr-
    os/petalinux/images/linux/image.ubimage.ub-

    os/petalinux/images/linux/system.dtb

    system.dtb-

    os/petalinux/images/linux/u-boot-dtb.elf

    u-boot.elf Rename u-boot-dtb.elf to u-boot.elf

    In case you want to use MIPI CSI2 interface to connect camera, copy complete test_board/os/petalinux/images/linux/dtbos folder to the micro SD card, too. This folder contains compiled overlay device tree files that correspond to currentrly supported cameras. This is optional and not needed for this application note.

  2. Insert the micro SD card into the TE0950 card reader slot J4.
  3. Switch the board to boot from micro SD card, set switch S2.1 = 0, S2.2 = 1 and S2.3 = 0.
  4. Power the board ON.
  5. Start serial terminal, putty for instance. The terminal settings are:
    SettingValue
    Baud rate115200
    Data bits8
    Stop bit1
    Paritynone
    Flow controlnone
  6. Work with serial terminal.

Examples


This section describes two examples that show how to interact with peripherals implemented in the Artix™ FPGA with the Versal™ processing system. The first example shows how to use an AXI Timer to control the FAN speed with PWM. The second one, it describes controlling user LEDs via AXI GPIO IP core.

 FAN Control


 If the TE0950 board is equipped with the cooler that has a FAN with four pin connector allowing PWM regulation, the FAN speed can be controlled with the timer which is in the Artix™ FPGA. The PWM value can be controlled by reading/writing of the system file:

 /sys/class/hwmon/hwmon0/pwm1

This value is in the range 0 to 255. When the board starts the PWM value is set to its maximum 255. To read the current value, execute from the serial terminal this command:

cat /sys/class/hwmon/hwmon0/pwm1

To set a new value of the PWM, 100 for example, execute from the serial terminal:

echo 100 > /sys/class/hwmon/hwmon0/pwm1

To determine the current system temperature for appropriate FAN speed control, read file:

/sys/bus/iio/devices/iio:device0/in_temp160_temp_input

from the serial terminal execute:

cat /sys/bus/iio/devices/iio:device0/in_temp160_temp_input

The FAN speed can be controlled according to current system temperature automatically just by reading in_temp160_temp_input and writing pwm1 files.  See attached python script fancontrol.py:

fancontrol.py
import time

temp_file = '/sys/bus/iio/devices/iio:device0/in_temp160_temp_input'
fanpwm_file = '/sys/class/hwmon/hwmon0/pwm1'

temp_min = 35.0
temp_max = 75.0
temp_hist_up = 1.0
temp_hist_down = 5.0
temp_prev = 0.0

print("FAN Control start ...\n")

# equation of a straight line: a*x + b*y + c = 0
# A = [temp_min; pwm_min], B = [temp_max, pwm_max]
# A = [temp_min; 0],       B = [temp_max, 255]
# u = B - A = (temp_max - temp_min; pwm_max - pwm_min)
# u = (temp_max - temp_min; 255 - 0)
# n = (255, -(temp_max - temp_min))
# p: 255*x -(temp_max - temp_min)*y + c = 0
# c: A is on the p
# c = -255*temp_min - (temp_max - temp_min)*0
c = -255 * temp_min

f_temp = open(temp_file, 'r')

while True:
  f_temp = open(temp_file, 'r')
  temp = float(f_temp.readline())
  f_temp.close()

  if ((temp - temp_prev) >= temp_hist_up) or ((temp_prev - temp) >= temp_hist_down):

    pwm = (-c - (255 * temp)) / -(temp_max - temp_min)
    pwmi = int(pwm)

    if pwmi < 0:
      pwmi = 0

    if pwmi > 255:
      pwmi = 255

    #print(str(temp), str(temp_prev), str(pwm), str(pwmi))

    f_pwm = open(fanpwm_file, 'w')
    f_pwm.write(str(pwmi))
    f_pwm.close()

    temp_prev = temp


  time.sleep(1)

 It is a simple python script which reads the current system temperature every second and then sets the FAN PWM value accordingly. The minimum PWM value 0 corresponds to 35 °C, the maximum PWM value 255 is reached at a temperature of 75 °C. The PWM value increases linearly with increasing temperature. As the temperature decreases, the PWM value decreases by a hysteresis that corresponds to 5 °C steps. 

To start the FAN control example automatically on each board startup:

  1. Copy file fancontrol.py directly to the root of the micro SD card.
  2. Create file init.sh on the root of the micro SD card which starts the fancontrol.py script
    #!/bin/bash
    python3 /run/media/mmcblk1p1/fancontrol.py &

GPIO LEDs and Switch


 In the whole system there are many GPIO peripherals. Some of these are found in the Versal™ processing system part, others are located in the Versal™ programmable logic, and still others are in the Artix™ programmable logic. To identify all GPIO peripherals use gpiodetect command from the serial terminal:

gpiodetect

gpiochip0 [a8000000.gpio] (34 lines)
gpiochip1 [a8080000.gpio] (3 lines)
gpiochip10 [a4120000.gpio] (5 lines)
gpiochip11 [versal_gpio] (58 lines)
gpiochip12 [pmc_gpio] (116 lines)
gpiochip2 [a80c0000.gpio] (2 lines)
gpiochip3 [a8100000.gpio] (2 lines)
gpiochip4 [a40a0000.gpio] (2 lines)
gpiochip5 [a40b0000.gpio] (8 lines)
gpiochip6 [a40c0000.gpio] (12 lines)
gpiochip7 [a40e0000.gpio] (8 lines)
gpiochip8 [a40f0000.gpio] (8 lines)
gpiochip9 [a4110000.gpio] (2 lines)

Those GPIOs whose address begins with “a8” are located in the Artix™ FPGA. The GPIO peripheral whose address is 0xA80800000 is the one that controls two user LEDs and one user DIP switch. From the gpiodetect report, it can be seen that it is named as gpiochip1. The gpiochip1 details can be obtained by executing gpioinfo command from the serial terminal:

gpioinfo gpiochip1

       	line   0: "A_USR_LED3"      	unused   input  active-high
        line   1: "A_USR_LED2"      	unused   input  active-high
        line   2: "A_USR_DIPSW_S5_4" 	unused   input  active-high

It is seen that the GPIO lines have not been set yet. The connected LEDs and switch are active low. To light up the LED (A_USR_LED3) connected to the line 0 of the gpiochip1, use command gpioset as follows:

gpioset `gpiofind "A_USR_LED3"`=0

Observe the TE0950 board, the user LED3 should start to light up. To turn the LED3 OFF use gpioset command again but with different argument:

gpioset `gpiofind "A_USR_LED3"`=1

The user LED2 can be controlled similarly. To get the current value of the user DIP switch S5.4, use command gpioget:

gpioget `gpiofind "A_USR_DIPSW_S5_4"`

Toggle the switch and repeat the gpioget command to see the different result.




Table of contents





App. A: Change History and Legal Notices


Document Change History


To get content of older revision go to "Change History" of this page and select older document revision number.

DateDocument Revision

Authors

Description

  • initial release
--all--
Document change history.