Using FIR Function with Streaming Interface - 2022.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-12-07
Version
2022.2 English

The run() function with streaming interfaces and without config input is defined in the HLS namespace similar to this:

 void run(
 hls::stream<in_data_t> &in_V,
 hls::stream<out_data_t> &out_V);

With config input, it is defined similar to this:

 void run(
 hls::stream<in_data_t> &in_V,
 hls::stream<out_data_t> &out_V,
 hls::stream<config_t> &config_V);

The FIR function is defined in the HLS namespace and can be called as follows:

// Create an instance of the FIR
static hls::FIR<STATIC_PARAM> fir1;
// Execute the FIR instance fir1
fir1.run(INPUT_DATA_STREAM, OUTPUT_DATA_STREAM);

The STATIC_PARAM is the static parameterization struct that defines most static parameters for the FIR. Both the input and output data are supplied to the function as hls::stream<>. These ports on the FIR IP will be implemented as AXI4-Stream ports.

Xilinx recommends always using the FIR function in a dataflow region using set_directive_dataflow or #pragma HLS dataflow.

Important: The FIR cannot be used in a region which is pipelined. If high-performance operation is required, pipeline the loops or functions before and after the FIR then use dataflow optimization on all loops and functions in the region.
The multichannel functionality of the FIR is supported through interleaving the data in a single input and single output stream.
  • The size of the input stream should be large enough to accommodate all samples: num_channels * input_length
  • The output stream size should be specified to contain all output samples: num_channels * output_length

The following code example demonstrates how the FIR IP function can be used.

template<typename data_t, int LENGTH>
void process_fe(data_t in[LENGTH], hls::stream<data_t> &out)
{
    for(unsigned i = 0; i < LENGTH; ++i)
        out.write(in[i]);
}

template<typename data_t, int LENGTH>
void process_be(hls::stream<data_t> &in, data_t out[LENGTH])
{
    for(unsigned i = 0; i < LENGTH; ++i)
        out[i] = in.read();
}

// TOP function
void fir_top(
    data_t in[FIR1_LENGTH],
    data_out_t out[FIR2_LENGTH])
{

    #pragma HLS dataflow

    hls::stream<data_t> fir1_in;
    hls::stream<data_intern_t> fir1_out;
    hls::stream<data_out_t> fir2_out;

    // Create FIR instance
    static hls::FIR<config1> fir1;
    static hls::FIR<config2> fir2;

    //==================================================
    // Dataflow process
    process_fe<data_t, FIR1_LENGTH>(in, fir1_in);
    fir1.run(fir1_in, fir1_out);
    fir2.run(fir1_out, fir2_out);
    process_be<data_out_t, FIR2_LENGTH>(fir2_out, out);
    //==================================================
}