클럭·리셋·클럭 도메인
휴대폰 기판 위에는 쌀알만 한 금속 깡통이 하나 있다. 그 안의 얇은 수정 조각이 1초에 3,840만 번 떨린다. SB-1의 큰 코어는 이 떨림을 100배 가까이 부풀린 3.8 GHz로 뛰고, GPU는 1 GHz, 메모리 컨트롤러는 또 다른 박자로 뛴다. 하나의 기준 박자에서 수십 개의 서로 다른 박자를 만들고, 그것을 칩 구석구석 수십억 개의 플립플롭에 몇 ps 오차로 동시에 전하고, 박자가 다른 블록끼리 데이터를 잃지 않고 건네는 일. 이 장은 그 클럭의 이야기다. 그리고 모든 것을 깨끗한 출발점에 세우는 리셋도 함께 다룬다.
- PLL이 위상 비교·전하 펌프·VCO·분주기로 기준 클럭의 정수배 주파수에 잠기는 과정을 설명하고, 루프 대역폭이 잠금 시간과 지터에 주는 영향을 확인한다.
- 클럭 트리의 스큐와 지터가 setup·hold 여유를 어떻게 깎는지 계산한다.
- 래치 기반 클럭 게이팅 셀(ICG)이 글리치 없이 클럭을 끄는 원리를 파형으로 읽는다.
- 준안정과 MTBF 식을 이해하고, 2단 동기화기·그레이 코드·비동기 FIFO로 클럭 도메인을 안전하게 건넌다.
- 비동기 인가·동기 해제 리셋과 리셋 동기화기가 필요한 이유를 설명한다.
수정 발진기에서 GHz까지: PLL
모든 클럭의 뿌리는 칩 밖의 수정 발진기(Crystal oscillator)다. 수정은 압전 효과로 정해진 주파수에서만 기계적으로 공진하므로, 온도가 변해도 주파수가 백만분의 수십(수십 ppm) 이내로 정확하다. 스마트폰은 보통 19.2 MHz나 38.4 MHz 수정(모뎀의 무선 규격과 맞추기 좋은 값)과, 시계용 32.768 kHz 수정을 함께 쓴다. 32,768 = 215이라 15번 반으로 나누면 정확히 1초가 된다.
그런데 수정은 수십 MHz 이상을 직접 만들기 어렵다. GHz 클럭은 칩 안의 VCO(Voltage-controlled oscillator, 전압 제어 발진기)가 만든다. VCO는 제어 전압에 따라 주파수가 바뀌는 링 발진기나 LC 발진기인데, 혼자 두면 온도와 전압에 따라 주파수가 수 %씩 떠다닌다. 그래서 VCO 출력을 N으로 나눠(분주) 수정 클럭과 비교하고, 어긋나면 제어 전압을 고쳐 주는 되먹임 고리를 만든다. 이것이 위상 고정 루프(PLL, Phase-locked loop)다. 고리가 잠기면 나눈 클럭이 기준 클럭과 박자가 같아지므로 \(f_{\text{out}} = N\cdot f_{\text{ref}}\)가 된다.
고리의 첫 단계는 위상·주파수 검출기(PFD, Phase-frequency detector)다. 기준 클럭 에지가 먼저 오면 UP 펄스를, 되먹임 클럭 에지가 먼저 오면 DN 펄스를 낸다. 펄스 폭이 곧 위상 차다. 아래에서 되먹임 클럭의 주파수와 위상을 바꿔 보자.
PFD의 펄스는 전하 펌프(Charge pump)를 켜서 작은 전류를 루프 필터 커패시터에 넣거나 뺀다. 커패시터 전압이 VCO의 제어 전압이다. 루프 필터의 저항은 위상 차에 바로 반응하는 비례 항을, 커패시터는 차이를 쌓아 두는 적분 항을 만든다. 결국 PLL은 "위상 오차를 0으로 만드는 PI 제어기"다. 이 제어기의 빠르기가 루프 대역폭(Loop bandwidth), 진동이 얼마나 빨리 가라앉는지가 감쇠 계수 \(\zeta\)다.
PLL 잠금 시뮬레이터
감쇠가 작으면 반응이 날카로워진다. 그런데 "±0.1% 안에 들어와 머문다"는 조건을 생각해 보자.
답 보기
오히려 늘어난다. ζ가 작으면 목표 주파수를 크게 지나쳤다가(오버슈트) 되돌아오기를 여러 번 반복하며 천천히 가라앉는다. 감쇠 진동의 포락선이 \(e^{-\zeta\omega_n t}\)로 줄어들기 때문에 잠금 시간은 대략 \(1/(\zeta\omega_n)\)에 비례한다. ζ가 너무 크면 이번에는 느릿느릿 다가간다. 그래서 설계자는 보통 \(\zeta\approx 0.7\sim1\)을 고른다.
클럭 트리: 동시에 도착하게 하기
PLL에서 나온 클럭 한 가닥은 수백만 개의 플립플롭에 닿아야 한다. 한 선이 감당할 수 없으니 버퍼를 줄줄이 달아 나무처럼 갈라 퍼뜨린다. 이것이 클럭 트리(Clock tree)다. 목표는 단 하나, 모든 잎(플립플롭)에 같은 시각에 도착하는 것이다. 도착 시각의 차이를 클럭 스큐(Clock skew)라 한다.
가장 단순한 방법은 뿌리에서 각 잎까지 가장 짧은 길로 따로 잇는 것이다. 그러면 가까운 잎은 일찍, 먼 잎은 늦게 받는다. 대칭으로 갈라지는 H-트리(H-tree)는 어느 잎까지든 길이가 같다. 아래에서 두 방식을 비교하고, 플립플롭 묶음(동그라미)을 끌어 옮겨 보자.
실제 칩에서는 플립플롭이 고르게 퍼져 있지 않고, 블록마다 클럭이 꺼졌다 켜지며, 공정 편차로 같은 길이의 배선도 지연이 조금씩 다르다. 그래서 설계 도구는 클럭 트리 합성(CTS, Clock tree synthesis) 단계에서 버퍼 크기와 배선 길이를 조절해 스큐를 수십 ps 이내로 맞춘다. 고성능 CPU는 트리 끝을 촘촘한 그물(클럭 메시(Clock mesh))로 묶어 편차를 평균해 버리기도 한다. 그 대가는 전력이다. 클럭망은 매 주기 두 번씩 전체를 충전·방전하므로 칩 동적 전력의 30~40%를 먹는 경우가 흔하다.
스큐와 지터는 타이밍 예산을 깎는다
2장에서 플립플롭 사이 조합 회로의 지연이 클럭 주기를 넘으면 안 된다는 setup 조건과, 너무 빨리 바뀌어 같은 에지의 데이터를 망치면 안 된다는 hold 조건을 보았다. 거기서는 두 플립플롭이 정확히 같은 순간에 클럭을 받는다고 가정했다. 이제 그 가정을 거두자. 받는 쪽(capture) 클럭이 \(t_{\text{skew}}\)만큼 늦게 도착하면 데이터에게는 시간이 그만큼 더 주어지지만, 같은 에지에서 바로 뒤따라 바뀌는 데이터도 그만큼 더 오래 버텨야 한다.
또 하나의 적은 지터(Jitter)다. 스큐가 "장소에 따른" 고정된 차이라면, 지터는 "시간에 따라" 매 주기 클럭 에지가 조금씩 흔들리는 것이다. PLL의 잡음, 전원 전압의 출렁임이 원인이다. 주기 하나가 평소보다 짧아질 수 있으니 setup 예산에서 빼 두어야 한다.
클럭 게이팅: 일하지 않으면 박자도 끈다
클럭망이 동적 전력의 큰 몫을 먹는다면, 일하지 않는 블록의 클럭을 끄는 것이 가장 효과적인 절전이다. 이것이 클럭 게이팅(Clock gating)이다(12장). 순진하게 생각하면 AND 게이트 하나면 된다. gclk = clk AND en. 하지만 en은 보통 조합 회로가 만든 신호라 아무 때나 바뀐다. clk가 1인 동안 en이 바뀌면 gclk에 짧은 가시 펄스(글리치(Glitch))가 생기고, 플립플롭은 이것을 진짜 에지로 알고 엉뚱하게 동작한다.
해결책은 en을 clk가 0일 때만 통과시키는 래치에 한 번 담는 것이다. clk가 1인 동안에는 래치가 값을 붙잡고 있으므로 gclk 펄스는 언제나 온전한 모양이 된다. 이 래치 + AND를 하나로 묶은 표준 셀을 ICG(Integrated clock gating cell)라 한다. 아래 en 줄의 칸(¼주기 단위)을 눌러 en을 아무 때나 바꿔 보자.
클럭 도메인을 건널 때: 준안정
SB-1에는 서로 다른 PLL에서 나온 클럭이 수십 개 있다. 같은 클럭을 받는 회로 묶음을 클럭 도메인(Clock domain)이라 하는데, 서로 무관한 두 도메인 사이에서는 보내는 쪽 데이터가 받는 쪽 클럭 에지와 언제 겹칠지 알 수 없다. 데이터가 setup·hold 창 안에서 바뀌면 플립플롭은 0도 1도 아닌 중간 전압에 걸려 한동안 머문다. 이것이 준안정(Metastability)이다. 언덕 꼭대기에 올려 둔 공처럼, 결국은 어느 한쪽으로 굴러떨어지지만 언제 떨어질지 모른다.
플립플롭 안의 교차 결합 인버터는 중간 전압에서 차이를 지수적으로 키운다. 처음 차이가 \(\Delta v_0\)라면 시간 \(t\) 뒤의 차이는 \(\Delta v_0\, e^{t/\tau}\)이고, \(\tau\)는 인버터 고리의 시정수(수~수십 ps)다. 데이터가 클럭 에지에 가까울수록 \(\Delta v_0\)가 작아 해소에 오래 걸린다.
준안정을 없앨 수는 없다. 할 수 있는 일은 해소할 시간을 충분히 주는 것이다. 비동기 신호를 플립플롭 두 개에 연달아 통과시키면, 첫째가 준안정에 빠져도 둘째가 읽기 전까지 한 주기 동안 해소할 시간이 생긴다. 이것이 2단 동기화기(Two-flop synchronizer)다. 실패할 확률은 해소 시간에 지수적으로 줄어든다. 평균 고장 간격 MTBF(Mean time between failures)는 다음과 같다.
MTBF 10년짜리 동기화기는 칩 하나로는 10년에 한 번이지만, 1억 대가 팔리면 하루에 수만 번 어딘가에서 일어난다. 게다가 한 칩에 CDC 경로가 수백~수천 개 있다. 그래서 설계 규칙은 "MTBF가 우주 나이보다 길어야 한다"는 말을 농담처럼 쓴다. 고속 클럭이나 τ가 큰 저전압 동작에서는 3단 동기화기를 쓴다.
여러 비트를 한꺼번에 건네면: 그레이 코드
2단 동기화기는 비트 하나에는 완벽하다. 결과가 이전 값이든 새 값이든 한 주기 늦게 정해질 뿐이다. 그런데 4비트 카운터를 비트마다 동기화기에 통과시키면 어떨까? 배선 길이와 동기화기의 해소 시간이 비트마다 조금씩 달라서, 0111 → 1000처럼 네 비트가 동시에 바뀌는 순간에 읽으면 어떤 비트는 새 값, 어떤 비트는 옛 값으로 읽힐 수 있다. 결과는 1111이나 0000 같은, 있지도 않았던 값이다.
해결책은 한 번에 한 비트만 바뀌는 그레이 코드(Gray code)로 세는 것이다. 이진수 \(b\)의 그레이 코드는 \(g = b \oplus (b \gg 1)\)이다. 그레이 카운터는 어느 순간에 읽어도 옛 값 아니면 새 값이다. 아래에서 비트 사이 지연 편차를 늘려 가며 두 방식을 비교해 보자.
① 제어 비트 하나: 2단 동기화기. ② 펄스나 요청: 토글 신호로 바꿔 동기화하고 받는 쪽에서 에지를 검출, 필요하면 응답을 돌려보내는 핸드셰이크. ③ 데이터 묶음: 데이터를 그대로 두고 "유효" 비트 하나만 동기화하거나, 다음 절의 비동기 FIFO. 설계 도구는 CDC 검사기로 이 규칙을 어긴 경로를 찾아낸다.
비동기 FIFO: 두 박자 사이의 완충지대
NoC가 CPU 도메인에서 메모리 도메인으로 요청을 넘길 때처럼 데이터가 계속 흐르는 경계에는 비동기 FIFO(Asynchronous FIFO)를 둔다. 원형 버퍼 하나를 두고, 쓰는 쪽은 자기 클럭으로 쓰기 포인터를, 읽는 쪽은 자기 클럭으로 읽기 포인터를 움직인다. 데이터 자체는 동기화하지 않는다. 대신 포인터만 그레이 코드로 바꿔 상대 도메인으로 동기화한다(Cummings, 2002).
- EMPTY: 읽는 쪽이 자기 읽기 포인터와 "동기화되어 넘어온" 쓰기 포인터를 비교해 같으면 비었다고 판단한다.
- FULL: 쓰는 쪽이 자기 쓰기 포인터와 동기화된 읽기 포인터를 비교한다. 포인터에 한 비트를 더 두어(깊이 8이면 4비트), 한 바퀴 더 돈 상태(위 두 비트만 다름)를 꽉 찬 것으로 본다.
동기화된 포인터는 두세 클럭 늦은 옛 값이다. 그래서 FULL·EMPTY는 실제보다 늦게 풀린다. 즉 비관적이다. 실제로는 빈 자리가 있는데도 꽉 찼다고 할 수는 있지만, 꽉 찼는데 비었다고 하지는 않는다. 그래서 안전하다. 두 클럭의 주파수와 깊이를 바꿔 가며 돌려 보자.
비동기 FIFO
들어오는 속도와 나가는 속도의 차이를 생각해 보자.
답 보기
FIFO는 속도 차이를 잠깐 흡수할 뿐이다. 순 유입률이 400 − 250 = 150 M개/s이므로 16칸은 약 107 ns(쓰기 클럭 약 43번) 만에 차고, 그 뒤로는 FULL이 쓰기를 막아(백프레셔) 평균 쓰기 속도가 250 MHz로 떨어진다. 데이터를 잃지는 않는다. 깊이는 "얼마나 긴 폭주를 흡수해야 하는가"와 "동기화 지연 동안 날아다니는 데이터"로 정한다. 지속적인 속도 차이는 깊이로 해결되지 않는다.
리셋: 모두 같은 출발선에
전원이 들어온 직후 플립플롭들은 아무 값이나 품고 있다. 리셋(Reset)은 모두를 정해진 값으로 되돌린다. 리셋을 거는 순간(인가)은 클럭과 상관없이 즉시 걸려도 된다. 클럭이 아직 안 돌거나 PLL이 잠기기 전에도 회로를 안전한 상태로 묶어 두어야 하기 때문이다. 문제는 리셋을 푸는 순간이다. 리셋 해제가 클럭 에지와 너무 가까우면(recovery·removal 시간 위반) 플립플롭이 준안정에 빠지거나, 칩 반대편의 플립플롭은 한 주기 늦게 풀린다. 그러면 함께 출발해야 할 상태 기계들이 서로 다른 박자에서 출발한다.
그래서 정석은 비동기 인가, 동기 해제(Asynchronous assert, synchronous deassert)다. 리셋 입력을 2단 동기화기 같은 리셋 동기화기에 넣되, 인가는 플립플롭의 비동기 리셋 핀으로 즉시 걸고, 해제만 클럭에 맞춰 두 주기 뒤에 내보낸다.
| 항목 | 대략값 | 비고 |
|---|---|---|
| 스마트폰 기준 수정 | 19.2 / 38.4 MHz | 시계용 32.768 kHz 별도 |
| 수정 주파수 정확도 | 약 ±10~20 ppm | 온도 보상 TCXO는 ±0.5~2 ppm |
| SoC의 PLL 수 | 약 10~30개 | CPU 클러스터·GPU·DDR·디스플레이·카메라·모뎀 등 2023~2025년 |
| CPU용 PLL 출력 지터 (RMS) | 약 0.5~2 ps | LC-VCO는 수백 fs까지 |
| PLL 잠금 시간 | 약 10~100 µs | DVFS 단계 전환 시간에 포함 |
| 클럭 스큐 목표 (블록 안) | 약 10~50 ps | 4 GHz면 주기 250 ps의 수~20% |
| 클럭망 전력 비중 | 동적 전력의 약 30~40% | 게이팅 전 기준, 설계마다 크게 다름 |
| 플립플롭 해소 시정수 τ | 약 5~20 ps | 저전압일수록 커진다 (7~3 nm급) |
핵심 정리
- PLL은 VCO 출력을 N으로 나눠 수정 기준과 비교(PFD)하고, 전하 펌프·루프 필터로 VCO를 고쳐 \(f_{\text{out}}=N f_{\text{ref}}\)에 잠근다. 루프 대역폭은 잠금 속도와 VCO·기준 잡음 사이의 타협이다.
- 클럭 트리는 모든 잎에 같은 시각에 도착하도록 균형을 맞춘다. 스큐는 setup·hold 중 하나를 돕고 다른 하나를 해치며, 지터는 setup 예산에서 빠진다.
- 클럭 게이팅은 래치가 든 ICG 셀로 해야 글리치가 없다. 클럭망은 동적 전력의 큰 몫이라 게이팅 효과가 크다.
- 비동기 경계에서 준안정은 피할 수 없고, 해소 시간을 주어 MTBF를 지수적으로 늘린다. 비트 하나는 2단 동기화기, 여러 비트는 그레이 코드나 비동기 FIFO로 건넌다.
- 리셋은 비동기로 걸고 동기로 푼다. 리셋 동기화기가 모든 플립플롭이 같은 에지에서 출발하게 한다.
확인 퀴즈
Q1. 기준 클럭 38.4 MHz인 정수 분주 PLL로 3.072 GHz를 만들려면 N은?
Q2. 받는 쪽 플립플롭의 클럭이 보내는 쪽보다 30 ps 늦게 도착한다(양의 스큐). 옳은 것은?
Q3. AND 게이트 하나로 클럭을 게이팅하면 생기는 문제와 해결책은?
Q4. 2단 동기화기에서 τ = 20 ps일 때 해소 시간을 200 ps 더 주면 MTBF는 대략 몇 배가 되는가?
Q5. 비동기 FIFO에서 포인터를 그레이 코드로 바꿔 동기화하는 이유는?
Q6. 리셋을 "비동기 인가, 동기 해제"로 하는 이유로 가장 알맞은 것은?