컴퓨터구조 프로젝트
(ALU 설계)
[목 차]
1. 개 요
2. 전체 블록도 및 흐름도
2-1. ALU Block Diagram
2-2. ALU Flow Chart
3. 프로그램
3-1. ALU.vhd
3-2. ALU_MODULE.vhd
4. 회로도
4-1. ALU Circuit : 전체 회로도
4-2. ALU Circuit : 입력 부분
4-3. ALU Circuit : ALU_MODULE_INPUT
4-4. ALU Circuit : ALU_MODULE_OUTPUT
4-5. ALU Circuit : ALU_MODULE_NORMAL
4-6. ALU Circuit : 출력 부분
5. 시뮬레이션
5-1. AND 시뮬레이션
5-2. OR 시뮬레이션
5-3. ADD 시뮬레이션
5-4. SUBTRACT 시뮬레이션
5-5. Set on less than 시뮬레이션
6. 결 론
1. 개요
CPU 내부 장치 중 하나인 ALU를 VHDL을 이용하여 제작한다. 입력 값은 Address A, B 32bit, ALU Operation이 있고, 출력 값은 결과 값 32bit, Zero flag, Overflow flag, Set flag가 있다. ALU Operation에 대한 동작사항은 아래와 같다.
|
ALU Operation |
Function | |
|
Binvert |
Operation | |
|
0 |
00 |
and |
|
0 |
01 |
or |
|
0 |
10 |
add |
|
1 |
10 |
subtract |
|
1 |
11 |
set on less than |
2. 전체 블록도 및 흐름도
2-1. ALU Block Diagram
2-2. ALU Flow Chart
3. 프로그램
3-1. ALU.vhd
library ieee;
use ieee.std_logic_1164.all;
library work;
entity ALU is
port (a, b: in BIT_VECTOR (31 downto 0);
Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT_VECTOR (31 downto 0);
Zero, overflow, set: out BIT);
end ALU;
architecture structural of ALU is
component ALU_MODULE_INPUT
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut: out BIT);
end component;
component ALU_MODULE_NORMAL
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut: out BIT);
end component;
component ALU_MODULE_OUT
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut, overflow, set: out BIT);
end component;
signal c: BIT_VECTOR (30 downto 0);
signal Less: BIT;
signal CarryIn, CarryOut: BIT;
begin
CarryIn <= '0';
Less <= '0';
REPEATE:
for I in 0 to 31 generate
INPUT_CASE:
if (I=0) generate
C0: ALU_MODULE_INPUT port map (a(I), b(I), Less, CarryIn, Binvert, Operation, Result(I), c(I));
end generate INPUT_CASE;
NORMAL_CASE:
if (I <= 30 and I >= 1) generate
C1: ALU_MODULE_NORMAL port map (a(I), b(I), Less, c(I-1), Binvert, Operation, Result(I), c(I));
end generate NORMAL_CASE;
OUTPUT_CASE:
if (I=31) generate
C2: ALU_MODULE_OUT port map (a(I), b(I), Less, c(I-1), Binvert, Operation, Result(I), CarryOut, overflow, set);
end generate OUTPUT_CASE;
end generate REPEATE;
process(Result)
begin
if ( not (Result(0) or Result(1) or Result(2) or Result(3) or Result(4) or Result(5) or Result(6) or Result(7) or Result(8) or Result(9) or Result(10) or Result(11) or Result(12) or Result(13) or Result(14) or Result(15) or Result(16) or Result(17) or Result(18) or Result(19) or Result(20) or Result(21) or Result(22) or Result(23) or Result(24) or Result(25) or Result(26) or Result(27) or Result(28) or Result(29) or Result(30) or Result(31)) = '0' ) then
Zero <= '0';
else
Zero <= '1';
end if;
end process;
end structural;
3-2. ALU_MODULE.vhd
library ieee;
use ieee.std_logic_1164.all;
entity ALU_MODULE_INPUT is
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut: out BIT);
end ALU_MODULE_INPUT;
architecture struct_ALU_MODULE_INPUT of ALU_MODULE_INPUT is
signal Binvert_b: BIT;
signal xor1, and1, and2: BIT;
signal Sub: BIT;
signal sub_Result, sub_CarryOut: BIT;
begin
process(Binvert, Operation, CarryIn, sub_Result, sub_CarryOut)
begin
Sub <= '1';
-- Case and
if (Binvert='0' and Operation="00") then
Result <= a and b;
CarryOut <= '0';
-- Case or
elsif (Binvert='0' and Operation="01") then
Result <= a or b;
CarryOut <= '0';
-- Case add
elsif (Binvert='0' and Operation="10") then
Result <= a xor b xor CarryIn;
CarryOut <= (a and b) or (CarryIn and a) or (CarryIn and b);
-- Case subtract
elsif (Binvert='1' and Operation="10") then
sub_Result <= a xor (not b) xor CarryIn;
sub_CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
Result <= sub_Result xor Sub xor sub_CarryOut;
CarryOut <= (sub_Result and Sub) or (sub_CarryOut and sub_Result) or (sub_CarryOut and Sub);
-- Case set on less than
elsif (Binvert='1' and Operation="11") then
Result <= Less;
sub_Result <= a xor (not b) xor CarryIn;
sub_CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
CarryOut <= (sub_Result and Sub) or (sub_CarryOut and sub_Result) or (sub_CarryOut and Sub);
else
Result <= '0';
CarryOut <= '0';
end if;
end process;
end struct_ALU_MODULE_INPUT;
entity ALU_MODULE_NORMAL is
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut: out BIT);
end ALU_MODULE_NORMAL;
architecture struct_ALU_MODULE_NORMAL of ALU_MODULE_NORMAL is
signal Binvert_b: BIT;
signal xor1, and1, and2: BIT;
begin
process(Binvert, Operation, CarryIn)
begin
-- Case and
if (Binvert='0' and Operation="00") then
Result <= a and b;
CarryOut <= '0';
-- Case or
elsif (Binvert='0' and Operation="01") then
Result <= a or b;
CarryOut <= '0';
-- Case add
elsif (Binvert='0' and Operation="10") then
Result <= a xor b xor CarryIn;
CarryOut <= (a and b) or (CarryIn and a) or (CarryIn and b);
-- Case subtract
elsif (Binvert='1' and Operation="10") then
Result <= a xor (not b) xor CarryIn;
CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
-- Case set on less than
elsif (Binvert='1' and Operation="11") then
Result <= Less;
CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
else
Result <= '0';
CarryOut <= '0';
end if;
end process;
end struct_ALU_MODULE_NORMAL;
entity ALU_MODULE_OUT is
port (a, b, Less, CarryIn, Binvert: in BIT;
Operation: in BIT_VECTOR (1 downto 0);
Result: inout BIT;
CarryOut, overflow, set: out BIT);
end ALU_MODULE_OUT;
architecture struct_ALU_MODULE_OUT of ALU_MODULE_OUT is
begin
process(Binvert, Operation, Result, CarryIn, a, b)
begin
-- Case and
if (Binvert='0' and Operation="00") then
Result <= a and b;
CarryOut <= '0';
-- Case or
elsif (Binvert='0' and Operation="01") then
Result <= a or b;
CarryOut <= '0';
-- Case add
elsif (Binvert='0' and Operation="10") then
Result <= a xor b xor CarryIn;
CarryOut <= (a and b) or (CarryIn and a) or (CarryIn and b);
-- Case subtract
elsif (Binvert='1' and Operation="10") then
Result <= a xor (not b) xor CarryIn;
CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
-- Case set on less than
elsif (Binvert='1' and Operation="11") then
Result <= Less;
set <= a xor (not b) xor CarryIn;
CarryOut <= (a and (not b)) or (CarryIn and a) or (CarryIn and (not b));
end if;
if ( Binvert='0' and Operation="10" and a='0' and b='0' and Result='1') then
overflow <= '1';
elsif ( Binvert='0' and Operation="10" and a='1' and b='1' and Result='0') then
overflow <= '1';
elsif ( Binvert='1' and Operation="10" and a='0' and b='1' and Result='1') then
overflow <= '1';
elsif ( Binvert='1' and Operation="10" and a='1' and b='0' and Result='0') then
overflow <= '1';
else
overflow <= '0';
CarryOut <= '0';
Result <= '0';
set <= '0';
end if;
end process;
end struct_ALU_MODULE_OUT;
4. 회로도
4-1. ALU Circuit : 전체 회로도
4-2. ALU Circuit : 입력 부분
ALU에 최초에 입력되는 부분이다. 그림에서 보이는 것처럼 a, b가 32bit, Binvert, Operation이 각각 입력되고, CarryIn, Less값이 내부 시그널로 사용되었다. 모듈은 CarryOut과 Result값을 출력으로 낸다.
4-3. ALU Circuit : ALU_MODULE_INPUT
ALU 모듈을 크게 3가지로 나눠진다. 처음에 입력 받을 때 쓰는 모듈, 2~31 bit 연산에 사용되는 모듈, 출력 값을 내는 모듈로 나눠진다. 위의 회로도는 처음에 입력 받을 때 쓰는 모듈로서, 2~31 bit 연산에 사용하는 모듈가 거의 유사하다. 하지만 sub 연산에서 b포트를 보수화 시키고 LSB에 1을 더하는 연산이 추가로 있으므로 그 부분이 다르다.
4-4. ALU Circuit : ALU_MODULE_OUTPUT
출력에 사용되는 모듈이다. 다른 모듈과 다른 점은 overflow, set flag를 확인하는 부분이 추가되어 있다. 마지막으로 남은 flag인 Zero flag는 출력 모듈에서 처리하는 것이 아니라 모든 Result값을 확인해야 하므로 출력 모듈을 나오고 난 뒤 확인하는 부분이 있다.
4-5. ALU Circuit : ALU_MODULE_NORMAL
2~31 bit의 값을 처리하는 모듈로서 나머지 두 모듈의 가장 기본이 되는 모듈이 된다. Operation값과 Binvert값을 확인하여 a, b포트에 대하여 각각의 연산을 수행하게 된다. 그리고 Result값과 CarryOut값을 출력으로 낸다.
4-6. ALU Circuit : 출력 부분
출력이 되는 부분으로서 마지막 모듈에서 나온 overflow값과 set값을 그대로 출력을 해주고 각 모듈에서 나오는 Result값을 확인하여 Zero flag의 활성화 여부를 확인하게 된다. 그리고 각 모듈의 Result값을 합쳐서 출력을 하게 된다.
5. 시뮬레이션
Altelra ModelSim 6.4를 사용하여 and, or, add, subtract, set on less than에 대한 시뮬레이션을 해본다. 각각의 결과는 아래와 같다.
5-1. AND
Binvert 값을 “0”, Operation 값을 “00”으로 주고 and 연산을 시뮬레이션 해본다. 입력 값을
a는 “00001000000000100000000000000011”, b는 “00000001000000000000000000000011”을 주었을 때 결과가 올바르게 나온 것을 알 수 있다.
5-2. OR
Binvert 값을 “0”, Operation 값을 “01”으로 주고 or 연산을 시뮬레이션 해본다. 입력 값을
a는 “00001000000000100000000000000011”, b는 “00000001000000000000000000000011”을 주었을 때 결과가 올바르게 나온 것을 알 수 있다.
5-3. ADD
Binvert 값을 “0”, Operation 값을 “10”으로 주고 add 연산을 시뮬레이션 해본다. 입력 값을
a는 “00000000000000000000000000001111”, b는 “00000000000000000000000000000101”을 주었을 때 15 + 5 = 20으로 결과가 올바르게 나온 것을 알 수 있다.
5-4. SUBTRACT
Binvert 값을 “1”, Operation 값을 “10”으로 주고 sub 연산을 시뮬레이션 해본다. 입력 값을
a는 “00000000000000000000000000001111”, b는 “00000000000000000000000000000101”을 주었을 때 15 - 5 = 10으로 결과가 올바르게 나온 것을 알 수 있다.
5-5. Set on less than
Binvert 값을 “1”, Operation 값을 “11”으로 주고 slt 연산을 시뮬레이션 해본다. 입력 값을 a는 “00000000000000000000000000000001”, b는 “00000000000000000000000000000011”을 주었을 때 a는 1, b는 3으로 a가 더 작으므로 set flag가 활성화된 것으로 보아 올바르게 결과가 나온 것을 알 수 있다.
6. 결론
이번 프로젝트에서 설계된 ALU는 일반적인 Carry 처리연산을 하였지만 ALU설계에서 Carry Prediction을 사용한다면 성능측면에서 상당한 이득이 될 것으로 예상된다. 일반적으로 디지털 덧셈의 성능은 Carry에 달려있는데 지금 만든 ALU는 64 gate delay를 가지고 있다. 그리고 과제 진행에 있어 ALU를 직접 설계해보면서 책에서는 배울 수 없는 많은 것을 배웠고, ALU의 내부가 어떻게 돌아가는지 알게 되었다.