요약

받는 쪽은 자기 시계의 박자(클럭)에 맞춰 비트 한 칸마다 신호가 높은지 낮은지를 읽는다. 가장 단순한 방법(NRZ)은 1이면 높게, 0이면 낮게 그대로 보낸다. 그런데 같은 값이 길게 이어지면 신호가 평평해서, 받는 쪽은 칸이 몇 개 지나갔는지 자기 시계로만 세야 한다. 두 시계가 조금만 달라도 비트를 하나 더 세거나 빠뜨리므로, 받는 쪽이 신호가 바뀌는 순간을 보고 자기 박자를 보내는 쪽에 맞추는 일(클럭 복구)이 꼭 필요하다.

예시로 보기

선 위로 오는 것은 높고 낮은 전압뿐이다. “여기서부터 다음 비트”라는 표시는 없다. 그래서 받는 쪽은 비트 하나가 얼마 동안 이어지는지(비트 폭)를 미리 알고, 칸마다 한가운데서 높이를 잰다. 한가운데서 재는 이유는 그곳이 높이가 바뀌는 칸 경계에서 가장 멀어, 박자가 조금 어긋나도 같은 칸을 읽기 때문이다.

비트 폭은 보내는 속도에서 바로 나온다. 1초에 100만 비트(1 Mbps)를 보내면 비트 하나는 100만분의 1초, 즉 1 µs(마이크로초) 동안 이어진다. 받는 쪽은 첫 비트가 시작된 뒤 0.5 µs, 1.5 µs, 2.5 µs, …에 높이를 잰다. 이 시각들이 칸의 한가운데다.

비트열 하나를 NRZ로 그리면

비트열 0010111101000010을 NRZ로 보낸다. 규칙은 하나다. 1인 칸은 높게, 0인 칸은 낮게 보낸다.

그림

그림을 왼쪽부터 읽는다. 맨 위 줄은 보낸 비트 16개이고, 점선 사이 한 칸이 비트 하나다. 파란 선이 NRZ 신호다. 첫 두 칸은 0이라 낮고, 셋째 칸은 1이라 올라가고, 넷째 칸은 0이라 다시 내려간다.

주황 점은 신호가 바뀌는 순간이다. 신호는 이웃한 두 비트가 서로 다를 때만 그 사이 경계에서 바뀐다. 그래서 칸 경계 15곳 가운데 8곳(시각 2, 3, 4, 8, 9, 10, 14, 15)에만 점이 있다. 받는 쪽 눈에 칸 경계가 “보이는” 곳은 이 8곳뿐이다.

칠한 두 곳은 같은 비트가 네 번 이어진 구간이다. 5~8번째 칸은 1이 네 개라서 4칸 동안 높은 채로 평평하다. 11~14번째 칸은 0이 네 개라서 4칸 동안 낮은 채로 평평하다. 이 구간 안의 칸 경계(시각 5, 6, 7과 11, 12, 13)는 신호에 아무 흔적을 남기지 않는다.

어? 경계가 안 보이면 받는 쪽은 1이 네 개인지 어떻게 아나? 평평했던 시간을 자기 시계로 재서 비트 폭으로 나눈다. 1 Mbps라면 4 µs 동안 높았으니 1이 네 개라고 판단한다. 이 판단은 받는 쪽 시계가 보내는 쪽 시계와 똑같이 갈 때만 맞다.

받는 쪽 시계가 조금 빠르면

받는 쪽 시계가 빠르면 받는 쪽은 비트 폭을 실제보다 좁게 잡는다. 보내는 쪽의 비트 폭을 1로 놓고, 받는 쪽이 비트 폭을 \(15/16\)(0.9375)으로 믿는다고 하자. 16칸마다 1칸꼴, 약 6% 빠른 시계다1.

