前言
频率计是一种用于测量信号频率的仪器。它可以准确地确定电子信号的频率,广泛应用于电子设备的测试和维护中。频率计的工作原理通常包括对输入信号进行采样,并通过内部电路计算信号的周期,从而得到频率值。现代频率计通常具有高精度、高稳定性,并且能够测量从赫兹(Hz)到千兆赫兹(GHz)范围的频率。
正文
一、频率检测计
1.项目需求
实验目标:设计基于等精度测量法的频率计(误差不大于10ns)测量结果通过数码管进行显示
2.技术介绍
误差不大于10ns,1/(10ns/10^9)=100Mhz,需要完成目标精度需要标准时钟为100Mhz。
常用频率测量法:频率测量法、周期测量法、等精度测量法。
频率测量法:在时间T内对被测时钟信号的时钟周期N进行计数,然后求出单位时间内的时钟周期数,即为被测时钟信号的时钟频率。(在T时间内记N个周期,F= N/T,不能保证周期的整数倍,因而产生一个周期的误差,当T较小时,误差对测量精度影响较大,因此在低频信号测量下误差较大,常用于高频信号测量)
周期测量法:先测量出被测时钟信号的时钟周期T,然后根据频率f=1/T求出被测时钟信号的频率。(不适应高频信号测量 )
等精度测量法:实际闸门Tx于测量信号进行同步,在标准时钟下对实际闸门的Tx进行计算,设置较长的软件闸门或提高标准时钟频率,即可消除频率测量法的误差。
等精度测量法是一种用于提高测量精度的技术,特别适用于高精度测量仪器,如频率计。其基本原理是通过对输入信号进行多次测量,并采用统计方法来减少误差。具体来说,等精度测量法通常包括以下步骤:对同一个信号进行多次独立测量,记录每次测量结果。将多次测量的结果进行统计分析,例如计算平均值、标准偏差等。通过分析测量结果的分布情况,识别和校正系统误差和随机误差。通过对测量数据的处理,可以得到更精确的频率值,并减小由噪声、环境变化等因素引入的误差。
等精度测量法的核心思想是通过多次测量和统计分析来提高测量结果的可靠性和准确性,从而在实际应用中减少测量误差。这种方法在高精度频率测量、信号分析等领域中非常重要。
设置高频率时钟调用ip核进行实验
这里要注意锁相环的复位信号时高电平有效,需要将外接的复位信号进行取反后接入。
3.顶层架构
这里因为数据位宽原因未将数据输出到数码管上,总工程框架如下。
4.端口描述
clk | 基础时钟(50MHZ) |
rst_n | 复位按键(低电平有效) |
[2:0] sel | 位选信号 |
[7:0] seg | 段选信号 |
test_clk | 待测信号 |
二、代码验证
频率测量模块freq_meter
module freq_meter(
input clk ,
input rst_n ,
input clk_test ,
output reg[31:0] data
);
parameter cnt_max = 27'd74999999;//1.5s计数器值
parameter cnt_05 = 27'd12499999;//0.5s计数器值
parameter a100Mhz = 27'd100000000;//100Mhz
reg [26:0] cnt;
reg gate;//软件闸门
reg gata;//实际闸门
reg [47:0] cnt_clk;//高精度计数值
reg test_clk;//寄存被测时钟
reg [47:0] cnt_test;//被测时钟周期计数
reg [47:0] cnt_long;//高频率时钟下周期计数
reg gata_100Mhz;//高频率下对实际闸门进行寄存
reg [47:0] cnt_long_100;//高频率时钟下周期计数寄存
reg cale_flag;//计算使能
wire clk100Mhz;
wire gata_fall;//闸门下降沿检测
wire fall_100Mhz;//高频率闸门下降沿检测
always@(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
cnt <= 27'd0;
else
if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt +1'b1;
end
always@(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
gate <= 1'b0;
else
if((cnt > cnt_05)&&(cnt <= (cnt_max - cnt_05)))//0.5s的软件闸门开启
gate <= 1'b1;
else
gate <= 1'b0;
end
always@(posedge clk_test,negedge rst_n)//使用待测时钟
begin
if(rst_n == 0)
gata <= 1'b0;
else
gata <= gate;//实际闸门
end
always@(posedge clk_test,negedge rst_n)//使用待测时钟
begin
if(rst_n == 0)
cnt_clk <= 48'd0;
else
if(gata == 1'b0)
cnt_clk <= 48'd0;
else
if(gata == 1'b1)
cnt_clk <= cnt_clk + 1'b1;
else
cnt_clk <= cnt_clk;
end
always@(posedge clk_test,negedge rst_n)//使用待测时钟
begin
if(rst_n == 0)
test_clk <= 1'b0;
else
test_clk <= gata;
end
assign gata_fall = ((test_clk == 1'b1)&&(gata == 1'b0))?1'b1:1'b0;
always@(posedge clk_test,negedge rst_n)//使用待测时钟
begin
if(rst_n == 0)
cnt_test <= 48'd0;
else
if(gata_fall == 1'b1)
cnt_test <= cnt_clk;
end
always@(posedge clk100Mhz,negedge rst_n)//使用100Mhz
begin
if(rst_n == 0)
cnt_long <= 48'd0;
else
if(gata == 1'b0)
cnt_long <= 48'd0;
else
if(gata == 1'b1)
cnt_long <= cnt_long + 1'b1;
else
cnt_long <= cnt_long;
end
always@(posedge clk100Mhz,negedge rst_n)//使用100Mhz
begin
if(rst_n == 0)
gata_100Mhz <= 1'd0;
else
gata_100Mhz <= gata;
end
assign fall_100Mhz = ((gata_100Mhz == 1'b1)&&(gata == 1'b0))?1'b1:1'b0;
always@(posedge clk100Mhz,negedge rst_n)//使用100Mhz
begin
if(rst_n == 0)
cnt_long_100 <= 48'd0;
else
if(fall_100Mhz == 1'b1)
cnt_long_100 <= cnt_long;
else
cnt_long_100 <= cnt_long_100;
end
always@(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
cale_flag <= 1'b0;
else
if(cnt == cnt_max)
cale_flag <= 1'b1;
else
cale_flag <= 1'b0;
end
always@(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
data <= 32'd0;
else
if(cale_flag == 1'b1)
data <=(a100Mhz / cnt_long_100 * cnt_test);
else
data <= data;
end
mypll mypll_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( clk100Mhz )
);
endmodule
数码管显示:该模块没有小数点显示,在仿真时未进行数据传入,如需实现数码管显示,对数据进行缩小例如对数据整/1000,再对缩小后的数据进行二进制转bcd,这里要注意数据位宽,不需要显示小数点时最大可显示999999Khz(首先得需要该频率的信号),最小可显示1Khz。
module seg_driver(
input clk,
input rst_n,
input [23:0] data_in,//接收数字时钟信号
output reg [2:0] sel,//位选信号
output reg [7:0] seg//段选信号
);
reg [18:0] cnt;//1MS
parameter MAX = 19'd50_000;
//20ns记50000次
//产生1ms的延时
//位选信号1ms变换一次
reg [3:0] temp;
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
cnt <= 19'd0;
else
if(cnt < MAX - 1)//产生1ms的延时
cnt <= cnt + 19'd1;
else
cnt <= 19'd0;
end
//数码管位选信号控制逻辑
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
sel <= 3'd0;
else
if(cnt == MAX - 1)//位选信号6位,1ms的延时到变化一次
if(sel < 5)
sel <= sel + 3'd1;
else
sel <= 3'd0;
else
sel <= sel;
end
always @(*) begin
if(rst_n == 0)
temp <= 4'd0;
else
case(sel)//位选信号到将数据输出到对应输出位上
3'd0 : temp <= data_in[23:20];
3'd1 : temp <= data_in[19:16];
3'd2 : temp <= data_in[15:12];
3'd3 : temp <= data_in[11:8];
3'd4 : temp <= data_in[7:4];
3'd5 : temp <= data_in[3:0];
default : temp <= 4'd0;
endcase
end
always @(*) begin
if(rst_n == 0)
seg <= 8'hff;
else
case(temp)//段选信号,对应的数码管信号
4'd0 : seg <= 8'b1100_0000;//0
4'd1 : seg <= 8'b1111_1001;//1
4'd2 : seg <= 8'b1010_0100;//2
4'd3 : seg <= 8'b1011_0000;//3
4'd4 : seg <= 8'b1001_1001;//4
4'd5 : seg <= 8'b1001_0010;//5
4'd6 : seg <= 8'b1000_0010;//6
4'd7 : seg <= 8'b1111_1000;//7
4'd8 : seg <= 8'b1000_0000;//8
4'd9 : seg <= 8'b1001_0000;//9
4'd10 : seg <= 8'b1000_1000;//A
4'd11 : seg <= 8'b1000_0011;//b
4'd12 : seg <= 8'b1100_0110;//C
4'd13 : seg <= 8'b1010_0001;//d
4'd14 : seg <= 8'b1000_0110;//E
4'd15 : seg <= 8'b1000_1110;//F
default : seg <= 8'hff;
endcase
end
endmodule
顶层连线
module freq_meter_top(
input clk,
input rst_n,
output [2:0]seg,
output [7:0]sel
);
wire clk_test;
wire[31:0]data;
freq_meter freq_meter(
.clk (clk ) ,
.rst_n (rst_n ),
.clk_test(clk_test),
.data (data )
);
seg_driver seg_driver(
.clk (clk ),
.rst_n (rst_n ),
.data_in ( ),//接收数字时钟信号
.sel (sel ),//位选信号
.seg (seg )//段选信号
);
pll_test pll_test_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( clk_test )
);
endmodule
仿真代码
`timescale 1ns/1ps
module freq_meter_top_tb;
reg clk ;
reg rst_n ;
wire [2:0] seg ;
wire [7:0] sel ;
defparam freq_meter_top.freq_meter.cnt_max = 74;//这里通过赋值减小计数,便于仿真
defparam freq_meter_top.freq_meter.cnt_05 = 12;//这里通过赋值减小计数,便于仿真
freq_meter_top freq_meter_top(
.clk (clk ),
.rst_n(rst_n),
.seg (seg ),
.sel (sel )
);
initial clk =1;
always #10 clk = ~clk;
initial begin
rst_n = 0;
#20
rst_n = 1;
#100000
$stop;
end
endmodule
三、仿真验证
运行仿真文件,在顶层文件中未将数据传至数码管显示文件,这里需要直接调用频率计算模块,通过仿真可看到data的数据为46000000hz
与调用的IP核输出相同,证明实验成功。
a100Mhz / cnt_long_100 * cnt_test=100_000_000/100*46=46_000_000。在高时钟下记100个时钟周期,即1/100_000_000*100s,在这段时间上对被测信号进行计数,记得46个周期,即被测信号频率为46/(1/100_000_000*100)= 46_000_000hz
参考资料
频率计