[컴퓨터 구조] The Processor(프로세서) - MIPS 명령어 실행 구조 구현

Yeontachi·2025년 5월 14일

이전 페이지에서 MIPS 명령어 일부를 지원하는 단순한 데이터 경로(Datapath)를 봤다면, 이번 페이지에서는 Datapath 위에 Control logic(제어 로직)을 추가하여 실제로 명령어를 실행할 수 있는 구조를 구현해본다.

ALU Control의 역할과 구현

MIPS의 ALU(Arithmetic Logic Unit)는 명령어 종류에 따라 다양한 연산을 수행해야 한다. 이를 위해 ALU에서는 4바트의 제어 신호가 입력되며, 이 신호 값에 따라 다음과 같은 연산 중 하나를 선택하여 수행한다.

ALU Control (4비트)수행 연산
0000AND
0001OR
0010ADD
0110SUBTRACT
0111SET ON LESS THAN (SLT)
1100NOR (확장용)

명령어 종류별 ALU 동작 방식

각 명령어 클래스에 따라 ALU는 고정된 연산을 수행하거나, R-type 명령어의 funct 필드에 따라 동작이 달라진다.

  • Load/Store(lw/sw) : 메모리 주소 계산 -> ALU Control = 0010
  • Branch equal(beq) : 두 레지스터 값 비교 -> Subtract -> Zero 여부 확인 -> ALU Control = 0110
  • R-type 명령어 : 연산 종류가 funct 필드에 따라 다름

예를 들어, R-type 명령어에서의 funct 필드가 100000 이면 add 연산이 필요하고, 100010이면 sub 연산이 필요하다. ALU는 이 funct 값을 기반으로 연산을 선택하며, 이를 위해 ALU Control 유닛은 다음 두 가지 입력을 기반으로 작동한다.

  • ALUOp(2비트) : opcode로부터 Main Control Unit이 생성
  • Funct(6비트) : R-type 명령어의 마지막 필드

이 두 값을 이용해, 조합 논리 회로는 최종 4비트의 ALU Control 신호를 생성한다.

ALU Control 동작 예시

명령어 종류ALUOpfunctALU 연산ALU Control
lw/sw00Xadd (주소 계산)0010
beq01Xsubtract (비교)0110
R-type10100000add0010
R-type10100010subtract0110
R-type10100100and0000
R-type10100101or0001
R-type10101010set on less than0111

Main Control Unit

ALU Control Unit이 ALUOp와 funct 필드를 사용하여 ALU 동작을 결정하고, 그 외 나머지 제어 신호를 생성하는 유닛이 Main Control Unit이다. 이 유닛은 명령어의 opcode 필드(31~26비트)를 기반으로, datapath의 구성 요소들을 제어하기 위한 여러 신호를 생성한다.

MIPS 명령어 클래스별 형식 요약

  • R-type : ALU 연산 결과는 rd에 저장되며, ALU 동작은 funct 필드에 따라 결정된다.
  • Load/Store : rs + offset 주소를 계산하여, lw는 해당 주소에서 값을 읽어 rt에 저장, sw는 rt의 값을 메모리에 저장한다.
  • Branch : ALU로 rs - rt 비교 후 Zero면, PC <- PC + 4 + offset x 4로 분기한다.

위 명령어 형식을 바탕으로, 제어 유닛은 아래의 사실들을 활용하여 설계된다.

  • opcode 필드는 항상 31~26에 위치 -> Main Control의 입력
  • rs, rt 필드25:21, 20:16 -> 항상 읽기 대상(R-type, branch, store 공통)
  • rd는 R-type에서 목적지, rt는 lw에서 목적지 -> 쓰기 대상 선택을 위해 MUX 필요
  • offset 필드(15:0)는 lw, sw, beq에서 즉시값으로 사용 -> sign-extension -> ALU 입력
  • funct는 R-type에서만 의미 있음 -> ALU Control에만 전달됨

따라서 목적지 레지스터를 선택하는 RegDst Mux와, ALU 입력을 정하는 ALUSrc MUX가 반드시 필요하다.

Main Control Unit의 출력 제어 신호

제어 신호비트 수설명
RegDst1비트목적지 레지스터 선택: rd(1) or rt(0)
ALUSrc1비트ALU의 두 번째 입력 선택: 레지스터 rt(0) or 즉시값(1)
MemtoReg1비트메모리 값 or ALU 결과를 레지스터에 저장
RegWrite1비트레지스터 파일 쓰기 여부
MemRead1비트메모리 읽기 수행 여부
MemWrite1비트메모리 쓰기 수행 여부
Branch1비트분기 수행 여부
ALUOp2비트ALU 제어 동작 지정용 (ALU Control 유닛으로 전달됨)
  • Control Unit은 명령어의 opcode 필드(31:26, 6비트)를 유일한 입력값으로 받는다. 이 단 하나의 입력만으로도 위와 같은 제어 신호들을 만들어낸다.

  • ALUOpALU Control 유닛에 입력되어 최종 ALU 연산 제어 신호(4비트)를 만든다.

  • 분기 명령어(beq)의 경우 다음 명령어의 주소 선택은 아래 조건에 따라 달라진다.

    • Branch 신호 = 1(명령어가 분기 명령어일 때)
    • ALU의 Zero 출력 = 1(rs == rt일 때)

    이 두 신호는 AND 게이트를 통해 결합되고, 그 결과가 PCSrc 신호를 만들어낸다. 따라서 PCSrc는 Control Unit의 직접 출력이 아니며, 하드웨어 내에서 유도되는(derived) 신호이다. 아래 회로도에서 PCSrc는 생략되며, 대신 Zero And Branch의 결과가 MUX에 연결되어 PC를 갱신할지 결정하게 된다.

Control Unit의 역할 요약
1. 명령어 fetch 후, Control Unit은 opcode를 입력받는다.
2. 각 제어 신호를 설정하여, MUX, ALU, 레지스터 파일, 메모리 등을 동작시킨다.
3. ALU 연산 제어는 ALUOp를 통해 ALU Control이 결정한다.
4. 분기인 경우, ALU Zero 출력Branch 신호가 결합되어 다음 PC 주소를 결정한다.

R-type Instruction

//Example
add $t1, $t2, $t3
  • Step 1: 명령어 가져오기(Instruction Fetch) : Program Counter(PC)의 값이 명령어 메모리에 주소로 전달되어 명령어가 읽혀진다. 동시에 PC + 4가 계산되어 다음 명령어의 주소를 준비한다.

    • 사용 하드웨어 : PC, Instruction Memory, Adder
  • Step 2: 레지스터 읽기 및 제어 신호 생성 : 명령어에서 rs, rt 필드를 해석하여 해당 레지스터($t2, $t3)를 레지스터 파일(Register File)에서 읽어온다. 동시에 Control Unit이 명령어의 opcode를 해석하여 다음 제어 신호들을 설정한다.

    • RegDst = 1(rd를 목적지로)
    • ALUSrc = 0(ALU 입력: rt)
    • RegWrite = 1(연산 결과 저장)
    • ALUOp = 10(ALU Control이 funct 필드를 해석하도록 지시)
    • 사용 하드웨어 : Register File, Main Control Unit, MUX for destination reg
  • Step 3: ALU 연산 수행 : 레지스터에서 읽은 값 두 개($t2, $t3)를 ALU로 전달한다. ALU는 명령어의 funct 필드를 기반으로, 정확한 연산(add)를 수행한다. 이때 ALU Control UnitALUOp=10과 funct를 조합해 ALU 제어 신호(0010 for add)를 생성한다.

    • 사용 하드웨어 : ALU, ALU Control Unit
  • Step 4: 결과 레지스터에 저장 : ALU 연산 결과가 레지스터 파일의 목적지 레지스터(rd=$t1)에 기록된다. 목적지 선택은 RegDst = 1로 인해 rd 필드(15:11)가 선택된다.

    • 사용 하드웨어 : Register File, Mux for RegDst, Write Register Control
