JK 입력식으로 동기 카운터 만들기
원하는 상태 변화에서 거꾸로 필요한 J·K 입력을 찾는 여기표를 만들고, 무관 조건을 넣은 카르노 맵으로 2비트 동기 카운터의 입력식을 이끌어 냅니다. 한 에지에서 모든 비트를 이전 값으로 함께 계산해야 하는 이유를 잘못된 구현과 비교하고, 동기 리셋과 실제 부품의 차이를 다룹니다.
래치·플립플롭·클록의 JK 표는 J와 K가 주어졌을 때 다음 상태가 무엇인지 알려 줍니다. 그런데 회로를 설계할 때는 질문이 거꾸로입니다. 원하는 다음 상태가 정해져 있고, 그 상태를 만들려면 J와 K에 무엇을 넣어야 하는지를 찾아야 합니다. 이 글에서는 이 거꾸로 된 표를 만들고, 부울 대수와 카르노 맵의 무관 조건을 이용해 2비트 동기 카운터의 입력식을 설계합니다.
원하는 전이에서 입력을 거꾸로 찾는다
두 비트 가 같은 상승 에지에서 함께 바뀌며 00, 01, 10, 11을 지나 다시 00으로 돌아가는 동기 카운터를 만들려고 합니다. 플립플롭 하나가 지금의 값 Q에서 다음 값 로 가려면 J와 K가 무엇이어야 하는지를 정리한 표를 여기표(excitation table)라고 합니다.
| Q | J | K | 이유 | |
|---|---|---|---|---|
| 0 | 0 | 0 | X | 유지(00)나 reset(01)이면 0이 그대로이다 |
| 0 | 1 | 1 | X | set(10)이나 반전(11)이면 1이 된다 |
| 1 | 0 | X | 1 | reset(01)이나 반전(11)이면 0이 된다 |
| 1 | 1 | X | 0 | 유지(00)나 set(10)이면 1이 그대로이다 |
X는 0을 넣든 1을 넣든 그 전이가 똑같이 일어난다는 뜻의 무관 조건입니다. 예를 들어 0에서 0으로 가려면 J만 0이면 되고, K가 0이면 유지, 1이면 reset이 되어 어느 쪽이든 결과가 0입니다. X는 값을 아무렇게나 둔다거나 회로에 0도 1도 아닌 신호를 넣는다는 뜻이 아니며, 식을 줄일 때 0과 1 가운데 편한 쪽으로 고를 수 있다는 뜻입니다. 이 표를 카운터의 네 가지 전이에 적용하면 다음과 같습니다.
| 00 | 01 | 0 | X | 1 | X |
| 01 | 10 | 1 | X | X | 1 |
| 10 | 11 | X | 0 | 1 | X |
| 11 | 00 | X | 1 | X | 1 |
무관 조건으로 입력식을 줄인다
입력 네 개를 각각 을 행, 을 열로 하는 2 × 2 카르노 맵에 놓습니다. 아래 표의 괄호 안 두 값은 그 행에서 , 일 때의 값입니다.
| 입력 | 행 | 행 | 묶음과 식 |
|---|---|---|---|
| (1, X) | (1, X) | X를 1로 골라 네 칸을 묶으면 1 | |
| (X, 1) | (X, 1) | X를 1로 골라 네 칸을 묶으면 1 | |
| (0, 1) | (X, X) | 열의 X를 1로 골라 세로 두 칸을 묶으면 | |
| (X, X) | (0, 1) | 열의 X를 1로 골라 세로 두 칸을 묶으면 |
과 의 열에 남은 X는 0으로 골라 식을 마무리합니다. 그래서 , 입니다. 아래 비트 은 에지마다 반전하고, 위 비트 은 에지 직전의 이 1일 때만 반전합니다. 이진수를 1씩 셀 때 아래 자리가 1이었다가 0으로 넘어가는 순간에만 위 자리가 바뀐다는 사실을 그대로 옮긴 식입니다.
이전 Q0가 상위 비트의 반전을 고릅니다
이전 Q0=0이므로 상위 비트는 유지한다. 두 비트가 토글해 0으로 돌아간다. 각 단계의 값과 전환 이유를 비교합니다.
컴퓨터구조 · 논리 연결
이전 Q0가 상위 비트의 반전을 고릅니다
J0·K0에는 논리 1, J1·K1에는 에지 직전 Q0를 연결합니다. 두 JK 소자는 같은 상승 에지에서 갱신합니다.
정상 동작의 입력 연결 개요입니다. Q0는 상위 소자의 클록이 아니라 J1·K1에 연결됩니다. reset 동안 J=0·K=1을 선택하는 추가 논리, 전원·setup/hold·배선 지연은 본문에서 따로 구분합니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 00→01부터 11→00까지 진행합니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 00→01 이전 Q0=0이므로 상위 비트는 유지한다. |
|
|
| 01→10 이전 Q0=1이므로 두 비트가 토글한다. |
|
|
| 10→11 이전 Q0=0이므로 Q1은 유지한다. |
|
|
| 11→00 두 비트가 토글해 0으로 돌아간다. |
|
|
이전 Q0가 상위 비트의 반전을 고릅니다
이전 Q0=0이므로 상위 비트는 유지한다. 두 비트가 토글해 0으로 돌아간다. 각 단계의 값과 전환 이유를 비교합니다.
컴퓨터구조 · 논리 연결
이전 Q0가 상위 비트의 반전을 고릅니다
J0·K0에는 논리 1, J1·K1에는 에지 직전 Q0를 연결합니다. 두 JK 소자는 같은 상승 에지에서 갱신합니다.
정상 동작의 입력 연결 개요입니다. Q0는 상위 소자의 클록이 아니라 J1·K1에 연결됩니다. reset 동안 J=0·K=1을 선택하는 추가 논리, 전원·setup/hold·배선 지연은 본문에서 따로 구분합니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 00→01부터 11→00까지 진행합니다.
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 00→01 이전 Q0=0이므로 상위 비트는 유지한다. |
|
|
| 01→10 이전 Q0=1이므로 두 비트가 토글한다. |
|
|
| 10→11 이전 Q0=0이므로 Q1은 유지한다. |
|
|
| 11→00 두 비트가 토글해 0으로 돌아간다. |
|
|
그림은 두 JK 플립플롭이 같은 클록을 함께 받고, 이 위 플립플롭의 클록이 아니라 , 입력으로 이어진 모습입니다. 을 위 비트의 클록으로 쓰는 리플 카운터와 구별해야 합니다. 리셋 회로, 전원, 게이트의 실제 지연은 그림에서 생략했으며, 아래에서 따로 다룹니다.
한 에지에서 모든 비트를 이전 값으로 계산한다
지금 상태가 01이면 은 반전해 0이 되고, 에지 직전의 이 1이므로 도 반전해 1이 되어 다음 상태는 10입니다. 이때 두 비트의 다음 값은 모두 에지 직전의 값으로 계산해야 합니다. 실제 회로에서도 모든 플립플롭이 같은 에지에서 동시에 값을 받아들이기 때문입니다. 소프트웨어로 흉내 낼 때 이것을 놓치면 전혀 다른 회로가 됩니다.
def jk(q, j, k):
return (j & (1 - q)) | ((1 - k) & q)
def counter_step(state, reset=False):
if reset:
return 0
q1, q0 = divmod(state, 2)
next_q0 = jk(q0, 1, 1)
next_q1 = jk(q1, q0, q0)
return 2 * next_q1 + next_q0
def counter_step_wrong(state):
q1, q0 = divmod(state, 2)
q0 = jk(q0, 1, 1)
q1 = jk(q1, q0, q0)
return 2 * q1 + q0
for step in (counter_step, counter_step_wrong):
state, trace = 0, []
for _ in range(4):
state = step(state)
trace.append(f"{state:02b}")
print(step.__name__, trace)
print(counter_step(0b11, reset=True))counter_step ['01', '10', '11', '00']
counter_step_wrong ['11', '10', '01', '00']
0jk는 JK 플립플롭의 특성 방정식 이고, divmod(state, 2)는 상태를 위 비트와 아래 비트로 나눕니다. counter_step은 두 비트의 다음 값을 모두 원래의 q0로 계산한 뒤 함께 돌려주므로, 00에서 시작해 01, 10, 11, 00으로 셉니다. counter_step_wrong은 q0를 먼저 새 값으로 바꾼 뒤 그 새 값으로 q1의 입력을 정합니다. 그 결과 11, 10, 01, 00으로 거꾸로 세는 회로가 되었는데, 위 비트가 "아래 비트가 1에서 0으로 넘어갈 때"가 아니라 "아래 비트가 1이 될 때" 반전하기 때문입니다. 마지막 줄은 리셋이 켜진 에지에서 11이 00이 된다는 결과입니다.
리셋과 실제 부품
counter_step의 리셋은 리셋 신호가 켜진 에지에서 00을 저장하는 동기 리셋입니다. 앞에서 구한 입력식 , 은 카운터가 세는 동작만 정한 것이라, 리셋까지 회로로 만들려면 리셋이 켜진 동안 각 비트에 , 을 넣어 다음 에지에서 0이 되게 하는 논리를 더해야 합니다. 플립플롭의 비동기 클리어 단자를 쓰면 에지와 상관없이 곧바로 0이 되므로, 같은 시간표로 읽을 수 없습니다.
실제 부품은 이 교재의 모델과 다를 수 있습니다. 예를 들어 onsemi SN74LS76A 데이터시트의 JK 플립플롭은 하강 에지에서 동작하고, 클록과 상관없이 동작하는 set과 clear 단자를 가집니다. 그래서 이 글의 상승 에지, 동기 리셋 모델을 그 부품의 배선과 타이밍으로 그대로 옮기면 안 됩니다. 실제 동기 회로에서는 에지 직전에 입력이 안정되는지, 출력 지연과 조합 회로의 지연, 설정 시간과 유지 시간을 함께 확인해야 하며, 이런 시간 조건은 MIT 6.004의 순차 논리 강의에서 더 볼 수 있습니다.
정리
- 여기표는 지금의 값과 원하는 다음 값에서 필요한 입력을 거꾸로 찾은 표이며, JK 플립플롭은 전이마다 한 입력이 무관 조건 X가 됩니다.
- 카운터의 전이마다 여기표를 적용하고, 무관 조건을 이용해 카르노 맵으로 줄이면 2비트 동기 카운터의 입력식은 , 입니다.
- 동기 회로에서는 모든 비트의 다음 값을 에지 직전의 값으로 함께 계산해야 하며, 새 값을 먼저 쓰면 다른 회로가 됩니다.
- 동기 리셋을 회로로 만들려면 입력 논리를 더해야 하고, 실제 부품의 동작 에지와 비동기 단자는 데이터시트로 확인합니다.
연습 문제
1. 잘못 이은 입력
은 그대로 두고 로 잘못 이었습니다. 00에서 시작해 네 에지 뒤까지의 상태를 쓰고, 정상 카운터와 처음 달라지는 전이를 찾으세요.
해설 보기
J = K = 1이면 그 비트는 에지마다 반전하므로, 두 비트가 함께 반전해 상태는 11, 00, 11, 00입니다. 첫 전이부터 정상 카운터의 00에서 01과 달리 00에서 11로 갑니다. 위 비트가 아래 비트와 상관없이 매번 반전하기 때문이며, , 을 에 이어야 아래 비트가 1일 때만 반전합니다. 입력식에 이 들어간 이유를 이 오류로 확인할 수 있습니다.
2. 3비트로 늘리기
같은 방법으로 3비트 동기 카운터를 만들면 맨 위 비트 의 입력 , 는 무엇이 되어야 하나요?
해설 보기
1씩 셀 때 어떤 자리는 그 아래 자리가 모두 1인 다음 순간에만 바뀝니다. 그래서 는 에지 직전의 과 이 모두 1일 때만 반전해야 하므로 입니다. 이 식으로 000에서 시작해 에지를 이어 가면 1, 2, … , 7을 지나 다시 0으로 돌아옵니다. 일반적으로 k번 비트의 입력은 그 아래 비트를 모두 AND한 값이 됩니다.
3. 리셋이 켜진 에지
정상 입력식을 쓴 카운터가 상태 11에 있을 때 리셋을 켜고 에지를 하나 주면 결과는 무엇인가요? 리셋을 켠 순간에 곧바로 00이 된다고 말해도 되나요?
해설 보기
동기 리셋은 리셋이 카운트보다 먼저이므로 그 에지에서 00이 저장됩니다. 본문 코드의 마지막 줄도 0을 냅니다. 하지만 리셋을 켠 순간에 곧바로 00이 되는 것은 아니고, 다음 에지가 올 때까지는 11이 유지됩니다. 곧바로 00이 되는 것은 비동기 클리어의 동작이므로, 두 방식을 같은 시간표로 설명하면 안 됩니다.
입력식을 설계한 뒤에는 모든 상태에서 다음 상태를 계산해 원하는 순서와 비교하고, 모든 비트를 에지 직전의 값으로 계산했는지 확인해 보세요. 다음 장의 CPU 데이터 경로에서는 레지스터와 선택 회로를 이어 명령어를 실행하는 경로를 만듭니다.