fpgavivado-hls

Vivado HLS design to read FIFO


I am trying to develop a system on FPGA to read data from the outer world (namely a Geiger pulse integrator, but at this point I am emulating it using an Arduino); the data stream is to be stored in a FIFO buffer, which I have implemented using the FIFO generator IP in Vivado. A little RTL module gets the data from the Arduino and succesfully writes it to the FIFO. In order to read the data from the FIFO output I need to set a read_enable to high, then wait for N clock cycles while storing the output in an array, and finally set the read_enable low again. And I need to do this in Vivado HLS (because I want to have AXI interface to a microprocessor). So far I have tried this (and some unsuccesful variations):

#include "ap_cint.h"

#define N 10

int readfifo(int fifo_dout, int1* fifo_rd_en, int data[N])
{
#pragma HLS INTERFACE s_axilite port=data
#pragma HLS INTERFACE ap_none register port=fifo_rd_en
#pragma HLS INTERFACE ap_none port=fifo_dout
#pragma HLS INTERFACE s_axilite port=return

    *fifo_rd_en=1;
    for(int i=0; i<10; i++)
    {
#pragma HLS PIPELINE off
        data[i] = fifo_dout;
    }
    *fifo_rd_en=0;
    return 1;
}

On different trials I have found two behaviours: either fifo_rd_en gets high and data is succesfully read but it never goes down again, or fifo_rd_en never gets high at all.

Is this approach wrong?

Thank you very much.


Solution

  • Since you're anyway using a Xilinx IP for generating the external FIFO, you can simply use the ap_fifo directive on fifo_dout and get rid of fifo_rd_en.

    Here is the modified code:

    int readfifo(int fifo_dout[N], int data[N])
    {
    #pragma HLS INTERFACE s_axilite port=data
    #pragma HLS INTERFACE s_axilite port=return
    #pragma HLS INTERFACE ap_fifo port=fifo_dout
      for(int i = 0; i < N; i++)
      {
    #pragma HLS PIPELINE II=1
        data[i] = fifo_dout[i];
      }
      return 1;
    }
    

    In this way, the read enable output signal is automatically included. Hence, there's no need to write it in the code. The following are the cosimulation waveforms of the synthesized HLS module.

    Waveforms of the FIFO read port. The read enable output signal is automatically included.

    As you can see, assuming the FIFO is not empty and already contains the N elements, the read enable stays on for N cycles and a new element is stored at each cycle.

    Note that this implementation adds a necessary check on whether the FIFO is empty. This means that, if the FIFO is empty, the resulting hardware module will wait for the i-th element to be available on the port. (This feature was missing in your intended implementation and could lead the hardware module to store meaningless data)

    p.s. If your implementation shall complete in N cycles no matter whether the FIFO is empty or not, you may want to switch to C++, where you have a FIFO class and its method read_nb()