받는 쪽은 첫 칸의 한가운데라고 믿는 시각 \(\tfrac12 \times \tfrac{15}{16}\)에 처음 읽는다. 그 뒤로는 \(\tfrac{15}{16}\)마다 한 번씩 읽는다. 그래서 \(k\)번째 읽기(\(k = 0, 1, 2, \dots\))의 시각은 \((k + \tfrac12) \times \tfrac{15}{16}\)이다. 아래 표의 읽기 번호는 1부터 세므로 \(k\)보다 1 크다.

세 줄을 직접 계산하면 다음과 같다.

  • 1번째 읽기(\(k = 0\)): \(0.5 \times \tfrac{15}{16} = 0.469\). 0과 1 사이이므로 보낸 쪽 1번째 칸(시각 0~1)을 읽는다. 진짜 한가운데 0.5보다 0.03칸 일찍 읽었다.
  • 8번째 읽기(\(k = 7\)): \(7.5 \times \tfrac{15}{16} = 7.031\). 7과 8 사이이므로 8번째 칸(시각 7~8)을 읽는다. 진짜 한가운데 7.5보다 0.47칸이나 일찍이지만, 아직 8번째 칸 안이다.
  • 9번째 읽기(\(k = 8\)): \(8.5 \times \tfrac{15}{16} = 7.969\). 여전히 7과 8 사이다. 9번째 칸(시각 8~9)을 읽어야 하는데, 8번째 칸을 한 번 더 읽는다.

나머지 줄도 같은 식으로 계산한 결과다.

읽기 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
읽는 시각 (보낸 칸 단위) 0.47 1.41 2.34 3.28 4.22 5.16 6.09 7.03 7.97 8.91 9.84 10.8 11.7 12.7 13.6 14.5
읽힌 보낸 칸 1 2 3 4 5 6 7 8 8 9 10 11 12 13 14 15
읽은 비트 0 0 1 0 1 1 1 1 1 0 1 0 0 0 0 1

왜 하필 9번째 읽기에서 틀리나? 받는 쪽은 읽을 때마다 칸 한가운데보다 \(1/16\)칸씩 더 일찍 읽는다. 이 앞당김은 \(k\)번째 읽기에서 \((k + \tfrac12)/16\)칸이다. 칸의 한가운데에서 그 칸의 시작점까지는 반 칸이다. 그래서 앞당김이 반 칸 이하이면 아직 제 칸 안이고, 반 칸을 넘으면 앞 칸으로 넘어간다. 8번째 읽기의 앞당김은 \(7.5/16 = 0.47\)칸이라 반 칸 안이다. 9번째 읽기는 \(8.5/16 = 0.53\)칸이라 반 칸을 처음 넘는다1.

그림

그림의 위쪽은 같은 NRZ 신호에 받는 쪽이 읽는 순간(주황 세로선)을 겹친 것이다. 세로선은 처음에는 칸 한가운데 가까이 있다가, 오른쪽으로 갈수록 칸의 왼쪽 경계 쪽으로 밀린다. 칠한 칸이 8번째 칸이다. 굵은 세로선 두 개(시각 7.03과 7.97)가 모두 이 칸 안에 떨어져서, 이 칸의 1을 두 번 읽는다.

아래쪽 막대는 읽기마다의 앞당김이고, 바로 위의 세로선과 같은 자리에 있다. 막대는 한 번에 \(1/16\)(0.0625)칸씩 자란다. 처음 8개(파랑)는 점선(반 칸) 아래이고, 9번째부터(주황)는 점선 위다. 점선 위의 읽기는 모두 한 칸 앞을 읽는다. 그래서 9번째 읽기부터는 읽은 비트가 보낸 비트보다 한 칸씩 늦다. 마지막 16번째 읽기(시각 14.53)는 15번째 칸을 읽고, 16번째 칸의 0은 아무도 읽지 않는다. 받는 쪽은 0010111110100001을 받았다고 믿는다2.

신호가 바뀔 때마다 다시 맞추면

중복은 1이 네 개 이어진 5~8번째 칸에서 생겼다. 신호가 평평하니 받는 쪽은 “1이 네 개인지 다섯 개인지”를 신호에서 알아낼 단서가 없다.

