ALU control
ALU의 여러 역할 중 기본이 되는 3가지 역할은 다음과 같다.
- LDUR/STUR: 메모리 주소 계산 → ALU = add
- R-type: opcode(11bit)에 따라 AND, OR, ADD, SUB 수행
- CBZ: 입력 그대로 통과(pass input b)

LEGv8에서 ALU 제어는 ALUOp(2bit) + Instruction[31:21](11bit opcode)를 함께 사용한다.
→ 이유: ALUOp는 상위 제어장치(Main Control Unit)가 명령의 종류(load/store/R-type 등)를 구분하기 위해 생성하고,
11-bit opcode는 세부 연산(add/sub/and/or)을 구분하기 위해 사용됨.
ALUOp와 Instruction을 보고 4bit의 ALU control lines가 ALU에 전달된다.
Main control Unit
- 입력: Opcode (31~26 또는 31~21bit)
- 출력: 여러 제어 신호(Control Lines)
→ ALUOp, MemRead, MemWrite, RegWrite, ALUSrc, MemToReg 등 - 각 명령에 따라 ALU 연산 제어, MUX 선택, 레지스터/메모리 enable 신호를 결정함.

R-Type Instruction
R-type을 더 자세하게 살펴보자

빨간 선(🟥)은 데이터 흐름(Data Path),
파란 선(🟦)은 제어 신호(Control Signals)
STEP 1 : 명령어 가져오기 (Instruction Fetch)
- Program Counter (PC) 에 현재 실행할 명령어의 주소가 들어 있음.
(예: 0x0040) - 그 주소가 Instruction Memory 의 Read Address 로 들어가서
→ Instruction[31:0] 비트 형태의 명령어를 읽어옴. - 동시에 PC + 4를 계산하는 작은 Adder가 오른쪽 위에 있음.
- 이건 다음 명령어 주소를 미리 계산해 둠.
- 결과는 다시 PC로 돌아갈 준비를 함.
📍그림에서:
- PC → Instruction memory (왼쪽 세로선)
- Add +4 부분은 “다음 명령”으로 넘어가기 위한 준비
STEP 2 : 명령어 해석 & 레지스터 읽기 (Decode & Register Read)
- Instruction 메모리에서 읽은 32비트 명령어는 다음과 같이 구성된다.
[31–21]: opcode
[20–16]: Rm (레지스터 2)
[9–5] : Rn (레지스터 1)
[4–0] : Rd (결과 레지스터) - 이 비트들이 각각 레지스터 파일(Registers) 의 입력으로 들어가서,
- Rn → Read Register 1 → X2
- Rm → Read Register 2 → X3
를 지정하고
→ 해당 레지스터 값들을 읽어 Read Data 1, Read Data 2로 출력.
- 동시에, Control Unit (파란색 블록)이 opcode(31–21)를 보고
→ ALUOp, ALUSrc, MemRead, MemWrite, RegWrite 등의 제어신호를 생성함.
📍그림에서:
- 파란선이 Control 유닛으로 가는 경로
- Instruction[31–21] → Control
- Instruction[9–5], [20–16] → Registers 입력
STEP 3: ALU에서 연산 수행 (Execute)
- ALU 입력 A ⬅ Read Data 1 (즉, X2)
ALU 입력 B ⬅ MUX를 통해 선택된 값:- R-type에서는 ALUSrc = 0 이므로 Read Data 2 (즉, X3)를 선택
- D-type (LDUR, STUR)에서는 ALUSrc = 1 로 Sign-extend된 Immediate 선택
- ALU Control 블록은
- Control 유닛에서 온 ALUOp(2bit) + Instruction의 opcode(11bit)를 받아
→ ALU가 수행할 정확한 연산을 결정 (add, sub, and, or 등).
- Control 유닛에서 온 ALUOp(2bit) + Instruction의 opcode(11bit)를 받아
- ALU는 X2와 X3를 더해서 결과를 출력 (ALU Result).
- 동시에 Zero 플래그도 만들어짐 (결과가 0이면 1로 세팅) → CBZ에서 사용됨.
📍그림에서:
- ALU 입력 왼쪽에 MUX가 있음 (Read data 2 vs Sign-extend)
- ALU 밑에 “ALU control” 박스 존재
- 출력은 “ALU result”, “Zero” 두 개로 나감
STEP 4: 결과 저장 (Write Back)
- ALU 결과(ALU Result) 가 오른쪽 위의 MUX로 들어감.
- R-type에서는 MemtoReg = 0 → ALU 결과 선택.
- LDUR 같은 메모리 읽기 명령이면 MemtoReg = 1 → Data Memory 출력 선택.
- 선택된 값이 다시 Registers 블록으로 들어감.
- 입력 Rd(Instruction[4–0]) → Write Register
- 데이터 → Write Data
- RegWrite 신호가 1이면 저장 수행.
- 즉, X1 ← X2 + X3 연산이 완료됩니다
📍그림에서:
- 맨 오른쪽 상단 MUX → Register Write Data로 연결
- 파란선 RegWrite = 1
- 빨간선으로 ALU result가 Write Data로 전달
추가 설명: 각 제어 신호의 역할
| Reg2Loc | D-type(STUR)에서는 두 번째 레지스터를 [4–0] (Rt) 로 선택하고, R-type에서는 [20–16] (Rm) 을 선택한다.” |
| Branch | 브랜치 명령일 때, PC를 바꿀지 결정 |
| MemRead | 데이터 메모리 읽기 활성화 (LDUR 등) |
| MemtoReg | 레지스터로 쓰는 값이 Memory인지 ALU결과인지 선택 |
| ALUOp | ALU 연산 종류 결정 (00=add, 01=sub 등) |
| MemWrite | 데이터 메모리 쓰기(STUR 등) |
| ALUSrc | ALU 입력 B가 Register인지 Immediate인지 선택 |
| RegWrite | 레지스터 파일에 쓰기 허용 (ADD, LDUR 등에서 1) |
Load Instruction

