01signal.com

Estrategias para el cierre de temporización

Esta página pertenece a una serie de páginas sobre temporización (timing). Las páginas anteriores explicaron la teoría detrás de los cálculos de temporización, analizaron la restricción del periodo de reloj e introdujeron el cierre de temporización (timing closure). Pero, ¿y si has intentado hacerlo bien y aun así tienes un problema de temporización? Esta página intenta responder a esa pregunta.

Introducción

En la página anterior intenté convencerte de que no existe un método único para resolver un problema de cierre de temporización. A veces es correcto centrarse en el camino crítico (critical path), y a veces no lo es. A veces el problema puede resolverse fácilmente con un cambio sencillo en la configuración de la herramienta, y a veces es mucho más difícil que eso. No hay sustituto para emplear toda la experiencia y el criterio que tengas con el fin de llegar a la causa raíz del problema. No hay manera de resumir el cierre de temporización con una lista de comprobación.

Y sin embargo, a menudo ayuda tener una lista de estrategias posibles. Así que en esta página he reunido algunos temas que merece la pena considerar cuando te enfrentas a un problema de temporización. Si has llegado aquí porque tienes un problema concreto de temporización que resolver, es posible que una de estas ideas te conduzca a la solución. Pero no esperes que tu solución esté escrita aquí literalmente.

Ten también en cuenta que esta serie de páginas no termina aquí. He elegido hablar del cierre de temporización antes que de muchos otros temas para motivar al lector. Sin embargo, la información de las páginas posteriores también es relevante.

Por la misma razón, la discusión sobre las restricciones de temporización de E/S se pospone para más adelante. Por ahora me centro en los caminos (paths) que comienzan y terminan dentro de la FPGA.

Así que aquí van algunas ideas para tener en cuenta en relación con el cierre de temporización.

Idea n.º 1: Arreglar el diseño lógico

Esta es siempre la solución menos atractiva. Lo es en particular si ya se sabe que el diseño funciona correctamente. No quieres cambiar algo que funciona. Y sin embargo, a menudo la razón fundamental del problema es que el código Verilog no se escribió con la suficiente calidad para el rendimiento requerido. Un cambio en el diseño lógico resuelve el problema de una vez por todas, en lugar de enfrentarte a dificultades continuas.

En la página anterior hay algunas sugerencias para escribir lógica rápida. Y conviene repetirlo: ten siempre presente la temporización durante el proceso de desarrollo. Es mucho más difícil corregir problemas de temporización que escribir bien el código Verilog desde el principio.

Idea n.º 2: Reducir el fan-out

Cuando una red (net) tiene un fan-out alto, el retardo de propagación (propagation delay) aumenta por dos razones principales:

Si se usa un reset síncrono (synchronous reset) en el diseño, es probable que esa señal tenga un fan-out alto. Este tema se trata en una página aparte.

Sin embargo, cualquier señal que llegue a muchos elementos lógicos puede causar problemas de temporización por un fan-out alto. A veces ese fan-out alto es evidente (p. ej., señales de habilitación de reloj (clock enable)), y a veces no es tan fácil preverlo. Las herramientas de FPGA suelen ayudar enumerando las redes con mayor fan-out.

Hay dos métodos para mantener el fan-out bajo:

Claramente, ambos métodos llegan al mismo resultado: el registro con fan-out alto se replica en varios registros. Entonces, si las herramientas pueden hacerlo automáticamente (con el primer método), ¿por qué molestarse en hacerlo manualmente (como en el segundo)?

El segundo método requiere más esfuerzo, pero tiene una ventaja significativa: es posible replicar el registro de manera razonada. Ten en cuenta que el objetivo no es solo reducir el fan-out. También es importante que la salida de cada registro se distribuya a elementos lógicos situados en una región pequeña del tejido lógico. De lo contrario, los retardos de enrutado serán grandes debido a la distancia física. Así que si el código Verilog se escribe pensando en el fan-out, es posible asegurar conexiones cortas entre los elementos lógicos. Esto se demuestra con una señal de reset síncrono en otra página.

Por el contrario, si las herramientas de FPGA se encargan de replicar los registros, el resultado puede no ser tan eficiente. La mejora del retardo de enrutado depende del algoritmo que decide cómo se utiliza cada registro replicado. La calidad del resultado depende de la herramienta de FPGA utilizada.