반대로 신호가 바뀌는 순간에는 단서가 있다. NRZ에서 신호가 바뀌는 곳은 언제나 칸 경계다. 그래서 받는 쪽은 신호가 바뀌는 순간 “지금이 칸 경계”라고 자기 칸 경계를 다시 잡을 수 있다. 다시 잡으면 그동안 쌓인 앞당김이 0으로 돌아간다. 이렇게 신호의 변화를 보고 박자를 맞추는 일이 클럭 복구다.

같은 15/16 시계로 다시 맞추면 이렇게 된다. 시각 4에서 신호가 올라간다. 받는 쪽은 4를 칸 경계로 잡고, 거기서부터 \(j\)번째 읽기(\(j = 0, 1, 2, \dots\))를 \(4 + (j + \tfrac12) \times \tfrac{15}{16}\)에 한다. 읽는 시각은 4.47, 5.41, 6.34, 7.28이고, 각각 5, 6, 7, 8번째 칸 안이다. 다음 읽기는 \(4 + 4.5 \times \tfrac{15}{16} = 8.22\)일 차례인데, 그 전인 시각 8에서 신호가 내려간다. 받는 쪽은 8을 새 칸 경계로 잡고 8.47에 9번째 칸을 읽는다. 1 네 개를 정확히 네 번 읽었다. 이 구간에서 앞당김이 가장 컸던 네 번째 읽기도 \(3.5/16 = 0.22\)칸으로, 반 칸에 한참 못 미친다.

그림

그림의 초록 점이 받는 쪽이 칸 경계를 다시 잡는 순간이다. 위쪽의 주황 세로선은 초록 점을 지날 때마다 칸 한가운데 근처로 돌아온다. 아래쪽 막대는 톱니 모양이다. 초록 선에서 0.03칸으로 떨어졌다가, 평평한 구간 안에서만 조금씩 자란다. 가장 큰 막대(시각 7.28과 13.28)도 0.22칸이라 점선(반 칸)에 닿지 않는다. 그래서 16번 모두 맞게 읽는다. 시계가 10% 틀려도 이 비트열은 그대로 읽힌다12.

어? 그럼 다시 맞추기만 하면 언제나 괜찮나? 아니다. 다시 맞추기는 평평한 구간 안에서는 아무 도움이 안 된다. 15/16 시계로는 같은 높이가 7칸까지 이어질 때만 맞게 읽는다. 8칸이 이어지면 그 안에서 앞당김이 반 칸을 넘어 한 칸을 또 두 번 읽는다. 그래서 클럭 복구가 되려면 신호가 너무 오래 평평하지 않아야 한다. NRZ는 이것을 보장하지 못한다. 데이터에 0이나 1이 얼마나 길게 이어질지 보내는 쪽도 미리 정할 수 없기 때문이다.

flowchart TD
  A["다음 칸의 한가운데까지 기다림"] --> B["신호 높이를 읽음"]
  B --> C{"그 사이 신호가 바뀌었나"}
  C -->|"예"| D["칸 경계를 바뀐 순간으로 다시 맞춤"]
  C -->|"아니오"| E["자기 시계로만 칸을 셈 - 앞당김이 쌓임"]
  D --> A
  E --> A

신호가 바뀔 때마다 ‘다시 맞춤’ 상자를 지나며 쌓인 오차가 0으로 돌아간다. 같은 높이가 길게 이어지면 ‘자기 시계로만’ 길만 되풀이되고, 앞당김이 반 칸을 넘는 순간 비트를 잘못 읽는다.

검증: 같은 클럭이면 그대로, 15/16이면 9번째 읽기에서 중복, 빠른 시계는 비트를 건너뛰지 않음(w = 0.01~0.99), 다시 맞추기를 하면 w = 0.9~1.1에서 정확, 1% 빠르면 51번째 읽기에서 첫 오류 — 40_nrz-clock-recovery_verify.py

정의

