当前位置: 首页 > news >正文

【FPGA数字信号处理】- FIR串行滤波器

理解和掌握 FIR 串行滤波器是踏入数字信号处理领域的重要一步。

那么,什么是 FIR 串行滤波器?它是如何工作的?又有着怎样的神奇之处呢?让我们一起揭开它的神秘面纱。

一、FIR 滤波器简介

FIR 滤波器,全称为有限脉冲响应(Finite Impulse Response)滤波器,是数字信号处理系统中最基本的元件之一。

fcec021ef4674ed78106ea128b57fd39.jpg

 与其他滤波器相比,FIR 滤波器具有独特的优势。它可以在保证任意幅频特性的同时具有严格的线性相频特征,这意味着它能够在对信号进行滤波处理时,不会对信号的相位产生扭曲,从而保证了信号的准确性。

此外,FIR 滤波器的单位抽样响应是有限长的,这使得滤波器是稳定的系统,不会像某些无限脉冲响应滤波器那样可能出现不稳定的情况。

二、FIR滤波器的工作原理

FIR滤波器的核心在于输入信号与单位冲击响应函数的卷积运算。

7fcc2a807b824ee3bf0cca67c3cbd70e.jpg

 简单来说,就是将输入信号与滤波器的系数进行逐点相乘,然后将乘积结果累加起来,得到输出信号。

6b5d35a594974a2cb14f04782dde7a17.png

 在并行结构中,同一个时刻,每个输入数据都与对应的滤波器系数相乘,并同时将上一个时刻各项乘法的结果进行求和,这样就能得到滤波结果,每个周期输出一个数据,也就是说滤波计算处理频率与输入信号采样频率一样,但消耗的资源会随着滤波器阶数而增加。

0458ba2157f3410492a597e3b62a673d.webp

 在串行结构中,只需要一个乘法器即可,可以节省资源,为了满足输入信号采样频率下同步输出滤波结果,也就是在一个输入信号周期内,需要完成所有计算,所以对于一个N阶FIR滤波器,考虑到对称系数的特性只要做N/2个乘法运算,也就是计算处理频率是输入信号采样频率的N/2倍。

d194ef6cf85644f584ee1ec5e0b66d4b.jpg

 三、FPGA代码实现

 

module fir_serial
(
input rst,
input clk,
input [11:0] data_in,
output [28:0] data_out
);

reg [12:0] add_a, add_b;
wire [12:0] add_s;

reg [11:0] coe; //12bit量化滤波器系数
wire [24:0] Mout;

reg [2:0] cnt;
reg [11:0] data_reg[15:0];
integer i;

reg [28:0] sum;
reg [28:0] data_out_temp;

always @ (posedge clk or posedge rst)
if (rst) cnt <= 'd0;
else cnt <= cnt + 1'b1;

always @ (posedge clk or posedge rst)
if (rst) begin //清0
data_reg[15] <= 'd0;
for (i=0; i<15; i=i+1'b1)
data_reg[i] <= 'd0;
end else begin
if (cnt == 'd7) begin
for (i=0; i<15; i=i+1'b1) //移位
data_reg[i+1] <= data_reg[i];
data_reg[0] <= data_in;
end
end

always @ (posedge clk or posedge rst)
if (rst) begin
add_a <= 'd0; add_b <= 'd0; coe <= 'd0;
end
else begin
case (cnt)
'd0: begin
add_a <= {data_reg[0][11], data_reg[0]};
add_b <= {data_reg[15][11], data_reg[15]};
coe <= 12'h000;
end
'd1: begin
add_a <= {data_reg[1][11], data_reg[1]};
add_b <= {data_reg[14][11], data_reg[14]};
coe <= 12'hffd;
end
'd2: begin
add_a <= {data_reg[2][11], data_reg[2]};
add_b <= {data_reg[13][11], data_reg[13]};
coe <= 12'h00f;
end
default: begin //第四个周期
add_a <= {data_reg[3][11], data_reg[3]};
add_b <= {data_reg[12][11], data_reg[12]};
coe <= 12'h02e;
end
endcase
end


assign add_s = add_a + add_b;
mult_gen_0 mult_inst
(
.CLK (clk),
.A (coe),
.B (add_s),
.P (Mout)
);
always @ (posedge clk or posedge rst)
if (rst) begin
sum <= 'd0; data_out_temp <= 'd0;
end
else begin
if (cnt == 'd2) begin
data_out_temp <= sum; sum <= {{4{Mout[24]}}, Mout};
end else
sum <= sum + {{4{Mout[24]}}, Mout};
end

assign data_out = data_out_temp;
endmodule


​如果需要更多学习资料和源码,想要学习FPGA实战入门进阶,请阅读下面这篇文章:
 

FPGA入门真的难吗?少走弯路,少踩坑。

 


http://www.mrgr.cn/news/23385.html

相关文章:

  • 线性代数基础
  • 【学术会议征稿】第八届电气、机械与计算机工程国际学术会议(ICEMCE 2024)
  • 下载运行flutter(3.22.3)项目踩坑记录
  • 解决el-table排序sortable只排序当前页问题
  • 关于使用ABB机器人MoveJ或MoveL报错50050或者轴配置出错问题解决办法
  • SQL server 日常运维命令
  • ubuntu 22.04 编译安装新内核
  • 萱仔个人博客系列——创建一个新的文章
  • UE4_后期处理_后期处理材质及后期处理体积一
  • GD32E230程序烧录和开发环境使用介绍
  • 机器学习 第9章 聚类
  • 安装OpenResty(Linux-Docker)
  • 什么是话费充值api接口?话费充值API接口如何对接?
  • Linux下快速比较两个目录的不同,包括文件内容
  • 2024年身份验证技术应用的10大发展趋势
  • HTML转义字符对照表
  • Spring Cloud全解析:熔断之Hystrix线程隔离导致的问题
  • 如何在NXP源码基础上适配ELF 1开发板的PWM功能
  • React(v18)事件原理
  • 具体的散列表实现示例