手把手教你用FPGA设计一个FIR数字滤波器

原创 电子工程世界 2025-01-03 08:01
要求

设计一个带通滤波器,并验证其功能。


1、使用MATLAB设计滤波器系数



MATLAB首页找到APP后找到滤波器设计工具并打开,使用该工具可以生成数字滤波器的系数后续用于FPGA配置FIR IP核。
打开滤波器设计工具后即可输入相关参数并设计需要的滤波器,本次设计一个带通滤波器,所以滤波器响应类型选择带通;设计方案选择FIR(有限冲激响应);滤波器阶数这里选择最小阶,也可以自己指定阶数,阶数越大滤波器的滤波效果越好但越耗费FPGA资源,阶数可以根据实际情况进行取舍;密度因子默认20;频率设定,本次设计的采样率设置为10MHz,滤波器的频率特性设置可以按照图示进行填写,图片指示的意义很清楚,Fstop1为下限阻带截止频率,这里设置为50kHz,Fpass1为下限通带截止频率,这里设置为100kHz,Fpass2为上限通道截止频率,这里设置为400kHz,Fstop2为上限阻带截止频率,这里设置为450kHz(Fpass1-Fstop1和Fstop2-Fpass2为过渡带宽度,本次设计的过渡带宽度为50kHz;Fpass2-Fpass1为通带宽度,本次设计的通带宽度为400kHz;其余为阻带);幅值设定,其中Astop为阻带衰减的幅度值,本次设计阻带衰减50dB,Apass为通带的纹波,这里限制通带纹波不超过0.1dB。
设置好以上参数后点击滤波器设计,等待片刻即可设计好所需滤波器,从左侧窗口当前滤波器信息中可以发现符合本次设计需求的最小阶数为483阶。
点击工具栏:
可以查看滤波器幅值响应、相位响应、零极点等。
点击工具栏文件--导出,即可导出设计的滤波器系数。导出后可以在工作区中看到滤波器系数的变量Num。
以下为本次导出的系数,一共484个。
滤波器系数在FPGA中导入时每个系数之间需要逗号隔开,所以这里将系数保存到txt并使用逗号隔开,注意最后一个数的逗号需要删除。
生成后的系数删除最后的逗号。


2、FPGA中FIR的实现



这里省略FPGA工程建立过程,新建工程后点击Create Block Design。
添加FIR IP核。
配置FIR IP核,Filter Option中Select Source选择Vector,Coefficient Vector中粘贴之前MATLAB生成的系数,其余保持默认。左边Freq.Response窗口中可以查看频率响应曲线。
Channel Specification中主要配置采样率和工作时钟,input Sampling Frequency(MHz)配置10MHz采样率,后续DDS工作时钟需要和采样率保持一致;Clock Frequency(MHz)配置200MHz后续FIR IP核的工作时钟给200MHz。
Implement配置,Coefficient With可以根据需要进行配置,本次设计时配置成24,配置成24时通过查看左边Freq.Response窗口可以发现两条红色和蓝色曲线重合较接近理想曲线Ideal,所以这里配置成24,也可以根据需要进行配置。
Interface这里配置如下:
FIR配置完后再增加一个fifo,配置如下:
配置完后将FIR和fifo相连并引出接口:
最后右击block design先generate Output ...再Create HDL...。


3、FPGA中DDS的实现



这里DDS用于产生FIR的输入信号。同样点击Create Block Design,添加DDS IP核。


Configuration配置System Clock(MHz)为10MHz即可,其余保持默认配置。
Detailed Implementation配置如下:
最后输出频率配置成0.15MHz即150kHz,也可以根据需要进行配置。
按照上述配置再生成50kHz、350kHz、450kHz频率的DDS。
生成完DDS后再生成一个fifo。该fifo用于跨时钟域,将DDS产生的10MHz时钟域的信号转到200MHz时钟域输入FIR进行滤波。fifo配置如下,深度16,数据位宽16bit。
最后将生成的IP核按下图连线,该dds用于测试fir滤波器。可以外部可以将DDS生成的350kHz和150kHz进行叠加后再输入到fifo中,最后经过跨时钟域后从Multi_wave_M_AXIS输出到FIR进行滤波,叠加后的波形存在和频(500kHz)、差频(200kHz),经过滤波器后只剩下差频200kHz,如果滤波器输出200kHz正弦波则说明设计符合预期。也可以将单频信号(50kHz/150kHz/350kHz/450kHz)输入滤波器查看滤波器输出幅度情况。