인코딩은 디지털 데이터를 디지털 신호로 바꾸는 일이다. 변조의 한 종류이고, 주로 유선 링크에서 쓴다. 노드의 네트워크 어댑터(NIC) 안에서 한다. 보내는 쪽이 인코딩하고, 받는 쪽이 신호를 다시 비트로 되돌린다(디코딩).

NRZ(Non-Return to Zero)는 1을 높은 신호, 0을 낮은 신호로 보낸다. 노드 안에서 데이터를 나타내는 방식과 같아서 따로 인코딩할 것이 없다. 이름은 “비트 칸 안에서 0 V로 돌아가지 않는다”는 뜻이다. 1이 이어지면 신호가 높은 채로 계속 머문다3.

NRZ는 1이나 0이 이어질 때 문제가 생긴다.

  1. 낮은 신호(0)가 이어지면 받는 쪽은 신호가 아예 없다고 오해할 수 있다. 1 Mbps 링크에서 0이 1,000개 이어지면 1 ms 동안 선이 낮은 채로 조용하다. 받는 쪽에서 보면 선이 끊겨 아무것도 오지 않는 것과 똑같다.
  2. 높은 신호(1)가 이어지면 전류가 계속 흐르고, 높고 낮음을 가르는 기준 전압이 흔들린다(기저 전압의 혼돈). 받는 쪽은 최근 받은 신호의 평균을 기준으로 삼는데, 1이 길게 오면 평균이 올라가 기준이 따라 올라가기 때문이다3. 기준이 높은 쪽으로 다가가면, 다음에 오는 높은 신호도 기준과 가까워져 1인지 0인지 헷갈린다.
  3. 클럭 복구를 할 수 없다. 보내는 쪽과 받는 쪽의 클럭이 맞지 않으면 비트를 잘못 읽는다. 예: 받는 쪽 클럭이 빠르면 비트 폭이 줄어들어 비트 오류가 난다.

그래서 클럭 복구, 즉 받는 쪽이 보내는 쪽의 클럭에 자기 클럭을 맞추는 일이 반드시 필요하다.

기호로 쓰면 다음과 같다1. 보내는 쪽의 비트 폭을 1로 놓고, 받는 쪽이 믿는 비트 폭을 \(w\)(1보다 작으면 받는 쪽 시계가 빠르다)라 한다. 받는 쪽은 \(k\)번째 칸(\(k = 0, 1, 2, \dots\))을 시각 \((k + \tfrac{1}{2})w\)에 읽는다. 그 시각에 지나가는 것은 보낸 쪽의 \(i_k\)번째 칸이다(\(\lfloor x \rfloor\)는 “x의 바닥”이라 읽고, \(x\) 이하의 가장 큰 정수다. 예: \(\lfloor 7.97 \rfloor = 7\)).

\[i_k = \left\lfloor \left(k + \tfrac{1}{2}\right) w \right\rfloor\]

보낸 쪽 칸 \(i\)는 시각 \(i\)부터 \(i + 1\) 직전까지 이어진다. 그래서 읽는 시각의 정수 부분이 곧 칸 번호다. 칸 번호도 0부터 센다.

예를 들어 \(w = \tfrac{15}{16}\), \(k = 7\)이면 \(7.5 \times \tfrac{15}{16} = 7.03\)이라 \(i_7 = 7\)이다. \(k = 8\)이면 \(8.5 \times \tfrac{15}{16} = 7.97\)이라 \(i_8 = 7\)이다. 두 읽기가 같은 칸 7, 즉 8번째 칸을 가리킨다. ‘예시로 보기’ 표에서 8번째와 9번째 읽기가 둘 다 8번째 칸을 읽은 것과 같다.

받는 쪽 시계가 \(\varepsilon\)(“엡실론”, 시계가 빠른 비율)만큼 빠르면 \(w = 1 - \varepsilon\)(\(0 < \varepsilon < 1\))이다. 읽는 시각을 풀어 쓰면 다음과 같다.

\[\left(k + \tfrac12\right)w = \left(k + \tfrac12\right) - \left(k + \tfrac12\right)\varepsilon\]

