Half Adder vs Full Adder
Half Adder (HA)
Adds 2 one-bit inputs. No carry-in. Used only at the least significant bit position.
Sum = A ⊕ B
Carry = A · B
Gates: 1 XOR + 1 AND
Full Adder (FA)
Adds 3 one-bit inputs (A, B, Cin). Chainable for multi-bit addition.
Sum = A ⊕ B ⊕ Cin
Cout = AB + Cin(A⊕B)
Gates: 2 XOR + 2 AND + 1 OR (= 2 half adders)
Logic Circuit Diagrams
Half Adder Circuit
Full Adder Circuit (two half adders)
Interactive Adder Simulator
Adder Simulator Interactive
Half Adder
Full Adder
4-bit Adder
Adder-Subtractor
A
0
+
B
0
=
Carry
0
Sum
0
0 + 0 = 0
Truth Tables
Half Adder
| A | B | Sum | Carry |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
Full Adder
| A | B | Cin | Sum | Cout |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
Ripple Carry Adder (4-bit)
Chain four full adders. The first stage uses a half adder (Cin = 0) or a full adder with Cin tied to 0. Each Cout feeds the next stage's Cin — the carry "ripples" from LSB to MSB.
Critical path: For an N-bit ripple carry adder, the worst-case delay is the carry propagation from bit 0 to bit N−1: τ = N × τ_FA. For N = 32 with τ_FA = 150 ps, this is 4.8 ns — limiting clock frequency to ~208 MHz. The Carry Lookahead Adder reduces this to O(log N) depth.
Verilog Implementations
Half Adder
module half_adder ( input wire a, b, output wire sum, carry ); assign sum = a ^ b; assign carry = a & b; endmodule
Full Adder (structural — two half adders)
module full_adder ( input wire a, b, cin, output wire sum, cout ); wire s1, c1, c2; half_adder ha1 (.a(a), .b(b), .sum(s1), .carry(c1)); half_adder ha2 (.a(s1), .b(cin), .sum(sum), .carry(c2)); assign cout = c1 | c2; endmodule
4-bit Ripple Carry Adder (structural)
module rca4 ( input wire [3:0] a, b, input wire cin, output wire [3:0] sum, output wire cout ); wire [3:0] c; full_adder fa0(.a(a[0]),.b(b[0]),.cin(cin), .sum(sum[0]),.cout(c[0])); full_adder fa1(.a(a[1]),.b(b[1]),.cin(c[0]), .sum(sum[1]),.cout(c[1])); full_adder fa2(.a(a[2]),.b(b[2]),.cin(c[1]), .sum(sum[2]),.cout(c[2])); full_adder fa3(.a(a[3]),.b(b[3]),.cin(c[2]), .sum(sum[3]),.cout(c[3])); assign cout = c[3]; endmodule
N-bit Adder — behavioral (let synthesizer optimize)
module adder #(parameter N = 32) (
input wire [N-1:0] a, b,
input wire cin,
output wire [N-1:0] sum,
output wire cout
);
assign {cout, sum} = a + b + cin;
endmodule
Adder-Subtractor (4-bit)
// When sub=0: out = a + b
// When sub=1: out = a - b (a + ~b + 1, 2's complement)
module adder_subtractor #(parameter N = 4) (
input wire [N-1:0] a, b,
input wire sub, // 0=add, 1=subtract
output wire [N-1:0] result,
output wire cout // also serves as borrow indicator
);
assign {cout, result} = a + (b ^ {N{sub}}) + sub;
endmodule
Adder Types Comparison
| Adder Type | Delay | Area | Use case |
|---|---|---|---|
| Ripple Carry (RCA) | O(N) | Low | Small N (<8-bit), area-constrained |
| Carry Lookahead (CLA) | O(log N) | Medium | 32-bit ALU — balanced speed/area |
| Carry Select (CSLA) | O(√N) | Medium-high | Mid-range, simpler than CLA |
| Prefix (Kogge-Stone) | O(log N) | High (many wires) | 64-bit, high-performance CPU ALU |
| Carry Save (CSA) | O(1) per layer | Medium | Multiplier accumulate trees |
For the carry lookahead deep dive with generate/propagate logic, Kogge-Stone prefix trees, and Verilog: Carry Lookahead Adder →