Vivado FFT9.0仿真验证

在网上看了很多的介绍,基本都是一样的,但是根据这些博客,自己验证了下发现结果和matlab中不一样。

1.配置IP核

用vivado17.2 IP版本为9.0,配置首先配置最大长度为64,时钟为100MHz,将长度可以改变选中,如下图所示:

进一步的配置,设置数据为整型,未缩放,输入16bit,输出自然顺序(不然虚部不方便验证)。

第三页默认

2.tb编写

module AA_tb;

reg aclk;
reg aresetn;
reg [15 : 0] s_axis_config_tdata;
reg s_axis_config_tvalid;
wire s_axis_config_tready;
reg [31 : 0] s_axis_data_tdata;
reg s_axis_data_tvalid;
wire s_axis_data_tready;
reg s_axis_data_tlast;
wire [47 : 0] m_axis_data_tdata;
wire [7 : 0] m_axis_data_tuser;
wire m_axis_data_tvalid;
reg m_axis_data_tready;
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;

reg [11:0] mem0_re[256:0];
reg [7:0] op_sample= 0;
reg op_sample_first = 1;
reg [7:0] ip_frame=0;
reg [7:0] op_frame=0;

// initial $readmemh("C:/Users/74339/Desktop/vivado_code/fft_test/signal.txt",mem0_re);
integer i;
reg s_data;

always #5 aclk = !aclk;

initial begin
// Initialize Inputs
aclk = 0;
aresetn = 0;
s_axis_config_tvalid = 0;
s_axis_config_tdata = 0;
s_axis_data_tvalid = 0;
s_axis_data_tdata = 0;
s_axis_data_tlast = 0;
m_axis_data_tready = 0;
s_data = 0;
i = 0;
// Wait 100 ns for global reset to finish
#150;
aresetn = 1;
m_axis_data_tready = 1;
s_axis_config_tvalid = 1;
s_axis_config_tdata = 16'b0101100101000100; // FFT desired (and not IFFT
//s_axis_config_tdata = 24'b100100000000000100; // FFT desired (and not IFFT

s_axis_data_tlast = 1;
s_axis_data_tdata = 48'h000000;
s_axis_data_tvalid = 0;

#3000;
aresetn = 0;
#300;
aresetn = 1;
m_axis_data_tready = 1;
s_axis_config_tvalid = 1;
s_axis_config_tdata = 16'b0101100101000110; // FFT desired (and not IFFT
//s_axis_config_tdata = 24'b100100000000000111; // FFT desired (and not IFFT

s_axis_data_tlast = 1;
s_axis_data_tdata = 48'h000000;
s_axis_data_tvalid = 0;

s_axis_data_tvalid = 0;
end

reg ff;

always @(posedge aclk)
begin
if(s_axis_data_tready == 1)
ff <= 1'b1;
else
ff <= ff;

end

reg [9:0] cntttt=0;

always @(posedge aclk)
begin
if(ff == 0)
cntttt <= 10'b0;
else if(cntttt==1023)
cntttt <= cntttt;
else
cntttt <= cntttt+1;

end

always @(posedge aclk)
begin
if((cntttt >= 800)&&(cntttt <= 814))
begin
s_axis_data_tvalid <= 1;
s_axis_data_tdata <=s_axis_data_tdata+1;
s_axis_data_tlast <= 0;
end
else if(cntttt == 815)
begin
s_axis_data_tvalid <= 1;
s_axis_data_tdata <=s_axis_data_tdata+1;
s_axis_data_tlast <= 1;
end

else
begin
s_axis_data_tvalid <= 0;
s_axis_data_tdata <=0;
s_axis_data_tlast <= 0;
end
end

xfft_1024 uut (
.aclk(aclk), // input wire aclk
// .aresetn(aresetn), // input wire aresetn
.s_axis_config_tdata(s_axis_config_tdata), // input wire [15 : 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 [63 : 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(s_axis_data_tlast), // input wire s_axis_data_tlast
.m_axis_data_tdata(m_axis_data_tdata), // output wire [79 : 0] m_axis_data_tdata
// .m_axis_data_tuser(m_axis_data_tuser), // 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
);
wire [15:0] m_real,m_image;

assign m_real = m_axis_data_tdata[15:0];
assign m_image = m_axis_data_tdata[39:24];

endmodule

3.16点FFT

需要注意的是输出为48位,[15:0] 为实部,[39:24]为虚部,查看结果如下所示:

