DSP

Xilinx FFT IP core V9.0的介绍和使用

2019-07-13 18:25发布

参考: http://blog.csdn.net/yijingjijng/article/details/48137897 http://xilinx.eetop.cn/viewnews-1262
http://blog.csdn.net/u011746496/article/details/44761865
http://xilinx.eetrend.com/article/6144
http://xilinx.eetrend.com/blog/8856
该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。 [plain] view plain copy  在CODE上查看代码片派生到我的代码片
  1. `timescale 1ns / 1ps  
  2. //////////////////////////////////////////////////////////////////////////////////  
  3. // Company:   
  4. // Engineer: shichaog  
  5. //   
  6. // Create Date: 04/13/2016 08:35:42 PM  
  7. // Design Name:   
  8. // Module Name: TB_fft256  
  9. // Project Name:   
  10. // Target Devices:   
  11. // Tool Versions:   
  12. // Description:   
  13. //   
  14. // Dependencies:   
  15. //   
  16. // Revision:  
  17. // Revision 0.01 - File Created  
  18. // Additional Comments:  
  19. //   
  20. //////////////////////////////////////////////////////////////////////////////////  
  21. module TB_fft256;  
  22.     // Inputs  
  23.     reg aclk;  
  24.     reg s_axis_config_tvalid;  
  25.     reg s_axis_data_tvalid;  
  26.     reg s_axis_data_tlast;  
  27.     reg m_axis_data_tready;  
  28.     reg [15:0] s_axis_config_tdata;  
  29.     reg [95: 0] s_axis_data_tdata;  
  30.   
  31.     // Outputs  
  32.     wire s_axis_config_tready;  
  33.     wire s_axis_data_tready;  
  34.     wire m_axis_data_tvalid;  
  35.     wire m_axis_data_tlast;  
  36.     wire event_frame_started;  
  37.     wire event_tlast_unexpected;  
  38.     wire event_tlast_missing;  
  39.     wire event_status_channel_halt;  
  40.     wire event_data_in_channel_halt;  
  41.     wire event_data_out_channel_halt;  
  42.     wire [95 : 0] m_axis_data_tdata;  
  43.       
  44.     reg[23:0] mem0_re[0:7];  
  45.     reg[23:0] mem1_re[0:7];  
  46.     reg[23:0] mem2_re[0:7];  
  47.     initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus0_24bit.dat",mem0_re);  
  48.     initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus1_24bit.dat",mem1_re);  
  49.     initial $readmemh("/home/gsc/FPGA_exercise/bf_verilog/stimulus2_24bit.dat",mem2_re);  
  50.       
  51.     reg[7:0]   op_sample= 0;  
  52.     reg        op_sample_first = 1;  
  53.     reg[7:0]   ip_frame=0;  
  54.     reg[7:0]   op_frame=0;  
  55.       
  56.     integer i;  
  57.       
  58.     // generate clk  
  59.     always #5 aclk =! aclk;  
  60.       
  61.     // Instantiate the Unit Under Test (UUT)  
  62. xfft_256 uut (  
  63.       .aclk(aclk),                                                // input wire aclk  
  64.       .s_axis_config_tdata(s_axis_config_tdata),                  // input wire [15 : 0] s_axis_config_tdata  
  65.       .s_axis_config_tvalid(s_axis_config_tvalid),                // input wire s_axis_config_tvalid  
  66.       .s_axis_config_tready(s_axis_config_tready),                // output wire s_axis_config_tready  
  67.       .s_axis_data_tdata(s_axis_data_tdata),                      // input wire [95 : 0] s_axis_data_tdata  
  68.       .s_axis_data_tvalid(s_axis_data_tvalid),                    // input wire s_axis_data_tvalid  
  69.       .s_axis_data_tready(s_axis_data_tready),                    // output wire s_axis_data_tready  
  70.       .s_axis_data_tlast(s_axis_data_tlast),                      // input wire s_axis_data_tlast  
  71.       .m_axis_data_tdata(m_axis_data_tdata),                      // output wire [95 : 0] m_axis_data_tdata  
  72.       .m_axis_data_tvalid(m_axis_data_tvalid),                    // output wire m_axis_data_tvalid  
  73.       .m_axis_data_tready(m_axis_data_tready),                    // input wire m_axis_data_tready  
  74.       .m_axis_data_tlast(m_axis_data_tlast),                      // output wire m_axis_data_tlast  
  75.       .event_frame_started(event_frame_started),                  // output wire event_frame_started  
  76.       .event_tlast_unexpected(event_tlast_unexpected),            // output wire event_tlast_unexpected  
  77.       .event_tlast_missing(event_tlast_missing),                  // output wire event_tlast_missing  
  78.       .event_status_channel_halt(event_status_channel_halt),      // output wire event_status_channel_halt  
  79.       .event_data_in_channel_halt(event_data_in_channel_halt),    // output wire event_data_in_channel_halt  
  80.       .event_data_out_channel_halt(event_data_out_channel_halt)  // output wire event_data_out_channel_halt  
  81.     );  
  82.       
  83.     initial begin  
  84.         // Initialize Inputs  
  85.         aclk = 0;  
  86.         s_axis_config_tvalid = 0;  
  87.         s_axis_config_tdata = 0;  
  88.         s_axis_data_tvalid = 0;  
  89.         s_axis_data_tdata = 0;  
  90.         s_axis_data_tlast = 0;  
  91.         m_axis_data_tready = 0;  
  92.           
  93.         // Wait 100 ns for global reset to finish  
  94.         #150;  
  95.         m_axis_data_tready = 1;  
  96.         s_axis_config_tvalid = 1;  
  97.         //s_axis_config_tdata = 16'b0101100101011011; // FFT desired (and not IFFT  
  98.         s_axis_config_tdata = 16'b0000000000000111; // FFT desired (and not IFFT  
  99.           
  100.         //s_axis_data_tlast = 1;  
  101.         s_axis_data_tdata = 96'h000000;   
  102.         s_axis_data_tvalid = 0;  
  103.       
  104.           
  105.         begin  
  106.           for(i=0;i<8;i=i+1)  
  107.               begin  
  108.                 #10  
  109.                 s_axis_data_tvalid <= 1;  
  110.                 s_axis_data_tdata <= {{24'h000000},mem1_re[i],{24'h000000},mem0_re[i]};  
  111.                 $display("mem_a[%d] = %h", i, mem0_re[i]);  
  112. //              if(i== 256)  
  113. //                  s_axis_data_tlast <= 1;  
  114. //              else  
  115. //                  s_axis_data_tlast <= 0;  
  116.                 end  
  117.           
  118.         end  
  119.         #10;  
  120.         s_axis_data_tdata = 96'h000000;   
  121.         s_axis_data_tvalid = 0;  
  122.         #1000 $finish;    
  123.         //$stop  
  124.           
  125.     end  
  126. endmodule  
stimulus0_24bit.dat文件内容如下: [plain] view plain copy  在CODE上查看代码片派生到我的代码片
  1. 000000  
  2. 000001  
  3. 000002  
  4. 000003  
  5. 000004  
  6. 000005  
  7. 000006  
  8. 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