01signal.com

8b/10b 인코딩, 64b/66b, 128b/130b 등에 대한 간단한 소개

이 페이지는 MGT(Multi-Gigabit Transceiver)를 소개하는 페이지 시리즈 중 세 번째입니다.

참고: Xillyp2p용 물리 링크를 구성하는 과정에서 이 페이지를 읽고 있다면, 이 페이지는 해당 작업과 관련이 없습니다. 이 경우에는 모든 인코딩 기능을 꺼야 합니다. Xillyp2p IP 코어(IP core)가 모든 기능을 내부적으로 구현하고, 사용자에게 애플리케이션 데이터를 위한 종단 간(end-to-end) 스트림을 제공하기 때문입니다.

소개

애플리케이션 로직의 데이터 스트림이 그대로 물리 채널로 전송되는 경우는 거의 없습니다. 그렇게 하면 앞서 설명한 이유 때문에 MGT가 오작동할 가능성이 매우 높습니다. 거의 모든 애플리케이션에서 MGT 또는 애플리케이션 로직은 물리 채널이 제대로 동작하도록 데이터 스트림에 인코딩을 적용합니다. 이 인코딩은 송신기와 수신기 사이의 동기화를 돕는 역할도 합니다.

하지만 예외도 있습니다. 이 완전한 설계 예제에서는 MGT를 인코딩 기능 없이 단순한 SERDES로 사용합니다. 애플리케이션 로직이 스크램블러와 그 밖에 필요한 기능들을 직접 구현하기 때문에 가능한 일입니다.

앞 페이지의 프로토콜 목록은 이러한 인코딩 방식들과 FPGA 사이에서 사용되는 프로토콜들을 연결해 줍니다.

8b/10b 인코딩

8b/10b 인코딩은 PCIe의 일부 버전, Gigabit Ethernet, SATA, DisplayPort, SuperSpeed USB 등 여러 프로토콜에서 사용됩니다. 모든 FPGA MGT에는 8b/10b 인코더와 디코더가 내장되어 있습니다. 물론 이 인코더는 로직 패브릭으로도 구현할 수 있지만, 그렇게 하지 않아도 된다는 뜻입니다.

이 인코딩은 각 바이트(8비트)를 10비트로 구성된 워드로 변환합니다. 이 변환의 주된 목적은 평균적으로 '0'과 '1'의 개수가 같은 비트 시퀀스를 만드는 것입니다. 즉, 인코딩된 데이터 스트림이 DC 밸런스를 유지하게 됩니다. 또 다른 장점은 데이터 스트림에 '0'과 '1' 사이의 전이가 충분히 자주 나타나도록 보장하여 CDR(Clock Data Recovery) 메커니즘이 제대로 동작할 수 있게 한다는 점입니다.

다만 8b/10b 인코딩은 데이터 스트림을 무작위화하지 않는다는 점에 유의하십시오. 특히 이퀄라이저(equalizer)를 사용해야 하고, 그 이퀄라이저가 데이터 스트림의 통계적 무작위성을 요구하는 경우라면 8b/10b 인코딩만으로는 충분하지 않습니다.

DC 밸런스 목표를 달성하기 위해 일부 8비트 워드는 두 개의 후보 중 하나로 인코딩될 수 있습니다. 예를 들어 8비트 워드 0x20(00100000, D0.1로 표기)은 1001111001 또는 0110001001로 인코딩될 수 있습니다. 두 대안 모두 0x20으로 디코딩됩니다. 첫 번째 대안에는 '0' 비트가 4개, '1' 비트가 6개 들어 있습니다. 두 번째 대안에는 '0' 비트가 6개, '1' 비트가 4개 들어 있습니다. 이것이 8b/10b 인코딩의 핵심 아이디어입니다. 인코더에는 두 가지 대안, 즉 '0'이 '1'보다 많은 대안과 그 반대인 대안이 있는 것입니다.

