Simplifiez la réutilisation de la conception avec les contraintes dynamiques des SDC

author-image

Par

Lorsque vous créez un bloc de conception ou un composant HDL qui peut être réutilisé dans de nombreux modèles, il peut être nécessaire de créer des contraintes SDC pour y aller. Il est utile de créer des contraintes qui ne nécessitent pas d’édition par le concepteur en réutilisant le composant. Les contraintes doivent être génériques, de sorte qu’elles fonctionnent quel que soit l’endroit où le bloc est instantané dans la hiérarchie de conception, et dynamiques afin qu’ils fonctionnent indépendamment de la façon dont le bloc de conception est connecté. Si des contraintes doivent être modifiées manuellement pour refléter les changements de conception, elles deviennent désynchronisées si le concepteur effectue des modifications de conception sans également mettre à jour les contraintes.

Cet exemple de conception couvre les techniques permettant de créer des contraintes SDC dynamiques qui répondent aux deux problèmes suivants :

  • Déterminer le nom d’un E/S de haut niveau connecté directement à un module de bas niveau
  • Création d’horloges générées sur la logique dans des modules de bas niveau

Le schéma de la Figure 1 présente une conception très simple pour cet exemple. Il comprend deux instances d’un bloc de conception réutilisable nommé reusable_block, indiqué en jaune. La Figure 2 montre le contenu de la conception reusable_block. reusable_block fonctionne comme une double horloge de débit de données pour un bus de sortie synchrone à la source. Sa sortie doit être connectée à une sortie de haut niveau. Les contraintes pour les reusable_block doivent inclure les horloges générées, car la sortie fonctionne comme une horloge synchrone source.

Figure 1. Exemple de circuit de conception.

Figure 2. Contenu de reusable_block.

Déterminer les noms d’E/S de haut niveau

Les contraintes pour reusable_block doivent s’adapter aux changements apportés aux noms d’E/S de haut niveau. Par conséquent, le nom d’E/S de haut niveau doit être déterminé lors de l’analyse de compilation ou de synchronisation. La commande get_fanouts Tcl renvoie une collection d’ID représentant des ports ou registres qui sont des fanouts d’un nom spécifié. La commande get_fanouts Tcl utilise une liste de netlist de synchronisation qui existe lors de l’analyse de compilation ou de synchronisation, de sorte qu’elle détermine dynamiquement la connectivité quel que soit le nom des nœuds fanout. Le code Tcl suivant montre comment utiliser get_fanouts pour obtenir la sortie de haut niveau qui est un ventilateur direct d’un registre de bas niveau.

foreach_in_collection fanout_id [get_fanouts $low_level_register_name] { break }
set top_level_io_name [get_node_info -name $fanout_id]

Le nom complet de la hiérarchie du registre de bas niveau n’a pas besoin d’être connu, car vous pouvez utiliser un wildcard et une partie connue de la hiérarchie qui existe dans le bloc de conception réutilisable pour le faire correspondre. Le dernier exemple de code de cette page montre comment correspondre au nom de registre de bas niveau.

Dans la conception de la Figure 1, la broche de sortie du module de bas niveau est connectée directement à une sortie de haut niveau. Le code Tcl suivant ajoute la vérification d’erreur pour s’assurer que le ventilateur du registre de bas niveau ne se trouve qu’à un seul emplacement et que l’emplacement du ventilateur est un port de sortie. Ce code Tcl doit faire partie du fichier SDC qui limite les reusable_block.

# Obtenez les fanouts du jeu de registre de bas niveau
fanout_collection [get_fanouts $low_level_register_name]

# Assurez-vous qu’il n’y a qu’un seul ensemble de ventilateur
num_fanouts [get_collection_size $fanout_collection]
si { 1 != $num_fanouts } { erreur de
    retour -code " $low_level_register_name fans out to $num_fanouts \
        nœuds mais doit ventilateur à un.
» }

# Obtenez le nom du nœud fanout
foreach_in_collection fanout_id $fanout_collection { break }
set fanout_name [get_node_info -name $fanout_id]

# Assurez-vous que le nœud fanout est un port de sortie
si {[capture { get_port_info -is_output_port $fanout_i } is_output] } {
    Il y a eu une erreur - il ne ventilateur vers un port de retour -erreur de code "
    $low_level_register_name fans out to $fanout_name \
        which is not a port » }
elseif { ! $is_ output } {
    # Il n’y a pas d’erreur, mais le port n’est pas un port de retour -erreur de code de
    retour « $fanout_name n’est pas un port de sortie »
} d’autre part {
    set top_level_io_name $fanout_name
} # top_level_io_name est le seul

fanout de low_level_register_name et il est le
# un port de sortie

Création d’horloges générées

Une horloge de sortie synchrone source doit être définie comme une horloge générée, basée sur l’horloge qui alimente les registres de sortie à deux débits de données. L’horloge générée doit être créée sans qu’aucune information ne soit entrée manuellement sur les horloges de la conception, car le bloc de conception peut être instantané dans n’importe quelle conception avec n’importe quelle schéma d’horloge.

