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.
Vivado 2023.2.2
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 | build 4 or higher to match Vivado 2023.2 | Artix™ | |
Reference Design | build 4 or higher to match Vivado 2023.2 | Versal™ | |
SW | Vitis | 2023.2 | -- |
SW | Vivado | 2023.2 | |
SW | Petalinux | 2023.2 | -- |
SW | Putty | -- | -- |
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.

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.
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.
./_create_linux_setup.sh
TE::hw_build_design -export_prebuilt
TE::EXT::generate_app_bit_mcs
TE::pr_program_flash -swapp fpga
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.
./_create_linux_setup.sh
TE::hw_build_design -export_prebuilt
TE::sw_run_vitis -all
/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.
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>;
};
&artix_usr_gpio {
gpio-line-names = "A_USR_LED3", "A_USR_LED2", "A_USR_DIPSW_S5_4";
};
/include/ "artix-overlay.dtsi"
SRC_URI:append = "file://system-user.dtsi file://mipi_csi2.dtsi file://artix-overlay.dtsi"
source /opt/petalinux/2023.2/settings.sh
cd test_board/os/petalinux petalinux-config --get-hw-description=../../vivado
petalinux-build
| test_board | Micro SD Card | Note |
|---|---|---|
| prebuilt/boot_images/23_1lse_8gb/u-boot/BOOT.bin | BOOT.bin | - |
| os/petalinux/images/linux/bl31.elf | bl31.elf | - |
| os/petalinux/images/linux/boot.scr | boot.scr | - |
| os/petalinux/images/linux/image.ub | image.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.
| Setting | Value |
|---|---|
| Baud rate | 115200 |
| Data bits | 8 |
| Stop bit | 1 |
| Parity | none |
| Flow control | none |
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.
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:
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:
#!/bin/bash python3 /run/media/mmcblk1p1/fancontrol.py &
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.
To get content of older revision go to "Change History" of this page and select older document revision number.
| Date | Document Revision | Authors | Description |
|---|---|---|---|
| |||
| -- | all | -- |