restricción de tiempo para circuitos sincronizadores de bus

10

Tengo un circuito sincronizador de bus para pasar un registro amplio a través de dominios de reloj.

Proporcionaré una descripción simplificada, omitiendo la lógica de reinicio asíncrono.

Los datos se generan en un reloj. Las actualizaciones son muchas (al menos una docena) de bordes de reloj separados:

PROCESS (src_clk)
BEGIN
   IF RISING_EDGE(clock) THEN
      IF computation_done THEN
          data <= computation;
          ready_spin <= NOT ready_spin;
      END IF;
   END IF;
END PROCESS;

La señal de control para datos nuevos, que está codificada con NRZI (por lo que una palabra válida en el bus corresponde a una transición en la señal de control). La señal de control pasa a través de una cadena DFF que actúa como sincronizador.

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      ready_spin_q3 <= ready_spin_q2;
      ready_spin_q2 <= ready_spin_q1;
      ready_spin_q1 <= ready_spin;
   END IF;
END PROCESS;

El circuito sincronizador introduce un breve retraso, que proporciona mucho tiempo para que el bus de datos se estabilice; el bus de datos se muestrea directamente sin riesgo de metaestabilidad:

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      IF ready_spin_q3 /= ready_spin_q2 THEN
         rx_data <= data;
      END IF;
   END IF;
END PROCESS;

Esto compila y funciona bien cuando se sintetiza en un FPGA Cyclone II. Sin embargo, TimeQuest informa violaciones de configuración y tiempo de espera, porque no reconoce el sincronizador. Peor aún, el manual de Quartus dice

Concéntrese en mejorar los caminos que muestran la peor holgura. El Fitter trabaja más duro en caminos con la peor holgura. Si arregla estas rutas, el Fitter podría mejorar las otras rutas de sincronización que fallan en el diseño.

Por lo tanto, quiero agregar las restricciones de tiempo adecuadas a mi proyecto para que Quartus gaste su esfuerzo de Fitter en otras áreas del diseño.

Estoy bastante seguro de que set_multicycle_pathes el comando SDC (Restricción de diseño de sinopsis) adecuado, ya que las líneas de datos tendrán múltiples ciclos del reloj de destino para estabilizarse, pero no puedo encontrar ningún ejemplo completo usando este comando para describir la lógica de cruce del dominio del reloj .

Realmente agradecería alguna orientación sobre cómo escribir restricciones de sincronización SDC para sincronizadores. Si ve un problema con este enfoque, hágamelo saber también.


Detalle del reloj:

Generador de reloj externo: dos canales, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz y relacionados).

Altera PLL: src_clk = refclk * 9/5 = 36 MHz

Altera PLL: dest_clk = refclk2 * 10 = 100 MHz

También tengo datos que van en la otra dirección, con 100 MHz src_clk y 36 MHz dest_clk.


TL; DR: ¿Cuáles son las restricciones de sincronización SDC correctas para el código anterior?

Ben Voigt
fuente
1
Esto sería mejor en el sitio de diseño de FPGA propuesto, pero esa propuesta aún no ha llegado a la versión beta.
Ben Voigt
¿Puedes publicar las definiciones de reloj para src_clk y dest_clk? ¿Están relacionados de alguna manera (múltiplos sincrónicos)? Si son relojes no relacionados, es típico usar set_false_path en esta situación.
Andy
@Andy: agregué algunos de los detalles. Gracias por ayudar con esto.
Ben Voigt

Respuestas:

9

No tengo experiencia con Quartus, así que trátelo como un consejo general.

Al trabajar en rutas entre dominios de reloj, las herramientas de temporización expanden los relojes al múltiplo menos común de sus períodos y seleccionan el par de aristas más cercano.

Para rutas de un reloj de 36 MHz (27.777 ns) a un reloj de 100 MHz (10 ns), si hice mis cálculos rápidos correctamente, el par más cercano de flancos ascendentes es 138.888 ns en el reloj de origen y 140 ns en el reloj de destino. ¡Esa es efectivamente una restricción de 900 MHz para esos caminos! Dependiendo del redondeo (o para relojes sin relación), podría salir peor que eso.

Hay al menos tres formas de escribir restricciones para esta estructura. Voy a llamar a los relojes fast_clky, slow_clkcomo creo, es más claro como ilustración.

Opción 1: desactivar el tiempo con set_false_path

La solución más fácil es usar set_false_pathpara deshabilitar el tiempo entre los relojes:

set_false_path -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_false_path -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Esto no es estrictamente correcto, ya que existen requisitos de tiempo para que el sincronizador funcione correctamente. Si la implementación física retrasa demasiado los datos en relación con la señal de control, entonces el sincronizador no funcionará. Sin embargo, dado que no hay ninguna lógica en el camino, es poco probable que se viole la restricción de tiempo. set_false_pathse usa comúnmente para este tipo de estructura, incluso en ASIC, donde el esfuerzo frente a la compensación de riesgo por fallas de baja probabilidad es más cauteloso que para FPGA.

Opción 2: relajar la restricción con set_multicycle_path

Puede permitir tiempo adicional para ciertas rutas con set_multicycle_path. Es más común utilizar rutas multiciclo con relojes estrechamente relacionados (p. Ej., Relojes interactivos 1X y 2X), pero funcionará aquí si la herramienta lo admite lo suficiente.

set_multicycle_path 2 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -setup
set_multicycle_path 1 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -hold

