1.4 时序逻辑、时钟复位与 FSM 本节摘要:时序逻辑让电路记住状态,也把错误从“算错”变成“采早了或采晚了”。锁存器电平敏感,触发器边沿敏感,二者时间哲学不同。建立与保持是采样窗口的两边;异步复位必须同步释放;FSM 要用安全编码和默认态。本节把这些写成能综合、能被 STA 检查的结构。 先说结论 阅读完本节,你应当能够: 对比锁存器与边沿触发器的透明窗口差异 用建立、保持解释为什么会亚稳态 画出异步复位同步释放链 写出两段式 FSM,并说明非法态处理 一、记住状态的两种哲学 组合逻辑不记仇。时序逻辑必须回答:如何在没有输入变化时仍保持一个值。锁存器选择电平敏感:使能高则透明,输入变化当场穿透;使能低则闩住。
本节摘要:时序逻辑让电路记住状态,也把错误从“算错”变成“采早了或采晚了”。锁存器电平敏感,触发器边沿敏感,二者时间哲学不同。建立与保持是采样窗口的两边;异步复位必须同步释放;FSM 要用安全编码和默认态。本节把这些写成能综合、能被 STA 检查的结构。
阅读完本节,你应当能够:
组合逻辑不记仇。时序逻辑必须回答:如何在没有输入变化时仍保持一个值。锁存器选择电平敏感:使能高则透明,输入变化当场穿透;使能低则闩住。它像一道只在放行时段敞开的闸门,脉冲宽、捕获能力强,也容易在敞开时段把毛刺关进去。
边沿触发器选择更严的哨兵制度。常见 D 触发器由主从两级锁存构成:沿到来时主级采样,从级在错开的相位把值交到输出。输出只在沿附近更新一次。数字 ASIC 流程几乎默认这种世界,因为 STA 的建立保持检查、扫描替换、时钟门控插入都按边沿寄存器建模。
原文把建立失守和保持坍塌说成滑入亚稳态。这不是修辞。数据在沿附近仍在跳,触发器内部交叉耦合分不出输赢,输出在轨电压中间徘徊,停留时间统计上没有上界。同步器的意义是把这场赌博限制在两级触发器内部,不让亚稳态直接驱动一大片组合。
建立检查问:数据是否在沿到来前足够早稳定。保持检查问:沿之后数据是否还坚持得够久,免得把刚采的值冲掉。同一条组合路径,慢了伤建立,太快伤保持。这就是为什么修建立时乱插缓冲可能把保持打穿,而修保持时乱加延迟单元可能把建立打穿。
| 元件 | 敏感方式 | 好处 | 代价 |
|---|---|---|---|
| 锁存 | 电平窗口 | 可借时间、面积略省 | 透明期毛刺、STA 建模烦 |
| 边沿触发器 | 时钟沿 | 工具链友好、扫描好插 | 面积与时钟负载更大 |
| 脉冲锁存 | 窄脉冲当沿 | 高性能数据通路 | 脉冲生成与变异敏感 |
可综合 RTL 里,除非你明确在做时间借用的数据通路,否则不要写锁存。综合推断出的锁存,十次有九次是缺 else。
一块时序逻辑只敏感一个时钟。门控用使能语义,不手写门去砍时钟树。多周期路径要在设计时就知道,并在约束里声明,否则 STA 会按单周期审判一条本该两拍走完的路径。
复位推荐异步断言、同步释放。断言要快,掉电和看门狗不能等一个边沿。释放要齐,复位树像一根长水管,各叶子到达时间不同,若异步释放,有的触发器已进 Idle,有的还停在 0,FSM 会跳进幽灵状态。同步释放用两级触发器把“复位撤掉”这件事对齐到本域时钟。

