建议先看我的这篇文章超前进位加法器
思想:
超前进位的思想:通过计算G和P信号,来解决后面三个16bit模块的进位信号,因此可以把高位的三个16bit模块并行起来。
流水线的做法: 在关键路径上插触发器,尽量均衡各部分的延时。
具体设计:g和p信号的计算以及G(GX)和P(PX)信号的计算,与C_in无关,因此可以单独先算出来。 通过这些进位产生/传播信号计算各模块的C_in。然后就是把关键路径尽量均分,这里插入三级触发器。
架构图如下:
verilog代码实现
module adder_nocarry(
input A,B,C_in,
output S
);
assign S = A ^ B ^ C_in;
endmodule
module adder_16bit( //超前三位计算进位信号
input [15:0]A,B,
input [15:0]C,
output [15:0]Y
);
generate
genvar i;
for(i=0;i<16;i=i+1)
begin
adder_nocarry a (A[i],B[i],C[i],Y[i]);
end
endgenerate
endmodule
module Carry_signal_cal_mode(
input [3:0]g,p,
input C_in,
output [3:0]C
);
assign C[0] = g[0] | (p[0]&C_in);
assign C[1] = g[1] | (p[1]&g[0]) | (p[0]&p[1]&C_in) ;
assign C[2] = g[2] | (p[2]&g[1]) | (p[2]&p[1]&g[0]) | (p[2]&p[1]&p[0]&C_in);
assign C[3] = g[3] | (p[3]&g[2]) | (p[3]&p[2]&g[1]) | (p[3]&p[2]&p[1]&g[0]) | (p[3]&p[2]&p[1]&p[0]&C_in) ;
endmodule
module Carry_signal_cal_mode_16bit(
input [15:0]g,p,
input [3:0]C_in,
output [15:0]C
);
generate
genvar i;
for(i=0;i<4;i=i+1)
begin: carry_signal_layer2
Carry_signal_cal_mode q (g[4*i+3:4*i],p[4*i+3:4*i],C_in[i],C[4*i+3:4*i]);
end
endgenerate
endmodule
module g_p_mode(
input [63:0]A,B,
output [63:0]g,p
);
generate
genvar i;
for(i=0;i<64;i=i+1)
begin: g_p
assign g[i] = A[i] & B[i];
assign p[i] = A[i] ^ B[i];
end
endgenerate
endmodule
module G_P_generator(
input [63:0]g,p,
output [15:0]G,P
);
generate
genvar i;
for(i=0;i<16;i=1+i)
begin: G_P_loop
assign G[i] = g[4*i+3] | (p[4*i+3]&g[4*i+2]) | (p[4*i+3]&p[4*i+2]&g[4*i+1]) | (p[4*i+3]&p[4*i+2]&p[4*i+1]&g[4*i]) ;
assign P[i] = p[4*i]&p[4*i+1]&p[4*i+2]&p[4*i+3];
end
endgenerate
endmodule
module GX_PX_generator(
input [15:0]G,P,
output [3:0]GX,PX
);
generate
genvar i;
for(i=0;i<4;i=1+i)
begin: G_P_loop
assign GX[i] = G[4*i+3] | (P[4*i+3]&G[4*i+2]) | (G[4*i+3]&P[4*i+2]&G[4*i+1]) | (P[4*i+3]&P[4*i+2]&P[4*i+1]&G[4*i]) ;
assign PX[i] = P[4*i]&P[4*i+1]&P[4*i+2]&P[4*i+3];
end
endgenerate
endmodule
module pipelined_adder_LKAHD(
input clk,rst,
input [63:0]A,B,
input C_in,
output [63:0]S,
output C_out
);
reg [127:0]L1_AB,L2_AB,L3_AB;
reg [63:0]L1_S,L2_S,L3_S;
reg [127:0]L1_gp,L2_gp,L3_gp;
reg [31:0]L1_GP,L2_GP,L3_GP;
reg [7:0]L1_GXPX,L2_GXPX,L3_GXPX;
reg L1_Cin,L3_Cin;
reg [3:0]L2_Cin;
wire [63:0]g,p;
wire [15:0]G,P;
wire [3:0]GX,PX;
wire [3:0]C2;
wire [15:0]C1;
wire [3:0]C3;
wire [15:0]S1;
wire [3:0]C2_2_1,C2_2_2,C2_2_3;
wire [15:0]C1_2_1,C1_2_2,C1_2_3;
wire [15:0]S2,S3,S4;
always@(posedge clk,posedge rst)
begin
if(rst)
begin
L1_AB<=0;
L1_S<=0;
L1_gp<=0;
L1_GP<=0;
L1_GXPX<=0;
L1_Cin <= 0;
L2_AB<=0;
L2_S<=0;
L2_gp<=0;
L2_GP<=0;
L2_GXPX<=0;
L2_Cin <= 0;
L3_AB<=0;
L3_S<=0;
L3_gp<=0;
L3_GP<=0;
L3_GXPX<=0;
L2_Cin <= 0;
end
else
begin
// first level sequential logic
L1_AB <= {A,B};
L1_S <= 64'b0;
L1_gp <= {p,g};
L1_GP <= {P,G};
L1_GXPX <= {PX,GX};
L1_Cin <= C_in;
//second leverl sequential logic
L2_AB <= L1_AB;
L2_S <= {48'b0,S1};
L2_gp <= L1_gp;
L2_GP <= L1_GP;
L2_GXPX <= L1_GXPX;
L2_Cin <= C3;
//third level sequential logic
L3_AB <= L2_AB;
L3_S <= {S4,S3,S2,L2_S[15:0]};
L3_gp <= L2_gp;
L3_GP <= L2_GP;
L3_GXPX <= L2_GXPX;
L3_Cin <= L2_Cin[3];
end
end
// first level combined logic
g_p_mode g_p (A,B,g,p);
G_P_generator G_P (g,p,G,P);
GX_PX_generator GX_PX(G,P,GX,PX);
//secvond level combined logic
Carry_signal_cal_mode level1_layer2 (L1_GP[3:0],L1_GP[19:16],L1_Cin, C2);
Carry_signal_cal_mode_16bit level1_layer1(L1_gp[15:0],L1_gp[79:64],{C2[2:0],L1_Cin},C1);
adder_16bit add1_1 (L1_AB[15:0],L1_AB[79:64],{C1[14:0],L1_Cin},S1);
Carry_signal_cal_mode layer3 (L1_GXPX[3:0],L1_GXPX[7:4],L1_Cin,C3);
//third level combined logic
Carry_signal_cal_mode level2_layer2_1 (L2_GP[7:4],L2_GP[23:20],L2_Cin[0],C2_2_1);
Carry_signal_cal_mode_16bit level2_layer1_1(L2_gp[31:16],L2_gp[95:80],{C2_2_1[2:0],L2_Cin[0]},C1_2_1);
adder_16bit add2_1 (L2_AB[31:16],L2_AB[95:80],{C1_2_1[14:0],L2_Cin[0]},S2);
Carry_signal_cal_mode level2_layer2_2 (L2_GP[11:8],L2_GP[27:24],L2_Cin[1],C2_2_2);
Carry_signal_cal_mode_16bit level2_layer1_2(L2_gp[47:32],L2_gp[111:96],{C2_2_2[2:0],L2_Cin[1]},C1_2_2);
adder_16bit add2_2 (L2_AB[47:32],L2_AB[111:96],{C1_2_2[14:0],L2_Cin[1]},S3);
Carry_signal_cal_mode level2_layer2_3 (L2_GP[15:12],L2_GP[31:28],L2_Cin[2],C2_2_3);
Carry_signal_cal_mode_16bit level2_layer1_3(L2_gp[63:48],L2_gp[127:112],{C2_2_3[2:0],L2_Cin[2]},C1_2_3);
adder_16bit add2_3 (L2_AB[63:48],L2_AB[127:112],{C1_2_3[14:0],L2_Cin[2]},S4);
assign S = L3_S;
assign C_out = L3_Cin;
endmodule
TB如下
module pipelined_adder_LKAHD_tb();
reg clk,rst;
reg [63:0]a,b;
reg cin;
wire cout;
wire [63:0]y;
pipelined_adder_LKAHD T4 (.clk(clk),.rst(rst),.A(a),.B(b),.C_in(cin),.S(y),.C_out(cout));
always #5 clk = ~clk;
integer i = 0;
initial
begin
rst = 1;
clk = 0 ;
cin = 1;
#10
rst = 0;
for(i=0;i<16;i=i+1)
begin
a = $random;
b = $random;
#10;
end
cin = 0;
for(i=0;i<16;i=i+1)
begin
a = $random;
b = $random;
#10;
end
end
endmodule