当前位置: 首页 > 工具软件 > Wallace > 使用案例 >

Booth压缩+华莱士树Wallace乘法器的通俗理解

辛健
2023-12-01

1.Booth压缩

目的: 减少乘法器的加法次数
原理: 0111_1100 = (1000_0000 - 0000_0100) 因( 0000_0100 + 0111_1100 = 1000_0000)
^^^ ^^(5个1) = ^ ^(2个1)
M ∗ ( 2 7 + 2 6 + 2 5 + 2 4 + 2 3 ) = M ∗ ( 2 8 − 2 3 ) M*(2^7+2^6+2^5+2^4+2^3)=M*(2^8-2^3) M(27+26+25+24+23)=M(2823)
压缩原则:

01为0111…110段开始, 对应+1

10为0111…110段结束, 对应-1

11为0111…110段中间部分, 对应0

00为0111…110段以外部分, 对应0

2.华莱士树

2.1 概述

简单讲就是, 乘法先看作加法, 就是咱们计算乘法 时候的乘数a与乘数b的每一位相乘, 再相加. 然后把所有要加的数分组, 得到和sum, 还有进位, 然后再把得到的sum和进位一继续与之前没加完的数继续加, 直到只剩两个数, 直接相加得到结果.

目的: (<->传统加法器: 串行, 一次移一位, 慢) 并行, 快

原理: 进位保存加法器(<->全加器: 串行, 一次一位, 利用上位和求现在位) 输入:3位, 输出:2位(和,进位)

​ 并行加法器: 输入:2位, 输出1位(和)

​ 两乘数[size:1], 则乘积[2 * size:1] 因([size:1]的数<2^size①, (2^size) * (2size)<2(2 * size), 即乘积<2^(2 * size),由①: [2 * size:1]可表示乘积)

步骤:

  1. (输入)3位一组->(输出)2位

  2. (输入)3位一组(↑2位+1位)->(输出)2位

  3. 重复2, 直至仅剩2位

  4. (输入)↑2位->(输出)1位

2.2 例示

例1: n=10

10位为1,需相加, 假设进位保存加法器个数无穷大, 每次都可分得(现存位数/3)个组

  1. (输入)3位一组分得3组(3=10/3)->(输出)3组每组少1位, 现存7位(10-3*(3-2)=7)

  2. (输入)3位一组分得2组(2=7/3)->(输出)2组每组少1位, 现存5位(7-2*(3-2)=5)

  3. (输入)3位一组分得1组(1=5/3)->(输出)1组每组少1位, 现存4位(5-1*(3-2)=4)

  4. (输入)3位一组分得1组(1=4/3)->(输出)1组每组少1位, 现存3位(4-1*(3-2)=3)

  5. (输入)3位一组分得1组(1=3/3)->(输出)1组每组少1位, 现存2位(3-1*(3-2)=2)

  6. 仅剩2位: (输入)2位并行加法->(输出)1位

    至此6个单位时间<->传统移位加法器10位相加需10单位时间

例2: n=100

// 简单c语言计算n位加法(华莱士树)次数
int WallaceAddTimes(int n)
{
    int times = 0;
    while (n>2)
    {
        n = n - n/3;
        ++times;
    }
    // ==2时跳出,并行加法器运算
    return times+1;
}
int main()
{
	cout << "100 bits adding in Wallace Tree: times = " //12
         << WallaceAddTimes(100) << endl;
    return 0;
}

大大加快运算速度! (前提, 可同时并行n/3个进位保存加法器)

3.小结

Booth压缩: ↓加法位数(负数补码同样可行)

华莱士树: ↓加法次数(并行)

二者加持, 如有神助 --> 高速加法器

对于verilog实现的传统移位乘法器可以不采用了qwq(虽然反对你, 但允许你的存在, 所以我在这里写一遍你)

module multiplier(
    a,
    b,
    result
);
parameter size = 8;
input [size:1] a,b;
output [2 * size:1] result;

reg [2 * size:1] shift_a, result;
reg [size:1] shift_b;

always @(a or b) begin
    shift_a = a;
    shift_b = b;
    result = 0;
    repeat(size) begin
        if(shift_b[1]) result = result + shift_a;
        shift_a = shift_a << 1;
        shift_b = shift_b >> 1;
    end
end
endmodule
 类似资料: