在做32点fft vivado实现时,对比matlab结果,发现对不上,是我代码有问题吗
IP核配置
俩出来的结果
matlab 代码
Fs = 1e9 ;
t = 0:1/Fs:31/Fs ;
length = 32 ;
n = 1:length ;
f1 = 31.25e6 ;
f2 = 300e6 ;
s1 = cos(2*pi*f1*t) ;
s2 = cos(2*pi*f2*t) ;
signalN = s1 + s2 ;
data_before_fft = 100* signalN ; %系数放大100倍
figure;hold on ;
plot(n, s1) ;
plot(n, s2) ;
hold off ;
figure;plot(n(1:32), signalN(1:32)) ;
title('输入信号') ;
fp = fopen('data_before_fft.txt','w') ;
for i = 1:length
if(data_before_fft(i)>=0)
temp = dec2bin(data_before_fft(i),16) ;
else
temp = dec2bin(data_before_fft(i)+2^16+1,16) ;
end
% temp = s_bin(i,:);
for j = 1:16
fprintf(fp,'%s',temp(j)) ;
end
fprintf(fp,'\r\n') ;
end
fclose(fp) ;
data_after_fft1 = fft(data_before_fft) ;
data_after_fft = data_after_fft1.' ;
data_real = real(data_after_fft) ;
data_imag = imag(data_after_fft) ;
data_r_i = [data_real, data_imag];
vivado 代码
module fft(
input wire clk,
input wire [15:0] din,
input wire last,
input wire s_axis_data_tvalid,
output wire [15:0] m_axis_data_tdata_r,
output wire [15:0] m_axis_data_tdata_i,
output wire [7:0] index
);
wire [31:0]s_axis_data_tdata;
wire [7:0]s_axis_config_tdata = {7'b0,1'b1};//NO need run time change length!
wire s_axis_config_tvalid = 1;
wire s_axis_config_tready ;
wire s_axis_data_tready ;
//wire s_axis_data_tlast = 0;
//wire s_axis_data_tvalid = 1 ;
//wire [7:0] index;
wire m_axis_data_tvalid;
wire m_axis_data_tready = 1;
wire m_axis_data_tlast=0;
wire event_frame_started;
wire event_tlast_unexpected;
wire event_tlast_missing;
wire event_status_channel_halt;
wire event_data_in_channel_halt;
wire event_data_out_channel_halt;
wire [31:0] m_axis_data_tdata;
assign s_axis_data_tdata = {16'b0,din};
assign m_axis_data_tdata_r = m_axis_data_tdata[15:0];
assign m_axis_data_tdata_i = m_axis_data_tdata[31:16];
xfft_0 fft_test (
.aclk(clk), // input wire aclk
.s_axis_config_tdata(s_axis_config_tdata), // input wire [7 : 0] s_axis_config_tdata
.s_axis_config_tvalid(s_axis_config_tvalid), // input wire s_axis_config_tvalid
.s_axis_config_tready(s_axis_config_tready), // output wire s_axis_config_tready
.s_axis_data_tdata(s_axis_data_tdata), // input wire [31 : 0] s_axis_data_tdata
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tlast(last), // input wire s_axis_data_tlast
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_data_tuser(index), // output wire [7 : 0] m_axis_data_tuser
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tready(m_axis_data_tready), // input wire m_axis_data_tready
.m_axis_data_tlast(m_axis_data_tlast), // output wire m_axis_data_tlast
.event_frame_started(event_frame_started), // output wire event_frame_started
.event_tlast_unexpected(event_tlast_unexpected), // output wire event_tlast_unexpected
.event_tlast_missing(event_tlast_missing), // output wire event_tlast_missing
.event_status_channel_halt(event_status_channel_halt), // output wire event_status_channel_halt
.event_data_in_channel_halt(event_data_in_channel_halt), // output wire event_data_in_channel_halt
.event_data_out_channel_halt(event_data_out_channel_halt) // output wire event_data_out_channel_halt
);
endmodule
tb
module tb_fft();
reg clk;
reg [15:0] din;
reg [15:0] stimulus[1:32];//32位
integer count;
integer i;
integer file;
wire [15:0] data_real;
wire [15:0] data_imag;
wire [7:0] index;
reg last;
reg s_axis_data_tvalid;
initial begin
clk = 0;
din = 0;
count = 0;
last = 0;
s_axis_data_tvalid = 0;
#10;
$readmemb("C:/Users/hp/OneDrive/桌面/FFT/data_before_fft.txt", stimulus);
file = $fopen("C:/Users/hp/OneDrive/桌面/FFT/data_before_fft.txt", "w");
#10;
for(i = 1;i<=32;i = i+1)begin
s_axis_data_tvalid = 1;
din = stimulus[i];
#4;
end
last = 1;
s_axis_data_tvalid = 0;
din = 16'b0;
end
always # 2 clk = ~clk;
always @(posedge clk) begin
$fwrite(file,"%h\n", data_real); //data_o为需要保存的信号数据
if(count > 2500)
$fclose(file);
count = count + 1;
end
fft fft_test(
.clk(clk),
.din(din),
.last(last),
.s_axis_data_tvalid(s_axis_data_tvalid),
.m_axis_data_tdata_r(data_real),
.m_axis_data_tdata_i(data_imag),
.index(index)
);
endmodule
对于FPGA实现的FFT结果和Matlab结果不一致的情况,有以下几点需要检查:
根据您提供的信息,目前无法确切判断代码是否有问题。但是,有几个方面可能会导致结果不匹配:
Vivado的FFT IP核设置不正确。请确保您正确配置了FFT IP核,并与Matlab的FFT设置相匹配。例如,FFT的长度、窗函数等应该一致。
Matlab的FFT函数和Vivado的FFT IP核的数据输入格式不匹配。请确认您在Vivado中正确处理了数据的格式,以便与Matlab的输入格式相匹配。
数据缩放不正确。根据您提供的代码,您将信号数据放大了100倍。请确保在Vivado中也进行了相同的缩放。
数据转换不正确。您在Matlab中使用了16位的二进制数据,但是没有提供Vivado中数据的处理方式。请确保您正确地转换了数据格式。
为了更好地帮助您解决问题,我建议您提供更多关于Vivado实现FFT的代码和设置的细节。同时,您可以尝试使用MATLAB验证FFT数据是否正确。下面是一种可能的解决方案:
首先,确保您的FFT设置正确。比如,FFT的长度应为32点。
N = 32; % FFT的长度
data_after_fft_matlab = fft(data_before_fft, N);
接下来,将MATLAB的FFT结果与Vivado的FFT结果进行比较,并输出不匹配的点。
diff = abs(data_after_fft_matlab - data_after_fft);
mismatch_idx = find(diff > 1e-6);
disp("不匹配的点:");
disp(mismatch_idx);
您可以使用以上代码查找不匹配的点,以确定问题所在。如果找不到问题,我建议您仔细检查Vivado设置和代码实现,确保与Matlab一致,并尝试调整参数和数据处理方法。
代码错误比较多,给你修改了一下。
注意:波形文件的路径我修改了。你要将波形文件复制到正确的文件夹
FFT IP 需要修改
代码也需要修改
module tb_fft();
reg clk;
reg [15:0] din;
reg [15:0] stimulus[1:32];//32位
integer count;
integer i;
integer file_r,file_i;
wire signed[15:0] data_real;
wire signed[15:0] data_imag;
wire [7:0] index;
wire s_axis_data_tready;
wire m_axis_data_tvalid;
reg last;
reg s_axis_data_tvalid;
initial begin
clk = 0;
din = 0;
count = 0;
last = 0;
s_axis_data_tvalid = 0;
#10;
$readmemb("d:/demo/data_before_fft.txt", stimulus); //文件存放的路径别有中文
file_r = $fopen("d:/demo/data_before_fftr.txt", "w+");
file_i = $fopen("d:/demo/data_before_ffti.txt", "w+");
if(s_axis_data_tready == 0) //等到 AXIS 准备好
#100;
for(i = 1;i<=32;i = i+1)begin
s_axis_data_tvalid = 1;
din = stimulus[i];
if(i==32) last = 1;
else last = 0;
#4;
end
last = 0;
s_axis_data_tvalid = 0;
din = 16'b0;
end
always # 2 clk = ~clk;
always @(posedge clk) begin
if(count >= 32)begin
$fclose(file_r);
$fclose(file_i);
end
else begin
if(m_axis_data_tvalid == 1) //输出数据有效才写文件
begin
$fwrite(file_r,"%d\n", data_real);
$fwrite(file_i,"%d\n", data_imag);
count <= count + 1;
end
end
end
fft fft_test(
.clk(clk),
.din(din),
.last(last),
.s_axis_data_tvalid(s_axis_data_tvalid),
.s_axis_data_tready(s_axis_data_tready),
.m_axis_data_tdata_r(data_real),
.m_axis_data_tdata_i(data_imag),
.m_axis_data_tvalid(m_axis_data_tvalid),
.index(index)
);
endmodule
module fft(
input wire clk,
input wire [15:0] din,
input wire last,
input wire s_axis_data_tvalid,
output wire s_axis_data_tready,
output wire [15:0] m_axis_data_tdata_r,
output wire [15:0] m_axis_data_tdata_i,
output wire m_axis_data_tvalid,
output wire [7:0] index
);
reg cfg_s=0;
wire [31:0] s_axis_data_tdata;
wire [7:0] s_axis_config_tdata = {7'b0,1'b0};//NO need run time change length!
reg s_axis_config_tvalid = 0;
wire s_axis_config_tready ;
//wire [7:0] index;
wire m_axis_data_tvalid;
wire m_axis_data_tready = 1;
wire m_axis_data_tlast;
wire event_frame_started;
wire event_tlast_unexpected;
wire event_tlast_missing;
wire event_status_channel_halt;
wire event_data_in_channel_halt;
wire event_data_out_channel_halt;
wire [31:0] m_axis_data_tdata;
assign s_axis_data_tdata = {16'b0,din};
assign m_axis_data_tdata_r = m_axis_data_tdata[15:0];
assign m_axis_data_tdata_i = m_axis_data_tdata[31:16];
always@(posedge clk)
begin
if(s_axis_config_tready == 1 && cfg_s == 0)
begin
s_axis_config_tvalid <= 1;
cfg_s <= 1;
end
else
s_axis_config_tvalid <= 0;
end
xfft_0 fft_test (
.aclk(clk), // input wire aclk
.s_axis_config_tdata(s_axis_config_tdata), // input wire [7 : 0] s_axis_config_tdata
.s_axis_config_tvalid(s_axis_config_tvalid), // input wire s_axis_config_tvalid
.s_axis_config_tready(s_axis_config_tready), // output wire s_axis_config_tready
.s_axis_data_tdata(s_axis_data_tdata), // input wire [31 : 0] s_axis_data_tdata
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tlast(last), // input wire s_axis_data_tlast
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_data_tuser(index), // output wire [7 : 0] m_axis_data_tuser
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tready(m_axis_data_tready), // input wire m_axis_data_tready
.m_axis_data_tlast(m_axis_data_tlast), // output wire m_axis_data_tlast
.event_frame_started(event_frame_started), // output wire event_frame_started
.event_tlast_unexpected(event_tlast_unexpected), // output wire event_tlast_unexpected
.event_tlast_missing(event_tlast_missing), // output wire event_tlast_missing
.event_status_channel_halt(event_status_channel_halt), // output wire event_status_channel_halt
.event_data_in_channel_halt(event_data_in_channel_halt), // output wire event_data_in_channel_halt
.event_data_out_channel_halt(event_data_out_channel_halt) // output wire event_data_out_channel_halt
);
endmodule