1、算法原理参考:
https://blog.csdn.net/qq_36854651/article/details/104834563
2、matlab仿真程序如下:
function y=fft_func (x)
%本程序对输入序列 x实现DIT-FFT基2算法,点数取大于等于x长度的2的幂次
% x=randn(1,2^4);
m=nextpow2 (length(x)); %进行补零操作,满足2的整数幂----nextpow2(7)=3,
N=2 ^m; %求x的长度对应的2的最低幂次m,对应多少点的FFT
if length(x) <N
x=[x, zeros(1, N-length(x))] ;%若x的长度不是2的幂,补零到2的整数幂.
end
nxd=bin2dec (fliplr (dec2bin((1:N)-1,m)))+1; %求1:2^m数列的倒序
%bin2dec将二进制转换为10进制 flip1r倒叙排列 dec2bin把一个十进制数转换成一个字符串形式的二进制数
y=x(nxd) ; %将x倒序排列作为y的初始值,这样我们输出的数值和蝶形运算的数值相对应。
for mm=1 :m %将DFT作m次基2分解,从左到右,对每次分解作DFT运算——把DFT分成log2N段来实现
Nmr= 2 ^mm; %这里是旋转因子中的N
u=1; %初始化WN0=1
WN=exp (-1i*2*pi/Nmr) ; %本次分解的基本DFT因子WN=exp (-i*2*pi/ Nmr)
for j=1 :Nmr/2 %本次跨越间隔内的各次蝶形运算
for k=j :Nmr :N %本次蝶形运算的跨越间隔为Nmr=2 ^mm
kp=k+Nmr/2; %确定蝶形运算的对应单元下标.
t=y (kp) *u; %蝶形运算的乘积项
y (kp)=y(k) -t; %蝶形运算的加法项
y(k)=y(k) +t; %蝶形运算的加法项
end
u=u*WN; %修改旋转因子,多乘一个基本DFT因子WN
end
end
%% 生产FPGA仿真数据
input = tx.*2^10;
output = Gen_TxT(input(1:1:end));
function output = Gen_TxT(input)
N = length(input);
input = round(input);
%% real
fid=fopen('data_real.txt','w');
for k=1:N
fprintf(fid,'%d \n',real(input(k)));
end
fclose(fid)
%% imag
fid=fopen('data_imag.txt','w');
for k=1:N
fprintf(fid,'%d \n',imag(input(k)));
end
fclose(fid)
%%
output = N;
end
3、verilog实现1024点FFT,tb文件
//
// Created:
`resetall
`timescale 1ns/10ps
module FFT_1024_tb ;
reg clk;
reg rst;
wire [31:0] data_in;
reg [15:0] data_in_a,data_in_b;
wire [31:0] data_out;
integer i;
reg dinen;
reg [15:0] din_r0,din_i0;
wire [15:0] dout_r0,dout_i0;
wire [9:0]dout_addr;
FFT_1024_top FFT_1024(
.clk(clk),
.rst_n (~rst),
.din_en (dinen),
.din_real (din_r0),
.din_imag (din_i0),
//output
.dout_addr (),
.dout_real (),
.dout_imag (),
.dout_en (),
.abs_fft (),
.dout_start()
);
parameter clk_period = 10 ; //clk period
initial begin
clk=0;
forever # (clk_period/2) clk = ~clk;
end
initial begin
rst = 1;
# (clk_period*4) rst = 1'b0;
end
initial begin
dinen = 0;
# (clk_period*10) dinen = 1'b1;
// # (clk_period*1024) dinen = 1'b0;
end
///////////read////////////
integer r1,r2,i1,i2;
integer f_din_I0,f_din_Q0;
initial begin
f_din_I0 = $fopen("data_real.txt","r");
f_din_Q0 = $fopen("data_imag.txt","r");
end
always@(posedge clk)
begin
if(rst )begin
din_r0 <= 0;
din_i0 <= 0;
end
else if( dinen) begin
r1 =$fscanf(f_din_I0,"%d",(din_r0));
r2 =$fscanf(f_din_Q0,"%d",(din_i0));
end
else begin
din_r0 <= 0;
din_i0 <= 0;
end
end
endmodule
4、modelsim仿真结果(matlab产生多个频点正弦信号导入到modelsim仿真FFT算法)
5、如需代码可私信,代码FFT功能完整。