前言
之前的文章《verilog学习:使用VCS仿真验证一个全加器》,示范了下全加器,这篇文章就展开说一下加法器。
- 参考的视频有:
【老邱数电】半加器与全加器基础
单片机功能这么强,为什么还要组合逻辑器件?
数字电路中全加器是什么原理,专用的加法器芯片有哪些
0200410-104536-数字电路(1)-半加器和全加器的设计1
加法器(Adder)
- 加法器分为1位数加法器和多位数加法器,1位数加法器又可以分为半加器和全加器。
- 半加:两个1位二进制数相加,不考虑来自低位的进位(2个二进制数相加);
- 全加:两个1位二进制数与来自低位的进位三者相加(3个二进制数相加);
- 半加器+半加法和全加法是算术运算电路中的基本单元,它们是完成1位二进制相加的一种组合逻辑电路。
1.半加器(Half Adder)
不考虑低位的进位信号,将两个一位二进制数相加,只求本位和
- 二进制加法隐含条件:变量只取0和1;逢二进位;
- 真值表如下:
被加数A | 加数B | 和数S | 进位CO |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
由表中可以看见,这种加法没有考虑低位来的进位,所以称为半加。
- 跟据真值表,写出方程;根据表达式画出逻辑图:
1.1 半加器verilog设计代码
- 第一种写法:
module half_adder(
input a, //第一个加数a
input b, //第二个加数b
output sum, //和
output cout //位
);
assign sum=a ^ b; //sum=a⊕b
assign cout=a & b; //cout=ab
endmodule
- 第二种写法:
module half_adder(cout,sum,a,b);
output cout;
output sum;
input a,b;
wire cout,sum ;
//assign {cout,sum}=a+b;
assign cout = a & b;
assign sum = a ^ b;
endmodule
- 这两种写法综合出来的电路图是一样的,如下:
- 第三种写法:
module half_adder(cout,sum,a,b);
output cout;
output sum;
input a,b;
wire cout,sum ;
assign {cout,sum}=a+b;
//assign cout = a & b;
//assign sum = a ^ b;
endmodule
- 第三种写法综合出来的电路图如下:
1.2 测试文件testbench
`timescale 1ns/10ps
//`include "adder.v"
module adder_testbench;
reg a,b;
wire sum,cout;
integer i,j;
adder adder_te(
.sum ( sum ),
.cout ( cout),
.a ( a ),
.b ( b )
);
initial begin
a=0;b=0;
for(i=1;i<16;i=i+1)
#20 a=i;
end
initial begin
for(j=1;j<16;j=j+1)
#10 b=j;
end
initial begin
$monitor($time,,,"%d + %d ={%b,%d}",a,b,cout,sum);
#160 $finish;
end
endmodule
- 三种方式产生的波形文件都一样(注意,这里是1bit数相加,高位会溢出的)!
2.全加器(Full Adder)
- 半加法器中,不考虑输入进位,在全加法器设计中将第i-1位的输出进位当
作第i位的输入。 - 在将两个多位二进制数相加时,除了最低位以外,每一位都应该考虑来自低位的进位,即将两个对应位的加数和来自低位的进位3个数相加。这种运算称为全加,所用的电路称为全加器。
- 两个1位二进制数相加,考虑低位进位
一位全加器的真值表如下图,其中Ai为被加数,Bi为加数,相邻低位来的进位数为Ci-1,输出本位和为Si。向相邻高位进位数为Ci
进位输入Ci-1 | 被加数Ai | 加数Bi | 本位和Si | 进位输出Ci |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
一位全加器的逻辑表达式如下:
Si=Ai⊕Bi⊕Ci-1
电路图如下:
2.1 全加器verilog设计代码
- 第一种写法:
module full_add (a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg sum,cout;
always @(a or b or cin)begin
sum = a ^ b ^ cin;
cout = a & b |(cin&(a^b));
end
endmodule
综合出来的电路:
- 第二种写法:
module full_add (a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg sum,cout;
always @(a or b or cin)begin
sum = a ^ b ^ cin;
//cout = a & b |(cin&(a^b));
cout = (a & b)|(b & cin)|(a & cin);
end
endmodule
综合出来的电路:
- 第三种写法:
module full_add (a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg sum,cout;
reg m1,m2,m3;
always @(a or b or cin)begin
{cout,sum} = a + b + cin;
end
endmodule
综合出来的电路:
2.2 测试文件testbench
`timescale 1ns/10ps
//`include "full_add.v"
module full_add_testbench;
reg a,b,cin;
wire sum,cout;
integer i,j,k;
full_add full_adder_te(
.sum ( sum ),
.cout ( cout),
.a ( a ),
.b ( b ),
.cin ( cin)
);
initial begin
a=0;
for(i=1;i<16;i=i+1)
#20 a=~a;
end
initial begin
b=0;
for(j=1;j<16;j=j+1)
#10 b=~b;
end
initial begin
cin=0;
for(k=1;k<16;k=k+1)
#5 cin=~cin;
end
initial begin
$monitor($time,,,"%d + %d + %d ={%b,%d}",a,b,cin,cout,sum);
#80 $finish;
end
endmodule
- 这三种方法的仿真波形都一样,可对比:
3.其实还有很多种加法器,可深入了解
后记
- 查看往期文章,请点击跳转
《IC前端数字验证导学》
《如何学习verilog,如何快速入门?》
《verilog学习:一个简单的入门verilog例子》
《verilog学习:使用VCS仿真验证一个全加器》
- 如需长期追更,可以扫码关注下面这个公众号