半加器、全加器的FPGA实现

1、什么是半加器、全加器?

        半加器电路是指对两个输入数据位相加,输出一个结果位和进位,没有进位输入的加法器电路。 是实现两个一位二进制数的加法运算电路。
        全加器是在半加器的基础上的升级版,除了加数和被加数加和外还要加前上一级传进来的进位信号。

2、如何写一个半加器模块?

2.1、设计方法

        半加器有两个1位2进制数输入,输出1个进位、1个结果位。真值表如下:

真值表


        根据真值表,可以绘制出半加器的波形图:

在这里插入图片描述

  • in1:加数1,2进制,1位
  • in2:加数2,2进制,1位
  • sum:结果位,2进制,1位
  • cout:进位,2进制,1位

2.2、Verilog实现

        根据上面的波形图可以编写Verilog代码如下:

/* //方法1:直接使用加法(assign语句)进行计算
module half_adder(
	input		in1,	//加数1
	input 		in2,	//加数2
	output		sum,	//两个数的加和
	output		cout	//加数和的进位
);
//使用拼接运算符分别表示:和 与 进位
assign {cout,sum} = in1 + in2; 

endmodule */

/* //方法2:使用always块
module half_adder(
	input			in1,	//加数1
	input 			in2,	//加数2
	output  reg		sum,	//两个数的加和
	output	reg		cout	//加数和的进位
);
//使用拼接运算符分别表示:和 与 进位
always@(*)begin
	{cout,sum} = in1 + in2;
end
 
endmodule */

//方法3:根据真值表把组合逻辑电路化简成与非门的形式
/**************真值表 
   in1	   in2	  summ	  cout
	0		0		0		0
	0		1		1		0
	1		0		1		0
	1		1		0		1
******/
//与非门化简有	sum = in1 ^ in2;	cout = in1 & in2
module half_adder(
	input	in1,	//加数1
	input 	in2,	//加数2
	output	sum,	//两个数的加和
	output	cout	//加数和的进位
);
//根据化简结果分别表示:和 与 进位
assign sum = in1 ^ in2;	
assign cout = in1 & in2;
 
endmodule

        在这里提供了三种实现的方法。三种方法分别生成的RTL视图如下:

方法1

在这里插入图片描述

在这里插入图片描述

 

  • 方法1、方法2生成的RTL视图相同,这说明这两种方法是组合逻辑电路的两种不同表达形式
  • 方法1、2因为使用了位拼接、加法运算,所以生成的电路里含有半加器
  • 方法3使用组合逻辑:异或生成结果位、与逻辑生成进位

2.3、Testbench

        Testbench文件如下:

`timescale 1ns/1ns				//时间刻度:单位1ns,精度1ns

module tb_half_adder();			//仿真模块
	
//输入reg 定义
reg	in1;
reg in2;

//输出wire定义
wire cout;
wire sum;

//设置初始化条件
initial begin
	in1<=1'b0;					//初始化为0
	in2<=1'b0;					//初始化为0
end

//产生激励条件
//always #10:表示每10个时钟周期实现后面的操作
always #10 in1<= $random %2;	//每10个时钟周期产生1个随机数
								//然后对随机数模2(结果要么0、要么1),再将其赋值给加数1
always #10 in2<= $random %2;	//同上

//例化被测试模块
half_adder u_half_adder(
	.in1(in1),
	.in2(in2),
	
	.sum(sum),	
	.cout(cout)
);
	
endmodule

2.4、仿真结果

        使用ModelSim执行仿真,仿真出来的波形如下所示:

在这里插入图片描述


        因为激励是随机产生的,我们这里就随便取三个点来验证。从波形图可以看到:

  • L1:in1 in2 sum cout 分别为1010
  • L1:in1 in2 sum cout 分别为1101
  • L1:in1 in2 sum cout 分别为0110
  • L1、L2、L3 这三个点的输出都是符合真值表的

3、如何写一个全加器模块?

3.1、设计方法

全加器有两个1位2进制数输入,一个低位传来的进位;输出1个进位、1个结果位。全加器的真值表如下:

在这里插入图片描述

 

        不难发现,低位的进位输入其实就相当于一个输入(可以称之为输入3)。
        根据真值表,可以绘制出全加器的波形图:

在这里插入图片描述

3.2、Verilog实现

        根据上面的波形图可以编写Verilog代码如下:

//全加器
module full_adder(
	input		in1,	//加数1
	input 		in2,	//加数2
	input 		cin,	//低位向高位的进位
	output		sum,	//两个数的加和
	output		cout	//加数和的进位
);

assign {cout,sum} = in1 + in2 + cin;	//使用位拼接 和 加法运算

endmodule

        RTL视图如下:

在这里插入图片描述

3.3、Testbench

        Testbench文件如下:

`timescale 1ns/1ns				//时间刻度:单位1ns,精度1ns