앞의 \((k + \tfrac12)\)는 칸 \(k\)의 진짜 한가운데이고, 뒤의 \((k + \tfrac12)\varepsilon\)은 그때까지 쌓인 앞당김이다. 칸 \(k\)는 한가운데에서 반 칸 앞인 시각 \(k\)에서 시작한다. 그래서 앞당김이 반 칸을 넘으면 읽는 시각이 칸 \(k\)를 벗어나 앞 칸으로 들어간다. 처음으로 같은 칸을 두 번 읽는 것은 다음 조건을 처음 만족하는 \(k\)다.

\[\left(k + \tfrac{1}{2}\right)\varepsilon > \tfrac{1}{2}, \qquad \text{즉 } k > \frac{1}{2\varepsilon} - \frac{1}{2}\]

오른쪽 식은 왼쪽 식의 양변을 \(\varepsilon\)으로 나눠 \(k + \tfrac12 > \tfrac{1}{2\varepsilon}\)을 얻은 뒤, 양변에서 \(\tfrac12\)을 뺀 것이다. 말로 하면, 칸마다 \(\varepsilon\)씩 쌓이는 앞당김이 반 칸을 넘는 순간 첫 오류가 난다.

\(\varepsilon\)에 세 가지 값을 넣으면 다음과 같다.

  • \(\varepsilon = \tfrac{1}{16}\)(약 6%)이면 \(\tfrac{1}{2\varepsilon} = 8\)이라 \(k > 7.5\), 즉 \(k = 8\)(9번째 읽기)이다. 표의 결과와 같다.
  • \(\varepsilon = \tfrac{1}{10}\)(10%)이면 \(\tfrac{1}{2\varepsilon} = 5\)라 \(k > 4.5\), 즉 \(k = 5\)(6번째 읽기)다. 시계가 더 틀릴수록 첫 오류가 일찍 온다.
  • \(\varepsilon = 1\%\)이면 \(\tfrac{1}{2\varepsilon} = 50\)이라 \(k > 49.5\), 즉 \(k = 50\)(51번째 읽기)에서 50번째 칸을 한 번 더 읽는다. 1 Mbps 링크라면 신호가 바뀌지 않을 때 약 0.05 ms 만에 첫 오류가 난다.

증명

\(w < 1\)일 때 받는 쪽은 칸을 건너뛰지 않고, 앞당김이 반 칸을 넘을 때 처음 같은 칸을 다시 읽는다는 것을 보인다. 읽는 시각의 간격이 1보다 짧다는 것만 쓴다.

증명 펼치기
  1. 칸 번호는 0 또는 1씩 는다. 이웃한 두 읽기 시각의 차이는 \(w\)이고 \(0 < w < 1\)이다. 바닥 함수는 입력이 1보다 적게 늘면 출력이 0 또는 1만 는다. 따라서 \(i_{k} - i_{k-1} \in \{0, 1\}\)이다. — 바닥 함수의 성질
  2. 앞당김이 반 칸 이하이면 제자리다. \(w = 1 - \varepsilon\)이면 \((k + \tfrac12)w = k + \tfrac12 - (k + \tfrac12)\varepsilon\)이다. \((k + \tfrac12)\varepsilon \le \tfrac12\)이면 이 값은 \([k, k + \tfrac12]\) 안에 있으므로 \(i_k = k\)다. — 대수 정리
  3. 반 칸을 넘는 첫 순간 중복이 생긴다. 조건을 처음 만족하는 \(k\)에서 \((k + \tfrac12)\varepsilon > \tfrac12\)이고, 2단계에 따라 \(i_{k-1} = k - 1\)이다. \(\varepsilon\)이 작아 \((k + \tfrac12)\varepsilon < \tfrac32\)이면 \((k + \tfrac12)w \in (k - 1, k)\)이므로 \(i_k = k - 1 = i_{k-1}\)이다. — 2단계와 같은 계산 ∎

