当前位置:   article > 正文

Quartus做FFT(详细看这篇就够了)

Quartus做FFT(详细看这篇就够了)

废话:暑假在家没事,就用FPGA做了FFT,一开始用的Quartus13.0做FFT,试了好长时间生成不了FFTip和,后面更新了quartus18.0就可以了,但用Modesim仿真还是不成功(后面了解到了自己下载的Modesim确实alter库),过了一段时间想到了不用Modesim,用在线逻辑分析仪,就成功解决了。

1:准备工作

1:Quartus的FFT IP核属于收费IP,如果是个人学习使用要对IP核单独破解。(参考https://blog.csdn.net/fpgadesigner/article/details/80605869 中的破解步骤)。

2:下载modelsim,这个modelsim不能用自己下载的modelsim,去官网下载,对应版本的modelsim-altera版本,已经将altera上的器件的lib编译好,如果自己下载modelsim使用,则还要自己编译相应的altera库,
3:不用Modesim用在线逻辑分析仪,具体可参考正点原子或者野火FPGA教程

2:正式工作

生成FFTip核

里面参数意义这里不做讲解参考在quartus中使用FFT IP核最全教程(从入门到放弃)_quartus fft ip核-CSDN博客

     

  1. module FFT_top
  2. (
  3. input wire sys_clk ,
  4. input wire sys_rst_n ,
  5. input wire [7:0] data_in ,
  6. output wire sink_valid ,
  7. output wire [7:0] data_modulus ,
  8. output wire data_sop ,
  9. output wire data_eop ,
  10. output wire data_valid ,
  11. output wire [9:0] index
  12. );
  13. wire sink_ready ;
  14. wire sink_sop ;
  15. wire sink_eop ;
  16. wire source_valid ;
  17. wire source_ready ;
  18. wire source_sop ;
  19. wire source_eop ;
  20. wire [1:0] sink_error ;
  21. wire [1:0] source_error;
  22. wire [5:0] source_exp ;
  23. wire [8:0] source_real ;
  24. wire [8:0] source_imag ;
  25. FFT_ctrl FFT_ctrl_U1
  26. (
  27. .sys_clk (sys_clk ),
  28. .sys_rst_n (sys_rst_n ),
  29. .source_eop(source_eop ),
  30. .sink_valid(sink_valid ),
  31. .sink_ready(sink_ready ),
  32. .sink_error(sink_error ),
  33. .sink_sop (sink_sop ),
  34. .source_ready(source_ready),
  35. .sink_eop (sink_eop )
  36. );
  37. FFT FFT_U2
  38. (
  39. .clk (sys_clk ), // 输入 clk.clk
  40. .reset_n (sys_rst_n ), // 输入 rst.reset_n
  41. .sink_valid (sink_valid), // 输入sink.sink_valid
  42. .sink_ready (sink_ready), // 输入 .sink_ready
  43. .sink_error (sink_error), // 输入 .sink_error
  44. .sink_sop (sink_sop ), // 输入 .sink_sop
  45. .sink_eop (sink_eop ), // 输入 .sink_eop
  46. .sink_real ({1'b0,data_in}), // 输入 .sink_real
  47. .sink_imag (9'd0 ), // 输入 .sink_imag
  48. .inverse (1'b0 ), // 输入 .inverse
  49. .source_valid (source_valid), // 输出 source.source_valid
  50. .source_ready (source_ready), // 输入 .source_ready
  51. .source_error (source_error), // 输出 .source_error
  52. .source_sop (source_sop ), // 输出 .source_sop
  53. .source_eop (source_eop ), // 输出 .source_eop
  54. .source_real (source_real ), // 输出 .source_real
  55. .source_imag (source_imag ), // 输出 .source_imag
  56. .source_exp (source_exp ) // 输出 .source_exp
  57. );
  58. data_modulus data_modulus_U3
  59. (
  60. .clk_50m (sys_clk ) ,
  61. .rst_n (sys_rst_n ) ,
  62. .source_real (source_real ) ,
  63. .source_imag (source_imag ) ,
  64. .source_sop (source_sop ) ,
  65. .source_eop (source_eop ) ,
  66. .source_valid(source_valid ) ,
  67. .data_modulus(data_modulus ) ,
  68. .data_sop (data_sop ) ,
  69. .data_eop (data_eop ) ,
  70. .data_valid (data_valid ) ,
  71. .index (index)
  72. );
  73. endmodule

          

  1. module FFT_ctrl
  2. (
  3. input wire sys_clk ,
  4. input wire sys_rst_n ,
  5. input wire source_eop ,
  6. output reg sink_valid ,
  7. output wire sink_ready ,
  8. output wire sink_error ,
  9. output reg sink_sop ,
  10. output wire source_ready,
  11. output reg sink_eop
  12. );
  13. reg [9:0] fft_cnt ;
  14. assign sink_ready = 1'b1;
  15. assign sink_error = 2'b00;
  16. assign source_ready = 1'b1;
  17. always@(posedge sys_clk or negedge sys_rst_n)
  18. if(!sys_rst_n)
  19. fft_cnt <= 10'd0;
  20. else if(source_eop == 1'b1)
  21. fft_cnt <= 10'd0;
  22. else if(fft_cnt == 10'd300)
  23. fft_cnt = 10'd300;
  24. else
  25. fft_cnt <= fft_cnt+10'd1;
  26. always@(posedge sys_clk or negedge sys_rst_n)
  27. if(!sys_rst_n)
  28. sink_sop <= 1'b0;
  29. else if(fft_cnt == 10'd1)
  30. sink_sop <= 1'b1;
  31. else
  32. sink_sop <= 1'b0;
  33. always@(posedge sys_clk or negedge sys_rst_n)
  34. if(!sys_rst_n)
  35. sink_eop <= 1'b0;
  36. else if(fft_cnt == 10'd256)
  37. sink_eop <= 1'b1;
  38. else
  39. sink_eop <= 1'b0;
  40. always@(posedge sys_clk or negedge sys_rst_n)
  41. if(!sys_rst_n)
  42. sink_valid <= 1'b0;
  43. else if((fft_cnt >= 10'd1)&&(fft_cnt <= 10'd256))
  44. sink_valid <= 1'b1;
  45. else
  46. sink_valid <= 1'b0;
  47. endmodule
  1. module data_modulus(
  2. input clk_50m,
  3. input rst_n,
  4. input [8:0] source_real,
  5. input [8:0] source_imag,
  6. input source_sop,
  7. input source_eop,
  8. input source_valid,
  9. output [7:0] data_modulus,
  10. output reg data_sop,
  11. output reg data_eop,
  12. output reg [9:0] index ,
  13. output reg data_valid
  14. );
  15. //reg define
  16. reg [15:0] source_data;
  17. reg [7:0] data_real;
  18. reg [7:0] data_imag;
  19. reg data_sop1;
  20. reg data_sop2;
  21. reg data_eop1;
  22. reg data_eop2;
  23. reg data_valid1;
  24. reg data_valid2;
  25. //*****************************************************
  26. //** main code
  27. //*****************************************************
  28. //取实部和虚部的平方和
  29. always @ (posedge clk_50m or negedge rst_n) begin
  30. if(!rst_n) begin
  31. source_data <= 16'd0;
  32. data_real <= 8'd0;
  33. data_imag <= 8'd0;
  34. end
  35. else begin
  36. if(source_real[8]==1'b0) //由补码计算原码
  37. data_real <= source_real;
  38. else
  39. data_real <= ~source_real + 1'b1;
  40. if(source_imag[8]==1'b0) //由补码计算原码
  41. data_imag <= source_imag;
  42. else
  43. data_imag <= ~source_imag + 1'b1;
  44. //计算原码平方和
  45. if(data_valid1==1'b1)
  46. source_data <= (data_real*data_real) + (data_imag*data_imag);
  47. else
  48. source_data <=16'd0;
  49. end
  50. end
  51. //例化sqrt模块,开根号运算
  52. sqrt sqrt_inst
  53. (
  54. .clk (clk_50m ),
  55. .radical (source_data ),
  56. .q (data_modulus),
  57. .remainder ( )
  58. );
  59. //数据取模运算共花费了三个时钟周期,此处延时三个时钟周期
  60. always @ (posedge clk_50m or negedge rst_n) begin
  61. if(!rst_n) begin
  62. data_sop <= 1'b0;
  63. data_sop1 <= 1'b0;
  64. data_sop2 <= 1'b0;
  65. data_eop <= 1'b0;
  66. data_eop1 <= 1'b0;
  67. data_eop2 <= 1'b0;
  68. data_valid <= 1'b0;
  69. data_valid1 <= 1'b0;
  70. data_valid2 <= 1'b0;
  71. end
  72. else begin
  73. data_valid1 <= source_valid;
  74. data_valid2 <= data_valid1;
  75. data_valid <= data_valid2;
  76. data_sop1 <= source_sop;
  77. data_sop2 <= data_sop1;
  78. data_sop <= data_sop2;
  79. data_eop1 <= source_eop;
  80. data_eop2 <= data_eop1;
  81. data_eop <= data_eop2;
  82. end
  83. end
  84. always @ (posedge clk_50m or negedge rst_n)
  85. if(~rst_n)
  86. index <= 10'd0;
  87. else if(data_valid==1'b0)
  88. index <= 10'd0;
  89. else if(data_valid==1'b1)
  90. index <= index + 1'b1;
  91. endmodule

运行结果这里输入的是195KH的信号,代码运行结果也是195KH,

计算方法参考正点原子的音频FFT,

最最最重要的是
                        FFTip核输出的source实部和虚部是带有符号位的,因此输入要大于实际值一位,输出的最高位表示符号位,别的正常写
原文链接:https://blog.csdn.net/youzjuer/article/details/121320018


                        
原文链接:https://blog.csdn.net/FPGADesigner/article/details/80690345

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号