IC设计中glitch free时钟选择器的设计过程

        芯片设计,包括FPGA程序设计中,都可能出现时钟选择器。在时钟选择器设计中,非常重要的一点就是避免在时钟切换时产生毛刺。

        关于glitch free时钟选择器设计的文章很多,但大多数都是直接给出了几种设计方法,而没有思考过程。本文则记录了自己的这一过程。

1. glitch free时钟选择器的基本结构会是什么样的?

        假设存在两个时钟,clka和clkb,sel为0时clka输出,为1时clkb输出;当前sel为0,clka正在输出。在上述假设下,如果sel切换为1,那么clkb需要输出。

        首先从考虑实现glitch free需要满足什么样的条件。第一,clka的输出需要先被同步关闭;第二,clkb需要在clka同步关闭后,再被同步开启。

        为了满足上述条件,在最简的实现下,clka时钟域至少存在一个寄存器,该寄存器输出clka的时钟控制信号,用于实现clka的同步输出/禁止控制,该寄存器记为q2;同理clkb时钟域也存在这样一个寄存器,记为q4。

        除了clka同步禁止外,禁止和启动顺序也很重要。clka需要先被禁止,然后clkb同步使能。所以,clkb的控制逻辑需要知道何时clka被禁止。为了实现该过程,那么q2的输出一定会被反馈给clkb的控制逻辑,然后送给q4。q2的输出为clka时钟域的信号,当他被送给q4前,需要经由clkb重新进行同步处理。同理,q4到q2之间也存在同样的反馈回路和同步过程。

        基于上述分析,glitch free时钟选择器的最简实现中,至少包含4个寄存器。q2和q4分别产生clka和clkb的同步时钟控制信号。在q2之前还存在q1,在q4之前还存在q3,分别实现对上文提到的反馈信号的同步处理。

        在q1和q2之间还存在简单的组合逻辑,该组合逻辑的输入分别是sel和feedback_b,feedback_b与q4输出相关,也就是与clkb输出状态相关;同理,在q3和q4之间也存在这样的组合逻辑。这两部分组合逻辑的作用是为了实现sel信号对时钟使能/禁止的控制。

2. q1和q2,q3和q4之间的组合逻辑是什么样的?

        q1和q2之间,q3和q4之间的控制逻辑应该是相似的。该组合逻辑有两个输入,以clka时钟为例,应该满足以下条件:

        当sel为1时,clka输出被禁止,feedback_b的值不重要;

        当sel由1切换为0时,组合逻辑输出不会立即发生变化。而是等待feedback_b,当feedback_b也发生变化时,组合逻辑输出才会变化,最终使能clka。

        基于上述思考,可以考虑在q1和q2之间使用“与”逻辑。该“与”逻辑的行为是:当sel为1时,组合逻辑输出立即变化,导致clka最先被同步关闭;当sel由1变为0时,只是满足了“与”逻辑输出值变化的一个条件,需要继续等待feedback_b变化后,输出才会翻转,最终使能clka。

3. 时钟使能/禁止逻辑

        这部分选择的自由度应该比较大。我们就选择使用或逻辑来实现时钟输出的使能和禁止,当时钟被禁止时,输出为常1。clka和clkb的“或”逻辑输出,进行“与”操作后作为最终的时钟输出。如下图。

IC设计中glitch free时钟选择器的设计过程_第1张图片

4. 分析并确定具体的实现逻辑

        当我们确定基本结构和组合逻辑的基本形式后,需要找到一个切入点来确定最终的实现形式。个人认为最好的切入点是sel变化时,被禁止的时钟。因为禁止行为最先发生,使能行为后发生。

        假设sel由0变为1,此时q2的输出需要在下一个clka上升沿后立即变为1,从而实现clka的禁止操作。

IC设计中glitch free时钟选择器的设计过程_第2张图片

         代码如下。

`timescale 1ps / 1ps

module clk_switch (
	input 				clka,
	input 				clkb,
	input 				sel, 	// 0: clka, 1: clkb

	output 				clk_o
);

reg 			ff1, ff2, ff3, ff4;
wire 			clka_inner_src, clkb_inner_src;

always_ff @ (posedge clka) begin
    ff2 <= ~sel & ~ff1;
    ff1 <= ff4;
end 

always_ff @ (posedge clkb) begin
    ff3 <= ff2;
    ff4 <= sel & ~ff3;	
end 

assign clka_inner_src = ~ff2 | clka;
assign clkb_inner_src = ~ff4 | clkb;

assign clk_o = clka_inner_src & clkb_inner_src;

endmodule

        

你可能感兴趣的:(IC设计,IC设计,glitch,free,verilog)