Semplifica il riutilizzo della progettazione con i vincoli dinamici SDC

author-image

di

Quando si crea un blocco di progettazione o un componente HDL che può essere riutilizzato in molti progetti, potrebbe essere necessario creare vincoli SDC per utilizzarlo. È utile creare vincoli che non richiedono la modifica da parte della finestra di progettazione che riutilizza il componente. I vincoli devono essere generici, in modo che funzionino indipendentemente da dove è stata creata un'istanza del blocco nella gerarchia di progettazione e dinamici in modo da funzionare indipendentemente dal modo in cui il blocco di progettazione è collegato. Se i vincoli devono essere modificati manualmente per riflettere le modifiche alla progettazione, non saranno sincronizzati se la finestra di progettazione apporta modifiche alla progettazione senza aggiornare anche i vincoli.

Questo esempio di progettazione copre le tecniche per la creazione di vincoli SDC dinamici che affrontano i seguenti due problemi:

  • Determinare il nome di un I/O di primo livello collegato direttamente a un modulo di basso livello
  • Creazione di clock generati con logica in moduli di basso livello

Il diagramma nella Figura 1 mostra un design molto semplice per questo esempio. Include due istanze di un blocco di progettazione riutilizzabile denominato reusable_block, mostrato in giallo. La figura 2 mostra il contenuto della progettazione reusable_block. reusable_block funziona come un clock a doppia velocità dei dati per un bus di output sincrono di origine. L'output deve essere collegato a un output di livello superiore. I vincoli per reusable_block devono includere clock generati, poiché l'output funziona come clock sincrono di origine.

Figura 1. Circuito campione per esempio di progettazione.

Figura 2. Contenuti di reusable_block.

Determinazione dei nomi di I/O di primo livello

I vincoli per reusable_block devono contenere modifiche ai nomi di I/O di primo livello. Pertanto, il nome di I/O di primo livello deve essere determinato durante la compilazione o l'analisi dei tempi. Il comando Tcl get_fanouts restituisce una raccolta di ID che rappresentano porte o registri che sono ventola di un nome specificato. Il comando Tcl get_fanouts utilizza un netlist di temporizzazione che esiste durante la compilazione o l'analisi dei tempi, quindi determina dinamicamente la connettività indipendentemente dai nomi dei nodi fanout. Il seguente codice Tcl mostra come utilizzare get_fanouts per ottenere l'output di primo livello che è una ventola diretta di un registro di basso livello.

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

Il nome della gerarchia completa del registro di basso livello non deve essere noto, perché è possibile utilizzare un carattere jolly e una porzione nota della gerarchia che esiste nel blocco di progettazione riutilizzabile per abbinarlo. L'ultimo esempio di codice in questa pagina mostra un esempio di come abbinare il nome del registro di basso livello.

Nella progettazione della Figura 1, il pin di uscita del modulo di basso livello è collegato direttamente a un'uscita di primo livello. Il seguente codice Tcl aggiunge il controllo degli errori per garantire che le ventole del registro di basso livello si trovino in una sola posizione e che la posizione della ventola sia una porta di output. Questo codice Tcl dovrebbe essere parte del file SDC che vincola reusable_block.

# Ottieni le ventole del set di registro di basso livello
fanout_collection [get_fanouts $low_level_register_name]

# Assicurati che ci sia un solo set di ventole
num_fanouts [get_collection_size $fanout_collection]
se { 1 != $num_fanouts } {
    return -code error "$low_level_register_name fans out to $num_fanouts \
        nodi ma deve uscire a uno."
}

# Ottieni il nome del nodo fanout
foreach_in_collection fanout_id $fanout_collection { break }
impostato fanout_name [get_node_info -name $fanout_id]

# Assicurati che il nodo fanout sia una porta di output se {
[catch { get_port_info -is_output_port $fanout_id } is_output get_port_info] } { # Si è verificato un errore : non viene visualizzato un errore di
    restituzione porta
    -errore di codice "$low_level_register_name fans out to $fanout_name \
        che non è una porta" }
elseif { ! $is_ output } {
    # Non c'è errore, ma la porta non è un errore di restituzione porta di output
    - errore di codice "$fanout_name non è una porta di output"
} else { set
    top_level_io_name $fanout_name
} # top_level_io_name è

l'unica ventola di low_level_register_name ed è una porta di
output #

Creazione di clock generati

Un clock di output sincrono di origine deve essere definito come clock generato, in base al clock che alimenta i registri di output a doppia velocità di dati. L'orologio generato deve essere creato senza alcuna informazione immessa manualmente sui clock nel progetto, perché il blocco di progettazione potrebbe essere istanziato in qualsiasi progetto con qualsiasi schema di clock.