La commande SDC suivante montre un moyen simple de créer une horloge générée pour l’horloge de sortie synchrone source pour la conception dans la Figure 1, lorsque l’emplacement dans la hiérarchie n’est pas connu.

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

Il s’agit d’une approche simple qui fonctionne pour une seule instanciation de reusable_block n’importe où dans la hiérarchie de conception, mais elle ne gère pas les situations d’instanciations ou de multiclocks multiples. Lorsque le schéma d’horloge est inconnu, la contrainte d’horloge générée devrait être capable de gérer les situations où plusieurs horloges ont été définies sur un seul signal d’horloge qui alimente le bloc de conception. Il existe souvent plusieurs horloges sur un seul signal d’horloge dans les conceptions qui prennent en charge différentes vitesses de protocole d’E/S, ou dans les conceptions qui prennent en charge le passage de l’horloge pour une redondance. L’exemple simple d’horloge générée ci-dessus échoue dans les situations de multiclockage, car il n’inclut pas l’option -master_clock permettant de faire la distinction entre plusieurs horloges sources.

Pour gérer plusieurs instantiations, utilisez une boucle pour créer des horloges générées uniques pour chaque instantiation. Pour gérer des situations multiclock, utilisez une procédure personnalisée appelée get_clocks_driving_pin, décrite dans l’exemple « Clocks Feeding a Pin design » (Alimenter une broche). Pour utiliser la procédure personnalisée, vous devez le copier à partir de la page d’exemple de broches alimentant les horloges. Vous pouvez l’enregistrer dans un fichier SDC séparé ajouté au projet, ou le copier-coller dans un fichier SDC avec toutes les autres contraintes qui limitent un bloc réutilisable. Si vous l’enregistrez en tant que fichier SDC ajouté au projet, assurez-vous qu’il est répertorié avant tout fichier SDC qui utilise la procédure personnalisée get_clocks_driving_pin.

Le code Tcl suivant montre comment créer des contraintes d’horloge générées sur des sorties de haut niveau stimulées par des registres de bas niveau dans la conception indiquée dans la Figure 1. Les horloges générées utilisent les sorties de haut niveau comme cibles et les broches muxsel de altddio_output s’enregistrent comme sources. Le code utilise une boucle pour itérer à travers toutes les instanciations de reusable_block dans la conception, et un circuit imbriqué pour gérer les situations de multiclock avec la procédure get_clocks_driving_pin personnalisée. Elle suppose que la procédure get_clocks_driving_pin a déjà été définie.

# get_pins retourne une broche muxsel pour chaque instanciation de reusable_block
# foreach_in_collection itérations sur chaque broche muxsel
foreach_in_collection pin_id [get_pins -compatibility_mode \
    |reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[0]]|muxsel] {

    # pin_name possède la hiérarchie de conception complète de la broche muxsel pour une
    nº d’instanciation de reusable_block
    réglée pin_name [get_node_info -nom $pin_id]
    
    # Utilisez le code ci-dessus, sans vérification d’erreur, pour obtenir
    le nom de la sortie de haut niveau foreach_in_collection port_id
    [get_fanouts $pin_name] { break }
    réglé port_name [get_node_info -nom $port_id]
    
    # Il peut y avoir plusieurs horloges alimentant le registre altddio_output
    # Une horloge générée est nécessaire pour chaque horloge qui se fournit
    # une broche muxsel. Chaque horloge qui fournit la broche du muxsel est une horloge maître.
    foreach master_clock [get_clocks_feeding_pin $pin_name] {

        post_message « Création d’horloge générée sur $port_name fed by $pin_name »
        #Créer l’horloge générée avec l’horloge maître appropriée.
        Nb. La source est la broche muxsel de la cellule altddio_output dans
        # l’instantiation actuelle de reusable_block.
        # Le nom est une combinaison de l’horloge maître et du nom #
        de la hiérarchie complète de la broche muxsel.
        # La cible est le port de haut niveau qui est le ventilateur de la broche muxsel.
        create_generated_clock -add -master_clock $master_clock \
            -source [get_pins $pin_name] -name ${master_clock}-${pin_name} \
            [get_ports $port_name]
    }
}

Avec ce code dans un fichier SDC inclus dans le projet, toutes les instanciations de reusable_block sont automatiquement limitées par les horloges générées. Les horloges générées sont toujours correctes et à jour, même dans les situations suivantes :

  • reusable_block est instantanément activée ou déplacée vers d’autres points de la hiérarchie de conception
  • Les E/S de haut niveau sont renommées
  • Le concepteur utilise plusieurs définitions d’horloge dans la conception

Le contenu de cette page est une combinaison de traduction humaine et informatique du contenu original en anglais. Ce contenu vous est fourni pour votre commodité et à titre informatif seulement et ne saurait être totalement exact ou complet. En cas de contradiction entre la version anglaise de cette page et la traduction, c'est la version anglaise qui prévaut. Afficher la version anglaise de cette page.