1단계 때문에, 일정하게 빠른 시계는 비트를 더 읽을 수만 있고 빠뜨릴 수는 없다. 비트를 빠뜨리는 것은 받는 쪽 시계가 느린 경우(\(w > 1\))다.

스스로 설명해 보기

  1. 1단계에서 \(w < 1\)이 필요한 이유
    근거

    읽는 간격이 1보다 짧아야 두 읽기 사이에 칸 경계가 많아야 하나만 지나간다. \(w > 1\)이면 경계를 두 개 넘어 칸 하나를 건너뛸 수 있다.

  2. 2단계의 “반 칸”
    근거

    받는 쪽은 칸의 한가운데(시작점에서 반 칸)에서 읽는다. 앞당김이 반 칸이면 읽는 시각이 칸의 시작점에 닿는다. 그보다 더 앞당겨지면 앞 칸으로 넘어간다.

  3. 다시 맞추기가 효과 있는 이유
    근거

    앞당김은 마지막으로 박자를 맞춘 순간부터 쌓인다. 신호가 바뀔 때마다 0으로 되돌리면, 같은 높이가 이어지는 길이 \(L\)에서 쌓이는 앞당김은 약 \(L\varepsilon\)뿐이다. \(L\varepsilon < \tfrac12\)이면 틀리지 않는다.

    • 이 논증의 핵심 아이디어는?
답

작은 오차가 칸마다 쌓이고, 쌓인 오차가 허용 범위(반 칸)를 넘는 순간 틀린다. 그래서 “얼마나 오래 단서 없이 버티는가”가 오류를 정한다.

  • 이 방법을 쓸 수 있는 다른 상황은?
    답

    시계 두 개를 따로 돌리는 모든 일. 예: 컴퓨터 시계가 하루에 몇 초씩 틀어져 인터넷 시간 서버로 주기적으로 맞추는 것, 숫자를 반올림해 더할 때 오차가 쌓이는 것.

예제

클럭 복구가 꼭 필요한 예

  1. NRZ로 0이 길게 이어지는 데이터(예: 0으로 채운 파일)를 보낼 때. 신호가 계속 낮다.
  2. NRZ로 1이 길게 이어지는 데이터를 보낼 때. 신호가 계속 높다.
  3. 보내는 쪽과 받는 쪽이 각자 시계를 가진 모든 링크. 두 시계는 물리적으로 완전히 같을 수 없다.

따로 클럭을 맞출 필요가 없는 예

  1. 보내는 쪽이 클럭을 별도의 선으로 함께 보낼 때. 받는 쪽은 그 선의 박자로 읽는다. 칩 사이 짧은 연결(SPI의 클럭 선)이 이렇다4.
  2. 한 번에 보내는 비트가 아주 적을 때. 시계 오차가 1%라도 약 50비트까지는 틀리지 않는다. 시리얼 포트(UART)는 10비트 남짓마다 시작 표시로 박자를 새로 맞춘다4. 1% 빠른 시계로 10번 읽으면 마지막 읽기의 앞당김은 \((9 + \tfrac12) \times 0.01 = 0.095\)칸이다. 반 칸의 5분의 1도 안 되니, 박자를 다시 맞출 때까지 넉넉히 버틴다.

연결

자주 하는 오해

“시계를 아주 정확하게 만들면 클럭 복구는 필요 없다”

아니다. 오차를 줄이면 첫 오류가 늦어질 뿐 사라지지 않는다. 시계 오차가 백만분의 1이어도 약 50만 비트 뒤에 첫 오류가 난다. 1 Gbps 링크에서는 0.5 ms 만이다1. 그럴듯해 보이는 이유는 오차 1%나 백만분의 1이 작게 느껴져서다. 하지만 비트는 1초에 수억 개씩 지나가므로 작은 오차가 금방 반 칸만큼 쌓인다. 그래서 받는 쪽은 신호의 변화에서 계속 박자를 다시 맞춰야 한다.

확인 문제

C1 NRZ에서 1이나 0이 길게 이어질 때 생기는 문제 세 가지를 쓰라.

