이번 문서의 목표: 이 파일을 다 읽으면 병렬 레지스터와 네 가지 시프트 레지스터(SISO·SIPO·PISO·PIPO)의 동작을 클록별로 추적하고, 링 카운터·존슨 카운터가 어떻게 시프트 레지스터로 특수한 순환 패턴을 만드는지 설명할 수 있다.
왜 플립플롭을 “나란히” 놓는가
18편에서 다룬 플립플롭 하나는 1비트만 기억한다. 그런데 실제 디지털 시스템은 8비트, 16비트처럼 여러 비트를 한 덩어리(워드, word)로 저장하고 옮겨야 한다. 예를 들어 CPU가 계산 결과 “01011010”이라는 8비트 값을 다음 연산까지 잠깐 보관해 둬야 한다면, 8비트를 동시에 저장할 수 있는 장치가 필요하다. 이렇게 여러 개의 플립플롭을 나란히 배치해 여러 비트를 한 단위로 저장하는 장치를 레지스터(register)라고 한다.
쉽게 말하면: 레지스터는 플립플롭 여러 개를 한 줄로 세워 놓고 같은 클록을 공유하게 만든, 여러 비트짜리 기억장치다.
병렬 레지스터: 가장 단순한 형태
쉽게 말하면: 4비트 데이터를 한 번에 저장하고 싶으면 D 플립플롭 4개를 나란히 놓고, 4개의 입력선에 동시에 데이터를 걸어 준 뒤 클록을 한 번 뛰게 하면 된다.
병렬 레지스터(parallel register)는 비트 레지스터라면 D 플립플롭을 개 나란히 배치하고, 모든 플립플롭이 같은 클록을 동시에 공유하도록 만든다. 클록이 뛰는 순간 개의 입력 이 동시에 각 플립플롭에 저장된다. 실제 회로에서는 로드 신호(load enable)를 추가로 두어, 로드 신호가 1일 때만 새 값을 저장하고 0이면 이전 값을 그대로 유지하게 만드는 경우가 많다. 이렇게 하면 레지스터가 “매 클록마다 무조건 새 값을 받는” 것이 아니라 “필요할 때만 값을 갱신”하도록 제어할 수 있다.
시프트 레지스터: 값을 옆으로 밀어낸다
쉽게 말하면: 시프트 레지스터는 플립플롭을 사슬처럼 연결해서, 클록이 뛸 때마다 각 플립플롭의 값이 옆 플립플롭으로 한 칸씩 넘어가게 만든 장치다.
시프트 레지스터(shift register)는 플립플롭 개를 사슬처럼 직렬로 연결한다. 첫 번째 플립플롭의 출력이 두 번째 플립플롭의 입력으로, 두 번째의 출력이 세 번째의 입력으로 이어지는 식이다. 클록이 한 번 뛸 때마다 모든 값이 한 칸씩 옆으로 밀려 이동한다(시프트, shift). 데이터를 넣는 방식(직렬 vs 병렬)과 꺼내는 방식(직렬 vs 병렬)의 조합에 따라 네 종류로 나뉜다.
네 가지 시프트 레지스터
| 구분 | 영문 | 입력 방식 | 출력 방식 | 대표 용도 |
|---|---|---|---|---|
| 직렬입력 직렬출력 | SISO(Serial-In Serial-Out) | 한 비트씩 순서대로 입력 | 한 비트씩 순서대로 출력 | 지연선(데이터를 일정 클록만큼 늦추는 용도) |
| 직렬입력 병렬출력 | SIPO(Serial-In Parallel-Out) | 한 비트씩 순서대로 입력 | 모든 비트를 한 번에 출력 | 직렬 통신 수신부(비트를 모아 병렬로 변환) |
| 병렬입력 직렬출력 | PISO(Parallel-In Serial-Out) | 모든 비트를 한 번에 입력 | 한 비트씩 순서대로 출력 | 직렬 통신 송신부(병렬 데이터를 직렬로 변환) |
| 병렬입력 병렬출력 | PIPO(Parallel-In Parallel-Out) | 모든 비트를 한 번에 입력 | 모든 비트를 한 번에 출력 | 사실상 병렬 레지스터와 동일한 동작 |
시험 함정: PIPO는 입출력이 모두 병렬이라 실질적으로 앞서 설명한 병렬 레지스터와 동작이 같다. “PIPO는 시프트 레지스터가 아니라 별개의 장치다”라고 오해하지 말 것 — 시프트 레지스터 계열의 이름 체계 안에서 입출력 방식만 병렬로 고정한 경우일 뿐이다.
SISO 4비트 시프트 레지스터의 클록별 추적
4비트 SISO 시프트 레지스터에 직렬로 (가장 먼저 들어오는 비트가 1)을 순서대로 입력한다고 하자. 각 플립플롭을 (이 가장 먼저 들어온 비트가 도달하는 마지막 자리, 이 매 클록 새 입력을 받는 첫 자리)이라 하고, 클록마다 오른쪽에서 왼쪽으로() 한 칸씩 이동한다고 하자. 초기값은 이다.
| 클록 | 직렬 입력 | ||||
|---|---|---|---|---|---|
| 초기 | – | 0 | 0 | 0 | 0 |
| 1번째 | 1 | 0 | 0 | 0 | 1 |
| 2번째 | 0 | 0 | 0 | 1 | 0 |
| 3번째 | 1 | 0 | 1 | 0 | 1 |
| 4번째 | 1 | 1 | 0 | 1 | 1 |
결과 해석: 4번째 클록이 지나면 이 되어, 직렬로 넣은 이 정확히 레지스터 안에 순서대로 담긴다. 만약 이 레지스터가 SIPO였다면 4번째 클록 직후 을 한 번에 병렬로 읽어 “이라는 4비트 값이 도착했다”고 판단할 수 있다. 반대로 PISO였다면, 처음에 을 4개의 병렬 입력선에 동시에 걸어 로드한 뒤, 클록마다 (또는 정해진 끝단)에서 한 비트씩 순서대로 꺼내 직렬 통신선으로 내보낸다.
유니버설 시프트 레지스터: 모드를 선택할 수 있는 만능형
쉽게 말하면: 유니버설 시프트 레지스터는 제어 신호 2비트로 “유지·오른쪽 시프트·왼쪽 시프트·병렬 로드” 네 가지 동작 중 하나를 매 클록마다 골라 쓸 수 있게 만든 레지스터다.
실제 CPU나 통신 장치에서는 상황에 따라 값을 유지하거나, 오른쪽으로 밀거나, 왼쪽으로 밀거나, 아예 새 값을 통째로 넣어야 하는 경우가 섞여서 발생한다. 이 네 가지 동작을 모드 선택 신호() 2비트로 고를 수 있게 만든 것이 유니버설 시프트 레지스터(universal shift register)다.
| 모드 선택 | 동작 |
|---|---|
| 00 | 상태 유지(변화 없음) |
| 01 | 오른쪽 시프트 |
| 10 | 왼쪽 시프트 |
| 11 | 병렬 로드(새 데이터 통째로 저장) |
각 플립플롭 앞에 4-입력 멀티플렉서(16편에서 다룬 MUX)를 하나씩 붙여, 값에 따라 “이전 값 유지”, “오른쪽 이웃 값”, “왼쪽 이웃 값”, “병렬 입력값” 중 하나를 골라 D 플립플롭 입력으로 연결하는 방식으로 구현한다.
링 카운터: 시프트 레지스터로 만드는 순환 패턴
쉽게 말하면: 링 카운터는 시프트 레지스터의 마지막 출력을 다시 첫 입력으로 되먹임해서, 단 하나의 1(또는 0)이 자리를 돌아가며 순환하게 만든 회로다.
링 카운터(ring counter)는 비트 시프트 레지스터의 마지막 플립플롭 출력을 첫 번째 플립플롭의 입력으로 다시 연결(피드백, feedback)한 구조다. 초기에 플립플롭 하나에만 1을 넣고(나머지는 0) 클록을 뛰게 하면, 그 1이 자리를 한 칸씩 옮겨가며 순환한다.
4비트 링 카운터의 상태 추적
| 클록 | ||||
|---|---|---|---|---|
| 초기 | 0 | 0 | 0 | 1 |
| 1번째 | 0 | 0 | 1 | 0 |
| 2번째 | 0 | 1 | 0 | 0 |
| 3번째 | 1 | 0 | 0 | 0 |
| 4번째 | 0 | 0 | 0 | 1(다시 순환) |
비트 링 카운터는 정확히 개의 서로 다른 상태만 순환하므로 모드 카운터로 동작한다. 4비트 링 카운터는 모드 4다.
존슨 카운터: 링 카운터의 절반 비트로 두 배의 상태를
쉽게 말하면: 존슨 카운터는 마지막 플립플롭의 반전된 출력을 첫 입력으로 되먹임해서, 같은 비트 수의 링 카운터보다 두 배 많은 상태를 만들어낸다.
존슨 카운터(Johnson counter, 뒤틀린 링 카운터twisted-ring counter라고도 부른다)는 링 카운터와 거의 같지만, 마지막 플립플롭의 출력을 반전시켜서(NOT을 걸어서) 첫 번째 입력으로 되먹임한다는 점만 다르다. 이 사소한 차이가 순환하는 상태 개수를 두 배로 늘린다.
4비트 존슨 카운터의 상태 추적
| 클록 | ||||
|---|---|---|---|---|
| 초기 | 0 | 0 | 0 | 0 |
| 1번째 | 0 | 0 | 0 | 1 |
| 2번째 | 0 | 0 | 1 | 1 |
| 3번째 | 0 | 1 | 1 | 1 |
| 4번째 | 1 | 1 | 1 | 1 |
| 5번째 | 1 | 1 | 1 | 0 |
| 6번째 | 1 | 1 | 0 | 0 |
| 7번째 | 1 | 0 | 0 | 0 |
| 8번째 | 0 | 0 | 0 | 0(다시 순환) |
결과 해석: 4비트 존슨 카운터는 0000부터 시작해 1이 오른쪽에서 왼쪽으로 채워지고(0001 → 0011 → 0111 → 1111), 그 다음 0이 다시 오른쪽에서 왼쪽으로 채워지며(1110 → 1100 → 1000 → 0000) 총 8개의 상태를 순환한다. 비트 존슨 카운터는 개의 상태를 순환하는 모드 카운터가 된다.
세 순환 회로의 상태 개수 비교
쉽게 말하면: 같은 비트 수를 쓰더라도 어떤 되먹임 방식을 쓰느냐에 따라 몇 개의 상태를 순환할 수 있는지가 완전히 달라진다.
| 구분 | 비트로 만들 수 있는 상태 개수 | 예시(4비트) | 되먹임 방식 |
|---|---|---|---|
| 링 카운터 | 개 | 4개(모드 4) | 마지막 출력을 그대로 첫 입력에 되먹임 |
| 존슨 카운터 | 개 | 8개(모드 8) | 마지막 출력을 반전해 첫 입력에 되먹임 |
| 일반 동기 카운터(21편) | 개(최대) | 최대 16개(모드 16) | 별도의 J, K 입력 논리로 임의 순서 설계 |
링 카운터와 존슨 카운터는 회로가 매우 단순(별도의 조합 논리 게이트가 거의 필요 없다)하다는 장점이 있지만, 만들 수 있는 상태 개수가 비트 수에 비례하는 수준(선형)에 그친다. 반면 21편에서 설계한 일반 동기 카운터는 비트 수의 지수(거듭제곱)만큼 많은 상태를 만들 수 있지만, 그만큼 J, K 입력을 계산하는 추가 논리 게이트가 필요하다.
시험 함정: 링 카운터와 존슨 카운터 모두 클록마다 정확히 한 칸씩만 값이 이동하는 시프트 레지스터의 일종이다. “카운터”라는 이름 때문에 21편의 이진 증가 카운터처럼 산술적으로 값이 1씩 늘어난다고 착각하면 안 된다. 이들이 세는 것은 “클록이 몇 번 뛰었는지”이지, 레지스터에 저장된 이진수 값이 산술적으로 증가하는 것이 아니다.
핵심 정리
- 레지스터는 D 플립플롭 여러 개를 나란히 배치해 여러 비트를 한 번에 저장하는 장치이며, 로드 신호로 갱신 여부를 제어할 수 있다.
- 시프트 레지스터는 입출력 방식(직렬·병렬)의 조합에 따라 SISO, SIPO, PISO, PIPO 네 종류로 나뉘고, PIPO는 사실상 병렬 레지스터와 동작이 같다.
- 유니버설 시프트 레지스터는 모드 선택 신호로 유지·오른쪽 시프트·왼쪽 시프트·병렬 로드 네 동작을 모두 지원한다.
- 링 카운터는 마지막 출력을 그대로 되먹임해 비트로 개 상태를 순환하고, 존슨 카운터는 반전해 되먹임해 개 상태를 순환한다.
- 링·존슨 카운터는 회로가 단순하지만 상태 개수가 비트 수에 선형적으로만 비례하는 반면, 21편의 일반 동기 카운터는 추가 게이트가 필요한 대신 비트 수의 거듭제곱만큼 많은 상태를 임의의 순서로 설계할 수 있다.