FFT ip核

在VIVADO中建立一个FFT核,只要依下图步骤就可以开始配置一个FFT核:

需要配置的参数有三个标签页,需要一一配置

第一个标签页里主要配置通道数,点数,时钟,吞吐量,结构,以及是否可以运行时配置,需要注意的是结构的配置会影响调整因子。

第二配置页主要是数据宽度,格式,控制信号,输出方式,和可选的控制信号。需要注意的是输据的输入是自然方式(Natural  Order),输出可以是自然方式也可以是倒序方式(Reversed Order),如果选用倒序方式输出,在后面处理中就要注意这一特性。

第三配置页主要配置内部数据块的使用和优化的方式

所有这些配置完成后,可以左侧一列中察看配置的结果,IP Symbol中主要察看各种接口,Implementation Detals 中有较多的信息,比如结构,长度,数据宽度等,需要注的是CONFIG TDATA这一项,与配置接口的参数有关,在使用中需要正确配置。在当前的配置, FWD_INV使用1bit,bit10:bit1用于调整因子,前面已经说过不同的结构调整因子不同,详细的可以参看FFT的核文献。

之后点击OK就可以完成配置,并生成FFT核,并在Project Manager的source中找IP Sources的资源,核的模板就是xfft_0.veo

我们就用这个模板创造我们的实例

有一些接口是不需要的,对它进行重新封装,配置参数是固定的,直接设成固定值,需要注意的是当前配置参数中,调整因子是0,即不调整,这在数据比较小的时候,不会出现问题,当输入数据比较大时,需要适当的设置,以免在进行蝶形运算时出现溢出的情况。


 
 
  1. //
  2. module fft_core_test(
  3. clk,
  4. config_en,
  5. dat_rdy,
  6. dat_last,
  7. dat_in_RE,
  8. dat_in_IM,
  9. fft_core_rdy,
  10. freq_o_en,
  11. freq_o_RE,
  12. freq_o_IM
  13. );
  14. input clk;
  15. input config_en;
  16. input dat_rdy;
  17. input dat_last;
  18. input [15:0] dat_in_RE,dat_in_IM;
  19. output fft_core_rdy;
  20. output freq_o_en;
  21. output [15:0] freq_o_RE,freq_o_IM;
  22. wire fft_core_rdy;
  23. wire freq_o_en;
  24. wire [15:0] freq_o_RE,freq_o_IM;
  25. //fft core
  26. wire aclk = clk;
  27. wire [15 : 0] s_axis_config_tdata = 16'b0_0000_0000_0000_00_1; //scal_sch: [14:1] FWD_INC:[0]
  28. wire s_axis_config_tvalid = config_en;
  29. wire s_axis_config_tready;
  30. wire [31 : 0] s_axis_data_tdata = {dat_in_IM,dat_in_RE};
  31. wire s_axis_data_tvalid = dat_rdy;
  32. wire s_axis_data_tready;
  33. assign fft_core_rdy = s_axis_data_tready;
  34. wire s_axis_data_tlast = dat_last;
  35. wire [31 : 0] m_axis_data_tdata;
  36. assign {freq_o_IM,freq_o_RE} = m_axis_data_tdata;
  37. wire m_axis_data_tvalid;
  38. assign freq_o_en = m_axis_data_tvalid;
  39. wire m_axis_data_tready = 1'b1;
  40. wire m_axis_data_tlast;
  41. wire event_frame_started;
  42. wire event_tlast_unexpected;
  43. wire event_tlast_missing;
  44. wire event_status_channel_halt;
  45. wire event_data_in_channel_halt;
  46. wire event_data_out_channel_halt;
  47. xfft_0 your_instance_name (
  48. .aclk(aclk), // input wire aclk
  49. .s_axis_config_tdata(s_axis_config_tdata), // input wire [15 : 0] s_axis_config_tdata
  50. .s_axis_config_tvalid(s_axis_config_tvalid), // input wire s_axis_config_tvalid
  51. .s_axis_config_tready(s_axis_config_tready), // output wire s_axis_config_tready
  52. .s_axis_data_tdata(s_axis_data_tdata), // input wire [31 : 0] s_axis_data_tdata
  53. .s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
  54. .s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
  55. .s_axis_data_tlast(s_axis_data_tlast), // input wire s_axis_data_tlast
  56. .m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
  57. .m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
  58. .m_axis_data_tready(m_axis_data_tready), // input wire m_axis_data_tready
  59. .m_axis_data_tlast(m_axis_data_tlast), // output wire m_axis_data_tlast
  60. .event_frame_started(event_frame_started), // output wire event_frame_started
  61. .event_tlast_unexpected(event_tlast_unexpected), // output wire event_tlast_unexpected
  62. .event_tlast_missing(event_tlast_missing), // output wire event_tlast_missing
  63. .event_status_channel_halt(event_status_channel_halt), // output wire event_status_channel_halt
  64. .event_data_in_channel_halt(event_data_in_channel_halt), // output wire event_data_in_channel_halt
  65. .event_data_out_channel_halt(event_data_out_channel_halt) // output wire event_data_out_channel_halt
  66. );
  67. endmodule