인코더는 이 기능을 이용하여 장기적으로 '0'과 '1' 사이의 균형을 유지합니다. 지금까지 데이터 스트림에 '0'이 너무 많았는지 '1'이 너무 많았는지를 기억해 두는 것입니다. 이 불균형을 러닝 디스패리티(Running Disparity)라고 합니다. 인코더는 이 불균형을 줄이는 쪽으로 10비트 워드를 선택합니다.

모든 8비트 워드에 10비트 후보가 두 개씩 있는 것은 아닙니다. 예를 들어 8비트 워드 0x23(00100011, D3.1로 표기)은 항상 1100011001로 인코딩됩니다. 이 인코딩된 워드는 '0'과 '1'의 개수가 같으므로 러닝 디스패리티에 영향을 주지 않습니다.

8b/10b 인코딩은 1983년에 처음 발표되었으며, 대략 2010년까지 도입된 프로토콜들에서 매우 널리 사용되었습니다. 최근에 발표된 프로토콜에서는 덜 사용됩니다. 주된 이유는 스크램블러(scrambler)가 프로토콜의 일부로 자주 포함되기 때문입니다. 스크램블러를 사용하면 데이터 스트림의 DC 밸런스가 보장되므로 8b/10b 인코딩이 그런 용도로는 더 이상 필요하지 않습니다. 스크램블러는 또한 '0'과 '1' 사이의 전이가 충분히 자주 일어나도록 해 줍니다. 반면 8b/10b 인코딩은 물리 채널로 전송해야 할 비트를 25% 더 늘립니다. 이 추가 비트는 실제 유용한 데이터를 전송하는 데 쓸 수도 있었던 것입니다.

그렇지만 스크램블러를 사용하는 성공적인 프로토콜 중에도 8b/10b를 함께 사용하는 경우가 있습니다. 예를 들어 모든 PCIe 버전은 스크램블러를 요구하지만, 3.0 미만의 PCIe 버전에서는 8b/10b 인코딩도 사용됩니다. 따라서 8b/10b 인코딩에는 분명 다른 장점도 있습니다. 이제 다음 주제인 K-심볼(K-symbol)로 넘어가겠습니다.

K-심볼

8b/10b 인코더가 인코딩하는 8비트마다 10비트를 생성한다는 것은, 인코딩된 워드가 원래 워드의 256가지와 비교해 1024가지 조합을 가질 수 있다는 뜻입니다. 원래 워드마다 인코딩 후보가 두 개씩 있다고 가정해도 512가지를 차지합니다. 앞서 언급했듯이 어떤 8비트 워드는 10비트 워드 후보가 하나뿐이므로 실제 인코딩된 워드의 가능성은 512가지보다 적습니다. 따라서 10비트 워드 중 적어도 512가지는 대응하는 8비트 워드가 없습니다.

따라서 8b/10b 인코딩은 규정에 없는 10비트 워드를 감지함으로써 물리 링크의 비트 오류를 검출할 수 있습니다. FPGA MGT에는 규정에 없는 10비트 워드가 감지되었을 때 애플리케이션 로직에 알려 주는 출력 포트가 있습니다. 하지만 이 오류 검출 메커니즘은 모든 오류를 잡아내지는 못하므로 가치가 높지는 않습니다.

8b/10b 인코딩에서 정말 가치 있는 기능은 K-심볼입니다. K-심볼은 8비트 워드 대신 인코딩되어 전송됩니다. 디코더는 일반 데이터 워드와 K-심볼을 구분할 수 있으며, K-심볼이 도착했을 때 애플리케이션 로직에 알려 주는 방법은 항상 마련되어 있습니다.

그 결과 8b/10b 인코딩을 쓰면 일반 데이터와 혼동되지 않는 방식으로 데이터 채널에 추가 정보를 보낼 수 있습니다. 프로토콜은 이 기능을 이용하여 수신기가 송신기의 데이터 스트림에 동기화되도록 돕는 경우가 많습니다.

K-심볼의 의미는 프로토콜에 따라 다릅니다. 그러나 많은 프로토콜이 동일한 의미로 사용하는 K-심볼이 하나 있습니다. K28.5는 흔히 컴마(Comma, COM)라고 불리며 데이터 스트림을 동기화하는 데 사용됩니다. 자세한 내용은 아래에서 설명합니다.

