在上一篇文章《基于Vivado的DDS和FIR核的使用》中,介绍了FIR IP核的使用,当时是通过单个系数集,单个通道实现的滤波功能。
在实际的过程中,可能存在想要动态改变滤波器,实现不同的滤波效果的目的。实现该目的,通常的一种做法为调整滤波器的系数,相应地一般有2种方法,一是通过Reload系数的方式;一是重配置系数的方式。前者是重新装载一份新的系数文件,而后者则是通过事先将所有的系数写入一份系数文件,通过配置来选择使用那一组系数。相比而言,前者配置相对复杂,但是节省资源;而后者配置简单,但是占用更多资源。因此对于仅仅只是少数几种参数进行切换,可以采用后者的方式。
这里就介绍如何通过重配置系数的方式来实现不同的滤波效果,将一个含有多个频率成分的信号,经由不同的带通滤波,得到不同频率的信号,不在通带范围内的信号都被滤掉了。
一、信号产生
通过DDS和加法电路来产生含有不同频率成分的信号。
1、DDS配置
通过DDS IP核,产生4路信号的输出,在配置IP核时,直接将通道设置为4,
因为需要输出4个信号,为了能够区分输出的端口上输出的数据是哪一个通道的,将tuser选项中的 data output设置为chan id,以实现输出通道数据的选择。
待IP配置完成后,进行例化操作,此处不做赘述。前面提到的输出通道选择的相关的代码如下:
reg data_ovalid_r;
reg [15:0] sine_data_25K; //25K波形数据
reg [15:0] sine_data_45K; //
reg [15:0] sine_data_65K; //
reg [15:0] sine_data_85K; //85K波形数据
always@(posedge clk_i or negedge rst_n)begin
if(rst_n == 1'b0) begin
data_ovalid_r <= 1'b0;
sine_data_25K <= 16'd0;
sine_data_45K <= 16'd0;
sine_data_65K <= 16'd0;
sine_data_85K <= 16'd0;
end
else begin
if(dds_data_valid) begin
data_ovalid_r <= 1'b1;
case(dds_data_tuser) //此处实现输出通道数据的选择
2'b00:sine_data_25K <= dds_dataout;
2'b01:sine_data_45K <= dds_dataout;
2'b10:sine_data_65K <= dds_dataout;
2'b11:sine_data_85K <= dds_dataout;
endcase
end
else begin
data_ovalid_r <= 1'b0;
sine_data_25K <= 16'd0;
sine_data_45K <= 16'd0;
sine_data_65K <= 16'd0;
sine_data_85K <= 16'd0;
end
end
end
2、混频,求和
求和直接用一个加法电路实现。将上述输出的4路信号进行求和,得到一个含有4个频率成分的信号。
reg signed [17:0] addr_wave;
always@(posedge clk_i or negedge rst_n)begin
if(!rst_n)
addr_wave <= 18'd0;
else if(dds_data_ovalid)
addr_wave <= sine_data_25K + sine_data_45K + sine_data_65K + sine_data_85K;
else
addr_wave <= addr_wave;
end
相应波形的matlab仿真结果如下:
二、FIR设计及IP配置
1、FIR 设计
同样的,FIR的系数设计用matlab实现,此处参考了CSDN 上其他网友的文章,采用了类似的设计。分别得到4个不同的系数coe文件,之后将其合并到一个coe文件中。
设计的带通滤波器的效果如下图所示:
2、FIR IP配置
FIR IP的配置与之前文章中提及的没有太多的区别,差异主要体现在系数文件和系数集个数的不同。
另外,需要留意的是,因系数集个数大于1,会在端口上多出来config配置端口,如下
接下来,重要的是,根据器件的时序要求进行设计,主要关注的是tvalid、tready、tdata等信号,在本例中,将dds输出的valid信号直接给到s_a端口,用作数据的有效信号,结合s_a_tready和s_a_tdata信号实现数据的输入;而对于config端口,通过定时计数的方式,定时一段时间,给一个信号,持续一个时钟周期的高电平,该信号用作cfg_tvalid使用,另外需要配合cfg_tdata。
相关的代码如下:
//计数
always@(posedge clk_50m or negedge clk_locked)begin
if(!clk_locked)
cnt <= 16'd0;
else if(cnt == CNT_MAX)
cnt <= 16'd0;
else
cnt <= cnt + 1'b1;
end
reg [ 7:0] s_cfg_data;
always@(posedge clk_50m or negedge clk_locked)begin
if(!clk_locked)
s_cfg_data <= 8'd0;
else begin
if(cnt == CNT_MAX) begin
sa_cfg_tvalid <= 1'b1;
if(s_cfg_data == 8'd3)
s_cfg_data <= 8'd0;
else
s_cfg_data <= s_cfg_data + 1'b1;
end
else begin
sa_cfg_tvalid <= 1'b0;
s_cfg_data <= s_cfg_data;
end
end
end
assign sa_cfg_tdata = s_cfg_data;
三、仿真分析
test代码十分简单,这里只贴出了仿真的结果。
结果图中,sa_data_tdata的波形跟matlab给出的波形一致,是4个信号的混频;
而fir_data_out的波形可以看出,在sa_cfg_tdata的不同数值下,实现了不同频率信号的输出,达到了通带内信号通过,带外信号衰减的选频的目的。
至此,整个的工程结束。
四、最后文章来源:https://www.toymoban.com/news/detail-839655.html
感谢一下《FIR 高级应用 - 多通道实验》的作者,给了我很多的启发,他的专栏里面的相关内容很值得一看。文章来源地址https://www.toymoban.com/news/detail-839655.html
到了这里,关于基于FPGA 的FIR IP使用提高一的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!