在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 1624|回复: 6

[原创] 孩子都能学会的FPGA:第十六课——用FPGA实现IIR滤波器

[复制链接]
发表于 2023-11-30 15:59:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 chdaj58 于 2023-11-30 16:05 编辑

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿真环境,只需要双击top_tb.bat文件就可以完成整个的仿真(前提是安装了modelsim),降低了初学者的门槛。如需整个工程请留言(WX:Blue23Light),不收任何费用,但是仅供参考,不建议大家获得资料后从事一些商业活动!

上节课我们将不同频率的正弦波叠加,造成输出波形上有很多毛刺,这在实际应用中,就是在我们需要的信号上叠加了干扰!如何去除干扰呢?那就要设计数字滤波器将干扰频率的波形滤除,保留需要的信号即可。

常用的数字滤波器有无限脉冲响应数字滤波器(Infinite Impulse Response),简称IIR滤波器;还有就是有限脉冲响应数字滤波器(Finite Impulse Response),简称FIR滤波器。

由于本节课程的重点不是讲数字滤波器的,所以要熟悉数字滤波器请去网上收索相关的内容,本节就是使用IIR滤波器来去除高频的干扰,让经过滤波器后的波形平滑。这儿只说明一点,IIR滤波器不光用到输入的数据,还需要输出的反馈数据,而FIR滤波器只需要输入的数据即可,所以从设计难度上来说,IIR设计难度更大一些。

设计IIR滤波器,可以不了解滤波的原理,但是要知道IIR的结构。IIR滤波器的系统函数的标准型如下所示:

v2-a15e51dfc16b37957aec67b4bf69ad63_720w.png

但是FPGA设计的时候需要用的是差分型,如下所示:
v2-50226967007d88e3a0d44833f63e0b31_720w.png
以二阶的IIR为例,用matlab搭建的simulink仿真图如下所示,需要的参数有coeff_scale,coeff_in,coeff_out1coeff_out2,只要确定这几个参数就可以完成IIR滤波器的设计。

v2-6be75858212194de3bc75b764ee0b06e_720w.png

下面讲述一下如何确定这几个参数,通过matlab的APP打开Filter Designer。

v2-1c30a34f5297fc6a961fa351fe943d80_720w.png

参数设置页面进行如下的设置,Response选择lowpass,IIR的Elliptic,Specify order选择2,采样频率Fs是2MHz(因为系统时钟是100MHz,50个系统时钟输入一个数据就是2MHz),Fpass设置是100KHz。最后点击Design Filter完成参数的设置。


v2-d4743636870a797a3711166b4e5210f9_720w.png
然后点击File,Export。


v2-bc6e31bf2f92ae15f81f64e25da7c49a_720w.png

最终将参数导入到Workspace即可,参数矩阵是SOS,增益参数是G

v2-c071eb1b864f29911e221907882c9ea4_720w.png

SOS的第2个参数就是coeff_in,第5个参数是coeff_out1,第6个参数是coeff_out2;G的第2个参数就是coeff_scale。


v2-2eb606140374d6ff1226d66851785900_720w.png


v2-2afbd3e31779b3c85d61145fdd4ee642_720w.png

得到的参数都是带小数点的,直接在FPGA内部是无法使用的,我们必须转换成16进制的定点数。可以使用指令y=fi(SOS,1,44,40),将SOS的数据转化成1个符号位,3个整数位,40个小数位的定点数,然后再使用y.hex指令将10进制的定点数转换成16进制的定点数。最终的参数如下所示。

v2-79fdeb69dffbae08b7a80dfdefa001ad_720w.png

有了参数,我们就开始IIR滤波器的设计。根据matlab的simulink仿真图,我们可以得到如下的差分公式:

y(n)=coeff_scale[x(n)+coeff_in*x(n-1)+x(n-2)]-coeff_out1*y(n-1)-coeff_out2*y(n-2),在这儿我们采用串行的方式,用一个乘法器来实现IIR的滤波。

为了模块的通用化,通过参数传递完成数据位宽的传递。这儿对数据位宽进行了扩展,考虑有多个加减法,直接将数据扩展了8位。输入的数据是9位,扩展8位后是17位。乘法运算后数据位宽再扩展44位,即61位。

v2-836e38487f00336b37faf68881b51177_720w.png

下面是中间要使用信号的定义,需要注意位宽。


v2-628e45c344cdced744faa0156a261657_720w.png