FPGA MGT에서 8b/10b를 활성화하면 애플리케이션 로직과의 인터페이스에는 데이터 바이트마다 별도의 신호선이 있습니다. 이 신호선은 해당 데이터가 일반 데이터 바이트인지 K-심볼인지를 나타냅니다. 즉, 송신 인터페이스에서는 전송할 각 워드를 일반 데이터로 보낼지 K-심볼로 보낼지 선택할 수 있습니다. 다만 어떤 워드를 K-심볼로 표시할 때 사용할 수 있는 8비트 워드는 다음 목록으로 제한됩니다.

바이트 값(16진수) K-심볼
1C K28.0
3C K28.1
5C K28.2
7C K28.3
9C K28.4
BC K28.5
DC K28.6
FC K28.7
F7 K23.7
FB K27.7
FD K29.7
FE K30.7

MGT 수신기의 경우도 마찬가지로, 애플리케이션 로직과의 인터페이스에서 수신된 바이트마다 별도의 신호선이 있습니다. 각 신호선의 값은 해당 바이트를 일반 데이터로 해석해야 하는지 K-심볼로 해석해야 하는지를 나타냅니다. 수신기에는 또한 K28.5를 특별한 방식으로 처리하는 기능이 있습니다. K28.5는 컴마 심볼(Comma Symbol, COM)이라고도 하며, 다음 절에서 설명합니다.

컴마 심볼(K28.5)

K28.5의 10비트 표현은 0011111010 또는 1100000101입니다. 이 워드는 특히 유용한데, 이 비트 시퀀스는 K28.5를 전송한 경우에만 물리 채널에 나타날 수 있기 때문입니다. 수신기는 K28.5를 검출하기 위해 송신기와 동기화되어 있을 필요가 없습니다. 마지막으로 수신된 10비트가 이 두 워드 중 하나와 일치하기만 하면 됩니다.

이 때문에 K28.5는 수신기를 동기화하는 훌륭한 도구입니다. K28.5가 감지되면 다른 10비트 워드들의 경계도 알 수 있습니다.

FPGA MGT에는 K28.5 심볼이 도착하면 도착하는 데이터 스트림을 자동으로 정렬하는 기능이 있습니다. 또한 더 큰 경계에 맞추어 정렬하도록 요청할 수도 있습니다. 예를 들어 MGT를 구성해서 도착한 K28.5가 32비트 워드의 시작 부분에 오도록 정렬할 수 있습니다.

수신기 정렬 외에도, 동기화가 필요한 다른 기능 블록을 정렬하는 데 K28.5를 사용할 수 있습니다. 예를 들어 프로토콜이 K28.5 심볼이 도착하면 스크램블러를 리셋하도록 요구할 수도 있습니다.

이런 가능성 때문에 프로토콜들은 수신기 동기화 목적으로 K28.5를 주기적으로 전송하도록 요구하는 경우가 많습니다. 핸드셰이크로 연결을 설정하는 프로토콜은 링크 설정 과정의 일부로 K28.5를 사용하기도 합니다. 어느 쪽이든, K28.5 심볼은 프로토콜 설계를 충분히 단순화해 주어서, 물리 채널에 추가로 전송되는 25%의 비트 비용을 정당화합니다.

스킵 심볼(K28.0 및 K28.1)

대부분의 실제 상황에서는 송신기와 수신기의 클록 주파수에 차이가 있습니다. 이로 인해 문제가 생길 수 있습니다. MGT와 애플리케이션 로직 사이의 인터페이스는 흔히 수신기 자신의 로컬 클록과 동기화되어 있습니다. 따라서 데이터는 송신기 클록에 맞춰 도착하지만, 애플리케이션 로직에는 수신기 클록에 맞춰 전달됩니다.

다시 말해, MGT가 수신하는 데이터는 상대편이 정한 속도로 도착하지만, 데이터가 소비되는 속도는 로컬 클록이 결정합니다.

