FPGA: sincroniza el reloj "muy cerca" de la señal

Esta es más una pregunta de aprendizaje, puedo resolver el problema, pero sería bueno saber cómo hacerlo: ¿se puede reconstruir un reloj a partir de una señal y es más fácil cuando se conoce básicamente la frecuencia del reloj?

Estoy usando una placa Terasic DE10 Lite, reflejando video de una Mac SE/30 (512x342x1bpp) en una pantalla VGA. Las conexiones de Mac son vsync, hsync y pixel desde la placa analógica, el nivel se convierte a 3,3 V y luego se conecta a los GPIO de la placa FPGA. A 1024x768 es un ajuste bastante bueno si se duplica el píxel. Obtener VGA a 60 Hz no es difícil, un bloque de IP ALTPLL a 65 Mhz hace que solo sea cuestión de contar el porche delantero/trasero y los pulsos de sincronización.

Copiar la señal de Mac es un poco más difícil. Terminé con un @always en un reloj ALTPLL funcionando a 15,67 MHz (y experimenté con números mult/div para tratar de acercarme lo más posible), la tasa de salida de píxeles de la Mac. No puedo igualar exactamente la velocidad del reloj de esta manera . Esto cuenta el período en blanco vertical y luego para cada línea cuenta hasta que comienzan los píxeles y muestrea cada píxel. Los píxeles se escriben en una losa de RAM de doble puerto hecha a partir de otro bloque de IP y se emiten mediante la rutina VGA.

Esto funciona y es perfectamente legible. Pero es feo ya que hay errores de muestreo debido a los relojes que no coinciden ligeramente. Si en lugar del reloj ALTPLL tomo CPUCLK del conector PDS de Mac y lo uso para registrar los píxeles, todo es lo más estable posible. Usando el reloj FPGA, los píxeles son inestables y cambian aleatoriamente donde no deberían.

La pregunta es, ¿qué haces si no puedes tomar el reloj del sistema? Creo que debe haber alguna forma de ajustar dinámicamente la frecuencia y el cambio de fase según la entrada, pero no sé dónde buscar.

(esta pregunta no obtuvo respuesta en Stack Overflow, tal vez encaje mejor aquí)

Respuestas (2)

No hay dos relojes que coincidan perfectamente. El método para determinar la verdadera frecuencia del reloj a partir de los datos se denomina "recuperación del reloj".

Si conoce la tasa de bits nominal, entonces un método sencillo que no requiere el uso de un bloque PLL/DCM es sobremuestrear los datos y buscar bordes. Normalmente, necesitaría sobremuestrear al menos 4 veces la tasa de bits. Así es como funciona...

  1. Cree un reloj en su parte que sea 4X la tasa de bits. En el caso de una tasa de bits de 65 MHz, este es un reloj de 260 MHz.

  2. El uso del reloj de 260 MHz registra el doble o el triple de los bits entrantes para evitar problemas de metaestabilidad. Estos tipos de problemas pueden ocurrir si una señal de entrada cambia muy cerca de un borde de reloj. Es casi seguro que esto suceda cuando se toman muestras de datos utilizando un reloj diferente del que se generaron los datos.

  3. Opcionalmente, haga dos etapas adicionales de registro y haga un voto mayoritario de 2 de 3 en las últimas tres etapas. Esto reducirá la detección falsa de bordes debido al ruido, lo que se vuelve importante en el siguiente paso, ya que está utilizando bordes en los datos para encontrar la frecuencia del reloj.

  4. Cree un contador de ejecución libre de dos bits que cuente de 0 a 3 y luego regrese a 0. El contador está cronometrado por el reloj de 260 MHz.

  5. Cada vez que vea una transición de 0 a 1 o de 1 a 0 en los datos de entrada, suponga que se encuentra en el borde del reloj y restablezca el contador a 1 (cnt <= "01").

  6. Siempre que el contador tenga un valor de 2 (cnt = "10"), use la salida de su voto mayoritario como su muestra de entrada. Y si mantiene un recuento de píxeles, también increméntelo.

Personalmente, he usado el método anterior para recuperar con éxito el reloj en datos en serie de hasta 100 Mbps.

