← 블로그로 돌아가기CPU 구조

시뮬레이터에서 CPU를 처음부터 만들기

레지스터, ALU, 공유 버스, 바이트 폭 RAM, 16비트 명령어, 플래그, 마이크로시퀀스 제어 장치를 갖춘 8비트 교육용 CPU를 일관되게 구축하고 검증하는 안내서입니다.

DennyDenny
약 11분 소요
Chalkboard feature illustration for “시뮬레이터에서 CPU를 처음부터 만들기”

요약: 이 안내서는 배선을 그리기 전에 완전한 교육용 아키텍처 하나를 정의합니다. 8비트 데이터 경로와 주소 공간, 바이트 폭 통합 RAM, 두 바이트로 인출하는 16비트 명령어, 범용 레지스터 네 개, ALU와 플래그, 단일 공유 버스, 마이크로시퀀스 제어기입니다. 각 하위 시스템을 만들고 검증하며 한 번에 버스 구동기 하나만 허용한 다음, 5 + 3을 계산하여 메모리에 8을 저장하는 다섯 명령어 프로그램을 실행합니다.

‘CPU 만들기’는 완성된 블록을 연결하는 일부터 트랜지스터를 배치하는 일까지 무엇이든 뜻할 수 있습니다. 이 튜토리얼은 그 양극단 사이에 있습니다. 레지스터, 멀티플렉서, 디코더, ALU, 메모리, 제어 저장소 같은 디지털 구성 블록으로 프로세서를 구성하되, 각 블록의 내부 게이트는 별도로 검증할 수 있는 설계로 다룹니다.

목표는 현대 상용 코어를 흉내 내는 것이 아닙니다. 모든 명령 구현이 충족해야 하는 계약을 드러내는 것입니다.

  1. 올바른 명령 바이트를 인출한다.
  2. 디코드하는 동안 이를 보존한다.
  3. 의도한 피연산자만 정확히 이동한다.
  4. 정의된 연산을 수행한다.
  5. 허용된 아키텍처 상태만 갱신한다.
  6. 올바른 다음 명령 주소를 선택한다.

1. 먼저 아키텍처를 고정하기

많은 CPU 프로젝트가 구축 도중에 메모리 폭, 명령어 폭, PC 증가량을 바꾸면서 실패합니다. 다음 명세를 일관되게 사용하세요.

속성교육용 CPU 정의
데이터 폭8비트
주소 폭8비트
메모리바이트 주소 지정 위치 256개, 명령어와 데이터를 통합
명령어 폭16비트, 연속된 두 바이트에 저장
명령 바이트 순서명령 시작 주소에 상위 바이트를 먼저 저장
순차 PC 진행인출 중 한 바이트씩 두 번 증가
범용 레지스터8비트 레지스터 네 개: R0–R3
피연산자 래치각각 8비트인 A와 B
명령 레지스터16비트
플래그Z(제로), N(음수), C(캐리), V(부호 있는 오버플로)
인터커넥트8비트 교육용 버스 하나
제어마이크로스텝 카운터와 제어 ROM

8비트 주소는 256개의 위치를 선택합니다. 이 아키텍처에서는 각 위치를 명시적으로 한 바이트로 정했으므로 메모리는 256바이트입니다. 모든 명령어가 두 바이트를 차지하므로 명령 시작 주소는 보통 짝수입니다.

블록 다이어그램

                         ┌──────────────────────┐
                         │ 제어 ROM +            │
                         │ 마이크로스텝 시퀀서    │
                         └──────────┬───────────┘
                                    │ 제어 신호
                                    ▼
 ┌────┐   ┌─────┐   ┌────────────── 8비트 공유 버스 ───────────────┐
 │ PC │──▶│ MAR │   │       │       │       │       │       │      │
 └────┘   └──┬──┘  ┌▼──┐  ┌▼──┐  ┌▼──┐  ┌▼──┐  ┌▼──┐  ┌▼──┐  ┌▼───┐
             │     │MDR│  │ R0│  │ R1│  │ R2│  │ R3│  │ A │  │ B │
             ▼     └─┬─┘  └───┘  └───┘  └───┘  └───┘  └┬──┘  └┬───┘
        ┌────────┐   │                                    └──┬───┘
        │256 × 8 │   │                                  ┌────▼────┐
        │  RAM   │   │                                  │ 8비트   │
        └────────┘   │                                  │  ALU    │
                     │                                  └────┬────┘
                     └──────▶ 16비트 IR ◀────────────────────┘
                                      │
                                      ▼
                                opcode / 필드

