(1)Verilog代码实现:
module freq_meter_calc
(
input clk ,
input reset_n ,
input clk_test ,
output reg [31:0] freq
);
reg [26:0] cnt0;
reg gata_r;
reg gata_t;
reg [47:0] cnt_clk_test;
reg gata_t_test_reg;
reg [47:0] max_x;
reg [47:0] cnt_clk100M;
reg gata_t_clk100M_reg;
reg [47:0] max_y;
reg [63:0] freq_reg;
wire clk_100M;
wire gata_t_test_nedge;
wire gata_t_clk100M_nedge;
parameter MCNT0 = 27'd74_999_999;
//0.25s = 250_000_000 ns = 20ns * 12_500_000 24位
parameter MCNT1 = 24'd12_499_999;
parameter STAND_MAX = 27'd100_000_000;
pll pll_inst (
.areset ( ~reset_n ),
.inclk0 ( clk ) ,
.c0 ( clk_100M ),
.locked ( )
);
//1.5s的一个计数器 1.5s = 1_500_000_000 ns = 20ns * 75_000_000; 需要一个27位的寄存器
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt0 <= 27'd0;
else if(cnt0 == MCNT0)
cnt0 <= 27'd0;
else
cnt0 <= cnt0 + 27'd1;
//软件闸门设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
gata_r <= 1'd0;
else if((cnt0 > MCNT1) && (cnt0 < MCNT0 - MCNT1))
gata_r <= 1'd1;
else
gata_r <= 1'd0;
//实际闸门设计
always@(posedge clk_test or negedge reset_n)
if(!reset_n)
gata_t <= 1'd0;
else
gata_t <= gata_r;
//实际闸门检测时钟计数模块
always@(posedge clk_test or negedge reset_n)
if(!reset_n)
cnt_clk_test <= 48'd0;
else if(gata_t)
cnt_clk_test <= cnt_clk_test + 48'd1;
else
cnt_clk_test <= 48'd0;
//实际闸门在检测时钟下的下降沿设计
always@(posedge clk_test)
gata_t_test_reg <= gata_t;
assign gata_t_test_nedge = ((gata_t_test_reg) && (!gata_t));
//检测时钟在实际闸门中的周期数设计
always@(posedge clk_test or negedge reset_n)
if(!reset_n)
max_x <= 48'd0;
else if(gata_t_test_nedge)
max_x <= cnt_clk_test;
else
max_x <= max_x;
//标准时钟在实际闸门的周期数计数模块设计
always@(posedge clk_100M or negedge reset_n)
if(!reset_n)
cnt_clk100M <= 48'd0;
else if(gata_t)
cnt_clk100M <= cnt_clk100M + 48'd1;
else
cnt_clk100M <= 48'd0;
//标准时钟在实际闸门下的下降沿设计
always@(posedge clk_100M)
gata_t_clk100M_reg <= gata_t;
assign gata_t_clk100M_nedge = ((gata_t_clk100M_reg) && (!gata_t)) ;
//标准时钟在实际闸门中的周期数设计
always@(posedge clk_100M or negedge reset_n)
if(!reset_n)
max_y <= 48'd0;
else if(gata_t_clk100M_nedge)
max_y <= cnt_clk100M;
else
max_y <= max_y;
//频率输出设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
freq_reg <= 64'd0;
else if(cnt0 == MCNT0)
freq_reg <= (max_x * STAND_MAX) / max_y ;
else
freq_reg <= freq_reg;
always@(posedge clk)
freq <= freq_reg[31:0];
endmodule
(2)仿真文件代码(测试时钟为500MHz):
`timescale 1ns/1ns
module freq_meter_calc_tb;
reg clk ;
reg reset_n ;
reg clk_test ;
wire [31:0]freq ;
initial clk = 1'd1;
always#10 clk = ~clk;
initial clk_test = 1'd1;
always#1 clk_test = ~clk_test;
initial begin
reset_n <= 1'd0;
#15;
reset_n <= 1'd1;
#2_000_000;
$stop;
end
freq_meter_calc freq_meter_calc_inst
(
.clk (clk ) ,
.reset_n (reset_n ) ,
.clk_test (clk_test) ,
.freq (freq)
);
defparam freq_meter_calc_inst.MCNT0 = 27'd74_999;
defparam freq_meter_calc_inst.MCNT1 = 27'd12_499;
endmodule
(3)仿真波形:
(3)仿真文件代码(测试时钟修改为20KHz):
`timescale 1ns/1ns
module freq_meter_calc_tb;
reg clk ;
reg reset_n ;
reg clk_test ;
wire [31:0]freq ;
initial clk = 1'd1;
always#10 clk = ~clk;
initial clk_test = 1'd1;
always#25000 clk_test = ~clk_test;
initial begin
reset_n <= 1'd0;
#15;
reset_n <= 1'd1;
#2_000_000;
$stop;
end
freq_meter_calc freq_meter_calc_inst
(
.clk (clk ) ,
.reset_n (reset_n ) ,
.clk_test (clk_test) ,
.freq (freq)
);
defparam freq_meter_calc_inst.MCNT0 = 27'd74_999;
defparam freq_meter_calc_inst.MCNT1 = 27'd12_499;
endmodule
(4)仿真波形:
(5)仿真文件代码(测试时钟修改为7MHz):
`timescale 1ns/1ns
module freq_meter_calc_tb;
reg clk ;
reg reset_n ;
reg clk_test ;
wire [31:0]freq ;
initial clk = 1'd1;
always#10 clk = ~clk;
initial clk_test = 1'd1;
always#71 clk_test = ~clk_test;
initial begin
reset_n <= 1'd0;
#15;
reset_n <= 1'd1;
#2_000_000;
$stop;
end
freq_meter_calc freq_meter_calc_inst
(
.clk (clk ) ,
.reset_n (reset_n ) ,
.clk_test (clk_test) ,
.freq (freq)
);
defparam freq_meter_calc_inst.MCNT0 = 27'd74_999;
defparam freq_meter_calc_inst.MCNT1 = 27'd12_499;
endmodule
(6)仿真波形: