基于AXI DMA IP核的DDR数据存储与PS端读取

描述

Vivado工程搭建

1. 创建基础工程

新建Vivado项目,选择目标FPGA型号。

添加Zynq Processing System IP核,配置DDR控制器和时钟。7000系列的Zynq可以参考正点原子DMA回环测试设置。

AXI

AXI

2. 添加AXI DMA IP核

配置AXI DMA为Simple模式。

设置数据位宽(如32/64位)和Width of Buffer Lenghth Register(26最大可以存2^26 bit)。

AXI

3. 添加Stream Data FIFO

这里看需要设置FIFO 深度

AXI

4. 添加自定义ip用于产生数据

这里可以参考https://fpga.eetrend.com/blog/2023/100568155.html,由于工程需要,对ip进行修改,使得传输的数据位宽是16位,一共传输320*256个数据。修改位宽后re-package可能会出现报错,请自行查找解决办法。

AXI

AXI

5. 添加自定义ip用于产生dma_start信号

由于dma传输过程中会出现数据丢失情况,这里借鉴了以下博主的解决方法:ZYNQ踩坑日记:AXI_DMA传输问题详解——问题再续篇-物联沃-IOTWORD物联网对于vivado中使用DMA传输数据时会丢数据的解决办法_vivado dma-CSDN博客

AXI

对数据产生ip进行了修改(右键ip->edit in packager),使得dma初始化之后再开始传输数据,避免数据丢失

AXI

在关键代码中进行如下修改:

AXI

最后再Re-Package IP,可以参考https://cloud.tencent.com/developer/article/1813652创建并修改自定义ip。

6. 连接IP核与总线

总体block design如下

AXI

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"#define DMA_DEV_ID      XPAR_AXIDMA_0_DEVICE_ID#define DDR_BASE_ADDR   XPAR_PSU_DDR_0_S_AXI_BASEADDR#define RX_BUFFER_BASE (DDR_BASE_ADDR + 0x01000000)#define DATA_LENGTH     81920// 与 PL 端对应#define MY_DMA_START_ADDR XPAR_MY_DMA_START_S_0_S00_AXI_BASEADDR#define MY_DMA_OFFSET MY_DMA_START_S_S00_AXI_SLV_REG0_OFFSETint main() {     XAxiDma AxiDma;     XAxiDma_Config *Config;    int status, 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!
");        return XST_FAILURE;     }      status = XAxiDma_CfgInitialize(&AxiDma, Config);    if (status != XST_SUCCESS) {         xil_printf("DMA Init Failed
");        return XST_FAILURE;     }    if (XAxiDma_HasSg(&AxiDma)) {         xil_printf("DMA configured as SG mode!
");        return XST_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
");        return XST_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的数据:

AXI

测试结果如下:

AXI

ila信号如下:

AXI

可以看到结果符合要求。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分