개요
가감산기와 7세그먼트 디스플레이, IC 74147 등을 구현하여 조잡한 8비트 (덧셈/뺄셈만 가능한)계산기를 만들어보겠습니다.
완성된 결과물은 여기에서 확인할 수 있습니다.
1. 핵심 - 가산기 (Adder)
가산기 두개의 2진수의 덧셈을 수행하는 논리회로입니다. ALU의 핵심이 되는 회로이기도 합니다.
반가산기 (Half Adder)
두개의 입력 A
와 B
를 받고, S
(Sum, 합)과 C
(Carry, 자리올림)를 출력하는 논리회로입니다.
A | B | S | C |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
전가산기와 다르게 자리올림 입력이 없기 때문에, 거의 사용되지 않습니다.
전가산기 (Full Adder)
2개의 반가산기와 OR 게이트로 구성되어 있습니다. A
, B
, Cin
(Carry in, 자리올림 입력)을 받고, S
, Cout
(Carry out, 자리올림 출력)을 출력합니다.
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비트 2진수 덧셈을 수행하므로, 2비트 이상의 덧셈을 수행하기 위해선 전가산기 여러개를 연결해서 사용합니다.
다중 비트 가산기
다중 비트 가산기에도 RCA(Ripple Carry Adder), CLA(Carry Lookahead Adder) 등의 여러 종류가 있습니다.
이 계산기에서 사용할 다중 비트 가산기는 RCA입니다.
RCA (Ripple Carry Adder)
4비트 RCA, +
기호가 있는 부분은 전가산기입니다.
단순히 전가산기를 병렬로 연결한 구조입니다. 비트의 수가 많아진다면, 자리올림이 전달되고 판단되는 시간이 길어지는 단점이 있습니다.
가감산기 (Adder/Subtractor)
4비트 가감산기, Sign
은 M
(Minus)라고도 불립니다.
가감산기는 덧셈과 뺄셈을 모두 수행할 수 있는 논리회로입니다. 위에서 만든 4비트 RCA에 Bn xor Sign
을 통해 Sign
이 1이라면 B
를 보수로 만들어 뺄셈을 수행합니다.
예시:
A | B | Sign | S | Cout |
---|---|---|---|---|
0010b (2) | 0011b (3) | 0 (Add) | 0101b (5) | 0 |
0101b (5) | 0011b (3) | 1 (Sub) | 0010b (2) | 1 |
감산기에서 Cout
(MSB = 최상위 비트)는 무시하며, 가산기에서 Cout
이 1
이라면 Overflow가 발생한 것입니다.
지금까진 4비트 회로를 만들었지만, 같은 논리로 8비트로 확장하면 8비트 계산기를 만들 수 있습니다.
2. 입력/출력 데이터 표시하기 - BCD 코드와 7세그먼트 디스플레이
BCD 코드
BCD(Binary Coded Decimal) 코드는 10진수를 2진수로 표현하는 방법입니다. 4비트를 사용하며, 0부터 9까지의 숫자를 표현할 수 있습니다:
Binary | BCD | Binary | BCD |
---|---|---|---|
0000 | 0 | 0101 | 5 |
0001 | 1 | 0110 | 6 |
0010 | 2 | 0111 | 7 |
0011 | 3 | 1000 | 8 |
0100 | 4 | 1001 | 9 |
만약 2진수가 9보다 크다면, 6(= 0110b
)을 더해 보정하여 사용합니다. 예를 들어, 1100b
(= 12)은 9보다 크므로, 1100b
+ 0110b
= 1 0010b
를 사용합니다.
7세그먼트 디스플레이 (7-Segment Display)
7세그먼트 디스플레이는 7개의 획으로 숫자나 문자를 표시하는 디스플레이입니다. 아래와 같이 A..G
까지의 획이 있습니다.
디스플레이에 숫자를 표시하기 위해 BCD to 7-Segment Decoder가 필요합니다.
해당 디코더는 아래와 같은 진리표를 가지고 있습니다:
BCD (A, B, C, D) | 7 Segment (A, B, C, D, E, F, G) |
---|---|
0 0 0 0 | 1 1 1 1 1 1 0 |
0 0 0 1 | 0 1 1 0 0 0 0 |
0 0 1 0 | 1 1 0 1 1 0 1 |
0 0 1 1 | 1 1 1 1 0 0 1 |
0 1 0 0 | 0 1 1 0 0 1 1 |
0 1 0 1 | 1 0 1 1 0 1 1 |
0 1 1 0 | 1 0 1 1 1 1 1 |
0 1 1 1 | 1 1 1 0 0 0 0 |
1 0 0 0 | 1 1 1 1 1 1 1 |
1 0 0 1 | 1 1 1 1 0 1 1 |
Binary to BCD
그런데 여러 자리의 10진을 7세그먼트 디스플레이에 표시하기 위해선 어떻게 해야할까요?
당연하겠지만 2개의 디스플레이를 사용하며, 이때 자릿수를 나눠서 BCD로 변환하는 Binary to BCD가 필요합니다. 해당 변환기는 Double Dabble 알고리즘을 사용하여 구현할 수 있습니다.
예를 들어, 2진수 10110110b
(= 182)를 BCD로 변환한다면, 아래와 같이 출력됩니다:
100의 자리 | 10의 자리 | 1의 자리 |
---|---|---|
0001bcd | 1000bcd | 0010bcd |
자세한 내용은 링크된 Wikipedia 문서를 참조해주세요.
3. 키패드 구현하기
지금까지 구현한것만 해도 8비트 계산기를 만들 수 있지만, 일반적으로 사용하는 계산기의 형태는 아닙니다. 이 차례에서 키패드를 통한 입력을 받을 수 있도록 구현해보겠습니다.
이 회로의 핵심은 10진수 입력을 BCD 코드로 변환하는 IC 74147과 D flip flop
을 사용한 레지스터입니다.
IC 74147
IC 74147은 10진수 입력을 BCD 코드로 변환하는 인코더입니다. 아래와 같은 진리표를 가지고 있습니다:
Decimal | Inputs (1, 2, 3, 4, 5, 6, 7, 8, 9) | Outputs (A, B, C, D) |
---|---|---|
0 | 1 1 1 1 1 1 1 1 1 | 1 1 1 1 |
1 | 0 1 1 1 1 1 1 1 1 | 1 1 1 0 |
2 | 1 0 1 1 1 1 1 1 1 | 1 1 0 1 |
3 | 1 1 0 1 1 1 1 1 1 | 1 1 0 0 |
4 | 1 1 1 0 1 1 1 1 1 | 1 0 1 1 |
5 | 1 1 1 1 0 1 1 1 1 | 1 0 1 0 |
6 | 1 1 1 1 1 0 1 1 1 | 1 0 0 1 |
7 | 1 1 1 1 1 1 0 1 1 | 1 0 0 0 |
8 | 1 1 1 1 1 1 1 0 1 | 0 1 1 1 |
9 | 1 1 1 1 1 1 1 1 0 | 0 1 1 0 |
눈치를 챘다면, 해당 칩을 사용할땐 입력/출력에 NOT 게이트를 사용해야 작동합니다.
회로도는 아래와 같습니다:
레지스터로 자릿수 구분하기
우리가 만들 계산기는 8비트 계산기이기 때문에, 총 3 자릿수의 숫자를 입력받아야 합니다. 때문에 위 IC 74147과 SIPO(Serial-in Parallel-out, 직렬 입력 - 병렬 출력) 시프트 레지스터를 활용하여 3 자릿수의 숫자를 입력받을 수 있도록 구현해보겠습니다.
먼저, 키패드 버튼를 눌렀을때 레지스터에 BCD 값을 저장하고, 레지스터의 클럭은 버튼을 눌렀을 때 발생하는 펄스를 사용합니다.
예시:
- 키패드에서
3
을 누름 - 레지스터 1에
0011b
저장 => 병렬 출력:0011b
0000b
0000b
- 키패드에서
5
를 누름 - 레지스터 1에 저장된 값(3)을 레지스터 2로 이동하고, 레지스터 1에
0101b
저장 => 병렬 출력:0101b
0011b
0000b
- 키패드에서
1
을 누름 - 같은 방법으로 시프트하고, 레지스터 1에
0001b
저장 => 병렬 출력:0001b
0101b
0011b
이렇게 입력을 받을 수 있습니다.
입력받은 숫자를 8비트 2진수로 변환하기
이제 입력받은 숫자를 8비트 2진수로 변환해야 합니다. 저같은 경우엔 100의 자리는 값에 100을 곱하고, 10의 자리는 값에 10을 곱하고, 1의 자리는 값에 1을 곱하여 더하는 방식으로 구현했습니다. (더 좋은 방법이 있다면 피드백 부탁드립니다.)
그리고 이렇게 만들어진 피연산자 하나를 SIPO 레지스터에 저장하고 레지스터를 리셋한 다음, 같은 절차로 2번째 피연산자를 저장합니다. 피연산자를 저장하기 위한 펄스는 Enter
, +
, -
버튼이며, Enter
는 단순히 펄스만 제공, +
와 -
는 펄스를 제공하고 D Flip Flop
을 통해 Sign
을 지정합니다.
이렇게 완성된 회로도는 아래와 같습니다:
마지막: 부가적인 기능 추가하기
이제 마지막으로 +
-
와 같은 기호를 표시하기 위한 LED 매트릭스를 추가하고, 계산 결과가 Overflow가 발생했는지 확인하기 위한 LED를 추가하면 8비트 계산기가 완성됩니다.