Vivado工程搭建
1. 創建基礎工程
新建Vivado項目,選擇目標FPGA型號。
添加Zynq Processing System IP核,配置DDR控制器和時鐘。7000系列的Zynq可以參考正點原子DMA回環測試設置。


2. 添加AXI DMA IP核
配置AXI DMA為Simple模式。
設置數據位寬(如32/64位)和Width of Buffer Lenghth Register(26最大可以存2^26 bit)。

3. 添加Stream Data FIFO
這里看需要設置FIFO 深度

4. 添加自定義ip用于產生數據
這里可以參考https://fpga.eetrend.com/blog/2023/100568155.html,由于工程需要,對ip進行修改,使得傳輸的數據位寬是16位,一共傳輸320*256個數據。修改位寬后re-package可能會出現報錯,請自行查找解決辦法。


5. 添加自定義ip用于產生dma_start信號
由于dma傳輸過程中會出現數據丟失情況,這里借鑒了以下博主的解決方法:ZYNQ踩坑日記:AXI_DMA傳輸問題詳解——問題再續篇-物聯沃-IOTWORD物聯網對于vivado中使用DMA傳輸數據時會丟數據的解決辦法_vivado dma-CSDN博客

對數據產生ip進行了修改(右鍵ip->edit in packager),使得dma初始化之后再開始傳輸數據,避免數據丟失

在關鍵代碼中進行如下修改:

最后再Re-Package IP,可以參考https://cloud.tencent.com/developer/article/1813652創建并修改自定義ip。
6. 連接IP核與總線
總體block design如下

PS端軟件設計(Vitis/SDK)
1. 初始化DMA
#include"xaxidma.h"#include"xparameters.h"#include"xil_cache.h"#include"xil_printf.h"#include"my_dma_start_s.h"#include"sleep.h"#defineDMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID#defineDDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR#defineRX_BUFFER_BASE (DDR_BASE_ADDR + 0x01000000)#defineDATA_LENGTH 81920// 與 PL 端對應#defineMY_DMA_START_ADDR XPAR_MY_DMA_START_S_0_S00_AXI_BASEADDR#defineMY_DMA_OFFSET MY_DMA_START_S_S00_AXI_SLV_REG0_OFFSETintmain() { XAxiDma AxiDma; XAxiDma_Config *Config; intstatus, i; u16 *RxBufferPtr = (u16 *)RX_BUFFER_BASE; xil_printf("---- Start DMA Receive Test ---- "); Config = XAxiDma_LookupConfig(DMA_DEV_ID); if(!Config) { xil_printf("No DMA config found! "); returnXST_FAILURE; } status = XAxiDma_CfgInitialize(&AxiDma, Config); if(status != XST_SUCCESS) { xil_printf("DMA Init Failed "); returnXST_FAILURE; } if(XAxiDma_HasSg(&AxiDma)) { xil_printf("DMA configured as SG mode! "); returnXST_FAILURE; } // 啟動接收 status = XAxiDma_SimpleTransfer(&AxiDma, (UINTPTR)RxBufferPtr, DATA_LENGTH *sizeof(u16), XAXIDMA_DEVICE_TO_DMA); if(status != XST_SUCCESS) { xil_printf("DMA Receive Config Failed "); returnXST_FAILURE; } //這里用于通知PL端開始發送數據 MY_DMA_START_S_mWriteReg(MY_DMA_START_ADDR,MY_DMA_OFFSET,1); usleep(5); MY_DMA_START_S_mWriteReg(MY_DMA_START_ADDR,MY_DMA_OFFSET,0); // 等待DMA完成(這里簡單用while輪詢)while(XAxiDma_Busy(&AxiDma, XAXIDMA_DEVICE_TO_DMA)); // 失效 Cache,保證讀到 DDR 最新數據 Xil_DCacheInvalidateRange((UINTPTR)RxBufferPtr, DATA_LENGTH *sizeof(u16)); // 打印接收數據for(i =0; i < DATA_LENGTH; i++) { ? ? ? ? xil_printf("DDR[%d] = 0x%04x ", i, RxBufferPtr[i]); ? ? } ? ? ?xil_printf("---- DMA Receive Done ---- "); ? ?return?XST_SUCCESS; }
2. 數據傳輸流程
啟動debug,在return XST_SUCCESS處打斷點,并查看memory中ddr的數據:

測試結果如下:

ila信號如下:

可以看到結果符合要求。
-
控制器
+關注
關注
114文章
17668瀏覽量
190660 -
DDR
+關注
關注
11文章
748瀏覽量
68597 -
AXI
+關注
關注
1文章
143瀏覽量
17809 -
Vivado
+關注
關注
19文章
848瀏覽量
70553
原文標題:基于AXI DMA IP核的DDR數據存儲與PS端讀取
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
ZYNQ SOC案例開發:AXI DMA使用解析及環路測試

基于AXI DMA IP核的DDR數據存儲與PS端讀取
評論