时钟的不断翻转会产生很大的翻转功耗,因此在某个模块不工作时及时地停下时钟常见的一种低功耗手段。
顾名思义就是为时钟输入增加一个使能en,详情如下
芯片设计进阶之路——门控时钟
6.4 Verilog RTL 级低功耗设计(下)
FPGA设计之门控时钟
门控时钟设计001:什么是门控时钟?如何产生门控时钟?
门控时钟设计002—门控时钟模块使用
门控时钟设计003:门控时钟降低了什么功耗
1. 结构
首先是门控时钟的电路实现
1.1. 与门门控
最简单的就是操作数隔离的方法,将时钟与en信号相与,通过控制en实现时钟门控
如下图
注意只有clk和clk_en同时为高的时候,gclk才输出高,所以如果clk_en时序不合适,会导致高电平的时间比低电平的时间短,甚至是毛刺,那还叫时钟嘛?
如下图
那怎么办?
实际上当clk为低的时候,clk_en可任意变化,gclk都是低。但当clk为高的时候,clk_en必须保持不变,才能保证没有毛刺,那什么东西能让clk_en保持不变呢?锁存器
1.2. Latch门控
电路已经很明显了,在clk为低时锁存器连通、clk为高时锁存器锁住,如下图
波形图如下,可见当clk为低的时候gclk为低没跑,但clk为高的时候,gclk的值可看作是clk上升沿采样的clk_en的值。
所以使用Latch可以有效地锁存clk_en值,同时不影响clk的周期性
其对应的RTL代码也很容易
always@(*) begin
if(clk)
clk_temp = clk_en;
else
clk_temp = clk_en;
end
assign gclk = clk & clk_temp;
clk与Latch的竞争——还是毛刺!
Latch门控时钟的本质是clk上升沿锁住了clk_en值,让clk为高时clk_temp不会翻转,所以消除了毛刺。
而在实际情况下,还记得竞争嘛?竞争的本质是逻辑门的两个输入连接着不同的器件,导致变化的信号到达与门的时刻不一。这里的与门也会存在!不过情况复杂一点。
假如clk现在是0,clk_en刚刚完成0→1,clk_temp还还没来得及变化。现在clk要0→1,从图上看,clk到与门就一根线故clk的1先到与门,然后clk_temp才0→1,这就导致clk占空比降低。
同理1→0的情况,如图
其实这种延迟非常正常,但如果这种延迟中间夹杂个posedge clk那就不好玩了
1.3. 触发器门控
前面提到Latch门控本质就类似于clk上升沿采样clk_en的值,所以干脆将clk低有效的锁存器换成clk上升沿的触发器得了。
波形也很友好啊
clk与触发器的竞争——还是毛刺!
还是那句话,逻辑门两个输入连接的器件不同势必会造成竞争。
加了触发器照样,不过分析容易了一些。
假如clk_temp保持为0,clk_en是1,clk由0变1。还是clk的1先到达与门,但是clk_en的1必须经过触发器才能到达clk_temp,所以也会出现占空比降低的情况出现。
2. RTL实现
那么怎么实现门控时钟呢?一般来说不需要自己写RTL代码实现,因为在综合的时候(如Design Compiler)会自动综合出门控时钟。
例如
但如果将代码改成下面就不会出现门控时钟,这是因为EN非高时,Q不是保持而是被置位,最后还是会被综合成MUX。
always@(posedge CLK)
if(EN)
Q <= D;
else
Q <= 0;
所以说,信号不使用时保持原状态,不仅可以降低翻转功耗,还可以被综合成门控时钟进一步降低功耗。
在设计过程中最多使用set_clock_gating_style
的DC命令实现门控时钟的控制,而且一般来说SoC设计更多的使用的是基于锁存器的门控时钟单元,因为它比触发器更加节省资源