Restricciones de tiempo ASIC a través de SDC: ¿Cómo especificar correctamente un reloj dividido por ondulación?

Introducción

Habiendo encontrado información múltiple, a veces contradictoria o incompleta en Internet y en algunas clases de capacitación sobre cómo crear restricciones de tiempo en formato SDC correctamente, me gustaría pedir ayuda a la comunidad de EE con algunas estructuras generales de generación de relojes que he encontrado.

Sé que hay diferencias sobre cómo se implementaría una determinada funcionalidad en un ASIC o FPGA (he trabajado con ambos), pero creo que debería haber una forma general y correcta de restringir el tiempo de una estructura determinada , independientemente de la tecnología subyacente; avíseme si me equivoco.

También hay algunas diferencias entre las diferentes herramientas para la implementación y el análisis de tiempo de diferentes proveedores (a pesar de que Synopsys ofrece un código fuente del analizador SDC), pero espero que sean principalmente un problema de sintaxis que se puede consultar en la documentación.

Consulte también la pregunta relacionada Restricciones de tiempo ASIC a través de SDC: ¿Cómo especificar correctamente un reloj multiplexado?

Pregunta

Se trata del siguiente divisor de reloj de ondulación, que es parte del módulo clkgen , que es parte de un diseño más grande que utiliza los relojes generadores:

Divisor de reloj ondulado

La generación de clk0parece ser relativamente sencilla:

create_clock [get_pins clkgen/clk0] -name baseclk -period 500

Aunque no estoy tan seguro acerca de los comandos SDC para los relojes generados, divididos clk2y clk4: clk8¿Cómo se deben especificar las opciones de origen y destino ? Mi pensamiento inicial fue que el objetivo es el pin de salida en la celda generadora de reloj, la fuente está lo más cerca posible del objetivo:

create_generated_clock -name div2clk -source [get_pins clkgen/divA/clk] -divide_by 2 [get_pins clkgen/divA/q]

La fuente también podría ser el pin de entrada del reloj del módulo:

create_generated_clock -name div2clk -source [get_pins clkgen/clk0] -divide_by 2 [get_pins clkgen/divA/q]

O el reloj fuente previamente definido , como se sugiere aquí :

create_generated_clock -name div2clk -source [get_clocks baseclk] -divide_by 2 [get_pins clkgen/divA/q]

...lo que también plantea la cuestión de si las opciones de origen o de destino deben ser distintas de get_pins, como get_nets, get_registerso get_ports.

clk2Para mantener el ejemplo lo más general posible , supongamos que los relojes generados clk4podrían clk8estar impulsando otros registros potencialmente interactivos (cruce de dominio de reloj) (que no se muestran en el esquema).

Creo que las restricciones para clk4y clk8deberían ser obvias una vez que sepamos cómo clk2se escribe la restricción.

La instancia X1 (un búfer simple) en el esquema es solo un marcador de posición para resaltar el problema de en qué parte de la red de propagación del reloj se debe configurar la opción de fuentecreate_generated_clock , ya que las herramientas automáticas de lugar y ruta generalmente son libres de colocar búferes en cualquier lugar (como como entre los pines divA1/qy ).divB1/clk

Respuestas (1)

Diría que la regla general es: configure el puerto de entrada del módulo superior o el pin Q de un flip-flop interno como la fuente del reloj generado.

Ejemplo de código Verilog:

module top (

input clk,
input rst,

...

);

...