Matlab中的代码如下所示:
N=16;
X=zeros(N,1);
for i=1:N
X(i)=i;
end
FFTX=fft(X,N);
x_real=round(real(FFTX));
x_imag=round(imag(FFTX));

实部为:

虚部:

IP的仿真结果和matlab结果基本一致。

4、64点FFT
同样的代码只需要将IP的配置值修改就行
module AA_tb;

reg aclk;
reg aresetn;
reg [15 : 0] s_axis_config_tdata;
reg s_axis_config_tvalid;
wire s_axis_config_tready;
reg [31 : 0] s_axis_data_tdata;
reg s_axis_data_tvalid;
wire s_axis_data_tready;
reg s_axis_data_tlast;
wire [47 : 0] m_axis_data_tdata;
wire [7 : 0] m_axis_data_tuser;
wire m_axis_data_tvalid;
reg m_axis_data_tready;
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;

reg [11:0] mem0_re[256:0];
reg [7:0] op_sample= 0;
reg op_sample_first = 1;
reg [7:0] ip_frame=0;
reg [7:0] op_frame=0;

// initial $readmemh("C:/Users/74339/Desktop/vivado_code/fft_test/signal.txt",mem0_re);
integer i;
reg s_data;

always #5 aclk = !aclk;

initial begin
// Initialize Inputs
aclk = 0;
aresetn = 0;
s_axis_config_tvalid = 0;
s_axis_config_tdata = 0;
s_axis_data_tvalid = 0;
s_axis_data_tdata = 0;
s_axis_data_tlast = 0;
m_axis_data_tready = 0;
s_data = 0;
i = 0;
// Wait 100 ns for global reset to finish
#150;
aresetn = 1;
m_axis_data_tready = 1;
s_axis_config_tvalid = 1;
//s_axis_config_tdata = 16'b0101100101000100; // FFT desired (and not IFFT
s_axis_config_tdata = 16'b0101100101000110;
s_axis_data_tlast = 1;
s_axis_data_tdata = 48'h000000;
s_axis_data_tvalid = 0;
/*
#3000;
aresetn = 0;
#300;
aresetn = 1;
m_axis_data_tready = 1;
s_axis_config_tvalid = 1;
s_axis_config_tdata = 16'b0101100101000110; // FFT desired (and not IFFT
//s_axis_config_tdata = 24'b100100000000000111; // FFT desired (and not IFFT
*/
s_axis_data_tlast = 1;
s_axis_data_tdata = 48'h000000;
s_axis_data_tvalid = 0;

s_axis_data_tvalid = 0;
end

reg ff;

always @(posedge aclk)
begin
if(s_axis_data_tready == 1)
ff <= 1'b1;
else
ff <= ff;

end

reg [9:0] cntttt=0;

always @(posedge aclk)
begin
if(ff == 0)
cntttt <= 10'b0;
else if(cntttt==1023)
cntttt <= cntttt;
else
cntttt <= cntttt+1;

end

always @(posedge aclk)
begin
//if((cntttt >= 800)&&(cntttt <= 814))
if((cntttt >= 800)&&(cntttt <= 862))
begin
s_axis_data_tvalid <= 1;
s_axis_data_tdata <=s_axis_data_tdata+1;
s_axis_data_tlast <= 0;
end
//else if(cntttt == 815)
else if(cntttt == 863)
begin
s_axis_data_tvalid <= 1;
s_axis_data_tdata <=s_axis_data_tdata+1;
s_axis_data_tlast <= 1;
end

else
begin
s_axis_data_tvalid <= 0;
s_axis_data_tdata <=0;
s_axis_data_tlast <= 0;
end
end

xfft_1024 uut (
.aclk(aclk), // input wire aclk
// .aresetn(aresetn), // input wire aresetn
.s_axis_config_tdata(s_axis_config_tdata), // input wire [15 : 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 [63 : 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(s_axis_data_tlast), // input wire s_axis_data_tlast
.m_axis_data_tdata(m_axis_data_tdata), // output wire [79 : 0] m_axis_data_tdata
// .m_axis_data_tuser(m_axis_data_tuser), // 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
);
wire [15:0] m_real,m_image;

assign m_real = m_axis_data_tdata[15:0];
assign m_image = m_axis_data_tdata[39:24];

endmodule

matlab:

N=64;
X=zeros(N,1);
for i=1:N
X(i)=i;
end
FFTX=fft(X,N);
x_real=round(real(FFTX));
x_imag=round(imag(FFTX));


文章转载自:LYC_0504

最新文章

最新文章