This is a Step-by-Step Tutorial how to create a Hardware Accelerator Platform for AXU2CGA/B Zynq UltraScale+ FPGA development board made by Alinx, that can be used for runnung GNU Radio applications with accelerating functions under the Xilinx Vitis toolset.
Adding the gr-satellites developed by EA4GPZ and building your own OOT modules is also included in this set of Tutorials.
Creating a Vitis platform has several main steps:
- Part-1 - Create the Vivado Hardware Design
- Part-2 - Software - Build the PetaLinux and GNU Radio
- Part-3 - Create a Vitis Platform and Application with DPU
- Part-4 - Build the AI model in Colab and Vitis-AI
You should already have installed the following software tools from AMD-Xilinx:
- Vitis 2021.2
- Vivado 2021.2
- Petalinux 2021.2
We should prepare the folder hierarchy first. For this purpose, perform the following commands:
mkdir axu2cgb
cd axu2cgb
mkdir hardware
mkdir software
mkdir platform
cd hardware
Create the Vivado Hardware Design1- Run the Vivado and create a project in the hardware folder with “axu2cgb_2021_2-vivado” name.
2- On the Project Type page, choose the RTL project and select the following options:
- Do not specify sources at this time
- Project is an extensible Vitis platform
3- In the Parts tab choose the correct Part named xczu2cg-sfvc784-1-e and click Next and Finish.
4- Create a Block Design and Add the Zynq UltraScale+ MPSoc IP.
5- Now wee need to reconfigure the Zynq Ultrascale+ block carefully for the custom AXU2CGB board.
You will need the board user manual, which can be downloaded from the manufacturer web page:
http://www.alinx.vip:81/ug_en/AXU2CG_User_Manual.pdf
Downloaded and open it. We need to set almost all settings in the Zynq block according to the data provided from the user manual of the AXU2CGB board.
NOTE: You can skip the whole Section 6 below, and just execute the TCL Command in Section-7 to make the Zynq block configuration all at once.
6- Double click on the Zynq block in the board design and go through all available settings.
6-1- QSPI configuration
- Enable QSPI and set the following in the Low Speed section:
6-2- eMMC configuration
- Enable SD 0 and select: MIO13..22
- Slot Type: eMMC
- Data Transfer Mode: 8Bit
- Enable Reset, and select MIO23.
6-3- SD card configuration
- Enable SD 1
- Select MIO 46..51
- Slot Type: SD 2.0
- Data Transfer Mode: 4Bit
- Enable CD to detect SD Card insertion and select MIO45
6-4- I2C configuration for EEPROM
- Enable I2C 1
- Select MIO 32..33
6-5- UART configuration
- Enable serial port UART 1
- Select MIO 24..25
6-6- Enable TTC0 - TTC3
6-7- Gigabit Ethernet configuration
- Enable GEM3 and MDIO3
- Select MIO 64..75 GEM3
- Select MIO 76..77 for MDIO3
6-8- USB port configuration
- Enable USB 0
- Select MIO 52..63
- Enable USB 3.0 and select GT Lane1
- Configure the USB Reset as below:
6-9- Configure PCIe and Display Port
6-10- Additional PCIe configuration
- Enable Switch To Advanced Mode in the Page Navigator (top left)
- Select PCIe Configuration tab. Set the following:
6-11- Clock configuration
Select the Clock Configuration tab and Input Clocks tab. Set the following:
- Input Reference frequency > PSS_REF_CLOCK: 33.333MHz;
- PCIe: Ref Clk0, 100MHz
- Display Port: Ref Clk2, 27MHz;
- USB0: Ref Clk1, 26MHz.
6-12 In Output Clocks tab
- If IOPLL is not selected, change it to IOPLL. So, it brings into correspondence with the same PLL.
6-13- Output Clocks continue
- DP_VIDEO: change to VPLL
- DP_AUDIO and DP_STC: change to RPLL.
- The rest remains the default
6-14- DDR configuration
- Load DDR Presets: select DDR4_MICRON_MT40A256M16GE_083E
- Others Options remain default.
6-15- Click OK, then Configuration Complete
7- In case you need to repeat the whole Zynq UltraScale+ block configuration all at once, here is a single TCL command. This command can be executed in the TCL console.
set_property -dict [list CONFIG.PSU__DPAUX__PERIPHERAL__IO {MIO 27 .. 30} CONFIG.PSU__GEM__TSU__ENABLE {0} CONFIG.PSU__ENET0__PERIPHERAL__ENABLE {0} CONFIG.PSU__ENET1__PERIPHERAL__ENABLE {0} CONFIG.PSU__ENET2__PERIPHERAL__ENABLE {0} CONFIG.PSU__ENET3__PERIPHERAL__ENABLE {1} CONFIG.PSU__ENET3__GRP_MDIO__ENABLE {1} CONFIG.PSU__I2C1__PERIPHERAL__ENABLE {1} CONFIG.PSU__I2C1__PERIPHERAL__IO {MIO 32 .. 33} CONFIG.PSU__PCIE__PERIPHERAL__ENABLE {1} CONFIG.PSU__PCIE__PERIPHERAL__ENDPOINT_IO {MIO 37} CONFIG.PSU__PCIE__PERIPHERAL__ROOTPORT_IO {MIO 37} CONFIG.PSU__USB0__REF_CLK_SEL {Ref Clk1} CONFIG.PSU__PCIE__DEVICE_PORT_TYPE {Root Port} CONFIG.PSU__PCIE__CLASS_CODE_SUB {0x04} CONFIG.SUBPRESET1 {DDR4_MICRON_MT40A256M16GE_083E} CONFIG.PSU__QSPI__PERIPHERAL__ENABLE {1} CONFIG.PSU__QSPI__PERIPHERAL__DATA_MODE {x4} CONFIG.PSU__QSPI__GRP_FBCLK__ENABLE {1} CONFIG.PSU__SD0__PERIPHERAL__ENABLE {1} CONFIG.PSU__SD0__SLOT_TYPE {eMMC} CONFIG.PSU__SD0__RESET__ENABLE {1} CONFIG.PSU__SD1__PERIPHERAL__ENABLE {1} CONFIG.PSU__SD1__PERIPHERAL__IO {MIO 46 .. 51} CONFIG.PSU__SD1__GRP_CD__ENABLE {1} CONFIG.PSU__SD1__SLOT_TYPE {SD 2.0} CONFIG.PSU__TTC0__PERIPHERAL__ENABLE {1} CONFIG.PSU__TTC1__PERIPHERAL__ENABLE {1} CONFIG.PSU__TTC2__PERIPHERAL__ENABLE {1} CONFIG.PSU__TTC3__PERIPHERAL__ENABLE {1} CONFIG.PSU__UART1__PERIPHERAL__ENABLE {1} CONFIG.PSU__UART1__PERIPHERAL__IO {MIO 24 .. 25} CONFIG.PSU__USB0__PERIPHERAL__ENABLE {1} CONFIG.PSU__USB0__RESET__ENABLE {1} CONFIG.PSU__USB0__RESET__IO {MIO 44} CONFIG.PSU__USB__RESET__MODE {Shared MIO Pin} CONFIG.PSU__USB3_0__PERIPHERAL__ENABLE {1} CONFIG.PSU__USB3_0__PERIPHERAL__IO {GT Lane1} CONFIG.PSU_BANK_0_IO_STANDARD {LVCMOS18} CONFIG.PSU_BANK_1_IO_STANDARD {LVCMOS18} CONFIG.PSU_BANK_2_IO_STANDARD {LVCMOS18} CONFIG.PSU__DISPLAYPORT__PERIPHERAL__ENABLE {1} CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__SRCSEL {VPLL} CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__SRCSEL {RPLL} CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__SRCSEL {RPLL} CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__SRCSEL {APLL} CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__SRCSEL {IOPLL} CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__SRCSEL {IOPLL}] [get_bd_cells zynq_ultra_ps_e_0]
8- Add the Clocking Wizard to the block design and double-click the clk_wiz_0 IP block to open the Re-Customize IP dialog box
Click the Output Clocks tab. Enable clk_out1 through clk_out3 in the Output Clock column. Set the Requested Output Freq as follows:
- clk_out1 to 100 MHz
- clk_out2 to 200 MHz
- clk_out3 to 400 MHz
At the bottom of the dialog box set the Reset Type to Active Low.
# Equivalent TCL command for adding the Clocking Wizard
create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0
set_property -dict [list CONFIG.CLKOUT2_USED {true} CONFIG.CLKOUT3_USED {true} CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200.000} CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {400.000} CONFIG.RESET_TYPE {ACTIVE_LOW} CONFIG.MMCM_CLKOUT1_DIVIDE {6} CONFIG.MMCM_CLKOUT2_DIVIDE {3} CONFIG.NUM_OUT_CLKS {3} CONFIG.RESET_PORT {resetn} CONFIG.CLKOUT2_JITTER {102.086} CONFIG.CLKOUT2_PHASE_ERROR {87.180} CONFIG.CLKOUT3_JITTER {90.074} CONFIG.CLKOUT3_PHASE_ERROR {87.180}] [get_bd_cells clk_wiz_0]
9- Add three Processor System Reset IPs to the design and connect the IPs together, as shown in figure below
# Adding 3 Processor System Reset IPs
create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0
create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_1
create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_2
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_clk0] [get_bd_pins clk_wiz_0/clk_in1]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_resetn0] [get_bd_pins clk_wiz_0/resetn]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_resetn0] [get_bd_pins proc_sys_reset_1/ext_reset_in]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_resetn0] [get_bd_pins proc_sys_reset_0/ext_reset_in]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_resetn0] [get_bd_pins proc_sys_reset_2/ext_reset_in]
connect_bd_net [get_bd_pins clk_wiz_0/clk_out1] [get_bd_pins proc_sys_reset_0/slowest_sync_clk]
connect_bd_net [get_bd_pins clk_wiz_0/clk_out2] [get_bd_pins proc_sys_reset_1/slowest_sync_clk]
connect_bd_net [get_bd_pins clk_wiz_0/clk_out3] [get_bd_pins proc_sys_reset_2/slowest_sync_clk]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_1/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_0/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_2/dcm_locked]
regenerate_bd_layout
10- Platform Setup
Enable all three clocks for the platform. Use menu Window -> Platform Setup. Set clock-2 as default.
11- Adding the Interrupt support.
Double click on the Zynq UltraScale+ MPSoC block again
- Select PS-PL Configuration > PS-PL interfaces > Master interface
- Enable the AXI HPM0 LPD option
- Disable AXI HPM0 FPD and AXI HPM1 FPD
- Enable General > Interrupts > PL to PS > IRQ0[0-7] Interrupts
Add the AXI Interrupt ControllerIP and configure it as a Single Interrupt Output Connection. Click OK
Then click on the “Run Connection Automation” link.
Select clk_out2 (200 MHz) as a source for master and slave interface and press OK.
Connect the irq output pin to the Zynq interrupt input.
12- Enable AXI Interfaces for the Platform in the Platform Setup tab:
- Enable first eight interfaces under zynq_ultra_ps_e_0 and set SP Tag for them.
- Enable M01_AXI to M07_IXA interfaces under ps8_0_axi_periph
Equivalent TCL commands:
# Enable AXI Interfaces in Platform Setup
set_property PFM.AXI_PORT {M_AXI_HPM0_FPD {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M_AXI_HPM1_FPD {memport "M_AXI_GP" sptag "" memory "" is_range "false"} S_AXI_HPC0_FPD {memport "S_AXI_HPC" sptag "HPC0" memory "" is_range "false"} S_AXI_HPC1_FPD {memport "S_AXI_HPC" sptag "HPC1" memory "" is_range "false"} S_AXI_HP0_FPD {memport "S_AXI_HP" sptag "HP0" memory "" is_range "false"} S_AXI_HP1_FPD {memport "S_AXI_HP" sptag "HP1" memory "" is_range "false"} S_AXI_HP2_FPD {memport "S_AXI_HP" sptag "HP2" memory "" is_range "false"} S_AXI_HP3_FPD {memport "S_AXI_HP" sptag "HP3" memory "" is_range "false"}} [get_bd_cells /zynq_ultra_ps_e_0]
set_property PFM.AXI_PORT {M01_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M02_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M03_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M04_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M05_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M06_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M07_AXI {memport "M_AXI_GP" sptag "" memory "" is_range "false"}} [get_bd_cells /ps8_0_axi_periph]
13- In the interrupt tab, enable the intr
14- Update Platform Name
15- Export hardware - XSA
- Validate the block design - press F6 (ignore axi_intc_0/intr Warning)
- Create HDL Wrapper (In Source tab, right click design_1.bd file in Design Sources group)
- Generate Block Design and select Synthesis Options to Global. Then click Generate.
- Generate Bitstream - Click the button in the Flow Navigator window.
- Export the Platform - click the button in Flow Navigator window. Select Hardware, then Pre-synthesis and enable Include bitstream.
This is the end of the first Vivado part of creating Platform. You can now close the Vivado program.
To continue, go to the second - PetaLinux part of the project:
Fast TrackIf you are stuck somewhere, there is a TCL script attached that create the whole project described above.
Run the script as soon as Vivado started in the Tcl Console window with a source command.
source create_axu2cgb_hw_acc_platform.tcl
When the TCL script finished then:
- Validate the Block Design - press F6
- Create HDL Wrapper
- Generate Block Design and select Synthesis Options to Global.
- Generate Bitstream
- Export the Platform and select Hardware, Pre-synthesis and enable Include bitstream.
Comments
Please log in or sign up to comment.