先设计出一位全加器,在根据分层次分模块设计出四位加法器。
module full_adder(
input A,B,Ci,
output reg S,Co);
/*参数说明:
输入:
A,B为一位二进制被加数,Ci为来自低位的进位
输出:
S为和,Co为进位
*/
always@(*)
begin
case({A,B,Ci})
3'b000:begin S=0;Co=0; end
3'b001:begin S=1;Co=0; end
3'b010:begin S=1;Co=0; end
3'b011:begin S=0;Co=1; end
3'b100:begin S=1;Co=0; end
3'b101:begin S=0;Co=1; end
3'b110:begin S=0;Co=1; end
3'b111:begin S=1;Co=1; end
endcase
end
endmodule
//filename:tb_fulladder.v
`timescale 10ns/1ns
module tb_fulladder();
reg A,B,Ci;
wire S,Co;
full_adder U(A,B,Ci,S,Co);
initial
$monitor($time,"\tA=%b,B=%b,Ci=%b,S=%b,Co=%b",A,B,Ci,S,Co);
initial
begin
A=0;B=0;Ci=0;
#5;
A=1;B=0;Ci=1;
#5;
A=1;B=1;Ci=0;
#5;
$stop;
end
endmodule
串行进位加法器。采用四个全加器构成四位数加法器。其原理图如图所示,将低位的进位输出信号接到高位的进位输出端。
module full_adder(
input A,B,Ci,
output reg S,Co);
/*参数说明:
输入:
A,B为一位二进制被加数,Ci为来自低位的进位
输出:
S为和,Co为进位
*/
always@(*)
begin
case({A,B,Ci})
3'b000:begin S=0;Co=0; end
3'b001:begin S=1;Co=0; end
3'b010:begin S=1;Co=0; end
3'b011:begin S=0;Co=1; end
3'b100:begin S=1;Co=0; end
3'b101:begin S=0;Co=1; end
3'b110:begin S=0;Co=1; end
3'b111:begin S=1;Co=1; end
endcase
end
endmodule
module _4adder(
input [3:0] A,B,
input Ci,
output [3:0] S,
output Co);
/*参数说明:
输入:
A,B为四位二进制被加数,Ci为来自低位的进位
输出:
S为和,Co为进位
*/
wire C0,C1,C2;
full_adder U0(A[0],B[0],Ci,S[0],C0);
full_adder U1(A[1],B[1],C0,S[1],C1);
full_adder U2(A[2],B[2],C1,S[2],C2);
full_adder U3(A[3],B[3],C2,S[3],Co);
endmodule
//filename:tb_4adder.v
`timescale 10ns/1ns
module tb_74HC283();
reg [3:0] A,B;
reg Ci;
wire [3:0] S;
wire Co;
/*参数说明:
输入:
A,B为一位二进制被加数,Ci为来自低位的进位
输出:
S为和,Co为进位
*/
_74HC283 U(A,B,Ci,S,Co);
initial
$monitor($time,"\tA=%b,B=%b,Ci=%b,S=%b,Co=%b",A,B,Ci,S,Co);
initial
begin
A=4'b0000;B=4'b0000;Ci=0;
#5;
A=4'b0000;B=4'b0000;Ci=1;
#5;
A=4'b1111;B=4'b1111;Ci=0;
#5;
A=4'b1111;B=4'b1111;Ci=1;
#5;
$stop;
end
endmodule
行为级建模加法器的功能明晰的,直接列真值表行为级建模,但是在编写过程中发现会出现这样
case({A,B,Ci})
9'b0000_0000_0:begin S=4'b0000;Co=0; end
9'b0000_0001—0:begin S=4'b0001;Co=0; end
......
endcase
case语句会出现512条语句,显然不可取。
数据流建模:
由于串行进位加法器速度受到进位信号的限制。人们又设计出一种多位数超前进位加法逻辑电路。
定义两个中间变量:产生变量Gi,传输变量Pi。这两个变量都与进位信号无关。通过代换将各位进位信号表达为只含有Gi,Pi与Ci-1的逻辑表达式(如下),所以个位的进位信号都只与两个加数和向最低位的进位信号Ci-1有关,因此它们是可以并行产生的。
难点核心体现在这个超前进位产生电路中,上面我们知道超前进位产生电路输入和输出的逻辑表达式之后,采用数据流建模即可。
//filename:ahead_gene_circuit.v
module ahead_gene_circuit(
input [3:0] P,G,
input Ci,
output [3:0] C);
/*参数说明:
输入:
P,G为定义的中间变量,产生变量Gi,传输变量Pi
Ci为来自低位的进位
输出:
C为各位的进位信号
*/
//根据各位进位信号的逻辑表达式,进行数据流建模。
assign C[0]=G[0]|(P[0]&Ci);
assign C[1]=G[1]|(P[1]&C[0]);
assign C[2]=G[2]|(P[2]&C[1]);
assign C[3]=G[3]|(P[3]&C[2]);
endmodule
//filename:tb_ahead_gene_circuit.v
`timescale 10ns/1ns
module tb_ahead_gene_circuit();
reg [3:0] P,G;
reg Ci;
wire [3:0] C;
ahead_gene_circuit U(P,G,Ci,C);
initial
$monitor($time,"\tP=%b,G=%b,Ci=%b,C=%b",P,G,Ci,C);
initial begin
P=4'b0000;G=4'b0000;Ci=0;
#5;
P=4'b1111;G=4'b1111;Ci=0;
#5;
P=4'b1010;G=4'b1010;Ci=0;
#5;
P=4'b1010;G=4'b1010;Ci=1;
#5;
$stop;
end
endmodule
//filename:ahead_gene_circuit.v
module ahead_gene_circuit(
input [3:0] P,G,
input Ci,
output [3:0] C);
/*参数说明:
输入:
Pi为传输信号,Gi为产生信号
Ci为对最低位的进位
输出:
C为各位的进位信号
*/
//根据各位进位信号的逻辑表达式,进行数据流建模。
assign C[0]=G[0]|(P[0]&Ci);
assign C[1]=G[1]|(P[1]&C[0]);
assign C[2]=G[2]|(P[2]&C[1]);
assign C[3]=G[3]|(P[3]&C[2]);
endmodule
module _74HC283(
input [3:0] A,B,
input Ci,
output [3:0] S,
output Co);
/*参数说明:
输入:A,B为被加数;Ci为对最低位的进位
输出:S为和,co为产生的进位信号
*/
//根据中间变量的定义表示出gi和pi。
wire [3:0] P,G,C;
assign P=A^B;
assign G=A&B;
//应用超前进位产生电路。
ahead_gene_circuit U(P,G,Ci,C);
assign Co=C[3];
assign S[3]=C[2]^P[3];
assign S[2]=C[1]^P[2];
assign S[1]=C[0]^P[1];
assign S[0]=Ci^P[0];
endmodule
`timescale 10ns/1ns
module tb2_74HC283();
reg [3:0] A,B;
reg Ci;
wire [3:0] S;
wire Co;
_74HC283 U(A,B,Ci,S,Co);
initial
$monitor($time,"\tA=%b,B=%b,Ci=%b,S=%b,Co=%b",A,B,Ci,S,Co);
initial begin
A=4'b0000;B=4'b0000;Ci=0;
#5;
A=4'b1111;B=4'b1111;Ci=0;
#5;
A=4'b1010;B=4'b1010;Ci=0;
#5;
A=4'b1010;B=4'b1010;Ci=1;
#5;
$stop;
end
endmodule
1。对于两个多位二进制数,也可以直接按位或,按位异或等等,不需要对数组一个一个进行或,异或等操作。
2.仿真时,对于多位二进制数进行波形显示时,点击对用变量左侧的加号,将数据波形分开,效果更好。
文章图片来自康华光编写的《电子技术基础——数字部分》