使用Verilog实现常见的加法器
本文使用VerilogHDL实现一些简单的加法器,本人水平有限,希望大佬能够多指证
开发环境与仿真环境
- Quartus Prime(18.0)
- 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测试集文章来源:https://www.toymoban.com/news/detail-488964.html
`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.参考资料\超前进位加法器原理与设计文章来源地址https://www.toymoban.com/news/detail-488964.html
到了这里,关于FPGA学习笔记(1):使用Verilog实现常见的加法器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!