、无毛刺时钟切换电路,又叫 Glitch free 电路、时钟无缝切换电路,在笔试中遇到过,如果没有接触过,很可能无从下手。
随着越来越多的多时钟应用于当今的芯片中(尤其是在通信领域),在芯片运行时经常需要切换时钟源。通常的实现方式是:在硬件中复用两个不同频率的时钟源,并通过内部逻辑控制复用器 MUX。
这两个时钟在频率上可能完全不相关,也可能成倍数关系。不管是哪种情况,都有可能在开关门控时产生毛刺(Glitch)。时钟线上的毛刺对整个系统是危险的,因为它可能使用边沿触发了部分寄存器,而其他寄存器却没被触发。
在这篇文章中,使用两种不同的方式来避免输出时钟上有毛刺。第一种方法适用于两个时钟的频率有倍数关系,第二种方法适用于两个无关的时钟。
1. 实时的时钟切换的问题
The problem with on-the-fly clock switching
如图 1 所示为时钟切换的一个简单实现,使用 AND-OR 门组成复用器 MUX。
纯组合逻辑的时钟切换,由于为电平触发,不可避免会产生毛刺;
这个时钟切换复用器有 1 个控制信号 SELECT,当 SELECT = 0 时输出 CLK0,当 SELECT = 1 时输出 CLK1。
当 SELECT 的值发生变化,输出时钟从当前的时钟源切换到下一个时钟源,此时可能会产生毛刺。
如图 1-1 中的时序图所示,当 SELECT 控制信号变化时,在输出 OUT CLOCK 上产生了毛刺。这类门控开关的问题在于,SELECT 开关控制信号会在时钟源的任意电平位置发生变化,从而导致输出时钟截断或者产生毛刺。
SELECT 控制信号很可能是由两个输入时钟源中的某一个去驱动触发器产生的,这意味着如果两个时钟源的频率成倍数关系,那么 SELECT 和两个时钟源有已知的时序关系,否则 SELECT 可能至少和一个时钟源异步。
不管是不是已知多个输入时钟源之间的频率或者相位关系,都不能在这些时钟源的高电平状态下进行切换(任一个高电平都不行,即对图 1,必须在 2 个输入时钟源均为低电平的时候进行切换)。如果两个时钟源有固定的关系,那么可以使用固定延时来减少两个时钟源起始和结束时间的差距。如果输入频率未知或者时钟不相关,则不能使用固定延时。
2. 相关时钟的无缝切换
Glitch protection for related clock sources
如图 2-1 所示为相关时钟源的无毛刺切换解决方法。在每个时钟源的选择路径上,都插入一个下降沿有效的 D 触发器。
(这里为什么是下降沿,参考:门控时钟与控制信号电平、与门门控、或门门控、上升沿门控、下降沿门控)
在时钟的每个下降沿寄存选择控制信号 SELECT,并且只有在其他时钟的选择被释放后(无效后)才会使能新的时钟选择,这样对输出毛刺问题进行很好的解决。
在时钟的下降沿处寄存选择控制信号,保证了控制信号不会在 2 个时钟源的高电平处进行跳变,这样就防止对输出时钟进行截断(截断导致毛刺)。
一个时钟的选择反馈到了另一个时钟(两个 QN,即~Q),这种反馈机制使得门控开关在选择输出下一个时钟之前,必须先取消当前时钟的输出选择,这样避免了任何可能出现的毛刺 Glitch。
假设此时 SELECT 在适中的高电平处进行了跳变,由于与门作用,需要等待其另一个时钟触发的寄存器输出 QN 也变化为 1 时,与门的结果 SELECT-1 才会变化,而 QN 的变化需要等待到时钟的下降沿才会变化,所以经过处理后的 SELECT-1 信号的跳变只发生在时钟的低电平处。
如图 2-2 的时序图所示为 SELECT 选择信号从 0 到 1 变化时是如何影响的输出 OUT CLOCK 的波形。首先在 CLK0 的下降沿停止 CLK0 在 OUT CLOCK 上的输出,然后在紧接着的 CLK1 的下降沿开始输出 CLK1。
module glitch_2 (
input clk0,
input clk1,
input select,
input rst_n,
output clkout
);
reg out1;
reg out0;
always @(negedge clk1 or negedge rst_n)begin
if(rst_n == 1'b0)begin
out1 <= 0;
end
else begin
out1 <= ~out0 & select;
end
end
always @(negedge clk0 or negedge rst_n)begin
if(rst_n == 1'b0)begin
out0 <= 0;
end
else begin
out0 <= ~select & ~out1;
end
end
assign clkout = (out1 & clk1) | (out0 & clk0);
endmodule
分析:
1、当select=0时,F1的输出一直都是0,因此输出受F0和clk0影响,而F0的输入端始终为1,因此输出只受clk0影响,且同相;
2、当select=1时,输出受F1影响,但是由于之前F0有一段时间为1,只有在clk0下降沿才会读入输入0,此时输出保持之前状态,当clk1下降沿来之后,开始随clk1同相;那么在clk0下降沿来之后,clk1下降沿来之前的输出,输出由谁决定呢?
3、clk0的停止位置下降沿来之后,或门的下输入为0,而之前时刻的clk1的输出一直为0,所以输出还是为0;当clk1时钟下降沿来之后,才知道seelct变为1,以后输出就按照clk1变化了
在这个电路中有 3 条时序路径需要特别考虑:
(1)SELECT 控制信号到任意一个下降沿有效的触发器 ;
(2)DFF0 的输出到 DFF1 的输入;
(3)DFF1 的输出到 DFF0 的输入。
如果这三条路径中的任一路径上的信号在目的寄存器时钟的捕获沿时发生变化,则寄存器的输出有一定的机会会进入亚稳态(meta-stable),这意味着会进入理想的 0 和 1 之间的一个状态。(在此例中,捕获沿均为下降沿)。
亚稳态经过一段时间后会 随机的 稳定为 0 或者 1,这就导致两个寄存器可能采集到不同的值(一个认为是 0,而另一个认为是 1)。因此,这就要求两个寄存器捕获沿和 对 SELECT 信号的发起沿分开,以避免任何可能的异步接口。由于两个时钟源的时序关系是已知的,所以上述可以通过使用恰当的多周期约束(multi-cylce hold)或者最小延时(minimun delay)约束来实现。
在芯片的启动时,DFF0 和 DFF1 两个寄存器都应该复位为“0”状态,这样在最开始时,两个时钟都没有被选中输出。通过在“0”状态下起点两个触发器,时钟开关内置了容错功能。
假定在启动时有个错误导致其中一个时钟没有进行翻转。如果使用这个错误时钟的触发器的初始状态是“1”状态,而此时这个触发器由于没有时钟的翻转边沿触发,所以导致该寄存器的输出状态不变,这就阻止了对另一个时钟的选择。通过让两个寄存器都以“0”状态开始,那么即使有一个时钟没能正常的工作,另一个正常的时钟也能通过门控输出。
3. 不相关时钟的无缝切换
Glitch protection for unrelated clock sources
在前一种避免输出毛刺的门控选择方式中,要求两个输入时钟源的频率有倍数关系,这样使用者可以(通过使用恰当的时序约束)避免信号与任何一个时钟域异步。这种实现方式没有处理异步信号的机制。
这样,提出第二种实现方式,使用同步电路来避免异步信号带来的潜在的亚稳态风险。当两个时钟源完全不相关时,异步行为可能来自 SELECT,也可能来自另一个时钟域的异步的反馈信号。
如图 3-1 所示,对每个时钟源路径上,各增加一个该时钟源上升沿驱动的触发器来避免亚稳态。时钟源路径上增加的上升沿有效的触发器,与现有的下降沿有效的触发器一起,用于减少 SELECT 或者异步反馈信号导致的潜在的亚稳态的概率。
使用简单的两级寄存器搭建的同步器,第一级的寄存器通过锁存数据来稳定数据,然后将稳定后的数据传输到第二级的触发器,由电路中的其他部分来解释。
电路功能:两个异步时钟源切换电路;
DFF1和DFF3作用(每条路是前两个触发器):在选择路径插入一个上升沿触发器,用于缓存数据,将数据传递给下一级;若去掉,会电路产生由异步信号引起的亚稳态;
DFF2和DFF4采用负沿采用原因(每条路上的后两个触发器):SELECT与反馈输出相与,下降沿采样反馈可以保证一个时钟被完全取消选择后,输出才输出另一个时钟,从而避免产生毛刺。
module glitch_DFF (
input clk0,
input clk1,
input select,
input rst_n,
output clkout
);
wire B;
reg DFF3Q, DFF4Q, DFF4_Q; //DFF4Q=Q,DFF4_Q=~Q
wire A;
reg DFF1Q, DFF2Q, DFF2_Q; //DFF2Q=Q,DFF2_Q=~Q
assign A = select & DFF4_Q;
assign B = ~select & DFF2_Q;
//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk1 or negedge rst_n) begin
if(~rst_n)
DFF1Q <= 0;
else
DFF1Q <= A;
end
//第二级触发器用下降沿采样
always@(negedge clk1 or negedge rst_n) begin
if(~rst_n) begin
DFF2Q <= 0;
DFF2_Q <= 1;
end
else begin
DFF2Q <= DFF1Q;
DFF2_Q <= ~DFF1Q;
end
end
//====================================================================
//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk0 or negedge rst_n) begin
if(~rst_n)
DFF3Q <= 0;
else
DFF3Q <= B;
end
//第二级触发器用下降沿采样
always@(negedge clk0 or negedge rst_n) begin
if(~rst_n) begin
DFF4Q <= 0;
DFF4_Q <= 1;
end
else begin
DFF4Q <= DFF3Q;
DFF4_Q <= ~DFF3Q;
end
end
wire E, F;
assign E = clk1 & DFF2Q;
assign F = clk0 & DFF4Q;
assign clkout = E | F;
endmodule
4. 结论
Conclusion
通过本文介绍的技术,可以避免时钟切换时产生的毛刺,而且开销很小。这些技术是完全可以进行扩展的,能用在多个时钟的切换上。对于多个时钟源,每个时钟的选择信号来源与其他所有时钟源的反馈。