两种clock gating cell的分析

clock gating应该是最常见也最容易实现的一种节省功耗的方式,有时还能节省面积提升频率。

我们一般会手动在某个模块的clock input后面加入clock gating cell,当系统判定这个模块处于idle状态时,就可以通过配置寄存器的方式把它的clock关掉。这一般是针对模块级或者比较大的逻辑来做的,很多细小的逻辑处则不会再人为干预了。现在的综合工具已经很聪明了,综合的时候工具会自行判断优劣并在合的适的地方插入clock gating cell,还可以分成多个层级进行gating,管理的更加精细。

我也不确定总共有多少种clock gating cell类型,我目前似乎只见过2 种clock gating cell,分别是CKLNQ和CKLHQ,一个是N,一个是H。

它们的接口长下面这样(以TSMC的standard cell为例):


CP和CPN是cell的clock input;

E是enable,TE是test enable,这两者之中的任何一个拉高(置1),都能把gating cell打开,进而能把CP/CPN向后传输至Q端。做design时一般只使用E port,另一个TE port会tie 0,留给DFT使用;

Q端是cell的输出。

对于做了多级clock gating的情况,如果两种gating cell混用,或者是只使用了同一种cell类型,但clock tree没处理好,可能会出现超出预期的结果。

比如,如果第1级用的是CKLNQ cell,上电后(从0ns开始仿真)它处于关断状态,Q端会送出一个always 0的信号。考虑下面2种情况:

case 1:第2级用的是CKLHQ cell(注意,这里是H),上电后它也处于关断状态,并且第1级cell和第2级cell之间的invertor是偶数级(如果tree上全是buffer,则与偶数级的invertor效果一致),此时它的Q端会给出一个还没开始toggle的always 1的clock信号吗?不,事实上是,Q端给出来的是x。

case 2:第2级用的依然是CKLNQ cell,但第1级cell与第2级cell间的clock tree是奇数级invertor,上电后,第2级也是关断状态,它的Q端会给出来一个没开始toggle的always 0的clock信号吗?答案是不会,Q端给出来的也是x。

为什么会出现x呢?这要从2个cell的仿真模型说起了,为了便于描述,就用实际代码来举例吧。

下面是2种cell的4个instance例化:


下面是仿真的波形:


从70ns开始,clk和clk_n开始在0和1之间正常toggle,4个instance的Q端也都正常输出,这之后的波形都比较正常,无须多说。

0ns和30ns处,E/clk/clk_n都是x。4个instance的所有input都是x(TE虽然为0,但它会和E做“或”操作,结果依然是x,效果是一样的),那它们的Q输出都为x也在意料之中了。

我们就重点分析10ns和50ns这2个时刻。

10ns处,E=x,clk=0,clk_n=1。

先比较2个NQ的instance。

下图是CKLNQ的verilog model:


对于nq_inst_0来说,CP=0,第106行的“与”操作决定了Q端的输出一定是0。

对于nq_inst_1来说,CP=1,第106行不能决定Q端的输出了,还需要分析Q_buf的值是什么。

notifier的默认值是x。一般来说,当cell内有timing violation时它会被置0或者置1,正常情况下它会一直保持x值,我们现在是RTL阶段的仿真测试,vcs仿真的option当然会加上+nospecify,不会进入specify block,也无从check timing,当然也不会有timing violation,因此notifier的值会一直为x。

第105行的tsmc_dla是一个primitive原语,对于nq_inst_1,相当于是:

tsmc_dla ( Q_buf, x, 0, 1, 1, x );

tsmc_dla原语的table如下:


table中任意一行都无法匹配,由于All combinations of the inputs that are not explicitly specified will drive the output state to the unknown value x(《IEEE Standard for Verilog Hardware Description Language IEEE Std 1364-2005》的8.2节,第139页),即,当input的组合形式没有在table中明确给出时,output会被置为x。于是,输出结果会被置为x,于是Q_buf为x,进而导致Q也为x,这就是nq_inst_1的Q端为什么会是x的原因。

再来分析HQ的2个instance,下面是CKLHQ的样子:


先看hq_inst_1,它的CPN=1,参考上图的第195行,这是一个“或”操作,于是Q必然为1。

再看hq_inst_0,CPN=0,第195行无法决定Q的值,还需要考虑“或”操作的另一个input才行。

193行的tsmc_dla可以简化为下面这行:

tsmc_dla ( _enl, x, 0, 1, 1, x );

它和前面的nq_inst_1的结果是完全相同的,因此它也会产生一个x输出,经过“取反”,再做“或”,依然是x,于是Q端就也是x了。

先看hq_inst_1,它的CPN=1,参考上图的第195行,这是一个“或”操作,于是Q必然为1。

再看hq_inst_0,CPN=0,第195行无法决定Q的值,还需要考虑“或”操作的另一个input才行。

193行的tsmc_dla可以简化为下面这行:

tsmc_dla ( _enl, x, 0, 1, 1, x );

它和前面的nq_inst_1的结果是完全相同的,因此它也会产生一个x输出,经过“取反”,再做“或”,依然是x,于是Q端就也是x了。

CKLNQ中的N意味着low,一方面代表着开始仿真时clock port需要从low/0开始才能保证它有一个非x值的Q port输出,另一方面代表着在E port disable时,Q port的输出会保持low/0。

CKLHQ中的H意味着high,一方面代表着开始仿真时clock port需要从high/1开始才能有一个非x值的Q port输出,另一方面代表着E port disable时,Q port的输出会保持high/1。

知道了它们为什么会输出x,也就能避开x,让2种gating cell输出非x值:

对于CKLNQ,上电后的CP input要给0,而不能给1。

对于CKLHQ,上电后的CPN input要给1,而不能给0。

这种x值只会出现在仿真中,并且会向后传递。在芯片回来后实际使用时应该是不会出问题的。但仿真时的x总是让人很难受,毕竟,仿真全都pass也不敢说没bug了,但如果仿真fail了,那大概率是有问题的。

把仿真的异常从源头上清理干净,而不是通过review log来决定是否waive掉,不仅能让自己安心,也能提升芯片的成功率,sign off签字时,手也不用抖那么厉害了。

可能会有人想,如果gating cell混用时,就在上电后先把所有gating cell的E port都force成1,让它们全打开,这样是不是就可以避免x的出现了呢?

答案是不行,看下面这个波形图:


上电后E为1。可以看到,只要clk/clk_n未开始toggle(70ns以前),gating cell的Q端就会保持在0/1/x,那么如果级联的2个clock gating cell属于不同种的类型的话,则会面那个gating cell就会继续输出x。

而且,在实际情况中,clock gating cell的E端是不可以乱force的。这是因为工具有可能会把寄存器的赋值条件当作clock gating的enable信号。如下:

always@(posedgeclkornegedgerst_n)beginif(~rst_n)counter<=8'h0;elseif(incr)counter<=counter+1;end

此时,工具就有可能会把if条件做成gating cell的enable信号(这也为什么文章开头说可以提升频率的原因,因为incr信号被从data path上挪到clock path上了,data path逻辑就变少了)。如果冒然把E port force成1,那counter就会开始累加,counter的结果也就错了。

原文链接:https://zhuanlan.zhihu.com/p/558679369

你可能感兴趣的:(两种clock gating cell的分析)