Restricciones de tiempo para relojes de muestreo central generados reenviados

Descripción del problema

Estoy tratando de descubrir la forma "correcta" de restringir (en formato .xdc, esto está en Vivado) un reloj síncrono de fuente reenviado que se genera (por división) a partir del reloj del sistema y se muestrea en el centro en el módulo receptor. La situación es la siguiente:

Tenemos un ADC al que nuestro FPGA está enviando datos. La interfaz con el ADC es síncrona con la fuente: reenviamos un reloj junto con los datos. También se muestrea en el centro en el sentido de que generamos los datos (en la FPGA) en el flanco descendente del reloj reenviado y capturamos los datos en el flanco ascendente del reloj reenviado. Para aumentar la complejidad, este reloj reenviado se genera dividiendo el reloj del sistema. Queremos poder establecer el retraso de salida de este reloj/datos reenviados para que podamos especificar los tiempos de configuración y espera del ADC. El problema es que no estamos seguros de cómo especificar las restricciones de varios ciclos para que Vivado descubra el borde correcto de lanzamiento y captura.

En la vida real, nuestro reloj reenviado solo se divide por dos del reloj del sistema, pero queremos saber cómo hacerlo en el caso más general, por lo que estableceremos la tasa de división en ocho por el bien del ejemplo.

Visualización

Forma de onda que muestra reloj, reloj generado (/8) y datos. Los datos se lanzan en el flanco descendente del reloj generado y se capturan en el flanco ascendente del reloj generado:

Forma de onda que muestra reloj, reloj generado (/8) y datos.  Los datos se lanzan en el flanco descendente del reloj generado y se capturan en el flanco ascendente del reloj generado.

El gran problema es averiguar las restricciones multiciclo correctas. No parece haber una forma intuitiva de especificar que los datos se lanzan en el flanco descendente del reloj generado y son capturados por el flanco ascendente. El problema principal es que los datos son generados por el reloj del sistema : un FSM (que crea el reloj generado) garantiza que los nuevos datos solo se inicien en los bordes donde cae el reloj generado. El "reloj de lanzamiento" es, por lo tanto, el reloj del sistema, mientras que el "reloj de captura" es SCKO.

A continuación se muestra un dibujo del sistema; SDO y SCKO son salidas de la FPGA:

Un dibujo del sistema: SDO y SCKO son salidas de la FPGA.

Soluciones tentativas

Pudimos resolver con bastante facilidad la cuestión del multiciclo con respecto a la configuración; en este caso establecemos:

set_multicycle_path 4 -setup -from [get_clocks sys_clk] -to [get_clocks SCKO] -start

Esto tiene sentido: nuestro borde de captura está a 4 ciclos de nuestro borde de lanzamiento, por lo que adelantamos el tiempo de configuración en ciclos de espera. Estos 4 ciclos están en términos del reloj del sistema, por lo que nos aseguramos de usar el indicador -start para que el multiplicador de configuración esté en términos del reloj de lanzamiento.

La pregunta es: ¿qué debemos hacer para la ruta multiciclo espera y por qué?

Investigación

Para la investigación, podemos consultar UG903 de Vivado: Uso de restricciones . De particular utilidad es la sección sobre rutas de múltiples ciclos, específicamente la sección "Multiciclos entre relojes RÁPIDOS a LENTOS" en la página 117. Pero esto solo nos dice cómo manejar una ruta de datos extendida; no entendemos cómo aplicar esto a nuestro proyecto, donde debemos asegurarnos de que Vivado sepa que los datos solo se lanzan en el flanco descendente de SCKO (que NO es el reloj que los genera; sys_clk los genera, sino solo ciertos flancos ascendentes de sys_clk).

