若是不考慮來自低位的進位將兩個1二進制數相加,稱爲半加。函數
實現半加運算的邏輯電路稱爲半加器。3d
真值表
code
邏輯表達式和
\begin{align}\notag
s = a{b}' + {a}'b
\end{align}
邏輯表達式進位輸出
\begin{align}\notag
co = ab
\end{align}
blog
verilog codeci
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
testbenchinput
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個數相加。這種運算稱爲全加,所用的電路稱爲全加器。it
真值表
class
邏輯表達式和
test
\begin{align}\notag
s = {({a}'{b}'{ci}' + a{b}'ci + {a}'bci + ab{ci}'})'
\end{align}
邏輯表達式進位輸出
\begin{align}\notag
co = {({a}'{b}' + {b}'{ci}' + {a}'{ci}')}'
\end{align}
基礎
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)能夠表示位
\begin{align}\notag
co_{i} = a_{i}b_{i} + (a_{i} + b_{i})(ci_{i})
\end{align}
從全加器的真值表寫出第i位和s(i)的邏輯式:
\begin{align}\notag
s_{i} = a_{i}{b_{i}}'{ci_{i}}' + {a_{i}}'b_{i}{ci_{i}}' + {a_{i}}'{b_{i}}'ci_{i} + (a_{i} + b_{i})ci_{i}
\end{align}
上式變換位異或函數位:
\begin{align}\notag
s_{i} = a_{i} \oplus b_{i} \oplus ci_{i}
\end{align}
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] 數字電子技術基礎(第五版) 閻石主編