简介:这份资源面向FPGA初学者与数字系统设计进阶者,提供基于Quartus II 13.1与Verilog HDL实现的等精度数字频率计完整工程。设计覆盖1Hz至150MHz宽频率范围,测量误差控制在0.01%以内,涉及采样量化、分频器、同步电路、误差校正、串口通信及Modelsim仿真验证等核心环节,可用于通信测试、科研测量等需要精确频率计数的场景。压缩包共390个文件,约17.56MB,以cdb、hdb、tdf等Quartus工程与仿真中间文件为主,辅以15个v源码文件、vo仿真输出、qsf与qpf工程配置、sof烧录文件及readme说明,完整保留从源码到综合布线的工程结构。目前已有1411人学习下载。读者可据此复现等精度测频算法,理解分频系数与同步时序对精度的影响,并借助测试平台文件排查计数与串口输出问题,适合作为课程设计或竞赛项目的参考工程。
1. 从一次测量翻车说起:为什么等精度频率计值得单独做一套方案
低频段测得好好的,一换到高频信号,读数就开始跳,误差大得没法看——这是很多人在做数字频率计时踩过的第一个坑。传统直接测频法在低频段精度尚可,但频率越高、闸门时间内计到的脉冲数越少,±1 个计数的量化误差占比就越大,读数自然不稳。等精度测量法正是冲着这个痛点来的:它让闸门时间跟随被测信号同步,在高频和低频段都能维持相同的相对测量精度,测量范围广、全频段精度一致,这也是它比普通测频方案更值得单独做一套完整设计的原因。
这套方案基于 Quartus II 13.1 和 Verilog HDL,面向的是要做数字频率计毕设、课设,或者需要一套可综合、可上板验证的等精度测频参考设计的同学和工程师。整份方案从需求拆到模块划分,再到 Verilog 实现和上板验收,能直接照着改、照着交。下面按「需求 → 设计 → 实现 → 避坑 → 验收」的顺序展开。
2. 需求分析与技术选型:等精度测频到底解决了什么问题
2.1 三种测频方法的取舍
做频率计绕不开三种方法:直接测频法、测周法、等精度测频法。直接测频法在固定闸门时间内数被测脉冲个数,频率越高计数值越大、相对误差越小,但低频段计数值小,误差被放大。测周法反过来,测一个周期的时间再取倒数,低频准、高频不准。等精度测频法的思路是让实际闸门时间由被测信号自己「卡」出来——用被测信号的边沿去同步标准闸门的起止,这样计数值始终是整数个被测周期,量化误差只跟标准时钟有关,与被测频率无关。
| 方法 | 适用频段 | 相对误差特点 | 实现复杂度 |
|---|---|---|---|
| 直接测频法 | 高频 | 低频误差大 | 低 |
| 测周法 | 低频 | 高频误差大 | 低 |
| 等精度测频法 | 全频段 | 全频段一致 | 中 |
选等精度法,本质是用一点控制逻辑的复杂度,换全频段一致的测量精度,这笔账在做毕设时是划算的。
2.2 关键指标怎么定
指标定不下来,后面模块没法划分。通常的做法是先明确这几项:测量范围(比如 1Hz~50MHz)、闸门时间(常用 1s,也可切 0.1s/10s)、相对误差(等精度下主要由标准时钟决定,1s 闸门配 50MHz 标准时钟,理论相对误差在 10⁻⁷ 量级)、显示位数(一般 8 位十进制)。标准时钟频率越高,量化误差越小,但功耗和时序压力也越大,50MHz 是个常见折中。
提示:闸门时间不是越长越好。1s 闸门刷新慢,做实时显示时体验差;10s 闸门精度高但响应迟钝。毕设里给个档位切换,答辩时能讲清楚取舍就够了。
2.3 为什么是 Quartus II 13.1 + Verilog
Quartus II 13.1 是老牌 FPGA 开发环境,对 Cyclone 系列支持成熟,工程结构清晰,适合教学和中小规模设计。Verilog 可综合子集足够描述测频的时序逻辑,且代码可移植到其他厂商工具链。选这套组合,一是资料多、踩坑少,二是综合报告和时序分析能直接作为验收依据,答辩时有据可查。
3. 总体架构设计:四个模块的职责划分与数据流
3.1 模块划分
整套设计拆成四个模块:分频与时钟管理、等精度测频核心、数据锁存与换算、数码管显示驱动。分频模块产生标准时钟和扫描时钟;测频核心负责同步闸门、计数;锁存换算把计数值转成频率值并拆成十进制位;显示驱动做动态扫描。
被测信号 ──┐ ├──► 等精度测频核心 ──► 数据锁存与换算 ──► 数码管显示驱动 标准时钟 ──┘ ▲ │ 分频与时钟管理数据流是单向的:测频核心每个闸门周期输出一组计数值,锁存模块在闸门结束时锁存并换算,显示模块持续扫描。这样划分的好处是每个模块接口清晰,单独仿真和上板调试都方便。
3.2 等精度测频的时序逻辑
核心时序是这样的:预设闸门信号到来后,不立即开始计数,而是等被测信号的上升沿,用这个边沿把闸门「打开」;预设闸门结束时,同样等被测信号的下一个上升沿再「关闭」。这样实际闸门时间恰好是被测信号周期的整数倍。在这段实际闸门时间内,同时用标准时钟计数,得到标准时钟计数值 Ns,被测信号计数值 Nx,则被测频率 Fx = Fs × Nx / Ns。
3.3 顶层接口定义
顶层模块把四个子模块例化连接,对外只留被测信号输入、时钟输入、复位、数码管段选位选输出。接口越少,上板接线越不容易出错。
module freq_meter_top( input wire clk_50m, // 板载50MHz标准时钟 input wire rst_n, // 低电平复位 input wire sig_in, // 被测信号输入 output wire [7:0] seg, // 数码管段选 output wire [7:0] sel // 数码管位选 ); wire [31:0] freq_val; // 换算后的频率值 wire [31:0] nx_cnt, ns_cnt; // 被测/标准计数值 // 子模块例化:分频、测频核心、换算、显示 // ... endmodule这段是顶层骨架,关键在接口命名和位宽。freq_val 用 32 位是因为最大频率 50MHz 换算成十进制要 8 位,留足余量。nx_cnt、ns_cnt 位宽要能容纳 1s 闸门内 50MHz 的计数,即至少 26 位,取 32 位保险。
4. 核心模块实现:同步闸门、计数与频率换算
4.1 同步闸门生成
同步闸门是整个等精度法的灵魂,写错了精度就无从谈起。思路是用两级寄存器对被测信号打拍,检测上升沿,再用闸门使能信号去控制计数器的启停。
// 被测信号边沿检测与同步闸门 reg sig_d1, sig_d2; always @(posedge clk_50m or negedge rst_n) begin if(!rst_n) begin sig_d1 <= 1'b0; sig_d2 <= 1'b0; end else begin sig_d1 <= sig_in; // 第一级打拍 sig_d2 <= sig_d1; // 第二级打拍 end end wire sig_rise = sig_d1 & ~sig_d2; // 检测上升沿 reg gate_en; // 预设闸门使能,1s高电平 reg gate_act; // 实际闸门,被边沿同步 always @(posedge clk_50m or negedge rst_n) begin if(!rst_n) gate_act <= 1'b0; else if(gate_en && sig_rise) gate_act <= 1'b1; // 闸门开启,对齐被测边沿 else if(!gate_en) gate_act <= 1'b0; // 闸门关闭 end两级打拍是为了消除亚稳态,sig_rise 只在被测信号真实上升沿出现一个时钟周期的高电平。gate_act 的开启严格对齐被测边沿,关闭则跟随 gate_en 拉低,实际闸门时间就是被测周期的整数倍。这里有个细节:关闭时如果也等边沿,逻辑会更严谨,但多数实现里关闭直接跟随预设闸门即可,误差在一个被测周期内,对结果影响可忽略。
4.2 双计数器设计
实际闸门有效期间,两个计数器同时工作:一个数被测信号边沿,一个数标准时钟。
reg [31:0] cnt_sig, cnt_std; always @(posedge clk_50m or negedge rst_n) begin if(!rst_n) begin cnt_sig <= 32'd0; cnt_std <= 32'd0; end else if(gate_act) begin cnt_std <= cnt_std + 1'b1; // 标准时钟计数 if(sig_rise) cnt_sig <= cnt_sig + 1'b1; // 被测边沿计数 end else begin cnt_sig <= 32'd0; // 闸门结束清零,准备下一轮 cnt_std <= 32'd0; end endcnt_std 每个时钟加一,cnt_sig 只在被测上升沿加一。闸门结束时两个值同时有效,下一轮开始前清零。注意清零放在 else 分支,保证闸门关闭后立即复位,不会把上一轮的值带进下一轮。
4.3 频率换算与除法器
Fx = Fs × Nx / Ns,Fs 是 50MHz。直接做乘法再除法,32 位乘 32 位资源消耗大,通常先算 Nx × Fs 再除以 Ns。如果标准时钟就是 50MHz,可以简化成 Fx = 50_000_000 × Nx / Ns。除法用组合逻辑或状态机实现都行,毕设里用状态机逐位除法更稳。
// 简化换算:先乘后除,注意位宽防溢出 wire [63:0] mul_tmp = cnt_sig * 64'd50_000_000; wire [31:0] freq_val = mul_tmp / cnt_std; // 组合除法,综合器会生成除法电路这段是行为级写法,综合器会自动推断除法器。缺点是组合路径长,高频下时序紧张。更稳的做法是写一个时序除法状态机,每个时钟算一位,几十个周期出结果,闸门周期是秒级,完全等得起。参数上,mul_tmp 用 64 位是因为 32 位乘 26 位结果可能超 32 位,位宽不够会静默截断,这是新手最容易翻车的地方之一。
5. 显示与联调:动态扫描、数据拆分与上板验证
5.1 频率值拆成十进制位
频率值要显示在数码管上,得先拆成十进制位。二进制转 BCD 常用「双 dabble」算法或逐位除 10 取余。8 位数码管对应 8 位十进制,逐位取余直观好懂。
// 逐位除10取余,拆出8位十进制 reg [3:0] digit [7:0]; integer i; reg [31:0] tmp; always @(*) begin tmp = freq_val; for(i = 0; i < 8; i = i + 1) begin digit[i] = tmp % 10; // 取最低位 tmp = tmp / 10; // 去掉最低位 end enddigit[0] 是个位,digit[7] 是最高位。组合逻辑里做 8 次除 10,综合出来是一串除法器,资源不小但能接受。想省资源可以改成时序逐位处理,一个时钟出一位。
5.2 动态扫描显示
8 位数码管用动态扫描,一位一位轮流点亮,靠视觉暂留形成稳定显示。扫描时钟一般 1kHz 左右,太快亮度不够,太慢会闪。
reg [15:0] scan_cnt; always @(posedge clk_50m or negedge rst_n) begin if(!rst_n) scan_cnt <= 16'd0; else scan_cnt <= scan_cnt + 1'b1; end wire [2:0] scan_sel = scan_cnt[15:13]; // 约1.5kHz扫描 // 根据scan_sel选择当前位,输出对应段码和位选scan_cnt 高位做位选,低位留给段码译码。段码用查找表把 0~9 映射成七段码,共阴共阳要跟板子对上,接反了显示全是乱码。
5.3 上板联调步骤
联调按「先分模块后整体」的顺序走:先用 SignalTap 抓 cnt_sig 和 cnt_std,确认闸门期间计数正常;再抓 freq_val,看换算结果对不对;最后看数码管。信号源先用信号发生器给已知频率,从 1kHz 到 10MHz 逐档验证,记录读数与标准值的偏差。偏差在理论误差范围内就算通过。
注意:SignalTap 会占用逻辑资源,抓深层信号时可能影响时序,验证完记得关掉再出最终报告。
6. 避坑与常见问题排查:五个最容易翻车的点
6.1 读数在高频段乱跳
现象是低频正常,一上高频读数就大幅波动。原因多半是标准时钟和被测信号没做跨时钟域处理,或者边沿检测只打了一拍,亚稳态导致误计数。解决方法是边沿检测至少两级打拍,跨时钟域信号统一同步后再用。
6.2 换算结果恒为零或溢出
现象是数码管一直显示 0 或者显示一个明显错误的大数。原因是乘法位宽不够,32 位乘 32 位结果被截断,或者除法分母为零。解决方法是乘法结果位宽取两个操作数位宽之和,除法前判断分母非零,闸门刚开启计数值为 0 时跳过换算。
6.3 闸门时间对不上
现象是测出来的频率系统性偏大或偏小一个固定比例。原因是实际闸门没有严格对齐被测边沿,或者预设闸门计数写错了。解决方法是抓 gate_act 的波形,量一下它的高电平时间是不是被测周期的整数倍,预设闸门计数器初值按标准时钟频率算准。
6.4 数码管显示闪烁或重影
现象是显示不稳、有拖影。原因是扫描频率太低,或者位选切换时没有消隐。解决方法是把扫描时钟提到 1kHz 以上,切换位选时先关段选再开下一位,消隐一个时钟周期。
6.5 综合报时序违例
现象是 Quartus 时序分析报 setup/hold 违例。原因是组合除法路径太长,或者逻辑层级太深。解决方法是把组合除法改成时序状态机,插入流水寄存器,或者降低标准时钟频率换取时序余量。
7. 验收与答辩:怎么证明这套频率计真的达标
验收不是「能显示数字」就完事,得拿数据说话。我一般会准备一张测试记录表,从低频到高频取若干测试点,每个点记录标准值、实测值、相对误差,最后算一个全频段最大相对误差。答辩时这张表比任何口头描述都有说服力。
| 测试点 | 标准频率 | 实测频率 | 相对误差 |
|---|---|---|---|
| 低频点 | 100Hz | 记录值 | 计算值 |
| 中频点 | 1MHz | 记录值 | 计算值 |
| 高频点 | 10MHz | 记录值 | 计算值 |
| 边界点 | 50MHz | 记录值 | 计算值 |
测试点要覆盖量程两端和中间,边界点尤其重要,能暴露计数位宽和时序的极限问题。误差计算用 |实测-标准|/标准,等精度方案下各频段误差应该基本一致,如果低频误差明显大于高频,说明同步闸门没做对。
答辩时老师最爱问三个问题:为什么用等精度而不是直接测频、实际闸门时间怎么保证是被测周期整数倍、误差来源有哪些。前两个在方案里已经讲透,误差来源要能说清:量化误差、标准时钟精度、闸门同步误差,其中量化误差在等精度法下只跟标准时钟有关,这是这套方案的核心优势,一定要讲出来。
还有个小技巧:答辩现场如果条件允许,用信号发生器实时改变频率,让老师看着读数跟着变,比放一段录屏可信得多。我吃过一次亏,只准备了静态截图,被追问「换频率准不准」时没法当场证明,后来每次验收都强制自己带信号源现场跑一遍全频段。希望这套方案能帮你少走点弯路,把等精度频率计稳稳当当地做出来、交上去。
本文还有配套的精品资源,点击获取