定义了相关的状态机,MULT_SCALE是完成coeff_scale*x(n)的计算,计算的结果存在mult_scale中,然后按照采样率打拍缓存到data_in_dly1(就是coeff_scale*x(n-1))和data_in_dly2(coeff_scale*x(n-2))中;状态机MULT_DI_DLY1是计算coeff_in*data_in_dly1;状态机MULT_DO_DLY1是计算coeff_out1*y(n-1);状态机MULT_DO_DLY2是计算coeff_out2*y(n+1);后面的四个状态机主要完成前面5个数据的加减运行,一个状态机完成一步的加或减。

v2-3777d0610223d4fcf1a57a2cadc8bb80_720w.png

状态机的跳转用组合逻辑实现,非常的简单,每次乘法或者加减法计算完成跳转到下一个状态,如下所示(代码太长,部分截图)。


v2-04846d978e7f5e1b9a24b9751779b559_720w.png

例化了一个乘法器,4个时钟周期出计算结果,根据状态机给乘数和被乘数赋不同的值,并产生开始计算的mult_en信号,主要用于4个时钟的计数。如下图所示(代码太长,部分截图)。


v2-718f36f70309de1df865b666d6337f5c_720w.png

乘法相关的信号,包括计数mult_cnt,乘法计算完成mult_vld,和结果mult_scale,mult_din,mult_dout1,mult_dout2等信号(代码太长,部分截图)。需要注意的是对乘法后的结果进行了小数位的截断,因为输入数据是整数,相乘后保留整数位即可,把小数直接舍弃即可。首位是符号位,是一定要取的。

v2-6d81b51b5531ebc79a92b613725f95dc_720w.png

根据状态机产生加减运算的使能信号addsub_en(代码太长,部分截图)。

v2-7cf80a9a53884f96f4b9006c0f49dc32_720w.png

产生加减法完成有效的信号addsub_vld,同时将输入和输出的数据按照采样率进行打拍,因为这儿用的是二阶的IIR,输入和输出打两拍即可,就是得到x(n-1),x(n-2),y(n-1),y(n-2)


v2-08c1b72a171574b2a9f9bd129975e7f9_720w.png
根据状态机完成加减法数据的运算。


v2-3d5ee1a9f33e0468bfcce7e00d9291fa_720w.png

最后就可以得到IIR滤波器的结果,注意经过IIR滤波器后输出数据的结果和输入数据的结果是一样的。

v2-fa840950f4fb1c5d96a3f4a17c637dc4_720w.png

完成设计后,建立仿真文件,双击sim目录下的top_tb.bat文件,完成自动化的仿真。


v2-551faef9f8dbc00efb8653156cacc80c_720w.png

仿真结果如下所示,经过IIR滤波后,基本恢复出来了低频的正弦波信号。滤波后的数据不是非常的平滑,可以改变滤波器的参数来改善一下。


v2-a2fded5ea95413f305534653d1beff9c_720w.png

IIR滤波器使用FPGA设计的流程就是这样的,读者可能会说如果需要更快的采样频率怎么办?我们可以大体评估一下现在的一次IIR需要多少时钟周期。一次乘法共需要8个时钟周期(进入状态机1个时钟,乘法使能1个时钟,计数了6次),一次加减法是3个时钟周期(进入状态机1个时钟,加减法使能1个时钟,出结果1个时钟),IIR的计数共用到了4次乘法和4次加法,那就是8*4+4*3=44个时钟周期,再加上IDLE和END各1个数时钟周期,那1次的IIR需要大约46个时钟周期。

如果想加快采样频率,那一次IIR的计数时间要缩短才可以!这儿就要设计FPGA设计的一个重要思想:用面积来换速度!因为上面的设计只用到了一个乘法器和加减法器,其实是可以使用多个乘法器和加减法器的。IIR可以使用4个乘法器(mult_scale*mult_din可以定义成一个参数),那就是8个时钟周期就可以完成所有乘法的运算;使用2个加减法器,4次的加减法可以缩短2次计数完成,那一次的IIR运算需要8+2*3+2=16个时钟周期!我们可以使用更多的FPGA资源来换取更快的处理速度!建议读者自己设计完成。

使用FIR滤波器也可以实现上面的功能,可能需要的阶数要多一些,建议读者自己来实现一下。


发表于 2023-12-1 08:33:14 | 显示全部楼层
赞!
发表于 2024-1-16 15:25:12 | 显示全部楼层
收藏下
发表于 2024-5-30 15:02:46 | 显示全部楼层
顶很好
发表于 2024-6-25 13:54:55 | 显示全部楼层
感谢分享
发表于 2024-6-26 10:22:50 | 显示全部楼层
Great, thanks
发表于 2024-7-16 17:27:32 | 显示全部楼层
感谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-27 04:59 , Processed in 0.027520 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表