always @(posedge clk or negedge rst)
begin
if (rst == 1'b0) 
    div_2_clk = 1'b0;
else
    div_2_clk = ~div_2_clk;           
end

...

endmodule

Ejemplo de código SDC:

create_clock -name clk -period 5 [get_port clk]
...
create_generated_clock -name slow_clk -source [get_port clk] -divide_by 2 [get_pins div_2_clk_reg/Q]

No probé la sintaxis anterior. También tenga en cuenta la extensión _regagregada al nombre RTL de la señal: esta es la extensión agregada por la herramienta de síntesis cuando detecta que la señal debe estar representada por un flip-flop. Esta extensión puede variar entre herramientas (no lo sé con certeza).

Si usa cualquier envoltorio RTL alrededor de flip-flops, configure la fuente de los relojes generados para que sea el pin Q interno del flip-flop, no el pin de salida del envoltorio.

Si sigue estas reglas simples, no necesita preocuparse por los búfer agregados por las herramientas de síntesis o P&R.

¡Gracias por tu respuesta! ¿Eso significa que el analizador de tiempo agregará los retrasos de la ruta (y el posible búfer insertado) a la latencia de los relojes (generados)? Por lo tanto, ¿debería ser mi primera línea SDC create_clock [get_ports clk0](suponiendo clk0que sea el puerto de nivel superior)? Si pudiera incorporar eso en su respuesta y también incluir al menos un ejemplo completo de la create_generated_clockdeclaración, ¡me encantaría aceptarlo!
@FriendFX, agregué algunos fragmentos de código, pero trátelos con cuidado, no están verificados.
gracias por el fragmento de SDC (no necesitaba el Verilog). Para los create_*clockcomandos, ¿eso significa que el analizador de tiempo agregará los retrasos de la ruta (y el posible búfer insertado) a la latencia de los relojes (generados)?
@FriendFX, ¿qué quiere decir con "la latencia del reloj (generado)"? ¿Latencia con respecto a qué? ¿Su reloj fuente? Si es así, entonces probablemente esté interesado en algo relacionado con el cruce del dominio del reloj entre estos relojes.
Lo que quise decir es si el retraso de la ruta de sourceun targetreloj generado incluirá cualquier búfer que la herramienta P&R pueda insertar entre estos nodos.
@FriendFX, no estoy seguro de poder responder a esta pregunta sin comprender por qué está interesado en la demora entre estos relojes. En general, una vez que realice un análisis de tiempo en el esquema posterior de P&R, todos los retrasos se tendrán en cuenta en el árbol del reloj (búferes, muxes, redes de alto fanout, etc.)
Mi única preocupación fue que leí en las Mejores prácticas para Quartus II TimeQuest Timing Analyzer que "la -sourceopción debe referirse al pin de reloj más cercano del objetivo especificado ". Esto solo puede ser relevante cuando se usan varios relojes en el mismo puerto y para ese caso, la -master_clockopción se puede utilizar de todos modos. Solo quiero asegurarme de que no estoy impidiendo que el analizador de tiempo tome en cuenta todos los retrasos correctamente.
En cuanto a su pregunta "¿por qué está interesado en la demora entre estos relojes?": si hay rutas de datos de registro a registro entre clk0y clk4en mi ejemplo, cualquier demora en la red de relojes entre clk0y clk4debe tenerse en cuenta por el tiempo analizador de estos caminos, ¿verdad?
@FriendFX, no puedo responder una pregunta específica de Quartus porque nunca he usado los FPGA de Altera. Si tiene una ruta entre registros clk0y clk4, la definirá como ruta falsa (si los relojes son mutuamente excluyentes, si usa sincronizadores, ...) o como una ruta de varios ciclos. En el primer caso, la herramienta no debe realizar ningún análisis de tiempo y depende de usted asegurarse de que no se produzca ningún fallo lógico. En el último caso, todas las demoras relevantes fueron tomadas en cuenta por otras herramientas que vi.
Tampoco quiero ser específico de Quartus. Desafortunadamente, no he encontrado ningún otro recurso SDC (relacionado con ASIC) que incluso entre en estos detalles. ¡Cualquier sugerencia sería apreciada! Espero que los SDC sean lo suficientemente universales para aplicarse a través de herramientas y flujos, como se menciona en mi pregunta original.
@FriendFX, no tengo buenas referencias para darte. Intente encontrar la Guía del usuario del Compilador de diseño de sinopsis. Sospecho que esta es la fuente de la documentación más completa.
Lo encontré aquí , pero desafortunadamente no brinda detalles sobre el create_generated_clockcomando SDC. Acepté tu respuesta. Tal vez -sourceen algún momento comience una pregunta separada sobre los detalles de la opción. ¡Gracias por tus esfuerzos!