【计算机组成原理】 Verilog语言编写32位并行加法器的理解
近日,为了完成本学期的计算机组成原理课程大作业的要求,我开始学习利用verilog语言编写的一套32位并行加法器以完成在整个项目中提高运算速度的基本要求。考虑到verilog语言和硬件设计的关联性,我们需要从结构上完成对并行加法器的理解。
32位加法器注重逻辑结构的顺序,本文主要简单介绍了加法器的逻辑顺序并附上代码说明,较为简单。
加法器结构
首先,并行加法器的特点基本决定了其组成结构,每一位均由对应的一位全加器确定输出结果,且每一位的对应进位输入将由超前进位加法器(CLA)在本位的运算开始前计算得到。
CLA基本功能:输入各位级的值,在全加器计算之前先行计算出各位级对应的进位输入,便于全加器计算并得到输出的值。
整个代码的流程框架为:
基础-1位全加器模块add;4位CLA模块cla
进阶1-使用1位全加器和4位CLA构成4位全加器
进阶2-使用4位CLA模块构成16位CLA模块
应用-使用16位CLA模块构成32位并行加法器
代码展示与理解
下文附上整理为逻辑顺序架构的32位超前进位加法器的整体代码,语句的基本注释已经附在代码块中。
//基础-设置一位全加器模块
module add(X,Y,Cin,F,Cout);
input X,Y,Cin;
output F,Cout;
assign F = X ^ Y ^ Cin;
assign Cout = (X ^ Y) & Cin | X & Y;
endmodule
//一位全加器输入x,y,Cin;输出F,Cout;
//基础-设置4位超前进位加法器CLA
module CLA(c0,c1,c2,c3,c4,p1,p2,p3,p4,g1,g2,g3,g4);
input c0,g1,g2,g3,g4,p1,p2,p3,p4;
output c1,c2,c3,c4;
//直接采取超前进位方式,完成相应的进位的计算
assign c1 = g1 ^ (p1 & c0),
c2 = g2 ^ (p2 & g1) ^ (p2 & p1 & c0),
c3 = g3 ^ (p3 & g2) ^ (p3 & p2 & g1) ^ (p3 & p2 & p1 & c0),
c4 = g4 ^ (p4 & g3) ^ (p4 & p3 & g2) ^ (p4 & p3 & p2 & g1) ^(p4 & p3 & p2 & p1 & c0);
endmodule
//4位CLA输入本级的基本参数,输出对应的各位级上的进位输入值
//进阶1-在一位全加器基础上设置四位并行进位加法器
module add_4(x,y,c0,c4,F,Gm,Pm); //定义4位加法器模块
input [4:1] x; // 设置4位二进制输入x,y
input [4:1] y;
input c0; //设置二进制输入进位c0
output c4,Gm,Pm; //设置二进制输出进位c4
output [4:1] F; //设置二进制输出4位数F
wire p1,p2,p3,p4,g1,g2,g3,g4; //设置wire类型线变量用于过程中计算
wire c1,c2,c3;
//分四级完成单位上的一位全加器输出
add add1(
.X(x[1]),
.Y(y[1]),
.Cin(c0),
.F(F[1]),
.Cout()
);
add add2(
.X(x[2]),
.Y(y[2]),
.Cin(c1),
.F(F[2]),
.Cout()
);
add add3(
.X(x[3]),
.Y(y[3]),
.Cin(c2),
.F(F[3]),
.Cout()
);
add add4(
.X(x[4]),
.Y(y[4]),
.Cin(c3),
.F(F[4]),
.Cout()
);
CLA CLA(
.c0(c0),
.c1(c1),
.c2(c2),
.c3(c3),
.c4(c4),
.p1(p1),
.p2(p2),
.p3(p3),
.p4(p4),
.g1(g1),
.g2(g2),
.g3(g3),
.g4(g4)
);
assign p1 = x[1] ^ y[1],
p2 = x[2] ^ y[2],
p3 = x[3] ^ y[3],
p4 = x[4] ^ y[4];
assign g1 = x[1] & y[1],
g2 = x[2] & y[2],
g3 = x[3] & y[3],
g4 = x[4] & y[4];
assign Pm = p1 & p2 & p3 & p4, //Pm和Gm分别为进位传递输出和进位产生输出
Gm = g4 ^ (p4 & g3) ^ (p4 & p3 & g2) ^ (p4 & p3 & p2 & g1);
endmodule
//进阶2-在4位CLA的基础上设置16位CLA模块
module CLA_16(A,B,c0,S,px,gx);
input [16:1] A;
input [16:1] B;
input c0;
output gx,px;
output [16:1] S;
wire c4,c8,c12;
wire Pm1,Gm1,Pm2,Gm2,Pm3,Gm3,Pm4,Gm4;
//同理分四级完成对应位数上的累加和超前进位计算
add_4 add1(
.x(A[4:1]),
.y(B[4:1]),
.c0(c0),
.c4(),
.F(S[4:1]),
.Gm(Gm1),
.Pm(Pm1)
);
add_4 add2(
.x(A[8:5]),
.y(B[8:5]),
.c0(c4),
.c4(),
.F(S[8:5]),
.Gm(Gm2),
.Pm(Pm2)
);
add_4 add3(
.x(A[12:9]),
.y(B[12:9]),
.c0(c8),
.c4(),
.F(S[12:9]),
.Gm(Gm3),
.Pm(Pm3)
);
add_4 add4(
.x(A[16:13]),
.y(B[16:13]),
.c0(c12),
.c4(),
.F(S[16:13]),
.Gm(Gm4),
.Pm(Pm4)
);
assign c4 = Gm1 ^ (Pm1 & c0),//计算各个分级位进位输出取值
c8 = Gm2 ^ (Pm2 & Gm1) ^ (Pm2 & Pm1 & c0),
c12 = Gm3 ^ (Pm3 & Gm2) ^ (Pm3 & Pm2 & Gm1) ^ (Pm3 & Pm2 & Pm1 & c0);
assign px = Pm1 & Pm2 & Pm3 & Pm4,//Pm和Gm分别为16进位传递输出和进位产生输出
gx = Gm4 ^ (Pm4 & Gm3) ^ (Pm4 & Pm3 & Gm2) ^ (Pm4 & Pm3 & Pm2 & Gm1);
endmodule
//进阶3-由16位CLA直接设置32位CLA
module add32(A,B,S,C32);
input [32:1] A;
input [32:1] B;
output [33:1] S;
output C32;
wire px1,gx1,px2,gx2; //设置中间操作变量
wire c16;
//将32位数分为两个16位操作数带入16位CLA模块完成并行计算过程
CLA_16 CLA1(
.A(A[16:1]),
.B(B[16:1]),
.c0(0),
.S(S[16:1]),
.px(px1),
.gx(gx1)
);
CLA_16 CLA2(
.A(A[32:17]),
.B(B[32:17]),
.c0(c16),
.S(S[32:17]),
.px(px2),
.gx(gx2)
);
assign c16 = gx1 ^ (px1 && 0), //默认AB相加时c0 = 0
C32 = gx2 ^ (px2 && c16); //确定32位输出进位为c32
S[33]=C32
endmodule
//32位并行加法器输入为32位二进制数A,B;最终的输出为33位二进制数S(将整体进位整合到二进制数当中成为第33位);