Dependiendo de si los datos entrantes son un poco más rápidos o más lentos que su reloj, el contador omitirá un tic o mantendrá un tic adicional para ajustar la tasa de conteo para que coincida con los datos.

Para una velocidad de datos más lenta, verá algo como...
...0,1,2,3,0,1,2,3, 0,1,1,2,3,0,1,2,3 , 0,1,2,3...

Para una velocidad de datos más rápida , verá algo como...
...0,1,2,3,0,1,2,3, 1,2,3,0,1,2,3,0,1, 2,3...

Hay otro método en el que puede hacer el sobremuestreo 4X utilizando dos relojes que tienen la misma velocidad que su reloj de píxeles pero 90 grados desfasados. Al muestrear en cuatro registros (uno al subir y otro al bajar para cada reloj) puede lograr el mismo efecto que con la configuración anterior basada en contadores. Las tasas de píxeles máximas posibles son más altas para ese método, pero la lógica es un poco más compleja.

El problema con la recuperación del reloj a través del sobremuestreo desbloqueado es que requiere que haya transiciones frecuentes, ya que la precisión con la que se puede medir el ancho de una región libre de transiciones está limitada por el error al hacer coincidir los relojes independientes. Como tal, esto probablemente funcionaría bien para una línea de escaneo que contenga texto. Pero en una línea en blanco con solo uno o dos píxeles de cuadro delimitador decorativo a cada lado, ¿eran 490 píxeles en el medio o 492? Incluso una fracción de un porcentaje de error al hacer coincidir el reloj hará que el borde derecho de las líneas sin texto no coincida con el borde derecho de las líneas.
Es por esta razón que a un sistema práctico le gustará que el monitor que reemplaza bloquee un PLL en un múltiplo de la frecuencia de sincronización horizontal y analice las transiciones de datos solo en un sentido estadístico para encontrar la cantidad de relojes de puntos entre sincronizaciones y el potencial desplazamiento fraccional de la sincronización a la posición de muestreo ideal para el primer píxel. Tal vez en el caso limitado de una sola fuente y video de baja resolución de dos estados, este sobremuestreo desbloqueado puede funcionar; pero no es lo que hay en una solución de producto habitual, como un monitor LCD uniforme en escala de grises o una tarjeta de captura. El FPGA seguramente tiene un PLL.
@ChrisStratton Para 768 líneas x 60 fps, es probable que la frecuencia HSYNC sea de alrededor de 46 kHz. Están usando la placa Terasic DE10 que tiene el FPGA 5CSXFC6D6F31C6N. La frecuencia mínima de entrada de PLL en ese FPGA es de 5 MHz, que es 100 veces la frecuencia de HSYNC. Por lo tanto, no pueden alimentar HSYNC directamente al PLL, y dado que es una placa de demostración COTS, no se puede agregar fácilmente hardware PLL externo que acepte la frecuencia más baja. No estoy seguro de cómo harían que el PLL funcione en su caso.
De hecho, eso es un poco de rompecabezas para el PLL. Sin embargo, aunque su idea de recuperación de reloj quizás pueda producir texto legible, no producirá alineación a menos que el reloj de ejecución libre sea lo suficientemente preciso como para que el problema original de texto mal legible no haya sido un problema. Puede ser necesario agregar un PLL externo, posiblemente multiplicado nuevamente en el interior. En realidad, estas placas de demostración tienen encabezados diseñados precisamente para admitir circuitos externos complementarios.
@ChrisStratton La misma idea contraria podría aplicarse a HSYNC en lugar de a los datos para eliminar el problema de los datos en blanco. Haga un contador de 13 bits a 4X la frecuencia de píxeles. Use ese contador para contar cuánto dura un HSYNC dentro de un cuarto de píxel. Durante cada línea de exploración, el conteo anterior se usa para convertir el conteo actual en un desplazamiento de píxeles que se puede usar para muestrear y almacenar los datos de píxeles. La lógica para determinar la posición del píxel a partir de los dos recuentos es solo una lógica de suma o resta. Se vuelve un poco más complicado cumplir con el tiempo ya que ahora tendríamos contadores más grandes a alta frecuencia.
Eso podría estar reduciéndose a algo: creo que lo que está diciendo es ejecutar un reloj a 4 veces el reloj de puntos aproximado, luego usar el conteo medido de relojes entre las sincronizaciones anteriores frente a lo esperado para calcular una fracción de error que lleva a agregar /cayendo un cuarto de período de vez en cuando. Afortunadamente, el reloj de puntos del OP es bastante lento en comparación con las capacidades de FPGA, probablemente puedan obtener 8-10x.
@ChrisStratton Lo había pensado un poco. También parece una opción viable. Sé que algunos PLL admiten empujar dinámicamente la fase. Básicamente, uno simplemente encontraría los números de multiplicación / división de PLL que estaban más cerca de ser un múltiplo de HSYNC y luego usaría la lógica de contador de sobremuestreo (como se indicó anteriormente) para empujar la fase. Eso podría tener algunas ventajas en el sentido de que las otras partes del diseño se vuelven más fáciles cuando uno tiene un reloj de píxeles real para trabajar fuera del PLL.

