还能优化?
PB22111665 胡揚嘉
再压榨一点性能?
我们先来计算现在的Booth编码+华莱士树的延时(粗糙的计算,以逻辑门计数)
64位加法使用16个4位超前进位实现,最长的逻辑通路有32个逻辑门
- 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;
-
32个booth编码, 8选1,实际有3个逻辑门延时
-
构造中间加法元素:最长延时:
temp_not << 1
: 一层64位加法和位拼接+4选1带来的两层逻辑门延时所以实际有35个逻辑门延时
-
CSA: 5层,每层2级延时,共10层
-
最后一层64位全加器 ,32延时
-
总计:3 + 35 + 10 +32 = 80层逻辑门延时(大致计算)
问题在哪里?
大部分是全加器带来的,(与二叉树乘法器性能相比也可以得知)
HOW: 减少全加器:在Booth编码的全加器优化掉
思路
我们取相邻的两个观察: $$ g1 times2^{2}x + g0 times 2^0 x $$ 假如g0导致需要加1( -x 或者 -2x)
我们可以将其放置到g1的末两位因为,g1相比g2乘以4,相当于左移两位,所为与g0相比,其与g0第0位对齐的那位一定为0,可以通过拼接的方式补位实现,这样避免了引入加法器。
四位的数据,探究某三个
对于数据1,假如需要取-x
那么等价于
对于数据1,假如需要取-x
在处理二进制数时,我们可以通过拼接和位移的方式来优化计算,避免使用加法器。我们通过定义相邻的位 ( 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
取代
我们计算一下延时
在取得中间加法变元之前:我们需要
multiply_by_2
,positive
,negative
带来的三层逻辑门延时pp_temp2
计算带来的4层逻辑门延时pp
计算带来的拼接操作,不妨假设3层延时- 总计:10层延时
!!! Amazing
我们从38层延时减少到10层。核心是减少了+
的代价,但是付出了更多的位拼接,以及中间信号产生的代价
还能干什么?
我们看一下优化前的架构
假如这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段。