이 그림은 개념적입니다. IR은 버스에서 두 개의 별도 바이트를 로드하고, ALU 결과는 자체적으로 선택된 출력 경로를 통해 버스에 도달합니다.

Sequential Instruction Executor를 참고용으로 열되, 이 글의 아키텍처를 실습의 기준으로 삼으세요. 템플릿이 다른 내부 규약을 쓴다면 둘을 조용히 섞지 말고 차이를 문서화하세요.

2. 명령어 형식 정의하기

사용자 정의 ISA는 16비트 형식 두 가지를 사용합니다.

레지스터 형식

15            12 11             8 7              4 3              0
┌───────────────┬────────────────┬────────────────┬────────────────┐
│ opcode [3:0]  │ RA [3:0]       │ RB [3:0]       │ RD [3:0]       │
└───────────────┴────────────────┴────────────────┴────────────────┘

즉시값/주소 형식

15            12 11             8 7                               0
┌───────────────┬────────────────┬─────────────────────────────────┐
│ opcode [3:0]  │ RD [3:0]       │ immediate / address [7:0]       │
└───────────────┴────────────────┴─────────────────────────────────┘

레지스터가 네 개인 이 기계에서는 레지스터 코드 0–3만 유효합니다. 디코더는 실수로 제어선을 선택하지 않도록 4–15 값을 거부하거나 안전하게 트랩해야 합니다.

Opcode니모닉형식정의된 효과
0NOP—이미 진행한 PC를 제외하고 아키텍처 상태 변화 없음
1LDI즉시값RD ← imm8
2LD즉시값RD ← RAM[addr8]
3ST즉시값RAM[addr8] ← RD
4ADD레지스터RD ← RA + RB; 플래그 갱신
5SUB레지스터RD ← RA − RB; 플래그 갱신
6JMP즉시값PC ← addr8
7JZ즉시값Z = 1이면 PC ← addr8
8HLT—제어기를 정지 상태로 전환

나머지 opcode는 모두 불법입니다. 디버깅 중에는 명시적인 illegal_instruction 경로를 추가하거나 안전한 트랩/정지로 매핑하세요.

3. 클록을 게이팅하지 않고 레지스터 만들기

8비트 레지스터는 하나의 클록과 하나의 논리적 로드 인에이블을 공유하는 에지 트리거 D 플립플롭 여덟 개입니다.

각 비트에 대해 다음과 같습니다.