답: ① 0이 이어지면 신호가 없는 것으로 오해할 수 있다. ② 1이 이어지면 전류가 계속 흘러 높고 낮음을 가르는 기준 전압이 흔들린다. ③ 신호가 바뀌지 않아 클럭 복구를 할 수 없고, 두 시계가 조금만 달라도 비트를 잘못 읽는다.

C2 받는 쪽은 왜 비트 칸의 한가운데서 높이를 재는가? 그리고 같은 높이가 길게 이어지는 것이 왜 문제인가?

답: 한가운데는 높이가 바뀌는 칸 경계에서 가장 멀어서, 박자가 반 칸 가까이 어긋나도 같은 칸을 읽는다. 같은 높이가 길게 이어지면 받는 쪽은 박자를 다시 맞출 단서(신호가 바뀌는 순간)가 없어, 시계 오차가 칸마다 쌓인다. 쌓인 오차가 반 칸을 넘으면 비트를 하나 더 읽거나 빠뜨린다.
흔한 오답: “신호가 약해져서”. 문제는 신호의 세기가 아니라 박자다.

C3 받는 쪽 시계가 보내는 쪽보다 1% 빠르다. 신호가 한 번도 바뀌지 않는다면, 받는 쪽은 몇 번째 읽기에서 처음으로 같은 칸을 두 번 읽는가?

답: 51번째 읽기(\(k = 50\)). 앞당김 \((k + \tfrac12) \times 0.01\)이 처음 \(\tfrac12\)을 넘는 \(k\)는 \(k > 49.5\)에서 \(k = 50\)이다. 이때 50번째 칸을 한 번 더 읽는다1.

C4 0010111101000010을 NRZ로 보냈다. 받는 쪽이 비트 폭을 15/16으로 잡고 칸 한가운데서 16번 읽으면 무엇을 받는가?

답: 0010111110100001. 읽는 시각이 매번 1/16씩 앞당겨져 9번째 읽기(시각 7.97)에서 8번째 칸의 1을 한 번 더 읽는다. 그 뒤는 한 칸씩 밀리고, 마지막 칸의 0은 읽지 못한다1.

C5 받는 쪽 시계가 일정하게 빠를 때, 받은 비트열에서 어떤 비트가 빠질 수는 없다. 그 이유를 대라.

답: 읽는 간격 \(w\)가 1보다 짧아서, 이웃한 두 읽기 사이에 칸 경계는 많아야 하나 지나간다. 그래서 읽는 칸 번호는 0 또는 1씩만 늘고, 건너뛰는 칸이 없다. 비트가 빠지려면 칸 번호가 2 이상 뛰어야 하고, 그것은 시계가 느릴 때(\(w > 1\)) 생긴다.

  1. 검증 코드로 확인했다. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  2. 40_nrz-clock-recovery_plot.py로 그렸고, 그림 1의 신호가 바뀌는 순간 8곳(시각 2, 3, 4, 8, 9, 10, 14, 15)과 4칸짜리 평평한 구간 두 곳, 그림 2의 읽는 시각 \((k + \tfrac12) \times \tfrac{15}{16}\)과 앞당김 0.47·0.53칸, 9번째 읽기 시각 7.97(8번째 칸), 받은 열 0010111110100001, 식 \(k > 1/(2\varepsilon) - 1/2\)이 \(\varepsilon = 1/16\)에서 주는 첫 중복 \(k = 8\), 그림 3의 다시 맞추기 결과(16번 모두 맞음, 가장 큰 앞당김 \(3.5/16 \approx 0.22\)칸)를 같은 코드로 확인했다. ↩ ↩2

  3. NRZ 이름의 뜻과 기준 전압이 흔들리는 원리(기저선 변동, baseline wander)는 Peterson & Davie, Computer Networks: A Systems Approach, 2.2절의 설명이다. ↩ ↩2

  4. SPI는 클럭 선(SCLK)을 데이터 선과 함께 쓰고, UART는 프레임마다 시작 비트의 하강 모서리에서 박자를 다시 맞춘다. ↩ ↩2