송신기 클록 주파수가 더 높으면 애플리케이션 로직이 MGT에서 데이터를 너무 느리게 가져가게 됩니다. 남는 데이터는 결국 쌓이게 되고 MGT 내부 어딘가에서 오버플로(overflow)가 발생합니다. 반대로 송신기 클록 주파수가 더 낮으면 애플리케이션 로직은 데이터가 도착하는 속도보다 더 빨리 데이터를 가져오려고 합니다. 이것 역시 문제입니다.

이 문제에 대한 간단한 해결책은 '스킵 심볼(skip symbol)'을 추가하는 것입니다. 예를 들어 SuperSpeed USB 프로토콜은 'SKP Ordered Set'을 두 개의 연속된 K28.1 심볼로 정의합니다. 이 프로토콜은 일반 데이터 워드 354개마다 이 K28.1 심볼 두 개를 한 번씩 전송하도록 요구합니다. 수신 MGT는 이 K28.1 심볼을 애플리케이션 로직에 전달하는 대신 버릴 수 있습니다. 이렇게 하면 송신기 클록이 수신기 클록보다 빠를 때 발생하는 데이터 잉여 문제가 해결됩니다. 클록 주파수 차이 때문에 수신 MGT에 데이터가 쌓이기 시작하면, MGT는 도착하는 K28.1 심볼을 건너뛰기 때문입니다.

이 메커니즘을 사용하면 송신기는 수신측 애플리케이션 로직이 354개의 워드만 가져가는 같은 시간 동안 356개의 워드를 전송할 수 있습니다. 356 / 354 ≈ 1.00565이므로, 이 메커니즘은 두 클록 사이의 주파수 차이를 최대 약 0.565%까지 흡수할 수 있습니다. 물론 이는 프로토콜 사양이 허용하는 범위보다 큰 값입니다.

수신 MGT는 또한 기존의 'SKP Ordered Set'에 K28.1 심볼을 추가할 수 있습니다. 이것은 송신기 클록이 더 느릴 때 도움이 됩니다. 송신기 클록이 더 느리면 수신측 애플리케이션 로직이 데이터가 도착하는 속도보다 더 빨리 데이터를 가져오려고 하기 때문입니다. 따라서 MGT는 누락된 데이터 자리를 K28.1 심볼로 채울 수 있습니다. 애플리케이션 로직은 어차피 모든 K28.1 심볼을 무시해야 하기 때문입니다.

PCIe 프로토콜도 스킵 심볼을 비슷한 방식으로 사용합니다. PCIe의 SKP Ordered Set 형식은 다릅니다. K-심볼 네 개, 즉 먼저 K28.5(컴마) 한 개, 그 다음에 K28.0 심볼 세 개로 구성됩니다. 그래도 스킵 심볼을 사용하는 원리는 동일합니다.

USB 프로토콜과 PCIe 프로토콜은 모두 오더드 셋과 관련하여 SKP라는 약어를 사용합니다. SuperSpeed USB 프로토콜에서 SKP는 K28.1을 의미하지만, PCIe에서는 K28.0을 의미한다는 점에 유의하십시오. 혼동이 생길 여지가 있습니다.

64b/66b 인코딩

앞서 언급했듯이 8b/10b 인코딩은 물리 채널을 비효율적으로 사용합니다. DC 밸런스 유지와 '0'과 '1' 사이의 전이 보장이라는 주된 목적은 스크램블러를 사용할 때는 필요하지 않습니다. 그래서 최근의 프로토콜들은 64b/66b 인코딩이나 그와 유사한 방식을 사용합니다. 다만 64b/66b가 실제로는 인코딩 방식은 아니라는 점을 알아 두는 것이 중요합니다. 그것은 오히려 데이터 스트림과 제어 워드를 구성하는 방법입니다. 데이터가 다른 표현으로 인코딩되지는 않습니다. 다만 데이터가 세그먼트로 나뉘고, 동기화와 제어 정보 전송을 가능하게 하기 위해 추가 비트가 삽입될 뿐입니다.

K-심볼은 8b/10b 인코딩에만 있는 개념이며, 다른 코딩 형식에서는 사용할 수 없습니다.

