手搓4/8位Wallace树乘法器

1. Wallace树乘法器原理

        使用华莱士树构建方法:此方法的基本原理是采用进位保存加法器(CSA)将参与运算的三个数变成两个数输出,从而减少一个相加数,通过这种方法可以对图1中同一列(p)的部分积进行化简,化简的结果是最后每个位数的S构成一个加数,每个位数的进位C构成另外一个加数,将S和C通过高性能加法器相加即可求得结果。图2为4位华莱士树乘法器结构。

        8位与4位华莱士树乘法器构建方法相同,通过3-2压缩器分级压缩,压缩到最终剩两个树,最终相加。

2. 推导过程

        首先推导部分积相乘结果,对部分积进行编号,以方便后续计算,从右上至坐下分别编号,并转化位树型。

对部分积编号

根据编号生成部分积向量代码为 

    // 生成部分积
    assign a = {	x[7],
			x[6], x[7],
			x[5], x[6], x[7],
			x[4], x[5], x[6], x[7], 
			x[3], x[4], x[5], x[6], x[7], 
			x[2], x[3], x[4], x[5], x[6], x[7], 
			x[1], x[2], x[3], x[4], x[5], x[6], x[7], 
			x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
			x[0], x[1], x[2], x[3], x[4], x[5], x[6], 
			x[0], x[1], x[2], x[3], x[4], x[5], 
			x[0], x[1], x[2], x[3], x[4], 
			x[0], x[1], x[2], x[3], 
			x[0], x[1], x[2], 
			x[0], x[1], 
			x[0]} & 
               {	y[7], 
			y[7], y[6], 
			y[7], y[6], y[5], 
			y[7], y[6], y[5], y[4], 
			y[7], y[6], y[5], y[4], y[3], 
			y[7], y[6], y[5], y[4], y[3], y[2], 
			y[7], y[6], y[5], y[4], y[3], y[2], y[1], 
			y[7], y[6], y[5], y[4], y[3], y[2], y[1], y[0], 
			y[6], y[5], y[4], y[3], y[2], y[1], y[0], 
			y[5], y[4], y[3], y[2], y[1], y[0], 
			y[4], y[3], y[2], y[1], y[0], 
			y[3], y[2], y[1], y[0], 
			y[2], y[1], y[0], 
			y[1], y[0], 
			y[0]};

 随后完成逐级压缩,每级压缩过程如图所示

其中圈两个的使用半加器、三个的使用全加器

