无符号二进制乘法---ChatGPT 5 thinking作答
下面把“无符号二进制乘法”的核心原理、典型硬件结构、时序与精度问题一次讲清,便于你画门级电路或在 HDL 中落地。
1. 数学与位宽
-
若 AAA 为 n 位、BBB 为 m 位无符号数,则乘积 P=A×BP=A\times BP=A×B 的精确位宽为 n+mn+mn+m 位,取值范围 [0, (2n−1)(2m−1)][0,\; (2^n-1)(2^m-1)][0,(2n−1)(2m−1)]。
-
二进制乘法实质就是**部分积(partial products)**的加权求和:
P=∑i=0m−1bi (A≪i),bi∈{0,1} P=\sum_{i=0}^{m-1} b_i \,(A\ll i),\quad b_i\in\{0,1\} P=i=0∑m−1bi(A≪i),bi∈{0,1}
乘数 BBB 的每一位 bib_ibi 要么“选择”加上 (A≪i)(A\ll i)(A≪i),要么加 0。
2. 逐位“移位-加法”乘法器(顺序型)
最基础、面积最省的一类(常用于微控制器或低功耗设计):
思路
- 准备寄存器:
A_reg(被乘数)、B_reg(乘数)、P_acc(2n 位累加器)。 - 循环 m 次:如果
B_reg[0]==1,则P_acc += A_reg;随后A_reg <<= 1,B_reg >>= 1。 - 循环结束,
P_acc即为乘积。
特点
- 面积小:用到一个 n 位加法器和若干寄存器。
- 延时/吞吐:需要 m 个时钟(或基于更高基数的 recoding 为 ⌈m/r⌉\lceil m/r\rceil⌈m/r⌉ 个时钟)。
- 变种:基-4(每拍处理 2 位)或基-8(每拍 3 位)可减少循环次数;对无符号可用“0/1/2/3 倍 A”的多路选择器替代多次加法。
3. 并行“阵列(Braun)乘法器”(组合逻辑)
更快、经典易综合的并行结构,适合中小位宽固定乘法。
结构
- 部分积产生:所有 pi,j=aj∧bip_{i,j} = a_j \land b_ipi,j=aj∧bi(与门阵列)。这形成一个“位阵列”,第 i 行整体左移 i 位。
- 阵列求和:用半加器(HA)与全加器(FA)按列把每一列的多比特相加并把进位传到更高列;最后用一条加法器得到 PPP。
优缺点
- 延时 O(n)\mathcal{O}(n)O(n)(进位在阵列中逐行/逐列传播),面积 O(nm)\mathcal{O}(nm)O(nm)。
- 规则、易布局布线;在 ASIC/FPGA 小到中等位宽时很实用。
- 关键名词:Braun array(专指无符号阵列乘法器)。
4. 树形乘法器(Wallace / Dadda / 压缩树)
为高性能而设计:尽量减少“列高度”,把多个部分积用**进位保存加法器(CSA, 3:2)**或 4:2 压缩器分层压缩,最终只剩两行,再用一次快加法器(CLA/前缀加法器)出结果。
流程
- 生成所有部分积位 pi,jp_{i,j}pi,j。
- 压缩树:反复用 3:2/4:2 压缩器把每列的位数降低,层数约 O(logn)\mathcal{O}(\log n)O(logn)。
- 终结加法:把得到的两行用一个快速加法器求和。
特点
- 延时约 O(logn)\mathcal{O}(\log n)O(logn),对大位宽远快于阵列。
- 面积与布线较复杂;Dadda 相对 Wallace 在门数更省但层数略多。
- 常与前缀加法器(Kogge–Stone、Brent–Kung 等)配合。
5. 示例(4×4)
以 A=10012(=9), B=10112(=11)A=1001_2(=9),\; B=1011_2(=11)A=10012(=9),B=10112(=11):
- 行 0(b0=1b_0=1b0=1):
1001 - 行 1(b1=1b_1=1b1=1,左移 1):
10010 - 行 2(b2=0b_2=0b2=0):
00000 - 行 3(b3=1b_3=1b3=1,左移 3):
1001000 - 求和:
00001001 + 00010010 + 00000000 + 01001000 = 01100011
结果01100011₂ = 99₁₀,与 9×119\times 119×11 一致。
(阵列乘法器把上面 4 行并行生成,并在阵列/树中完成求和。)
6. 速度与面积的权衡
- 顺序型:面积最小、功耗低;时延 m 拍(或 ⌈m/r⌉\lceil m/r\rceil⌈m/r⌉ 拍)。适合低成本 MCU、低功耗 IP。
- 阵列型:一次组合运算,时延 ∝n\propto n∝n,布线简单。中等速度。
- 树型:速度最快(logn\log nlogn 层),但门数与布线复杂度更高;适合高性能 CPU、DSP、GPU。
- 流水线:在阵列或树的中间插入寄存器,提升最高频率;代价是额外面积和延迟(多拍)。
7. 与“符号乘法”的关系
-
本题是无符号。若要支持有符号(补码),常见做法是:
- 保持无符号部分积生成,但对被乘数/乘数做符号扩展与Booth 重编码(radix-4/8),减少部分积个数;最后仍用压缩树 + 终结加法。
- 纯无符号场景不必引入 Booth,但也可以用“补 0 前导位”的 modified Booth 来减少部分积。
8. 乘累加(MAC)与 4:2 压缩器
在滤波/卷积中常见 MAC:ACC := ACC + A*B。硬件里会把“先前累加值的两行”连同新的部分积一起进入压缩树,用 3:2/4:2 压缩器把行数继续压缩,避免每次都做“完整乘法再另行加法”,这就是乘法器—累加器融合的关键。
9. 固定小数(定点)与截断/舍入
若 AAA 为 QIA.FAI_A.F_AIA.FA、BBB 为 QIB.FBI_B.F_BIB.FB,则乘积是 Q(IA+IB).(FA+FB)(I_A+I_B).(F_A+F_B)(IA+IB).(FA+FB)。若需要回到原小数位:
- 右移 FA+FB−FoutF_A+F_B-F_{out}FA+FB−Fout 位;为降低误差,右移前可加 0.5 ULP(即在舍入位上加 1)。
- 若只保留低 n 位(例如仅输出低半部),上半部非零即溢出(对无符号语义)。
10. HDL 实现要点(要落地可直接抄用)
(1) 最简单推导型:综合器/FPGA 会自动用 DSP 块或高效乘法器替换
module mul_unsigned #(parameter N=16, M=16) (
input [N-1:0] A,
input [M-1:0] B,
output [N+M-1:0] P
);
assign P = A * B; // 让综合器推断乘法器/DSP
endmodule
(2) 逐位移位-加法(顺序型)
module mul_shift_add #(parameter N=16, M=16) (
input clk, start,
input [N-1:0] A,
input [M-1:0] B,
output reg [N+M-1:0] P,
output reg done
);
reg [N-1:0] a_reg;
reg [M-1:0] b_reg;
reg [$clog2(M):0] cnt;
always @(posedge clk) begin
if (start) begin
P <= 0;
a_reg <= A;
b_reg <= B;
cnt <= 0;
done <= 1'b0;
end else if (!done) begin
if (b_reg[0]) P <= P + {{M{1'b0}}, a_reg}; // 对齐到低位
a_reg <= a_reg << 1;
b_reg <= b_reg >> 1;
cnt <= cnt + 1;
if (cnt == M-1) done <= 1'b1;
end
end
endmodule
(3) 阵列乘法器(部分积 + 栈式求和)——结构化写法思路
- 生成
pp[i][j] = A[j] & B[i] - 把第 i 行整体左移 i 位后,用 HA/FA 逐列相加;或直接用CSA 树先压到两行,再一次加法器终结。
(如需,我可以给出 8×8 或 16×16 的门级网表/可综合生成器。)
11. 常见坑
- 输出位宽不够:n×m 必须给 n+mn+mn+m 位输出,否则上位被截断;若只保留低 n 位需显式处理溢出。
- 固定小数对齐:忘了右移与舍入,会导致系统性缩放误差。
- 时序路径过长:并行乘法器在大位宽下需要前缀加法器/压缩树或流水线,否则过不了时钟约束。
- FPGA 上乱用门级阵列:大多数 FPGA 里
*会自动映射到 DSP48 等硬块,速度/面积/功耗更优。
更多推荐


所有评论(0)