一、参考文献
- 张丽君,大点数FFT的二维算法FPGA并行实现[J].
- 许丁鸿,一种2-D高速滑动FFT处理器的设计与硬件实现[D].
二、实现过程
算法推导和实现过程,可以参考以上两篇论文,下图截取自《一种2-D高速滑动FFT处理器的设计与硬件实现》2.5节内容。
三、Matlab代码
由于我在代码里注释写得特别清楚,这里就不废话了,直接上Matlab代码。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Zheng Wei, 2022/12/18
%% 用Matlab验证二维FFT算法实现过程的正确性,然后移植到FPGA中实现。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc; % 清除命令行窗口
clear all; % 清除所有变量、函数等
close all; % 关闭所有图形窗口
N=16384; % 总共为N点
L=1024; % 分成L行
C=N/L; % 分成C列
% 产生一个N点的离散序列
n=1:N;
y=n.*ones(1,N);
% 先直接做N点的一维FFT变换,以便与二维FFT变换的结果进行对比
fft1d_out = fft(y,N);
% -------------------------------------------------------
% 以下是二维FFT变换实现过程
% 第一步:将N点分成L行C列
for c=1:C
y1(:,c) = y(1,c:C:end); % 先分成C列,每列L点
end
% 第二步:做C次L点的列变换
% fft_col=fft(y1,L);
for c=1:C
y_col = y1(:,c); % 取出每列的L点
fft_col(:,c) = fft(y_col,L); % 再对每列做L点FFT变换
end
% 第三步:获得旋转因子WN_nk
for c=1:C
for l=1:L
nk=(2*pi*(c-1)*(l-1))/N; % 先得到nk
W(l,c)=cos(nk)-i*sin(nk); % 再得到旋转因子
% W1(l,c)=exp(-i*nk); % 再得到旋转因子
end
end
% 第四步:将列变换的结果乘以旋转因子WN_nk
fft_col_w=fft_col.*W;
% 第五步:做L次C点的行变换
% fft_row=fft(fft_col_w,C,2);
for l=1:L
y_row = fft_col_w(l,:); % 取出每行的C点
fft_row(l,:) = fft(y_row,C); % 再对每行做C点FFT变换
end
% 第六步:整序输出
for c=1:C
for l=1:L
fft2d_out(1,((c-1)*L)+l)=fft_row(l,c); % 从第一列依次到最后一列
end
end
% 将二维FFT变换的结果与一维FFT变换的结果进行对比,确认算法的正确性
% 除了很小的计算误差,两者的结果是一样的
fft_diff = fft2d_out - fft1d_out;
从matlab运行结果可以看到,二维FFT变换结果与一维FFT变换结果的最大误差也只有10^(-9),完全可以认为两者的计算结果是一致的。后续要做的工作,就是把Matlab代码实现过程迁移到FPGA上,用Verilog代码去实现,用Modelsim去做仿真验证,最后再上板测试了。