Código Gray explicado: por qué lo usan los codificadores rotatorios
El código Gray da a los valores adyacentes una distancia de Hamming de un bit. Conoce sus fórmulas de conversión, sus ventajas para codificadores y las restricciones de CDC que sigue necesitando una FIFO asíncrona.
En resumen: En el código Gray binario reflejado, los valores adyacentes difieren en un bit. Esta propiedad limita la ambigüedad en un límite de posición construido correctamente y resulta útil para los punteros de FIFO asíncronas. No elimina la metaestabilidad, los fallos de sensores, los transitorios combinacionales ni la necesidad de restricciones de temporización para CDC.
Un contador binario estándar de 4 bits que avanza de a conmuta los cuatro bits a la vez. En un diagrama de temporización idealizado, esos bits cambian simultáneamente. En silicio real —con retardos de puerta desiguales, flancos con distintas velocidades de transición y rieles de alimentación ruidosos— cambian en algún orden no especificado, lo que produce un breve parpadeo de valores intermedios como o en el bus. Para un registro de CPU, esto es inocuo: el valor se muestrea en un flanco de reloj después de que todo se estabilice. Para un sensor leído por un observador asíncrono, esos transitorios son lecturas reales.
El código Gray, también llamado código binario reflejado, modifica la condición de contorno: las palabras de código adyacentes difieren en un bit, por lo que un observador correctamente alineado no tiene que resolver a la vez varias transiciones de bit previstas. El único bit que está cambiando aún puede ser ambiguo, ruidoso o metaestable; por ello, el código Gray reduce una clase de error en lugar de hacer infalible la interfaz.
¿Por qué importa la adyacencia de un bit?
Considera un codificador rotatorio: el disco óptico o magnético que indica a un controlador de motor en qué ángulo está un eje. El disco tiene pistas concéntricas; cada pista aporta un bit de la palabra de posición, leído por un sensor situado en un ángulo fijo. A medida que el disco gira, el sensor observa una secuencia de valores binarios.
Si las pistas están codificadas en binario directo, el límite entre la posición () y la posición () exige que tres pistas cambien de estado en el mismo ángulo nominal. La colocación de los sensores, la geometría de las pistas y las diferencias de umbral hacen que esas transiciones no tengan por qué observarse simultáneamente. El controlador puede decodificar brevemente una palabra intermedia alejada de cualquiera de las dos posiciones adyacentes.
Codificar el mismo disco en código Gray convierte cada límite angular en una transición de un solo bit:
| Posición | Binario | Gray |
|---|---|---|
| 0 | 000 | 000 |
| 1 | 001 | 001 |
| 2 | 010 | 011 |
| 3 | 011 | 010 |
| 4 | 100 | 110 |
| 5 | 101 | 111 |
| 6 | 110 | 101 |
| 7 | 111 | 100 |
Observa la columna Gray. Entre dos filas adyacentes cualesquiera, exactamente un bit cambia. Entre la fila 7 y la fila 0 también cambia exactamente un bit, así que la secuencia es cíclica y de distancia unitaria. Bajo el modelo previsto de un límite a la vez, la incertidumbre de umbral queda confinada al código adyacente antiguo o nuevo. La desalineación a través de varios límites, la contaminación, las pistas dañadas, el ruido eléctrico o la decodificación de una muestra metaestable aún pueden producir un error.
La tabla de código Gray de 4 bits
El patrón se extiende de forma natural:
| Decimal | Binario | Gray |
|---|---|---|
| 0 | 0000 | 0000 |
| 1 | 0001 | 0001 |
| 2 | 0010 | 0011 |
| 3 | 0011 | 0010 |
| 4 | 0100 | 0110 |
| 5 | 0101 | 0111 |
| 6 | 0110 | 0101 |
| 7 | 0111 | 0100 |
| 8 | 1000 | 1100 |
| 9 | 1001 | 1101 |
| 10 | 1010 | 1111 |
| 11 | 1011 | 1110 |
| 12 | 1100 | 1010 |
| 13 | 1101 | 1011 |
| 14 | 1110 | 1001 |
| 15 | 1111 | 1000 |
El nombre «reflejado» procede de la regla de construcción: para formar el código de bits, toma el código de bits, refléjalo verticalmente, antepone un a la mitad original y un a la mitad reflejada. El reflejo garantiza que el límite entre las dos mitades sea una transición de un solo bit (el nuevo MSB).
Conversión de binario a Gray
La conversión de binario a Gray es una de las fórmulas más limpias de la lógica digital:
con para el MSB. Como expresión única:
En hardware, cada salida Gray es una XOR de bits binarios adyacentes; no hay cadena de acarreo y la profundidad lógica ideal es una etapa XOR. Eso no garantiza una salida combinacional sin transitorios mientras cambian físicamente varios bits de un contador binario. Registra el valor Gray convertido antes de tratarlo como señal de CDC. Para entender por qué XOR es el operador adecuado, vuelve a consultar el papel de la puerta XOR como detector de diferencias.
Ejemplo resuelto. Convierte el binario a Gray.
Resultado: Gray , que la tabla anterior confirma como la codificación del decimal 11.
Conversión de Gray a binario
La dirección inversa usa una XOR de prefijo:
De forma equivalente, recorriendo desde el MSB hacia abajo: y después . Una implementación serie directa tiene profundidad XOR lineal, pero un árbol XOR de prefijo paralelo puede reducir la profundidad a costa de más cableado y puertas. No supongas que la cadena ingenua es la única implementación.
Para el ejemplo anterior, al decodificar Gray :
Binario recuperado: , decimal 11. Ida y vuelta sin errores.
Más allá de los codificadores: cruce de dominios de reloj
Los codificadores rotatorios son la motivación de manual, pero el uso moderno más importante del código Gray está dentro de las FPGA y los SoC: punteros de FIFO asíncronas para el cruce de dominios de reloj (CDC).
Una FIFO de doble reloj necesita que cada lado estime el puntero del otro para poder determinar el estado lleno o vacío. Enviar directamente un contador binario ordinario de varios bits a través del límite no es seguro porque un incremento puede cambiar varios bits.
Un diseño robusto de punteros Gray normalmente:
- mantiene el puntero de trabajo en binario para la aritmética local;
- convierte el puntero siguiente a Gray;
- registra el valor Gray en el dominio de origen;
- sincroniza cada bit Gray en el dominio de destino; y
- compara el puntero sincronizado utilizando las ecuaciones de lleno/vacío documentadas de la FIFO.
La codificación Gray implica que solo cambia un bit lógico del puntero por incremento, pero no garantiza por sí sola un CDC correcto. El bit que cambia puede violar la ventana de captura de un biestable de destino y volverse metaestable. El sesgo de enrutamiento también puede hacer que distintos bits Gray de diferentes transiciones de origen se solapen en el destino, salvo que las restricciones de implementación limiten el retardo o el sesgo del bus. Tanto AMD como Intel documentan dichas restricciones para punteros de FIFO codificados en Gray.
El puntero sincronizado también se retrasa varios relojes de destino. La lógica de lleno/vacío está diseñada para ser conservadora ante esa latencia; no es un recuento entre dominios continuamente exacto. Usa un diseño de FIFO asíncrona probado o IP de proveedor cuando la corrección sea importante.
Un contador de código Gray en hardware
Dos enfoques prácticos son:
- Contador binario + conversión registrada. Calcula
gray_next = binary_next XOR (binary_next >> 1)y captura ambos valores siguientes en el mismo reloj de origen. La salida Gray registrada cambia de acuerdo con la secuencia de código; no expongas un convertidor no registrado alimentado por un contador binario con ondulación o sesgo como si no produjera transitorios. - Máquina de estados Gray nativa. Deriva la lógica de siguiente estado que siga directamente la secuencia Gray elegida. Esto evita un registro de estado binario, pero hace menos cómoda la aritmética de incremento/decremento y de direcciones FIFO.
Para experimentar con el primer enfoque, abre la plantilla de contador binario de 4 bits, añade la red XOR y registra sus cuatro salidas. Compara los estados estables después de cada reloj. Si el simulador modela el retardo de puerta, inspecciona también la salida del convertidor no registrado durante las transiciones; puede revelar por qué importa el registro de origen.
Inconvenientes: la aritmética es incómoda
El superpoder del código Gray —las transiciones de un solo bit— tiene un precio: la aritmética en código Gray es difícil. No existe una fórmula de propagación de acarreo que funcione directamente con valores codificados en Gray. Sumar dos números Gray requiere convertir ambos a binario, sumarlos y volver a convertirlos. La multiplicación y los desplazamientos presentan el mismo problema.
Por eso, las rutas de datos aritméticas ordinarias suelen convertir el estado codificado en Gray a binario en lugar de realizar aritmética completa directamente en código Gray. La codificación es útil en límites concretos, no un sustituto universal del binario. Los mapas de Karnaugh usan el orden Gray por otro motivo: las celdas adyacentes deben diferir en una variable de entrada para que los grupos geométricos correspondan a implicantes.
Nota histórica
La codificación recibe su nombre del investigador de Bell Labs Frank Gray. Su solicitud de patente «Pulse Code Communication» se presentó en 1947 y se concedió como la patente estadounidense 2,632,058 en 1953; denomina al esquema código binario reflejado y destaca que las amplitudes representadas vecinas difieren en una posición de pulso. Las secuencias relacionadas de distancia unitaria son anteriores a la patente, por lo que es más preciso atribuir a Gray esta aplicación influyente y la línea de denominación que atribuirle la invención de todas esas secuencias.
Errores habituales
- Suponer que la aritmética funciona. Sumar valores codificados en Gray bit a bit produce resultados sin sentido. Convierte siempre primero a binario.
- Ignorar la convención de cero en el MSB. La fórmula de binario a Gray presupone un cero virtual por encima del MSB. Olvidarlo invierte el signo del bit alto.
- Mezclar Gray con bucles de registros de desplazamiento. Un registro de desplazamiento estándar, como los diseños SISO/SIPO, desplaza los bits lateralmente y no conserva de extremo a extremo las propiedades de distancia unitaria. Convierte en los límites.
- Confundir Gray con one-hot. La codificación one-hot (solo hay un bit activado) también es resistente a transitorios en otro sentido, pero tiene un ancho de en vez de . El código Gray es la opción compacta.
Qué sigue
La guía publicada de SISO, SIPO, PISO y PIPO compara las cuatro rutas de datos habituales de los registros de desplazamiento. No uses un registro de desplazamiento ordinario como sustituto de una FIFO asíncrona: los datos relacionados de varios bits requieren un protocolo que preserve la coherencia a través del límite de reloj.
Para ver el código Gray en acción, carga la plantilla de contador binario de 4 bits, construye el convertidor, añade un registro de salida y verifica la distancia de Hamming entre valores registrados consecutivos. Después, elimina deliberadamente el registro en un modelo sensible al retardo e inspecciona el comportamiento transitorio.
