您的位置:首页 > 其它

FPGA - FFT频谱分析 - 测量频率和幅值

2017-08-04 09:06 429 查看
昨天,有使用Quartus Ⅱ 15.1 的反正切IP核(ALTFP_ATAN),结果不尽人意,输入32’d1 结果输出确实32’d0。搞不明白是那里的问题,就先放下了。今天写一下,利用Quartus Ⅱ15.1 的FFT IP核进行频谱分析,测量频率和幅值(好吧,幅值没有搞明白,但是当输入信号频率远远低于采样率的时候幅值是几乎稳定的,但不是我想要的结果)。

———————————————————————————————————————————————

先放几张仿真图,频谱分辨率分别是1 10 100 1000,输入信号频率是450Hz。我们可以从这几张图中,再次认识到用FFT做频谱分析出现误差的栅栏效应(在我上一篇博客中有详细讲解,当然大多是摘自高西全老师的《数字信号处理》一书)









利用FFT测频的思路是寻找最大幅值,确定最大幅值的RAM地址,再根据公式和频谱分辨率相称即可。用FFT测量幅值,我虽然没有做出来,可能是太废,但原理还是比较简单的。寻找到最大值后根据缩放因子进行左移或后移,再除于(N/2)。

module  Mre_Fre(
input                               clk,
input                               rst_n,
input               [1:0]           NumKey1,
input               [9:0]           Data_In,
input               [9:0]           WrAddr,
output              [19:0]      Assignment,//幅值
output              [31:0]      Fre//频率

);

reg     [9:0]       Fre_reso;//频率分辨率
always @  (posedge clk or n
4000
egedge rst_n)
if(!rst_n)
Fre_reso <= 1'b1;
else
case(NumKey1)
2'd0 :
Fre_reso <= 1'b1;
2'd1 :
Fre_reso <= 4'd10;
2'd2 :
Fre_reso <= 7'd100;
2'd3 :
Fre_reso <= 10'd1000;
endcase

//状态锁存
reg     [9:0]       temp1,temp2,temp3;//寄存器
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
temp1 <= 'd0;
temp2 <= 'd0;
temp3 <= 'd0;
end
else
begin
temp1 <= Data_In;
temp2 <= temp1;
temp3 <= temp2;
end

reg     [1:0]           status;//状态
reg     [9:0]           A;//幅值
reg     [31:0]      F;//频率
reg                     Flag;//峰值标志位

always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
status <= 'd0;
A <= 'd0;
F <= 'd0;
Flag <= 'd0;
end
else
case(status)
2'd0 :
if(WrAddr == 10'd1)
begin
status <= 1'd1;
A <= 'd0;
F <= 'd0;
Flag <= 'd0;
end
else
begin
Flag <= 'd0;
status <= 'd0;
end
2'd1 :
if(WrAddr <= 10'd512)
begin
status <= 1'd1;
if(temp2 - temp1 > 3'd5 && temp2 > temp3)
begin
if(temp2 >= A)
begin
F <= WrAddr - 2;//Ram的特性,会有两个地址的延迟。
A <= temp2;
end
end
end
else
begin
Flag <= 1'b1;
status <= 'd2;
end
2'd2 :
status <= 'd0;

endcase

assign  Fre = Flag ? F*Fre_reso : Fre;
assign  Assignment = Flag ? A * 2 : Assignment;

/*
always @ (posedge clk or negedge rst_n)
if(!rst_`
````

Fre <= 'd0;
else if(status == 3'd2)
Fre <= F*Fre_reso;
else
Fre <= Fre;
*/

endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: