跳转至

还能优化?

PB22111665 胡揚嘉

再压榨一点性能?

我们先来计算现在的Booth编码+华莱士树的延时(粗糙的计算,以逻辑门计数)

64位加法使用16个4位超前进位实现,最长的逻辑通路有32个逻辑门

  1. Booth编码
// 构造Booth编码
assign booth[ 0] =  (  b[ 1] == 1'b0 ) ? 
            ( (b[ 0] == 1'b0) ? ((1'b0  == 1'b0) ? 3'd0 : 3'd1 ) :   ((1'b0  == 1'b0) ? 3'd1 : 3'd2) ) :
            ( (b[ 0] == 1'b0) ? ((1'b0  == 1'b0) ? 3'd6 : 3'd7 ) :   ((1'b0  == 1'b0) ? 3'd7 : 3'd0) ) ;
//构造16个加法元素
    wire [63:0] add [15:0];
    wire [63:0] temp_a = {32'd0, a};
    wire [63:0] temp_not = ~temp_a + 1;          
    assign add[15] = ((booth[15] == 3'd0) ? 64'd0 : ((booth[15] == 3'd1) ? temp_a  : ((booth[15] == 3'd2) ? temp_a << 1 : ((booth[15] == 3'd7) ? temp_not  : temp_not << 1 )))) << 30;
  1. 32个booth编码, 8选1,实际有3个逻辑门延时

  2. 构造中间加法元素:最长延时:temp_not << 1: 一层64位加法和位拼接+4选1带来的两层逻辑门延时

    所以实际有35个逻辑门延时

  3. CSA: 5层,每层2级延时,共10层

  4. 最后一层64位全加器 ,32延时

  5. 总计:3 + 35 + 10 +32 = 80层逻辑门延时(大致计算)

问题在哪里?

大部分是全加器带来的,(与二叉树乘法器性能相比也可以得知)

HOW: 减少全加器:在Booth编码的全加器优化掉

思路

\[ -y_{31} \times 2^{31} + y_{30} \times 2^{30} + y_{29}\times 2^{29}+ \cdots+y_1\times 2^1 + y_0\times 2^0 \\ =(y_{29}+y_{30}-2\times y_{31}) \times2^{30} + (y_{27}+y_{28}-2\times y_{29}) \times2^{28} + \cdots \\ +(y_{1}+y_{2}-2\times y_{3}) \times2^{2} + (y_{-1}+y_0-2 \times y_1) \times 2^0 \]

我们取相邻的两个观察: $$ g1 times2^{2}x + g0 times 2^0 x $$ 假如g0导致需要加1( -x 或者 -2x)

我们可以将其放置到g1的末两位因为,g1相比g2乘以4,相当于左移两位,所为与g0相比,其与g0第0位对齐的那位一定为0,可以通过拼接的方式补位实现,这样避免了引入加法器。

1. 0000xxxx
2. 00xxxx00
3. xxxx0000

四位的数据,探究某三个

对于数据1,假如需要取-x

那么等价于

1. 0000xxxx
2. 00xxxx01 // 表示对末尾进行增1
3. xxxx0000

对于数据1,假如需要取-x

1. 0000xxxx
2. 00xxxx01  // 对末尾进行增1
3. xxxx0100  // 更改数据3的值以反映取负2x

​ 在处理二进制数时,我们可以通过拼接和位移的方式来优化计算,避免使用加法器。我们通过定义相邻的位 ( g1 ) 和 ( g0 ) 来管理数值的变化。特别是在需要对某一位进行取负或加法的情况下,我们可以通过将额外的位操作到高位,来确保数值的正确性和计算的高效性。

​ 对于示例中的数据,假设我们需要从某个数据中取出负值,通过调整低位的位值并将高位的值左移,我们能够有效地管理和调整数值,而无需复杂的加法器设计。这种方法不仅提高了计算效率,也简化了电路设计。

​ 处理后,可以发现,Booth编码的加法操作消失了,变成了位拼接操作。

​ 但是,对于第一个(最高的)有取负的情况,我们需要增加单独一个中间加法元素来承载这个+1

代码如下:

module MUL_Wallace(
    // input   clk,         //时钟
    input  [31:0] a,     //被乘数
    input  [31:0] b,     //乘数
    // output [63:0] add [15:0],
    output [31:0] l,     //积低32位
    output [31:0] h      //积高32位
    );

    logic [2:0] bits[16];
    assign bits[ 0] = {b[1:0], 1'b0};
    assign bits[ 1] = b[ 3: 1];
    assign bits[ 2] = b[ 5: 3];
    assign bits[ 3] = b[ 7: 5];
    assign bits[ 4] = b[ 9: 7];
    assign bits[ 5] = b[11: 9];
    assign bits[ 6] = b[13:11];
    assign bits[ 7] = b[15:13];
    assign bits[ 8] = b[17:15];
    assign bits[ 9] = b[19:17];
    assign bits[10] = b[21:19];
    assign bits[11] = b[23:21];
    assign bits[12] = b[25:23];
    assign bits[13] = b[27:25];
    assign bits[14] = b[29:27];
    assign bits[15] = b[31:29];
    // assign bits[16] = b[33:31];

    genvar i;
    generate
        for (i = 0; i < 16; i = i + 1)
        begin:encoder
        assign multiply_by_2[i] = bits[i][0] ~^ bits[i][1];
        assign positive[i] = (~bits[i][2]) & (bits[i][1] | bits[i][0]);
        assign negative[i] = ~((~bits[i][2]) | (bits[i][1] & bits[i][0]));
        end
    endgenerate


    logic [32: 0] pp_temp1[16];
    logic [32: 0] pp_temp2[16];
    genvar i;
    generate
        for (i = 0; i < 16; i = i + 1)
        begin
        assign pp_temp1[i] = (multiply_by_2[i]) ? {a, 1'b0} : {a[31], a};
        assign pp_temp2[i] = ({33{positive[i]}} & pp_temp1[i]) | ({33{negative[i]}} & (~pp_temp1[i]));
        end
    endgenerate


    logic [63:0] pp[17];

    // 根据给定逻辑赋值 pp 数组的每个元素
    assign pp[ 0] = {{31{pp_temp2[ 0][32]}}, pp_temp2[ 0]}; // pp[0] 的赋值
    assign pp[ 1] = {{29{pp_temp2[ 1][32]}}, pp_temp2[ 1], 1'b0, negative[ 0]}; // pp[1] 的赋值
    assign pp[ 2] = {{27{pp_temp2[ 2][32]}}, pp_temp2[ 2], 1'b0, negative[ 1], 2'b0}; // pp[2] 的赋值
    assign pp[ 3] = {{25{pp_temp2[ 3][32]}}, pp_temp2[ 3], 1'b0, negative[ 2], 4'b0}; // pp[3] 的赋值
    assign pp[ 4] = {{23{pp_temp2[ 4][32]}}, pp_temp2[ 4], 1'b0, negative[ 3], 6'b0}; // pp[4] 的赋值
    assign pp[ 5] = {{21{pp_temp2[ 5][32]}}, pp_temp2[ 5], 1'b0, negative[ 4], 8'b0}; // pp[5] 的赋值
    assign pp[ 6] = {{19{pp_temp2[ 6][32]}}, pp_temp2[ 6], 1'b0, negative[ 5], 10'b0}; // pp[6] 的赋值
    assign pp[ 7] = {{17{pp_temp2[ 7][32]}}, pp_temp2[ 7], 1'b0, negative[ 6], 12'b0}; // pp[7] 的赋值
    assign pp[ 8] = {{15{pp_temp2[ 8][32]}}, pp_temp2[ 8], 1'b0, negative[ 7], 14'b0}; // pp[8] 的赋值
    assign pp[ 9] = {{13{pp_temp2[ 9][32]}}, pp_temp2[ 9], 1'b0, negative[ 8], 16'b0}; // pp[9] 的赋值
    assign pp[10] = {{11{pp_temp2[10][32]}}, pp_temp2[10], 1'b0, negative[ 9], 18'b0}; // pp[10] 的赋值
    assign pp[11] = {{ 9{pp_temp2[11][32]}}, pp_temp2[11], 1'b0, negative[10], 20'b0}; // pp[11] 的赋值
    assign pp[12] = {{ 7{pp_temp2[12][32]}}, pp_temp2[12], 1'b0, negative[11], 22'b0}; // pp[12] 的赋值
    assign pp[13] = {{ 5{pp_temp2[13][32]}}, pp_temp2[13], 1'b0, negative[12], 24'b0}; // pp[13] 的赋值
    assign pp[14] = {{ 3{pp_temp2[14][32]}}, pp_temp2[14], 1'b0, negative[13], 26'b0}; // pp[14] 的赋值
    assign pp[15] = {{ 1{pp_temp2[15][32]}}, pp_temp2[15], 1'b0, negative[14], 28'b0}; // pp[15] 的赋值
    assign pp[16] = {31'b0 ,negative[15], 32'b0}; // pp[16] 的赋值,这里没有 negative 的计算




    //CSA中间量保存
    wire [63:0] temp_add [29:0];
    wire [63:0] all;
    //例化CSA
    CSA csa_1(
        .a   (add[ 2]) ,
        .b   (add[ 1]),
        .c   (add[ 0]),
        .y1  (temp_add[ 1]),
        .y2  (temp_add[ 0])
    );
    CSA csa_2(
        .a   (add[ 5]) ,
        .b   (add[ 4]),
        .c   (add[ 3]),
        .y1  (temp_add[ 3]),
        .y2  (temp_add[ 2])
    ); 
    CSA csa_3(
        .a   (add[ 8]) ,
        .b   (add[ 7]),
        .c   (add[ 6]),
        .y1  (temp_add[ 5]),
        .y2  (temp_add[ 4])
    ); 
    CSA csa_4(
        .a   (add[11]) ,
        .b   (add[10]),
        .c   (add[ 9]),
        .y1  (temp_add[ 7]),
        .y2  (temp_add[ 6])
    ); 
    CSA csa_5(
        .a   (add[14]) ,
        .b   (add[13]),
        .c   (add[12]),
        .y1  (temp_add[ 9]),
        .y2  (temp_add[ 8])
    ); 
    CSA csa_6(
        .a   (add[15]) ,
        .b   (temp_add[ 1]),
        .c   (temp_add[ 0]),
        .y1  (temp_add[11]),
        .y2  (temp_add[10])
    ); 
    CSA csa_7(
        .a   (temp_add[ 4]) ,
        .b   (temp_add[ 3]),
        .c   (temp_add[ 2]),
        .y1  (temp_add[13]),
        .y2  (temp_add[12])
    ); 
    CSA csa_8(
        .a   (temp_add[ 7]) ,
        .b   (temp_add[ 6]),
        .c   (temp_add[ 5]),
        .y1  (temp_add[15]),
        .y2  (temp_add[14])
    ); 
    CSA csa_9(
        .a   (temp_add[ 9]) ,
        .b   (temp_add[ 8]),
        .c   (temp_add[10]),
        .y1  (temp_add[17]),
        .y2  (temp_add[16])
    ); 
    CSA csa_10(
        .a   (temp_add[13]) ,
        .b   (temp_add[12]),
        .c   (temp_add[11]),
        .y1  (temp_add[19]),
        .y2  (temp_add[18])
    ); 
    CSA csa_11(
        .a   (temp_add[15]) ,
        .b   (temp_add[14]),
        .c   (temp_add[16]),
        .y1  (temp_add[21]),
        .y2  (temp_add[20])
    ); 
    CSA csa_12(
        .a   (temp_add[19]) ,
        .b   (temp_add[18]),
        .c   (temp_add[17]),
        .y1  (temp_add[23]),
        .y2  (temp_add[22])
    ); 
    CSA csa_13(
        .a   (temp_add[22]) ,
        .b   (temp_add[21]),
        .c   (temp_add[20]),
        .y1  (temp_add[25]),
        .y2  (temp_add[24])
    ); 
    CSA csa_14(
        .a   (temp_add[25]) ,
        .b   (temp_add[24]),
        .c   (temp_add[23]),
        .y1  (temp_add[27]),
        .y2  (temp_add[26])
    );
    CSA csa_15(
        .a   (temp_add[27]) ,
        .b   (temp_add[26]),
        .c   (pp[16]),
        .y1  (temp_add[28]),
        .y2  (temp_add[29])
    );


    //最后一层全加器
    assign all = temp_add[29] + temp_add[28];
    assign l = all [31: 0];
    assign h = all [63:32];

endmodule

上面的Booth被这里的multiply_by_2, positive, negative取代

我们计算一下延时

在取得中间加法变元之前:我们需要

  1. multiply_by_2, positive, negative带来的三层逻辑门延时
  2. pp_temp2计算带来的4层逻辑门延时
  3. pp计算带来的拼接操作,不妨假设3层延时
  4. 总计:10层延时

!!! Amazing

我们从38层延时减少到10层。核心是减少了+的代价,但是付出了更多的位拼接,以及中间信号产生的代价

还能干什么?

我们看一下优化前的架构

graph LR
    A[Booth = 38]
    B[CSA = 10]
    C[adder = 32]

    A --> B --> C

假如这80层是我们的瓶颈,怎么办?

切时钟,分成多次计算

不妨讲Booth切开

graph LR
    A[Booth = 38]
    B[CSA = 10]
    C[adder = 32]
    D[38]
    E[42]

    subgraph first Flow
        A --> D
    end

        B --> C
        C --> E

这样我们的最大逻辑时延变成了42

代码:

module MUL_Wallace(
    // input   clk,         //时钟
    input  [31:0] a,     //被乘数
    input  [31:0] b,     //乘数
    // output [63:0] add [15:0],
    output [31:0] l,     //积低32位
    output [31:0] h      //积高32位
    );

    //构造2位booth编码
    wire [2:0] booth [15:0];
    assign booth[15] =  (  b[31] == 1'b0 ) ? 
                        ( (b[30] == 1'b0) ? ((b[29] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[29] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[30] == 1'b0) ? ((b[29] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[29] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[14] =  (  b[29] == 1'b0 ) ? 
                        ( (b[28] == 1'b0) ? ((b[27] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[27] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[28] == 1'b0) ? ((b[27] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[27] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[13] =  (  b[27] == 1'b0 ) ? 
                        ( (b[26] == 1'b0) ? ((b[25] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[25] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[26] == 1'b0) ? ((b[25] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[25] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[12] =  (  b[25] == 1'b0 ) ? 
                        ( (b[24] == 1'b0) ? ((b[23] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[23] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[24] == 1'b0) ? ((b[23] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[23] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[11] =  (  b[23] == 1'b0 ) ? 
                        ( (b[22] == 1'b0) ? ((b[21] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[21] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[22] == 1'b0) ? ((b[21] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[21] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[10] =  (  b[21] == 1'b0 ) ? 
                        ( (b[20] == 1'b0) ? ((b[19] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[19] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[20] == 1'b0) ? ((b[19] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[19] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 9] =  (  b[19] == 1'b0 ) ? 
                        ( (b[18] == 1'b0) ? ((b[17] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[17] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[18] == 1'b0) ? ((b[17] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[17] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 8] =  (  b[17] == 1'b0 ) ? 
                        ( (b[16] == 1'b0) ? ((b[15] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[15] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[16] == 1'b0) ? ((b[15] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[15] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 7] =  (  b[15] == 1'b0 ) ? 
                        ( (b[14] == 1'b0) ? ((b[13] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[13] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[14] == 1'b0) ? ((b[13] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[13] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 6] =  (  b[13] == 1'b0 ) ? 
                        ( (b[12] == 1'b0) ? ((b[11] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[11] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[12] == 1'b0) ? ((b[11] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[11] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 5] =  (  b[11] == 1'b0 ) ? 
                        ( (b[10] == 1'b0) ? ((b[ 9] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[ 9] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[10] == 1'b0) ? ((b[ 9] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[ 9] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 4] =  (  b[ 9] == 1'b0 ) ? 
                        ( (b[ 8] == 1'b0) ? ((b[ 7] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[ 7] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[ 8] == 1'b0) ? ((b[ 7] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[ 7] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 3] =  (  b[ 7] == 1'b0 ) ? 
                        ( (b[ 6] == 1'b0) ? ((b[ 5] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[ 5] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[ 6] == 1'b0) ? ((b[ 5] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[ 5] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 2] =  (  b[ 5] == 1'b0 ) ? 
                        ( (b[ 4] == 1'b0) ? ((b[ 3] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[ 3] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[ 4] == 1'b0) ? ((b[ 3] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[ 3] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 1] =  (  b[ 3] == 1'b0 ) ? 
                        ( (b[ 2] == 1'b0) ? ((b[ 1] == 1'b0) ? 3'd0 : 3'd1 ) :   ((b[ 1] == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[ 2] == 1'b0) ? ((b[ 1] == 1'b0) ? 3'd6 : 3'd7 ) :   ((b[ 1] == 1'b0) ? 3'd7 : 3'd0) ) ;
    assign booth[ 0] =  (  b[ 1] == 1'b0 ) ? 
                        ( (b[ 0] == 1'b0) ? ((1'b0  == 1'b0) ? 3'd0 : 3'd1 ) :   ((1'b0  == 1'b0) ? 3'd1 : 3'd2) ) :
                        ( (b[ 0] == 1'b0) ? ((1'b0  == 1'b0) ? 3'd6 : 3'd7 ) :   ((1'b0  == 1'b0) ? 3'd7 : 3'd0) ) ;
    //构造16个加法元素
    reg [63:0] add [15:0];
    wire [63:0] temp_a = {32'd0, a};
    wire [63:0] temp_not = ~temp_a + 1;     
    always @(posedge clk) begin
        add[15] <= ((booth[15] == 3'd0) ? 64'd0 : ((booth[15] == 3'd1) ? temp_a  : ((booth[15] == 3'd2) ? temp_a << 1 : ((booth[15] == 3'd7) ? temp_not  : temp_not << 1 )))) << 30;
        add[14] <= ((booth[14] == 3'd0) ? 64'd0 : ((booth[14] == 3'd1) ? temp_a  : ((booth[14] == 3'd2) ? temp_a << 1 : ((booth[14] == 3'd7) ? temp_not  : temp_not << 1 )))) << 28;
        add[13] <= ((booth[13] == 3'd0) ? 64'd0 : ((booth[13] == 3'd1) ? temp_a  : ((booth[13] == 3'd2) ? temp_a << 1 : ((booth[13] == 3'd7) ? temp_not  : temp_not << 1 )))) << 26;
        add[12] <= ((booth[12] == 3'd0) ? 64'd0 : ((booth[12] == 3'd1) ? temp_a  : ((booth[12] == 3'd2) ? temp_a << 1 : ((booth[12] == 3'd7) ? temp_not  : temp_not << 1 )))) << 24;
        add[11] <= ((booth[11] == 3'd0) ? 64'd0 : ((booth[11] == 3'd1) ? temp_a  : ((booth[11] == 3'd2) ? temp_a << 1 : ((booth[11] == 3'd7) ? temp_not  : temp_not << 1 )))) << 22;
        add[10] <= ((booth[10] == 3'd0) ? 64'd0 : ((booth[10] == 3'd1) ? temp_a  : ((booth[10] == 3'd2) ? temp_a << 1 : ((booth[10] == 3'd7) ? temp_not  : temp_not << 1 )))) << 20;
        add[ 9] <= ((booth[ 9] == 3'd0) ? 64'd0 : ((booth[ 9] == 3'd1) ? temp_a  : ((booth[ 9] == 3'd2) ? temp_a << 1 : ((booth[ 9] == 3'd7) ? temp_not  : temp_not << 1 )))) << 18;
        add[ 8] <= ((booth[ 8] == 3'd0) ? 64'd0 : ((booth[ 8] == 3'd1) ? temp_a  : ((booth[ 8] == 3'd2) ? temp_a << 1 : ((booth[ 8] == 3'd7) ? temp_not  : temp_not << 1 )))) << 16;
        add[ 7] <= ((booth[ 7] == 3'd0) ? 64'd0 : ((booth[ 7] == 3'd1) ? temp_a  : ((booth[ 7] == 3'd2) ? temp_a << 1 : ((booth[ 7] == 3'd7) ? temp_not  : temp_not << 1 )))) << 14;
        add[ 6] <= ((booth[ 6] == 3'd0) ? 64'd0 : ((booth[ 6] == 3'd1) ? temp_a  : ((booth[ 6] == 3'd2) ? temp_a << 1 : ((booth[ 6] == 3'd7) ? temp_not  : temp_not << 1 )))) << 12;
        add[ 5] <= ((booth[ 5] == 3'd0) ? 64'd0 : ((booth[ 5] == 3'd1) ? temp_a  : ((booth[ 5] == 3'd2) ? temp_a << 1 : ((booth[ 5] == 3'd7) ? temp_not  : temp_not << 1 )))) << 10;
        add[ 4] <= ((booth[ 4] == 3'd0) ? 64'd0 : ((booth[ 4] == 3'd1) ? temp_a  : ((booth[ 4] == 3'd2) ? temp_a << 1 : ((booth[ 4] == 3'd7) ? temp_not  : temp_not << 1 )))) <<  8;
        add[ 3] <= ((booth[ 3] == 3'd0) ? 64'd0 : ((booth[ 3] == 3'd1) ? temp_a  : ((booth[ 3] == 3'd2) ? temp_a << 1 : ((booth[ 3] == 3'd7) ? temp_not  : temp_not << 1 )))) <<  6;
        add[ 2] <= ((booth[ 2] == 3'd0) ? 64'd0 : ((booth[ 2] == 3'd1) ? temp_a  : ((booth[ 2] == 3'd2) ? temp_a << 1 : ((booth[ 2] == 3'd7) ? temp_not  : temp_not << 1 )))) <<  4;
        add[ 1] <= ((booth[ 1] == 3'd0) ? 64'd0 : ((booth[ 1] == 3'd1) ? temp_a  : ((booth[ 1] == 3'd2) ? temp_a << 1 : ((booth[ 1] == 3'd7) ? temp_not  : temp_not << 1 )))) <<  2;
        add[ 0] <= ((booth[ 0] == 3'd0) ? 64'd0 : ((booth[ 0] == 3'd1) ? temp_a  : ((booth[ 0] == 3'd2) ? temp_a << 1 : ((booth[ 0] == 3'd7) ? temp_not  : temp_not << 1 ))))  ;
    end     


    //CSA中间量保存
    wire [63:0] temp_add [27:0];
    wire [63:0] all;
    //例化CSA
    CSA csa_1(
        .a   (add[ 2]) ,
        .b   (add[ 1]),
        .c   (add[ 0]),
        .y1  (temp_add[ 1]),
        .y2  (temp_add[ 0])
    );
    CSA csa_2(
        .a   (add[ 5]) ,
        .b   (add[ 4]),
        .c   (add[ 3]),
        .y1  (temp_add[ 3]),
        .y2  (temp_add[ 2])
    ); 
    CSA csa_3(
        .a   (add[ 8]) ,
        .b   (add[ 7]),
        .c   (add[ 6]),
        .y1  (temp_add[ 5]),
        .y2  (temp_add[ 4])
    ); 
    CSA csa_4(
        .a   (add[11]) ,
        .b   (add[10]),
        .c   (add[ 9]),
        .y1  (temp_add[ 7]),
        .y2  (temp_add[ 6])
    ); 
    CSA csa_5(
        .a   (add[14]) ,
        .b   (add[13]),
        .c   (add[12]),
        .y1  (temp_add[ 9]),
        .y2  (temp_add[ 8])
    ); 
    CSA csa_6(
        .a   (add[15]) ,
        .b   (temp_add[ 1]),
        .c   (temp_add[ 0]),
        .y1  (temp_add[11]),
        .y2  (temp_add[10])
    ); 
    CSA csa_7(
        .a   (temp_add[ 4]) ,
        .b   (temp_add[ 3]),
        .c   (temp_add[ 2]),
        .y1  (temp_add[13]),
        .y2  (temp_add[12])
    ); 
    CSA csa_8(
        .a   (temp_add[ 7]) ,
        .b   (temp_add[ 6]),
        .c   (temp_add[ 5]),
        .y1  (temp_add[15]),
        .y2  (temp_add[14])
    ); 
    CSA csa_9(
        .a   (temp_add[ 9]) ,
        .b   (temp_add[ 8]),
        .c   (temp_add[10]),
        .y1  (temp_add[17]),
        .y2  (temp_add[16])
    ); 
    CSA csa_10(
        .a   (temp_add[13]) ,
        .b   (temp_add[12]),
        .c   (temp_add[11]),
        .y1  (temp_add[19]),
        .y2  (temp_add[18])
    ); 
    CSA csa_11(
        .a   (temp_add[15]) ,
        .b   (temp_add[14]),
        .c   (temp_add[16]),
        .y1  (temp_add[21]),
        .y2  (temp_add[20])
    ); 
    CSA csa_12(
        .a   (temp_add[19]) ,
        .b   (temp_add[18]),
        .c   (temp_add[17]),
        .y1  (temp_add[23]),
        .y2  (temp_add[22])
    ); 
    CSA csa_13(
        .a   (temp_add[22]) ,
        .b   (temp_add[21]),
        .c   (temp_add[20]),
        .y1  (temp_add[25]),
        .y2  (temp_add[24])
    ); 
    CSA csa_14(
        .a   (temp_add[25]) ,
        .b   (temp_add[24]),
        .c   (temp_add[23]),
        .y1  (temp_add[27]),
        .y2  (temp_add[26])
    ); 

    //最后一层全加器
    assign all = temp_add[27] + temp_add[26];
    assign l = all [31: 0];
    assign h = all [63:32];

endmodule

我使用了reg来保存中间量[63: 0] add[16]来将流水切成2段。