Dff={Dbus,if load=1Q,if load=0D_{\text{ff}} = \begin{cases} D_{\text{bus}}, & \text{if load}=1 \\ Q, & \text{if load}=0 \end{cases}

D 입력 앞의 2:1 멀티플렉서로 이 식을 구현하거나, 소자의 전용 클록 인에이블 기능을 사용하세요. 모든 상태 요소를 하나의 전역 클록에 둡니다.

전역 클록과 load를 AND하여 로컬 클록을 만들지 마세요. 통제되지 않은 클록 게이팅은 하드웨어에 스큐와 글리치를 만들 수 있습니다. 집적형 클록 게이팅 셀과 FPGA 클록 제어 자원은 별도의 타이밍 인지 메커니즘입니다.

버스에 연결된 각 레지스터에는 다음이 필요합니다.

  • 버스의 8비트 입력
  • 저장된 8비트 출력
  • load_x 제어
  • 교육용 버스를 구동하도록 허용된 oe_x 경로

PC에는 증가 경로와 명시적인 로드 경로가 추가로 필요합니다. IR에는 독립적인 상위/하위 바이트 로드가 필요합니다. MAR은 메모리 주소를 보유하고, MDR은 메모리 데이터 한 바이트를 캡처하거나 공급합니다.

복제하기 전에 레지스터 하나 검증하기

다음 경우를 시험합니다.

  1. load = 0: 여러 클록 뒤에도 Q가 변하지 않습니다.
  2. load = 1: 활성 에지에서 Q가 버스를 캡처합니다.
  3. 에지에서 멀리 떨어진 시점의 데이터 변화: 다음 인에이블 에지에서만 Q가 변합니다.
  4. 제공된 경우 리셋: Q가 문서화된 상태에 도달합니다.
  5. 출력 인에이블 꺼짐: 레지스터가 버스를 구동하지 않습니다.

디지털 시뮬레이터는 이 모델의 논리적 순서를 검증할 수 있습니다. 아날로그 준안정성을 재현하거나 물리적 셋업 및 홀드 타이밍을 증명하지는 않습니다.

4. ALU를 만들고 모든 플래그 정의하기

A와 B를 안정적인 피연산자 래치로 사용합니다. ALU는 조합 회로여야 하며, 숨은 아키텍처 상태를 포함해서는 안 됩니다.

alu_op연산결과
000ADDA + B
001SUBA − B
010ANDA & B
011OR`A
100XORA ^ B
101NOT~A
110SHLA << 1, 0 채움
111SHR논리 A >> 1, 0 채움

ALU 안내서는 연산 레인과 출력 멀티플렉서를 자세히 설명합니다. 핵심 산술 설계는 다음과 같습니다.

  • 8단 전가산기 체인
  • A + (~B) + 1로 구현하는 뺄셈
  • 병렬 비트 단위 게이트
  • 고정된 1비트 시프터 배선
  • alu_op로 선택하는 출력 멀티플렉서

플래그 정의

논리 및 시프트 명령이 C와 V에 무엇을 하는지도 포함해 플래그를 ISA의 일부로 정의합니다.

  • Z: 모든 결과 비트가 0이면 1입니다.
  • N: 결과 비트 7이며, 부호 연산에서만 부호 비트로 해석합니다.
  • ADD의 C: 비트 7의 캐리 출력입니다.
  • SUB의 C: ‘빌림 없음’ 또는 ‘빌림’ 중 하나를 선택하고 문서화합니다. 이 안내서에서는 가산기의 캐리 출력 규약과 맞는 빌림 없음을 사용합니다.
  • ADD의 V: 피연산자의 부호가 같고 결과 부호가 반대입니다.
  • SUB의 V: 피연산자의 부호가 다르고 결과 부호가 A와 다릅니다.

뺄셈 레인을 반전된 B 피연산자와 캐리 입력으로 구현할 때, 캐리 입력/캐리 출력 XOR의 동등한 식은 2의 보수 덧셈과 뺄셈에 적용됩니다. 계산 사례는 CPU 플래그를 참조하세요.

이 교육용 ISA는 ADD와 SUB에서 Z, N, C, V를 갱신합니다. 논리 및 시프트 연산은 C/V를 보존할지 새 의미를 정의할지 마이크로코드를 작성하기 전에 문서화된 정책을 선택하세요. ‘배선에 우연히 들어 있는 값’은 유효한 정책이 아닙니다.

ALU 검증 표

최소한 다음을 시험합니다.

경우예상 중점
0x00 + 0x00Z
0xFF + 0x01부호 없는 캐리와 제로
0x7F + 0x01부호 있는 오버플로와 N
0x80 + 0x80캐리와 부호 있는 오버플로
0x00 − 0x01빌림 규약과 N
0x80 − 0x01부호 있는 오버플로
AND/OR/XOR 항등식비트 단위 레인
0x81의 시프트방향, 채움 비트, 시프트되어 나간 비트 정책

5. 공유 버스 만들기

교육용 버스는 여러 가능한 소스를 가진 여덟 개의 선입니다. 다음 중심 불변 조건이 적용됩니다.

∑enabled bus drivers≤1\sum \text{enabled bus drivers} \le 1

가능한 구동기는 PC, MDR, R0–R3, A, B, IR 바이트, ALU 결과를 포함합니다. 정확한 목록은 ‘레지스터 수’보다 길므로 제어 명세에서 모든 소스를 열거하세요.

DigiSim에서는 트라이스테이트 버퍼로 공유 버스를 모델링할 수 있습니다.

  • 전송 중에는 정확히 하나의 소스만 인에이블합니다.
  • 다음 활성 에지에 하나 이상의 목적지 로드 신호를 인가합니다.
  • 어떤 소스도 버스를 구동하지 않을 때는 버스를 캡처하지 않습니다.

경합은 설계 오류입니다. 물리적 출력 충돌은 잘못된 전압과 과도한 전류를 유발할 수 있으며, 그 결과는 기술과 지속 시간에 따라 다르므로 ‘칩은 항상 탄다’는 유용한 규칙이 아닙니다.

현대 FPGA 패브릭은 일반적으로 내부 공유 버스를 실제 내부 트라이스테이트 배선이 아니라 멀티플렉서로 구현합니다. ASIC 스타일도 다양합니다. 트라이스테이트 버스는 소유권과 전송을 설명하는 명확한 교육 모델로 남아 있습니다.

버스 중재 시험

R0와 R1에 알려진 값을 넣습니다.

  • R0 = 0xAA
  • R1 = 0x55

R0만, R1만, 구동기 없음, 두 구동기를 모두 확인합니다. 마지막 두 경우는 유효하지 않은 제어기 상태로 취급해야 합니다. 그런 다음 단언문이나 가시적 표시기를 추가해 이후의 마이크로코드 오류를 즉시 감지하세요.

6. 바이트 폭 메모리 연결하기

시뮬레이터의 RAM 구성 요소를 아키텍처 메모리 모델로 사용합니다. 물리 RAM이 문자 그대로 D 래치 배열이라고 주장하지 마세요. SRAM, DRAM, 블록 RAM, 합성된 레지스터 배열은 서로 다른 저장 셀과 타이밍을 사용합니다.

이 CPU의 인터페이스는 다음과 같습니다.

  • MAR이 구동하는 ADDR[7:0]
  • MDR 또는 제어된 버스 인터페이스를 통해 전송되는 DATA[7:0]
  • mem_read
  • mem_write
  • 모델이 가변 지연을 지원할 경우 선택적인 ready

이 안내서는 한 전용 마이크로스텝에서 읽기를 요청하고 캡처할 수 있다고 가정합니다. 선택한 메모리가 동기식이거나 가시적인 지연이 있다면 대기 상태를 넣고 데이터가 유효할 때만 캡처하세요.

명령 메모리와 데이터는 같은 256바이트를 공유합니다. 별도 메모리를 쓰는 하버드 설계도 유효하지만, 이는 다른 아키텍처와 인출 일정입니다.

쓰기 가능한 저장소와 비휘발성/상수 저장소 추상화의 차이는 RAM과 ROM을 참조하세요.

7. 마이크로시퀀스 제어기 만들기

제어기는 opcode, 마이크로스텝, 플래그, 기계 상태를 다음으로 변환합니다.

  • 버스 출력 인에이블
  • 레지스터 로드 인에이블
  • ALU 연산
  • 메모리 읽기/쓰기 제어
  • PC 증가/로드 제어
  • 플래그 로드
  • IR 상위/하위 바이트 로드
  • 다음 마이크로스텝 또는 명령 종료 제어

한 구현은 제어 ROM을 사용합니다.

제어 주소 = {opcode, microstep}
제어 워드 = {oe 신호, load 신호, alu_op, 메모리 제어, 다음 제어}

플래그는 선택된 동작을 한정할 수 있습니다. 예를 들어 JZ에서는 load_pc = microcode_load_pc AND Z로 하거나 제어 저장소 주소에 참여시킬 수 있습니다. 마이크로스텝 카운터가 항상 증가한다고 가정하는 것보다 명시적인 다음 상태 논리가 더 명확한 경우가 많습니다.

이는 교육용 마이크로코드 제어기입니다. 실제 프로세서는 조합 디코드, 프로그램 가능 제어 저장소, 상태 기계, 시퀀서의 여러 조합을 사용합니다. RISC/CISC 레이블을 구현의 지름길로 쓰지 마세요.

안전한 기본값

사용하지 않는 모든 제어 ROM 항목은 다음을 해야 합니다.

  • 모든 버스 구동기를 비활성화한다.
  • 메모리 쓰기를 비활성화한다.
  • 아키텍처 레지스터 쓰기를 비활성화한다.
  • 정의된 불법 명령 또는 정지 경로로 들어간다.

초기화되지 않은 제어 워드는 절대 ‘임의 메모리에 임의 데이터를 쓰기’가 되어서는 안 됩니다.

8. 두 명령 바이트를 일관되게 인출하기

RAM과 데이터 경로의 폭은 8비트이고 각 명령어는 16비트이므로, 인출에는 두 번의 바이트 읽기가 필요합니다. 정의상 상위 바이트를 먼저 저장합니다.

선택한 RAM 읽기에 마이크로스텝 하나면 충분하다고 가정하면 다음과 같습니다.

단계레지스터 전송중요한 제어
F0MAR ← PCoe_pc, load_mar
F1MDR ← RAM[MAR]; PC ← PC + 1mem_read, load_mdr, inc_pc
F2IR[15:8] ← MDRoe_mdr, load_ir_hi
F3MAR ← PCoe_pc, load_mar
F4MDR ← RAM[MAR]; PC ← PC + 1mem_read, load_mdr, inc_pc
F5IR[7:0] ← MDRoe_mdr, load_ir_lo

F5 뒤 IR에는 완전한 명령어 하나가 들어 있고 PC는 이미 다음 명령어를 가리킵니다. 디코드는 실행 시퀀스를 선택합니다.

RAM에 주소-데이터 대기가 필요하다면 F1과 F4를 요청, 대기, 캡처 단계로 나누세요. 바이트 폭 전송 하나 안에 16비트 인출을 숨기지 마세요.

9. 실행 마이크로연산 정의하기

ADD RD, RA, RB

단계전송
E0A ← R[RA]
E1B ← R[RB]
E2R[RD] ← A + B; FLAGS ← ALU flags
E3명령 종료, F0로 복귀

RA, RB, RD는 디코드된 인에이블로 R0–R3 중 하나를 선택합니다. 유효하지 않은 레지스터 코드는 불법 명령 경로로 가야 합니다.

LDI RD, imm8

단계전송
E0R[RD] ← IR[7:0]
E1명령 종료

LD RD, addr8

단계전송
E0MAR ← IR[7:0]
E1MDR ← RAM[MAR]
E2R[RD] ← MDR
E3명령 종료

ST RD, addr8

단계전송
E0MAR ← IR[7:0]
E1MDR ← R[RD]
E2RAM[MAR] ← MDR
E3명령 종료

JMP와 JZ

  • JMP: PC ← IR[7:0] 후 종료합니다.
  • JZ: Z가 1일 때만 PC를 로드하고, 관계없이 종료합니다.

HLT

쓰기를 전혀 내보내지 않는 안정적인 제어기 상태로 들어갑니다. 수동 구동 시뮬레이터의 클록을 멈추는 것은 편리하지만, 클록 에지가 계속되어도 아키텍처 상태는 잘 정의되어 있어야 합니다.

10. 시험 프로그램을 손으로 어셈블하고 로드하기

이 프로그램은 5와 3을 로드하고, 이를 R2에 더한 뒤, 결과를 주소 0x10에 저장하고 정지합니다.

시작 주소명령어16비트 워드메모리 바이트
0x00LDI R0, #50x10050x10 0x05
0x02LDI R1, #30x11030x11 0x03
0x04ADD R2, R0, R10x40120x40 0x12
0x06ST R2, 0x100x32100x32 0x10
0x08HLT0x80000x80 0x00

그 열 바이트를 주소 0x00부터 0x09에 로드한 뒤 리셋합니다.

  • PC = 0x00
  • 제어기 마이크로스텝 = F0
  • halted = 0
  • 제어 워드가 선택할 때를 제외한 모든 버스 구동기는 비활성화

첫 인출을 한 단계씩 실행해 다음을 확인합니다.

  1. F2 뒤 IR 상위 바이트는 0x10입니다.
  2. F5 뒤 IR은 0x1005입니다.
  3. PC는 0x02입니다.
  4. LDI가 R0에 0x05를 넣습니다.
  5. 다른 레지스터나 메모리 위치는 변하지 않습니다.

정지 시 다음과 같아야 합니다.

  • R0 = 0x05
  • R1 = 0x03
  • R2 = 0x08
  • RAM[0x10] = 0x08
  • PC = 0x0A

이 최종 값들은 필요하지만 충분하지는 않습니다. 고장 난 CPU도 다른 위치를 훼손하면서 이 값들은 만들 수 있습니다.

11. 최종 답만이 아니라 불변 조건 검증하기

다음을 점검에 추가하세요.

  • 어느 시점에도 버스 출력 인에이블이 둘 이상이 아님
  • 메모리 쓰기는 ST 쓰기 단계에서만 인가됨
  • IR 바이트는 F2와 F5에서만 로드됨
  • 정상 인출마다 PC가 정확히 두 번 증가함
  • 플래그는 갱신하도록 정의된 명령에서만 기록됨
  • 잘못된 opcode나 레지스터 코드는 의도하지 않은 쓰기를 일으키지 않음
  • 정지 상태는 아키텍처 부작용을 일으키지 않음
  • 리셋은 알려진 제어기 상태에 도달함

모든 명령어에서 다음의 추적을 기록합니다.

clock, microstep, PC, IR, bus owner, bus value,
register loads, memory read/write, ALU op, flags

시험이 실패하면 예상 추적과 처음 달라지는 사이클을 찾으세요. 최종의 잘못된 값에서 디버깅을 시작하면 보통 몇 단계 늦습니다.

오실로스코프 디버깅 안내서는 모델링된 파형을 물리 타이밍 사인오프와 혼동하지 않고 살피는 방법을 설명합니다.

12. 흔한 실패 모드

증상가능성 높은 원인먼저 확인할 것
IR에 바이트 순서가 뒤바뀜로더와 인출의 명령 바이트 순서가 다름주소 PC 및 PC+1
PC가 네 번 진행바이트마다 두 번 증가하거나 폭 가정을 섞음F0–F5 추적
버스 경합두 출력 인에이블이 제어 비트를 공유디코드된 제어 워드
캡처할 때 버스가 구동되지 않음소스 인에이블 누락버스 소유자 단언
ADD가 잘못된 레지스터에 기록RD 필드 디코드 또는 레지스터 코드 순서IR[3:0]와 로드선
저장이 명령 메모리를 훼손주소/즉시값 또는 mem_write 타이밍MAR와 ST E2
분기가 오래된 Z를 사용플래그가 기록되지 않았거나 JZ가 잘못된 상태를 샘플ADD/SUB E2와 JZ
제어기가 인출로 돌아가지 않음종료/다음 상태 항목 누락마이크로스텝 전이
불법 opcode가 연산 수행사용하지 않는 제어 ROM을 안전하게 초기화하지 않음기본 제어 워드

13. 이 CPU가 가르치는 것과 가르치지 않는 것

이 설계는 레지스터 전송, 명령어 인코딩, 버스 소유권, ALU 플래그, 메모리 시퀀싱, 제어기 상태를 가르칩니다.

다음은 모델링하지 않습니다.

  • 트랜지스터 수준 RAM 또는 논리
  • 캐시 계층이나 가상 메모리
  • 추측 실행이나 비순차 실행
  • 아날로그 클록 동작이나 준안정성
  • 물리적 전파, 배선, 전력, 열 한계
  • 상용 보안 또는 예외 아키텍처

이 단일 공유 버스는 관찰하기 쉽게 의도한 것이지 현대 CPU 내부 토폴로지에 관한 주장이 아닙니다.

안전한 순서의 확장

  1. 자동화된 명령 시험을 추가합니다. 기능을 더하기 전에 각 opcode와 불법 인코딩을 검증합니다.
  2. AND, OR, XOR, 시프트를 추가합니다. 먼저 플래그 동작을 정의한 다음 제어 시퀀스를 추가합니다.
  3. 직접 비교를 이용한 조건 분기를 추가합니다. 플래그 기반 ISA와 비교-분기 ISA의 차이가 드러납니다.
  4. 스택 포인터와 호출/복귀를 추가합니다. 스택 성장, 바이트 순서, 오버플로 동작을 명세화합니다.
  5. 인터럽트 상태 기계를 추가합니다. 벡터를 로드하기 전에 복귀 주소와 플래그를 저장하고 우선순위와 마스킹을 정의합니다.
  6. 명령 메모리와 데이터 메모리를 분리합니다. 새 인출 일정을 통합 메모리 설계와 비교합니다.
  7. 다중 사이클 참조가 통과한 뒤에만 파이프라인합니다. 그 뒤 단계 유효성, 스톨, 포워딩, 플러시, 예외를 정의합니다.

파이프라인 확장을 시도하기 전에 인출–디코드–실행 심화와 명령 레지스터/디코드 안내서를 사용하세요.

직접 해 보기

Sequential Instruction Executor는 방향을 잡는 데, 8비트 ALU 시스템은 산술을 별도로 검증하는 데, CPU 플래그 레지스터는 상태 동작을 시험하는 데 사용하세요. 회로도 옆에는 아키텍처와 마이크로연산 표를 문서로 유지합니다.

중요한 이정표는 8을 한 번 보는 것이 아닙니다. 각 상태 변화가 왜 허가되었는지 설명하고, 추적에서 재현하며, 다른 상태는 변하지 않았음을 증명할 수 있어야 합니다.

아이디어를 실제로 작동하는 회로로 만들어 보세요.