本节摘要:组合逻辑的输出只由当前输入决定,但延迟、毛刺与面积由拓扑决定。算术通路里进位链是最顽固的关键路径:行波加法定不了吉赫兹账,超前进位、进位选择与前缀树是在硅上改因果深度。乘法器的 Booth 编码不是装饰,而是压缩部分积层数的能效选择。本节按“先能综合,再砍路径”写。
阅读完本节,你应当能够:
组合云没有时钟,不代表它没有时间。信号从输入翻转到输出稳定,中间每个门都在交 RC 的税。深亚微米下,互连延迟常常压过门延迟,所以“这个 if-else 看起来很浅”不可信——综合之后可能是一长串 AOI 加一段横跨模块的金属。
原文把组合设计放在速度、能量、鲁棒三维坐标系里。速度看传播延迟,它吃输入转换时间、负载电容、驱动能力,还有米勒效应。能量看翻转:开关活动因子乘上电容再乘电压平方。鲁棒看噪声容限和工艺角:典型角快百分之十、慢角功能翻车的电路,工程价值为零。
毛刺是组合特有的税。输入不同时到达,输出可能先错后对。功能仿真用周期末采样,看不见;功耗仿真和串扰分析会看见。减少毛刺的办法是平衡路径、避免深优先级链、不要用一长串异或当时钟使能。异或链对奇偶校验很香,对时序和活动因子很毒。
静态 CMOS 的好处是稳态几乎不耗静态电流(漏电另算),输出被强上拉或强下拉锚定。传输管逻辑省管,却把电平与噪声容限交给弱驱动。动态逻辑快,但预充电和电荷分享要额外纪律,数字后端默认库往往不让你随便用。可综合 RTL 里,老老实实写布尔运算,让综合器映射到标准单元,通常比手炫动态逻辑更接近能交货。
所有算术的根是进位。n 位行波加法器里,第 i 位要等第 i-1 位的进位稳定。延迟近似随位数线性涨。原文给过数量级直觉:工艺进到几十纳米后,单级门是皮秒量级,全加器更慢,64 位行波的关键路径可以到纳秒级,对吉赫兹目标直接判死刑。不要指望综合器把行波“自动”变成前缀树——它有时会,有时不敢,因为面积和布线拥塞。
破壁的三条经典路:
| 结构 | 深度直觉 | 代价 | 我何时用 |
|---|---|---|---|
| 行波 | 随位宽线性 | 面积小、路径长 | 低频、窄位宽、非关键 |
| 超前 | 组内并行 | 扇出与布线 | 中等位宽 |
| 选择 | 两套和 | 面积明显 | 已有空面积、路径差一口气 |
| 前缀树 | 对数深度 | 布线密集 | 宽位宽、频率紧 |
乘法更狠。部分积阵列是一堆加法。Booth 编码把连续的 1 压缩,减少部分积层数,原文把它说成 64 位乘法器里能效的分水岭,并不夸张:少一层压缩树,就少一层进位与翻转。华莱士树或达达树继续压高度,换来不规则布线。DSP 风格的乘加若每拍都做,就该在规格阶段决定流水级数,而不是综合报违例后再塞寄存器——那是重定时能做的事,但重定时改不了你算法上必须一拍看到的组合跨度。
概念结构:
操作数A/B → 部分积生成 → 压缩树 → 最终加法 → 结果 ↑ Booth编码减少层数
⚠️ 常见坑:在 RTL 里写
y = a * b + c;然后给综合一个不可能的周期。工具会堆超大组合云,STA 报出跨过半个芯片的路径。先切拍,再谈单元尺寸。
💡 关键直觉:算术优化的本质是缩短进位的因果链,不是把乘法写成更“高级”的运算符。
组合块必须完整:每个输出在所有分支有值。优先用连续赋值描述浅逻辑;深逻辑用 case 并写默认。位宽显式化,避免隐式截断把符号位吃掉——仿真用 32 位中间量碰巧对,综合按你写的 16 位截断。
资源共享要自己想清楚。两个乘加若互斥,可以用选择器共用一台乘法器,省面积,加一级 MUX 延迟。综合器有时会共享,有时不会,因为它怕时序。关键路径上的乘加我倾向不共享;配置通路上的除法可以共享甚至做成多拍迭代。
比较器不要用减法看符号位还兼做算术,除非你真的需要差。独立比较器往往更易被映射到专用单元。优先级编码器是隐藏的长链:从位 0 找到第一个 1,深度随宽度走。高优先级仲裁若在关键路径上,考虑分两拍或用前缀式查找。
静态时序不理解“这个操作数这拍不变”。活动因子在功耗里重要,在建立检查里,所有输入都被当成可能同时翻转。你要减少虚假关键路径,用约束标假路径,而不是在组合里写注释“此输入很少变”。
原文还提到 AOI 复合门:a & b | c 可能映射成一级 AOI21,而不是 AND 再 OR。这对延迟有好处,前提是你的布尔式不要被人为拆成带寄存器的两拍——那是另一份契约。前端能做的是保持表达式扁平、减少无意义的中间变量层次,让映射器看见完整云团。
几乎不要。标准单元库的驱动强度、多阈值、布局抽象是为 RTL 映射准备的。手写门级在 DFT 插入、形式等价、ECO 时都会变成孤岛。只在库没有的特殊单元或全定制数据通路里才下到晶体管。
切在进位链或压缩树自然分层的地方,让每拍组合延迟大致均匀。不要切在已经很浅的 MUX 上还把寄存器插进拥塞区。重定时可以微移寄存器,但规格级的拍数仍然要人定。
进位深度决定拍数,拍数决定接口。若规格写“一拍 64 位加”,你就是在买前缀树或选择加法器的面积。若可以两拍,行波加一级寄存器也可能过时序,面积和布线都会更顺。不要把这一笔藏在综合脚本的努力里。
饱和与溢出策略属于组合契约。DSP 风格的截断、饱和到最大正数、还是包绕,必须与算法位宽一致。仿真用 32 位整数碰巧不溢出,综合按 16 位包绕,对拍会在边角激励才炸。把溢出属性写成断言:合法输入不得溢出,或溢出必须置位标志。
比较链和优先仲裁常被当成“控制,不是算术”,却经常成为关键路径。找第一个 1 的深度随宽度走,和行波进位是同一类因果。宽向量的优先编码要按前缀或分拍做。仲裁若在数据通路上,输出选通建议再打一拍,把米利型变成摩尔型,毛刺少、STA 也好看。
资源共享用互斥证明说话。两个乘法器从未同时使能,才能共用。互斥要用覆盖率或形式属性盯住。靠注释说“不会同时”的共享,会在偶然同时时把两条路径的延迟叠到同一台乘法器上,功能与时序一起坏。
组合云的功能对了,仍可能在周期中途多次翻转。STA 不惩罚这些中间翻转,功耗和 SI 惩罚。平衡路径、减少深优先级、避免用异或链当使能,是为了少交活动因子的税。综合后看翻转报告,若某片云活动异常高,回到表达式看是不是有互斥项没写成默认零。
算术通路的符号扩展和饱和要在组合边界显式完成,不要靠“多留几位中间量碰运气”。形式属性可以证明:合法输入下溢出标志与规格一致。证明过的位宽,综合才敢用无关项压缩;没证明,优化器一压缩,边角激励就错。
把加法器拓扑选择写进设计记录:为何前缀而不是两拍行波。后人改频率时才知道那是规格决策还是偶然综合结果。没有记录的拓扑,会被下一次综合启发式改掉,时序突然变脸。
设计记录用三行:位宽、周期预算、选择的加法或乘法结构。后人改频率时先读这三行,再决定是换前缀还是加拍。没有记录,综合启发式一变,芯片就换了一张算术脸。形式属性锁定位宽与溢出,比注释抗衰老。毛刺高的云在功耗预估里单独点名,避免只在 STA 里当它不存在。
进位链的选择一旦写进记录,综合脚本就不要再偷偷换结构,除非记录同时改。偷偷换的结果是面积和时序同时漂,却没有人知道漂的原因。优先编码器与仲裁深度按位宽评估,和控制通路的“看起来很浅”脱钩。看起来浅的 case 可能是长链。资源共享必须有互斥属性,覆盖率要打到互斥成立。毛刺高的云在功耗预估里单独列名,让第4章知道 STA 看不见的税。算术节的出门证是:关键加法或乘法的拍数、拓扑、溢出策略三行都能被陌生人读懂。读不懂的三行,等于还没设计完。
资源共享若发生在进位链中段,MUX 延迟会叠进本已最长的路径。共享只允许发生在拍与拍之间的边界,而不是在前缀树肚子里。评审看到共享符号,先问插在哪一级寄存之后。
下一节处理时间契约本身:锁存与触发器、复位释放、FSM 编码,这些决定 STA 检查的是哪一种边沿世界。