并行前缀加法器verilog实现
前缀网络用KS树,64位加法器的verilog实现如下:
module cal_union(
input g2,p2,g1,p1,
output G,P
);
assign G = g2 | p2&g1;
assign P = p1 & p2;
endmodule
module adder_nocarry(
input A,B,C_in,
output S,
output g,p
);
assign S = A ^ B ^ C_in;
assign g = A & B;
assign p = A ^ B;
endmodule
module Para_prefix_mod_64bit(
input [63:0]g,p,
output [63:0]G,P //P[i] 表示 p[i:0] , G[i] 类似
);
//采用KS树结构,64位需要6层树,每层有 16 - (1<<(i-1)) 个计算单元
wire [63:0] GL[6:0],PL[6:0];
assign GL[0] = g;
assign PL[0] = p;
generate
genvar i,j;
for(i=1;i<7;i=i+1)
begin: layer
for(j=(1<<(i-1));j<64;j=j+1)
begin: column
cal_union ui1(
.g2(GL[i-1][j]), // g2,p2 代表高的那一位
.p2(PL[i-1][j]),
.g1(GL[i-1][j-(1<<(i-1))]),
.p1(PL[i-1][j-(1<<(i-1))]),
.G(GL[i][j]),
.P(PL[i][j])
);
end
for(j=0;j<(1<<(i-1));j=j+1)
begin: column_
assign GL[i][j] = GL[i-1][j];
assign PL[i][j] = PL[i-1][j];
end
end
endgenerate
assign G = GL[6];
assign P = PL[6];
endmodule
module adder_prefix_64bit(
input [63:0] A,B,
input C_in,
output [63:0] S,
output C_out
);
wire [63:0] g,p,G,P;
wire [64:0] C;
assign C [0] = C_in;
generate
genvar j;
for(j=0;j<64;j=j+1)
begin: carry_mod
assign C[j+1] = G[j] | (P[j]&C_in); //C [j] 代表 第j个半加器的C_in
end
genvar i;
for(i=0;i<64;i=i+1)
begin: add_mod //64 half_adder
adder_nocarry add_unit(
.A(A[i]),
.B(B[i]),
.C_in(C[i]),
.S(S[i]),
.g(g[i]),
.p(p[i])
);
end
endgenerate
//前缀网络计算进位信号
assign C_out = C[64];
Para_prefix_mod_64bit prefix_net(.g(g), .p(p), .G(G) ,.P(P));
endmodule
module adder_prefix_tb();
reg [63:0]A,B;
reg C_in;
wire C_out;
wire [63:0]S;
adder_prefix_64bit T4 (.A(A),.B(B),.C_in(C_in),.S(S),.C_out(C_out));
integer i = 0;
initial
begin
C_in = 1;
for(i=0;i<16;i=i+1)
begin
A = $random;
B = $random;
#10;
end
C_in = 0;
for(i=0;i<16;i=i+1)
begin
A = $random;
B = $random;
#10;
end
end
endmodule
后续——
发现C_in的扇出太大了,应该想办法改进