赞
踩
废话:暑假在家没事,就用FPGA做了FFT,一开始用的Quartus13.0做FFT,试了好长时间生成不了FFTip和,后面更新了quartus18.0就可以了,但用Modesim仿真还是不成功(后面了解到了自己下载的Modesim确实alter库),过了一段时间想到了不用Modesim,用在线逻辑分析仪,就成功解决了。
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教程
生成FFTip核
里面参数意义这里不做讲解参考在quartus中使用FFT IP核最全教程(从入门到放弃)_quartus fft ip核-CSDN博客
- module FFT_top
- (
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire [7:0] data_in ,
-
- output wire sink_valid ,
- output wire [7:0] data_modulus ,
- output wire data_sop ,
- output wire data_eop ,
- output wire data_valid ,
- output wire [9:0] index
- );
-
- wire sink_ready ;
- wire sink_sop ;
- wire sink_eop ;
- wire source_valid ;
- wire source_ready ;
- wire source_sop ;
- wire source_eop ;
-
- wire [1:0] sink_error ;
- wire [1:0] source_error;
- wire [5:0] source_exp ;
- wire [8:0] source_real ;
- wire [8:0] source_imag ;
-
- FFT_ctrl FFT_ctrl_U1
- (
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .source_eop(source_eop ),
-
- .sink_valid(sink_valid ),
- .sink_ready(sink_ready ),
- .sink_error(sink_error ),
- .sink_sop (sink_sop ),
- .source_ready(source_ready),
- .sink_eop (sink_eop )
- );
-
- FFT FFT_U2
- (
- .clk (sys_clk ), // 输入 clk.clk
- .reset_n (sys_rst_n ), // 输入 rst.reset_n
- .sink_valid (sink_valid), // 输入sink.sink_valid
- .sink_ready (sink_ready), // 输入 .sink_ready
- .sink_error (sink_error), // 输入 .sink_error
- .sink_sop (sink_sop ), // 输入 .sink_sop
- .sink_eop (sink_eop ), // 输入 .sink_eop
- .sink_real ({1'b0,data_in}), // 输入 .sink_real
- .sink_imag (9'd0 ), // 输入 .sink_imag
- .inverse (1'b0 ), // 输入 .inverse
- .source_valid (source_valid), // 输出 source.source_valid
- .source_ready (source_ready), // 输入 .source_ready
- .source_error (source_error), // 输出 .source_error
- .source_sop (source_sop ), // 输出 .source_sop
- .source_eop (source_eop ), // 输出 .source_eop
- .source_real (source_real ), // 输出 .source_real
- .source_imag (source_imag ), // 输出 .source_imag
- .source_exp (source_exp ) // 输出 .source_exp
- );
-
- data_modulus data_modulus_U3
- (
- .clk_50m (sys_clk ) ,
- .rst_n (sys_rst_n ) ,
- .source_real (source_real ) ,
- .source_imag (source_imag ) ,
- .source_sop (source_sop ) ,
- .source_eop (source_eop ) ,
- .source_valid(source_valid ) ,
-
- .data_modulus(data_modulus ) ,
- .data_sop (data_sop ) ,
- .data_eop (data_eop ) ,
- .data_valid (data_valid ) ,
- .index (index)
- );
- endmodule
- module FFT_ctrl
- (
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire source_eop ,
-
- output reg sink_valid ,
- output wire sink_ready ,
- output wire sink_error ,
- output reg sink_sop ,
- output wire source_ready,
- output reg sink_eop
- );
-
- reg [9:0] fft_cnt ;
-
- assign sink_ready = 1'b1;
- assign sink_error = 2'b00;
- assign source_ready = 1'b1;
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- fft_cnt <= 10'd0;
- else if(source_eop == 1'b1)
- fft_cnt <= 10'd0;
- else if(fft_cnt == 10'd300)
- fft_cnt = 10'd300;
- else
- fft_cnt <= fft_cnt+10'd1;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- sink_sop <= 1'b0;
- else if(fft_cnt == 10'd1)
- sink_sop <= 1'b1;
- else
- sink_sop <= 1'b0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- sink_eop <= 1'b0;
- else if(fft_cnt == 10'd256)
- sink_eop <= 1'b1;
- else
- sink_eop <= 1'b0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- sink_valid <= 1'b0;
- else if((fft_cnt >= 10'd1)&&(fft_cnt <= 10'd256))
- sink_valid <= 1'b1;
- else
- sink_valid <= 1'b0;
-
- endmodule
-
- module data_modulus(
- input clk_50m,
- input rst_n,
-
- input [8:0] source_real,
- input [8:0] source_imag,
- input source_sop,
- input source_eop,
- input source_valid,
- output [7:0] data_modulus,
- output reg data_sop,
- output reg data_eop,
- output reg [9:0] index ,
- output reg data_valid
-
- );
-
- //reg define
- reg [15:0] source_data;
- reg [7:0] data_real;
- reg [7:0] data_imag;
- reg data_sop1;
- reg data_sop2;
- reg data_eop1;
- reg data_eop2;
- reg data_valid1;
- reg data_valid2;
-
- //*****************************************************
- //** main code
- //*****************************************************
-
- //取实部和虚部的平方和
- always @ (posedge clk_50m or negedge rst_n) begin
- if(!rst_n) begin
- source_data <= 16'd0;
- data_real <= 8'd0;
- data_imag <= 8'd0;
- end
- else begin
- if(source_real[8]==1'b0) //由补码计算原码
- data_real <= source_real;
- else
- data_real <= ~source_real + 1'b1;
-
- if(source_imag[8]==1'b0) //由补码计算原码
- data_imag <= source_imag;
- else
- data_imag <= ~source_imag + 1'b1;
- //计算原码平方和
- if(data_valid1==1'b1)
- source_data <= (data_real*data_real) + (data_imag*data_imag);
- else
- source_data <=16'd0;
- end
- end
-
- //例化sqrt模块,开根号运算
- sqrt sqrt_inst
- (
- .clk (clk_50m ),
- .radical (source_data ),
-
- .q (data_modulus),
- .remainder ( )
- );
-
- //数据取模运算共花费了三个时钟周期,此处延时三个时钟周期
- always @ (posedge clk_50m or negedge rst_n) begin
- if(!rst_n) begin
- data_sop <= 1'b0;
- data_sop1 <= 1'b0;
- data_sop2 <= 1'b0;
- data_eop <= 1'b0;
- data_eop1 <= 1'b0;
- data_eop2 <= 1'b0;
- data_valid <= 1'b0;
- data_valid1 <= 1'b0;
- data_valid2 <= 1'b0;
- end
- else begin
- data_valid1 <= source_valid;
- data_valid2 <= data_valid1;
- data_valid <= data_valid2;
- data_sop1 <= source_sop;
- data_sop2 <= data_sop1;
- data_sop <= data_sop2;
- data_eop1 <= source_eop;
- data_eop2 <= data_eop1;
- data_eop <= data_eop2;
- end
- end
-
- always @ (posedge clk_50m or negedge rst_n)
- if(~rst_n)
- index <= 10'd0;
- else if(data_valid==1'b0)
- index <= 10'd0;
- else if(data_valid==1'b1)
- index <= index + 1'b1;
- endmodule
运行结果这里输入的是195KH的信号,代码运行结果也是195KH,
计算方法参考正点原子的音频FFT,
原文链接:https://blog.csdn.net/FPGADesigner/article/details/80690345
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。