Step 1: 명령어 가져오기 (Instruction Fetch)
- PC(Program Counter) → 현재 명령어 주소를 Instruction Memory에 전달
- 해당 주소에서 32bit 명령어를 읽음
- 동시에 PC + 4 를 계산하여 다음 명령어 주소를 준비
회로상 위치
- 그림 왼쪽 상단
- PC → Instruction Memory → Instruction[31:0]
- 위쪽 Add +4 블록: “다음 명령어 준비”
- 파란선(제어신호)과 무관, 항상 실행됨
Step 2: 명령어 해석 & 레지스터 읽기 (Decode)
- 읽은 32bit 명령어를 분해 [31–21]: opcode (LDUR)
[20–12]: offset (9bit)
[9–5] : base register (Rn = X2)
[4–0] : target register (Rt = X1) - Control Unit 이 opcode를 보고 신호를 생성: ALUSrc = 1 (offset을 사용)
MemRead = 1 (메모리에서 읽기)
MemWrite = 0
MemToReg = 1 (Memory → Register)
RegWrite = 1 (레지스터에 결과 저장)
- Register File에서:
- Read Register 1 = [9–5] → X2 (base address)
- Read Register 2 는 사용 안 함 (store 때만 필요)
- Write Register = [4–0] → X1
Step 3: 주소 계산 (Execute)
- offset ([20–12])을 Sign-Extend (9bit → 64bit)
- ALU 입력:
- ALU A = X2 (기준 주소)
- ALU B = Sign-extended offset
- ALUSrc = 1 이므로 MUX가 offset 쪽을 선택
- ALU 연산:→ 이게 실제 메모리 주소 ALU Result = X2 + offset
회로상 위치
- 중앙 하단의 Sign-extend → ALU 입력
- ALU control은 “add” 연산만 수행 (LDUR/STUR의 주소 계산)
Step 4: 메모리 접근 (Memory Access)
동작
- 위에서 계산한 주소(ALU result)를 Data Memory의 Read Address로 보냄
- MemRead = 1 → 해당 주소의 데이터를 읽음
- 읽은 데이터가 “Read Data”로 출력됨
회로상 위치
- 오른쪽 하단의 Data Memory
- 입력: Address = ALU result
- 출력: Read data (파란선으로 Register로 이동)
Step 5: 레지스터에 결과 저장 (Write Back)
동작
- Data Memory의 “Read Data”가
MUX로 들어감 (MemToReg = 1 → Memory 선택) - Register File의 Write Data 입력으로 전달됨
- Write Register = [4–0] (X1), RegWrite = 1
→ X1 ← Memory[X2 + offset]
회로상 위치
- 오른쪽 위의 MUX (ALU result vs Memory read data)
- MUX 출력 → Registers 블록의 “Write data” 포트
- 파란선 RegWrite = 1
STUR Instruction