Observa que, por defecto, cuando el sintetizador detecta dos registros que se comportan exactamente igual, los fusiona automáticamente en un solo registro. Por tanto, si un registro se replica en el código Verilog, el sintetizador sustituirá todas las réplicas por un único registro. Esto suele ocurrir incluso si los registros equivalentes están en módulos distintos. Para evitar esa fusión, hay que desactivar explícitamente esta funcionalidad. Una forma habitual de conseguirlo es con atributos de síntesis, como "dont_touch", "dont_merge" o "keep".

Idea n.º 3: Revisar el floorplanning

Por defecto, la colocación de los elementos lógicos en el tejido lógico la determinan automáticamente las herramientas de FPGA (más concretamente, el colocador (placer)). Sin embargo, es posible pedir que ciertos elementos lógicos se sitúen en áreas concretas de la FPGA. También es posible pedir que un elemento lógico concreto se coloque en una posición determinada. Este tipo de peticiones se denomina floorplanning. Estas peticiones se hacen mediante restricciones de colocación, que a menudo son comandos Tcl con una sintaxis parecida a la de las restricciones de temporización (timing constraints).

En la mayoría de los casos, las restricciones de colocación dificultan el cumplimiento de las restricciones de temporización. La primera razón es obvia: cuando las opciones del colocador están limitadas, el resultado solo puede ser peor que sin limitación. Sin embargo, hay razones más concretas:

En la mayoría de los diseños, lo mejor es evitar el floorplanning y dar libertad al colocador para optimizar la ubicación de los elementos lógicos. Sin embargo, hay casos en los que las restricciones de colocación se usan con frecuencia, por ejemplo:

Para el cierre de temporización, es importante ser consciente de que las restricciones de colocación pueden ser la causa de problemas. En particular, si los retardos de enrutado son mayores de lo esperado, la causa raíz puede ser la incapacidad del colocador para optimizar las posiciones de los elementos lógicos. Recuerda que el floorplanning puede tener un efecto negativo sobre caminos (paths) que no tienen relación con los elementos lógicos cuya colocación está restringida.

Idea n.º 4: Revisar las restricciones de temporización

Las restricciones de temporización son cruciales para el funcionamiento fiable de la FPGA. Por tanto, deberían verificarse antes de la implementación del proyecto. Sin embargo, a veces las restricciones acaban siendo incorrectas. Los errores pueden hacerse evidentes durante el cierre de temporización. No debería ocurrir, pero cuando ocurre, por supuesto es mejor corregir el problema.

Hay una página completa sobre cómo revisar las restricciones de temporización. Aquí solo comentaré dos errores comunes que pueden llevar a problemas con el cierre de temporización:

Comenzando por los relojes no relacionados: el tema de los cruces de dominios de reloj (clock domain crossing) ya se ha tratado antes: hay varias razones por las que es importante que las restricciones de temporización reflejen cuáles son relojes relacionados (related clocks) y cuáles no. La razón más importante es garantizar el funcionamiento correcto de la lógica, pero el cierre de temporización también se ve afectado: si una pareja de relojes es tratada innecesariamente como relojes relacionados por las herramientas, se imponen requisitos de temporización innecesarios en los caminos entre esos dos relojes. Como resultado, las herramientas desperdician esfuerzos en esos caminos a costa de otros que sí los necesitan.

La restricción de temporización que corrige este problema se explica más adelante en esta serie de páginas.

En cuanto a los resets asíncronos: en la mayoría de los casos es necesario imponer restricciones de temporización sobre un camino que termina en un reset asíncrono. Pero a veces no hace falta. Por ejemplo, si hay garantía de que el reloj no estará activo cuando el reset pase a inactivo. Otra posibilidad es que el flip-flop que recibe el reset asíncrono tenga un mecanismo de protección frente a violaciones de temporización, igual que ocurre con un cruce de dominios de reloj. En esas situaciones, los esfuerzos de las herramientas por cumplir los requisitos de temporización no sirven para nada.

Puede ser difícil darse cuenta de que problemas de este tipo dificultan el cierre de temporización: a veces el camino crítico (critical path) no tiene nada que ver con los dos relojes tratados innecesariamente como relacionados. Si un reset asíncrono desvía los esfuerzos de las herramientas, reconocerlo es aún más difícil. En tales situaciones, intentar centrarse en el camino crítico para mejorar su temporización puede ser inútil.

Las restricciones de temporización pueden, por supuesto, estar mal de muchas otras formas. La situación descrita aquí es solo una posibilidad. Así que un problema de temporización puede ser una buena oportunidad para revisar las restricciones de temporización en general.

Idea n.º 5: Sencillamente, inténtalo otra vez

Recuerda que el proceso de colocación y enrutado (place and route) comienza repartiendo los elementos lógicos de manera bastante arbitraria sobre el tejido lógico. Luego las herramientas intentan mejorar la temporización mediante intentos repetidos. Por tanto, el éxito del proceso depende en cierta medida de la suerte. También es posible que un comportamiento ligeramente distinto del algoritmo de colocación y enrutado obtenga mejores resultados, aunque no haya una explicación lógica de por qué.

Así que si las restricciones de temporización fallan y el margen (slack) negativo es relativamente pequeño (entre el 10 y el 20% del retardo total), puede bastar con intentarlo de nuevo. Pero volver a ejecutar la implementación probablemente no servirá de nada: la mayoría del software de FPGA está diseñado para repetir con exactitud el resultado cuando se ejecuta con la misma entrada. Así que es necesario cambiar algo antes de volver a ejecutar. Ese cambio no tiene por qué estar relacionado con el camino crítico. La cuestión es evitar una repetición exacta de la implementación anterior.

Por ejemplo, en Vivado cada ejecución tiene un atributo llamado "strategy". Como su nombre indica, ese atributo controla la estrategia que aplican las herramientas durante la implementación. Cambiar ese atributo garantiza que la siguiente implementación no sea idéntica a la anterior. También es posible que otra estrategia tenga más sentido para el diseño lógico concreto.

Todas las herramientas de FPGA ofrecen posibilidades parecidas para modificar los parámetros del proceso de implementación. A menudo se puede pedir un mayor nivel de esfuerzo para alcanzar los objetivos del diseño. A veces ese mayor esfuerzo es realmente necesario, pero con frecuencia pedir más esfuerzo ayuda solo porque las herramientas hacen algo distinto.

Otra forma de evitar la repetición es hacer cambios en el código Verilog. Una vez más, el cambio no tiene por qué estar relacionado con el camino crítico. A veces basta con cambiar el nombre de un registro para obtener una implementación lo bastante distinta de la anterior.

Esta idea puede llevarse al extremo: es posible ejecutar la implementación en varios ordenadores en paralelo, cada uno con parámetros ligeramente distintos. Eso puede tener sentido cuando el precio de la FPGA es importante. En ese escenario, merece la pena dejar que los ordenadores trabajen a fondo para cumplir las restricciones de temporización en una FPGA más barata.

En resumen, este método se basa sobre todo en la suerte. Las expectativas deben ser coherentes: volver a intentarlo solo ayuda cuando las herramientas fallan de forma ocasional. Pero siempre es mejor mejorar la temporización por otras vías, si es posible.

Idea n.º 6: ¿Está la FPGA llena?

Es bastante habitual que los problemas con las restricciones de temporización comiencen cuando el nivel de ocupación de la FPGA ronda el 70%. Hay tres razones principales:

De las tres razones mencionadas, solo la tercera tiene algún tipo de solución: por ejemplo, puede ayudar decidir manualmente qué lógica usa los bloques de RAM de la FPGA y otros recursos similares. Aparte de eso, la única solución para una FPGA llena es elegir una más grande, aunque no siempre es posible. Por tanto, es importante prever que el cierre de temporización será más difícil a medida que se añada más lógica.

Idea n.º 7: ¿Quizá necesitas otra FPGA?

A veces no queda más remedio que admitir que la FPGA no está a la altura. Si la misma FPGA está disponible con un grado de velocidad superior, la solución puede ser decidir subir a una FPGA más rápida. Esta decisión aumenta el coste de compra, por supuesto, pero también puede tener otra consecuencia menos esperada: puede haber escasez de FPGA con el grado de velocidad superior. Aunque esas FPGA más rápidas abunden en un momento dado, las FPGA rápidas suelen ser las primeras en desaparecer del mercado cuando la demanda supera a la oferta.

