时钟周期检测标志信号

发布于:2024-04-16 ⋅ 阅读:(13) ⋅ 点赞:(0)

在某些情况下需要对系统时钟分频后的时钟进行周期检测,引出周期标志信号以便在后续其他情况的使用。虽然在大多数情况下我们能够知道分频后的时钟是系统时钟的几倍分频,但为增强在分频时钟改变情况下周期标志信号的复用性或对未知时钟的周期检测,可以考虑以下方法或思想,以延申到类似情况下使用。

检测方法

方法一:上升沿判断

将时钟打一拍后取clk&(~clk_reg),上升沿时该值会拉高一个时钟周期。

也可以用下降沿进行判断方法类似。

方法二:时钟移位判断

对时钟左移判断移位后的值,移位后dived_clk_buf==2'd1即为上升沿到来,dived_clk_buf==2'd2即为下降沿到来。

reg  [1:0]      dived_clk_buf    ;

always  @(posedge  clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        dived_clk_buf <= 2'd3;
    else 
        dived_clk_buf <= {dived_clk_buf[0],dived_clk};//移位时钟以判断周期
end

always  @(posedge  clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        XX;
    else if(dived_clk_buf==2'd1)
        XXX;
    else 
         XXXX;
end

实现与仿真

Verilog实现

由两部分组成:产生分频时钟模块+周期检测标志模块;改变分频时钟模块的分频周期可在仿真测试文件中例化时进行参数修改。

产生分频时钟模块:

//========================================================================
// 	Author			:YprgDay
//========================================================================
module dived_clk
#(
	parameter 				DIV_FREQUENCY		=	4				,//分频数(只允许偶分频),dived_clk周期为DIV_FREQUENCY*clk的周期
	parameter 				PERIOD_WIDTH_MAX	=	2				,//(DIV_FREQUENCY-1)对应的二进制位宽
	parameter 				CNT_PERIOD_MAX		=	DIV_FREQUENCY-1	,
	parameter 				CNT_HALF_PERIOD_MAX	=	CNT_PERIOD_MAX >> 1//计数分频中值
)
(
	input 	wire rst_n 	,
	input 	wire clk 	,
	
	output  reg  dived_clk
);

	reg [PERIOD_WIDTH_MAX-1:0] 		cnt_period			;//时钟分频计数
	//分频时钟
	always @(posedge clk or negedge rst_n)begin
		if(rst_n == 1'b0)begin
			dived_clk <= 0;
		end
		else if(cnt_period == CNT_PERIOD_MAX)begin
            dived_clk <= 0;
		end
		else if(cnt_period == CNT_HALF_PERIOD_MAX)begin
			dived_clk <= 1;
		end
		else begin
			dived_clk <= dived_clk;
		end
	end
	//分频计数器
	always @(posedge clk or negedge rst_n)begin
		if(rst_n == 1'b0)begin
			cnt_period <= 0;
		end
		else if(cnt_period == CNT_PERIOD_MAX)begin
			cnt_period <= 0;
		end
		else begin
			cnt_period <= cnt_period + 1'b1;
		end
	end	
endmodule

周期检测标志模块:

//========================================================================
// 	Author			:YprgDay
//========================================================================
module clk_period(
	input 	wire 	rst_n 		,
	input 	wire 	clk 		,
	input 	wire 	dived_clk	,
	output 	wire 	clk_flag1	,
	output 	wire 	clk_flag2
);

	reg 		dived_clk_reg		;
	reg  [1:0]  dived_clk_buf  		;
	//==========================< 方法一 >============================
	always @(posedge clk or negedge rst_n)begin
			if(rst_n == 1'b0)begin
				dived_clk_reg <= 0;
			end
			else begin
				dived_clk_reg <= dived_clk;
			end
		end	
	assign clk_flag1 = dived_clk&(~dived_clk_reg);
	//==========================< 方法二 >============================
	always  @(posedge  clk or negedge rst_n)
		begin
			if(rst_n == 1'b0)
				dived_clk_buf <= 2'd3;
			else 
				dived_clk_buf <= {dived_clk_buf[0],dived_clk};//左移
		end
	assign clk_flag2 = (dived_clk_buf==2'd1);
endmodule

仿真测试

仿真产生系统时钟与复位信号。

//========================================================================
// 	Author			:YprgDay
//========================================================================
`timescale 1ns/1ns
module tb_clk_period();
	
	parameter 				CLK_PERIOD		=	10		    ;//设置时钟信号周期
	parameter 				HALF_CLK_PERIOD	=	CLK_PERIOD/2;//生成时钟信号半周期
	
	reg                     i_rst_n							;
	reg                     i_clk							;
	
	wire					dived_clk						;
	wire					clk_flag1						;
	wire					clk_flag2                       ;
	//==========================< Clock block >============================
	always 	  	#HALF_CLK_PERIOD		i_clk = ~i_clk;
	
	//==========================< i_rst_n block >============================
	 initial begin
		i_clk 	  = 	1'b1	;
		i_rst_n  <= 	1'b0	;

		#40
		i_rst_n  <= 	1'b1	;
	end
	dived_clk 
		#(
			.DIV_FREQUENCY	  (8),//分频数(只允许偶分频),dived_clk周期为DIV_FREQUENCY*clk的周期
			.PERIOD_WIDTH_MAX (3)//(DIV_FREQUENCY-1)对应的二进制位宽
		)
	u_dived_clk
		(
			.rst_n		(i_rst_n	),
			.clk 		(i_clk		),
					
			.dived_clk  (dived_clk	)
		);
	clk_period u_clk_period(
			.rst_n 		(i_rst_n 	),
			.clk 		(i_clk 		),
			.dived_clk	(dived_clk  ),
			.clk_flag1	(clk_flag1	),
			.clk_flag2  (clk_flag2	)
);
endmodule

仿真效果如下:

可以看出方法一的时钟标志信号在时钟上升沿后拉高;方法二的时钟标志信号在时钟上升沿后下一拍拉高。

在这里插入图片描述