跳转到主要内容

FPGA项目开发之AXI Stream FIFO IP

作者: 碎碎思,本文转载自:<span id="profileBt"><a href="https://mp.weixin.qq.com/s/wV0r5hcdE53bxJ4QAMCJ4g">OpenFPGA微信公众号</a></s…;

Xilinx Vivado中提供了AXI FIFO和AXI virtual FIFO类似IP,这篇文章主要通过实例来讲解这两个IP的使用方法。

<strong>AXI Virtual FIFO Controller</strong>

FIFO 是我们设计中常用的工具,因为它们使我们能够在进行信号和图像处理时缓冲数据。我们还使用异步FIFO来处理数据总线的时钟域交叉问题。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277767-1.png…; alt=""></center>

FIFO 的挑战之一是存储大量数据需要 FPGA 内的大量资源。当然,这在较小的 FPGA 中可能是一个问题,因为 BRAM 资源是有限的。但在许多情况下,较小的 FPGA 可能会连接外部存储器,如 DDR3 或 DDR3L。开发人员可以使用此存储器通过直接存储器访问 (DMA) 在 DDR 存储器存储外部缓冲数据。

AMD-Xilinx 提供了一个称为 AXI Virtual FIFO Controller 的 IP 内核,以简化开发人员希望使用 DDR 存储器将信号或数据样本存储在外部 DDR 中作为 FIFO 的情况。

AXI Virtual FIFO Controller为开发人员提供可连接到信号处理路径的主从 AXI 流端口。与 DDR 存储器的接口由完整的 AXI 接口提供。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277768-2.png…; alt=""></center>

使用这些接口,AXI Virtual FIFO Controller能够在 DDR 中创建一个 FIFO,并且能够存储比使用内部 BRAM 更大数量的数据。

AXI Virtual FIFO Controller能够将多个通道数据存储在外部 DDR 中。需要注意的一件事是内存位置与其他内存使用(例如,MicroBlaze 应用程序)可能会发生冲突。在 IP 定制时,我们能够分配的空间需要注意。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277769-3.png…; alt=""></center>

接下来创建一个以 Xilinx FPGA(S7-50 )为目标的小项目,项目主要演示AXI Virtual FIFO Controller的工作原理。在本设计中,XADC 是要写入 DDR 的 AXI Stream 数据的来源,DDR 可以通过 AXI Stream 输出其样本。

AXI Virtual FIFO Controller 的输出(读取通道)连接到 AXI Stream FIFO ,最后处理器通过 AXI4-Lite 接口读取数据。

下面显示了设计中的输入路径,其中包含由 XADC 生成的信号和一个subset convertor,用于将 TLast 信号添加到 AXI 流。AXI ILA 使 XADC 生成的数据能够与我们稍后在 DDR 存储器中看到的数据进行对比。然后,信号通过 AXI Virtual FIFO Controller进入 DDR。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277770-4.png…; alt=""></center>

输出路径类似。它从 DDR 通过 SMC 进入 AXI Virtual FIFO Controller,然后输出到 AXI Stream FIFO,MicroBlaze 就可以访问它。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277771-5.png…; alt=""></center>

将此下载到 FPGA 后,我们可以运行一个简单的 hello world 应用程序,暂停程序,并观察 AXI Virtual FIFO Controller缓冲数据的 DDR 内存位置。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277772-6.png…; alt=""></center>

该数据可以通过观察 Vivado ILA 来对比。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277773-7.png…; alt=""></center>

输出路径需要 AXI Stream FIFO 断言 Tready 信号。为此,我们需要使用 MicroBlaze 上运行的软件配置 AXI Stream FIFO。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277774-8.png…; alt=""></center>

<strong>AXI Stream FIFO</strong>

在本节中,我们将继续检查输出路径,了解如何使用AXI Stream FIFO 从 DDR 中的 AXI Virtual FIFO Controller读取样本。
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277775-9.png…; alt=""></center>

