4.3 时钟与复位建模 本节摘要:时钟在测试台里生成、在设计中只被消费;复位分同步与异步两种流派,各自有明确的适用边界;异步复位必须同步释放,否则复位释放沿本身就是亚稳态事故现场。这一节是所有时序设计的地基。 延迟与毛刺的规律讲完,这一节把时间维度落到两个最基础的信号上:时钟与复位。它们看似简单,却是设计规范、综合约束、时序分析全部围绕的锚点——锚点设错,全盘皆输。 时钟:只该有一个出生地 测试台里生成时钟的标准写法是一句 initial 加一句 forever: 设计内部(要综合的模块里)不该出现自产时钟——真实设计的时钟来自外部晶振或时钟管理单元,RTL 里自己翻转发明的时钟会让综合约束与实际接线对不上号。
本节摘要:时钟在测试台里生成、在设计中只被消费;复位分同步与异步两种流派,各自有明确的适用边界;异步复位必须同步释放,否则复位释放沿本身就是亚稳态事故现场。这一节是所有时序设计的地基。
延迟与毛刺的规律讲完,这一节把时间维度落到两个最基础的信号上:时钟与复位。它们看似简单,却是设计规范、综合约束、时序分析全部围绕的锚点——锚点设错,全盘皆输。
测试台里生成时钟的标准写法是一句 initial 加一句 forever:
`timescale 1ns/1ps module tb_clock_reset; reg clk = 1'b0; reg rst_n = 1'b0; // 100 MHz 时钟:周期 10ns,半周期翻转 always #5 clk = ~clk; initial begin rst_n = 1'b0; #37; // 避开整周期边界,暴露复位期间时钟照跑的事实 rst_n = 1'b1; #500; $finish; end endmodule
设计内部(要综合的模块里)不该出现自产时钟——真实设计的时钟来自外部晶振或时钟管理单元,RTL 里自己翻转发明的时钟会让综合约束与实际接线对不上号。分频时钟的正确建模方式有两种:专用分频寄存器翻转输出后当普通信号用、或全部逻辑统一在主时钟下用使能分频。第二种是高速设计的正路——全设计只有一个时钟沿,时序分析简单,跨分频域的握手也统一。6.3 节的跨时钟域案例会回到这个话题。
门控时钟(用组合逻辑关掉时钟以省功耗)在 RTL 里同样禁手写——时钟树上的毛刺会直接造成假沿。功耗优化该用工具插入门控单元(第八章展开),工具会保证门控后的时钟干净。
复位的两派取舍,本质是「复位信号要不要过时钟沿这道关」:
// 同步复位:复位逻辑进入数据路径 always @(posedge clk) begin if (!rst_n) q <= 1'b0; // rst_n 是普通数据输入 else q <= d; end // 异步复位:复位端走触发器的专用异步引脚 always @(posedge clk or negedge rst_n) begin if (!rst_n) q <= 1'b0; else q <= d; end
| 维度 | 同步复位 | 异步复位 |
|---|---|---|
| 复位路径 | 占用数据路径资源 | 走触发器异步引脚,不占数据路径 |
| 复位脉宽要求 | 必须覆盖至少一个时钟沿,时钟未起无法复位 | 沿到即复位,时钟不工作也有效 |
| 复位释放 | 天然与时钟同步,无释放风险 | 释放沿可能违反恢复移除窗口,有亚稳态风险 |
| 抗毛刺 | 天然过滤复位线毛刺 | 复位线毛刺直接触发复位 |
| 典型倾向 | 数据通路类设计 | 控制类、需要时钟前复位的设计 |
两派没有绝对赢家。工程上常见的折中是「异步复位、同步释放」:复位生效走异步引脚(保证任何时刻都能复位),复位释放经过同步器(保证释放沿与时钟对齐):
module reset_sync( input wire clk, input wire rst_async_n, // 外部异步复位,低有效 output wire rst_sync_n // 同步释放的复位 ); reg ff1, ff2; always @(posedge clk or negedge rst_async_n) begin if (!rst_async_n) begin ff1 <= 1'b0; ff2 <= 1'b0; end else begin ff1 <= 1'b1; ff2 <= ff1; end end assign rst_sync_n = ff2; endmodule
释放沿到来时,ff1、ff2 在时钟推动下逐拍变高,rst_sync_n 的上升沿与时钟严格对齐,恢复窗口违例的风险被同步器吸收。两级触发器是最低配置,极高速设计会加第三级进一步压低失效概率。

案例展开:复位树上的状态撕裂。 背景:某多时钟域设计,外部复位经背板走线后分别到达各域,联调时偶发两个域「半个域复位了半个域没有」。操作:波形比对发现外部复位释放沿落在域 A 时钟的违例窗口内,域 A 部分寄存器脱离复位、部分仍在复位态,跨域握手随即错乱。结果:每个时钟域各配一个复位同步器,外部复位只作为同步器的异步输入,各域消费本地同步后的复位。结果复发率归零。解读:复位线是全局信号,全局信号的「同时性」在任何真实系统里都不成立——传播延迟注定各处看到不同相位。把「同时」的保证交给每域的同步器,而不是寄希望于布线,这是复位架构设计的核心思想。变式:多电源域设计还要考虑复位期间时钟未起的问题——复位释放条件里加入「时钟稳定」标志,避免同步器在无时钟状态下失效。
设计文档里关于复位该写清的事:哪些寄存器需要复位(不是全部——数据通路的流水寄存器常免复位,控制状态必须复位)、复位值各是什么、复位来源是同步还是异步、异步释放是否都过同步器、复位线毛刺是否有过滤。这张清单在第九章规范一节还会出现——复位是设计评审的必查项,因为它出错时的症状(随机性状态错乱)距离病因(复位架构)隔得太远。
短于一个时钟周期是常见误区——真实系统的复位脉宽由复位电路决定,通常远宽于时钟周期。仿真里复位太短,会掩盖「复位期间时钟沿触发行为」这类问题。惯例是复位持续至少几个时钟周期,且释放沿与时钟沿错开半个周期左右,把真实世界的相位随机性带进仿真。
门控单元的仿真模型要如实模拟使能毛刺的通过特性,不能简化成理想与门——否则仿真发现不了毛刺问题,上板才发现。用工艺库提供的验证过的门控单元模型,自己不手写。这也是「时钟只交给工具和库」原则在仿真侧的投影。
每域一个复位同步器,同步器的异步输入都接同一个全局复位源,输出供本域使用。域与域之间的复位时序差异是允许的——各域在自己时钟的约束下安全释放即可,跨域信号反正要过各自域的同步器。要避免的是让一个域的本地复位直接喂给另一个域,那会把复位线变成一条失控的跨域信号。
时间证词到此听审完毕。下一章下沉到电路最底层:门级与原语建模——离开行为描述,看看电路的物理长相。