Step 1: 명령어 가져오기 (Fetch)
- PC → Instruction Memory로 주소 전달
- 명령어 읽기: [31:0] 비트
- 동시에 PC + 4 계산 (다음 명령어 준비용)
(위쪽 Add 4 블록)
Step 2: 명령어 해석 & 레지스터 읽기 (Decode)
읽은 명령어를 비트 단위로 분해하면:
| 비트 | 의미 | 예시 |
| [31–21] | opcode (LDUR/STUR 구분) | STUR |
| [20–12] | offset (9bit) | #40 |
| [9–5] | base register (Rn) | X2 |
| [4–0] | source register (Rt) | X1 |
Control Unit 생성 신호:
| 신호 | 값 | 의미 |
| Reg2Loc | 1 | [4–0] (Rt) 사용 |
| ALUSrc | 1 | offset 사용 |
| MemRead | 0 | 메모리 읽기 안 함 |
| MemWrite | 1 | 메모리에 쓰기 |
| MemtoReg | X | 사용 안 함 |
| RegWrite | 0 | 레지스터 쓰기 안 함 |
| ALUOp | 00 | add (주소 계산용) |
Register File 동작
- Read Register 1 = [9–5] = X2 → 주소 기준(base)
- Read Register 2 = [4–0] = X1 → 메모리에 쓸 데이터(source)
- Write Register 사용 안 함 (RegWrite = 0)
📍 Reg2Loc = 1 → [4–0] (Rt)을 두 번째 입력으로 선택
(이 부분이 바로 STUR 전용 동작)
Step 3: 주소 계산 (Execute)
- offset([20–12]) → Sign-extend(9bit → 64bit)
- ALU 입력:
- A = X2 (base)
- B = Sign-extended offset
- ALUSrc = 1 → MUX에서 offset 선택
- ALU 수행:→ 실제로 데이터를 쓸 메모리 주소 계산 완료
-
ALU result = X2 + offset
Step 4: 메모리 접근 (Memory Access)
- 계산된 주소(ALU result)를 Data Memory의 address 입력으로 전달
- MemWrite = 1 → Memory Write 활성화
- Memory에 쓸 데이터 = Register File의 Read Data 2 (즉, X1)
📍 그림에서:
- 오른쪽 하단의 “Write data memory” 선 = X1
- “Address data” = ALU result
Step 5: 레지스터에 저장 없음 (Write Back)
- LDUR은 메모리에서 읽은 값을 레지스터에 썼지만,
- STUR은 메모리에 쓰기만 하고 레지스터에 저장하지 않음.
- RegWrite = 0, MemtoReg 미사용.
CBZ Instruction

명령어 형식 (CB-type)
| 필드 | 비트 구간 | 설명 |
| opcode | [31–24] | 명령 종류 (CBZ / CBNZ) |
| offset | [23–5] | 19비트 분기 거리 |
| Rt | [4–0] | 비교할 레지스터 (예: X1) |
동작 과정 (5단계 요약)
| 단계 | 동작 |
| 1️⃣ Fetch | PC로 명령어 읽고, 동시에 PC+4 계산 |
| 2️⃣ Decode | Rt([4–0]) → Register File에서 X1 읽기 (Read Register 2) |
| 3️⃣ Execute | ALU가 X1 값이 0인지 검사 → Zero 플래그 설정 |
| 4️⃣ Branch 주소 계산 | branch = PC + (SignExtend(offset[23–5]) << 2) |
| 5️⃣ PC 선택 | Zero=1 → branch 주소로, Zero=0 → PC+4 로 진행 |
Control Signal 설정
| 신호 | 값 | 설명 |
| Reg2Loc | 1 | [4–0] 선택 (Rt 읽기) |
| ALUSrc | 0 | ALU 입력 = 레지스터 |
| MemRead / MemWrite | 0 | 메모리 접근 없음 |
| RegWrite | 0 | 레지스터 갱신 없음 |
| Branch | 1 | 분기 동작 사용 |
| ALUOp | 01 | 비교용 (Zero 확인) |
ALU 역할
- X1 값이 0이면 Zero=1, 아니면 0
- ALU 자체는 “전달(pass B)”만 수행
- Zero 플래그가 MUX의 분기 선택에 사용됨
PC 갱신
| 조건 | 다음 PC |
| X1 == 0 | PC ← PC + (offset << 2) |
| X1 ≠ 0 | PC ← PC + 4 |
Unconditional Branch

명령어 형식 (B-type)
| 필드 | 비트 구간 | 크기 | 설명 |
| opcode | [31–26] | 6bit | 명령 종류 (B) |
| address (offset) | [25–0] | 26bit | 분기할 거리 (word 단위 offset) |
➡️ 총 32비트
동작 원리 (단계별)
| 단계 | 설명 |
| ① | PC가 현재 명령어 주소를 Instruction Memory에 전달 → 명령어 읽음 |
| ② | PC + 4 계산 (기본 다음 주소) |
| ③ | 26비트 offset을 꺼내서 Sign-Extend (64bit 확장) |
| ④ | offset을 왼쪽으로 2비트 Shift (<<2) → ×4 (워드 주소 → 바이트 주소) |
| ⑤ | PC + (Sign-extended offset << 2) 계산 → 분기 주소 생성 |
| ⑥ | UncondBranch 신호 = 1 → MUX가 항상 branch 주소 선택 |
| ⑦ | PC ← branch 주소 로 갱신 (즉, 점프 실행) |