跨时钟域不要发明第三种办法。单比特用两级同步器;多比特用握手或异步 FIFO。原文在 STA 章强调:工具可以把跨域标成异步从而豁免建立保持,但同步器内部两级之间仍必须干净。布局把两级拉出八百微米,第二级建立失败,整条 CDC 就是摆设。
时钟偏斜是寄存器之间的相对到达差。有意偏斜偶尔用来救建立,但会伤害保持,且让扫描捕获窗口变窄。RTL 阶段能做的是少造时钟:不要为了“快一点”用组合逻辑衍生时钟。衍生时钟是 STA 和抖动的灾区。
⚠️ 常见坑:用计数器进位当时钟,或用数据边沿当时钟。功能仿真像模一样,硅上偏斜和毛刺会让采样点漂移。
💡 关键直觉:触发器买的是时间上的确定性。你破坏时钟质量,等于把买来的确定性退货。
两段式:组合块算次态和输出,时序块只采样次态。次态逻辑完整,默认态写死。一段式把输出和状态都塞进边沿块,容易写出锁存式输出或多余寄存器。三段式把输出再寄存一拍,有利于时序,改变了对外拍序,接口规格要一起改。
编码:二进制省触发器;独热译码快、触发器多,适合高速控制、状态数不太多;格雷在跨域传状态时相邻只翻一比特。非法态必须有出口,扫描和单粒子翻转会把你送进未定义编码。安全 FSM 从非法态回到复位或错误态,而不是“应该到不了就不管”。
always @(posedge clk or negedge rst_n) begin if (!rst_n) state <= S_IDLE; else state <= state_n; end always @(*) begin state_n = state; case (state) S_IDLE: if (go) state_n = S_RUN; S_RUN: if (done) state_n = S_IDLE; default: state_n = S_IDLE; endcase end
输出若是摩尔型,只跟状态走,毛刺少、时序好分析。米利型跟输入走,反应快,组合路径更长。控制类我偏摩尔;数据选通有时不得不用米利,那就把选通再打一拍。
DFT 会把触发器换成扫描触发器,FSM 在移位时会穿越非法态。功能复位与测试复位的优先级要在规格里写清,否则扫描退出后状态机停在幽灵态,芯片“测试通过、上电乱跳”。
算,而且是 CDC 的标准件。两侧各用本域时钟,格雷码指针跨域,空满生成在本域。不要自己用双口 RAM 加两个计数器“等效”FIFO,空满会在跨域上打架。
不能。保持与周期无关,它看最短路径。放慢时钟只救建立。保持要加延迟、减偏斜、或禁止工具把缓冲优化掉。
状态位要进扫描。独热状态机在移位时会穿越多 1,功能译码若没有 default,输出会在测试后残留。安全出口不是装饰:从非法编码回到 Idle 或 Error,并用断言统计是否发生。发生不一定是设计错,也可能是测试残留或单粒子,但你必须有确定行为。
握手 FSM 最容易在反压下写出锁存式输出:valid 组合依赖于 ready,ready 又组合依赖于 valid,组合环加上时序块,仿真偶发,综合报环或推出振荡器。规则是:至少有一侧寄存。常见做法是源侧寄存数据与 valid,宿侧寄存 ready,或用弹性缓冲打成两拍。接口规格要写明延迟是零拍还是一拍,软件驱动和验证都靠这一拍。
同步器两级必须放在同一模块、同一约束视图里,便于 don't_touch 和放置靠近。把第一级写在 A 模块、第二级写在 B 模块,布局会把它们拉开,STA 还可能找不到这对寄存器。命名用统一前缀,审查才能搜到。
多周期路径的使能必须和数据同拍合格。使能晚一拍,STA 按多周期放行,功能却在单周期采样,硅上必错。使能生成建议与数据同一时序块,或明确打拍关系后写进 SDC 注释。约束与 RTL 分开维护时,这一条最容易漂。
实验室里很难抓到亚稳态,因为它的停留时间没有上界、出现概率又随窗口变窄而指数下降。于是有人删掉第二级“反正没见过”。直到某次异步口在高低温下偶发。同步器的面积几乎为零,删掉它换来的是无法复现的现场。
两级是否够,取决于时钟频率、工艺和可靠性目标。更高可靠场合用三级或带滤波的结构。无论几级,放置必须靠近,约束必须保护,内部必须跑 STA。把同步器当普通数据路径优化,布局会把它拉成八百微米的笑话。
FSM 的默认态要在仿真里用强制非法编码测到。测不到的 default 等于没写。扫描移位后的残留也要测:退出测试模式是否强制再复位。量产流程若允许测试后直接进用户模式,这条就是功能。
扫描会把 FSM 带进非法编码。退出测试后若没有强制功能复位,芯片可能停在幽灵态。量产流程必须规定:测试结束是否再来一次释放。规定要写进接口表,驱动和测试程序共同遵守。同步器放置约束写成可检索的 dont_touch 组,审查用搜索而不是用记忆。
保持与周期无关这句话,要在实验室墙上看见。有人改晶振“修好”偶发错误,过两周在更高温度复发,那是保持或 CDC。同步器两级同模块同约束,命名可搜。FSM 用强制非法编码测 default,用扫描退出测是否再复位。握手至少一侧寄存,消灭 valid 与 ready 的组合环。多周期使能与数据同拍,SDC 注释指向同一信号。衍生时钟禁令写进 lint。这些都是时间契约的螺栓,松一颗,STA 后面会用一整页违例提醒你。
某通路功能仿真完美,高温样片上电后偶发停在非法态。抓波发现复位释放在芯片两端相差好几拍,靠近根的 FSM 已进 Run,远端仍在 Idle,握手两边各执一词。根因是异步释放、复位树偏斜。改成每域两级同步释放后,非法态断言不再触发。同一颗硅上扫描退出若不做功能复位,仍可能把独热机留在多 1 编码。于是量产程序加上测试后再释放一次。这个案例把建立保持之外的时间问题摊开:释放齐不齐、测试后知不知。墙上看见“保持与周期无关”,旁边应再贴“释放要齐、测试后要再醒”。
再补一条出门检查:强制把 FSM 打进非法编码看是否回 Idle;扫描移位后不给功能复位看是否幽灵;跨域口搜同步器前缀看是否成对。三条都做,时间契约才算上了螺栓。衍生时钟 lint 必须零。多周期使能与数据同名注释进 SDC。这些检查不花综合许可证,却能少买一轮金属。半醒复位与保持崩是两种病,药不同,墙上两句话都要在。
独热机在扫描移位中途会经过多 1 编码,若下一拍就按功能译码,会同时打开互斥通路。移位期间要用扫描模式冻结输出译码,或规定捕获前必须先回 Idle。这条写进 FSM 编码说明,比事后在硅上抓“偶发双驱动”便宜。
下一章把这些触发器和组合云送进综合:标准单元、约束、扫描链,网表开始长出物理的脸。