Il seguente comando SDC mostra un modo semplice per creare un clock generato per il clock di output sincrono di origine per la progettazione nella Figura 1, quando la posizione nella gerarchia non è nota.

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

Si tratta di un approccio semplice che funziona per una singola istanza di reusable_block in qualsiasi punto della gerarchia di progettazione, ma non gestisce più istanze o situazioni multiclock. Quando lo schema di clock è sconosciuto, il vincolo di clock generato dovrebbe essere in grado di gestire situazioni in cui sono stati definiti più clock su un singolo segnale di clock che alimenta il blocco di progettazione. Più clock su un singolo segnale di clock spesso esistono in progetti che supportano diverse velocità di protocollo di I/O o progetti che supportano il passaggio di clock per la ridondanza. Il semplice esempio di clock generato sopra non riesce in situazioni di multiclock perché non include l'opzione -master_clock per distinguere tra più clock di origine.

Per gestire più istanze, utilizzare un ciclo per creare clock generati univoci per ogni istanza. Per gestire situazioni multiclock, utilizzare una procedura personalizzata chiamata get_clocks_driving_pin, descritta nell'esempio di progettazione clock che alimenta un pin. Per utilizzare la procedura personalizzata, è necessario copiarla dalla pagina di esempio di progettazione clock che alimenta un pin. È possibile salvarlo come file SDC separato aggiunto al progetto o copiarlo e incollarlo in un file SDC con tutti gli altri vincoli che limitano un blocco riutilizzabile. Se lo si salva come file SDC aggiunto al progetto, assicurarsi che sia elencato prima di qualsiasi file SDC che utilizza la procedura personalizzata get_clocks_driving_pin.

Il seguente codice Tcl mostra come creare vincoli di clock generati su output di primo livello basati su registri di basso livello nella progettazione mostrata nella Figura 1. I clock generati utilizzano le uscite di primo livello come obiettivi e i pin muxsel di altddio_output si registrano come fonti. Il codice utilizza un ciclo per iterare tutte le istanze di reusable_block nella progettazione e un ciclo annidato per gestire le situazioni di multiclock con la procedura personalizzata get_clocks_driving_pin. Presuppone che la procedura get_clocks_driving_pin sia già stata definita.

# get_pins restituisce un pin muxsel per ogni istanza di reusable_block
# foreach_in_collection itera su ciascun pin 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 ha la gerarchia di progettazione completa del pin muxsel per
    un'istanza di reusable_block
    impostata pin_name [nome get_node_info $pin_id]
    
    # Utilizzare il codice riportato sopra, senza controllo degli errori, per ottenere
    il nome dell'output di primo livello
    foreach_in_collection port_id [get_fanouts $pin_name] { break }
    impostato port_name [get_node_info -name $port_id]
    
    # Possono esserci più clock che alimentano il registro altddio_output
    # È necessario un clock generato per ogni clock che alimenta
    # un pin muxsel. Ogni orologio che alimenta il pin muxsel è un clock master.
    foreach master_clock [get_clocks_feeding_pin $pin_name] {

        post_message "Creazione di clock generato su $port_name alimentato da $pin_name" # Crea il clock generato con
        il clock master appropriato.
        # L'origine è il pin muxsel della cella altddio_output in
        # l'istanza corrente di reusable_block.
        # Il nome è una combinazione dell'orologio principale e del
        nome della gerarchia # completa del pin muxsel.
        # La destinazione è la porta di primo livello che è la ventola del pin muxsel.
        create_generated_clock -add -master_clock $master_clock \
            -source [get_pins $pin_name] -name ${master_clock}-${pin_name} \
            [nome_get_ports $port]
    }
}

Con questo codice in un file SDC incluso nel progetto, tutte le istanze di reusable_block vengono automaticamente limitate con clock generati. I clock generati sono sempre corretti e aggiornati, anche nelle seguenti situazioni:

  • reusable_block viene creata un'istanza o spostata in altri punti della gerarchia di progettazione
  • I/O di livello superiore vengono rinominati
  • Il designer utilizza più definizioni di clock nella progettazione

Il contenuto di questa pagina è il risultato della combinazione tra la traduzione umana e quella automatica del contenuto originale in lingua inglese. Questo contenuto è fornito soltanto a titolo di informazione generale e non ha pretese di completezza o accuratezza. In presenza di contraddizioni tra la versione in lingua inglese di questa pagina e la sua traduzione, fa fede la versione inglese. Visualizza la versione in lingua inglese di questa pagina.