第 4 章 · 时间证词:时序控制与事件调度 章节摘要:本章跟着「一个事件何时被听见」的主线走:敏感列表决定谁有资格触发过程块,事件队列决定同一时刻内语句的裁决顺序,延迟模型决定信号传播的刻度,时钟与复位建模决定整个设计的节拍源。时间维度的语法,是把正确陈述放到正确时刻的机制。 一条主线 主线是时间的三层结构。最外层是仿真时间:从零开始、按事件推进的刻度轴, 这样的延迟控制就是在这根轴上排班。中间层是同一时刻内部:多个事件挤在同一个时间点时,仿真器用分层的事件队列与调度规则裁决先后,delta 周期就是这层的最小刻度。最内层是真实硬件的时间约束:建立保持窗口、传播延迟、复位释放时机——仿真器按离散刻度演出,硬件按连续物理执行,两层的误差就是「仿真过了、板上不行」的根源。
章节摘要:本章跟着「一个事件何时被听见」的主线走:敏感列表决定谁有资格触发过程块,事件队列决定同一时刻内语句的裁决顺序,延迟模型决定信号传播的刻度,时钟与复位建模决定整个设计的节拍源。时间维度的语法,是把正确陈述放到正确时刻的机制。
主线是时间的三层结构。最外层是仿真时间:从零开始、按事件推进的刻度轴,#10 这样的延迟控制就是在这根轴上排班。中间层是同一时刻内部:多个事件挤在同一个时间点时,仿真器用分层的事件队列与调度规则裁决先后,delta 周期就是这层的最小刻度。最内层是真实硬件的时间约束:建立保持窗口、传播延迟、复位释放时机——仿真器按离散刻度演出,硬件按连续物理执行,两层的误差就是「仿真过了、板上不行」的根源。本章三节从内往外拆:先审事件触发的资格问题(敏感列表),再审时间刻度的建模问题(延迟模型),最后落地到节拍源本身(时钟与复位)。
第一站 4.1「敏感列表与事件队列」:过程块的触发资格与仿真器的调度裁决。漏信号的敏感列表为什么导致仿真综合不一致,@(*) 为什么是解药,阻塞与非阻塞在队列里的执行位置——这一站把第 3 章的赋值语义接到调度机制的底层。
第二站 4.2「延迟模型与毛刺」:#延迟 的三种形态、惯性延迟对窄脉冲的吞噬、门延迟与线延迟的建模差异。毛刺是组合逻辑的天然属性,这一站解释它从哪来、仿真为什么常常看不见、设计上怎么与它共处。
第三站 4.3「时钟与复位建模」:测试台怎么生成时钟、同步复位与异步复位的取舍、异步释放的亚稳态风险与复位同步器。这是所有时序设计的地基,也是面试与 code review 的必考点。
先划一条边界:本章讲的是「语言的时间语法」,不是「时序设计方法」。建立保持时间怎么算、时钟树怎么约束、跨域协议怎么设计,这些更深的话题分布在此处(复位建模、跨域同步)与后续章节(综合流程)里。本章的目标是让你读懂仿真器的时间观,从而读懂波形、预判调度行为。
常见误读有三个。误读一:「延迟写在代码里,硬件就有这个延迟」——综合器忽略一切延迟,真实延迟由工艺与布局决定。误读二:「仿真通过说明时序没问题」——RTL 仿真只有行为时序,物理时序要等综合后的静态时序分析。误读三:「时间刻度精度越高仿真越准」——精度只影响刻度细分,模型精度取决于延迟标注是否真实。这三个误读的共同根源是把仿真世界与物理世界混为一谈,本章反复划的就是这条线。
本章的拐点是接受「仿真时间是离散的演出」。事件驱动仿真没有连续的物理时间:时间轴只在有事件的时间点之间跳跃,同一时刻内部还要按调度区细拆。理解了这套机制,很多怪现象就有了答案——为什么 $strobe 能看到非阻塞的最终值、为什么零延迟的循环会卡死仿真、为什么两条竞争路径的输出顺序不可预期。
结论落在设计纪律上:凡是依赖「同一时刻内先后顺序」的代码都是坏代码,因为它依赖的是调度实现而非电路结构。真正的硬件里,同一时钟沿上触发的寄存器是真正同时更新的,不存在谁先谁后;你的 RTL 应当只依赖「沿」这个概念,不依赖「沿内顺序」。第 9 章的竞争案件侦破,用的正是这条判据。
时间机制就位后,下一章下沉到电路的最底层:门级与原语建模。在那里没有 always、没有行为规则,只有一个个门和它们的接线——这是现场重建的世界,也是看懂综合网表、排查物理级问题的预备课。