然后新建一个用于simulation的testbench文件, 用于sim的testbench文件是出现 在simulation Sources中的,也可以按源文件的方式建立testbench,这样出现的testbench出现在 Design Sources中,开发环境可能会认为这一文件也是正式的工程文件,可能会报出一些问题,具体自己试。


 
 
  1. module sim_fft( );
  2. reg all_en;
  3. reg clk;
  4. reg config_ena;
  5. reg dat_rdy;
  6. reg dat_last;
  7. reg [15:0] dat_c;
  8. wire [15:0] dat_in_RE,dat_in_IM;
  9. wire fft_core_rdy_t;
  10. wire freq_o_en_t;
  11. wire [15:0] freq_o_RE_t,freq_o_IM_t;
  12. integer handle1;
  13. initial
  14. begin//sequence block
  15. handle1 = $fopen("fsave.txt");
  16. #200000 $fclose(handle1);
  17. $stop;
  18. end
  19. initial
  20. begin
  21. clk = 0;
  22. dat_rdy = 0;
  23. dat_last = 0;
  24. //dat_in_RE= 0;
  25. dat_c = 0;
  26. config_ena = 0;
  27. all_en= 0;
  28. #200 all_en = 1;
  29. //#20 config_ena =1;
  30. //#100 config_ena =0;
  31. forever #10 clk = ~clk;
  32. end
  33. //
  34. reg [15:0] cnt=0;
  35. reg [15:0] index = 0;
  36. always @(posedge clk)
  37. begin
  38. if(all_en)
  39. begin
  40. cnt <= cnt + 1'b1;
  41. if(cnt = = 0)
  42. begin
  43. config_ena <=1;
  44. end
  45. else if(cnt == 3)
  46. config_ena <= 0;
  47. else if(cnt == 5)
  48. begin
  49. dat_rdy <= 1;
  50. dat_c <= 0;
  51. // dat_in_IM <= 0;
  52. index = 0;
  53. end
  54. else if(cnt == 16'd1028)
  55. begin
  56. dat_last <= 1'b1;
  57. dat_c <= (dat_c + 12'h100);
  58. end
  59. else if(cnt == 16'd1029)
  60. begin
  61. dat_rdy <= 1'b0;
  62. dat_last <= 1'b0;
  63. end
  64. else
  65. begin
  66. //dat_last <= 1'b0;
  67. dat_c <=(dat_c + 12'h100);
  68. end
  69. if(dat_rdy)
  70. index <= index +1;
  71. end
  72. end
  73. always @(posedge clk)
  74. begin
  75. if(dat_rdy)
  76. $fwrite(handle1,"%d %d \n",dat_in_RE,dat_in_IM);
  77. else if(freq_o_en_t)
  78. $fwrite(handle1,"%d %d \n",freq_o_RE_t,freq_o_IM_t);
  79. end
  80. assign dat_in_RE ={ 8'b0,{ dat_c[15]? ~dat_c[15:8] : dat_c[15:8]}};
  81. assign dat_in_IM =0;
  82. fft_core_test fft_core_inst(
  83. .clk(clk),
  84. .config_en(config_ena),
  85. .dat_rdy(dat_rdy),
  86. .dat_last(dat_last),
  87. .dat_in_RE(dat_in_RE[15: 0]),
  88. .dat_in_IM(dat_in_IM[15: 0]),
  89. .fft_core_rdy(fft_core_rdy_t),
  90. .freq_o_en(freq_o_en_t),
  91. .freq_o_RE(freq_o_RE_t),
  92. .freq_o_IM(freq_o_IM_t)
  93. );
  94. endmodule

然后启动编译,之后就可以启动功能仿真。仿真的结果如下图。仿真的时候要注意一下event_tlast_unexpected和 event_tlast_missing;  这两个信号,如果出现则说明接口的时序配置有问题,跟FFT内部的配置不一致.

在前面的testbench文件中,我们可以看到产生了一个三角波用于测试,同时我们把原始输入到FFT核 中的数据和FFT核输出的数据保存了下来,以便于用MATLAB进行分析。


 
 
  1. clear;
  2. file_name='fsave.txt';
  3. fid = fopen(file_name,'r');
  4. c = fscanf(fid,'%d');
  5. fclose(fid);
  6. for i=1: length(c)
  7. if(c(i)>32767)
  8. b(i) = c(i)-65536;
  9. else b(i) = c(i);
  10. end
  11. end
  12. d1=b(1:2:end);
  13. d2=b(2:2:end);
  14. comp1=d1(1:1024) + j*d2(1:1024);
  15. comp2=d1(1025:2048) + j*d2(1025:2048);
  16. c1avr=sum(comp1)/length(comp1);
  17. c1=comp1-c1avr;
  18. % c1=comp1;
  19. c1fft=abs(fft(c1,1024));
  20. c2fft=abs(comp2);
  21. plot(c1);
  22. figure
  23. subplot(2,1,1);
  24. plot(c1fft);
  25. subplot(2,1,2);
  26. plot(c2fft);
  27. figure
  28. subplot(2,1,1);
  29. plot(c1fft(1:50));
  30. subplot(2,1,2);
  31. plot(c2fft(1:50));

下图为保存数据画出来的三角波,在这里进行了一个去直流的过程,所以MATLAB的进行FFT的结果中应该不含直流分量,而FFT核运算出的数据中应该有直流分量。

下图中,第一个MATLAB进行的FFT结果,第二个FFT核输出的结果

只看前50个点的数据。可以看到两种方式输出数据中的频率分量都是对准的,而且在第二个图中(FFT核输数据)可以看到直流分量是有的。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值