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

基于FPGA的FIR滤波器设计:从MATLAB参数设计到FPGA实现及验证

基于fpga的fir滤波器设计,通过matlab代码设计滤波器参数,最终通过fpga实现,modelsim仿真,最后在开发板上实现,两路adc采集的掺杂高频信号经过低通滤波器之后,由dac输出,由signal tap 抓取输入输出信号如下图,滤波效果良好,最后使用示波器查看adc输入和经过滤波器滤波后dac输出的数据正常。

最近在FPGA上折腾了个双通道FIR低通滤波器,从MATLAB仿真到Modelsim验证,最后在Cyclone IV开发板跑通了。整个过程踩了不少坑,但看着示波器上被驯服的高频噪声还是挺有成就感的。咱们直接上干货。

先甩段MATLAB代码生成滤波器系数。这里用汉明窗设计了个80阶低通,截止频率设20kHz(毕竟ADC采样率才100kHz):

order = 80; fc = 0.2; % 归一化截止频率 b = fir1(order, fc, 'low', hamming(order+1)); fvtool(b,1); % 可视化频率响应 dlmwrite('fir_coef.txt', b, 'precision', '%.18f');

系数生成后得注意定点化处理——直接用浮点数会吃光FPGA的DSP资源。我这边用Q2.14格式,在Quartus里搞了个COE文件导入ROM。有个细节:系数对称性可以省一半乘法器,但手写代码时容易把索引搞反,建议用MATLAB的fliplr函数预处理。

基于fpga的fir滤波器设计,通过matlab代码设计滤波器参数,最终通过fpga实现,modelsim仿真,最后在开发板上实现,两路adc采集的掺杂高频信号经过低通滤波器之后,由dac输出,由signal tap 抓取输入输出信号如下图,滤波效果良好,最后使用示波器查看adc输入和经过滤波器滤波后dac输出的数据正常。

上Verilog代码时,乘累加操作是关键。这里用了三级流水线结构提升时序性能:

always @(posedge clk) begin // 移位寄存器更新 delay_line <= {adc_data, delay_line[0:ORDER-1]}; // 对称系数乘法 for(int i=0; i<ORDER/2; i++) begin mult_result[i] <= $signed(delay_line[i]) * coeff[i]; mult_result[ORDER-1-i] <= $signed(delay_line[ORDER-1-i]) * coeff[i]; end // 流水线累加 sum_stage1 <= mult_result[0] + mult_result[1]; sum_stage2 <= sum_stage1 + mult_result[2]; // ... 实际需要循环处理 dac_data <= sum_final >>> 14; // Q格式转换 end

注意这里的符号位处理和移位操作,实测少个符号位会导致输出波形下半周削波。Modelsim仿真时特意灌入10kHz+50kHz混合信号,抓到的波形显示高频分量衰减了40dB以上。

SignalTap调试时发现个诡异现象——输出信号偶尔出现毛刺。后来发现是跨时钟域问题,ADC数据进来是12MHz,而FIR主频跑120MHz。加了个双时钟FIFO做缓冲,用Chip Planner查看布局布线确认时序收敛。

最后上板测试,用信号发生器同时给两路ADC输入1Vpp混合信号(1kHz正弦波+30kHz噪声),示波器抓到的输出信号信噪比提升了28dB。有意思的是发现FPGA温度比平时高了7℃,查资源报告发现用了86个DSP模块,看来这滤波器阶数确实有点猛。下次试试用DAFIR结构优化下资源消耗。

http://www.jsqmd.com/news/459305/

相关文章:

  • 鸿蒙中 系统语言和区域的获取与监听
  • 计算机毕业设计springboot单亲家庭帮扶管理系统 基于SpringBoot的单身父母家庭综合支持与服务系统 特殊结构家庭社会救助与资源对接数字化平台
  • Pscad仿真-三机九节点系统,储能替换一台同步机,对比是否加入调频策略 三机系统改成50hz
  • Adobe Photoshop
  • SpringBoot3快速集成SMS4J,10分钟搞定短信+OA双渠道消息发送
  • 02计算机组成原理-流水线冒险(上)
  • 06.Python 中数字:整数、浮点数完全指南
  • 新手避坑指南:惯性器件参数表里的‘零偏稳定性‘可能骗了你
  • 电力负荷聚类分析:从数据到典型场景
  • 基于PFC6.0的单轴拉伸实验:二维与三维探索及声发射振铃计数解析
  • 锂电池SOC估算:EKF估计SOC仿真与扩展卡尔曼滤波
  • 基于YOLOv8的钢材表面缺陷检测系统【附源码+可远程安装部署】
  • VC维与PAC学习:如何量化你的模型复杂度?
  • 用广义神经网络GRNN实现多特征输入单因变量输出的拟合预测
  • 【小龙虾】OpenClaw 3.8继续炸场!龙虾不睡觉,全球程序员连夜赶工
  • 基于MotorCAD的永磁电机退磁仿真及电流波形自定义探索
  • 车载以太网TC8测试实战:SOME/IP协议在SOA架构下的完整测试流程(含Vector工具链配置)
  • OEE提升15%的机械加工厂的数字化
  • RTKLIB实战:5分钟搞定标准单点定位(SPP)完整流程(附避坑指南)
  • 基于YOLOv8的花卉识别系统【附源码+可远程安装部署】
  • SecureCRT新手必看:10个高效命令让你远程操作飞起(附常用快捷键)
  • FastestDet:超越业界轻量级目标检测算法的五大特性
  • winform PictureBox 显示大图片带垂直滚动条
  • iReport 5.6.0实战:手把手教你用List组件搞定学生名单报表(附避坑指南)
  • 氚云 vs 宜搭:表单控件全对比,哪个更适合你的业务场景?
  • 基于RK3588J的AI检测设备实战解析
  • 为什么你的Ubuntu实时内核编译失败了?PREEMPT_RT补丁常见问题解析
  • 用Anki高效啃透华工通信原理:自制考点卡片模板分享(含HDB3编码/匹配滤波器真题)
  • 提示工程架构师实战:Agentic AI生态影响研究的样本选择策略
  • mfc140u.dll丢失的解决方法-mfc140u.dll文件下载