上一篇简单描述了时序逻辑与组合逻辑电路的区别、建模,其中提到了时序逻辑电路是由时钟驱动的,那么时钟根据不同的相位关系可以分为同步时钟和异步时钟,工作在同步时钟的电路称为同步电路,工作在异步时钟的电路称为异步电路。
同步时钟与异步时钟
那么先区分一下同步时钟和异步时钟,两个时钟是同步还是异步其实跟频率无关,而是跟相位强相关,换句话说就是同步时钟一定是同相的,但不一定同频,异步时钟相位一定是不同的,频率可以是相同的。举个例子,一个1G的ahb时钟经过计数器分频得到一个500M的apb时钟,那么ahb时钟和apb时钟频率是不同的,但是如果都是在上升沿采样则是同步时钟;相反地,两个毫无关系同样是1G的时钟不一定就是同步时钟,因为他们之间相位关系不确定。
setup与hold
而这篇要讨论的主题是静态时序分析-STA,STA分析的就是同步电路,因为异步电路不具备相位关系,所以没法进行分析,这种情况需要做特殊处理,会单独开一篇文章详细描述各种情况下的异步处理。STA分析的基本原理则是同步时序电路中的建立时间(setup time)和保持时间(hold time),而这也是数字电路的核心之一。建立时间是指在时钟上升沿采样之前数据必须稳定的最小时间,保持时间是指在时钟沿采样之后数据必须稳定的时间,时钟沿只有在这个安全窗口内采样数据才不会出错,否则就会出现亚稳态,而且亚稳态会往后面的电路传播,导致不可预期的错误。这两个时间参数是standcell的固有属性,由fundry厂的工艺决定的,一般来说工艺越先进这两个时间值越小,意味着留给designer的裕量更多,有更多的机会跑更高的频率;同时意味着同样的设计电路可能在6nm工艺下没有问题,但是在28nm工艺下却会有问题(相同时钟频率)。
STA的目的就是保证所有的同步时序电路中数据在T1~T2时间内保持稳定不能动,换句话说就是data1不能来得太晚,晚于T1则会导致建立时间违例(setup timing violation);data1也不能走得太早,否则会导致保持时间违例(hold timing violation)。所以需要DATA“早来晚走”,但是DATA产生的电路是固定的,意味着latency是固定在一个范围的,那再从DATA的视角来画个时序图看看应该就是这样:
DATA从DFF1的CP->Q经过组合逻辑到达DFF2的D端不能太快,不能早于T1,也就是说中间这团组合逻辑不能太短,否则会造成hold timing violation,如果设计电路确实中间组合逻辑就是没啥东西,这种可能就需要后端来做一些操作,比如插buffer、反相器对、甚至调一下位置拉长DFF1和DFF2的物理距离(比较少见)或者干脆换DFF器件 ,但是这些操作都是有代价的,比如增大面积;也不能太晚以至晚于T2,也就是说中间组合逻辑不能太长,否则就是setup timing violation,这也是前端设计实现硬件电路最需要考虑的问题,一旦出现这种问题一般是采用插拍(pipeline)的方式,也就是再经过一级触发器再送到DFF2,这样很长的这个组合逻辑就可以被拆分到两段时序中(所以写RTL的时候如果没把握时序有没有问题最好能加个插拍的参数或者宏来方便修改),同时要注意这条路插拍了还能否与此逻辑相关的逻辑对齐,这也是最麻烦的地方;还有一种方法是降低时钟频率,但这样有违设计spec,除非是流片回来没有其他办法了可以想办法降频试试。要注意hold time与时钟频率无关的,从上图来看就是第二个时钟上升沿来得早与否与hold time无关。
这些时序分析会在综合工具DC或者STA中进行,而如何让这些工具知道我们的设计是工作在什么时钟频率下,有哪些注意事项,这就是我们设计工程师需要写的SDC,这个常用的一些语法用例后面单独开一篇文章记录,这也是非常关键的基本功,SDC写得有问题很可能流片回来变砖头。
STA计算
上面都是比较概念性、抽象的介绍,接下来就实际计算一下就能更明白静态时序分析的具体内容。
建立时间计算
如下图所示:
T1:时钟源到DFF1的路径delay,时钟周期为T;
T2:时钟源到DFF2的路径delay,时钟周期为T;
Tc2q:时钟到数据输出的delay;
Tcom:组合路径delay;
Tsup:setup时间要求;
Thld:hold时间要求;
那么数据实际从时钟到达DFF2的时间Tar = T1 + Tc2q + Tcom;
由于建立时间要求数据最晚到达时间Treq = T2 + T - Tsup;
为了不发生时序违例,则需要数据在最晚达到时间之前到,即:
Tar < Treq
==> T1 + Tc2q + Tcom < T2 + T - Tsup
==> Tcom < T + T2 - T1 - Tc2q - Tsup
其中T2和T1的大小其实并不确定(skew),和时钟树的走线相关,所以按照悲观的算法来看可以认为T1>T2,另外时钟本身可能在传输中出现jitter(周期或者占空比发生变化),把这二者都算成uncertainty time :Tunce,于是得到:
Tcom < T - Tunce - Tc2q - Tsup;
因此对于建立时间要求来讲组合逻辑delay越小越友好。
换种说法,假设建立时间裕量为Tsup_margin,该时间表示数据在Treq之前多久到,则要求裕量越大越好:
Tsup_margin = Treq - Tar
= T2 + T - Tsup - T1 - Tc2q - Tcom
= T - Tunce - Tc2q - Tcom
同样也可以看出要求Tcom越小越好。
保持时间计算
如下图所示:
这里数据实际从时钟到达DFF2的时间也是Tar = T1 + Tc2q + Tcom;
而由于保持时间要求数据最早到达时间Treq = T2 + Thld;
保持时间要求数据需要比最早到达时间晚到,所以需要:
Tar > Treq
==> T1 + Tc2q + Tcom > T2 + Thld
==> Tcom > T2 - T1 - Tc2q + Thld
同理也是按悲观的算法(在实际的同一条路径分析中其实具体T1和T2的大小关系是确定的,不可能两个的计算都按最悲观的来)来看则:Tcom > Thld - Tc2q + Tunce
假设保持时间裕量为Thld_margin,该时间表示数据在Treq之后多久到,同样要求裕量越大越好:
Tsup_margin = Tar - Treq
= T1 + Tc2q + Tcom - T2 - Thld
= Tc2q + Tcom - Tunce - Thld
可以看出来保持时间要求Tcom越大越好,不能太小,否则会导致保持时间违例,所以如果出现保持时间违例则需要增加中间组合逻辑的delay,一般是后端手动插一些buffer来增加Tcom,前端设计的时候不需要考虑hold time检查。