64b/66b 인코딩은 예를 들어 10G/100G Ethernet 등 여러 프로토콜에서 사용됩니다. 참고로 최신 PCIe 및 USB 버전들은 아래에서 설명하는 다른 방식을 기반으로 합니다.

64b/66b 인코딩은 데이터 스트림을 64비트 세그먼트로 나누고 각 세그먼트의 시작에 2비트를 추가합니다. 따라서 각 세그먼트는 물리 채널에서 66비트 길이가 됩니다. 이 추가되는 2비트는 '01' 또는 '10' 두 값 중 하나를 가질 수 있습니다. 이 두 비트가 '01'이면 뒤따르는 64비트 워드에는 8바이트의 데이터가 들어 있습니다. 이 두 비트가 '10'이면 그다음 바이트가 일종의 코드가 되어, 나머지 56비트에 데이터 워드가 몇 개, 제어 워드가 몇 개 들어 있는지를 정의합니다.

제어 워드는 특히 프레임(패킷)의 시작과 끝을 나타내는 데 사용되며, 클록 주파수 차이를 보상하기 위한 유휴 워드(8b/10b의 스킵 심볼과 유사)를 삽입하는 데에도 사용됩니다. 프로토콜별 고유의 제어 워드를 정의하는 것도 가능합니다.

앞서 말했듯이 처음 두 비트가 '10'이면 나머지 64비트는 두 부분으로 나뉩니다. 하나는 8비트 코드 워드이고, 다른 하나는 데이터와 제어 워드가 조합된 56비트입니다. 이 56비트 안에서 데이터와 제어 워드를 배치하는 방식은 꽤 복잡합니다. 특히 각 제어 워드가 7비트 길이이기 때문입니다. 이렇게 7비트로 하는 것은 남은 56비트 안에 제어 워드를 최대 8개까지 넣기 위해서입니다.

이 인코딩을 사용하는 프로토콜들은 DC 밸런스와 데이터 무작위성을 보장하기 위해 데이터에 스크램블러를 적용하기도 합니다. 이런 무작위성은 이퀄라이저 때문만 필요한 것이 아닙니다. 수신기가 도착하는 데이터 스트림에서 66비트 세그먼트의 시작 위치를 찾는 데에도 필요합니다. 수신기는 각 66비트 세그먼트의 처음 두 비트를 검사하여 동기화를 수행합니다. 이 두 비트가 계속 '01' 또는 '10'으로만 나타나면 수신기는 동기화된 것입니다. 그렇지 않으면 다른 위치를 시도해야 합니다. 스크램블러는 나머지 비트들이 무작위적임을 보장하므로, 수신기가 잘못 정렬된 경우에는 곧 유효한 조합 대신 '00'이나 '11'이 나타나게 됩니다.

결국 64b/66b는 물리 채널을 더 효율적으로 사용하지만, 이 방식을 사용하는 프로토콜은 구현하기가 더 어렵습니다. 특히 각 세그먼트를 처음 두 비트에 따라, 그리고 경우에 따라서는 뒤따르는 8비트에 따라서도 다르게 처리해야 한다는 점이 구현을 복잡하게 만듭니다. FPGA MGT에 따라 이런 문제를 지원하는 수준이 다릅니다. 특히 어떤 MGT에는 도착 데이터를 66비트 세그먼트 경계에 자동으로 정렬하는 내장 메커니즘이 있습니다. 그렇지만 데이터와 제어 워드가 섞여 있는 66비트 세그먼트를 해석하는 더 어려운 작업은 여전히 애플리케이션 로직의 몫입니다.

FPGA MGT에는 66비트 세그먼트 스트림에서 64비트 워드를 뽑아내는 기어박스(gearbox)가 내장되어 있을 가능성이 높습니다. 기어박스에 대한 자세한 내용은 이 시리즈의 다음 페이지에서 다룹니다.

64b/67b, 128b/130b 및 128b/132b

64b/66b가 물리 채널을 더 효율적으로 사용하긴 하지만 구현이 복잡합니다. PCIe와 SuperSpeed USB 프로토콜이 8b/10b에서 벗어날 때 다른 길을 택한 이유도 아마 이 때문일 것입니다.