4、top模块编写



顶层模块例化两个block_design ,dds产生50kHz、150kHz、350kHz和450kHz的正弦信号,外部将dds生成的其中两个信号做乘法后输入到dds的fifo接口中,使相乘的信号从10Mhz时钟域到200Mhz时钟域,最后输入到FIR中进行滤波。如果需要测试FIR单频信号的滤波器则可以将DDS输出的其中一个信号与常数相乘后再输入到FIR中进行测试。另外top模块中还需例化一个pll产生10MHz时钟用于DDS产生信号,以及200MHz时钟用于FIR。

  • module fir_top(

  • input pl_ref_clk_100m_p,

  • input pl_ref_clk_100m_n

  • );

  • reg [4:0] cnt;

  • wire clk_10m,clk_200m;

  • wire signed [7:0] M_AXIS_50k_tdata;

  • wire M_AXIS_50k_tvalid,M_AXIS_50k_tready;

  • wire signed [7:0] M_AXIS_150k_tdata;

  • wire M_AXIS_150k_tvalid,M_AXIS_150k_tready;

  • wire signed [7:0] M_AXIS_350k_tdata;

  • wire M_AXIS_350k_tvalid,M_AXIS_350k_tready;

  • wire signed [7:0] M_AXIS_450k_tdata;

  • wire M_AXIS_450k_tvalid,M_AXIS_450k_tready;

  • wire signed [15:0] Multi_wave_S_AXIS_tdata;

  • wire Multi_wave_S_AXIS_tvalid,Multi_wave_S_AXIS_tready;

  • wire signed [15:0] Multi_wave_M_AXIS_tdata;

  • wire Multi_wave_M_AXIS_tvalid,Multi_wave_M_AXIS_tready;

  • wire signed [15:0] FIR_S_AXIS_tdata;

  • wire FIR_S_AXIS_tvalid,FIR_S_AXIS_tready;

  • wire signed [23:0] FIR_M_AXIS_tdata;

  • wire FIR_M_AXIS_tvalid,FIR_M_AXIS_tready;

  • assign rst_n = locked;

  • // Multi_wave_S_AXIS

  • assign Multi_wave_S_AXIS_tdata = M_AXIS_450k_tdata * 8'hff/*M_AXIS_350k_tdata */;

  • assign Multi_wave_S_AXIS_tvalid = M_AXIS_450k_tvalid & 1/*M_AXIS_350k_tvalid */;

  • assign M_AXIS_50k_tready = Multi_wave_S_AXIS_tready;

  • assign M_AXIS_150k_tready = Multi_wave_S_AXIS_tready;

  • assign M_AXIS_350k_tready = Multi_wave_S_AXIS_tready;

  • assign M_AXIS_450k_tready = Multi_wave_S_AXIS_tready;

  • // Multi_wave_M_AXIS

  • assign FIR_S_AXIS_tvalid = Multi_wave_M_AXIS_tvalid;

  • assign FIR_S_AXIS_tdata = Multi_wave_M_AXIS_tdata;

  • assign Multi_wave_M_AXIS_tready = FIR_S_AXIS_tready;


  • assign FIR_M_AXIS_tready = (cnt == 'd19) && Multi_wave_M_AXIS_tvalid;

  • dds_design_wrapper dds_design(

  • .M_AXIS_150k_tdata (M_AXIS_150k_tdata ),

  • .M_AXIS_150k_tready (M_AXIS_150k_tready ),

  • .M_AXIS_150k_tvalid (M_AXIS_150k_tvalid ),

  • .M_AXIS_350k_tdata (M_AXIS_350k_tdata ),

  • .M_AXIS_350k_tready (M_AXIS_350k_tready ),

  • .M_AXIS_350k_tvalid (M_AXIS_350k_tvalid ),

  • .M_AXIS_450k_tdata (M_AXIS_450k_tdata ),

  • .M_AXIS_450k_tready (M_AXIS_450k_tready ),

  • .M_AXIS_450k_tvalid (M_AXIS_450k_tvalid ),

  • .M_AXIS_50k_tdata (M_AXIS_50k_tdata ),

  • .M_AXIS_50k_tready (M_AXIS_50k_tready ),

  • .M_AXIS_50k_tvalid (M_AXIS_50k_tvalid ),

  • .Multi_wave_M_AXIS_tdata (Multi_wave_M_AXIS_tdata ),

  • .Multi_wave_M_AXIS_tready(Multi_wave_M_AXIS_tready),

  • .Multi_wave_M_AXIS_tvalid(Multi_wave_M_AXIS_tvalid),

  • .Multi_wave_S_AXIS_tdata (Multi_wave_S_AXIS_tdata ),

  • .Multi_wave_S_AXIS_tready(Multi_wave_S_AXIS_tready),

  • .Multi_wave_S_AXIS_tvalid(Multi_wave_S_AXIS_tvalid),

  • .aresetn (rst_n ),

  • .clk_10m (clk_10m ),

  • .clk_200m (clk_200m )

  • );

  • always@(posedge clk_200m or negedge rst_n)begin

  • if(!rst_n)begin

  • cnt <= 'd0;

  • end

  • else begin

  • cnt <= (cnt == 'd19)? 'd0 : (cnt + 1'b1);

  • end

  • end

  • bandpass_fir_wrapper bandpass_fir(

  • .FIR_M_AXIS_tdata (FIR_M_AXIS_tdata ),

  • .FIR_M_AXIS_tready (FIR_M_AXIS_tready ),

  • .FIR_M_AXIS_tvalid (FIR_M_AXIS_tvalid ),

  • .FIR_S_AXIS_tdata (FIR_S_AXIS_tdata ),

  • .FIR_S_AXIS_tready (FIR_S_AXIS_tready ),

  • .FIR_S_AXIS_tvalid (FIR_S_AXIS_tvalid ),

  • .aresetn (rst_n ),

  • .clk_200m (clk_200m )

  • );

  • clk_wiz_0 pll(

  • .clk_10m(clk_10m),

  • .clk_200m(clk_200m), // output clk_200m

  • .reset(1'b0), // input reset

  • .locked(locked), // output locked

  • .clk_100m_in(clk_100m) // input clk_100m_in

  • );

  • IBUFDS clk_100m_ibufds(

  • .O (clk_100m),

  • .I (pl_ref_clk_100m_p),

  • .IB (pl_ref_clk_100m_n)

  • );

  • endmodule




5、功能仿真



DDS产生的四个信号如下:
50kHz信号,一个时钟周期的时间为102.31-82.31=20us,刚好为50kHz。
150kHz,一个时钟周期的时间为82.51-75.91=6.6us,频率约为151515Hz。
350kHz,一个是时钟周期的时间为71.21-68.31=2.9us,频率约为344827Hz。
450kHz,一个时钟周期的时间为91.51-89.31=2.2us,频率约为454545Hz。
将150kHz正弦和350kHz正弦叠加后输入到FIR,输入信号代码修改如下(配图中的频率写错了,实际是150kHz和350kHz相叠加,图片的是450kHz和350kHz,图片上的组合也不影响测试FIR,因为两个信号的和频以及差频为800kHz和100kHz,经过滤波器后100kHz信号正常输出而800kHz信号则被滤除):
两个光标之间的间隔为112.975-102.975=10us,每个时钟周期为5us,所以滤波器输出的频率为200kHz。由于输入的信号为150kHz正弦波叠加350kHz的正弦波,叠加后的波形存在和频500kHz和差频200kHz,由于500kHz在滤波器通频带外,所以500kHz的信号会被滤除,经过滤波器后只剩下200kHz的正弦波。所以仿真结果符合滤波器特性。仿真波形如下图,其中FIR_M_AXIS_tdata信号为FIR滤波输出信号。
将50kHz正弦信号输入FIR,输入信号代码修改如下:50kHz信号与常数8‘hff叠加后输入到FIR。
由于50kHz在滤波器带外,所以经过滤波器后幅度应该被衰减。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata被衰减,符合预期。
将150kHz正弦信号输入FIR,输入信号代码修改如下:150kHz信号与常数8‘hff叠加后输入到FIR。
由于150kHz在滤波器带内,所以经过滤波器后幅度不变。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata幅度正常,符合预期。
将350kHz正弦信号输入FIR,输入信号代码修改如下:350kHz信号与常数8‘hff叠加后输入到FIR。
由于350kHz在滤波器带内,所以经过滤波器后幅度不变。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata幅度正常,符合预期。
将450kHz正弦信号输入FIR,输入信号代码修改如下:450kHz信号与常数8‘hff叠加后输入到FIR。
由于450kHz在滤波器带外,所以经过滤波器后幅度应该被衰减。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata被衰减,符合预期。


6、结论


从仿真结果可知输入信号不管是单频信号还是叠加后的双频信号,结果都符合预期。相关工程源码请点击阅读原文,在原贴中下载。


· END ·


欢迎将我们设为“星标”,这样才能第一时间收到推送消息。

关注下方“汽车开发圈”回复“Auto”,免费领取Autosar入门与实践资料包!


扫码添加小助手回复“进群”

和电子工程师们面对面交流经验

电子工程世界 关注EEWORLD电子工程世界,即时参与讨论电子工程世界最火话题,抢先知晓电子工程业界资讯。
评论
  • Matter加持:新世代串流装置如何改变智能家居体验?随着现在智能家庭快速成长,串流装置(Streaming Device,以下简称Streaming Device)除了提供更卓越的影音体验,越来越多厂商开始推出支持Matter标准的串流产品,使其能作为智能家庭中枢,连结多种智能家电。消费者可以透过Matter的功能执行多样化功能,例如:开关灯、控制窗帘、对讲机开门,以及操作所有支持Matter的智能家电。此外,再搭配语音遥控器与语音助理,打造出一个更加智能、便捷的居家生活。支持Matter协议
    百佳泰测试实验室 2025-01-03 10:29 107浏览
  • 物联网(IoT)的快速发展彻底改变了从智能家居到工业自动化等各个行业。由于物联网系统需要高效、可靠且紧凑的组件来处理众多传感器、执行器和通信设备,国产固态继电器(SSR)已成为满足中国这些需求的关键解决方案。本文探讨了国产SSR如何满足物联网应用的需求,重点介绍了它们的优势、技术能力以及在现实场景中的应用。了解物联网中的固态继电器固态继电器是一种电子开关设备,它使用半导体而不是机械触点来控制负载。与传统的机械继电器不同,固态继电器具有以下优势:快速切换:确保精确快速的响应,这对于实时物联网系统至
    克里雅半导体科技 2025-01-03 16:11 132浏览
  • 本文继续介绍Linux系统查看硬件配置及常用调试命令,方便开发者快速了解开发板硬件信息及进行相关调试。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。查看系统版本信息查看操作系统版本信息root@ido:/# cat /etc/*releaseDISTRIB_ID=UbuntuDISTRIB_RELEASE=20.04DISTRIB_CODENAME=focalDIS
    Industio_触觉智能 2025-01-03 11:37 105浏览
  • 在快速发展的能源领域,发电厂是发电的支柱,效率和安全性至关重要。在这种背景下,国产数字隔离器已成为现代化和优化发电厂运营的重要组成部分。本文探讨了这些设备在提高性能方面的重要性,同时展示了中国在生产可靠且具有成本效益的数字隔离器方面的进步。什么是数字隔离器?数字隔离器充当屏障,在电气上将系统的不同部分隔离开来,同时允许无缝数据传输。在发电厂中,它们保护敏感的控制电路免受高压尖峰的影响,确保准确的信号处理,并在恶劣条件下保持系统完整性。中国国产数字隔离器经历了重大创新,在许多方面达到甚至超过了全球
    克里雅半导体科技 2025-01-03 16:10 87浏览
  • 影像质量应用于多个不同领域,无论是在娱乐、医疗或工业应用中,高质量的影像都是决策的关键基础。清晰的影像不仅能提升观看体验,还能保证关键细节的准确传达,例如:在医学影像中,它对诊断结果有着直接的影响!不仅如此,影像质量还影响了:▶ 压缩技术▶ 存储需求▶ 传输效率随着技术进步,影像质量的标准不断提高,对于研究与开发领域,理解并提升影像质量已成为不可忽视的重要课题。在图像处理的过程中,硬件与软件除了各自扮演着不可或缺的基础角色,有效地协作能够确保图像处理过程既高效又具有优异的质量。软硬件各扮演了什么
    百佳泰测试实验室 2025-01-03 10:39 89浏览
  • 车身域是指负责管理和控制汽车车身相关功能的一个功能域,在汽车域控系统中起着至关重要的作用。它涵盖了车门、车窗、车灯、雨刮器等各种与车身相关的功能模块。与汽车电子电气架构升级相一致,车身域发展亦可以划分为三个阶段,功能集成愈加丰富:第一阶段为分布式架构:对应BCM车身控制模块,包含灯光、雨刮、门窗等传统车身控制功能。第二阶段为域集中架构:对应BDC/CEM域控制器,在BCM基础上集成网关、PEPS等。第三阶段为SOA理念下的中央集中架构:VIU/ZCU区域控制器,在BDC/CEM基础上集成VCU、
    北汇信息 2025-01-03 16:01 140浏览
  • 在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容,修改源码再编译很费时。今天为大家介绍一个便捷的方法,让OpenHarmony通过挂载镜像来修改镜像内容!触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器,树莓派卡片电脑设计,支持开源鸿蒙OpenHarmony3.2-5.0系统,适合鸿蒙开发入门学习。挂载镜像首先,将要修改内容的镜像传入虚拟机当中,并创建一个要挂载镜像的文件夹,如下图:之后通过挂载命令将system.img镜像挂载到sys
    Industio_触觉智能 2025-01-03 11:39 92浏览
  • 【工程师故事】+半年的经历依然忧伤,带着焦虑和绝望  对于一个企业来说,赚钱才是第一位的,对于一个人来说,赚钱也是第一位的。因为企业要活下去,因为个人也要活下去。企业打不了倒闭。个人还是要吃饭的。企业倒闭了,打不了从头再来。个人失业了,面对的不仅是房贷车贷和教育,还有找工作的焦虑。企业说,一个公司倒闭了,说明不了什么,这是正常的一个现象。个人说,一个中年男人失业了,面对的压力太大了,焦虑会摧毁你的一切。企业说,是个公司倒闭了,也不是什么大的问题,只不过是这些公司经营有问题吧。
    curton 2025-01-02 23:08 244浏览
  • 自动化已成为现代制造业的基石,而驱动隔离器作为关键组件,在提升效率、精度和可靠性方面起到了不可或缺的作用。随着工业技术不断革新,驱动隔离器正助力自动化生产设备适应新兴趋势,并推动行业未来的发展。本文将探讨自动化的核心趋势及驱动隔离器在其中的重要角色。自动化领域的新兴趋势智能工厂的崛起智能工厂已成为自动化生产的新标杆。通过结合物联网(IoT)、人工智能(AI)和机器学习(ML),智能工厂实现了实时监控和动态决策。驱动隔离器在其中至关重要,它确保了传感器、执行器和控制单元之间的信号完整性,同时提供高
    腾恩科技-彭工 2025-01-03 16:28 134浏览
  • 光耦合器,也称为光隔离器,是一种利用光在两个隔离电路之间传输电信号的组件。在医疗领域,确保患者安全和设备可靠性至关重要。在众多有助于医疗设备安全性和效率的组件中,光耦合器起着至关重要的作用。这些紧凑型设备经常被忽视,但对于隔离高压和防止敏感医疗设备中的电气危害却是必不可少的。本文深入探讨了光耦合器的功能、其在医疗应用中的重要性以及其实际使用示例。什么是光耦合器?它通常由以下部分组成:LED(发光二极管):将电信号转换为光。光电探测器(例如光电晶体管):检测光并将其转换回电信号。这种布置确保输入和
    腾恩科技-彭工 2025-01-03 16:27 126浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