La relación de borde predeterminada para la configuración es de ciclo único, es decir set_multicycle_path 1. Estos comandos permiten un ciclo más del reloj de punto final ( -end) para las rutas de configuración. El -holdajuste con un número uno menos que la restricción de configuración casi siempre es necesario cuando se configuran rutas de ciclo múltiple, para más información, ver más abajo.

Para restringir rutas en la otra dirección de manera similar (relajar la restricción en un período del reloj más rápido), cambie -enda -start:

set_multicycle_path 2 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -setup
set_multicycle_path 1 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -hold

Opción 3: especifique el requisito directamente con set_max_delay

Esto es similar al efecto de set_multicycle_pathpero ahorra tener que pensar a través de las relaciones de borde y el efecto sobre las restricciones de retención.

set_max_delay 10 -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_max_delay 10 -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Es posible que desee emparejar esto con los set_min_delaycontroles de retención, o dejar el control de retención predeterminado en su lugar. También puede hacer set_false_path -holdpara deshabilitar las comprobaciones de retención, si su herramienta lo admite.


Detalles sangrientos de selección de bordes para rutas de varios ciclos

Para comprender el ajuste de retención que se combina con cada ajuste de configuración, considere este ejemplo simple con una relación 3: 2. Cada dígito representa un borde ascendente del reloj:

1     2     3
4   5   6   7

La verificación de configuración predeterminada usa los bordes 2 y 6. La verificación de retención predeterminada usa los bordes 1 y 4.

La aplicación de una restricción de 2 ciclos múltiples -endajusta la configuración predeterminada y las comprobaciones de retención para usar el siguiente borde después de lo que estaban usando originalmente, lo que significa que la verificación de configuración ahora usa los bordes 2 y 7 y la verificación de retención usa los bordes 1 y 5. Para dos relojes a la misma frecuencia, este ajuste tiene sentido: cada lanzamiento de datos corresponde con una captura de datos, y si el borde de captura se mueve por uno, la verificación de retención también debería moverse por uno. Este tipo de restricción podría tener sentido para dos ramas de un solo reloj si una de las ramas tiene un gran retraso. Sin embargo, para la situación aquí, no es deseable una verificación de retención utilizando los bordes 1 y 5, ya que la única forma de solucionarlo es agregar un ciclo completo de retraso de reloj en la ruta.

La restricción de retención de varios ciclos de 1 (para retención, el valor predeterminado es 0) ajusta el borde del reloj de destino uesd para las comprobaciones de retención hacia atrás en un borde. La combinación de MCP de configuración de 2 ciclos y restricciones de MCP de retención de 1 ciclo dará como resultado una verificación de configuración con los bordes 2 y 7, y una verificación de retención con los bordes 1 y 4.

Andy
fuente
2

No sé la respuesta para Altera, pero en Xilinx Land puede establecer el retraso de un dominio de reloj al siguiente. Tendrá que resolver las matemáticas (depende del diseño), pero generalmente es el más corto de los dos períodos de reloj. Piense en este momento como el sesgo máximo entre dos señales cualquiera (incluida su señal de control), y puede determinar si su circuito de sincronización va a poder manejarlo.

set_mulicycle_path no es lo correcto, ya que normalmente se trataría de casos en que tanto el origen como el destino están en el mismo dominio de reloj. Nuevamente, lo estoy basando en mi experiencia con Xilinx, por lo que su millaje puede variar.


fuente
1

Creo que es seguro poner un set_false_path sobre el sincronizador.

También puede poner "set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO" en el qsf para ayudar a Quartus a detectar el sincronizador.

fbo
fuente
Como se veria eso? set_false_path -from ready_spin -to ready_spin_q2? Y set_false_path -from data -to rx_data?
Ben Voigt
set_false_path -from src_clk -to ready_spinNo estoy seguro de que sea apropiado colocar la ruta falsa en los datos, ya que no la está sincronizando.
fbo
0

Sospecho que el problema es que, si bien es posible que sepa que las señales del bus no van a cambiar en ninguna parte cerca del punto donde están bloqueadas, el software no lo sabe. Su mejor opción es probablemente decirle al software explícitamente que las señales de bus entrantes están sincronizadas con el reloj del bus, y deshabilitar cualquier optimización antes del lugar donde realmente las bloquea (un optimizador teóricamente podría reemplazar su circuito con uno que sería equivalente si las entradas realmente fueran síncronas, pero que podrían lanzarse en un bucle si cambian en los ciclos de reloj que el circuito que dibujó no le importaría).

Super gato
fuente
¿No set_multicycle_pathsería la forma de decirle al sintetizador / analizador de tiempo con qué frecuencia pueden cambiar las señales de origen? Y no estoy seguro de qué quieres decir con "reloj de bus", hay un bus de señal que cruza dominios de reloj, entonces, ¿a qué reloj llamas "reloj de bus"? Creo que tienes razón en que aún podría haber metaestabilidad si el sintetizador introduce fallas durante los períodos en los que no estoy actualizando data. Supongo que podría instanciar específicamente bloques DFF allí :(
Ben Voigt
@BenVoigt: Creo que "set_multicycle_path" se usa con más frecuencia para decirle al validador de tiempos que una cadena de lógica combinatoria entre dos puntos de enclavamiento debería tomar N (Tc) -Ts-Tp (N veces el tiempo del ciclo menos el tiempo de muestra menos el enclavamiento tiempo de propagación) en lugar de solo Tc-Ts-Th. No sé cómo tal cosa interactuaría con el enclavamiento por diferentes relojes.
supercat