时钟切换逻辑避免产生glitch的原理
先关闭当前时钟,再打开目标时钟。而不管关闭还是使能,都必须保证当前时钟或目标时钟的使能信号的跳变都分别在时钟为低电平期间进行的,防止产生时钟glitch。
以下为一个例子。
图1 glitch-free clk mux
左边的红色虚线框内,我们来一步步分析:
1)去除4个D触发器之后,本质上是一个RS触发器。如下图:
图2 RS触发器
选用RS触发器的原因有2。其一,可以防抖。以part0_a为例,Sel从1到0的跳变,若仅为非常短的glitch,则可能sel+还来不及从1到0跳变,故sel-也保持为0,从而防止了输出因glitch而抖动。其二,利用反馈,让时钟切换按照安全的顺序,即先关闭当前时钟,再打开目标时钟。而不管关闭还是使能,都必须保证当前时钟或目标时钟的使能信号的跳变都是分别在时钟为低电平期间进行的,防止产生时钟glitch。
2)选择信号同步
因clk0和clk1通常为异步时钟,因此有必要将sel+和sel-进行同步后使用。这就是图1中两条路径上的各两个DFF的第一个DFF的作用。图1中标示了“可增加为两级DFF同步电路”
3)时钟门控
为保证时钟切换时无glitch,最后一步是经同步的选择信号sel+或sel-,再分别进行一次时钟门控。如图1中所标示的“clock gating latch”。
如以上2)所述,最佳的实现电路,如下图:
DFF增加至3级,其中前两级的同步输出,分别作为clk gating cell(ICG)的使能端输入。同步 + clk gating + RS触发器,三种手段实现glitch free时钟切换电路。
综合时对以上时钟切换逻辑的sdc约束:
1) clk0和clk1 可视为 异步时钟,时序分析时可做如下设置
set_clock_groups –asynchronous –name asyn_clk_group \
-group [get_clocks clk0] \
-group [get_clocks clk1]
2) 时钟切换分析
实际的设计,可能无法直接如以上1)中所示设置clk0和clk1为异步时钟关系,比如clk0和clk1是分频时钟的关系,非异步时钟。此时可做以下设置:
Clk0 路径上的的第一个dff 和clk1的第三个dff有一条path。Clk1 的dff3的输出发生变化时,该变化经过clk0上的3个dff同步,所以该路径可设为false path。
Clk1路径上的的第一个dff 和clk0的第三个dff有一条path。
set_false_path -from [get_cells dff13 to [get_cells dff00]
set_false_path -from [get_cells dff03 to [get_cells dff10]
通常整个芯片中,会有较多的该类glitch free clk mux,可使用以下方法将所有相关的path都设置为false path。假设glitch free clk mux的模块名为mux_clk_gfree (因uniquify,综合后netlist中各个mux的例化名会稍有不同,如chip_mux_clk_gfree_0_0, chip_mux_clk_gfree_1_0等。故以下正则表达式中使用了 *mux_clk_gfree*)。
foreach_in_collection a [get_cells –hier * -filter “ref_name=~*mux_clk_gfree*”] {
set name [get_object_name $a]
set_false_path –from [get_cells ${name}/dff13] \
-to [get_cells ${name}/dff00
set_false_path –from [get_cells ${name}/dff03] \
-to [get_cells ${name}/dff10
}