Full Adder는 Carry IN을 받을 수 있는 가산기를 의미한다.
Full Adder를 만들기 위해서는 먼저 다음과 같은 진리표를 작성한다.
| 입력 | 출력 | |||
| A | B | Cin | S | 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 |
이 진리표를 통해서 식을 구할 수 있다.
1) Sum
진리표를 그대로 식으로 나타낸 다음 불 대수를 이용하여 최적화한다.
$$ S = \bar{A}\bar{B}C_{in}+\bar{A}B\bar{C}_{in}+A\bar{B}\bar{C}_{in}+ABC_{in} = C_{in}(\overline{A\oplus B}) + \bar{C}_{in}(A\oplus B) = A\oplus B\oplus C_{in} $$
2) Carry Out

K-map의 사각형을 식으로 나타내면 다음과 같다.
$$ C_{out} = AC_{in} + BC_{in} + AB $$
위 식을 살펴보면 단순히 두개 이상의 입력이 1일 때 출력을 1로 하는 것을 알 수 있다.
이제 구한 식을 토대로 Verilog 코드를 작성한다. 다음과 같이 작성할 수 있다.
module FullAdder(S, Cout, a, b, Cin);
output S, Cout;
input a, b, Cin;
wire w0, w1, w2, w3;
xor xor2_0(w0, a, b);
xor xor2_1(S, w0, Cin);
nand nand2_0(w1, a, b);
nand nand2_1(w2, a, Cin);
nand nand2_2(w3, b, Cin);
nand nand3_0(Cout, w1, w2, w3);
endmodule
Carry Out을 계산하는 부분이 원래 식과 다름을 알 수 있는데 이는 드모르간의 법칙을 이용하여 AND에서 NAND로 식을 바꾸었기 때문이다. 이렇게 NAND로 바꾸게 될 경우 AND에 비해서 Transistor Cost가(=Area) 적게 소모된다.
(단, FPGA는 Lookup-table을 이용해서 Logic Gate를 구현하기 때문에 별로 의미는 없다.)
테스트벤치를 위한 코드는 다음과 같다.
`timescale 1ns / 100ps
module tb_FullAdder;
reg a, b, Cin;
wire S, Cout;
FullAdder uut(S,Cout,a,b,Cin);//uut means unit under test
initial begin
a = 0; b = 0; Cin = 0;
#10 a = 0; b = 0; Cin = 1;
#10 a = 0; b = 1; Cin = 0;
#10 a = 0; b = 1; Cin = 1;
#10 a = 1; b = 0; Cin = 0;
#10 a = 1; b = 0; Cin = 1;
#10 a = 1; b = 1; Cin = 0;
#10 a = 1; b = 1; Cin = 1;
#10 ;
end
endmodule
Full Adder의 경우 경우의 수가 몇가지 없으므로 전수조사를 하도록 한다.
테스트 결과는 다음과 같다. (S/W: ModelSim)

최종적으로 합성된 결과물을 RTL Viewer로 보면 다음과 같이 합성되었음을 알 수 있다. (S/W: Intel Quartus)
