Quartus仿真的FIR滤波器设计之旅
Quartus仿真的FIR滤波器设计 包含仿真文件和说明文档 采用布莱克曼窗(Blackman),99阶(这样有100个系数),采样频率50MHz,通带频率1.5MHz。 图例是滤波效果,初始信号是0.5MHz和5MHz信号叠加,滤波后剩余0.5MHz的信号
最近在研究数字信号处理相关内容,其中FIR滤波器设计是个有趣的课题,今天就来分享下用Quartus进行FIR滤波器设计并仿真的过程,还会附上仿真文件和说明文档的相关要点。
一、FIR滤波器设计原理简述
FIR(Finite Impulse Response)滤波器,即有限冲激响应滤波器,它的特点是单位冲激响应h(n)在有限个n值处不为零。设计FIR滤波器的关键之一是确定滤波器的系数。这里我们采用布莱克曼窗(Blackman)来设计99阶的FIR滤波器(也就意味着有100个系数)。布莱克曼窗的特点是能够有效降低旁瓣电平,使得滤波器的过渡带更平滑。
二、参数设定
本次设计中,采样频率设定为50MHz,通带频率为1.5MHz。为啥选这些参数呢?采样频率50MHz,对于我们后续要处理的信号频率来说,能够满足奈奎斯特采样定理,保证信号不失真采样。通带频率1.5MHz是根据我们期望通过的信号频率范围来确定的。
三、代码实现
在Quartus中,我们可以用Verilog或者VHDL来实现FIR滤波器。这里以Verilog为例:
module fir_filter (
input wire clk, // 时钟信号,频率50MHz
input wire rst, // 复位信号
input wire signed [15:0] in_signal, // 输入信号,16位有符号数
output reg signed [31:0] out_signal // 输出信号,32位有符号数
);
// 定义99阶FIR滤波器系数,这里假设已经通过布莱克曼窗计算好
reg signed [15:0] coefficients [0:99];
initial begin
// 这里需要根据布莱克曼窗公式计算出具体的系数填充进来
coefficients[0] = 16'sd10;
// 省略其他99个系数的赋值
end
reg signed [15:0] delay_line [0:99]; // 延迟线,用于存储过去的输入值
always @(posedge clk or posedge rst) begin
if (rst) begin
out_signal <= 32'sd0;
for (int i = 0; i < 100; i = i + 1) begin
delay_line[i] <= 16'sd0;
end
end else begin
// 将新的输入值存入延迟线的开头
delay_line[0] <= in_signal;
// 进行乘法累加操作计算输出
out_signal = 32'sd0;
for (int i = 0; i < 100; i = i + 1) begin
out_signal = out_signal + (delay_line[i] * coefficients[i]);
end
// 更新延迟线,将每个值向后移动一位
for (int i = 99; i > 0; i = i - 1) begin
delay_line[i] <= delay_line[i - 1];
end
end
end
endmodule
代码分析
- 模块定义:定义了一个名为
firfilter的模块,有输入时钟clk、复位信号rst、16位有符号输入信号insignal以及32位有符号输出信号out_signal。 - 系数定义:用一个数组
coefficients来存储FIR滤波器的100个系数。这里只是简单示例了第一个系数的赋值,实际应用中需要根据布莱克曼窗函数计算出所有系数填充进来。 - 延迟线定义:
delay_line数组用于存储过去的输入值,长度为100,与滤波器阶数对应。 - always块:在时钟上升沿或者复位信号有效时触发。复位时,输出信号清零,延迟线所有值清零。正常工作时,将新的输入值存入延迟线开头,通过乘法累加操作计算输出值,然后更新延迟线,将每个值向后移动一位,为下一次计算做准备。
四、仿真文件编写
仿真文件用于验证我们设计的FIR滤波器是否能达到预期效果。
`timescale 1ns / 1ps
module tb_fir_filter;
reg clk;
reg rst;
reg signed [15:0] in_signal;
wire signed [31:0] out_signal;
// 实例化FIR滤波器
fir_filter uut (
.clk(clk),
.rst(rst),
.in_signal(in_signal),
.out_signal(out_signal)
);
// 生成50MHz时钟
initial begin
clk = 0;
forever #10 clk = ~clk; // 周期为20ns,对应50MHz
end
// 仿真激励
initial begin
rst = 1;
in_signal = 16'sd0;
#20;
rst = 0;
// 生成0.5MHz和5MHz信号叠加的初始信号
for (int i = 0; i < 1000; i = i + 1) begin
in_signal = 16'sd($sin(2 * $pi * 0.5e6 * i * 20e - 9) * 32767 + $sin(2 * $pi * 5e6 * i * 20e - 9) * 32767);
#20;
end
#200;
$stop;
end
endmodule
仿真代码分析
- 测试平台模块定义:
tbfirfilter模块用于测试FIR滤波器。定义了时钟clk、复位信号rst、输入信号insignal以及输出信号outsignal。 - 实例化FIR滤波器:将设计好的FIR滤波器模块实例化,连接各个信号。
- 时钟生成:通过
initial块和forever循环生成周期为20ns(对应50MHz)的时钟信号。 - 仿真激励:开始时复位信号有效,输入信号清零。一段时间后取消复位,然后通过循环生成0.5MHz和5MHz信号叠加的初始信号。这里利用
$sin函数根据时间生成对应频率的正弦波信号并叠加,乘以32767是为了将幅值归一化到16位有符号数的范围。最后暂停仿真以便观察结果。
五、滤波效果展示
从仿真结果中我们可以得到滤波效果的图例。初始信号是0.5MHz和5MHz信号叠加,经过FIR滤波器滤波后,理想情况下应该剩余0.5MHz的信号。通过观察输出信号的频谱或者时域波形,可以直观地看到5MHz信号被有效滤除,只留下了0.5MHz的信号,这就证明了我们设计的FIR滤波器达到了预期的滤波效果。
六、说明文档要点
在说明文档里,要详细阐述FIR滤波器设计的原理,包括为什么选择布莱克曼窗以及99阶的依据。介绍参数设定的原因,如采样频率和通带频率的选择。对代码进行详细解释,包括每个模块、信号以及关键代码段的作用。还要说明仿真的目的、激励信号的生成方式以及如何从仿真结果验证滤波器的正确性。最后附上仿真结果的图例,并对图例进行简要分析,让读者能清晰地了解整个FIR滤波器设计和仿真的过程。
Quartus仿真的FIR滤波器设计 包含仿真文件和说明文档 采用布莱克曼窗(Blackman),99阶(这样有100个系数),采样频率50MHz,通带频率1.5MHz。 图例是滤波效果,初始信号是0.5MHz和5MHz信号叠加,滤波后剩余0.5MHz的信号
以上就是本次Quartus仿真的FIR滤波器设计的全过程啦,希望对大家有所帮助。如果在实现过程中有任何问题,欢迎一起讨论。

更多推荐
所有评论(0)