Vivado FFT9.0模擬驗證
阿新 • • 發佈:2018-11-09
在網上看了很多的介紹,基本都是一樣的,但是根據這些部落格,自己驗證了下發現結果和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));