将 FFT 函数与阵列接口搭配使用 - 2023.2 简体中文

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 简体中文

含阵列实参的 FFT 函数在 HLS 名称空间内定义,可按如下方式调用:

hls::fft<STATIC_PARAM> (
INPUT_DATA_ARRAY,
OUTPUT_DATA_ARRAY, 
OUTPUT_STATUS, 
INPUT_RUN_TIME_CONFIGURATION);

STATIC_PARAM 属于静态参数化结构体,用于为 FFT 定义静态参数。

输入数据和输出数据都作为阵列(INPUT_DATA_ARRAYOUTPUT_DATA_ARRAY)提供给函数。在最终实现中,FFT RTL 块上的端口将作为 AXI4‑Stream 端口来实现。AMD 建议

重要: 您必须始终在数据流区域中使用 FFT 函数(使用 set_directive_dataflow),并使用 set_directive_stream 命令将两个阵列都指定为串流阵列。FFT 无法在经流水打拍的区域内使用。为了避免发生诸如在时钟周期内 FFT 停滞且不处理任何数据之类的情况,就需要高性能运算,为此:
  • 整个设计层级(包括 FFT 层级及其上层层级)都必须是数据流区域或仅包含循环数据流的函数。
  • 所有 FIFO 的深度必须足以避免在协同仿真中出现阻塞,如 协同仿真死锁检测 中所述。
  • 整个层级内的所有数据流进程都必须仅包含:
    • 带有回绕选项的流水线
    • 或者带有回绕选项的流水打拍循环

阵列的数据类型可采用 floatap_fixed

typedef float data_t;
complex<data_t> in_fft[FFT_LENGTH];
complex<data_t> out_fft[FFT_LENGTH];

要使用定点数据类型,应使用 Vitis HLS 任意精度类型 ap_fixed

#include "ap_fixed.h"
typedef ap_fixed<FFT_INPUT_WIDTH,1> data_in_t;
typedef ap_fixed<FFT_OUTPUT_WIDTH,FFT_OUTPUT_WIDTH-FFT_INPUT_WIDTH+1> data_out_t;
#include <complex>
typedef hls::x_complex<data_in_t> cmpxData;
typedef hls::x_complex<data_out_t> cmpxDataOut;

使用这 2 种类型时,都应使用相同且正确的数据大小来将 FFT 参数化。对于浮点数据,数据宽度始终为 32 位,指定任何其他大小都将被视为无效。

重要: FFT 的输入和输出宽度可配置为受支持范围内的任意值。连接到输入参数和输出参数的变量必须按 8 位增量来定义。例如,如果输出宽度配置为 33 位,那么输出变量必须定义为 40 位变量。

多通道 FFT

可通过针对输入数据和输出数据使用 2 维阵列来使用 FFT 的多通道功能。在此情况下,阵列数据的配置方法应为第 1 个维度表示每个通道,且第 2 个维度表示 FFT 数据。

typedef float data_t;
static complex<data_t> in_fft[FFT_CHANNELS][FFT_LENGTH];
static complex<data_t> out_fft[FFT_CHANNELS][FFT_LENGTH];

FFT 核使用并生成数据作为交织式通道(例如,ch0-data0、ch1-data0、ch2-data0 等,ch0-data1、ch1-data1、ch2-data1 等,以此类推)。因此,要按读取或写入数据的顺序来对 FFT 的输入或输出阵列进行串流,必须首先迭代通道索引,为多个通道填满或清空 2 维阵列,如下示例所示:

cmpxData   in_fft[FFT_CHANNELS][FFT_LENGTH];
cmpxData  out_fft[FFT_CHANNELS][FFT_LENGTH];
 
// Read data into FFT Input Array
for (unsigned i = 0; i < FFT_LENGTH; i++) {
 for (unsigned j = 0; j < FFT_CHANNELS; ++j) {
 in_fft[j][i] = in.read();
 }
}
   
// Write data out from FFT Output Array
for (unsigned i = 0; i < FFT_LENGTH; i++) {
 for (unsigned j = 0; j < FFT_CHANNELS; ++j) {
 out.write(out_fft[j][i]);
 }
}