단계주요 동작제어 신호주요 하드웨어
1명령어 fetch 및 PC 증가-PC, Instr Mem, Adder
2레지스터 읽기 및 제어 신호 설정RegDst, ALUSrc, ALUOp, RegWriteControl Unit, RegFile
3ALU 연산 (funct 기반)ALU ControlALU, ALU Control
4결과 저장 (rd)RegWrite, RegDstRegFile, MUX

Load Instruction

//Example
lw $t1, 8($t2)
  • Step 1: 명령어 가져오기 (Instruction Fetch) : 현재 PC 값을 사용하여 Instruction Memory에서 명령어를 가져온다. 동시에 PC + 4를 계산해 다음 명령어의 주소를 준비한다.
    • 사용 하드웨어 : PC, Instruction Memory, Adder
  • Step 2: 레지스터 읽기 : 명령어 rs 필드(25:21)를 통해 $t2 값을 Register File에서 읽는다. 동시에 Control Unit이 opcode = 100011(lw)임을 해석하여 제어 신호들을 설정한다.
    • ALUSrc = 1(ALU 입력에 즉시값 사용)
    • RegWrite = 1, MemRead = 1
    • MemtoReg = 1(메모리 값을 레지스터에 저장)
    • ALUOp = 00(주소 계산용 덧셈)
  • Step 3: 주소 계산 : 읽어온 $t2 값과 명령어의 offset 필드(15:0)를 sign-extend한 후, 두 값을 ALU에 입력하여 메모리 주소를 계산한다.
    • 사용 하드웨어: ALU, Sign-extend Unit, MUX for ALUSrc
  • Step 4: 메모리 접근(읽기) : 위에서 계산된 주소를 Data Memory에 전달하여 해당 위치의 데이터를 읽는다.
    • 사용 하드웨어 : Data Memory
    • 제어 신호: MemRead = 1
  • Step 5: 레지스터에 쓰기 : 메모리에서 읽은 값을 Register File의 목적지 레지스터에 저장한다. 이때 목적지 레지스터에는 rt 필드(20:16)에 의해 결정되며, RegDst = 0에 따라 선택된다.
    • 사용 하드웨어 : Register File, MUX for RegDst, MUX for MemtoReg
단계주요 동작제어 신호주요 하드웨어
1명령어 fetch 및 PC + 4-PC, Instr Mem, Adder
2$t2 읽기 및 제어 신호 설정ALUSrc = 1, ALUOp = 00, RegWrite = 1RegFile, Control Unit
3주소 계산: $t2 + offsetALUSrc, ALUOpALU, Sign Extend, MUX
4메모리 읽기MemRead = 1Data Memory
5메모리 값 → $t1에 저장RegWrite = 1, MemtoReg = 1RegFile, MUX
  • Store 명령어와의 차이점
    • sw는 regwrite = 0, MemWrite= 1
    • 두 번째 레지스터(rt)의 값을 메모리에 저장(쓰기)
    • 메모리 -> 레지스터 저장 단계 없음
    • 즉, lw는 메모리에서 레지스터로, sw는 레지스터에서 메모리로의 흐름만 바뀔 뿐, 나머지 경로는 매우 유사하다.

Branch-on-Equal Instruction