Es bastante natural: las FPGA más rápidas son las que superaron mejor los tests, y siempre pueden usarse en lugar de las más lentas. A veces el fabricante no consigue producir las FPGA rápidas, y a veces hay un gran consumidor que compra todo lo que puede usar.

Así que, si trabajas en un producto destinado a fabricarse durante mucho tiempo, prefiere siempre el grado de velocidad más bajo con el que tu diseño pueda funcionar. Esto es cierto incluso aunque el dinero no sea un problema.

Un tipo de actualización completamente distinto es elegir una FPGA de una familia más reciente. O quizá elegir una FPGA de otro fabricante. Ese cambio es más drástico, pero debería considerarse si el proyecto está en sus primeras fases. Todos tendemos a enamorarnos de las herramientas y los componentes que nos resultan familiares. Pero cuando todo resulta demasiado familiar, es buen momento para mirar a nuestro alrededor en busca de alternativas.

Dicho esto, los ingenieros de FPGA con experiencia saben que elegir la FPGA más reciente y sus herramientas es una apuesta arriesgada. Pero a menudo hay una alternativa bastante consolidada que es mucho mejor que la FPGA elegida actualmente. En tal situación, es mejor salir de la zona de confort y probar algo nuevo.

Idea n.º 8: Reducir el rango de temperatura

Hay una razón por la que he puesto esta posibilidad casi al final: es la solución más fea de todas. Pero a veces no hay otra opción.

Por defecto, la aplicación de las restricciones de temporización por parte de las herramientas garantiza que la FPGA funciona de forma fiable en todo el rango de temperatura definido en la hoja de datos. Algunas herramientas de FPGA permiten elegir otro rango de temperatura para un proyecto (por ejemplo, Quartus tiene un atributo llamado "MAX_CORE_JUNCTION_TEMP" para ese fin). Eso puede usarse para indicar a las herramientas que no hace falta soportar el rango completo de temperatura.

En general, los retardos de los elementos lógicos de la FPGA aumentan a medida que sube la temperatura. Si se reduce la temperatura máxima, los valores de los retardos en los cálculos de temporización son menores. Eso hace más fácil cumplir los requisitos de tsetup. A veces es la única manera de que las herramientas cumplan las restricciones de temporización.

Es importante entender los riesgos de usar este método. En particular, hay que tener en cuenta que hablamos de la temperatura de unión. Es decir, la temperatura sobre el silicio de la FPGA, no la temperatura ambiente.

Así que cuando la temperatura máxima sea de 85 °C, no significa que la FPGA funcione dentro de un horno a esa temperatura. Esa temperatura también puede alcanzarse a temperatura ambiente (25 °C), en particular si la FPGA no tiene disipador. Siempre hay una diferencia entre la temperatura de unión y la ambiente. La magnitud de esa diferencia depende del consumo de potencia de la FPGA y de la solución de refrigeración.

Si trabajas en un producto comercial, ten en cuenta que la temperatura ambiente de la FPGA puede ser bastante más alta que la temperatura de la sala. En particular, si la FPGA está dentro de una caja con mala circulación de aire, la temperatura interior puede superar con creces la temperatura exterior. Para empeorar las cosas, se espera que la mayoría de los productos electrónicos funcionen entre 0 °C y 40 °C (aproximadamente; estas cifras cambian de un producto a otro). Así que cuando se prueba el producto final a la temperatura más alta, con la FPGA dentro de la carcasa, ¿cuál es la temperatura de unión? Esa es la pregunta que hay que hacerse. Los cálculos de temporización deben basarse en esa temperatura (o en una superior).

En otras palabras, si reduces la temperatura máxima para cumplir las restricciones de temporización y todo funciona bien en el laboratorio, eso no significa nada. Recuerda que, en lo que respecta a las restricciones de temporización, el hecho de que el diseño de la FPGA funcione en el laboratorio nunca significa nada. Pero reducir la temperatura máxima es aún peor en ese sentido. Reducir el rango de temperatura sin pensar puede ser una invitación a un problema serio: la prueba final del producto antes de la fabricación, que se hace a la temperatura más alta, puede fallar, y será imposible cumplir las restricciones de temporización si se corrige el rango. La única manera de resolver ese problema será reescribir el diseño de la FPGA desde el principio.

