(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/1nsmodule 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;
endfreq_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/1nsmodule 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;
endfreq_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/1nsmodule 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;
endfreq_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)仿真波形: