컴퓨터 구조 - CPU 구조 - ALU
CPU 구조
1. ALU (Arithmetic Logic Unit)
CPU에서 연산을 담당하는 부분이다. 덧셈, 뺄셈, 곱셈, 나눗셈 같은 산술 연산뿐만 아니라 AND, NOT, OR, XOR등 비트 논리 연산과 비트 시프트 연산까지 담당하여 계산한다.
1) 간략한 세부 구조
현대 컴퓨터의 Processor에는 강력한 기능의 ALU가 달려있다.
강력한 만큼 너무도 복잡하기에 여기에 모든 구조를 표기하기는 어렵다.
따라서 가장 기초적인 기능인 AND, OR, NAND, NOR, CMP(두 값이 같은지?) 논리 연산과 ADD, SUB 산술연산이 포함되어있고 연산 결과에 따라서 Condition Flag로 Overflow, Carry, Negative, Equal, Zero가 Set되는 ALU를 만들어보겠다.
아래는 1bit에 대해서 AND 혹은 OR 연산을 하는 회로이다.
문제는 이렇게되면 결과값을 OR 연산을 쓸지 AND 연산된 값을 쓸지 알수가 없다.
따라서 Selector 값에 따라 출력값을 결정해줄 수 있는 MUX를 사용해야한다.
기본적으로 다수의 연산을 지원할 수 있는 것은 MUX 때문이다.
이전 포스팅에서 언급했듯이 MUX는 여러 입력 중 하나를 선택하여 그 입력만 출력되도록 하는 회로이다.
해당 MUX에서 제공하는 선택권의 개수가 많을 수록 제공하는 연산의 수도 많아진다.
가령 Selector 값이 3 line이라면 $2^{3}$ 이기 때문에 최대 8개의 연산을 지원하는 방식이다.
위에서 만든 AND와 OR 연산을 하는 회로에 2x1 MUX를 달아보도록 하겠다.
위의 그림은 2 x 1 MUX를 달아둔 모습이다.
Selector의 값이 0이면 AND 연산, 1이면 OR 연산을 출력한다.
몇개의 연산이 더 늘어날 것이므로 이후에는 MUX를 간략화해서 표기하도록 하겠다.
ADD 연산은 이전 포스팅에서 언급했던 전 가산기를 사용하면 된다. 그렇게되면 아래와 같은 형태가 된다.
위 회로는 1bit에 대해서 AND, OR, ADD 연산을 할 수 있는 회로 유닛이다.
이 유닛을 32개 붙이고 아래 자리수의 Carry_out을 윗 자리의 Carry_in으로 연결하게 되면 32bit에 대해서 AND, OR, ADD 연산을 할 수 있는 회로가 된다.
SUB 연산은 어차피 2의 보수를 이용해서 연산을 하기 때문에 B에 대해서 2의 보수를 취할 수 있는 로직이 있으면 된다. 2의 보수는 전체를 Invert 한 뒤에 1을 더해주면 된다.
따라서 위와 같이 각 자리 B의 값에 NOT을 취해준 뒤에 0번째 bit에서 Carry_in에 1을 넣어주게되면 자연스럽게 2의 보수를 취할 수 있게 된다.
NAND와 NOR은 어떻게하면 될까?
드모르간 법칙에 의해 NAND와 NOR은 아래와 같이 치환된다.
$\overline{(a+b)}=\overline{a}\cdot \overline{b}$
$\overline{a\cdot b}=\overline{a}+\overline{b}$
따라서 아래와 같이 A에도 NOT을 달고 MUX를 통해 각 자리 선택해서 출력할 수 있게 해주면 된다.
NOR을 구하고 싶을때 위의 식에 따라 A 비트를 NOT, B 비트를 NOT으로 세팅해준뒤에 AND 값을 출력하면 되고, NAND를 구하고 싶을땐 A 비트를 NOT, B 비트를 NOT을 세팅해준뒤에 OR 값을 출력하면 된다.
이제 Condition Flag를 세팅할 것인데 종류가 Negative, Overflow, Carry, Equal, Zero가 있다. 여기서 Negative Flag 부터 알아보자.
ALU에 Less값을 추가한다. 1번째 ALU를 제외하고 모든 less 값은 0을 받게되고 받은 less값을 그대로 출력한다.
단 32번째 ALU의 경우에는 SUM한 결과를 0번째 ALU의 less로 넣는다.
마지막 32번째 ALU의 경우 부호비트로 사용하므로 연산결과값이 1이면 음수이다. 따라서 1번째 ALU의 less값이 1로 반환되면 결과값이 음수이므로 Negative를 1로 세팅하면 된다.
Overflow의 경우 32번째 ALU의 Carry_in과 Carry_out이 다르면 overflow가 났다는 뜻이므로 그때 1로 세팅해주면 된다.
Carry는 32번째 Carry_out 값을 동일하게 따라가면 된다.
Zero는 결과값이 0일때 True로 세팅되는 것으로 ADD일때나 SUB 연산시 나오는 result를 모두 OR 게이트에 넣은 후 NOT을 취해주는 값으로 세팅해주면 된다. 어느비트라도 1이라면 OR 이후에는 1로 세팅되므로 결과값이 모두 0일때나 0으로 세팅된다.
Equal은 추가적인 회로가 필요하다. A와 B값이 같다면 1로 세팅되는게 Equal flag인데 각 비트의 A와 B에 XNOR을 붙인다. 이는 1bit 비교기에서 두 비트가 같은지 확인하는 회로에서 차용한 것이다.
그리고 XNOR 연산 결과를 모두 AND로 묶게 되면 모두가 1일때만 1로 반환되므로 모든 비트가 같음을 확인하는 Equal Flag 값으로 사용할 수 있다.