Así que, antes de cambiar el rango de temperatura para el cierre de temporización, asegúrate de que es seguro hacerlo: haz una evaluación rigurosa del rango de temperatura de unión en todas las condiciones de funcionamiento posibles.

Observa que es imposible ampliar el rango de temperatura más allá del valor por defecto cambiando los parámetros de implementación. El rango de temperatura por defecto de las herramientas es siempre el mismo que indica la hoja de datos. Por tanto, no es posible garantizar un funcionamiento fiable de la FPGA fuera de ese rango por defecto.

Idea n.º 9: Relojes relacionados no alineados

Esta es una situación bastante esotérica y también un poco difícil de entender. Por eso la he dejado para el final.

Supongamos que hay un cruce de dominios de reloj (clock domain crossing) entre dos relojes relacionados (related clocks) que no están alineados. En otras palabras, los dos relojes derivan del mismo reloj de referencia, pero no hay ningún mecanismo que controle la desviación de reloj (clock skew) entre ellos.

Como resultado, a las herramientas les resulta más difícil cumplir los requisitos de temporización en los caminos entre esos dos relojes. Hay dos tipos posibles de dificultad (recuerda que tsetup y thold se explicaron antes):

Es importante señalar que, cuando las herramientas necesitan trabajar más de lo habitual para superar estas dificultades, puede ser a costa de optimizar otros caminos.

Sin embargo, los relojes relacionados no alineados no son un error, y a veces son inevitables. Esa situación solo significa que las herramientas tienen que trabajar más. Si se cumplen las restricciones de temporización, no hay ningún problema con el diseño. No obstante, conviene evitarlo siempre que sea posible con un esfuerzo razonable.

Observa que el error mencionado en la «Idea n.º 4» es distinto, aunque ambos errores lo ponen innecesariamente difícil a las herramientas y ambos están relacionados con el cruce de dominios de reloj.

La mejor solución para una situación con relojes relacionados no alineados es alinear esos relojes. Normalmente se hace añadiendo una PLL o añadiendo una salida de reloj a una PLL existente. El objetivo es que los dos relojes en cuestión sean salidas de la misma PLL.

Otra solución posible es tratar los relojes como no relacionados (unrelated clocks). Eso exige un cambio tanto en el diseño lógico como en las restricciones de temporización. Puede merecer la pena si no resulta demasiado difícil. Más sobre este tema más adelante.

Veremos ahora un ejemplo de un cruce de dominios de reloj entre relojes relacionados no alineados.

   wire       pll_clk;

   reg [24:0] result;
   reg [11:0] x, y, x1, y1;

   clk_wiz_0 pll_i
   (.clk_in1(clk),
    .clk_out1(pll_clk));

   always @(posedge clk)
     begin
	x1 <= x;
	y1 <= y;
     end

   always @(posedge pll_clk)
     result <= x1 * y1;

Observa que hay una PLL (clk_wiz_0). Esta PLL usa @clk como reloj de referencia, y @clk tiene una frecuencia de 250 MHz. Es la misma PLL que se mostró en el ejemplo de la parte superior de una página anterior. La frecuencia de @pll_clk es de 125 MHz.

La parte importante de este ejemplo es el cruce de dominios de reloj entre dos relojes relacionados (@clk y @pll_clk). Como solo @pll_clk lo genera la PLL, estos dos relojes no están alineados. Por tanto, hay una desviación de reloj (clock skew) en los caminos hacia @result (desde @x1 y @y1). A pesar de esa desviación, los relojes siguen siendo relojes relacionados, y las herramientas intentarán cumplir los requisitos de temporización.

Si la única razón para usar @clk es la necesidad de un reloj a 250 MHz, la solución correcta es generar otro reloj con la PLL. No es un desperdicio de recursos producir un reloj con la misma frecuencia que el de referencia. Al contrario, hacerlo ahorra mucho esfuerzo a las herramientas. Solo hay una buena razón para usar @clk directamente como se muestra en el ejemplo: cuando la lógica que usa @clk debe funcionar antes de que la PLL genere relojes utilizables.

El informe de temporización generado por Vivado es el siguiente. En este caso concreto, solo hubo un problema con el requisito de tsetup.

