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 aparte:

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 en NRZI (por lo tanto, 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 un 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, lo que proporciona suficiente tiempo para que el bus de datos se estabilice; el bus de datos se muestrea directamente sin riesgo de metastabilidad:

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 se compila y funciona bien cuando se sintetiza en un FPGA Cyclone II. Sin embargo, TimeQuest informa sobre las infracciones de la configuración y el 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 instalador trabaja más duro en   Caminos con la peor holgura. Si arreglas estos caminos, el instalador podría mejorar   las otras rutas de tiempo que fallan en el diseño.

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

Estoy bastante seguro de que set_multicycle_path es el comando SDC (Restricción de diseño de la sinopsis) adecuado, ya que las líneas de datos tendrán varios ciclos del reloj de destino para estabilizar, pero no puedo encontrar ningún ejemplo completo con 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 tiempo SDC para los 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 en la otra dirección, con 100 MHz src_clk y 36 MHz dest_clk.

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

    
pregunta Ben Voigt

4 respuestas

9

No tengo experiencia con Quartus, así que trata esto como un consejo general.

Al trabajar en rutas entre dominios de reloj, las herramientas de tiempo expanden los relojes al mínimo común de sus períodos y seleccionan el par de bordes más cercano.

Para las rutas desde 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. ¡Eso es efectivamente una restricción de 900 MHz para esos caminos! Dependiendo del redondeo (o de 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_clk y slow_clk , ya que creo que es más claro para la ilustración.

Opción 1: deshabilitar la sincronización con set_false_path

La solución más fácil es usar set_false_path para desactivar 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 los datos demasiado en relación con la señal de control, entonces el sincronizador no funcionará. Sin embargo, dado que no hay ninguna lógica en la ruta, es poco probable que se viole la restricción de tiempo. set_false_path se usa comúnmente para este tipo de estructura, incluso en ASIC, donde la compensación entre esfuerzo y riesgo por fallas de baja probabilidad es más cautelosa que para las FPGA.

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

Puede permitir tiempo adicional para ciertas rutas con set_multicycle_path . Es más común usar rutas de varios ciclos con relojes estrechamente relacionados (por ejemplo, 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 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 ajuste de -hold con un número uno menor que la restricción de configuración casi siempre es necesario al configurar rutas de múltiples ciclos, para más información, vea más abajo.

Para restringir las rutas en la otra dirección de manera similar (relajando la restricción en un período del reloj más rápido), cambie de -end a -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_path pero evita tener que pensar en las relaciones de borde y el efecto en 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 vincular esto con set_min_delay para cheques retenidos, o dejar el cheque retenido predeterminado en su lugar. También puede hacer set_false_path -hold para deshabilitar los cheques en espera, si su herramienta lo admite.

Detalles sangrientos de la selección de borde para rutas de múltiples ciclos

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

1     2     3
4   5   6   7

La comprobación de configuración predeterminada utiliza los bordes 2 y 6. La comprobación de retención predeterminada utiliza los bordes 1 y 4.

La aplicación de una restricción de varios ciclos de 2 con -end ajusta la configuración predeterminada y los controles de espera para usar el siguiente borde después de lo que estaban usando originalmente, lo que significa que el control de configuración ahora usa los bordes 2 y 7 y el control de retención usa los bordes 1 y 5. Para dos relojes a la misma frecuencia, este ajuste tiene sentido: cada lanzamiento de datos se corresponde con una captura de datos, y si el borde de captura se mueve hacia afuera en uno, la verificación de espera también debe moverse en 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í, un control de espera que usa los bordes 1 y 5 no es deseable, ya que la única forma de solucionarlo es agregar un ciclo completo de demora 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 retención de cheques 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 resultará en 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.

    
respondido por el Andy
2

No sé la respuesta para Altera, pero en Xilinx Land puede configurar el retraso de un dominio de reloj a otro. Tendrá que calcular 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 cualquiera de las dos señales (incluida la señal de control), y puede calcular si su circuito de sincronización podrá manejarlo.

set_mulicycle_path no es lo correcto a usar porque normalmente se trataría de casos en los que tanto el origen como el destino están en el mismo dominio de reloj. Nuevamente, me baso en mi experiencia con Xilinx para que su kilometraje pueda variar.

    
respondido por el user3624
1

Creo que es seguro colocar un set_false_path sobre el sincronizador.

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

    
respondido por el 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 ningún lugar cerca del punto en el que están bloqueadas, el software no lo sabe. Su mejor opción es probablemente decirle al software explícitamente que las señales entrantes del bus están sincronizadas con el reloj del bus, y deshabilitar las optimizaciones antes del lugar donde realmente las traba (un optimizador teóricamente podría reemplazar su circuito con uno que sería equivalente) Si las entradas realmente fueran sincrónicas, pero que se podrían lanzar para un bucle si cambian en ciclos de reloj, el circuito que dibujó no se preocuparía).

    
respondido por el supercat

Lea otras preguntas en las etiquetas