verilog 实现加法器
半加器
如果不考虑来自低位的进位将两个1二进制数相加,称为半加。
实现半加运算的逻辑电路称为半加器。
真值表
>> 逻辑表达式和 s=ab′+a′b >> 逻辑表达式进位输出 co=ab
verilog code
module halfadder(
output s, //sum
output co, //carry
input a,
input b
);
assign s = a ^ b;
assign co = a & b;
//assign {co,s} = a + b;
endmodule
testbench
module halfadder_tb;
wire s;
wire co;
reg a;
reg b;
initial
begin
a = 0;
b = 0;
#10 a = 0 ;b = 0;
#10 a = 0 ;b = 1;
#10 a = 1 ;b = 0;
#10 a = 1 ;b = 1;
#10 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
halfadder u_halfadder(
.s(s),
.co(co),
.a(a),
.b(b)
);
endmodule
全加器
在将两位多位二进制数相加时,除了最低位以外,每位都应该考虑来自低位的进位,即将两个对应位的加数和来自低位的进位3个数相加。这种运算称为全加,所用的电路称为全加器。
真值表
逻辑表达式和
s=(a′b′ci′+ab′ci+a′bci+abci′)′ >> 逻辑表达式进位输出 co=(a′b′+b′ci′+a′ci′)′
verilog code
module fulladder(
output s, //sum
output co, //carry to high bit
input a,
input b,
input ci //carry from low bit
);
//RTL level
assign s = ~((~a&~b&~ci)||(a&~b&ci)||(~a&b&ci)||(a&b&~ci));
assign co = ~((~a&~b)||(~b&~ci)||(~a&~ci));
//assign {co,s} = a + b + ci;
endmodule
testbench
module fulladder_tb;
wire s;
wire co;
reg a;
reg b;
reg ci;
initial
begin
ci = 0; a = 0 ;b = 0;
#10 ci = 0; a = 0 ;b = 1;
#10 ci = 0; a = 1 ;b = 0;
#10 ci = 0; a = 1 ;b = 1;
#10 ci = 1; a = 0 ;b = 0;
#10 ci = 1; a = 0 ;b = 1;
#10 ci = 1; a = 1 ;b = 0;
#10 ci = 1; a = 1 ;b = 1;
#10 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
fulladder u_fulladder(
.s(s),
.co(co),
.a(a),
.b(b),
.ci(ci)
);
endmodule
多位加法器
串行进位加法器
依次将低位全加器的进位输出co接到全加器的进位输入端ci,就可以构成多位加法器。
显然,每一位的相加结果都必须等到低一位的进位产生才能建立起来,因此,这种结构的电路称为串行进位加法器(或称为行波进位加法器)。
verilog code (fulladder为上面所述的全加器)
module serialadder(
output [3:0] s,
output co,
input [3:0] a,
input [3:0] b,
input ci
);
wire [3:0] co_tmp;
fulladder u_add0(
.s(s[0]), //sum
.co(co_tmp[0]), //carry to high bit
.a(a[0]),
.b(b[0]),
.ci(ci) //carry from low bit
);
fulladder u_add1(
.s(s[1]), //sum
.co(co_tmp[1]), //carry to high bit
.a(a[1]),
.b(b[1]),
.ci(co_tmp[0]) //carry from low bit
);
fulladder u_add2(
.s(s[2]), //sum
.co(co_tmp[2]), //carry to high bit
.a(a[2]),
.b(b[2]),
.ci(co_tmp[1]) //carry from low bit
);
fulladder u_add3(
.s(s[3]), //sum
.co(co_tmp[3]), //carry to high bit
.a(a[3]),
.b(b[3]),
.ci(co_tmp[2]) //carry from low bit
);
assign co = co_tmp[3];
endmodule
testbench
module serialadder_tb;
wire [3:0] s;
wire co;
reg [3:0] a;
reg [3:0] b;
reg ci;
initial
begin
a = 4'b0000; b = 4'b0000; ci = 0;
#10 a = 4'b1111; b = 4'b1111; ci = 0;
#10 a = 4'b1100; b = 4'b1001; ci = 0;
#10 a = 4'b0111; b = 4'b0110; ci = 0;
#10 a = 4'b0101; b = 4'b0101; ci = 1;
#10 a = 4'b1110; b = 4'b1001; ci = 1;
#10 a = 4'b0010; b = 4'b0110; ci = 1;
#10 a = 4'b0110; b = 4'b1100; ci = 1;
#10 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
serialadder u_serialadder(
.s(s),
.co(co),
.a(a),
.b(b),
.ci(ci)
);
endmodule
超前进位加法器
超前进位信号的产生原理
- ab = 1 --> co = 1
- a + b = 1,且ci = 1 --> co =1
两位多位数中第i位相加产生的进位输出co(i)可以表示位
coi=aibi+(ai+bi)(cii)
>> 从全加器的真值表写出第i位和s(i)的逻辑式: si=aibi′cii′+ai′bicii′+ai′bi′cii+(ai+bi)cii >> 上式变换位异或函数位: si=ai⊕bi⊕cii
verilog code
module carry_look_aheadadder(
output [3:0] s,
output co,
input [3:0] a,
input [3:0] b,
input ci
);
wire [3:0] co_tmp;
wire [3:0] cin;
assign cin[3:0] = {co_tmp[2:0],ci};
//计算中间进位
assign co_tmp[0] = a[0]&b[0] || (a[0] || b[0])&(cin[0]);
assign co_tmp[1] = a[1]&b[1] || (a[1] || b[1])&(cin[1]);
assign co_tmp[2] = a[2]&b[2] || (a[2] || b[2])&(cin[2]);
assign co_tmp[3] = a[3]&b[3] || (a[3] || b[3])&(cin[3]);
//计算和
assign s[0] = a[0] ^ b[0] ^ cin[0];
assign s[1] = a[1] ^ b[1] ^ cin[1];
assign s[2] = a[2] ^ b[2] ^ cin[2];
assign s[3] = a[3] ^ b[3] ^ cin[3];
assign co = co_tmp[3];
endmodule
testbench
module carry_look_aheadadder_tb;
wire [3:0] s;
wire co;
reg [3:0] a;
reg [3:0] b;
reg ci;
initial
begin
a = 4'b0000; b = 4'b0000; ci = 0;
#10 a = 4'b1111; b = 4'b1111; ci = 0;
#10 a = 4'b1100; b = 4'b1001; ci = 0;
#10 a = 4'b0111; b = 4'b0110; ci = 0;
#10 a = 4'b0101; b = 4'b0101; ci = 1;
#10 a = 4'b1110; b = 4'b1001; ci = 1;
#10 a = 4'b0010; b = 4'b0110; ci = 1;
#10 a = 4'b0110; b = 4'b1100; ci = 1;
#10 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
carry_look_aheadadder u_carry_look_aheadadder(
.s(s),
.co(co),
.a(a),
.b(b),
.ci(ci)
);
endmodule
参考资料
[1] 数字电子技术基础(第五版) 阎石主编
形而上者谓之道 形而下者谓之器。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义