module tb_full_adder();			//仿真模块

//输入reg 定义
reg	in1;
reg in2;
reg cin;

//输出wire定义
wire cout;
wire sum;

//设置初始化条件
initial begin
	in1<=1'b0;					//初始化为0
	in2<=1'b0;					//初始化为0
	cin<=1'b0;					//初始化为0
end

//产生激励条件
//always #10:表示每10个时钟周期实现后面的操作
always #10 in1<= $random %2;	//每10个时钟周期产生1个随机数
								//然后对随机数模2(结果要么0、要么1),再将其赋值给加数1
always #10 in2<= $random %2;	//同上
always #10 cin<= $random %2;	//同上

//例化被测试模块
full_adder u_full_adder(
	.in1(in1),
	.in2(in2),
	.cin(cin),
	.sum(sum),	
	.cout(cout)
);
	
endmodule

3.4、仿真结果

        使用ModelSim执行仿真,仿真出来的波形如下所示:

在这里插入图片描述

        

        因为激励是随机产生的,我们这里就随便取三个点来验证。从波形图可以看到:

  • L1:in1 in2 cin sum cout 分别为10101
  • L1:in1 in2 cin sum cout 分别为10010
  • L1:in1 in2 cin sum cout 分别为11111
  • L1、L2、L3 这三个点的输出都是符合真值表的

4、调用半加器实现全加器

4.1、设计方法

前面讲过,全加器不过是在半加器的基础上多了一个低位进位信号(这个信号可以看作是一个加数3)。输出与半加器相同。
那么全加器可以看是三个输入在做加法,那么我们可以先使用一个半加器计算出两个加数1、加数2的结果,在用低位进位(加数3)与之前的结果相加,就可以得到全加器的结果了。
简而言之,我们可以通过调用两个半加器模块来实现全加器。

        再来看一遍半加器和全加器的真值表:

在这里插入图片描述

在这里插入图片描述


例化第1个半加器模块,输入分别为加数1、加数2、则其输出无外乎4种情况:

  • 输入为in1= 0 ,in2 = 0;输出 sum1 = 0,cout1 = 0 ,例化第2个半加器模块,输入分别为sum1 、低位进位cin ,有如下情况:
    1.1 cin =0 ,那么 sum2= 0,cout2 = 0
    1.2 cin =1 ,那么 sum2= 1,cout2 = 0
  • 输入为in1= 0 ,in2 = 1;输出 sum1 = 1,cout1 = 0 ,例化第2个半加器模块,输入分别为sum1 、低位进位cin ,有如下情况:
    2.1 cin =0 ,那么 sum2= 1,cout2 = 0
    2.2 cin =1 ,那么 sum2= 0,cout2 = 1
  • 输入为in1= 1 ,in2 = 0;输出 sum1 = 1,cout1 = 0 。情况同2
  • 输入为in1= 1 ,in2 = 1;输出 sum1 = 0,cout1 = 1,例化第2个半加器模块,输入分别为sum1 、低位进位cin ,有如下情况:
    4.1 cin =0 ,那么 sum2= 0,cout2 = 1
    4.2 cin =1 ,那么 sum2= 1,cout2 = 1

        

        将上述情况与全加器的真值表对比,发现:

  • sum2与全加器的结果为sum相同
  • cout则为 cou1 || cout 2

        据此,可以画出实例化的框图:

在这里插入图片描述

4.2、Verilog实现

        根据上面的模块框图可以编写Verilog代码如下:

module full_adder(
	input		in1,	//加数1
	input 		in2,	//加数2
	input 		cin,	//低位向高位的进位
	output		sum,	//两个数的加和
	output		cout	//加数和的进位
);
//wire define
//模块之间的连线,结合模块图理解
wire	h0_cout;
wire	h1_cout;
wire	h0_sum;

assign cout = h0_cout || h1_cout;
 
//例化半加器1
half_adder u1_half_adder(
	.in1(in1),		
	.in2(in2),		
	.sum(h0_sum),	
	.cout(h0_cout)	
);

//例化半加器2
half_adder u2_half_adder(
	.in1(h0_sum),		
	.in2(cin),			
	.sum(sum),			
	.cout(h1_cout)	
);

endmodule

        生成的RTL视图如下:

在这里插入图片描述


        这与之前理论上的框图一致,分别例化了两个半加器模块。

4.3、其他

        Testbench文件同3.3。仿真结果同3.4.

  • 28
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的单刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值