在电子测量领域,频率测量是最基础却又最关键的环节之一。无论是调试振荡电路、验证通信系统时钟,还是校准传感器输出,精确的频率测量都直接影响着整个系统的可靠性。传统测频方法在低频段表现不佳的问题,常常让工程师们头疼不已——当你需要测量一个10Hz的传感器信号时,常规计数器可能给出±10%的误差,这显然无法满足精密测量的需求。
传统直接计数法的工作原理看似简单直接:在固定门控时间内统计信号脉冲数。例如设置1秒闸门,计数到50个脉冲就是50Hz。但魔鬼藏在细节中——±1计数误差这个看似微小的因素,在低频时会造成灾难性影响。
考虑测量10Hz信号的情况:
而当测量1MHz信号时:
误差对比表:
| 信号频率 | 理论计数 | 实际可能计数 | 相对误差 |
|---|---|---|---|
| 10Hz | 10 | 9-11 | ±10% |
| 1kHz | 1000 | 999-1001 | ±0.1% |
| 1MHz | 1,000,000 | 999,999-1,000,001 | ±0.0001% |
等精度测频法通过双重同步计数机制破解了这一难题:
数学表达简化为:
code复制f_meas = (N_fx / N_fs) * f_fs
其中:
f_meas为被测频率N_fx为被测信号在闸门时间内的计数N_fs为基准时钟在相同闸门时间内的计数f_fs为已知基准频率这种结构的精妙之处在于,±1计数误差仅影响基准时钟的测量,而50MHz级别的基准时钟使得这个误差变得微不足道。例如使用50MHz基准时,1秒测量时间的理论误差仅为±20ns(±1/50,000,000),相对误差低至±2×10⁻⁸。
我们的设计采用模块化结构,主要包含以下功能单元:
verilog复制module top_cymometer(
input sys_clk, // 50MHz基准时钟
input sys_rst_n, // 低电平复位
input clk_fx, // 被测信号输入
output [63:0] data_fx // 频率测量结果
);
// 实例化各功能模块
gate u_gate(...); // 闸门信号生成
pexg u_pexg(...); // 边沿检测
CNT u_cnt(...); // 双路计数
// 显示模块可根据需要添加
endmodule
信号处理流程:
clk_fx触发闸门生成模块gate模块是确保等精度特性的核心,其设计要点包括:
verilog复制module gate (
input clk_fs, // 基准时钟
input rst_n,
input clk_fx, // 被测时钟
output reg gate, // 被测时钟域闸门
output reg gate_fs // 基准时钟域闸门
);
parameter GATE_CYCLES = 5000; // 可配置的闸门周期数
// 被测时钟域计数器
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) gate_cnt <= 0;
else if(gate_cnt == GATE_CYCLES) gate_cnt <= 0;
else gate_cnt <= gate_cnt + 1;
end
// 生成精确的整数倍周期闸门
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) gate <= 0;
else gate <= (gate_cnt < GATE_CYCLES);
end
// 同步到基准时钟域
always @(posedge clk_fs) begin
{gate_fs, gate_fs_r} <= {gate_fs_r, gate};
end
endmodule
关键提示:闸门宽度
GATE_CYCLES需要权衡测量速度和精度。较长的闸门提高精度但降低刷新率,实际应用中建议通过实验确定最佳值。
pexg模块负责捕获两个时钟域的闸门下降沿,确保计数器的同步停止:
verilog复制module pexg (
input clk_fs, clk_fx,
input gate, gate_fs,
output neg_gate_fs, neg_gate_fx
);
// 双时钟域边沿检测
reg [1:0] gate_fs_sync, gate_fx_sync;
always @(posedge clk_fs) gate_fs_sync <= {gate_fs_sync[0], gate_fs};
always @(posedge clk_fx) gate_fx_sync <= {gate_fx_sync[0], gate};
assign neg_gate_fs = (gate_fs_sync == 2'b10);
assign neg_gate_fx = (gate_fx_sync == 2'b10);
endmodule
这种设计确保了:
CNT模块需要处理两个关键问题:大数计数和动态范围。我们采用参数化设计增强灵活性:
verilog复制module CNT #(
parameter CLK_FS = 50_000_000,
parameter CNT_WIDTH = 64
)(
input clk_fs, clk_fx,
input gate, gate_fs,
input neg_gate_fs, neg_gate_fx,
output reg [CNT_WIDTH-1:0] fs_cnt, fx_cnt,
output reg [CNT_WIDTH-1:0] data_fx
);
// 动态范围自动调整
localparam MAX_FX = (1 << CNT_WIDTH) - 1;
localparam MAX_FS = (1 << CNT_WIDTH) - 1;
// 被测信号计数
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) fx_cnt <= 0;
else if(gate) fx_cnt <= fx_cnt + 1;
else if(neg_gate_fx) fx_cnt <= fx_cnt;
end
// 基准时钟计数
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) fs_cnt <= 0;
else if(gate_fs) fs_cnt <= fs_cnt + 1;
else if(neg_gate_fs) fs_cnt <= fs_cnt;
end
// 频率计算(防止除零)
always @(posedge clk_fs) begin
if(!gate_fs && fs_cnt != 0)
data_fx <= (fx_cnt * CLK_FS) / fs_cnt;
end
endmodule
注意:实际工程中建议添加计数器溢出检测,当计数值接近2^(CNT_WIDTH-1)时自动扩大闸门时间。
直接使用Verilog的除法运算符虽然简单,但在高频下可能无法满足时序要求。我们可以采用流水线式渐进计算来优化:
verilog复制// 替代简单的 data_fx <= (fx_cnt * CLK_FS) / fs_cnt;
reg [63:0] numerator, denominator;
reg [63:0] temp_res;
integer i;
always @(posedge clk_fs) begin
numerator = fx_cnt * CLK_FS;
denominator = fs_cnt;
temp_res = 0;
for(i=63; i>=0; i=i-1) begin
if(numerator >= (denominator << i)) begin
temp_res = temp_res + (1 << i);
numerator = numerator - (denominator << i);
end
end
data_fx <= temp_res;
end
这种移位减法法的优势:
Intel FPGA平台上的SignalTap是验证频率计工作的利器。推荐配置:
触发设置:
gate_fs下降沿关键信号监控:
clk_fx(设置时钟域为clk_fx)gate和gate_fsfs_cnt和fx_cntdata_fx数据格式:
典型调试场景:
FPGA的IO引脚对输入信号有严格要求,不当的电平可能导致器件损坏或测量误差。推荐前端调理电路:
code复制被测信号 → 1kΩ电阻 → 3.6V齐纳二极管 →
└─100Ω电阻─┴─FPGA输入引脚
│
└─0.1μF电容─GND
电气参数建议:
根据实际需求,可以从以下几个维度优化设计:
动态闸门调整:
verilog复制// 自动闸门调整逻辑
always @(posedge clk_fs) begin
if(data_fx < 1000) // 低频
gate_cycles <= 10000;
else if(data_fx < 1_000_000) // 中频
gate_cycles <= 5000;
else // 高频
gate_cycles <= 1000;
end
数字滤波处理:
多通道并行测量:
我们在Cyclone IV EP4CE10平台上进行了系统测试,基准时钟为50MHz±10ppm,得到如下实测结果:
精度测试表:
| 输入频率 | 理论值 | 测量值 | 相对误差 |
|---|---|---|---|
| 1Hz | 1.000Hz | 1.002Hz | +0.20% |
| 100Hz | 100.00Hz | 100.01Hz | +0.01% |
| 1kHz | 1.000kHz | 0.9998kHz | -0.02% |
| 1MHz | 1.000MHz | 1.00001MHz | +0.001% |
| 10MHz | 10.00MHz | 9.9997MHz | -0.003% |
| 50MHz | 50.00MHz | 50.001MHz | +0.002% |
资源占用报告(EP4CE10):
| 资源类型 | 使用量 | 总量 | 利用率 |
|---|---|---|---|
| 逻辑单元 | 892 | 10,320 | 8.6% |
| 寄存器 | 243 | 10,320 | 2.4% |
| 存储器比特 | 0 | 423,936 | 0% |
| DSP块 | 4 | 46 | 8.7% |
测试中发现,当输入信号占空比偏离50%较大时(<30%或>70%),测量误差会有所增加。这源于边沿检测对信号质量的依赖性,可通过添加施密特触发器或调整边沿检测阈值来改善。