第三章的之前部分见链接文章
目录
代码的部分解释
3.5 状态依赖模型
3.6 黑盒接口时序模型
3.7 高级时序模型
3.7.1 接收引脚电容
3.7.2 输出电流
3.7.3 针对于串扰噪声分析的模型
3.7.4 其他噪声模型
3.8 功耗建模
3.8.1 动态功耗
3.8.2 漏电功耗
3.9 单元库中的其他属性
3.10 特征以及工作条件
3.10.1 降额使用的K系数
3.10.2 库的单位
代码的部分解释
在之前的代码部分,可能有些迷惑,有关于timing_type, timing_sense。参考博客:静态时序分析 第二章 基础知识
组合逻辑时序弧
时序弧类型信息:timing_type : combinational ;用于指定时序弧是组合逻辑,没有特别声明的都是组合逻辑时序弧。(也就是说这语句,可以不写)
三种时序弧需要在时序信息文件中通过定义相关PIN和逻辑状态信息进行声明:
timing_sense:positive_unate #同向时序弧
timing_sense:negative_unate #反向时序弧
timing_sense:non_unate #不定态时序弧
边沿时序弧
表示时序单元从时钟信号有效沿到输出信号有效的延时信息。
timing_sense:falling_edge #下降沿有效
timing_sense:rising_edge #上升沿有效
建立时序弧
表示时钟的有效边沿到来之前,数据输入信号保持有效的时间信息。根据时钟信号有效沿不同,分为上升和下降两种,通过时序弧类型信息setup_falling和setup_rising进行声明。
timing_sense:setup_falling #下降沿有效
timing_sense:setup_rising #上升沿有效
保持时序弧
表示时钟有效沿到来之后,数据输入信号维持有效的时间信息。根据时钟信号有效沿不同,分为上升沿有效和下降沿有效两种,通过时序弧类型信息hold_falling和hold_rising进行声明。
timing_sense:hold_falling #下降沿有效
timing_sense:hold_rising #上升沿有效
恢复时序弧
表示在时钟有效沿前使能信号保持有效的时间信息。根据时钟信号有效沿不同,分为上升沿有效和下降沿有效两种,通过时序弧类型信息recovery_rising和recovery_falling进行声明。
timing_sense:recovery_falling #下降沿有效
timing_sense:recovery_rising #上升沿有效
移除(撤销)时序弧
在时钟沿有效后使能信号保持有效的时间信息。根据时钟信号有效沿不同,分为上升沿有效和下降沿有效两种,通过时序弧类型信息removal_rising和removal_falling进行声明。
timing_sense:removal_falling #下降沿有效
timing_sense:removal_rising #上升沿有效
脉冲宽度时序弧
用来表示时钟信号同一状态下维持有效的最小总时间信息。根据信号有效状态的不同,分为高电平有效和低电平有效两种,通过时序弧类型信息min_pulse_width进行声明。
timing_sense:min_pulse_width
3.5 状态依赖模型
很多的时序弧都是依靠别的引脚上的电平状态的,比如之前提到过的异或门,同或门。在3.5中描述了很多状态依赖模型。
同或异或以及其他时序逻辑元件
对于2输入异或门而言,考虑A1输入到Z输出的时序弧。若A2的值为0,则为正单调时序弧;若A2的值为1,则为负单调时序弧。这两种时序模型,我们用状态依赖模型来描述。
pin (Z) {
direction : output;
max_capacitance : 0.0842;
function : "(A1^A2)";
timing() {
related_pin : "A1";
when : "!A2";
sdf_cond : "A2 == 1'b0";
timing_sense : positive_unate;
cell_rise(delay_template_3x3) {
index_1 ("0.0272, 0.0576, 0.1184"); /* Input slew */
index_2 ("0.0102, 0.0208, 0.0419"); /* Output load */
values( \
"0.0581, 0.0898, 0.2791", \
"0.0913, 0.1545, 0.2806", \
"0.0461, 0.0626, 0.2838");
}
. . .
}
在这里虽然节选的片段虽然只展示了cell_rise的延时,但是其他模型如 cell_fall, rise_transition和 fall_transition的表也是用when条件语句来指定的
timing() {
related_pin : "A1";
when : "A2";
sdf_cond : "A2 == 1'b1";
timing_sense : negative_unate;
cell_fall(delay_template_3x3) {
index_1 ("0.0272, 0.0576, 0.1184");
index_2 ("0.0102, 0.0208, 0.0419");
values( \
"0.0784, 0.1019, 0.2269", \
"0.0943, 0.1177, 0.2428", \
"0.0997, 0.1796, 0.2620");
}
. . .
}
sdf_cond 用来指定生成SDF文件时要使用的时序弧的条件 (SDF文件的介绍)
状态依赖模型被用于多种时序弧,许多时序逻辑单元使用状态依赖模型来指定建立时间或者是保持时间的约束。
pin (D) {
. . .
timing() {
related_pin : "CK";
timing_type : hold_rising;
when : "!SE";
fall_constraint(hold_template_3x3) {
index_1("0.08573, 0.2057, 0.3926");
index_2("0.08573, 0.2057, 0.3926");
values("-0.05018, -0.02966, -0.00919",\
"-0.0703, -0.05008, -0.0091",\
"-0.1407, -0.1206, -0.1096");
}
. . .
}
}
在上面的例子中,用到了扫描触发器。它是状态依赖的时序模型进行保持时间约束的一个实例。
扫描触发器的基本功能:
- 当SE(scan enable)引脚被激活(例如设为高电平)时,扫描触发器会接收外部测试信号,并通过串行输入(Scan In)将数据加载到触发器中。这使得测试设备能够顺序访问多个触发器的状态。
- 在此模式下,触发器的正常输入(例如D输入)被禁用,外部测试数据取而代之。
有些时序关系同时用状态依赖时序模型和非状态依赖时序模型来指定。时序分析会使用状态依赖时序模型,前提是元件的状态现在已知,并且包含在一种状态依赖时序模型中。如果元件的状态不包含在状态依赖的时序模型中,就会使用非状态依赖的时序模型。
例如,考虑保持时间约束只由一个SE引脚为逻辑0的条件指定,而没有为逻辑1的独立时序模型的情况。在该场景下,如果SE引脚置为1,此时便使用状态无关时序模型。如果此时状态无关时序模型并没有指定,就意味着没有任何有效保持时间约束。
可以为时序库中的任何属性指定时序依赖模型,可以指定功率,漏电功率,过渡时间,上升下降延时等等一些属性。下面是例子。
leakage_power() {
when : "A1 !A2";
value : 259.8;
}
leakage_power() {
when : "A1 A2";
value : 282.7;
}
3.6 黑盒接口时序模型
主要讲黑盒的IO接口的时序弧,这个模型可以捕获黑盒的IO接口的时序,这个模型既可以有时序逻辑的时序弧,也可以有组合逻辑的时序弧,这些时序弧也可以是状态依赖的。
对于上图的例子,可以把时序弧分为下面几类:
- 输入到输出的组合逻辑时序弧:是输入到输出的组合逻辑路径。
- 输入时序逻辑时序弧:对应于连接到触发器D引脚的输入端口的建立时间或保持时间。通常在模块的输入端口连接到FF的D输入端口之前还会存在一些组合逻辑,在这里就可以进行建立时间检查。
- 异步输入时序弧:这个与恢复时间约束和移除时间约束有些相似。对应的例子就是ARST连接到FF的异步清零端口输入。
- 输出时序逻辑时序弧:与时钟到触发器的输出引脚Q的输出相似。在FF的输出端口和黑盒的输出端口之间存在组合逻辑。
总的来说,一个黑盒可以存在以下的时序弧:
- 从输入到输出的组合逻辑路径
- 从同步输入到有关的时钟引脚的建立时间、保持时间时序弧
- 从异步输入引脚到有关的时钟引脚的恢复时间、移除时间时序弧
- 从时钟引脚到输出引脚的传播延时时序弧
如上所述的接口时序模型只捕捉在接口上的时序,不关心内部的时序。
3.7 高级时序模型
如NLDM的时序模型,用输出负载电容以及输入过渡时间来表征时序弧的延时。实际上,单元的输出看到的负载不止有电容,还有互联电阻(interconnect resistance),这是个问题,应为我们之前都一直假设NLDM模型的输入负载是纯电容。如果互连电阻较小,我们依然可以使用NLDM的模型。不得不考虑电阻时,我们要改进NLDM,方法是在输出端获得等效的有效电容(effective capacitance).在延迟计算工具中使用“有效”电容方法获得等效电容,在单元输出端具有与RC互连单元相同的延迟。
尺寸缩小导致互连电阻的影响变得很大,造成很大的不精确,因为波形变得高度非线性。各种不同的建模方法为单元的输出驱动,提供了更高的精度。这些方法使用等效电流源对单元的输出级进行建模。
如CCS(composite current source)时序模型,它使用随时间变化且依赖电压的电流源。时序信息由指定模型在不同场景下的接受引脚电容(receiver pin capacitance)和输出充电电流(output current)来提供。下面介绍。
3.7.1 接收引脚电容
接收引脚电容指的就是NLDM模型中输入引脚的电容值,在NLDM模型中这个电容值是固定的。不同于NLDM模型,CCS模型允许在过渡波形信号的不同部分指定不同的电容值。电容值不是单一的,可以根据信号的状态进行变化(由于内部互连以及由米勒效应引起的等效的非线性电容)。
类似于NLDM模型,CSS模型也可以在引脚级别上直接指定电容,所有经过这个引脚的时序弧都要用到这个电容值。也可以在时序弧级别上指定,这样对于不同的时序弧,就可以指定不同的电容模型,这两种方法将会在下面介绍。
引脚级别
一个一维表模型的例子
pin (IN) {
. . .
receiver_capacitance1_rise ("Lookup_table_4") {
index_1: ("0.1, 0.2, 0.3, 0.4"); /* Input transition */
values("0.001040, 0.001072, 0.001074, 0.001085");
}
索引1receiver_capacitance1_rise指定了这个引脚的输入过渡时间索引值。一维表格中的values指定了输入引脚上用于上升沿波形的接收电容。相似的,receiver_capacitance2_rise指定了输入上升波形的尾随部分的电容值。而如果需要输入引脚用于下降沿波形,则需要分别使用属性receiver_capacitance1_fall 和receiver_capacitance2_fall。
时序弧级别
接收引脚的电容同样可以用时序弧指定,这里就需要用到一个二维表,使用输入过渡时间以及输出负载,来共同的指定值。在下面的例子里指定了波形的开始部分在输入引脚IN的上升电容是输入过渡时间和输入引脚的负载的函数。
pin (OUT) {
. . .
timing () {
related_pin : "IN" ;
. . .
receiver_capacitance1_rise ("Lookup_table_4x4") {
index_1("0.1, 0.2, 0.3, 0.4"); /* Input transition */
index_2("0.01, 0.2, 0.4, 0.8"); /* Output capacitance */
values("0.001040 , 0.001072 , 0.001074 , 0.001075", \
"0.001148 , 0.001150 , 0.001152 , 0.001153", \
"0.001174 , 0.001172 , 0.001172 , 0.001172", \
"0.001174 , 0.001171 , 0.001177 , 0.001174");
}
. . .
}
. . .
} //这是个4*4的表格
下面的表中有4种不同的接受电容类型,如上面所说的,这可以用一个一维表模型在引脚级别进行指定,也可以用一个二维表模型在时序弧级别进行指定。
3.7.2 输出电流
在CCS模型中,非线性时序表现为输出电流,可以用输入转换时间,输出负载在表中指定具体的值。对于每一种组合,都指定了一个输出电流的波形,此处的输出电流的波形,实际上就是时间的函数
pin (OUT) {
. . .
timing () {
related_pin : "IN" ;
. . .
output_current_fall () {
vector ("LOOKUP_TABLE_1x1x5") {
reference_time : 5.06; /* Time of input crossing threshold */
index_1("0.040"); /* Input transition */
index_2("0.900"); /* Output capacitance */
index_3("5.079e+00, 5.093e+00, 5.152e+00,
5.170e+00, 5.352e+00");/* Time values */
/* Output charging current: */
values("-5.784e-02, -5.980e-02, -5.417e-02,
-4.257e-02, -2.184e-03");
}
. . .
}
. . .
}
. . .
}
reference_time指的是输入波形超过延迟阈值的时间,index_1和index_2是指输入过渡时间和输出负载电容,index_3指的是时间。索引1和索引2每个只能有一个值,索引3指向的是时间值,表中的输出电流值,以此为一一对照得到输出电流。因此对于给定的输入转换时间以及输出,输出电流是时间的函数。
如果是输出有上升的波形:用output_current_rise
3.7.3 针对于串扰噪声分析的模型
针对于串扰噪声和毛刺的分析 的模型,被描述为CCSN(CCS Noise)模型,CCSN模型是结构模型(structual),并在单元内表示为不同的通道连接块(CCB, Channel Connected Blocks)
CCB是:通道连接块,单元内源漏相连接的部分。反相器、与非门、或非门都只有一个CCB。整个单元的连接只使用了一个CCB来完成。与门、或门,就包含了多个CCB。
通常只指定两个CCB:由单元输入所驱动的第一个CCB,驱动单元输出的最后的一个CCB。通常他们会被指定使用稳态电流,输出电压,以及传播噪声的模型。对于单级的组合逻辑单元(如或非门、与非门),CCSN通常需要对每个时序弧进行指定。这些单级组合逻辑时序单元,只存在一个CCB,模型是从单元的输入引脚到输出引脚的。
一个与非门的例子
pin (OUT) {
. . .
timing () {
related_pin : "IN1";
. . .
ccsn_first_stage() { /* First stage CCB */
is_needed : true;
stage_type : both; /*CCB contains pull-up and pull-down*/
is_inverting : true;
miller_cap_rise : 0.8;
miller_cap_fall : 0.5;
(ccsn_dc) {
index_1 ("-0.9, 0, 0.5, 1.35, 1.8"); /* Input voltage */
index_2 ("-0.9, 0, 0.5, 1.35, 1.8"); /* Output voltage*/
values ( \
"1.56, 0.42, . . ."); /* Current at output pin */
}
. . .
output_voltage_rise () {
vector (ccsn_ovrf) {
index_1 ("0.01"); /* Rail-to-rail input transition */
index_2 ("0.001"); /* Output net capacitance */
index_3 ("0.3, 0.5, 0.8"); /* Time */
values ("0.27, 0.63, 0.81");
}
. . .
}
output_voltage_fall () {
vector (ccsn_ovrf) {
index_1 ("0.01"); /* Rail-to-rail input transition */
index_2 ("0.001"); /* Output net capacitance */
index_3 ("0.2, 0.4, 0.6"); /* Time */
values ("0.81, 0.63, 0.27");
}
. . .
}
propagated_noise_low () {
vector (ccsn_pnlh) {
index_1 ("0.5"); /* Input glitch height */
index_2 ("0.6"); /* Input glitch width */
index_3 ("0.05"); /* Output net capacitance */
index_4 ("0.3, 0.4, 0.5, 0.7"); /* Time */
values ("0.19, 0.23, 0.19, 0.11");
}
propagated_noise_high () {
. . .
}
}
}
代码解释:
时序弧由IN1指向OUT,
is_needed
为true
表示该阶段是必需的。stage_type : both
表示该阶段既包含上拉(pull-up)又包含下拉(pull-down)电路。is_inverting : true
表示这个电路具有反相特性。miller_cap_rise
和miller_cap_fall
分别是米勒电容在上升和下降时的值。然后先用ccsn_dc定义了直流电流特性,然后用表模型定义了输出电压以及传播噪声。
以下是详细的解释:
直流电流
直流电流代表输出端口对应于不同的输入输出电压。
输出电压
output_voltage_rise
和 output_voltage_fall
结构体分别包含 CCB 输出上升和下降的时序信息。在表中都用索引1指定rail2rail的输入转换时间,用索引2指定输出电容,索引3指定了时间,三个索引共同确定表中的一个值。
传播噪声
高传播噪声和低传播噪声模型,同样也指定了多维表,在表中给出了噪声传播的有关时序信息。这些模型主要用于表征输入到 CCB 的串扰毛刺(glitch)或噪声在输出端的传播特性。表征时输入端使用了对称的三角波。
表中的内容包括:
- 输入毛刺幅度(索引1)
- 输入毛刺宽度(索引2)
- CCB输出节点的电容(索引3)
- 时间(索引4)
由CCB传播的噪声由表中的值指出。
二级单元的噪声模型
对于一些二级单元,如与门,或门的CCS噪声模型,通常描述为时序弧的一部分。因为这些单元包含了两个独立的CCB,所以这些模型分别被指定为ccsn_first_stage 和 ccsn_last_stage。下面是一个与门的例子。
pin (OUT) {
. . .
timing () {
related_pin : "IN1";
. . .
ccsn_first_stage() {
/* IN1 to internal node between stages */
. . .
}
ccsn_last_stage() { /* Internal node to output */
. . .
}
. . .
}
timing () {
related_pin : "IN2";
. . .
ccsn_first_stage() {
/* IN2 to internal node between stages */
. . .
}
ccsn_last_stage() {
/* Internal node to output */
/* Same as from IN1 */
. . .
}
. . .
}
. . .
}
可以知道在单级单元的例子中省去了IN2的代码部分,在这里就是一个比较全面的结构了。
多级&时序单元的噪声模型
复杂的组合逻辑单元或者顺序单元,CCS噪声模型通常是引脚规格的一部分来描述。单级或者两级的基本逻辑门的CCSN模型通常是按照引脚对的方式,作为时序弧的一部分进行描述。而多级时序单元,通常为所有的输入引脚描述ccsn_first_stage模型,为所有的输出引脚描述ccsn_last_stage模型。这些CCSN模型不再是时序弧的一部分而是,直接对引脚进行指定。
复杂单元的CCS噪声模型主要是针对引脚的,而基本逻辑门的噪声模型是针对引脚对的。
如果输入和输出之间的内部路径多达两级CCB,则噪声模型也可以表示为引脚对时序弧的一部分。通常,多级单元中可以将某些CCS噪声模型指定为引脚对时序弧的一部分,而其他一些噪声模型可以通过引脚说明来指定。
下面的例子包含了使用引脚描述的CCS噪声模型,以及部分时序弧描述的CCS噪声模型。
pin (CDN) {
. . .
}
pin (CP) {
. . .
ccsn_first_stage() {
. . .
}
}
pin (D) {
. . .
ccsn_first_stage() {
. . .
}
}
pin (Q) {
. . .
timing() {
related_pin : "CDN";
. . .
ccsn_first_stage() {
. . .
}
ccsn_last_stage() {
. . .
}
}
}
pin (QN) {
. . .
ccsn_last_stage() {
. . .
}
}
引脚CP、D、QN都是用的引脚CCS噪声模型,在语句块中都指定了ccsn_first_stage或者是ccsn_last_stage
引脚Q是用的时序弧的CCS噪声模型,描述了与CDN之间的时序弧,两个ccsn函数的定义显示了信号在这段路径上的噪声传播情况。
3.7.4 其他噪声模型
单元库可以提供其他的模型来描述噪声,部分模型在CCS模型之前就开始使用了。如果CCS噪声模型可用,就不用这些模型。出于完整性的考虑,我们介绍他们。
直流裕度模型(DC Margin): 单元输入引脚,在不引起输出端口的尖刺的情况下,可允许的最大直流变化。例如,直流裕度对于输入为低,指的就是输入引脚最大的直流电压变化,而不引起输出引脚出现过渡。
抗扰度模型(Noise Immunity):抗扰度指定了输入引脚可接受的最大的毛刺幅值。这通常用一个二维表来描述,两个索引分别是毛刺宽度和输出引脚电容。表中的值对应于输入引脚可以允许的毛刺幅度。这意味着任何小于指定幅度和宽度的毛刺都不会通过单元传播。
- noise_immunity_high:高抗干扰能力
- noise_immunity_low:低抗干扰能力
- noise_immunity_above_high:高于高抗噪声能力,即使在高噪声环境仍能正常运行。
- noise_immunity_below_low:低于低抗噪声能力,在低噪声环境也有可能无法正常运行。
3.8 功耗建模
单元库中包含了有关单元功耗的信息,包含动态功耗以及静态功耗。
3.8.1 动态功耗
主要原因是对于输出负载的充电以及内部的电平值转换。这两者主要指的是:输出翻转功耗以及内部开关功耗。
内部开关功率在单元库中被称为internal power,这是当单元的输入或输出处于活动状态时单元内部的功耗。对于组合逻辑单元,输入引脚的电平跳变会导致输出引脚的电平跳变,从而导致内部开关功耗。例如,每当输入引脚电平跳变时,反相器单元就会消耗功率。 下面是单元库中描述的单元内部开关功率:
pin (Z1) {
. . .
power_down_function : "!VDD + VSS";
related_power_pin : VDD;
related_ground_pin : VSS;
internal_power () {
related_pin : "A";
power (template_2x2) {
index_1 ("0.1, 0.4"); /* Input transition */
index_2 ("0.05, 0.1"); /* Output capacitance */
values ( /* 0.05 0.1 */ \
/* 0.1 */ "0.045, 0.050", \
/* 0.4 */ "0.055, 0.056");
}
}
}
上面的代码展示了从输入引脚A到输出引脚Z1的功耗。2*2的表格的索引1是A输入引脚的输入过渡时间,索引2是输出引脚Z1的输出节点电容。注意,尽管该表包含了输出电容,但表中的值仅对应于内部开关,不包括输出电容的影响。该值表示每个开关转换(上升或下降)时在单元中耗散的内部能量。就是内部一次电平值转换需要消耗多少能量。
单位:电压(伏特)、电容(皮法pF)、功耗(皮焦pJ)
上面的代码还给出了电源引脚、接地引脚的说明,power_down_function表示如何关闭这个单元。下面展示了单元的电源引脚说明
cell (NAND2) {
. . .
pg_pin (VDD) {
pg_type : primary_power;
voltage_name : COREVDD1;
. . .
}
pg_pin (VSS) {
pg_type : primary_ground;
voltage_name : COREGND1;
. . .
}
}
定义了电源引脚为VDD,并在后面的type中指定了是主要的供电来源。定义了地引脚VSS,并在后面的type中指定了是主要的地线。此外还定义了电源电压的名称以及接地电压的名称。
功耗的语法同样也可以分别指定上升以及下降。就像时序弧,功耗同样也可以是状态依赖的。
对于组合逻辑单元,开关功耗是基于输入输出引脚对来指定的。但是对于一个触发器(具有互补输出),CLK-Q的输出,同样也会导致CLK-QN的输出,因此这个单元库可以将内部开关功率指定为三维表格。下面例子中的三维表,分别是输入CLK的压摆率,输出引脚Q电容,输出引脚QN电容。
pin (Q) {
. . .
internal_power() {
related_pin : "CLK";
equal_or_opposite_output : "QN";
rise_power(energy_template_3x2x2) {
index_1 ("0.02, 0.2, 1.0"); /* Clock transition */
index_2 ("0.005, 0.2"); /* Output Q capacitance */
index_3 ("0.005, 0.2"); /* Output QN capacitance */
values ( /* 0.005 0.2 */ /* 0.005 0.2 */ \
/* 0.02 */ "0.060, 0.070", "0.061, 0.068", \
/* 0.2 */ "0.061, 0.071", "0.063, 0.069", \
/* 1.0 */ "0.062, 0.080", "0.068, 0.075");
}
fall_power(energy_template_3x2x2) {
index_1 ("0.02, 0.2, 1.0");
index_2 ("0.005, 0.2");
index_3 ("0.005, 0.2");
values ( \
"0.070, 0.080", "0.071, 0.078", \
"0.071, 0.081", "0.073, 0.079", \
"0.066, 0.082", "0.068, 0.085");
}
}
开关功耗依然存在,即使输出或者内部的状态并没有发生改变。一个常见的例子就是触发器的时钟引脚发生了翻转,每当触发器的时钟引脚发生翻转的时候,都会产生功耗。通常是由触发器单元内部反相器的开关所带来的。即使触发器输出未发生改变,也会消耗由于时钟引脚切换引起的功率。因此,对于时序逻辑单元,输入引脚功率(input pin power)是指单元内部的功耗,即输出不切换时的功耗。以下例子中描述了输入引脚功率:
cell (DFF) {
. . .
pin (CLK) {
. . .
rise_power () {
power (template_3x1) {
index_1 ("0.1, 0.25, 0.4"); /* Input transition */
values ( /* 0.1 0.25 0.4 */ \
"0.045, 0.050, 0.090");
}
}
fall_power () {
power (template_3x1) {
index_1 ("0.1, 0.25, 0.4");
values ( \
"0.045, 0.050, 0.090");
}
}
}
. . .
}
这代表了CLK输入引脚由于翻转所带来的功耗,即使输出没有发生改变。
双重计数引起时钟引脚功耗重复计算
CLK-Q的功耗表格是不包含CLK内部功耗有关影响的,CLK的内部功耗与输出Q不切换时的情况相对应。
3.8.2 漏电功耗
电源给单元供电的时候,消耗了功率,但没有产生任何活动,都是由非0的漏电流所引起的漏电功耗。可能由亚阈值电流引起,也可能由栅氧的隧穿电流所导致。之前的CMOS工艺,我们都可以忽略漏电流,然而随着工艺尺寸的缩小,不得不考虑漏电流了。
如果使用高阈值电压的MOS管,漏电流可以减小,但是单元的工作速度变慢了。使用高阈值电压或者是低阈值电压MOS管,栅氧隧穿电流的影响都差不多,因此一种可能的用于减小漏电功耗的方法就是采用高阈值MOS管。类似于在高阈值电压和标准阈值电压单元之间进行选择,设计中使用的单元强度(strength)也是一种漏电功耗和工作速度之间的折中。强度较高的单元具有较高的漏电功率,但速度较高。
MOS的亚阈值特性与温度有很强的非线性关系。大多数情况下,如果温度由25℃升至125℃,亚阈值损耗可以提升10-20倍。MOS的栅氧层的隧穿电流,与器件的温度或是阈值电压没有关系。在使用100nm以上的工艺时,漏功耗可以不考虑,但是当使用65nm一下的工艺的时候,就需要考虑漏功耗了。举例来说,室温时使用65nm或更好的工艺时,栅氧漏电流的功耗可能与亚阈值电流的功耗相等;而当温度上升的时候,亚阈值损耗仍然是漏功耗的主导因素。
在单元库中,每个单元的漏功耗都指定了。举例来说,一个反相器可能有以下的规格:
这是单元中耗散的漏电功率,漏电功率单位在库的头文件中指定,通常以纳瓦nW为单位。通常,漏电功率还取决于单元的状态,可以使用when
条件指定状态相关值。
cell_leakage_power : 0.70;
leakage_power() {
when : "!I";
value : 1.17;
}
leakage_power() {
when : "I";
value : 0.23;
}
上面代码中0.7是功耗的默认值,通常是两个条件值的平均 (1.17+0.23) / 2 = 0.7
3.9 单元库中的其他属性
面积规格
面积规格指定了单元或是单元组的面积:
area : 2.35;
上面指定了单元的面积是2.35个单位面积,这个可以代表实际的使用的硅面积或者是一个相对的测量值。
功能规格
指定了一个引脚或是一个引脚组的功能:
pin (Z) {
function: "IN1 & IN2";
. . .
}
上面的代码说明Z引脚的功能就是将输入引脚1&2的值相与。
SDF条件
SDF(标准延迟格式)属性支持SDF文件的生成,以及在反注释过程中(backannotation)的条件匹配。就像when条件语句指定了状态依赖模型进行时序分析的条件,用于SDF注释的状态依赖时序使用的相应规范称为sdf_cond
timing() {
related_pin : "A1";
when : "!A2";
sdf_cond : "A2 == 1'b0";
timing_sense : positive_unate;
cell_rise(delay_template_7x7) {
. . .
}
}
3.10 特征以及工作条件
一个单元库创立之时,就指定了该库的特征以及工作条件,比如说这个库的头文件可能包含以下的内容
nom_process : 1;
nom_temperature : 0;
nom_voltage : 1.1;
voltage_map(COREVDD1, 1.1);
voltage_map(COREGND1, 0.0);
operating_conditions("BCCOM"){
process : 1;
temperature : 0;
voltage : 1.1;
tree_type : "balanced_tree";
}
nom_process:指定了所使用的工艺节点,值为1,应该代表一个编号。
nom_temperature:指定了温度条件,值为0,可能代表一个特定的温度条件。
nom_voltage:指定了工作条件下的电压,通常是电源电压,这里是1.1V。
voltage_map(COREVDD1, 1.1):定义了一个映射,将1.1V的值映射给名字为COREVDD1的电压。
如果特征和工作条件不同,则在延迟计算过程中获得的时序值需要进行降额(derate)处理, 这可以通过使用库中指定的降额系数(k系数)来完成。显而易见这样会带来不精确(inaccuracy)。降额程序仅在无法在目标操作条件下对库进行表征时才会被使用。这意味着如果无法在目标操作条件(如不同的温度或电压)下对电路单元进行实际测试和测量,就会采用降额的方法来估算性能。
工艺变量
库的表征是一个很耗时的过程,使用不同的工艺角来表征库需要几周的时间。工艺变量的设置可以使一个库设定的工艺角用在另一个工艺角的时序计算过程(就是一个工艺角的特征共享了)。工艺的k kk-系数可用于完成从特征库工艺到目标工艺的延迟降额。如上所说,这引入了时序计算过程中的不精确性;在不同工艺之间的降额尤其不精确,因此很少使用。总而言之,指定不同工艺变量值(例如1.0或任何其它值)的唯一功能就是在少数情况下允许跨工艺条件进行降额处理。
3.10.1 降额使用的K系数
如上所说,在工作条件与特征条件不同时,要使用降额系数也就是k系数。它是一个近似的系数。
/* k-factors */
k_process_cell_fall : 1;
k_process_cell_leakage_power : 0;
k_process_cell_rise : 1;
k_process_fall_transition : 1;
k_process_hold_fall : 1;
k_process_hold_rise : 1;
k_process_internal_power : 0;
k_process_min_pulse_width_high : 1;
k_process_min_pulse_width_low : 1;
k_process_pin_cap : 0;
k_process_recovery_fall : 1;
k_process_recovery_rise : 1;
k_process_rise_transition : 1;
k_process_setup_fall : 1;
k_process_setup_rise : 1;
k_process_wire_cap : 0;
k_process_wire_res : 0;
k_temp_cell_fall : 0.0012;
k_temp_cell_rise : 0.0012;
k_temp_fall_transition : 0;
k_temp_hold_fall : 0.0012;
k_temp_hold_rise : 0.0012;
k_temp_min_pulse_width_high : 0.0012;
k_temp_min_pulse_width_low : 0.0012;
k_temp_min_period : 0.0012;
k_temp_rise_propagation : 0.0012;
k_temp_fall_propagation : 0.0012;
k_temp_recovery_fall : 0.0012;
k_temp_recovery_rise : 0.0012;
k_temp_rise_transition : 0;
k_temp_setup_fall : 0.0012;
k_temp_setup_rise : 0.0012;
k_volt_cell_fall : -0.42;
k_volt_cell_rise : -0.42;
k_volt_fall_transition : 0;
k_volt_hold_fall : -0.42;
k_volt_hold_rise : -0.42;
k_volt_min_pulse_width_high : -0.42;
k_volt_min_pulse_width_low : -0.42;
k_volt_min_period : -0.42;
k_volt_rise_propagation : -0.42;
k_volt_fall_propagation : -0.42;
k_volt_recovery_fall : -0.42;
k_volt_recovery_rise : -0.42;
k_volt_rise_transition : 0;
k_volt_setup_fall : -0.42;
k_volt_setup_rise : -0.42;
注意!k_volt系数是负的,意味着延迟减小随着供电电压的增大。但是k_temp系数是正的,意味着随着温度的升高,延迟增加。(除非单元具有2.10节中所描述的温度反转现象)
举例来说,如果一个库的特征条件是1.08V和125℃,使用慢工艺模型。如果实际的工作条件是1.14V和100℃,使用慢工艺模型,那么单元的上升延时可以如下计算:
0.06是因为1.14-1.08=0.06;25是因为125-100=25.假设我们用上表中的参数:
3.10.2 库的单位
关于库描述的所有值,都使用库单位。这些单位使用Liberty文件来描述
library("my_cell_library") {
voltage_unit : "1V";
time_unit : "1ns";
capacitive_load_unit (1.000000, pf);
current_unit : 1mA;
pulling_resistance_unit : "1kohm";
. . .
}
在本文中,我们假定标准库的时间单位为纳秒(ns),电压单位为伏特(V),内部功率单位为皮焦耳(pJ),泄漏功率单位为纳瓦(nW),电容值单位为皮法拉(pF),电阻值单位为千欧姆,面积单位为平方微米(μm2),除非有其他的明确说明。
部分内容翻译自“Static Timing Analysis for Nanometer Designs A Practical Approach” 欢迎指正!