#Example
beq $t1, $t2, offset
# $t1==$t2이면, PC <- PC + 4 + (offset x 4)
  • Step 1: 명령어 가져오기(Instruction Fetch) : 현재 PC를 이용해 명령어 메모리에서 beq 명령어를 가져온다. 동시에 PC + 4를 계산하여 기본적으로 다음 명령어 주소를 준비한다.

    • 사용 하드웨어 : PC, Instruction Memory, Adder
  • Step 2: 레지스터 읽기 : 명령어의 rs와 rt 필드(25:21, 20:16)를 이용해 $t1, $t2 값을 레지스터 파일에서 읽어온다. 동시에 Control Unit이 opcode = 000100(beq)을 해석하여 제어 신호를 설정한다.

  • Step 3: 비교 및 분기 주소 계산 : ALU는 $t1 - $t2 연산을 수행하여 Zero 출력을 생성한다. 동시에, 명령어의 하위 16비트(offset)를 sign-extend -> shift-left-2하여 branch target offset을 생성한다. 이 offset을 PC + 4에 더하여 분기 대상 주소를 계산한다.

  • Step 4: 다음 명령어 주소 설정 : ALU에서 Zero 출력이 1이면(t1==t1==t2), Control Unit의 Branch 신호도 1이므로 AND 게이트 출력이 1, PC는 branch target으로 설정된다. 조건이 거짓이면 AND 게이트 출력이 0이므로 PC는 그냥 PC + 4가 된다.

    • 사용 하드웨어 : AND 게이트(Zero And Branch), MUX for PCSrc(PC + 4 vs Branch Address)
단계주요 동작제어 신호주요 하드웨어
1명령어 fetch 및 PC + 4-PC, Instr Mem, Adder
2$t1, $t2 읽기 및 제어 신호 설정Branch = 1, ALUOp = 01RegFile, Control Unit
3비교 수행 및 분기 주소 계산ALUSrc = 0ALU, Sign Extend, Shift-left-2, Adder
4분기 조건 판단 → 다음 PC 결정Zero + BranchAND, MUX for PCSrc

Jump 명령어 구현: 데이터 경로와 제어 확장

  • opcode : 6비트(000010, 210)
  • target : 26비트 -> 점프할 주소의 일부
  • Jump 명령어는 무조건 분기(Unconditional Jump)이며, 조건 검사 없이 PC를 새로운 주소로 설정한다.
  • Jump 주소 계산 방식 : Jump 명령어는 32비트 주소를 직접 제공하지 않는다.
    PC ← { PC+4[31:28], target[25:0], 00 }
    	- 상위 4비트 : PC + 4의 31:28 비트
    • 중간 26비트 : 명령어의 target 필드

    • 하위 2비트 : 항상 00(워드 정렬 주소)

      분기(branch) 명령어는 offset을 더하는 방식이었지만, jump는 아예 새로운 주소로 PC를 대체하는 구조이다.

데이터 경로 확장

  • 새로운 MUX : 기존 PC는 다음 명령어 주소를 선택할 때 PC + 4 또는 branch target 중에서 선택한다. 이제 여기에 jump 주소도 선택지로 추가되어야 한다. -> **3-입력 MUX(또는 2단계 MUX 조합) 필요
  • Jump 주소 생성 로직 : target[25:0] -> shift-left-2 -> 28비트 / PC + 4[31 : 28]와 결합 -> 전체 32비트 주소 생성
  • 새로운 제어 신호 jump : 1비트 제어 신호, jump==1 이면 PC를 jump 주소로 설정, 기존 Branch AND Zero 경로와는 별개로 작동한다.
항목설명
명령어 형식opcode(6) + target(26)
주소 계산{PC+4[31:28], target, 00}
데이터 경로 확장shift-left-2, PC 상위 비트 병합, 추가 MUX
제어 신호Jump (1비트) 신호 추가
차이점조건 분기 아님 (ALU 사용 X, Zero 확인 X)

제어 신호 설정 예시

명령어RegDstALUSrcMemtoRegRegWriteMemReadMemWriteBranchJumpALUOp
R-type1001000010
lw0111100000
swX1X0010000
beqX0X0001001
jXXX00001XX
profile
기초를 다지는 중입니다.📚🧑‍💻

0개의 댓글