April 15, 2022
Editor’s Note: This content is republished from the MicroZed Chronicles, with permission from the author.
We looked at the AXI Virtual FIFO Controller in a blog a couple weeks ago and created an example design running on the Arty S7-50 while examining the input path. This design used the XADC to output an AXI stream which is input into a AXI Virtual FIFO Controller which then stores the samples in DDR. The read path of the example implemented a AXI Stream FIFO IP core connected to a MicroBlaze processor. This allows the MicroBlaze application to process the samples as they are pulled from the Virtual FIFO in the DDR.
In this blog, we are going to examine the output path that looks at how the AXI Stream FIFO is used to read out samples from the AXI Virtual FIFO in DDR.
If you have not come across it before, the AXI Stream FIFO allows developers to be able to access AXI streams from AXI memory mapped peripherals without the need to implement a full DMA solution. To enable this, the AXI Stream FIFO provides the ability to read and write from AXI MM to AXI streams. Just like this example, this can be used to interact with an AXI Virtual FIFO Controller or with IP like the Fast Fourier Transform which has configuration data over AXIS.
To interface with our designs, the AXI Stream FIFO provides the following interfaces:
The AXI Stream FIFO presents a simple register interface that enables the user to define the following:
Data is written or read from the AXI Stream FIFO via a memory address which writes into or reads from the FIFO.
In this application, we are only using the receive path to read from the AXI Virtual FIFO Controller using the MicroBlaze.
Setting this up in software is very straight forward. We need to do the following within the software:
#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;
}
The entire application as created can be access via my GitHub.
Having looked at the AXI Virtual FIFO Controller and the AXI Stream FIFO, these IP cores are both very useful in applications where we want to buffer large amounts of data and interact with AXI streams without the overhead of a DMA.