Перейти к содержимому

AXI DMA PS+PL Loopback on ZYNQ FPGA using VIVADO + VITIS UNIFIED IDE on Alinx AXU2CGBI

Dr. Hazoor Ahmad (EEDHA)

0:00 / 0:00

AXI DMA PS+PL Loopback on ZYNQ FPGA using VIVADO + VITIS UNIFIED IDE on Alinx AXU2CGBI

153 просмотра · 2 недели назад
Dr. Hazoor Ahmad (EEDHA)
285 подписчиков
153 просмотра · 2 недели назад
In this tutorial, I build a complete AXI DMA loopback design on the Alinx AXU2CGBI board (Xilinx Zynq UltraScale+ MPSoC, XCZU2CG-SFVC784-1-E) — going beyond a PS-only Hello World to real PS-PL codesign. We configure the AXI DMA IP in Vivado, wire it into the Zynq UltraScale+ processing system, and verify a working data path with a bare-metal loopback test in Vitis Unified IDE. This is the essential next step after PS Hello World for anyone learning FPGA/embedded codesign on the AXU2CGBI — and a foundation for more advanced datapaths like streaming DSP and FFT-based processing. What you'll learn: ✅ Enabling the right PS-PL interfaces (AXI HPM0 LPD, AXI HP0 FPD) for DMA ✅ Configuring interrupts (PL to PS, IRQ0/IRQ1) for AXI DMA ✅ Adding and wiring AXI DMA, AXI SmartConnect, and reset/clock signals in Vivado IP Integrator ✅ Direct Register mode vs Scatter Gather mode — and a real hardware/software mismatch bug I hit and fixed ✅ Writing and running a bare-metal AXI DMA loopback test in Vitis Unified IDE ✅ A critical Vitis workflow gotcha: why "switching XSA" on an existing platform can silently fail, and why creating a fresh platform + application project is the reliable fix ✅ Verifying DMA Loopback PASSED over UART Hardware used: 🔹 Alinx AXU2CGBI (Zynq UltraScale+ MPSoC, XCZU2CG-SFVC784-1-E) 🔹 USB-UART / JTAG cable Software used: 🔹 Xilinx Vivado 2024.2 🔹 Vitis Unified IDE Timestamps: 00:08 – Intro 00:20 – Creating a Vivado project 01:00 – Creating a Block Design and adding Zynq IP 01:30 – PS UART and DDR configuration 02:30 – PS-PL Configuration: enabling AXI HP/HPM ports and interrupts 04:10 – Adding and configuring AXI DMA 05:00 – Adding AXI SmartConnect, wiring clocks, resets, and interrupts 06:30 – Validating design and generating bitstream 08:00 – Setting up Vitis workspace 08:50 – Creating platform from xsa file and building 09:50 – Creating application from the generated platform 11:15 – Application build 12:00 – Application run 12:30 – DMA Loopback PASSED If this helped you get PS-PL codesign working on your own AXU2CGBI board, please like, subscribe, and let me know in the comments what you'd like to see next — AXI4-Stream FIFO, Scatter Gather with BD rings, or the Xilinx FFT IP for matched filtering! Tags: #Zynq #UltraScale #AlinxAXU2CGBI #Vitis #Vivado #FPGA #AXIDMA #embeddedsystems #Xilinx #AMDXilinx #MPSoC #PSPLCodesign // AXI DMA Simple Loopback Example #include "xparameters.h" #include "xaxidma.h" #include "xil_cache.h" #include "xil_printf.h" #define MAX_PKT_LEN 32 #define TIMEOUT 1000000 #define TX_BUFFER_BASE (XPAR_PSU_DDR_0_BASEADDRESS + 0x02000000) #define RX_BUFFER_BASE (XPAR_PSU_DDR_0_BASEADDRESS + 0x02200000) XAxiDma AxiDma; int main(void){ XAxiDma_Config *CfgPtr; u8 *TxBuffer = (u8 *)TX_BUFFER_BASE; u8 *RxBuffer = (u8 *)RX_BUFFER_BASE; int Status = XST_SUCCESS; int i, Timeout; xil_printf("\r\nAXI DMA Simple Loopback Test\r\n"); CfgPtr = XAxiDma_LookupConfig(XPAR_XAXIDMA_0_BASEADDR); if (CfgPtr == NULL) return XST_FAILURE; Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr); XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA); for (i = 0; i != MAX_PKT_LEN; i++) { TxBuffer[i] = i; RxBuffer[i] = 0; } Xil_DCacheFlushRange((UINTPTR)TxBuffer, MAX_PKT_LEN); Xil_DCacheFlushRange((UINTPTR)RxBuffer, MAX_PKT_LEN); if (Status == XST_SUCCESS) Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR)RxBuffer,MAX_PKT_LEN,XAXIDMA_DEVICE_TO_DMA); if (Status == XST_SUCCESS) Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR)TxBuffer,MAX_PKT_LEN,XAXIDMA_DMA_TO_DEVICE); Timeout = TIMEOUT; while (Status == XST_SUCCESS && (XAxiDma_Busy(&AxiDma, XAXIDMA_DMA_TO_DEVICE) || XAxiDma_Busy(&AxiDma, XAXIDMA_DEVICE_TO_DMA)) && Timeout--); if (Timeout == 0) Status = XST_FAILURE; Xil_DCacheInvalidateRange((UINTPTR)RxBuffer, MAX_PKT_LEN); for (i = 0; (i != MAX_PKT_LEN) && (Status == XST_SUCCESS); i++) if (TxBuffer[i] != RxBuffer[i]) Status = XST_FAILURE; xil_printf("DMA Loopback %s\r\n", (Status == XST_SUCCESS) ? "PASSED" : "FAILED"); return Status; }