
乘法是一项基本的算术运算,但在高性能硬件中实现它却是一项复杂的挑战,远非简单的纸笔计算可比。每秒执行数十亿次运算的需求暴露了基本算法的局限性,在数学理论与实际的芯片设计之间造成了关键的鸿沟。本文将深入探讨硬件乘法器设计的领域,揭示使现代计算成为可能的巧妙权衡和架构创新。在“原理与机制”部分,我们将解构乘法器的构建模块,从基本的位移操作到如阵列乘法器和 Wallace 树乘法器等复杂的并行结构,并探讨如 Booth 算法和 Baugh-Wooley 算法等优化方法。随后,“应用与跨学科联系”部分将展示这些设计如何在数字信号处理和密码学等领域发挥关键作用,突显在速度、面积和功耗之间不断进行的工程平衡。我们首先从将简单的乘法行为转变为高速工程壮举的核心原理开始。
乘法。乍一看,这似乎是个已解决的问题。我们在学校都学过这个方法:将数字一个写在另一个上面,逐位相乘得到一系列移位的行,然后费力地将它们全部相加。这是一种可靠的算法,一种令人安心的惯例。但当你需要构建一个每秒执行数十亿次这类运算的硬件时,那种令人安心的惯例就变成了一场艰苦的马拉松。硬件乘法器设计的世界是一段引人入胜的旅程,它探索我们如何将这种小学算法转变为具有惊人速度和效率的东西。这是一个关于用新视角审视熟悉问题,并在我们为解决它而使用的巧妙技巧中发现美的故事。
让我们从最简单的情况开始。如果你想将一个数乘以二,该怎么办?在我们熟悉的十进制系统中,乘以十毫不费力:你只需在末尾添上一个零。数字 53 变成 530。用二进制(基数为2)思考的计算机也有类似的技巧。要将一个二进制数乘以二,你只需将其所有位向左移动一个位置,并在右侧的空位上填一个零。要乘以四(),你移动两个位置。要乘以十六(),你移动四个位置。
想象一个电路,其任务是将任意 8 位数乘以 16。它需要一个复杂的逻辑门和加法器阵列吗?完全不需要。最高效的设计根本不需要任何计算。它只由导线组成!输入位 直接连接到输出引脚 ,输入 连接到输出 ,依此类推。四个最低有效输出位, 到 ,被连接到一个恒定的“0”。就是这样。你以光速(或者至少是电流通过导线的速度)完成了乘法,并且逻辑开销为零。这是效率的柏拉图式理想——乘法仅仅是一种简单的重新布线行为。它树立了一个优美的基准,所有其他更复杂的方法都必须以此为衡量标准。
当然,我们不能总是幸运地乘以 2 的幂。当我们需要将两个任意数字(比如 和 )相乘时,会发生什么?让我们回到课本上的方法。第一步是生成中间行,在二进制世界中,这被称为部分积(partial products)。对于两个 位数,我们生成 行部分积。这些行中的每一位都是 的一位和 的一位之间进行简单逻辑与(AND)运算的结果。例如,在一个 的乘法中,部分积位 就是 。然后根据这些位的位值(或权重)将它们组织成列。位 的权重为 ,因此所有索引之和 相同的位都属于同一列。
在硬件中最直接的实现方式是创建一个模仿纸笔方法的结构:阵列乘法器。它是一个由简单加法器电路组成的网格。每个加法器接收一个部分积位、其上方加法器的和,以及其右上方加法器的进位,然后产生一个新的和与一个新的进位。逻辑沿对角线向下流经整个阵列,很像我们手动计算进位的方式。
这种设计非常规整,易于在硅芯片上形成图案。但它有一个致命的缺陷:其速度受到可怕的进位传播(carry propagation)的限制。最高有效位位置的最终结果,要等到一个进位信号可能从最低有效位开始,“涟漪”般地沿对角线穿过整个阵列后才能就绪。这会产生一个随数字大小线性增长的延迟。
这引出了数字设计中的一个基本权衡。我们可以构建这个大型的组合电路(阵列乘法器),它一次性计算出答案,但存在很长的传播延迟。或者,我们可以使用时序电路。一个时序设计可能只使用一个加法器,并在多个时钟周期内重复使用它,每次将一个部分积加到一个累加寄存器中。这节省了大量的硬件(芯片面积),但速度却大大降低,因为总时间现在是周期数乘以时钟周期。这是经典的工程选择:你想要一辆能让你瞬间到达的庞大跑车,还是一辆慢悠悠但紧凑省油的踏板车?对于高性能计算来说,踏板车是不行的。我们需要速度,但必须找到一种方法来摆脱进位链的束缚。
阵列乘法器的瓶颈在于它坚持在处理下一行之前完全加完当前行。进位传播是问题所在。那么,如果我们……不这么做呢?如果我们能把进位问题推迟处理呢?这就是Wallace 树乘法器背后的绝妙见解。
Wallace 树不采用刚性网格,而是逐列看待问题。在我们部分积矩阵中任取一列,它就是一堆需要相加的位。一个全加器(FA)是一个简单的电路,它接收三个输入位,并产生一个两位的输出:一个和位和一个进位位。注意刚刚发生了什么:我们输入 3 个位,得到了 2 个位。我们压缩了信息!关键在于,和位与输入位具有相同的权重(它留在同一列),而进位位具有下一个更高的权重(它向左移动一列)。
因此,Wallace 树的策略是:在每一列中,尽可能多地取位,并将它们三个一组。将每组三个位送入一个全加器。如果剩下两个位,就使用一个半加器(HA),它是一个 2 输入、2 输出的压缩器。如果只剩一个位,就直接传递到下一级。例如,如果一列开始有 5 个位,我们可以使用一个全加器(处理三个位)和一个半加器(处理剩下的两个位),从而将该列的 5 个位减少到下一级的仅 2 个和位(外加两个被送到下一列的进位位)。
我们在所有列上同时并行地应用这个过程。在第一级,我们可能会将给定列中高达(比如说)11 位的矩阵减少到只有 5 位(三个来自全加器的和输出,还有两个剩余)。在下一级,这 5 位变成 3 位。再下一级,3 位变成 1 位。矩阵的高度在每一级都急剧缩小。我们不仅可以从列的角度思考,也可以从部分积行的角度思考。一层全加器可以将 3 行压缩成 2 行(一个和行和一个进位行)。因此,如果我们从 6 个部分积行开始,第一级规约后我们会剩下 4 行。
这种“分而治之”的规约过程持续进行,直到只剩下两行:一个最终的“和”行和一个最终的“进位”行。这种方法的优美之处在于其速度。规约级的数量不是线性增长,而是随位数对数增长。这是一个巨大的速度提升。我们付出的代价是结构上的优雅。因为第 列中加法器的进位输出必须连接到下一级第 列中加法器的输入,这些连接变成了一张非均匀布线的网。这使得 Wallace 树在芯片设计者中以“不规则”或“非结构化”著称,与阵列乘法器的整齐网格相比。这是以物理布局的规整性换取纯粹、原始速度的权衡。
Wallace 树通过推迟处理进位传播问题来施展其魔法。树中使用的电路是一种进位保留加法器(CSA),之所以如此命名,是因为它们将进位位“保留”到一个单独的向量中,而不是立即传播它们。在所有规约阶段之后,我们剩下两个数,它们的和就是最终答案。
但现在我们面临着关键时刻。我们不能再推迟进位了。我们需要一个单一、确定的二进制数作为我们的乘积。如果我们将最终的两个向量输入到另一个进位保留加法器中,我们只会得到另一对和向量与进位向量。我们只是在无限期地拖延问题。
对于这最后一步,我们无处可逃:我们必须执行一次带有完全进位传播的真正加法。这需要一种不同类型的加法器,即进位传播加法器(CPA)。幸运的是,因为我们只需要相加两个数,我们可以使用非常快速、专门的 CPA 设计(如超前进位加法器),其延迟问题远小于处理整个初始矩阵时的延迟。Wallace 树的工作是完成繁重的任务,将堆积如山的部分积减少到两个数的“小山丘”。而 CPA 的工作是执行最后、干净的求和。
到目前为止,我们的策略是生成所有的部分积,然后尽快将它们相加。但如果我们可以更聪明一些,从一开始就减少需要生成的部分积的数量呢?这就是 Booth 算法的天才之处。
考虑将一个数乘以 63。在 8 位二进制中,63 是 00111111。一个朴素的乘法需要生成并相加对应于那一长串 1 的六个部分积。但我们知道 。在二进制中,这是 。那么,我们能否用一次加法(对于 项)和一次减法(对于 项)来代替六次加法呢?
是的!Booth 算法是实现这一点的系统方法。它通过查看相邻的位对来重新编码乘数。一串 1,比如 ...0111...,以一个 01 转换开始(表示块的开始,一个“减”操作),并以一个 10 转换结束(表示块的结束,一个“加”操作)。在中间,11 对意味着“什么也不做”。通过应用这个规则,63 的二进制数 00111111 被重新编码为 Booth 表示 0+100000-1(其中 +1 表示加,-1 表示减)。我们用两个操作替换了六个操作。
这不仅仅是一个数学上的奇思妙想;它有直接的硬件优势。更少的加法和减法意味着时序乘法器中更少的时钟周期,或并行乘法器中选择和求和部分积所需的硬件更少。当乘以两个数时,我们甚至可以有策略地选择那个 1 的块较少的数作为“乘数”,从而进一步提高效率。这是一个优美的算法优化,它在我们开始加法之前就减少了工作量。
还有一个最后的复杂问题:负数。计算机通常使用二的补码(two's complement)表示法来表示有符号数。在这个系统中,最高有效位具有负权重。使用我们讨论过的方法进行朴素的乘法将产生不正确的结果,因为它没有考虑这些负权重。
人们可以构建特殊的硬件来处理由此产生的减法,但有一个更优雅的解决方案:Baugh-Wooley 算法。这是对二的补码乘法公式的一个巧妙的数学重排。其目标是创建一个所有项都为正的部分积矩阵。它通过选择性地反转一些部分积位,并在特定列中添加一些校正常量来实现这一目标。
结果纯粹是魔法。我们从一个棘手的有符号乘法问题开始,通过在部分积生成阶段进行简单的变换,将其转换为一个无符号加法问题。由此产生的正数位矩阵可以直接输入到我们为无符号数设计的高速 Wallace 树架构中。这种统一是伟大工程设计的标志——我们不是为两个不同的问题建造两台不同的机器,而是找到一种巧妙的方法,让两个问题在同一台非常高效的机器看来是相同的。
从有线移位的简单优雅,到 Wallace 树复杂、不规则的美,再到 Booth 和 Baugh-Wooley 算法的巧妙,硬件乘法器的设计是计算机体系结构的缩影。这是一个关于权衡、在并行中寻求速度、以及数学变换将难题简化的力量的故事。它揭示了即使在最基本的操作中,也存在着巨大的创造力和深刻的洞察力空间。
现在我们已经拆解了硬件乘法器的内部机制,以加法器、移位器和逻辑门的形式审视了它的齿轮和弹簧,是时候退后一步,欣赏这些成品机器在其自然栖息地中的风采了。这些复杂的设计究竟存在于何处?它们解决了什么问题?你可能会惊讶地发现,乘法器设计的原理并不仅限于中央处理器的算术单元。它们的回响贯穿于众多领域,从承载我们声音跨越全球的信号,到保护我们信息的加密秘钥。对硬件乘法器的研究,本质上是对工程中基本权衡的研究:速度、尺寸和功耗之间永恒的拉锯战。
也许乘法器设计最令人惊讶的应用是学会如何完全避免乘法。一个通用的乘法器,能够接收任意两个数并得出它们的乘积,是一个庞大且耗电的“怪兽”。但很多时候,我们并不需要如此强大的工具。在数字系统中,一个常见的任务是将一个变量乘以一个固定的、已知的常数。何必杀鸡用牛刀呢?
假设我们需要将一个数(我们称之为 )乘以常数 13。稍加思索就会发现 。在二进制的世界里,这便是 。对于数字电路来说,乘以 2 的幂是世界上最简单的事情——它只是一个位移操作。乘以 就是向左移动 3 位。所以,要计算 ,我们根本不需要乘法器!我们可以简单地计算 。我们用两次移位和两次加法替换了一次复杂的乘法——这些操作在硅片面积和功耗方面要便宜得多。这种“强度折减”是优化编译器和硬件综合工具的基石。
这个简单的技巧是数字信号处理(DSP)中一种更强大技术——无乘法器设计——的基础。在许多应用中,如音频和视频滤波,滤波器的行为由一组常数系数定义。通过用特殊形式(如规范有符号数位(CSD)格式)表示这些系数,我们可以最大限度地减少实现一次乘法所需的加法和减法次数。CSD 表示法允许使用正和负的 2 的幂,所以像 这样的数,只需一次减法即可实现,而不是三次加法()。这种巧妙的算术是设计高效、低功耗 DSP 电路的核心。
在任何领域中,乘法器的重要性都无法与数字信号处理(DSP)领域相比。绝大多数 DSP 算法,从清除嘈杂音频的滤波器到压缩视频文件的算法,都从根本上基于一个操作:乘法累加(MAC)。一串数据流输入,每个样本与一个系数相乘,然后将结果累加起来。处理器执行此 MAC 操作的速度决定了系统的性能。
考虑一个数字滤波器的设计。滤波器用于选择性地移除或增强信号中的某些频率。滤波器的数学配方涉及卷积,即一系列的乘法和加法。实现这一点的硬件可能包括一个乘法器核心、一个用于偏移的加法器,以及防止失控值的饱和逻辑——这是一个小型的、专门的数据路径,其中乘法器是主角。
数字滤波器的两个主要家族,有限脉冲响应(FIR)和无限脉冲响应(IIR),代表了一个围绕乘法器的经典设计选择。FIR 滤波器在概念上简单且固有稳定,但它们通常需要为每个输出样本进行大量的乘法运算。对于一个频率截止非常陡峭的滤波器,所需的乘法次数可能变得非常巨大。另一方面,IIR 滤波器使用反馈,可以用少得多的乘法实现同样陡峭的截止。然而,这种效率是有代价的:它们对系数的精度更敏感,微小的误差可能导致不稳定。在 FIR 和 IIR 之间的选择是一个系统级决策,关乎是使用许多简单、稳健的乘法,还是使用少数复杂、敏感的乘法。
信号处理领域的皇冠明珠之一是快速傅里叶变换(FFT),一种揭示信号频谱的算法。它通过大幅减少与直接方法相比所需的计算量,改变了信号处理。一个硬件 FFT 引擎是并行计算的奇迹,其设计是调度艺术的大师课。核心操作涉及将数据样本与称为“旋转因子”的复数相乘。一个实时系统,如雷达或无线通信基站,有着源源不断的数据流。设计者必须计算出需要多少个物理乘法器单元,以及如何流水线化操作以跟上这数据“消防水龙带”。整个系统的吞吐量受限于乘法器的数量以及它们可以运行的时钟速度。
我们已经讨论了速度,但成本呢?这就引出了所有硬件设计中最根本的权衡。如果你想快速计算某样东西,通常必须投入更多的硬件,这会花费更多的硅片面积和消耗更多的功率。乘法是这一原则的典型例子。
想象一下你想构建一个乘法器。最简单的方法,类似于我们在小学学习的方式,是时序的移位-相加算法。这需要很少的硬件:一个加法器,几个寄存器和一些控制逻辑。但它很慢——乘数的每一位都需要一个时钟周期。对于 64 位乘法,这意味着 64 个周期。
如果你需要立刻得到答案呢?为此,你需要一个组合乘法器,一个巨大的逻辑门海洋,它接收输入并在一次令人窒息的传递中产生完整的乘积。例如,一个阵列乘法器将部分积排列成一个网格,并使用一个二维的加法器阵列来求和。它快得多,但其尺寸随位数以平方级增长,。对于大数来说,这变得极其昂贵。
有中间地带吗?有,而且非常优美。Wallace 树乘法器是数字设计中最优雅的结构之一。它不是在一个长而慢的链条中逐对相加 个部分积,而是使用一个“进位保留加法器”网络来一次相加三个。把它想象成一个锦标赛的淘汰赛支架。在每一轮中,你将操作数的数量从 减少到大约 。这种减少在整个结构中并行发生。轮数随 的对数增长,使其速度极快。Wallace 树出色地展示了并行性如何克服延迟,用一个规则、简单的结构(阵列)换取一个更复杂、不规则但快得多的结构。
到目前为止,我们一直假设乘法的含义就是我们一直以来所认为的那样。但在许多高级应用中,算术的规则本身都发生了变化。
在密码学和纠错编码中,计算通常在一个称为伽罗瓦域(Galois Field)或有限域的数学结构中进行。在域 中,元素可以被看作是系数仅为 0 或 1 的多项式。在这里,“加法”只是异或(XOR)操作。“乘法”则要奇怪得多:你首先像平常一样乘多项式(用 XOR 进行加法),然后求除以一个特殊的、固定的“不可约多项式”后的余数。这可不是你日常的乘法!一个伽罗瓦域的硬件乘法器不是由标准加法器构成的,而是由一个与门(AND,用于系数乘法)和异或门(XOR,用于系数加法和最终的规约步骤)网络构成的。这些专门的乘法器是 AES 算法(保护你的在线交易)和里德-所罗门码(让你的蓝光光盘即使被刮伤也能完美播放)等算法的核心。
最后,我们必须面对我们的数字世界是有限的这一现实。当我们乘以两个 位数时,真实结果最多可以有 位。但如果我们的处理器的寄存器和数据路径只有 位宽呢?我们被迫截断结果,丢掉最高有效位。这是一个危险的游戏。在某些情况下,截断后的结果,当被解释为有符号数时,可能与真实乘积大相径庭,甚至符号都可能是错的。对于为 DSP 和嵌入式系统编写正确的软件来说,精确理解这种“类溢出错误”何时发生至关重要,因为在这些系统中,每一位存储空间都非常宝贵。这一点,以及需要为不同的数字系统(如历史性的一的补码)调整像 Booth 这样的算法,提醒我们算法并非抽象的柏拉图式理想;它们与其在硬件中的物理表示深度交织在一起。一个真正稳健的系统需要对这种联系有深刻的理解。
从最基础的移位-相加优化到有限域令人费解的算术,硬件乘法器是数字设计的缩影。它是数学的优雅与物理约束相遇的地方,也是算法的抽象之美被锻造成硅的地方。对完美乘法器的追求,在许多方面,就是对计算本身的追求。