Slack (VIOLATED) :        -1.456ns  (required time - arrival time)
  Source:                 x1_reg[7]/C
                            (rising edge-triggered cell FDRE clocked by clk  {rise@0.000ns fall@2.000ns period=4.000ns})
  Destination:            result_reg/DSP_OUTPUT_INST/ALU_OUT[10]
                            (rising edge-triggered cell DSP_OUTPUT clocked by clk_out1_clk_wiz_0  {rise@0.000ns fall@4.000ns period=8.000ns})
  Path Group:             clk_out1_clk_wiz_0
  Path Type:              Setup (Max at Slow Process Corner)
  Requirement:            4.000ns  (clk_out1_clk_wiz_0 rise@8.000ns - clk rise@4.000ns)
  Data Path Delay:        3.012ns  (logic 2.677ns (88.878%)  route 0.335ns (11.122%))
  Logic Levels:           5  (DSP_A_B_DATA=1 DSP_ALU=1 DSP_M_DATA=1 DSP_MULTIPLIER=1 DSP_PREADD_DATA=1)
  Clock Path Skew:        -2.192ns (DCD - SCD + CPR)
    Destination Clock Delay (DCD):    0.998ns = ( 8.998 - 8.000 )
    Source Clock Delay      (SCD):    3.202ns = ( 7.202 - 4.000 )
    Clock Pessimism Removal (CPR):    0.012ns
  Clock Uncertainty:      0.148ns  ((TSJ^2 + DJ^2)^1/2) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Discrete Jitter          (DJ):    0.103ns
    Phase Error              (PE):    0.086ns
  Clock Net Delay (Source):      1.414ns (routing 0.002ns, distribution 1.412ns)
  Clock Net Delay (Destination): 1.184ns (routing 0.002ns, distribution 1.182ns)
  Clock Domain Crossing:  Inter clock paths are considered valid unless explicitly excluded by timing constraints such as set_clock_groups or set_false_path.

    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk rise edge)        4.000     4.000 r
    AG12                                              0.000     4.000 r  clk (IN)
                         net (fo=0)                   0.000     4.000    clk_IBUF_inst/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.738     4.738 r  clk_IBUF_inst/INBUF_INST/O
                         net (fo=1, routed)           0.105     4.843    clk_IBUF_inst/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.049     4.892 r  clk_IBUF_inst/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.795     5.687    clk_IBUF
    BUFGCE_X1Y2          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.101     5.788 r  clk_IBUF_BUFG_inst/O
    X2Y0 (CLOCK_ROOT)    net (fo=62, routed)          1.414     7.202    clk_IBUF_BUFGCE
    SLICE_X52Y45         FDRE                                         r  x1_reg[7]/C
  -------------------------------------------------------------------    -------------------
    SLICE_X52Y45         FDRE (Prop_HFF_SLICEM_C_Q)
                                                      0.138     7.340 f  x1_reg[7]/Q
                         net (fo=1, routed)           0.335     7.675    result_reg/A[7]
    DSP48E2_X8Y18        DSP_A_B_DATA (Prop_DSP_A_B_DATA_DSP48E2_A[7]_A2_DATA[7])
                                                      0.396     8.071 r  result_reg/DSP_A_B_DATA_INST/A2_DATA[7]
                         net (fo=1, routed)           0.000     8.071    result_reg/DSP_A_B_DATA.A2_DATA<7>
    DSP48E2_X8Y18        DSP_PREADD_DATA (Prop_DSP_PREADD_DATA_DSP48E2_A2_DATA[7]_A2A1[7])
                                                      0.182     8.253 r  result_reg/DSP_PREADD_DATA_INST/A2A1[7]
                         net (fo=1, routed)           0.000     8.253    result_reg/DSP_PREADD_DATA.A2A1<7>
    DSP48E2_X8Y18        DSP_MULTIPLIER (Prop_DSP_MULTIPLIER_DSP48E2_A2A1[7]_U[10])
                                                      0.994     9.247 f  result_reg/DSP_MULTIPLIER_INST/U[10]
                         net (fo=1, routed)           0.000     9.247    result_reg/DSP_MULTIPLIER.U<10>
    DSP48E2_X8Y18        DSP_M_DATA (Prop_DSP_M_DATA_DSP48E2_U[10]_U_DATA[10])
                                                      0.164     9.411 r  result_reg/DSP_M_DATA_INST/U_DATA[10]
                         net (fo=1, routed)           0.000     9.411    result_reg/DSP_M_DATA.U_DATA<10>
    DSP48E2_X8Y18        DSP_ALU (Prop_DSP_ALU_DSP48E2_U_DATA[10]_ALU_OUT[10])
                                                      0.803    10.214 r  result_reg/DSP_ALU_INST/ALU_OUT[10]
                         net (fo=1, routed)           0.000    10.214    result_reg/DSP_ALU.ALU_OUT<10>
    DSP48E2_X8Y18        DSP_OUTPUT                                   r  result_reg/DSP_OUTPUT_INST/ALU_OUT[10]
  -------------------------------------------------------------------    -------------------

                         (clock clk_out1_clk_wiz_0 rise edge)
                                                      8.000     8.000 r
    BUFGCE_X1Y2          BUFGCE                       0.000     8.000 r  clk_IBUF_BUFG_inst/O
                         net (fo=62, routed)          1.078     9.078    pll_i/inst/clk_in1
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT0)
                                                     -1.777     7.301 r  pll_i/inst/mmcme3_adv_inst/CLKOUT0
                         net (fo=1, routed)           0.422     7.723    pll_i/inst/clk_out1_clk_wiz_0
    BUFGCE_X1Y0          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.091     7.814 r  pll_i/inst/clkout1_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=6, routed)           1.184     8.998    result_reg/CLK
    DSP48E2_X8Y18        DSP_OUTPUT                                   r  result_reg/DSP_OUTPUT_INST/CLK
                         clock pessimism              0.012     9.010
                         clock uncertainty           -0.148     8.862
    DSP48E2_X8Y18        DSP_OUTPUT (Setup_DSP_OUTPUT_DSP48E2_CLK_ALU_OUT[10])
                                                     -0.104     8.758    result_reg/DSP_OUTPUT_INST
  -------------------------------------------------------------------
                         required time                          8.758
                         arrival time                         -10.214
  -------------------------------------------------------------------
                         slack                                 -1.456

