FPGA学习笔记(1):使用Verilog实现常见的加法器

使用Verilog实现常见的加法器

本文使用VerilogHDL实现一些简单的加法器,本人水平有限,希望大佬能够多指证

开发环境与仿真环境

  1. Quartus Prime(18.0)
  2. Modelsim

第一种加法器件:半加器

半加器可以用于计算两个单比特二进制数的和,C表征进位输出,S表述计算的结果。

半加器的真值表

在这里插入图片描述
化简以后的逻辑表达式可以表达为:
s = a’b+ab’
c = ab

Verilog 代码块

module half_adder 
(
	input 	IN_a,
	input 	IN_b,
	output 	s,
	output  C_o
);

assign s    = IN_a ^ IN_b ;
assign C_o  = IN_a & IN_b ;

endmodule

第二种加法器件:全加器

全加器相比于半加器考虑到了进位输入的情况,输入端口变为了a,b,cin,输入仍然是进位输出C_o以及加法运算结果s。

逻辑真值表

在这里插入图片描述
化简以后的逻辑表达式为
S = A ^ B ^ Cin
C_o = AB + Cin(A ^ B)

Verilog程序实现

// 全加器
module full_adder 
(
	input 	IN_a,
	input 	IN_b,
	input 	IN_Ci,
	output 	s,
	output  C_o
);

assign s    = IN_a ^ IN_b ^ IN_Ci;
assign C_o  = (IN_a & IN_b) | (IN_a & IN_Ci) | (IN_b & IN_Ci);

endmodule

进行仿真测试,编写测试用例

`timescale 1 ns/ 1 ps
module full_adder_vlg_tst();
// constants                                           
// general purpose registers

// test vector input registers
reg IN_Ci;
reg IN_a;
reg IN_b;
// wires                                               
wire C_o;
wire s;

// assign statements (if any)                          
full_adder i1 (
// port map - connection between master ports and signals/registers   
	.C_o(C_o),
	.IN_Ci(IN_Ci),
	.IN_a(IN_a),
	.IN_b(IN_b),
	.s(s)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin                          
IN_a=0;IN_b=0;IN_Ci=0;
#20;
IN_a=0;IN_b=1;IN_Ci=0;
#20;
IN_a=1;IN_b=1;IN_Ci=0;
#20;
IN_a=1;IN_b=0;IN_Ci=0;
#20;
IN_a=1;IN_b=0;IN_Ci=1;
#20;
IN_a=1;IN_b=1;IN_Ci=1;
#20; 
$stop;                                                      
// --> end                                             
                      
end                                                    
                                              
endmodule

仿真波形如下图所示:
在这里插入图片描述
可以看出在我们设计用例下完美的满足了全加器的设计要求

第三种加法器:RCA(行波进位加法器)

以上的文章介绍了单bit加法器的实现,将每个全加器的输出进位Cout接入到下一个全加器的Cin端即可实现多Bit加法器的实现。下图展示的式16bit的行波进位加法器的结构。
在这里插入图片描述
由上图可以看出得到进位c16的结果依赖于c15,c14,c13,…,c2,c1,c0,对于32-bit,64-bit,128-bit等加法器,进位链将显得更加长。所以,行波进位加法器设计简单,只需要级联全加器即可,但它的缺点在于超长的进位链,限制了加法器的性能。

Verilog 实现

module RCA #
(
	parameter integer width = 4 
)
(
	input  [width-1:0] A,
    input  [width-1:0] B,
    output [width-1:0] S,
     
    input  C_i,
    output C_o
);
wire [width:0] c;
genvar i;
generate
	for (i = 0; i < width; i=i+1) 
	begin :my_rca
		full_adder my_addr
		(
			.IN_a(A[i]),
			.IN_b(B[i]),
			.IN_Ci(c[i]),
			.s(S[i]),
			.C_o(c[i+1])
		);
	end
endgenerate
assign c[0]= C_i;
assign C_o = c[width];
endmodule

编写测试用例进行仿真测试

`timescale 1 ns/ 1 ps
module RCA_vlg_tst();
reg [3:0] A;
reg [3:0] B;
reg C_i;
// wires                                               
wire C_o;
wire [3:0]  S;                       
RCA i1 (
	.A(A),
	.B(B),
	.C_i(C_i),
	.C_o(C_o),
	.S(S)
);
initial                                                
begin                                                                           
A=7;B=8;C_i=0;
#20;
A=1;B=8;C_i=0;
#20;
A=1;B=2;C_i=1;
#20;
A=9;B=9;C_i=1;
#20;  
A=15;B=15;C_i=1;
#20; 
$stop;                                                                                                                
end                                                    
                                            
endmodule

仿真图像
在这里插入图片描述

第四种加法器:超前进位加法器

