1. 程式人生 > >Xilinx FFT IP v9.0 使用

Xilinx FFT IP v9.0 使用

該ip用於實現N=2**m(m=3~16)點FFT的變換,

實現的數學型別包括:

A)      定點全精度

B)      定點縮減位寬

C)      塊浮點

每一級蝶型運算後舍入或者取整。對於N點運算,FFT還是逆FFT,scaling策略以及迴圈字首的長度是執行時可配置的,可隨幀改變,改變變換點數會復位FFT ip核。

 有四種可選擇的FFT的實現架構:

1)  PipelinedStreaming I/O

2)  Radix-4Burst I/O

3)  Radix-2Burst I/O

4) Radix-2 Lite Burst I/O

FFTip核使用基二和基四分解法計算離散傅立葉變換,對於Burst I/O architectures採用時域抽取法實現,對於Pipelined Streaming I/Oarchitecture.使用頻域抽取法。當使用基四計算時,其蝶型演算法的級數是log 4 (N),每一級包括N/4的基四蝶型運算。對於點數不是4的指數情況,則需要一個額外的基二來組合資料。類似的基二實現法需要log 2 (N)級蝶型運算。對於scaling方法,其每一級的scaling因子由s_axis_config_tdata來配置。Ip核的埠如下:


輸入輸出方向在上圖中已經很明顯了,下面描述埠作用

Aclk輸入時鐘,上升沿有效

Aclken :使用有效訊號,高使能

Aresetn:同步復位訊號,低電平有效(至少保持aclk兩個時鐘週期)

s_axis_config_tdata:包括配置資訊,CP_LEN, FWD/INV, NFFT,SCALE_SCH.

上面訊號所有s開始的表示的是axi訊號的slave端,m是master端。各訊號作用參考《Fast Fourier Transform v9.0 LogiCORE IP Product Guide》

以8點FFT示意,configure

implementtation


summary


由於xilinx自帶的testbench是VHDL的,這裡給出自己寫的verilog版本的testbench。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: shichaog
// 
// Create Date: 04/13/2016 08:35:42 PM
// Design Name: 
// Module Name: TB_fft256
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module TB_fft256;
	// Inputs
	reg aclk;
	reg s_axis_config_tvalid;
	reg s_axis_data_tvalid;
	reg s_axis_data_tlast;
	reg m_axis_data_tready;
	reg [15:0] s_axis_config_tdata;
	reg [95: 0] s_axis_data_tdata;

	// Outputs
	wire s_axis_config_tready;
	wire s_axis_data_tready;
	wire m_axis_data_tvalid;
	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 [95 : 0] m_axis_data_tdata;
	
	reg[23:0] mem0_re[0:7];
	reg[23:0] mem1_re[0:7];
    reg[23:0] mem2_re[0:7];
	initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus0_24bit.dat",mem0_re);
	initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus1_24bit.dat",mem1_re);
	initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus2_24bit.dat",mem2_re);
	
	reg[7:0]   op_sample= 0;
	reg        op_sample_first = 1;
	reg[7:0]   ip_frame=0;
	reg[7:0]   op_frame=0;
	
	integer i;
	
	// generate clk
    always #5 aclk =! aclk;
	
	// Instantiate the Unit Under Test (UUT)
xfft_256 uut (
      .aclk(aclk),                                                // input wire aclk
      .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 [95 : 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 [95 : 0] m_axis_data_tdata
      .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
    );
    
	initial begin
		// Initialize Inputs
		aclk = 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;
		
		// Wait 100 ns for global reset to finish
		#150;
		m_axis_data_tready = 1;
		s_axis_config_tvalid = 1;
		//s_axis_config_tdata = 16'b0101100101011011; // FFT desired (and not IFFT
		s_axis_config_tdata = 16'b0000000000000111; // FFT desired (and not IFFT
		
		//s_axis_data_tlast = 1;
		s_axis_data_tdata = 96'h000000;	
		s_axis_data_tvalid = 0;
	
		
		begin
		  for(i=0;i<8;i=i+1)
		      begin
                #10
                s_axis_data_tvalid <= 1;
                s_axis_data_tdata <= {{24'h000000},mem1_re[i],{24'h000000},mem0_re[i]};
		        $display("mem_a[%d] = %h", i, mem0_re[i]);
//		        if(i== 256)
//		            s_axis_data_tlast <= 1;
//		        else
//		            s_axis_data_tlast <= 0;
                end
	    
	    end
		#10;
		s_axis_data_tdata = 96'h000000;	
        s_axis_data_tvalid = 0;
		#1000 $finish;  
		//$stop
		
	end
endmodule
stimulus0_24bit.dat檔案內容如下:
000000
000001
000002
000003
000004
000005
000006
000007
stimulus1_24bit.dat檔案內容隨便,這裡是兩個通道的FFT計算。模擬波形圖如下:


MATLAB計算所得的FFT結果如下:


將FFT結果的放大後得到如下圖:

MATLAB計算的結果是28,而fpga模擬結果是00000e,-4則是fffffe,這是因為設定了scaling因子,且scaling因子是2,即28/2=14。

關於hls的實現見:

http://blog.csdn.net/shichaog/article/details/50811449