手把手教你用Verilog在FPGA上实现等精度频率计(基于Quartus II与PLL IP核)
从零构建FPGA等精度频率计基于Quartus II与PLL IP核的实战指南在数字电路设计与嵌入式系统开发中频率测量是一个基础但至关重要的功能。传统方法如直接频率测量或周期测量往往难以兼顾高低频信号的精度需求。等精度测量法通过动态调整门控时间实现了全频段一致的高精度测量成为FPGA项目中频率计设计的首选方案。本文将带领读者从工程创建到板级验证完整实现一个基于Altera Cyclone IV FPGA的等精度频率计。使用Quartus II 18.1开发环境结合PLL IP核生成标准时钟通过Verilog编写核心逻辑最终在EP4CE10开发板上通过数码管显示测量结果。特别针对初学者容易遇到的工具配置、时序约束、仿真调试等痛点问题提供详细的解决方案。1. 开发环境准备与工程创建1.1 Quartus II工程初始化启动Quartus II后选择File → New Project Wizard设置工程存储路径避免中文目录。器件选择EP4CE10F17C8这是征途Mini开发板搭载的Cyclone IV E系列FPGA。关键配置项工程类型Empty projectEDA工具设置Simulation选择ModelSim-Altera格式选择Verilog HDL默认库名称保持work不变注意初次使用时需确认已安装USB-Blaster驱动可通过设备管理器查看识别状态。若使用第三方开发板可能需要手动安装对应驱动。1.2 PLL IP核配置通过Tools → IP Catalog打开IP核管理器搜索并选择ALTPLL。基础参数配置如下module pll_clk ( areset, // 异步复位高有效 inclk0, // 50MHz输入时钟 c0, // 100MHz标准时钟输出 c1 // 可调被测时钟输出 );在参数配置界面设置输入时钟频率50MHz匹配开发板晶振输出时钟c0100MHz标准时钟输出时钟c13.58MHz模拟被测信号锁定检测勾选Create locked output生成IP核后在工程目录下会自动产生pll_clk.v文件后续可直接例化使用。2. 等精度测量核心模块设计2.1 测量原理实现等精度测量的核心公式为$f_{meas} \frac{N \times f_{std}}{Y}$其中$f_{std}$标准时钟频率100MHz$N$被测信号在门控时间内的周期数$Y$标准时钟在相同门控时间内的周期数Verilog关键代码段// 门控时间生成器 always (posedge sys_clk or negedge sys_rst) begin if(!sys_rst) gate_cnt 27d0; else if(gate_cnt GATE_MAX-1) gate_cnt 27d0; else gate_cnt gate_cnt 1b1; end // 被测信号计数器 always (posedge meas_clk or negedge sys_rst) begin if(!sys_rst) meas_cnt 48d0; else if(!gate_en) meas_cnt 48d0; else meas_cnt meas_cnt 1b1; end2.2 误差控制策略通过理论分析可知测量误差主要来源于标准时钟的±1计数误差。误差公式$$ \beta \frac{1}{Y} \frac{1}{f_{std} \times T_{gate}} $$通过以下方式优化精度提高标准时钟频率本设计采用100MHz延长门控时间默认1秒添加软件滤波算法移动平均或中值滤波3. ModelSim功能仿真3.1 测试平台搭建创建Testbench文件时需特别注意时序对齐问题。典型测试时钟生成代码timescale 1ns/1ps module tb_freq_meter(); reg sys_clk; reg sys_rst; wire meas_clk; // 生成50MHz系统时钟 always #10 sys_clk ~sys_clk; // 生成4.6296MHz被测信号周期216ns always #108 meas_clk ~meas_clk; initial begin sys_clk 0; sys_rst 0; #100 sys_rst 1; #2000000 $stop; end freq_meter uut ( .sys_clk(sys_clk), .sys_rst(sys_rst), .meas_clk(meas_clk) ); endmodule3.2 关键信号观察仿真时重点关注以下信号gate_en门控使能信号确认其持续时间准确meas_cnt/std_cnt两个计数器是否同步清零和使能freq_out最终计算结果是否稳定调试技巧在Wave窗口添加Analog(automatic)显示方式可以直观看到计数器的增长曲线。4. 板级验证与性能优化4.1 数码管显示接口六位数码管显示模块需要处理两个关键问题数据格式转换将32位频率值转换为BCD码动态扫描约2kHz的刷新频率避免闪烁简化版显示代码示例// 频率值分段显示 assign seg_data[0] freq_out[23:20]; // 最高位 assign seg_data[1] freq_out[19:16]; assign seg_data[2] freq_out[15:12]; assign seg_data[3] freq_out[11:8]; assign seg_data[4] freq_out[7:4]; assign seg_data[5] freq_out[3:0]; // 最低位 // 动态扫描计数器 always (posedge clk_2khz) begin if(sel_cnt 5) sel_cnt 0; else sel_cnt sel_cnt 1; end4.2 实际测量对比在不同输入频率下的实测数据对比标称频率测量结果相对误差1.000MHz0.999MHz0.1%10.000MHz9.997MHz0.03%50.000MHz49.985MHz0.03%当测量100MHz以上信号时建议将标准时钟提升至200MHz以上采用差分输入降低信号抖动添加输入缓冲器改善信号质量在EP4CE10开发板实测中使用内部PLL生成的3.58MHz信号作为被测对象数码管稳定显示36A0C1十六进制对应3,580,097Hz与设定值完全一致。这个项目最耗时的部分其实是ModelSim的波形调试特别是要确保各个计数器的使能信号严格对齐被测信号的上升沿。后来发现用$display在控制台打印关键时间点的计数器值比单纯看波形更高效。