Esta página es la tercera de una serie de páginas dedicada al transceptor multigigabit (MGT).
Nota: Si estás leyendo esta página como parte de la configuración de un enlace físico para Xillyp2p, esta página no es relevante para ti: en ese caso, todas las funciones de codificación deben desactivarse, ya que el núcleo de IP (IP core) de Xillyp2p lo implementa todo internamente y ofrece al usuario flujos de extremo a extremo para los datos de aplicación.
Introducción
El flujo de datos de la lógica de aplicación casi nunca se transmite tal cual por el canal físico. Si se hiciera así, lo más probable es que el MGT no funcionara bien, por las razones que se explicaron anteriormente. En casi todas las aplicaciones, el MGT o la lógica de aplicación aplican una codificación al flujo de datos para garantizar que el canal físico pueda funcionar correctamente. Esta codificación ayuda también con la sincronización entre el transmisor y el receptor.
Hay excepciones, sin embargo: en este diseño de ejemplo completo, el MGT se utiliza como un simple SERDES, sin codificación alguna activada. Esto es posible porque la lógica de aplicación implementa el codificador de aleatorización (scrambler) y las demás funcionalidades necesarias.
Esta página repasa los fundamentos de las técnicas de codificación más utilizadas. La lista de protocolos de la página anterior relaciona estas codificaciones con los protocolos que se usan entre FPGAs.
Codificación 8b/10b
La codificación 8b/10b se utiliza en varios protocolos, por ejemplo en algunas versiones de PCIe, Gigabit Ethernet, SATA, DisplayPort y SuperSpeed USB. Todos los MGT de FPGA incorporan un codificador y un decodificador 8b/10b, aunque este codificador también puede implementarse en el tejido lógico.
Esta codificación traduce cada byte (8 bits) en una palabra de 10 bits. El propósito principal de esta traducción es crear una secuencia de bits con el mismo número de ‘0’ y de ‘1’ en promedio. Es decir, los bits del flujo de datos codificado están equilibrados en corriente continua. Otra ventaja es que la codificación asegura que haya suficientes transiciones entre ‘0’ y ‘1’ en el flujo de datos, de manera que el mecanismo de recuperación de reloj y datos (clock data recovery, CDR) pueda funcionar correctamente.
Observa, sin embargo, que la codificación 8b/10b no aleatoriza el flujo de datos. En particular, la codificación 8b/10b por sí sola no es suficiente si se utiliza un ecualizador (equalizer) que exija que el flujo de datos sea estadísticamente aleatorio.
Para alcanzar el objetivo del equilibrio en corriente continua, algunas de las palabras de 8 bits pueden codificarse en dos candidatos posibles. Por ejemplo, la palabra de 8 bits 0x20 (00100000, denotada D0.1) puede codificarse como 1001111001 o como 0110001001. Ambas alternativas se decodifican de vuelta a 0x20. Observa que la primera alternativa tiene cuatro bits ‘0’ y seis bits ‘1’. La segunda alternativa tiene seis bits ‘0’ y cuatro bits ‘1’. Esta es la idea central de la codificación 8b/10b: el codificador dispone de dos alternativas, una con más ‘0’ que ‘1’ y la otra al revés.
El codificador utiliza esta característica para garantizar el equilibrio entre ‘0’ y ‘1’ a largo plazo: recuerda si ha habido demasiados ‘0’ o demasiados ‘1’ en el flujo de datos hasta ese momento. Ese desequilibrio se denomina disparidad acumulada (Running Disparity). El codificador elige la palabra de 10 bits que ayude a reducir ese desequilibrio.
No todas las palabras de 8 bits tienen dos candidatos de 10 bits. Por ejemplo, la palabra de 8 bits 0x23 (00100011, denotada D3.1) siempre se codifica como 1100011001. Esta palabra codificada tiene el mismo número de ‘0’ y de ‘1’, de modo que no influye en la disparidad acumulada.
Esta codificación se publicó por primera vez en 1983 y ha sido muy popular en los protocolos que aparecieron hasta aproximadamente el año 2010. Es menos popular en los protocolos publicados recientemente. La razón principal es que esos protocolos suelen incluir también un codificador de aleatorización (scrambler). El equilibrio en corriente continua del flujo de datos queda entonces garantizado por el uso del scrambler, de modo que la codificación 8b/10b no es necesaria para ese fin. El scrambler se encarga también de que haya transiciones entre ‘0’ y ‘1’ con la frecuencia suficiente. Por otro lado, la codificación 8b/10b añade un 25% más de bits para transmitir por el canal físico. Esos bits sobrantes podrían haberse utilizado para transmitir datos útiles.
Dicho esto, algunos protocolos de éxito que utilizan un scrambler emplean también la codificación 8b/10b. Por ejemplo, todas las versiones de PCIe exigen el uso de un scrambler, pero la codificación 8b/10b se utiliza también en las versiones de PCIe anteriores a la 3.0. Así que, evidentemente, la codificación 8b/10b tiene otras ventajas. Y esto nos lleva al siguiente tema: los símbolos K.
Símbolos K
El hecho de que un codificador 8b/10b genere 10 bits a partir de cada 8 bits que codifica implica que la palabra codificada tiene 1024 combinaciones posibles, frente a las 256 posibilidades de la palabra original. Incluso si suponemos que cada palabra original tiene dos posibles palabras codificadas, se cubrirían 512 posibilidades. Como se ha dicho antes, algunas palabras de 8 bits tienen una sola palabra de 10 bits para traducir, así que hay menos de 512 posibilidades entre las palabras de 10 bits. La conclusión es, por tanto, que al menos 512 de las combinaciones de 10 bits no se corresponden con ninguna palabra de 8 bits.
De ahí que la codificación 8b/10b pueda detectar errores de bit en el enlace físico, al detectar palabras de 10 bits ilegales. Los MGT de FPGA tienen puertos de salida que sirven para informar a la lógica de aplicación cuando se detecta una palabra de 10 bits ilegal. Este mecanismo de detección de errores no es muy valioso, sin embargo, porque no detecta todos los errores.
La característica realmente valiosa de la codificación 8b/10b son los símbolos K (K-symbols). Un símbolo K se codifica y se transmite en lugar de una palabra de 8 bits. El decodificador es capaz de distinguir entre una palabra de datos normal y un símbolo K, y siempre hay alguna manera de informar a la lógica de aplicación cuando llega un símbolo K.
Así pues, la codificación 8b/10b permite al transmisor enviar información adicional por el canal de datos de una manera que no se confunde con los datos normales. Los protocolos utilizan a menudo esta posibilidad para ayudar al receptor a sincronizarse con el flujo de datos del transmisor.
El significado de los símbolos K depende del protocolo. Hay, no obstante, un símbolo K que muchos protocolos utilizan con el mismo significado: el K28.5 se denomina a menudo coma (Comma, COM) y se utiliza para sincronizar el flujo de datos. Más sobre esto a continuación.
Cuando la codificación 8b/10b está activada en un MGT de FPGA, la interfaz con la lógica de aplicación tiene un cable adicional por cada byte de datos. Ese cable indica si el dato es un byte de datos normal o un símbolo K. En otras palabras, la interfaz de transmisión de datos permite elegir si cada palabra transmitida es un dato normal o un símbolo K. Dicho esto, cuando una palabra de datos se marca como símbolo K, la palabra de 8 bits correspondiente se limita a las siguientes opciones:
| Valor del byte (hex) | Símbolo 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 |
De forma parecida, en el receptor del MGT hay un cable adicional por cada byte recibido en la interfaz con la lógica de aplicación. El valor de cada uno de esos cables indica si el byte correspondiente debe interpretarse como un dato normal o como un símbolo K. El receptor tiene también una funcionalidad especial para tratar el K28.5 (el símbolo de coma, Comma Symbol, COM) de manera particular. Este símbolo K se trata a continuación.
El símbolo de coma (K28.5)
La representación de 10 bits del K28.5 es 0011111010 o 1100000101. Esta palabra es especialmente útil porque esa secuencia de bits solo puede aparecer en el canal físico como resultado de transmitir un K28.5. El receptor no necesita estar sincronizado con el transmisor para detectar un K28.5: basta con que los últimos 10 bits recibidos coincidan con una de estas dos palabras.
Esto convierte al K28.5 en una herramienta excelente para sincronizar el receptor. Una vez detectado este símbolo K, se conocen los límites de las demás palabras de 10 bits.
Los MGT de FPGA tienen la capacidad de alinear automáticamente el flujo de datos entrante en respuesta a la llegada de un símbolo K28.5. Normalmente también es posible pedir que la alineación se haga con respecto a un límite mayor. Por ejemplo, el MGT puede configurarse para alinear un K28.5 entrante con el comienzo de una palabra de 32 bits.
Además de alinear el receptor, el símbolo K28.5 puede utilizarse para alinear otras unidades funcionales que necesiten sincronización. Por ejemplo, el protocolo puede solicitar que el scrambler se reinicie cuando llegue este símbolo K.
Debido a estas posibilidades, los protocolos suelen exigir que se transmita un K28.5 periódicamente para sincronizar al receptor. Los protocolos que establecen una conexión mediante un handshake suelen usar el K28.5 como parte del establecimiento del enlace. En cualquier caso, el símbolo K28.5 simplifica el diseño del protocolo hasta el punto de justificar el 25% de bits extra que se transmiten por el canal físico.
El símbolo de omisión (K28.0 y K28.1)
En la mayoría de las situaciones prácticas, existe una diferencia entre las frecuencias de reloj del transmisor y del receptor. Esto puede plantear un problema: a menudo, la interfaz entre el MGT y la lógica de aplicación es síncrona con el reloj local del receptor. Así que los datos llegan según el reloj del transmisor, pero se entregan a la lógica de aplicación según el reloj del receptor.
En otras palabras, los datos que recibe un MGT llegan a un ritmo marcado por el otro lado. Pero el reloj local determina la velocidad con la que se consumen esos datos.
Si la frecuencia del reloj del transmisor es mayor, el resultado es que la lógica de aplicación extrae los datos del MGT demasiado despacio. Los datos sobrantes se acaban acumulando y se producirá un desbordamiento (overflow) en algún lugar del MGT. Por otro lado, si la frecuencia del reloj del transmisor es menor, la lógica de aplicación intenta extraer los datos más rápido de lo que llegan. Esto también es un problema.
Una solución sencilla a este problema consiste en añadir símbolos de omisión (skip). Por ejemplo, el protocolo SuperSpeed USB define un conjunto ordenado SKP (SKP Ordered Set) como dos símbolos K28.1 consecutivos. El protocolo exige que estos dos símbolos K28.1 se transmitan una vez por cada 354 palabras de datos normales. Al MGT receptor se le permite descartar esos símbolos K28.1 en lugar de presentarlos a la lógica de aplicación. Esto resuelve el problema del exceso de datos cuando el reloj del transmisor es más rápido que el del receptor: cuando el MGT receptor empieza a acumular datos debido a la diferencia de frecuencias, omite los símbolos K28.1 que van llegando.
Con este mecanismo, el transmisor puede enviar 356 palabras en el mismo periodo en el que la lógica de aplicación del receptor extrae solo 354. Con el cálculo 356 / 354 ≈ 1,00565, se deduce que este mecanismo puede absorber una diferencia de frecuencia de hasta el ~0,565% entre los dos relojes. Esto es más de lo que la especificación del protocolo permite, por supuesto.
Al MGT receptor también se le permite añadir símbolos K28.1 a un conjunto ordenado SKP ya existente. Esto puede ayudar cuando el reloj del transmisor es más lento. En ese caso, la lógica de aplicación del lado receptor intenta extraer datos más rápido de lo que llegan. Al MGT se le permite entonces rellenar los huecos que falten con símbolos K28.1: se espera que la lógica de aplicación ignore los símbolos K28.1 de todas formas.
El protocolo PCIe utiliza el símbolo de omisión de forma similar. El formato del conjunto ordenado SKP de PCIe es distinto y consta de cuatro símbolos K: primero un K28.5 (coma) y después tres símbolos K28.0. Los principios de uso del símbolo de omisión son, no obstante, los mismos.
Tanto el protocolo USB como el protocolo PCIe utilizan la abreviatura SKP en relación con los conjuntos ordenados. Observa que esto significa K28.1 cuando se menciona en el protocolo SuperSpeed USB, pero K28.0 en relación con PCIe. Esto deja margen para la confusión.
Codificación 64b/66b
Como ya se ha dicho, la codificación 8b/10b utiliza el canal físico de manera ineficiente, y los propósitos principales de esta codificación (equilibrio en corriente continua y presencia de transiciones entre ‘0’ y ‘1’) no son necesarios cuando se usa un codificador de aleatorización (scrambler). Por eso los protocolos más recientes confían en la codificación 64b/66b y métodos similares. Es importante señalar, sin embargo, que la 64b/66b no es realmente un método de codificación. Es más bien un método para organizar el flujo de datos y las palabras de control. Los datos no se codifican a una representación distinta. Lo único que ocurre es que los datos se organizan en segmentos y se insertan bits adicionales para permitir la sincronización y el envío de información de control por el canal.
Observa que los símbolos K pertenecen exclusivamente a la codificación 8b/10b y no están disponibles en ninguno de los demás formatos de codificación.
La codificación 64b/66b la utilizan varios protocolos, por ejemplo Ethernet de 10G/100G. Vale la pena señalar que las versiones avanzadas de PCIe y USB se basan en otros métodos, como se comenta más abajo.
La codificación 64b/66b divide el flujo de datos en segmentos de 64 bits y añade dos bits al comienzo de cada segmento. Por tanto, cada segmento tiene 66 bits en el canal físico. Esos dos bits extra pueden tener uno de dos valores: "01" o "10". Si esos dos bits son "01", la palabra de 64 bits que sigue contiene ocho bytes de datos. Si son "10", el byte siguiente contiene un código que define qué contienen los 56 bits restantes: cuántas palabras de datos y cuántas palabras de control.
Las palabras de control se utilizan, en particular, para indicar el inicio y el final de las tramas (paquetes), pero también para insertar palabras de relleno (idle words) con el fin de compensar las diferencias de frecuencia de reloj (de forma parecida a los símbolos de omisión de la 8b/10b). También pueden definirse palabras de control específicas de un protocolo.
Como ya se ha mencionado, si los dos primeros bits son "10", el resto de los 64 bits se divide en dos partes: una palabra de código de 8 bits y 56 bits formados por una combinación de palabras de datos y de control. La organización de las palabras de datos y de control dentro del segmento de 56 bits es bastante complicada, sobre todo porque cada palabra de control tiene 7 bits. Esta peculiaridad es necesaria para poder insertar ocho palabras de control en los 56 bits restantes.
Además, los protocolos que usan esta codificación emplean también un codificador de aleatorización (scrambler) para los datos, con el fin de garantizar el equilibrio en corriente continua y la aleatoriedad de los datos. Esa aleatoriedad no se necesita solo por el ecualizador: el receptor también la necesita para encontrar el comienzo de los segmentos de 66 bits en el flujo de datos entrante. Para ello examina los dos primeros bits de cada segmento de 66 bits. Si ese par de bits repite una y otra vez los valores "01" o "10", el receptor está sincronizado. En caso contrario, debe probar una posición distinta. El codificador de aleatorización se asegura de que los demás bits sean aleatorios, de modo que si el receptor está desalineado, pronto aparecerá un "00" o un "11" en lugar de las combinaciones válidas.
En definitiva, la codificación 64b/66b aprovecha mejor el canal físico subyacente; sin embargo, un protocolo que utiliza este método es más difícil de implementar. En particular, la necesidad de tratar cada segmento de forma distinta (según los dos primeros bits y posiblemente también según los ocho bits que les siguen) añade complejidad a la implementación. Los distintos MGT de FPGA ofrecen diferentes niveles de ayuda en este asunto. En particular, algunos MGT tienen un mecanismo integrado que alinea automáticamente el receptor con los segmentos de 66 bits de los datos entrantes. La lógica de aplicación es, no obstante, responsable de la tarea más difícil de desempaquetar los segmentos de 66 bits que contienen una combinación de palabras de datos y de control.
Es probable que un MGT de FPGA tenga incorporado un gearbox (adaptador de anchura de palabra) para extraer palabras de 64 bits a partir del flujo de segmentos de 66 bits. Los gearboxes se tratan con más detalle en la página siguiente de esta serie.
64b/67b, 128b/130b y 128b/132b
Aunque la codificación 64b/66b aprovecha mejor el canal físico, este método es complicado de implementar. Esta es probablemente la razón por la que los protocolos PCIe y SuperSpeed USB tomaron otro camino al abandonar la codificación 8b/10b.
Ambos protocolos conservaron la idea de dividir el flujo de datos en segmentos. En lugar de segmentos de 64 bits, estos protocolos se basan en 128 bits.
PCIe 3.0 y versiones posteriores se basan en 128b/130b. De forma similar a la codificación 64b/66b, cada segmento de 128 bits de este protocolo comienza con "01" o "10" para distinguir entre datos y códigos de control. SuperSpeed USB Gen 2 se basa en 128b/132b. Cada uno de sus segmentos de 128 bits comienza con "0011" o "1100" para el mismo propósito. La única diferencia es que el protocolo USB reserva cuatro bits en lugar de dos para protegerse mejor contra los errores de bit.
También de forma similar a la codificación 64b/66b, se utiliza un codificador de aleatorización (scrambler) sobre la parte de 128 bits de cada segmento para garantizar el equilibrio en corriente continua y la aleatorización del flujo de datos. Pero ahí termina la similitud con la 64b/66b: ambos protocolos definen el significado del contenido de la parte de 128 bits según su propia estructura. Por tanto, 128b/130b y 128b/132b solo indican la división del flujo de datos en segmentos y cuántos bits se añaden a la parte que contiene datos. El resto es específico de cada protocolo.
La codificación 64b/67b funciona de forma parecida. La diferencia es que se añaden tres bits a cada segmento de 64 bits, con los mismos fines. Esta codificación la utiliza principalmente el protocolo Interlaken.
Sin codificación
Es posible implementar un enlace de comunicación sin ninguno de los métodos de codificación mencionados. Un ejemplo de este tipo de protocolo es xillyp2p, que utiliza una palabra de sincronización cada 223 bits para alinear y sincronizar el receptor con el transmisor. Para este protocolo, el MGT no es más que un SERDES. La principal ventaja de esta estrategia es que el protocolo no depende en absoluto de las demás características del MGT. Esto simplifica la implementación del protocolo en una amplia variedad de MGT. Otra ventaja es que la instanciación (instantiation) del MGT es mucho más sencilla, como se muestra en este diseño de ejemplo.
La desventaja es que se utilizan recursos de lógica de la FPGA para algo que posiblemente podría haberse hecho dentro del MGT.
Este enfoque es adecuado cuando el protocolo cubre todas las necesidades que la codificación podría ayudar a resolver: equilibrio en corriente continua, aleatorización (cuando sea necesaria), sincronización y alineación de palabras, además de la distinción entre datos e información de control.
Resumen
Como se ha mostrado, hay distintos enfoques para codificar el flujo de datos de la lógica de aplicación, y también es posible no utilizar codificación alguna. Para la mayoría de las aplicaciones, la codificación 8b/10b es la más fácil de manejar, pero esta codificación es poco eficiente en lo que respecta al flujo de datos del canal físico. Por eso los protocolos más recientes han adoptado otros métodos de codificación más eficientes, pero considerablemente más difíciles de usar.
Con esto concluye la tercera página de esta serie sobre los MGT. La página siguiente presenta algunas partes del PCS, entre otras las que implementan las codificaciones aquí mencionadas.