1. 程式人生 > >Vivado FFT9.0模擬驗證

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));