对于宽度较宽的加法器来说,行波进位加法器这一加法器设计思路的缺点就显得尤为突出,因为行波进位加法器的进位输出依赖于前一级的进位,造成
有较长时间的延迟,限制了加法器的性能,对于高速处理器等将是个极大的瓶颈。所以,下面介绍的超前进位加法器优化改进行波进位器。
设计思路:
令:
在这里插入图片描述
然后有:
在这里插入图片描述
对于4位的LCA可以得知:
在这里插入图片描述
根据此公式进行Verilog硬件设计:

// 生成传播信号(P)和生成信号(G)
module pg_gen 
(
	input 	A,
	input 	B,
	output  P,
	output  G
);
assign P = A ^ B;
assign G = A & B;
endmodule


module LCA #
(
	parameter integer width = 4
)
(
	input 	[width-1:0] IN_a,
	input 	[width-1:0] IN_b,
	input  				C_i, 
	output	[width-1:0] Sum,
	output  			C_o
);



wire [width-1:0] G;
wire [width-1:0] P;
wire [width:0] C;

genvar i;
generate
for (i = 0; i < width; i=i+1) 
	begin:my_lca
		pg_gen u_pg_gen
		(
			.A(IN_a[i]) ,
			.B(IN_b[i]) ,
			.P(P[i])    ,
			.G(G[i])
		);
	end
endgenerate


assign C[0] = C_i;
assign C[1] = G[0] + (C[0]&P[0]);
assign C[2] = G[1] + (G[0]&P[1]) + (C[0] & P[1] & P[0]);
assign C[3] = G[2] + (G[1]&P[2]) + (G[0] & P[2] & P[1]) + (C[0] & P[2] & P[1] & P[0]);
assign C[4] = G[3] + (G[2]&P[3]) + (G[1] & P[3] & P[2]) + (G[0] & P[3] & P[2] & P[1]) + (C[0] & P[3] & P[2] & P[1] & P[0]); 

assign C_o = C[width];


genvar k;
generate
	for( k=0; k<width; k=k+1) 
	begin:my_result
		 assign Sum[k] = P[k] ^ C[k];
	end
endgenerate

endmodule

使用的tb测试集

`timescale 1 ns/ 1 ps
module LCA_vlg_tst();
// constants                                           
// general purpose registers
// test vector input registers
reg C_i;
reg [3:0] IN_a;
reg [3:0] IN_b;
// wires                                               
wire C_o;
wire [3:0]  Sum;

// assign statements (if any)                          
LCA i1 (
// port map - connection between master ports and signals/registers   
	.C_i(C_i),
	.C_o(C_o),
	.IN_a(IN_a),
	.IN_b(IN_b),
	.Sum(Sum)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin                          
IN_a = 5;IN_b = 5; C_i = 0;
#40;
IN_a = 15;IN_b = 15; C_i = 0;
#40;
IN_a =  9;IN_b = 6; C_i = 1;
#40; 
IN_a =  7;IN_b = 8; C_i = 1;
#40; 
IN_a =  1;IN_b = 2; C_i = 1;
#40;                                                    
// --> end                                             
//$display("Running testbench");                       
end                                                    
                                             
endmodule

仿真波形
在这里插入图片描述
可以看出完成了设计需求
参考资料
1.参考资料\超前进位加法器原理与设计

  • 2
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为一名FPGA工程师,你可以通过以下方法来进行学习和实践: 1. 首先,熟悉FPGA的基础语法和概念。这包括了理解数字电路和信号处理的基础知识,以及了解FPGA代码的规范写法。你可以参考引用中提到的方法,先学习基础语法,再扎实相关知识。 2. 掌握不同的FPGA设计方式。除了使用原理图设计方式,你还可以尝试使用描述语言(如Verilog)进行设计。Verilog已经在FPGA开发和IC设计领域占据了领导地位,可以更好地满足实际项目的需求。你可以参考引用中的内容,了解Verilog的基础知识和逻辑电路的表示方式。 3. 在实践中提高设计能力。通过实际的项目设计和实现,你可以进一步提高自己的FPGA工程能力。尝试使用不同的开发工具,熟悉开发流程和操作。在实践中,你可以学习解决实际问题的方法和技巧,提高自己的设计能力。 4. 注意资源的合理使用。在FPGA设计中,要慎用%和/运算符,因为它们可能会消耗大量的资源。如果你的FPGA有内嵌的硬件乘法器或者除法器,可以使用它们来代替%,/运算符。而对于乘或除2的倍数次的操作,可以使用位移运算符来代替,这样可以减少资源的消耗。参考引用中的内容了解更多关于资源消耗的注意事项。 总结起来,作为一名FPGA工程师,你需要熟悉FPGA的基础语法和概念,掌握不同的设计方式,通过实践不断提升自己的设计能力,并注意资源的合理使用。这样,你将能够更好地进行FPGA工程师的学习和实践。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值