AXI Stream FIFO 允许开发人员能够从 AXI 内存映射外设访问 AXI 流,而无需实施完整的 DMA 解决方案。为了实现这一点,AXI Stream FIFO 提供了从 AXI MM 到 AXI 流的读写能力。就像此示例一样,这可用于与AXI Virtual FIFO Controller或 IP 进行交互,例如快速傅里叶变换,它具有通过 AXIS 的配置数据。

为了与我们的设计交互,AXI Stream FIFO 提供了以下接口:

RX Stream Data – 这是要由 AXI Stream FIFO 接收的数据

TX Stream Data — 这是由 AXI Stream FIFO 传输的数据

TX Stream Control Data – 此接口支持 AXI 以太网 IP 内核的传输协议

AXI Lite – 用于访问配置寄存器和数据 Tx 和 Rx 数据的内存映射接口

AXI MM – 用于数据 Tx/Rx 的可选 AXI MM 接口
<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277777-11.pn…; alt=""></center>

AXI Stream FIFO 提供了一个简单的寄存器接口,使用户能够定义以下内容:

Transmission Length——要传输的数据的长度

Transmission Vacancy – FIFO 中当前空的位置

Receive Length – 接收到的数据包的长度

Receive Occupancy – FIFO 中占用的插槽数

Receive / Transmission Destination – 边带 AXIS 信号 TIDest

Receive / Transmission ID – Side band AXIS 信号 TId

Receive / Transmission User – Side band AXIS 信号 TUser

系统/传输和接收中断

系统/传输和接收复位

通过写入 FIFO 或从 FIFO 读取的内存地址从 AXI Stream FIFO 写入或读取数据。

在此应用程序中,我们仅使用接收路径使用 MicroBlaze 从 AXI Virtual FIFO Controller读取样本。

在软件中设置非常简单。我们需要在软件中执行以下操作:

配置 AXI Stream FIFO

读取FIFO的占用情况

从 FIFO 中读出指定的字数

在应用软件中根据需要处理样品

#include <stdio.h>

#include "platform.h"

#include "xil_printf.h"

#include "xstreamer.h"

#include "xllfifo.h"

#define FIFO_DEV_ID XPAR_AXI_FIFO_0_DEVICE_ID

#define WORD_SIZE 4

XLlFifo_Config *Config;

XLlFifo FifoInstance;

int main()

{

int Status,i;

u32 RxWord;

static u32 ReceiveLength;

init_platform();

Config = XLlFfio_LookupConfig(FIFO_DEV_ID);

XLlFifo_CfgInitialize(&FifoInstance, Config, Config->BaseAddress);

print("Hello World\n\r");

print("Successfully ran Hello World application");

/* Check for the Reset value */

Status = XLlFifo_Status(&FifoInstance);

XLlFifo_IntClear(&FifoInstance,0xffffffff);

Status = XLlFifo_Status(&FifoInstance);

if(Status != 0x0) {

xil_printf("\n ERROR : Reset value of ISR0 : 0x%x\t"

"Expected : 0x0\n\r",

XLlFifo_Status(&FifoInstance));

return XST_FAILURE;

}

while(1){

while(XLlFifo_iRxOccupancy(&FifoInstance)) {

/* Read Receive Length */

ReceiveLength = (XLlFifo_iRxGetLen(&FifoInstance))/WORD_SIZE;

for (i=0; i < ReceiveLength; i++) {

RxWord = XLlFifo_RxGetWord(&FifoInstance);

printf("%x \n\r",RxWord);

}

}

}

cleanup_platform();

return 0;

}

源程序如下:

https://github.com/ATaylorCEngFIET/MZ_439

<center><img src="https://cdn.eetrend.com/files/2022-11/wen_zhang_/100565483-277776-10.pn…; alt=""></center>

查看 AXI Virtual FIFO Controlle和 AXI Stream FIFO 后,这些 IP 内核在我们希望缓冲大量数据并与 AXI 流交互而无需 DMA 开销的应用中都非常有用。