39.简易频率计(基于等精度测量法)(2)

(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)仿真波形:

上一篇:使用 ConfigMaps 优化 Spring Boot 配置管理:环境变量或卷挂载


下一篇:Kafka Producer发送消息流程之Sender发送线程和在途请求缓存区