频谱最大值及频率获取
在之前章节,笔者介绍了如何通过FFT的输出结果,以及下标索引,确定检测到的信号频率,其中一个关键的信息是频率分辨率,在固定的运行时钟以及单次FFT长度下,频率分辨率为定值,可以直接在上位机中进行配置即可,故想要在上位机进行频率计算,只要FPGA向上位机传输输出索引即可,本节将介绍如何获取最大幅值以及索引,并完善之前章节的代码,将下位机的整体工程初步确定。
对于获取最大值,只需要一个简单的比较模块即可,但笔者初步考虑是计算每一帧的最大值,及其计算出来的信号频率,虽然对于测试信号正弦波来讲,其应该每一帧都是一致的,笔者实现整个项目主要是想分享一些代码设计思路和整体架构,和工程上的实际需求是不一样的。
故为计算每一帧的最大值,便需要在下一帧到来时,清除本帧的最大值,归零。考虑使用每一帧传输的last信号实现该功能。
module max_amplitude_search(
input i_clk ,
input i_rst ,
input [12:0] i_xpow ,
input [10:0] i_xindex ,
input i_xk_tlast ,
output [12:0] o_max_pow ,
output [10:0] o_max_index
);
reg [12:0] ro_max_pow ;
reg [10:0] ro_max_index;
reg ri_xk_tlast ;
assign o_max_pow = ro_max_pow ;
assign o_max_index = ro_max_index ;
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ro_max_pow <= 'd0;
ro_max_index <= 'd0;
end
else if(ro_max_pow < i_xpow) begin
ro_max_pow <= i_xpow;
ro_max_index <= i_xindex;
end
else if(ri_xk_tlast) begin
ro_max_pow <= 'd0;
ro_max_index <= 'd0;
end
else begin
ro_max_pow <= ro_max_pow;
ro_max_index <= ro_max_index;
end
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ri_xk_tlast <= 'b0;
else
ri_xk_tlast <= i_xk_tlast;
end
endmodule
该模块的输入应为模值输出模块,需要注意的是,在上一节中介绍到的模值计算模块,其延迟为18个时钟周期,输入的是FFT复数谱数据,而在最大值搜索模块中,因为需要用到FFT索引下标以及FFT输出的tlast信号,为了保持模值与这两个信号之间的对齐,故需要对这两个信号做延迟处理,再输入至模值搜索模块。
为了简化代码的编写,使用RAM-based Shift Register ip核实现18个周期的延迟。
该模块书写完成后,进行测试,编写激励文件,仿真结果如下图
输出给其它级模块的结果为两路合成结果。
至此,下位机代码基本完成,还缺少的则是数据上传部分,该部分功能简单,只需要使能对应数据长度的时钟周期,将数据写入FIFO,供上位机读取即可。下图所示是整体工程的原理图示意
在下一章节,笔者将就数据上传的帧封装部分做简要介绍,仿真,并将各个模块之间的连接关系做进一步梳理,然后进行工程整体的仿真设计。
本节代码若是感兴趣,可以私信博主免费领取。