【Verilog】一文读懂加法器:全加器、半加器、溢出、行为级描述

一、1位二进制半加器

没有进位carry-in,只有两个加数相加得到和sum和进位cout。

代码

module top_module( 
    input a, b,
    output cout, sum );
	assign cout = a&b; //cout为a和b的与
	assign sum = a^b; //sum为a和b的亦或
endmodule

二、1位二进制全加器

含有进位carry-in,还有两个数相加,结果为和sum和进位输出carry-out。

真值表

A和B相加,Ci-1表示前一个加法器的进位值,Si是运算结果sum,Ci是进位值。
在这里插入图片描述

表达式

根据真值表,可以写出相对应的表达式:
Si=Ai⊕Bi⊕Ci-1
Ci= Ai*Bi+Ci-1(A1⊕Bi)

框图

在这里插入图片描述

代码

根据逻辑表达式写1位二进制全加器:

module top_module(
	input a,b,cin,
	output sum,cout 
	);
	assign sum = a^b^cin;
	assign cout = a&b|cin&(a^b);
endmodule

或者也可以根据框图来写:

module add1(
	input a,b,cin,
	output cout,sum
	);
	wire S1,T1,T2,T3;
	xor x1(S1,a,b);
	xor x2(sum,S1,cin);
	and a1(T3,a,b);
	and a2(T2,b,cin);
	and a3(T1,a,cin);
	or o1(cout,T1,T2,T3);
endmodule

三、 3位二进制加法器

可以实例化三个1位二进制加法器,然后将上一位加法器的carry-out连到当前的carry-in,将当前的carry-out连接到下一位加法器的carry-in。这里,我用for循环构造了三个1位二进制加法器,最后组成了3位二进制加法器。

module top_module(
	input [2:0]a,b,
	input cin,
	output [2:0]cout,
	output [2:0]sum
	);
reg [2:0] temp_cout;
integer i;
always @(*) begin
	for(i = 0;i<3;i++)begin
		if(i == 0)begin
			sum[0] = a[0]^b[0]^cin;
			temp_cout[0] = a[0]&b[0] | cin&(a[0]^b[0]);
		end
		else begin
			sum[i] = a[i]^b[i]^temp_cout[i-1];
			temp_cout[i] = a[i]&b[i] | temp_cout[i-1]&(a[i]^b[i]);
		end
	end
end
assign cout = temp_cout;
endmodule

四、用行为级描述

如下图,直接用x+y。其中结果sum要比加数多一位,sum的最高位表示进位carry-out。
在这里插入图片描述

代码示例1

module top_module (
    input [3:0] x,
    input [3:0] y, 
    output [4:0] sum);
    assign sum = x+y;
endmodule

代码示例2

//100位的二进制加法
module top_module( 
    input [99:0] a, b,
    input cin,
    output cout,
    output [99:0] sum );
    assign {cout,sum} = a+b+cin;//结果的最高位是进位cout,低位是结果sum
endmodule

五、关于溢出

两个补码相加,就会出现溢出的情况。当两个正数相加产生负结果,或两个负数相加产生正结果时,就会发生溢出。可以根据两个加数和结果sum的最高位符号位来判断是否溢出。补码的最高位是符号位,0为正数、1为负数。如果两个加数都为负数(最高位为1),和为正数(最高位是0)的话,则溢出;如果两个数都为正数(最高位为0),和为负数(最高位为1)的话,则溢出。

代码

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 
 
    assign s = a + b;
    //判断溢出:两个正数相加出现了负数或者两个负数相加出现正数。
    //如果两个加数都为负数(最高位为1),和为正数(最高位是0)的话,则溢出;如果两个数都为正数(最高位为0),和为负数(最高位为1)的话,则溢出。
    assign overflow = a[7]&b[7]&~s[7] | ~a[7]&~b[7]&s[7];

endmodule

六、十进制数的加法

10进制数的加法是以10为基数的。这里,我们通过实例化四个4位十进制加法器(bcd_fadd)来构造一个16位的十进制加法器。

代码

module top_module( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );
reg [3:0]temp_cout;
generate
	genvar i;
	for(i = 0;i<4;i++)begin:BCD_Adder
		if(i==0)begin
			bcd_fadd bcd_fadd_u(
				.a(a[i+3:0]),
				.b(b[i+3:0]),
				.cin(cin),
				.cout(temp_cout[0]),
				.sum(sum[i+3:0])
				);
		end
		else begin
			bcd_fadd bcd_fadd_u(
				.a(a[i*4+3:i*4]),
				.b(b[i*4+3:i*4]),
				.cin(temp_cout[i-1]),
				.cout(temp_cout[i]),
				.sum(sum[i*4+3:i*4])
				);
		end
	end
	assign cout = temp_cout[3];
endgenerate
endmodule
  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值