核心概念:锁存点(Latch Point)与引脚测量点
理解负值 Setup/Hold 的关键在于区分 触发器的外部引脚 和其内部的 实际锁存点。
理想触发器模型: 我们通常想象数据(D)在时钟(CLK)上升沿 瞬间 被捕获。Setup 要求数据在 CLK 上升沿 之前 稳定一段时间(Tsu > 0),Hold 要求数据在 CLK 上升沿 之后 保持稳定一段时间(Th > 0)。
现实触发器结构: 实际的触发器内部由门电路(通常是传输门和反相器)构成。数据信号需要经过一些内部路径才能到达真正决定其值的主锁存器或从锁存器节点。同样,时钟信号也需要经过缓冲、反相才能驱动这些锁存器节点。
锁存点(Latch Point): 这是触发器内部决定数据值被捕获的 实际物理节点(例如,主锁存器的关键节点)。时钟信号到达这个点并满足其阈值时,数据值即被锁定。
路径延迟差异: 数据信号从 D 引脚到达锁存点的路径延迟(
Td_d2latch
)和时钟信号从 CLK 引脚到达锁存点的路径延迟(Td_clk2latch
)通常是 不同 的。这种差异是导致 Setup/Hold 时间为负的根本原因。负值的含义:
负保持时间 (Th < 0): 表示时钟信号从 CLK 引脚传播到内部锁存点所花费的时间 (
Td_clk2latch
) 大于 数据信号从 D 引脚传播到锁存点所花费的时间 (Td_d2latch
)。这意味着,即使数据在 D 引脚上的变化发生在 CLK 引脚上的时钟沿 之后(违反了正 Hold 时间的直观要求),只要这个“之后”的程度小于|Th|
,数据在内部锁存点 相对于内部时钟到达点 仍然是稳定的,从而满足实际的保持要求。 可以理解为时钟“走得太慢”,需要数据“等一等”它。负建立时间 (Tsu < 0): 表示数据信号从 D 引脚传播到锁存点所花费的时间 (
Td_d2latch
) 大于 时钟信号从 CLK 引脚传播到锁存点所花费的时间 (Td_clk2latch
)。这意味着,即使数据在 D 引脚上的变化发生在 CLK 引脚上的时钟沿 之后(违反了正 Setup 时间的直观要求),只要这个“之后”的程度小于|Tsu|
,数据在内部锁存点 相对于内部时钟到达点 仍然有足够的时间稳定下来,从而满足实际的建立要求。 可以理解为数据“走得太慢”,时钟需要“等一等”它。
总结:负的 Setup/Hold 时间本质上是触发器内部路径延迟差异在外部引脚测量点上的一种体现。它告诉我们,在外部引脚上观察到的数据变化和时钟变化的相对时序要求可以放宽(甚至允许数据在时钟之后变化),但这只是为了补偿内部路径延迟的不对称,确保在内部的 实际锁存点,时序要求(数据在时钟有效前稳定 Tsu_effective / 在时钟有效后稳定 Th_effective)仍然得到满足。 内部的 Tsu_effective
和 Th_effective
总是正数。
示例分析 (时钟周期 = 5ns)
示例 1:负保持时间 (Th = -0.4ns)
触发器参数:
Td_clk2latch
= 0.8ns (时钟从 CLK 引脚到锁存点的延迟 - 较长)Td_d2latch
= 0.4ns (数据从 D 引脚到锁存点的延迟 - 较短)Th_effective
= 0.2ns (锁存点实际需要的保持时间)计算外部引脚保持时间:
Th = Th_effective + Td_d2latch - Td_clk2latch = 0.2 + 0.4 - 0.8 = -0.2ns
。实际中可能有更复杂的建模,假设我们最终得到规格书上的Th = -0.4ns
。
时序场景分析 (分析 T1 时刻的捕获):
Launch Edge (T0=0ns): 时钟在 CLK 引脚上升沿。此时启动数据 Data(T0) 的传输。
Capture Edge (T1=5ns): 时钟在 CLK 引脚上升沿。此时需要捕获数据 Data(T0) 的最终值。
数据路径 (Data(T0) -> Q):
D 引脚数据变化时刻:
T_data_launch = T0 + 0 = 0ns
(假设组合逻辑延迟为 0,即 D 在 T0 就变为 Data(T0) 的值)。数据到达锁存点时刻:
T_data_arrive_latch = T_data_launch + Td_d2latch = 0 + 0.4 = 0.4ns
。数据 必须保持稳定 直到锁存点时钟有效后
Th_effective = 0.2ns
。
时钟路径 (CLK @ T1 -> Latch):
CLK 引脚 T1 上升沿时刻:
T_clk_capture_pin = 5.0ns
。时钟到达锁存点时刻:
T_clk_arrive_latch = T_clk_capture_pin + Td_clk2latch = 5.0 + 0.8 = 5.8ns
。 (关键:时钟内部延迟大,锁存点时钟在 5.8ns 才有效)
锁存点实际时序要求:
数据在锁存点 最早允许变化 的时刻:
T_data_must_stable_until_latch = T_clk_arrive_latch + Th_effective = 5.8 + 0.2 = 6.0ns
。当前数据 Data(T0) 在锁存点变化时刻:
T_data_arrive_latch = 0.4ns
(它代表 Data(T0) 的值稳定在锁存点的起始时间)。下一个数据 Data(T1) 何时会改变锁存点的值?这取决于驱动 D 引脚的组合逻辑。假设组合逻辑延迟为
Tcomb
。Data(T1) 在 D 引脚出现的时间是T1 + Tcomb = 5 + Tcomb ns
。它到达锁存点的时间是T_data_next_arrive_latch = 5 + Tcomb + Td_d2latch = 5 + Tcomb + 0.4ns
。
保持时间检查 (在锁存点): 要保证 Data(T0) 在锁存点的值在 5.8ns 到 6.0ns 期间不被 Data(T1) 覆盖:
T_data_next_arrive_latch >= T_data_must_stable_until_latch
5 + Tcomb + 0.4 >= 6.0
Tcomb >= 6.0 - 5 - 0.4 = 0.6ns
这意味着组合逻辑延迟至少需要 0.6ns,才能保证在内部锁存点满足实际的保持时间要求 (Th_effective=0.2ns)。外部引脚保持时间检查 (Th = -0.4ns): 工具会检查在 CLK 引脚捕获沿 (T1=5.0ns) 时刻:
数据 变化时间 (Data(T1) 到达 D 引脚的时间) >= 捕获沿时间 + Th
T_data_change_pin >= 5.0 + (-0.4) = 4.6ns
数据变化时间
T_data_change_pin = T1 + Tcomb = 5 + Tcomb ns
(Data(T1) 在 D 引脚出现的时间)所以
5 + Tcomb >= 4.6ns
。这个不等式总是成立,因为Tcomb >= 0
。单看这个外部检查,似乎没有保持时间要求!
为什么需要负 Th 和内部检查? 虽然外部检查
5 + Tcomb >= 4.6
总是成立,但我们从内部检查知道Tcomb
实际需要 >= 0.6ns。负的 Th (-0.4ns) 有效地 放松了在外部引脚上对数据必须晚于时钟变化的限制。它允许 Data(T1) 在 CLK 引脚 T1 上升沿 之前 就到达 D 引脚(只要不早于 4.6ns),而不会立即导致保持时间违例。这补偿了时钟内部路径较慢 (Td_clk2latch=0.8 > Td_d2latch=0.4
) 的特性。最终保证内部锁存点时序的关键是组合逻辑延迟Tcomb >= 0.6ns
。
结论 (负 Hold): 负的保持时间 (Th = -0.4ns) 表明,由于时钟内部路径延迟 (
0.8ns
) 大于数据内部路径延迟 (0.4ns
),数据信号在 D 引脚上可以在时钟捕获沿 (T1=5.0ns) 之前 变化(最早可至 4.6ns),只要驱动 D 引脚的组合逻辑延迟 (Tcomb
) 足够大(本例 >=0.6ns),就能保证在内部锁存点 (时钟 5.8ns 有效) 满足实际的保持时间要求 (Th_effective=0.2ns)。
示例 2:负建立时间 (Tsu = -0.3ns)
触发器参数:
Td_clk2latch
= 0.5ns (时钟从 CLK 引脚到锁存点的延迟 - 较短)Td_d2latch
= 0.9ns (数据从 D 引脚到锁存点的延迟 - 较长)Tsu_effective
= 0.2ns (锁存点实际需要的建立时间)计算外部引脚建立时间:
Tsu = Tsu_effective + Td_d2latch - Td_clk2latch = 0.2 + 0.9 - 0.5 = 0.6ns
。实际中可能有更复杂的建模,假设我们最终得到规格书上的Tsu = -0.3ns
。
时序场景分析 (分析 T1 时刻的捕获):
Launch Edge (T0=0ns): 时钟在 CLK 引脚上升沿。此时启动数据 Data(T0) 的传输。
Capture Edge (T1=5ns): 时钟在 CLK 引脚上升沿。此时需要捕获数据 Data(T0) 的最终值。
数据路径 (Data(T0) -> Q):
D 引脚数据稳定时刻:
T_data_stable_pin = T0 + Tcomb
(假设组合逻辑延迟为Tcomb
ns。这是 Data(T0) 在 D 引脚稳定下来的时间)。数据到达锁存点时刻:
T_data_arrive_latch = T_data_stable_pin + Td_d2latch = Tcomb + 0.9ns
。(关键:数据内部延迟大)
时钟路径 (CLK @ T1 -> Latch):
CLK 引脚 T1 上升沿时刻:
T_clk_capture_pin = 5.0ns
。时钟到达锁存点时刻:
T_clk_arrive_latch = T_clk_capture_pin + Td_clk2latch = 5.0 + 0.5 = 5.5ns
。(关键:时钟内部延迟小,锁存点时钟在 5.5ns 就有效)
锁存点实际时序要求:
数据 必须稳定 在锁存点的时刻:
T_data_must_arrive_latch = T_clk_arrive_latch - Tsu_effective = 5.5 - 0.2 = 5.3ns
。建立时间检查:
T_data_arrive_latch <= T_data_must_arrive_latch
Tcomb + 0.9 <= 5.3
Tcomb <= 5.3 - 0.9 = 4.4ns
这意味着组合逻辑延迟最大不能超过 4.4ns,才能保证在内部锁存点满足实际的建立时间要求 (Tsu_effective=0.2ns)。
外部引脚建立时间检查 (Tsu = -0.3ns): 工具会检查在 CLK 引脚捕获沿 (T1=5.0ns) 时刻:
数据 稳定时间 (Data(T0) 在 D 引脚稳定的时间) >= 捕获沿时间 + Tsu
T_data_stable_pin >= 5.0 + (-0.3) = 4.7ns
数据稳定时间
T_data_stable_pin = T0 + Tcomb = Tcomb ns
(假设 T0=0)所以
Tcomb >= 4.7ns
。单看这个外部检查,要求数据在 D 引脚至少要在 4.7ns 稳定。
对比与意义:
内部检查要求:
Tcomb <= 4.4ns
(上限)外部检查要求:
Tcomb >= 4.7ns
(下限)这看起来矛盾 (
4.7ns <= Tcomb <= 4.4ns
无解)? 问题出在哪里?关键在于
T_data_stable_pin
的定义: 外部建立时间检查中的T_data_stable_pin
指的是 Data(T0) 在 D 引脚 最终稳定下来 的时间,也就是T0 + Tcomb
。而负的 Tsu 要求这个稳定时间>= 4.7ns
。但同时,内部路径要求 Data(T0) 必须在 5.3ns 前到达锁存点,其路径延迟是 0.9ns,所以推导出Tcomb <= 4.4ns
。矛盾解析: 负的建立时间
Tsu = -0.3ns
本身是触发器特性的描述。Tcomb >= 4.7ns
这个要求是 基于这个特定触发器模型 (Tsu = -0.3ns
) 计算出来的外部约束。它和内部推导的Tcomb <= 4.4ns
共同 定义了Tcomb
的可行窗口:4.7ns <= Tcomb <= 4.4ns
。这个窗口是空的! 这似乎意味着这个设计无法满足时序? 是的!
设计修改/解释: 这个矛盾结果突显了负建立时间触发器的挑战。为了满足时序:
要么需要 减少组合逻辑延迟
Tcomb
使其小于 4.4ns (以满足内部锁存点要求)。要么需要 满足外部检查
Tcomb >= 4.7ns
。但两者不能同时满足 (
4.7 > 4.4
)。这意味着:要么这个触发器不适合用于
Tcomb > 4.4ns
的路径。要么
Tcomb
必须被设计成 小于 4.4ns。此时,外部检查Tcomb >= 4.7ns
自动失败 (Tcomb < 4.4 < 4.7
),但 只要Tcomb <= 4.4ns
,内部锁存点的建立时间要求 (Tsu_effective=0.2ns
) 就满足了。负的建立时间检查 (Tsu = -0.3ns
) 在这种情况下 被违反是允许的,因为内部路径延迟 (Td_d2latch=0.9 > Td_clk2latch=0.5
) 已经补偿了数据到达 D 引脚较晚的情况。
负 Tsu 的核心作用: 负的建立时间
Tsu = -0.3ns
放宽了在外部引脚上对数据必须早于时钟变化的限制。它允许 Data(T0) 在 D 引脚上的稳定时间 (Tcomb
) 晚于 CLK 引脚捕获沿 (T1=5.0ns) (最晚可至5.0 - (-0.3) = 5.3ns
,但实际外部检查要求>=4.7ns
,这个例子中更严格的约束来自内部路径延迟推导出的上限Tcomb <= 4.4ns
)。它补偿了数据内部路径较慢 (Td_d2latch=0.9 > Td_clk2latch=0.5
) 的特性。最终保证内部锁存点时序的关键是组合逻辑延迟Tcomb <= 4.4ns
。 外部负 Tsu 检查 (Tcomb >= 4.7ns
) 在Tcomb <= 4.4ns
时会失败,但这个失败是触发器特性允许的,只要内部锁存点满足Tsu_effective
。
结论 (负 Setup): 负的建立时间 (Tsu = -0.3ns) 表明,由于数据内部路径延迟 (
0.9ns
) 大于时钟内部路径延迟 (0.5ns
),数据信号在 D 引脚上可以在时钟捕获沿 (T1=5.0ns) 之后 才稳定下来(本例允许最晚稳定至 5.3ns,但实际设计约束Tcomb <= 4.4ns
意味着数据必须在 4.4ns 稳定在 D 引脚),只要这个“之后”的程度不超过|Tsu|
(0.3ns
) 加上时钟周期和路径延迟允许的范围,就能保证在内部锁存点 (时钟 5.5ns 有效) 满足实际的建立时间要求 (Tsu_effective=0.2ns)。外部负 Tsu 检查 (>=4.7ns
) 可能被违反,但这是该触发器特性下为满足内部时序而允许的。
最终总结
负值原因: Setup/Hold 时间为负值是由于触发器内部数据路径延迟 (
Td_d2latch
) 和时钟路径延迟 (Td_clk2latch
) 存在差异造成的。这种差异导致在外部引脚测量的时序要求与内部实际锁存点的时序要求 (Tsu_effective
,Th_effective
) 之间需要一个偏移量。负 Hold Time (Th < 0): 表示
Td_clk2latch > Td_d2latch
(时钟内部慢)。它允许数据在外部 D 引脚上在时钟捕获沿 之前 变化,补偿了时钟内部较慢的特性,确保内部锁存点有足够的实际保持时间 (Th_effective > 0
)。设计上需要关注组合逻辑延迟 (Tcomb
) 的下限。负 Setup Time (Tsu < 0): 表示
Td_d2latch > Td_clk2latch
(数据内部慢)。它允许数据在外部 D 引脚上在时钟捕获沿 之后 才稳定,补偿了数据内部较慢的特性,确保内部锁存点有足够的实际建立时间 (Tsu_effective > 0
)。设计上需要关注组合逻辑延迟 (Tcomb
) 的上限,并且要注意外部负 Tsu 检查可能被违反,但只要内部要求满足即可。关键点: 负的 Setup/Hold 时间 并不降低时序要求,它只是将内部锁存点严格的正时序要求 (
Tsu_effective > 0
,Th_effective > 0
),通过路径延迟差异的补偿,转换成了在外部引脚上更宽松(甚至允许数据在时钟之后变化)但物理上等效的约束。静态时序分析工具会精确计算这些路径延迟和触发器特性,自动处理负值,确保内部锁存点的真实时序得到满足。设计者理解这一机制有助于解读时序报告和优化设计。
注意:建立时间和保持时间不能同时为负值,两者的和也不能是负值