很多同学做电赛信号类题目比如 2023 年 H 题信号分离装置时第一次接触 FIR 滤波器都会卡在「系数」上代码里这一长串数字到底是啥 为什么注释说要替换成 MATLAB 生成的值 我自己随便写几个数不行吗这篇文章全程用生活化类比 大白话从底层逻辑到实操步骤讲透零基础也能看懂看完就能上手用。一、先搞懂FIR 滤波器到底是什么1. 一个生活化的类比想象你手里有一杯混在一起的「细沙子」和「粗石子」你想把两者分开你会用什么 答案很简单筛子。孔小的筛子沙子漏下去石子留在上面 → 留下细的、挡住粗的孔大的筛子石子也能漏下去 → 粗的细的都过去对应到电路的世界里混合的沙子石子 混合在一起的不同频率的电信号比如题目里的 50kHz 低频信号 100kHz 高频信号筛子 FIR 滤波器专门用来「按频率分拣信号」细沙子 低频信号粗石子 高频信号让低频通过、挡住高频 → 低通 FIR 滤波器让高频通过、挡住低频 → 高通 FIR 滤波器2. 那「FIR 系数」又是什么筛子的过滤效果完全由「孔的大小、孔的密度、筛子的层数」决定。 对应到 FIR 滤波器里决定滤波效果的这整套「设计参数」就是 FIR 系数。更直白一点1024 阶的 FIR 滤波器就有 1024 个系数 每个系数对应一个「权重值」 滤波器干活的本质就是把历史采样值按权重加权求和。3. 对应代码它到底是怎么干活的原理非常简单就是小学级别的「乘法 加法」没有任何玄学。你的 FPGA 每秒对信号采样很多次比如 100MHz 就是每秒采 1 亿次每采一个数就存起来一共存最近的 1024 个采样值。 每来一个新数据滤波器就做一件事把这 1024 个历史数值每个都乘上自己对应的权重系数再把所有结果加起来最终的和就是「滤波后的输出值」。举个最小的例子3 阶 FIR只有 3 个系数滤波器系数[0.25, 0.5, 0.25]最近 3 个采样值[2, 4, 6]滤波结果 2×0.25 4×0.5 6×0.25 0.5 2 1.5 41024 阶的 FIR 逻辑完全一模一样只是从 3 个数相加变成了 1024 个数相加。 代码里的 BRAM 延迟线就是用来存这 1024 个历史采样值的MAC 乘累加单元就是专门算「乘法 加法」的硬件模块。二、为什么系数不能自己乱写必须用 MATLAB 生成核心一句话你想要的「刚好留住 50kHz、完美挡住 100kHz」这个效果对应的 1024 个权重是多少人工根本算不出来。展开讲 3 个最实在的原因每一个都对应电赛里的真实坑点1. 精度要求极高差一点效果就崩要做到「50kHz 信号几乎原样通过80kHz 以上的信号削弱 100 倍」这 1024 个系数的取值是非常精密的。 就像你要做一个筛子刚好留住 0.05mm 的沙子、挡住 0.1mm 的石子孔的大小、密度、排列都要精准计算不是随手画几个孔就能用的。系数差一点点就会出现该保留的信号被衰减输出幅值变小该滤掉的信号没挡住分离不干净严重的时候甚至完全分不出两路信号2. 数量太多人工根本算不完1024 个系数每个都是精确的小数还要满足「左右严格对称」的要求这样输出波形才不会变形。 人工算 1024 个精准的数算到明年也算不对还很容易算错。MATLAB 里有现成的专业工具函数比如fir1你只要告诉它 3 件事你的采样率是多少比如 100MHz截止频率是多少比如 60kHz 以下通过滤波器要多少阶比如 1024 阶它 1 秒钟就能算出 1024 个精准的系数还能直接生成你需要的整数格式复制粘贴就能用。这是电子行业的标准做法不是什么 “偷懒技巧”。3. 没有通用系数参数一变全得换FIR 系数不是万能的它和你的硬件参数是强绑定的。只要下面任意一个参数变了所有系数都要重新生成采样率变了比如从 100MHz 改成 50MHz截止频率变了比如从 60kHz 改成 70kHz滤波器阶数变了比如从 1024 阶改成 512 阶不存在一套 “拿过来就能用在所有项目里” 的通用系数必须根据你的实际电路参数用工具生成对应的值。三、为什么代码里的系数是 “占位符”很多网上的示例代码只中间会写前十几个和最后几个系数注释一句「由 MATLAB 生成」不是作者不想写全原因很现实太长了1024 个系数全写出来要占几十上百行代码示例代码会非常臃肿影响阅读不通用作者的采样率、截止频率和你的硬件不一定匹配全写给你也用不了。⚠️重点提醒直接用占位符代码编译上板一定会出问题。 相当于一个筛子大部分孔的大小都是错的根本滤不干净轻则分离效果差重则完全看不到分离后的波形基本分都拿不到。四、高频专业名词大白话对照表碰到术语不用慌下面这张表可以直接存下来对照看表格专业名词大白话解释阶数如 1024 阶系数的总个数相当于筛子的层数。阶数越高筛得越干净但运算量越大、占用资源越多。低通 / 高通 FIR低通 低频信号通过、高频挡住高通 高频信号通过、低频挡住。线性相位所有频率的信号通过滤波器后延迟时间完全一样。最大的好处是波形不会变形正弦波进去还是正弦波。要实现这点系数必须左右严格对称MATLAB 生成的系数天然满足。Q1.15 定点格式FPGA 不擅长算小数所以把所有小数放大 32768 倍转成整数来运算最后再缩回去。比如 0.5 就存成 16384。窗函数汉宁窗、汉明窗等设计滤波器的不同「配方」。不同配方效果不同有的筛得干净但过渡慢有的边缘锐利但旁瓣大电赛常规题目用汉宁窗就足够。通带 / 阻带通带 能顺利通过的频率范围阻带 被大幅削弱、挡住的频率范围。阻带衰减能把不需要的信号削弱多少倍比如 40dB 就是削弱 100 倍60dB 就是削弱 1000 倍。BRAM 延迟线FPGA 里的一块专用高速内存专门用来存最近的 1024 个采样值方便每次拿出来乘系数相加。MAC 乘累加FPGA 里专门算「乘法 加法」的硬件单元FIR 滤波的核心运算全靠它。五、电赛实操FIR 滤波器完整落地步骤讲完原理给你一套电赛里直接能用的标准流程照着做就能把 FIR 滤波器跑起来步骤 1确定你的设计指标先根据题目要求定参数以分离 50kHz 和 100kHz 为例系统采样率100MHz低通滤波器通带截止 60kHz阻带起始 80kHz高通滤波器通带起始 90kHz阻带截止 70kHz阶数1024 阶窗函数汉宁窗步骤 2用 MATLAB 生成系数把下面的脚本复制到 MATLAB 里运行一键就能生成 Verilog 能用的系数文件matlab%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 电赛FIR滤波器系数生成脚本 % 输出16位Q1.15定点格式可直接复制到Verilog代码 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clear; clc; %% 1. 设置参数 Fs 100e6; % 采样率 100MHz N 1024; % 滤波器阶数 F_pass_low 60e3; % 低通通带截止 60kHz %% 2. 设计低通滤波器并转定点 h_low fir1(N-1, F_pass_low/(Fs/2), low, hann(N)); h_low_fix round(h_low * 32767); % 转16位Q1.15整数 %% 3. 输出Verilog格式系数到文件 fid fopen(coeff_low.txt, w); for i 1:N val h_low_fix(i); if val 0 fprintf(fid, 16d%d,, val); else fprintf(fid, -16d%d,, abs(val)); end if mod(i, 8) 0 fprintf(fid, \n); end end fclose(fid); %% 4. 查看幅频响应验证效果 fvtool(h_low, 1, Fs, Fs); title(低通FIR滤波器幅频响应); disp(系数生成完成已保存为 coeff_low.txt);运行后会弹出一个窗口显示滤波器的幅频曲线你可以直观看到通带平不平、阻带衰减够不够。步骤 3把系数替换进 Verilog 代码打开生成的coeff_low.txt把里面的内容全选复制替换掉代码里系数数组的占位内容高通滤波器同理操作。步骤 4上板验证先输入单频信号用示波器测输出幅值确认通带内衰减小、阻带内衰减大再输入混合信号观测分离效果确认两路信号无明显串扰。六、电赛常见踩坑提醒不要随便改单个系数改一个就破坏了整体对称性线性相位会消失输出波形会失真。注意采样率匹配MATLAB 里填的采样率必须和 FPGA 实际的采样时钟一模一样差一点截止频率就会偏。防止溢出两路信号相加、乘累加后都要注意位宽要么加饱和截断要么扩展位宽避免波形削顶。阶数不是越高越好阶数越高延迟越大资源占用也越多满足题目要求即可不用盲目堆高阶。最后总结FIR 滤波器本质就是一个「按频率分拣信号的电子筛子」FIR 系数就是这个筛子的「设计图纸」决定了滤波效果的好坏系数数量多、精度要求高人工算不现实用 MATLAB 生成是行业标准做法电赛落地流程定指标 → MATLAB 生成系数 → 替换进代码 → 上板验证。FIR 滤波器是电赛信号题的基础核心搞懂原理再动手比盲目抄代码调 bug 效率高得多。我接着用「筛沙子」的类比把这些设计参数一个个掰开讲每个都讲清是什么、对应筛子的啥属性、改了会有什么影响全程不用公式看完就知道为什么要这么设。这些参数本质上就是你给 MATLAB 下的「定制筛子的规格要求」你说清楚要求工具才能给你生成刚好能用的系数。一、逐个参数大白话拆解1. 采样率Fs大白话定义FPGA 每秒对输入信号采集多少个数据点单位是 Hz。100MHz 采样率 每秒采 1 亿个点8.192MHz 采样率 每秒采 819.2 万个点筛子类比相当于你每秒舀多少勺沙子过筛。舀得越快单位时间处理的量越大。为什么重要它决定了你能处理的最高信号频率奈奎斯特极限最高只能处理采样率一半的频率。100MHz 采样率最多只能处理 50MHz 以内的信号超过就会混叠失真。设计系数和实际硬件必须严格一致。你 MATLAB 里填 100MHz 生成的系数放到 50MHz 的 FPGA 上截止频率会直接偏一半滤波器完全不准。2. 滤波器阶数N也叫抽头数大白话定义滤波器一共有多少个系数也就是加权求和的时候要拿多少个历史数据来算。1024 阶 1024 个系数 每次算结果要乘 1024 次、加 1024 次筛子类比筛子的层数。一层筛不干净就叠十层、一百层。层数越多筛得越干净但筛子越沉、筛得越慢。改了会怎样阶数越高 → 筛选的边界越锐利过渡带越窄、拦得越干净阻带衰减越大阶数越高 → 占用 FPGA 资源越多乘法器、内存都要更多、信号延迟越大电赛里够用就行不用盲目堆高阶1024 阶应对基础题完全足够。3. 通带截止频率Fpass大白话定义能几乎原样通过、几乎不被削弱的频率边界。低通滤波器低于这个频率的信号都能顺利通过高通滤波器高于这个频率的信号都能顺利通过筛子类比筛子的标准孔径。小于孔径的沙子全能漏下去几乎不被拦住。举例子 低通设置通带截止 60kHz → 50kHz 的信号在通带里输出幅值和输入几乎一样损失很小。4. 阻带起始频率Fstop大白话定义从这个频率开始信号会被大幅削弱基本过不去。低通滤波器高于这个频率的信号都会被大幅度衰减筛子类比肯定拦得住的石子尺寸。大于这个尺寸的石子基本全被扣在筛子上漏不下去。举例子 低通设置阻带起始 80kHz → 100kHz 的信号在阻带里会被削弱几十上百倍基本被滤干净。5. 过渡带Transition Band大白话定义通带和阻带中间的那段频率区间信号是慢慢被削弱的不是一刀切。比如通带 60kHz、阻带 80kHz过渡带就是 60kHz ~ 80kHz 这 20kHz 的区间筛子类比筛孔不是 100% 均匀的总有一些不大不小的颗粒会漏下去一部分、拦住一部分不是全过也不是全拦。重点常识 现实里不存在「60kHz 全过、60.001kHz 全挡」的理想滤波器所有真实滤波器都有过渡带。阶数越高过渡带越窄筛选边界越锐利阶数越低过渡带越宽边界越模糊这也是为什么题目要分离 50kHz 和 100kHz我们不把截止设成 50kHz要把 50kHz 放在通带里、100kHz 放在阻带里中间留够过渡带的空间不然 50kHz 刚好落在过渡带上会被衰减。6. 阻带衰减大白话定义阻带里的信号会被削弱到原来的多少分之一单位是 dB分贝。不用记公式记住常用值就行20dB 削弱到 1/1040dB 削弱到 1/10060dB 削弱到 1/1000数字越大衰减越狠滤得越干净筛子类比筛子拦石子的干净程度。40dB 就是 100 颗石子里只能漏下去 1 颗60dB 就是 1000 颗里才漏 1 颗。电赛参考一般 40dB 以上就够用分离出来的两路信号互相串扰很小示波器上基本看不到干扰。7. 通带纹波大白话定义通带里的信号幅值波动有多大也就是通带平不平。纹波小 通带里所有频率的增益几乎一样输出幅值稳定纹波大 通带里有的频率增益高、有的低信号会变形筛子类比合格的筛子所有小于孔径的沙子都应该漏得一样快不能有的漏得快、有的漏得慢。电赛参考用窗函数法设计的 FIR通带纹波本身就很小比如汉宁窗的纹波可以忽略基础题基本不用操心这个参数。8. 窗函数Window Function大白话定义设计滤波器的「数学配方 / 工艺」不同的窗函数做出来的滤波器特性不一样。筛子类比不同的筛子编织工艺。有的工艺做出来的筛子边缘过渡快但拦得不够干净有的工艺拦得特别干净但边缘过渡慢、边界模糊常见的几种窗函数对比电赛够用版表格窗函数阻带衰减过渡带特点矩形窗最差21dB最窄边界最锐利但拦得最不干净一般不用汉宁窗中等44dB中等均衡性最好电赛最常用不容易出错汉明窗较好53dB略宽于汉宁比汉宁窗干净一点过渡差不多布莱克曼窗很好74dB最宽滤得最干净但相同阶数下过渡带最宽电赛选型建议无脑选汉宁窗就行均衡、好调试、不容易出问题。二、参数之间的「此消彼长」关系设计滤波器不是参数越极端越好它们之间是互相约束的核心记住 3 条相同阶数下要阻带衰减越大过渡带就越宽要过渡带越窄阻带衰减就越小。既要窄过渡带、又要大衰减只能提高滤波器阶数代价是占用更多资源、延迟变大。采样率越高相同阶数下过渡带的绝对宽度就越大比如 100MHz 下过渡带 20kHz换成 50MHz 下过渡带就只有 10kHz。三、结合电赛 H 题完整的参数选型逻辑给你捋一遍为什么常规方案会选这些参数你就懂设计思路了需求分离 50kHz 和 100kHz 的混合信号选采样率FPGA 系统时钟 100MHz直接用 100MHz 采样简单省事也远高于信号频率的 2 倍不会混叠。定通带和阻带低通要留住 50kHz所以通带截止设 60kHz留 10kHz 余量要挡住 100kHz所以阻带起始设 80kHz留 20kHz 余量。过渡带 20kHz。高通反过来通带起始 90kHz阻带截止 70kHz。选阶数1024 阶汉宁窗刚好能在 20kHz 过渡带里做到 40dB 以上的衰减资源占用也不高性价比最高。选窗函数汉宁窗均衡稳定调试简单。最后总结这些参数本质就是「你想要什么样的筛子」的完整描述采样率 处理速度阶数 筛子层数通带 / 阻带 孔的大小、拦石子的尺寸窗函数 制作工艺你把这些要求告诉 MATLAB它就会算出对应的 1024 个系数你粘进代码里滤波器就能按你的要求干活了。