Este informe muestra que las herramientas no consiguieron cumplir las restricciones de temporización. El camino mostrado comienza en el flanco de subida de @clk en 4 ns y termina en el flanco de subida de @pll_clk en 8 ns. El problema es el tiempo que tarda el reloj en el pin de entrada en llegar al pin de reloj del primer flip-flop: 3,2 ns. El tiempo de llegada de ese flanco es, por tanto, de 7,2 ns.

Pero @pll_clk lo genera la PLL, así que ese reloj está alineado con el pin de entrada de @clk. El retardo es, por tanto, de solo 1,0 ns. El tiempo de llegada de @pll_clk al segundo flip-flop es, pues, de 9,0 ns. Así que el tiempo que queda para el camino de datos es de 9,0 – 7,2 = 1,8 ns (aproximadamente, por la incertidumbre del reloj y otros factores). No es suficiente para una multiplicación aritmética, ni siquiera usando la unidad aritmética específica. Por tanto, no se pudieron cumplir los requisitos de temporización.

Así que en este ejemplo el reloj llega tarde al primer flip-flop debido a la desviación de reloj. Eso produce el incumplimiento del requisito de tsetup.

Observa que esto puede resolverse manipulando la alineación de @pll_clk. Por ejemplo, el reloj de referencia de la PLL puede ser la salida del buffer global de reloj que distribuye @clk. También es posible definir el desfase de la PLL para conseguir una mejor alineación. Sin embargo, son soluciones que solo deberían usarse como último recurso.

Resumen

Una vez más, estas eran solo algunas ideas que podrían ayudar a resolver un problema de cierre de temporización. Desgraciadamente, resolver un problema de este tipo puede exigir mucho más. De hecho, no hay ningún tema en el campo de las FPGA que no esté relacionado de algún modo con el cierre de temporización.

Como ya se ha dicho, la mejor estrategia es escribir el diseño lógico con cuidado desde el principio. La mejor manera de abordar el cierre de temporización es evitarlo.


Hasta este punto, esta serie de páginas ha tratado la temporización, pero no ha dicho mucho sobre las restricciones de temporización. Eso está a punto de cambiar: a partir de la página siguiente, la discusión se vuelve más técnica.

Esta página se ha traducido del inglés mediante traducción automática. En caso de duda, consulta el texto original.
Copyright © 2021-2026. All rights reserved. (dcc38493)