Hemos intentado pasar por diferentes multiplicadores de retención, pero no estamos seguros de cuál es la forma correcta de hacerlo. Para nuestro ejemplo de "dividir por 2", descubrimos que establecer un multiplicador de retención de 1 funcionaría: el informe de ruta parecía indicar algo que podíamos convencernos de que era la respuesta correcta (es decir, inició el "reloj de origen" en un período después de el "reloj de lanzamiento": esto correspondería a la ruta de lanzamiento que comienza en el flanco descendente del reloj reenviado y la ruta de captura que comienza en el flanco ascendente del reloj reenviado.

También hemos analizado varios parámetros para nuestro reloj generado, retardo de salida y restricciones de ruta de varios ciclos establecidas. Hemos visto el indicador "-clock_fall", pero esto le dice a la herramienta que queremos capturar en el flanco descendente (cuando en realidad necesitamos decirle que se inicie en el flanco descendente, pero con un reloj diferente). También hemos analizado "-rise" y "-fall", pero no hemos podido averiguar realmente qué hacen o qué efecto tienen.

Pregunta

En resumen: ¿cuál es la restricción multiciclo correcta para poner aquí y por qué?

La solución para dividir por ocho es completamente diferente de la solución para dividir por dos, porque el cruce del dominio del reloj para dividir por ocho es mucho más simple. Para dividir por dos, solo usaría un FIFO de reloj dual y ejecutaría una calibración rápida al inicio para mover la fase del reloj de muestreo al centro.

Respuestas (1)

Queremos poder establecer el retraso de salida de este reloj/datos reenviados para que podamos especificar los tiempos de configuración y espera del ADC.

De la explicación anterior, necesita generar un retraso en las líneas de datos y reloj, tengo dos soluciones para este problema.

1) utilizando recursos de retardo de entrada (IDELAY) u ODELAY https://www.xilinx.com/support/documentation/user_guides/ug471_7Series_SelectIO.pdf

en el diseño de alta velocidad, algunos retrasos en PCB se compensan con búferes de retraso (estos tienen alguna pestaña de retrasos)

2) la segunda solución es sincronizar el reloj FPGA con la retroalimentación del reloj ADC (se genera en PLL). ¡Creo que no es fácil ni útil para su caso!

Editado:

Creo que en FPGA primero debe considerar qué circuito necesita , luego decirle al compilador que lo genere. Xilinx dijo: "ruta lógica que requiere más de un ciclo de reloj para que los datos se estabilicen en el punto final. Si el circuito de control del punto de inicio y final de la ruta lo permite, Xilinx recomienda que utilice la ruta multiciclo".

Ahora, en su ejemplo, donde tiene dos señales del lado FPGA al ADC (no dice requisitos de baja potencia, el ciclo múltiple ayuda a este objetivo), Xilinx dijo "datos para estabilizar" porque esto puede generar metaestabilidad. con reloj y pin de datos de FPGA a ADC, entonces el retraso entre el borde del reloj y los datos estables tiene dos casos, el primero mayor que un ciclo del reloj o menor que, para el último caso, IDELAY está bien, pero si tiene más de un ciclo Demora (cuando le preocupe) usted compensa su demora, configurando un dato en el último ciclo de reloj o dos relojes o más, luego la demora del sub-reloj compensa con (IDELAY).

Creo que su caso no necesita "set_multicycle_path" . Si desea baja potencia, entonces puede preocuparse por "Multicycles in Single Clock Domain" . Si tiene un pin que recibe una señal del lado del ADC, cuando el ADC no es estable menos que el ciclo del reloj, debe intentar "Multiciclos en el dominio de un solo reloj" por motivos de metaestabilidad .

si su problema no es el retraso, un diagrama del sistema y la dirección de la señal puede ayudar a comprender mejor el problema.
Ese no es realmente el problema, lo siento. Mi problema radica en qué comando .xdc debo escribir para restringirlo adecuadamente, no en la estructura del sistema en sí. Agregaré un diagrama del sistema a la publicación original.
@YSl, ¿puedo preguntarle por qué aplica esta restricción? (Creo que un diseño de bajo consumo y mejorar la seguridad por ejemplo), ¿Qué estás esperando? (en circuito) ahora, creo que aguantar no es importante,
@YSl ¿Por qué no incluye el pin de entrada de ADC, que está relacionado con set_multicycle_path, no el pin de salida que acaba de enviar en él? Si me dice qué espera agregar al circuito original, puedo explicarle el tiempo.
Incluimos esta restricción porque queremos asegurarnos de que nuestra ruta de salida cumpla con los tiempos de configuración y espera (con retrasos de seguimiento) del ADC. No estoy seguro de lo que quiere decir con el pin de entrada del ADC: la única relevancia que tiene para las restricciones de FPGA es especificar cuáles son los números de retraso de salida. Queremos entender cómo hacer mejor las restricciones multiciclo en general, razón por la cual esta pregunta se refiere a una ruta -divide_by 8 en lugar de la ruta real -divide_by 2 que tenemos.