基於HLS的FFT核使用
HLS的FFT庫結構體定義
結構體定義及頭文件包含
#include <stdio.h>
#include <complex>
#include "hls_fft.h"
const char FFT_INPUT_WIDTH = 32;
const char FFT_OUTPUT_WIDTH = FFT_INPUT_WIDTH;
const char FFT_CONFIG_WIDTH = 24;
const char FFT_NFFT_MAX = 10;
const int FFT_LENGTH = 1 << FFT_NFFT_MAX;
struct config1 : hls::ip_fft::params_t
{
static const unsigned input_width = FFT_INPUT_WIDTH;
static const unsigned output_width = FFT_OUTPUT_WIDTH;
static const unsigned ordering_opt = hls::ip_fft::natural_order;
static const unsigned config_width = FFT_CONFIG_WIDTH;
static const bool has_nfft = true;
static const unsigned max_nfft = FFT_NFFT_MAX;
};
const int max = 1 << FFT_INPUT_WIDTH; // might not work for > 32 bits!
const int max_half_minus_one = (max/2)-1;
const double sc = ldexp(1.0, FFT_INPUT_WIDTH-1); // 1*2^(FFT_INPUT_WIDTH-1)
重定義定點型數據
typedef hls::ip_fft::config_t<config1> config_t;
typedef hls::ip_fft::status_t<config1> status_t;
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;
typedef std::complex<data_in_t> cmpxDataIn;
typedef std::complex<data_out_t> cmpxDataOut;
實時參數設置
config_t fft_config;
fft_config.setDir(0); //用來配置FFT:0正向 1反向
fft_config.setSch(0x57B);//用來設置縮放因子[01 01 01 11 10 10]
fft_config.setNfft(nfft); //用來設置FFT點數
函數主體
void access_src(unsigned short *pSrc, cmpxDataIn in[FFT_LENGTH], int len)
{
double input_data_re;
unsigned short cachemem[128], d;
for(int i=0;i<len;)
{
#pragma HLS pipeline
#pragma HLS loop_tripcount min=1 max=16
int m = ((len-i)>128) ? 128 : len-i;
memcpy(cachemem, &pSrc[i], m*sizeof(unsigned short));
for(int k=0;k<m;k++)
{
#pragma HLS loop_tripcount min=1 max=128
d = cachemem[k];
input_data_re = (d > max_half_minus_one) ? (d-(max-1))/sc : d/sc;
in[i+k] = cmpxDataIn(input_data_re, 0);
}
i += m;
}
}
void access_dst(unsigned short *pDst, cmpxDataOut out[FFT_LENGTH], int len)
{
unsigned short cachemem[128];
for(int i=0;i<len;)
{
#pragma HLS pipeline
#pragma HLS loop_tripcount min=1 max=16
int m = ((len-i)>128) ? 128 : len-i;
for(int k=0;k<m;k++)
{
#pragma HLS loop_tripcount min=1 max=128
float An = sqrt(out[i+k].real().to_float()*out[i+k].real().to_float()+out[i+k].imag().to_float()*out[i+k].imag().to_float());
cachemem[k] = An*sc;
}
memcpy(&pDst[i], cachemem, m*sizeof(unsigned short));
i += m;
}
}
void getfft_2d(int nfft, unsigned short *pSrc, unsigned short *pDst)
{
#pragma HLS INTERFACE s_axilite port=nfft
#pragma HLS INTERFACE m_axi port=pSrc offset=slave
#pragma HLS INTERFACE m_axi port=pDst offset=slave
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS dataflow
config_t fft_config;
status_t fft_status;
cmpxDataIn xn[FFT_LENGTH];
cmpxDataOut xk[FFT_LENGTH];
fft_config.setDir(0); //正向FFT
fft_config.setSch(0x57B);
fft_config.setNfft(nfft);
access_src(pSrc, xn, 1<<nfft);
hls::fft<config1>(xn, xk, &fft_status, &fft_config);
access_dst(pDst, xk, 1<<nfft);
}
- 歡迎關注微信公衆號【電子物語】,更多精彩等着你