逐级压缩最后相乘代码为

    // 第一级
    hadd U1(.x(a[34]), .y(a[35]), .out(b0));  
    hadd U2(.x(a[41]), .y(a[42]), .out(b1));

    // 第二级	
    hadd U3(.x(a[26]), .y(a[27]), .out(c0));  
    fadd U4(.x(a[32]), .y(a[33]), .z(b0[0]), .out(c1));  
    fadd U5(.x(a[40]), .y(b1[0]), .z(b0[1]), .out(c2));  
    fadd U6(.x(a[47]), .y(a[48]), .z(b1[1]), .out(c3));

    // 第三级
    hadd U7(.x(a[19]), .y(a[20]), .out(d0));  
    fadd U8(.x(a[24]), .y(a[25]), .z(c0[0]), .out(d1));  
    fadd U9(.x(a[31]), .y(c1[0]), .z(c0[1]), .out(d2));  
    fadd U10(.x(a[39]), .y(c2[0]), .z(c1[1]), .out(d3));
    fadd U11(.x(a[46]), .y(c3[0]), .z(c2[1]), .out(d4));
    fadd U12(.x(a[52]), .y(a[53]), .z(c3[1]), .out(d5));

    // 第四级
    hadd U13(.x(a[13]), .y(a[14]), .out(e0));  
    fadd U14(.x(a[17]), .y(a[18]), .z(d0[0]), .out(e1));  
    fadd U15(.x(a[23]), .y(d1[0]), .z(d0[1]), .out(e2));  
    fadd U16(.x(a[30]), .y(d2[0]), .z(d1[1]), .out(e3));
    fadd U17(.x(a[38]), .y(d3[0]), .z(d2[1]), .out(e4));
    fadd U18(.x(a[45]), .y(d4[0]), .z(d3[1]), .out(e5));
    fadd U19(.x(a[51]), .y(d5[0]), .z(d4[1]), .out(e6));
    fadd U20(.x(a[56]), .y(a[57]), .z(d5[1]), .out(e7));

    // 第五级
    hadd U21(.x(a[8]), .y(a[9]), .out(f0));  
    fadd U22(.x(a[11]), .y(a[12]), .z(e0[0]), .out(f1));  
    fadd U23(.x(a[16]), .y(e1[0]), .z(e0[1]), .out(f2));  
    fadd U24(.x(a[22]), .y(e2[0]), .z(e1[1]), .out(f3));
    fadd U25(.x(a[29]), .y(e3[0]), .z(e2[1]), .out(f4));
    fadd U26(.x(a[37]), .y(e4[0]), .z(e3[1]), .out(f5));
    fadd U27(.x(a[44]), .y(e5[0]), .z(e4[1]), .out(f6));
    fadd U28(.x(a[50]), .y(e6[0]), .z(e5[1]), .out(f7));
    fadd U29(.x(a[55]), .y(e7[0]), .z(e6[1]), .out(f8));
    fadd U30(.x(a[59]), .y(a[60]), .z(e7[1]), .out(f9));

    // 第六级
    hadd U31(.x(a[4]), .y(a[5]), .out(g0));  
    fadd U32(.x(a[6]), .y(a[7]), .z(f0[0]), .out(g1));  
    fadd U33(.x(a[10]), .y(f1[0]), .z(f0[1]), .out(g2));  
    fadd U34(.x(a[15]), .y(f2[0]), .z(f1[1]), .out(g3));
    fadd U35(.x(a[21]), .y(f3[0]), .z(f2[1]), .out(g4));
    fadd U36(.x(a[28]), .y(f4[0]), .z(f3[1]), .out(g5));
    fadd U37(.x(a[36]), .y(f5[0]), .z(f4[1]), .out(g6));
    fadd U38(.x(a[43]), .y(f6[0]), .z(f5[1]), .out(g7));
    fadd U39(.x(a[49]), .y(f7[0]), .z(f6[1]), .out(g8));
    fadd U40(.x(a[54]), .y(f8[0]), .z(f7[1]), .out(g9));
    fadd U41(.x(a[58]), .y(f9[0]), .z(f8[1]), .out(g10));
    fadd U42(.x(a[61]), .y(a[62]), .z(f9[1]), .out(g11));

    //第七级
    assign add_a = {g11[1], g10[1], g9[1], g8[1], g7[1], g6[1], g5[1], g4[1], g3[1], g2[1], g1[1], g0[1], g0[0], a[2]}; 
    assign add_b = {a[63], g11[0], g10[0], g9[0], g8[0], g7[0], g6[0], g5[0], g4[0], g3[0], g2[0], g1[0], a[3], a[1]};
    assign add_out = add_a + add_b;

 3. 4/8位wallace树乘法器代码

最终,8位Wallace整体实现代码为,后附4位Wallace乘法器

`timescale 1ns / 1ps 
 
module wallac_mult_8bit(x, y, out);
    parameter size = 8; // 定义参数,乘法器的位数

    input [size - 1 : 0] x, y; // 输入y是乘数,x是被乘数
    output [2*size - 1 : 0] out; // 乘法器的输出(组合逻辑)

    wire [size*size - 1 : 0] a; // a为部分积
    wire [1 : 0] b0, b1; // 第一级的输出,包含进位
    wire [1 : 0] c0, c1, c2, c3; // 第二级的输出,包含进位
    wire [1 : 0] d0, d1, d2, d3, d4, d5; // 第三级的输出,包含进位
    wire [1 : 0] e0, e1, e2, e3, e4, e5, e6, e7; // 第四级的输出,包含进位
    wire [1 : 0] f0, f1, f2, f3, f4, f5, f6, f7, f8, f9; // 第五级的输出,包含进位
    wire [1 : 0] g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11; // 第六级的输出,包含进位
    wire [2*size - 3 : 0] add_a, add_b; // 第六级的输入
    wire [2*size - 2 : 0] add_out; // 第六级的输出

    // 生成部分积
    assign a = {	x[7],
			x[6], x[7],
			x[5], x[6], x[7],
			x[4], x[5], x[6], x[7], 
			x[3], x[4], x[5], x[6], x[7], 
			x[2], x[3], x[4], x[5], x[6], x[7], 
			x[1], x[2], x[3], x[4], x[5], x[6], x[7], 
			x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
			x[0], x[1], x[2], x[3], x[4], x[5], x[6], 
			x[0], x[1], x[2], x[3], x[4], x[5], 
			x[0], x[1], x[2], x[3], x[4], 
			x[0], x[1], x[2], x[3], 
			x[0], x[1], x[2], 
			x[0], x[1], 
			x[0]} & 
               {	y[7], 
			y[7], y[6], 
			y[7], y[6], y[5], 
			y[7], y[6], y[5], y[4], 
			y[7], y[6], y[5], y[4], y[3], 
			y[7], y[6], y[5], y[4], y[3], y[2], 
			y[7], y[6], y[5], y[4], y[3], y[2], y[1], 
			y[7], y[6], y[5], y[4], y[3], y[2], y[1], y[0], 
			y[6], y[5], y[4], y[3], y[2], y[1], y[0], 
			y[5], y[4], y[3], y[2], y[1], y[0], 
			y[4], y[3], y[2], y[1], y[0], 
			y[3], y[2], y[1], y[0], 
			y[2], y[1], y[0], 
			y[1], y[0], 
			y[0]};
    // 第一级
    hadd U1(.x(a[34]), .y(a[35]), .out(b0));  
    hadd U2(.x(a[41]), .y(a[42]), .out(b1));

    // 第二级	
    hadd U3(.x(a[26]), .y(a[27]), .out(c0));  
    fadd U4(.x(a[32]), .y(a[33]), .z(b0[0]), .out(c1));  
    fadd U5(.x(a[40]), .y(b1[0]), .z(b0[1]), .out(c2));  
    fadd U6(.x(a[47]), .y(a[48]), .z(b1[1]), .out(c3));

    // 第三级
    hadd U7(.x(a[19]), .y(a[20]), .out(d0));  
    fadd U8(.x(a[24]), .y(a[25]), .z(c0[0]), .out(d1));  
    fadd U9(.x(a[31]), .y(c1[0]), .z(c0[1]), .out(d2));  
    fadd U10(.x(a[39]), .y(c2[0]), .z(c1[1]), .out(d3));
    fadd U11(.x(a[46]), .y(c3[0]), .z(c2[1]), .out(d4));
    fadd U12(.x(a[52]), .y(a[53]), .z(c3[1]), .out(d5));

    // 第四级
    hadd U13(.x(a[13]), .y(a[14]), .out(e0));  
    fadd U14(.x(a[17]), .y(a[18]), .z(d0[0]), .out(e1));  
    fadd U15(.x(a[23]), .y(d1[0]), .z(d0[1]), .out(e2));  
    fadd U16(.x(a[30]), .y(d2[0]), .z(d1[1]), .out(e3));
    fadd U17(.x(a[38]), .y(d3[0]), .z(d2[1]), .out(e4));
    fadd U18(.x(a[45]), .y(d4[0]), .z(d3[1]), .out(e5));
    fadd U19(.x(a[51]), .y(d5[0]), .z(d4[1]), .out(e6));
    fadd U20(.x(a[56]), .y(a[57]), .z(d5[1]), .out(e7));

    // 第五级
    hadd U21(.x(a[8]), .y(a[9]), .out(f0));  
    fadd U22(.x(a[11]), .y(a[12]), .z(e0[0]), .out(f1));  
    fadd U23(.x(a[16]), .y(e1[0]), .z(e0[1]), .out(f2));  
    fadd U24(.x(a[22]), .y(e2[0]), .z(e1[1]), .out(f3));
    fadd U25(.x(a[29]), .y(e3[0]), .z(e2[1]), .out(f4));
    fadd U26(.x(a[37]), .y(e4[0]), .z(e3[1]), .out(f5));
    fadd U27(.x(a[44]), .y(e5[0]), .z(e4[1]), .out(f6));
    fadd U28(.x(a[50]), .y(e6[0]), .z(e5[1]), .out(f7));
    fadd U29(.x(a[55]), .y(e7[0]), .z(e6[1]), .out(f8));
    fadd U30(.x(a[59]), .y(a[60]), .z(e7[1]), .out(f9));

    // 第六级
    hadd U31(.x(a[4]), .y(a[5]), .out(g0));  
    fadd U32(.x(a[6]), .y(a[7]), .z(f0[0]), .out(g1));  
    fadd U33(.x(a[10]), .y(f1[0]), .z(f0[1]), .out(g2));  
    fadd U34(.x(a[15]), .y(f2[0]), .z(f1[1]), .out(g3));
    fadd U35(.x(a[21]), .y(f3[0]), .z(f2[1]), .out(g4));
    fadd U36(.x(a[28]), .y(f4[0]), .z(f3[1]), .out(g5));
    fadd U37(.x(a[36]), .y(f5[0]), .z(f4[1]), .out(g6));
    fadd U38(.x(a[43]), .y(f6[0]), .z(f5[1]), .out(g7));
    fadd U39(.x(a[49]), .y(f7[0]), .z(f6[1]), .out(g8));
    fadd U40(.x(a[54]), .y(f8[0]), .z(f7[1]), .out(g9));
    fadd U41(.x(a[58]), .y(f9[0]), .z(f8[1]), .out(g10));
    fadd U42(.x(a[61]), .y(a[62]), .z(f9[1]), .out(g11));

    //
    assign add_a = {g11[1], g10[1], g9[1], g8[1], g7[1], g6[1], g5[1], g4[1], g3[1], g2[1], g1[1], g0[1], g0[0], a[2]}; 
    assign add_b = {a[63], g11[0], g10[0], g9[0], g8[0], g7[0], g6[0], g5[0], g4[0], g3[0], g2[0], g1[0], a[3], a[1]};
    assign add_out = add_a + add_b;

    // 最终输出
    assign out = {add_out, a[0]};

endmodule

// 全加器模块
module fadd(x, y, z, out);
    input x, y, z;  
    output [1 : 0] out;  
    assign out = x + y + z;  
endmodule

// 半加器模块
module hadd(x, y, out);
    input x, y;  
    output [1 : 0] out;  
    assign out = x + y;  
endmodule

注意,如果要两个乘法器一块仿真,需要扇出其中一个的全加器和半加器模块,防止重复定义报错。 

`timescale 1ns / 1ps 
 
module wallac_mult_4bit(x, y, out);
    parameter size = 4; // 定义参数,乘法器的位数

    input [size - 1 : 0] x, y; // 输入y是乘数,x是被乘数
    output [2*size - 1 : 0] out; // 乘法器的输出(组合逻辑)

    wire [size*size - 1 : 0] a; // a为部分积
    wire [1 : 0] b0, b1; // 第一级的输出,包含进位
    wire [1 : 0] c0, c1, c2, c3; // 第二级的输出,包含进位
    wire [5 : 0] add_a, add_b; // 第三级的输入
    wire [6 : 0] add_out; // 第三级的输出

    // 生成部分积
    assign a = {x[3], x[2], x[3], x[1], x[2], x[3], x[0], x[1],
                x[2], x[3], x[0], x[1], x[2], x[0], x[1], x[0]} &
               {y[3], y[3], y[2], y[3], y[2], y[1], y[3], y[2],
                y[1], y[0], y[2], y[1], y[0], y[1], y[0], y[0]};

    // 第一级
    hadd U1(.x(a[8]), .y(a[9]), .out(b0));  
    hadd U2(.x(a[11]), .y(a[12]), .out(b1));

    // 第二级
    hadd U3(.x(a[4]), .y(a[5]), .out(c0));  
    fadd U4(.x(a[6]), .y(a[7]), .z(b0[0]), .out(c1));  
    fadd U5(.x(b1[0]), .y(a[10]), .z(b0[1]), .out(c2));  
    fadd U6(.x(a[13]), .y(a[14]), .z(b1[1]), .out(c3));

    // 第三级
    assign add_a = {c3[1], c2[1], c1[1], c0[1], c0[0], a[2]}; 
    assign add_b = {a[15], c3[0], c2[0], c1[0], a[3], a[1]};  
    assign add_out = add_a + add_b;

    // 最终输出
    assign out = {add_out, a[0]};

endmodule

// 全加器模块
module fadd(x, y, z, out);
    input x, y, z;  
    output [1 : 0] out;  
    assign out = x + y + z;  
endmodule

// 半加器模块
module hadd(x, y, out);
    input x, y;  
    output [1 : 0] out;  
    assign out = x + y;  
endmodule

测试思路为,枚举所有乘法结果并于正确结果相比较,如果错误输出错误提示。

`timescale 1ns / 1ps  
module wallac_mult_tb;  
  
    // 输入和输出  
    reg [3:0] multiplicand1;  
    reg [3:0] multiplier1;  
    wire [7:0] product1;  

    reg [7:0] multiplicand2;  
    reg [7:0] multiplier2;  
    wire [15:0] product2;

    // 实例化4位和8位华莱士树乘法器模块  
    wallac_mult_4bit mult1 (  
        .x(multiplicand1),  
        .y(multiplier1),  
        .out(product1)  
    );  
    
    wallac_mult_8bit mult2 (  
        .x(multiplicand2),  
        .y(multiplier2),  
        .out(product2)  
    );  

    integer i, y;

    // 生成4位乘法器输入组合并验证输出
    always begin 
        if (i < 256) begin
            multiplicand1 = i / 16;
            multiplier1 = i % 16;
            #1;  // 等待乘法器输出稳定
            if (product1 !== multiplicand1 * multiplier1) begin
                $display("Error at time %0t: multiplicand1 = %d, multiplier1 = %d, expected product1 = %d, got %d", 
                         $time, multiplicand1, multiplier1, multiplicand1 * multiplier1, product1);
            end
            i = i + 1;
        end else begin 
            i = 0;
        end
        #9;
    end 

    // 生成8位乘法器输入组合并验证输出
    always begin
        if (y < 65536) begin
            multiplicand2 = y / 256;
            multiplier2 = y % 256;
            #1;  // 等待乘法器输出稳定
            if (product2 !== multiplicand2 * multiplier2) begin
                $display("Error at time %0t: multiplicand2 = %d, multiplier2 = %d, expected product2 = %d, got %d", 
                         $time, multiplicand2, multiplier2, multiplicand2 * multiplier2, product2);
            end
            y = y + 1;
        end else begin
            y = 0;
        end
        #19;
    end 

    initial begin
        i = 0;
        y = 2568;
        multiplicand1 = 4'b0000;  
        multiplier1 = 4'b0000;  
        multiplicand2 = 8'b0;  
        multiplier2 = 8'b0; 
        #50000;
        $stop;
    end

    initial begin
        $monitor("a = %d, b = %d, result = %d", multiplicand2, multiplier2, product2);
        //$fsdbDumpfile("wallac_mult.fsdb");
        //$fsdbDumpvars();
    end
endmodule

 4. 仿真结果

如图为部分打印结果,没有任何错误报告提示,表明65536种输出结果均正确。

5.综合与分析

约束条件:

create_clock -name vclk -period 10

set in_ports [all_inputs]

set_input_delay 0 -clock vclk -add_delay $in_ports

set_output_delay 0 -clock vclk -add_delay [all_outputs]

面积约束

set_max_area 0

相较于4位华莱士树乘法器2.89 ns,8bit乘法器数据到达时间为6.95 ns。面积消耗由520增加到2572。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值