Sería útil pensar un poco en cómo una tarjeta de video produce realmente sus señales de salida.

Véase, por ejemplo, una línea de modelos XFree86. Aquí hay uno para 1024x768 @ 60 Hz (no entrelazado) de una herramienta generadora en línea , los detalles son específicos de la implementación, pero la idea se mantiene esencialmente en todas las computadoras y modos de video.

Dot Clock Frequency:     60.80 MHz 
Modeline "1024x768" 60.80  1024 1056 1128 1272   768  768  770  796

Tiene un reloj de píxeles, una región de video activo, una señal de sincronización definida como su inicio y final, y un número total de relojes en un período de línea, en este ejemplo 1272. Todo esto se expresa en unidades de relojes de píxeles, que es decir que todo se remonta al reloj de píxeles y lo hace de una manera digitalmente consistente.

Entonces, para un modo de video dado en una computadora dada, las proporciones son estables, es solo la velocidad del reloj de píxeles la que tiene una ligera desviación con la temperatura, el envejecimiento, etc.

Básicamente, si pudiera conocer los números del modelo, entonces podría dividir su propio oscilador de reloj de píxeles por el número correcto de relojes para que coincida la señal de sincronización (1272 en el ejemplo anterior), y así tener un PLL que bloquea su reloj de píxeles a la tarjeta de vídeo fuente. Todo lo que tiene que hacer es contar el número correcto de píxeles hasta el borde izquierdo de la región activa.

¿Cómo podrías encontrar los números de modelo? Bueno, usted personalmente probablemente podría buscarlos.

Lo que sospecho que hace un monitor moderno pixelado (LCD, etc.) impulsado por una fuente analógica es hacer algo así como una "búsqueda" cuando presiona el botón de sintonización de imagen. Probablemente no sea difícil adivinar la resolución horizontal y puede medir la duración del video activo. Luego, puede medir la relación entre el período horizontal general y el video activo y, a partir de eso, sabe el número total aproximado de relojes de píxeles en una línea de modelo; por ejemplo, en mi ejemplo, 1272 determinado en proporción de tiempo a 1024. PLL en la conjetura de 1272 (o por ahí).

Luego prueba varios números en torno a eso y hace algún tipo de comparación para ver en qué datos de muestra parecen "mejores", donde "mejor" puede definirse como algo así como mostrar el promedio más alto de diferencia de nivel de píxel a píxel consecutivo cerca de ambos lados de la pantalla, lo que indica que el muestreo está bien alineado con la mitad de los períodos de píxeles y no captura las transiciones intermedias entre ellos, y lo hace en toda la pantalla de manera que coincida tanto en fase como en frecuencia. O tal vez solo verifica que la región activa tenga exactamente el número correcto de relojes de píxeles de ancho. Pero si puede permitirse generar un reloj que sea algo así como 3x-6x el reloj de píxeles real,

Probablemente, este análisis es algo que haría con el software en un núcleo de procesador (interno o externo a la FPGA) que puede introducir registros que controlan su máquina de estado de captura y ejecutar estadísticas que no son en tiempo real en un búfer de línea congelado; por ejemplo, básicamente trata el hardware de captura como un alcance digital.