功能描述:测量周期信号的频率、占空比、相位差。
首先学习等精度原理,如下图所示。
不难看出,我们需要完成的就是在一个规定的门信号内,分别对待测信号和基准时钟进行计数,最后通过公式即可算出频率。
而这个门是由被测信号产生的,这样就可以消除被测信号的误差,所以误差只有基准信号有,而基准时钟的频率一般都很高。而误差
只与GATE_TIME(门的长度) x CLK_FS 有关,所以等精度测量法无需考虑输入信号的频率。
波形图:
代码
module dengjingdu(
input clk,
input rst,
input clk_25k,
output reg [40:0]data
);
reg [14:0]r_data;
parameter TIME = 27'd75_000_000 - 1; //1.5秒整个门时长
parameter TIME_1 = 27'd12_500_000 - 1; //0.25秒前后低电平的时长
parameter CLK = 26'd50_000_000;
reg [26:0] gate_cnt;
reg gate; //软件闸门
reg gate_t; //同(实际闸门)
reg gate_c; //标准信号下的门(50mhz)
reg gate_t_temp;
reg flag; //计算标志信号
reg [14:0] cnt_clk_25k; //(25k)被测信号在门时钟内的计数值
reg [14:0] cnt_clk_25_temp;
reg [25:0] cnt_clk;
reg [25:0] cnt_clk_temp;
wire gate_t_nege; //下降沿
wire gate_c_nege; //下降沿
always @(posedge clk or negedge rst)
begin
if(!rst)
gate_cnt <= 1'b0;
else if(gate_cnt == TIME )
gate_cnt <= 1'b0;
else
gate_cnt <= gate_cnt + 1'b1;
end
always @(posedge clk or negedge rst)
begin
if(!rst)
gate <= 1'b0;
else if(gate_cnt > TIME_1
&& gate_cnt <(TIME - TIME_1))
gate <= 1'b1; //1秒的高电平
else
gate <= 1'b0;
end
always @(posedge clk_25k or negedge rst) //将门同步到被测信号
begin
if(!rst)
gate_t <= 1'b0;
else
gate_t <= gate;
end
always @(posedge clk_25k or negedge rst) //被测信号下计数
begin
if(!rst)
cnt_clk_25k <= 1'b0;
else if(gate_t <= 1'b0)
cnt_clk_25k <= 1'b0;
else if(gate_t == 1'b1)
cnt_clk_25k <= cnt_clk_25k + 1'b1;
end
always @(posedge clk_25k or negedge rst)
begin
if(!rst)
gate_t_temp <= 1'b0;
else
gate_t_temp <= gate_t;
end
assign gate_t_nege = ((gate_t_temp == 1'b1) && (gate_t == 1'b0)) ? 1'b1 : 1'b0;
always @(posedge clk_25k or negedge rst) //门下降沿将计数值寄存保持
begin
if(!rst)
cnt_clk_25_temp <= 1'b0;
else if (gate_t_nege)
cnt_clk_25_temp <= cnt_clk_25k;
end
always @(posedge clk or negedge rst) //标准信号的计数值
begin
if(!rst)
cnt_clk <= 1'b0;
else if(gate_t == 1'b0)
cnt_clk <= 1'b0;
else if(gate_t == 1'b1)
cnt_clk <= cnt_clk + 1'b1;
end
always @(posedge clk or negedge rst) //打拍取下降沿
begin
if(!rst)
gate_c <= 1'b0;
else
gate_c <= gate_t;
end
assign gate_c_nege = ((gate_c == 1'b1) && (gate_t == 1'b0))
? 1'b1 : 1'b0;
always @(posedge clk or negedge rst)
begin
if(!rst)
cnt_clk_temp <= 1'b0;
else if (gate_c_nege)
cnt_clk_temp <= cnt_clk ;
end
always @(posedge clk or negedge rst)
begin
if(!rst)
flag <= 1'b0;
else if(gate_cnt == TIME )
flag <= 1'b1;
else
flag <= 1'b0;
end
always @(posedge clk or negedge rst)
begin
if(!rst)
data <= 1'b0;
else if(flag == 1'b1)
data <= (cnt_clk_25_temp * CLK);
end
always @(posedge clk or negedge rst)
begin
if(!rst)
r_data <= 1'b0;
else
r_data <= data / cnt_clk_temp;
end
endmodule