配置PL DDR4
我用的是vivado 2023
配置完成以后,将bit文件烧写入MPSOC以后, 调试窗口会出现一个这样的子窗口,表示我们正确配置了ddr4 ip核. 有可能显示未通过字样的原因,我将在后面一起说明.
首先FPGA通过调用MIG IP核向DDR4芯片写入数据,写完之后通过MIG IP核从DDR4芯片读出所写入的数据,并判断读出的数据与写入的数据是否相同,如果相同则LED灯常亮,否则LED灯闪烁.
至此, 这些步骤可以根据alinx官方提供的例程来实现.
创建block design如下图
给ddr4 ip加axi接口从ps验证 pl ddr 数据是否可读可写
生成xsa文件,ps端测试代码如下:
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
/*
#define XPAR_DDR4_0_BASEADDRESS 0x400000000
这个宏定义的地址,是vivado bd设计通过以后 自动分配的地址.
*/
#define BUF_SIZE (256)
int main()
{
init_platform();
print("Hello World\n\r");
print("Successfully ran Hello World application\r\n");
int i = 0;
unsigned int sendBuff[BUF_SIZE ] = {0};
unsigned int recvBuff[BUF_SIZE ] = {0};
for(i = 0; i < BUF_SIZE ; i++)
{
sendBuff[i] = i;
xil_printf("sendBuff[%d] = %d\r",i,sendBuff[i]);
usleep(20000);
}
for(i = 0; i < BUF_SIZE ; i++)
{
Xil_Out32((XPAR_DDR4_0_BASEADDRESS + i*4),sendBuff[i]);
}
for(i = 0; i < BUF_SIZE ; i++)
{
recvBuff[i] = Xil_In32((XPAR_DDR4_0_BASEADDRESS + i*4));
xil_printf("recvBuff[%d] = %d\r\n",i,recvBuff[i]);
}
cleanup_platform();
return 0;
}
ps端具体代码可以通过vitis生成
至此, ps 读取pl 端的ddr4 已经调通, 这为我们接下来创建 vfifo提供基础.
创建基于PL DDR4 的 VFIFO
VFIFO ,该模块处理将AXI MM空间转换为FIFO的所有要求。它管理DRAM地址并生成每个通道FIFO状态信号
将VFIFO 模块加入bd文件, 并通过axi stream fifo ip 实例化fifo.在我的理解,VFIFO只是把我们创建的fifo映射到指定内存地址的这么一个ip, 通过把axi stream fifo ip与VFIFO 连在一起,相当于这个axi stream fifo 有了ddr4的内存地址, 从而摆脱了bram空间不足的尴尬.
通过ps端的内存窗口,可以看出,这就是我写入fifo的数据与地址.
如果需要创建多个AXI STREAM FIFO 并映射到VFIFO要怎么操作?
我们以创建2个AXI STREAM FIFO为列.
当我配置好了2个fifo数据回环, 并通过ps控制读写axi_fifo_mm_s_1 时, 红色线应该走的数据流,
实际数据最后走了M00_AXIS 出来了, 这与我的设计不符.如下图
此时想到了, axi interconnect 0 是否需要配置, 标记不同通道进来的数据.通过查看pg038第8页,发现官方推荐的是axis switch.
那就把axi interconnect 改成axi switch试一试,如下, 结果还是不行.
在查阅了多个资料以后,感觉跟axi4 总线的tdest信号有关, 本以为axis switch 会自己生成不同的tdest, 实际上需要通过ps端配置.
图上文档说, 先写tdr寄存器也就是tdest,再放data到fifo中,最后写tlr也就是lenth寄存器.
根据要求将tdr 寄存器写成1, 也就是vfifo的第二通道.
最后在ps memory窗口中得到验证: 第二通道地址是(0x40000 0000 + 8000)
至此, 基于 PL DDR4 VFIFO 验证成功.