Cuando se crea un bloque de diseño o un componente HDL que se puede reutilizar en muchos diseños, puede ser necesario crear restricciones de SDC para acompañarlo. Es útil crear restricciones que no requieran edición por parte del diseñador que reutiliza el componente. Las restricciones deben ser genéricas, por lo que funcionan independientemente de dónde se cree una instancia del bloque en la jerarquía del diseño y dinámicas, de modo que funcionen independientemente de cómo esté conectado el bloque de diseño. Si las restricciones deben aplicarse manualmente a fin de reflejar los cambios de diseño, se quedarán fuera de sincronización si el diseñador realiza cambios de diseño sin actualizar las restricciones.
Este ejemplo de diseño cubre las técnicas para crear restricciones de SDC dinámicas que abordan los dos problemas siguientes:
- Determinar el nombre de una E/S de nivel superior conectada directamente a un módulo de bajo nivel
- Creación de relojes generados en la lógica en módulos de bajo nivel
El diagrama de la Figura 1 muestra un diseño muy simple para este ejemplo. Incluye dos instancias de un bloque de diseño reutilizable denominado reusable_block, que se muestra en amarillo. La Figura 2 muestra el contenido del diseño reusable_block. reusable_block funciona como un reloj de velocidad de datos doble para un bus de salida sincrónico de origen. Su salida debe estar conectada a una salida de nivel superior. Las restricciones para reusable_block deben incluir relojes generados, porque la salida funciona como un reloj de origen sincrónico.
Determinar los nombres de E/S de nivel superior
Las restricciones para reusable_block deben adaptarse a los cambios en los nombres de E/S de nivel superior. Por lo tanto, se debe determinar el nombre de E/S de nivel superior durante la compilación o el análisis de la sincronización. El comando get_fanouts Tcl devuelve una colección de identificadores que representan puertos o registros que son fanouts de un nombre especificado. El comando get_fanouts Tcl utiliza una lista de conexiones de temporización que existe durante la compilación o el análisis de sincronización, de modo que determina dinámicamente la conectividad, independientemente de los nombres de los nodos de fanout. El siguiente código Tcl muestra cómo utilizar get_fanouts para obtener la salida de nivel superior que es un ventilador directo de un registro de bajo nivel.
foreach_in_collection fanout_id [get_fanouts $low_level_register_name] { break } establecer top_level_io_name [get_node_info -name $fanout_id]
No es necesario conocer el nombre de la jerarquía completa del registro de bajo nivel, ya que se puede utilizar una oratorio y una parte conocida de la jerarquía que existe en el bloque de diseño reutilizable para que coincida con él. El último ejemplo de código de esta página muestra un ejemplo de cómo coincidir con el nombre del registro de bajo nivel.
En el diseño de la Figura 1, el pin de salida del módulo de bajo nivel se conecta directamente a una salida de nivel superior. El siguiente código Tcl agrega la comprobación de errores para asegurarse de que los ventiladores del registro de bajo nivel se registren en solo una ubicación y que la ubicación del ventilador sea un puerto de salida. Este código Tcl debe formar parte del archivo SDC que limita la reusable_block.
# Obtenga los ventiladores del conjunto de registro de bajo nivel fanout_collection [get_fanouts $low_level_register_name] # Asegúrese de que solo haya un conjunto de ventiladores num_fanouts [get_collection_size $fanout_collection] si { 1 != $num_fanouts } { error de código de devolución "$low_level_register_name fans fuera a $num_fanouts \ nodos, pero debe ventilar en uno." } # Obtenga el nombre del nodo de ventilador foreach_in_collection fanout_id $fanout_collection { break } establecer fanout_name [get_node_info -name $fanout_id] # Asegúrese de que el nodo fanout sea un puerto de salida si { [catch { get_port_info -is_output_port $fanout_id } is_output] } { # Hubo un error: no aparece un error de devolución de código de puerto "$low_level_register_name fans hacia $fanout_name \ que no es un puerto" } elseif { ! $is_ output } { # No hay error, pero el puerto no es un error de devolución de puerto de salida -code "$fanout_name no es un puerto de salida" } else { set top_level_io_name $fanout_name } # top_level_io_name es el único ventilador de low_level_register_name y no es un puerto de salida
Creación de relojes generados
Un reloj de salida sincrónico de origen se debe definir como un reloj generado, basado en el reloj que alimenta los registros de salida de la velocidad de datos doble. El reloj generado se debe crear sin ninguna información ingresada manualmente sobre relojes en el diseño, porque el bloque de diseño podría crearse una instancia en cualquier diseño con cualquier esquema de temporificación.
El siguiente comando SDC muestra una manera sencilla de crear un reloj generado para el reloj de salida sincrónico de origen para el diseño en la Figura 1, cuando no se conoce la ubicación en la jerarquía.
create_generated_clock -name reusable_generated -source [get_pins \ *|reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[0]|muxsel] \ $top_level_io_name
Es un enfoque directo que funciona para una sola creación de instancias de reusable_block en cualquier lugar de la jerarquía de diseño, pero no maneja múltiples instancias o situaciones de bloqueo múltiple. Cuando se desconocido el esquema de temporación, la restricción de reloj generada debería ser capaz de manejar situaciones en las que se han definido varios relojes en una sola señal de reloj que alimenta el bloque de diseño. A menudo existen múltiples relojes en una sola señal de reloj en diseños que admiten diferentes velocidades de protocolo de E/S, o diseños que admiten el cambio de reloj para redundancia. El ejemplo de reloj generado simple de arriba falla en situaciones de bloqueo múltiple porque no incluye la opción -master_clock para distinguir entre múltiples relojes de origen.
Para gestionar varias instancias, utilice un bucle para crear relojes generados únicos para cada creación de instancias. Para gestionar situaciones de bloqueo múltiple, utilice un procedimiento personalizado llamado get_clocks_driving_pin, que se describe en el ejemplo de diseño "Relojes que desastrzo un pin". Para utilizar el procedimiento personalizado, debe copiarlo desde la página de ejemplo de diseño De relojes que conchan un pin. Puede guardarlo como un archivo SDC independiente que se agrega al proyecto, o copiarlo y pegado en un archivo SDC con todas las demás restricciones que limitan un bloque reutilizable. Si lo guarda como un archivo de SDC que se agrega al proyecto, asegúrese de que aparece antes que cualquier archivo SDC que utilice el procedimiento personalizado get_clocks_driving_pin.
El siguiente código Tcl muestra cómo crear restricciones de reloj generadas en salidas de nivel superior impulsadas por registros de bajo nivel en el diseño que se muestra en la Figura 1. Los relojes generados utilizan las salidas de nivel superior como sus objetivos, y los pines muxsel de altddio_output se registran como sus fuentes. El código utiliza un bucle para iterar a través de todas las instancias de reusable_block en el diseño y un bucle anidado para manejar situaciones de bloqueo múltiple con el get_clocks_driving_pin procedimiento personalizado. Da por sentado que el procedimiento de get_clocks_driving_pin ya se ha definido.
El número get_pins devuelve un pin de muxsel por cada creación de instancias de reusable_block cantidad de foreach_in_collection itera sobre cada pin de muxsel foreach_in_collection pin_id [get_pins -compatibility_mode \ *|reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[5]0]|muxsel] { # pin_name tiene la jerarquía de diseño completa del pin muxsel para una creación de instancias de reusable_block conjunto pin_name [get_node_info -name $pin_id] # Utilice el código que se muestra anteriormente, sin comprobar los errores, para obtener el nombre del resultado de nivel superior foreach_in_collection port_id [get_fanouts $pin_name] { break } set port_name [get_node_info -name $port_id] # Puede haber varios relojes de representación en el registro altddio_output se requiere un reloj generado para cada reloj que alimenta # un pin muxsel. Cada reloj que representa el pin muxsel es un reloj maestro. foreconferencia master_clock [get_clocks_feeding_pin $pin_name] { post_message "Crear un reloj generado en $port_name alimentado por $pin_name" # Cree el reloj generado con el reloj maestro adecuado. # La fuente es el pin muxsel de la celda altddio_output en # la creación de instancias actual de reusable_block. # El nombre es una combinación del reloj maestro y el nombre # de jerarquía completa del pin muxsel. # El objetivo es el puerto de nivel superior que es el ventilador del pin muxsel. create_generated_clock -add -master_clock $master_clock \ -source [get_pins $pin_name] -name ${master_clock}-${pin_name} \ [get_ports $port_name] }
Con este código en un archivo SDC incluido en el proyecto, todas las instancias de reusable_block se limitan automáticamente a los relojes generados. Los relojes generados siempre son correctos y actualizados, incluso en las siguientes situaciones:
- reusable_block se crea una instancia de o se mueve a otros puntos de la jerarquía de diseño
- Se renombran las E/S de nivel superior
- El diseñador utiliza varias definiciones de reloj en el diseño