두 프로토콜 모두 데이터 스트림을 세그먼트로 나눈다는 아이디어는 유지했습니다. 다만 64비트 세그먼트 대신 128비트를 기반으로 합니다.

PCIe 3.0 이상은 128b/130b를 기반으로 합니다. 64b/66b 인코딩과 비슷하게, 128b/130b의 각 128비트 세그먼트는 데이터와 제어 코드를 구분하기 위해 '01' 또는 '10'으로 시작합니다. SuperSpeed USB Gen 2는 128b/132b를 기반으로 하며, 같은 목적으로 각 128비트 세그먼트가 '0011' 또는 '1100'으로 시작합니다. 유일한 차이는 USB 프로토콜이 비트 오류에 대한 더 나은 보호를 위해 2비트 대신 4비트를 사용한다는 것입니다.

64b/66b와 마찬가지로 각 세그먼트의 128비트 부분에는 DC 밸런스와 데이터 무작위화를 보장하기 위해 스크램블러가 적용됩니다. 그러나 공통점은 여기까지입니다. 두 프로토콜 모두 128비트 부분의 내용이 무엇을 의미하는지는 각자 고유한 구조에 따라 정의합니다. 따라서 128b/130b와 128b/132b는 데이터 스트림을 세그먼트로 나누는 방식과 데이터가 들어 있는 부분에 몇 비트를 추가하는지만 나타낼 뿐입니다. 나머지는 각 프로토콜 고유의 사항입니다.

64b/67b 인코딩도 비슷한 방식으로 동작합니다. 차이점은 같은 목적을 위해 64비트 세그먼트마다 3비트를 추가한다는 것입니다. 이 인코딩은 주로 Interlaken 프로토콜에서 사용됩니다.

인코딩 없음

위에서 언급한 인코딩 방식을 전혀 사용하지 않고도 통신 링크를 구현할 수 있습니다. 그러한 프로토콜의 예로는 Xillyp2p가 있습니다. Xillyp2p는 223 비트마다 동기화 워드를 사용하여 수신기를 송신기에 정렬하고 동기화합니다. 이 프로토콜에게 MGT는 단지 SERDES일 뿐입니다. 이 방식의 주요 장점은 프로토콜이 MGT의 다른 기능에 전혀 의존하지 않는다는 것입니다. 따라서 다양한 MGT에서 프로토콜 구현이 단순해집니다. 또 다른 장점은 이 설계 예제에서 볼 수 있듯이 MGT의 인스턴스화(instantiation)가 훨씬 간단하다는 것입니다.

단점은 MGT 내부에서 처리할 수 있었을 일에 FPGA 로직 리소스를 사용해야 한다는 것입니다.

이 접근 방식은 인코딩이 도와줄 수 있는 모든 필요를 프로토콜이 자체적으로 처리할 수 있을 때 적합합니다. 즉, DC 밸런스 유지, 무작위화(필요한 경우), 동기화 및 워드 정렬, 그리고 데이터와 제어 정보의 구분이 그것입니다.

요약

위에서 살펴본 것처럼 애플리케이션 로직의 데이터 스트림을 인코딩하는 방법에는 여러 가지가 있으며, 아무 인코딩도 사용하지 않는 선택지도 있습니다. 대부분의 애플리케이션에서는 8b/10b 인코딩이 다루기 가장 쉽지만, 물리 채널의 데이터 전송량 측면에서는 낭비가 큽니다. 그래서 최근 프로토콜들은 더 효율적이면서도 다루기는 훨씬 어려운 다른 인코딩 방식을 채택하고 있습니다.

이것으로 MGT에 관한 이 시리즈의 세 번째 페이지를 마칩니다. 다음 페이지에서는 PCS의 일부 구성 요소들을 소개하며, 특히 여기서 언급한 인코딩을 구현하는 부분들을 다룹니다.

이 페이지는 영어 원문을 기계 번역한 것입니다. 의문이 드는 부분이 있으면 원문을 참조하시기 바랍니다.
Copyright © 2021-2026. All rights reserved. (dcc38493)