Simplifique a reutilização do design com restrições dinâmicas de SDC

author-image

Por

Quando você cria um bloco de projeto ou componente HDL que pode ser reutilizável em muitos designs, pode ser necessário criar restrições de SDC para ir com ele. É útil criar restrições que não exigem edição pelo designer reutilizando o componente. As restrições devem ser genéricas, para que funcionem independentemente de onde o bloco seja instaurou na hierarquia de design e dinâmica para que funcionem independentemente de como o bloco de projeto está conectado. Se as restrições devem ser editadas manualmente para refletir alterações de projeto, elas se desincronizem se o designer fizer alterações de projeto sem também atualizar as restrições.

Este exemplo de projeto aborda técnicas para criar restrições dinâmicas de SDC que abordam os dois problemas a seguir:

  • Determinar o nome de uma E/S de alto nível conectada diretamente a um módulo de baixo nível
  • Criação de clocks gerados na lógica em módulos de baixo nível

O diagrama na Figura 1 mostra um design muito simples para este exemplo. Ele inclui duas instâncias de um bloco de design reutilizável chamado reusable_block, mostrado em amarelo. A Figura 2 mostra o conteúdo do reusable_block design. reusable_block funciona como um clock de taxa de dados dupla para um barramento de saída síncrono de origem. Sua saída deve estar conectada a uma saída de alto nível. As restrições para reusable_block devem incluir clocks gerados, porque a saída funciona como um clock síncrono de origem.

Figura 1. Circuito de amostra para exemplo de projeto.

Figura 2. Conteúdo de reusable_block.

Determinar nomes de E/S de alto nível

As restrições para reusable_block devem acomodar alterações em nomes de E/S de alto nível. Portanto, o nome de E/S de alto nível deve ser determinado durante a compilação ou análise de temporização. O get_fanouts Tcl retorna uma coleção de IDs representando portas ou registros que são fanouts de um nome especificado. O get_fanouts Tcl usa uma netlist de sincronização que existe durante a compilação ou análise de temporização, de modo que determina dinamicamente a conectividade, independentemente dos nomes dos nós de fanout. O código Tcl a seguir mostra como usar o get_fanouts para obter a saída de nível superior que é um fanout direto de um registro de baixo nível.

foreach_in_collection fanout_id [get_fanouts $low_level_register_name] { quebrar } definir top_level_io_name
[get_node_info -name $fanout_id]

O nome da hierarquia completa do registro de baixo nível não precisa ser conhecido, porque você pode usar um curinga e uma parte conhecida da hierarquia que existe no bloco de design reutilizável para corresponder a ele. O último exemplo de código nesta página mostra um exemplo de como corresponder ao nome de registro de baixo nível.

No design da Figura 1, o pino de saída do módulo de baixo nível é conectado diretamente a uma saída de alto nível. O código Tcl a seguir adiciona verificação de erro para garantir que os ventiladores de baixo nível registrem-se em apenas um local e que o local do fanout seja uma porta de saída. Este código Tcl deve fazer parte do arquivo SDC que restringe reusable_block.

# Obtenha as fanouts do conjunto de registro de baixo nível fanout_collection [get_fanouts $low_level_register_name] # Certifique-se de que há apenas um conjunto de

fanouts
num_fanouts [get_collection_size $fanout_collection] se { 1 != $num_fanouts } { erro de código de devolução
    "$low_level_register_name fans out to $num_fanouts \

nós mas deve se fanouts para um". # Obtenha o nome do nó fanout foreach_in_collection fanout_id $fanout_collection { break } set fanout_name [get_node_info -name $fanout_id] # Certifique-se de que o nó de fanout é uma porta de saída se { [catch { get_port_info -is_output_port $fanout_id } is_output] } { Houve um erro - ele não se adeptou a um erro de código de devolução de porta
    "$low_level_register_name fans para $fanout_name \ que não é uma
        porta"
} elseif { ! $is_ saída } { # Não há erro, mas a porta não é um erro de código de devolução da porta de saída "$fanout_name não é uma porta de saída" } outra
    { definir
    top_level_io_name $fanout_name } #
top_level_io_name
é o único fanout do low_level_register_name e é # uma porta de saída

Criação de clocks gerados

Um clock de saída síncrono de origem deve ser definido como um clock gerado, com base no clock que alimenta os registros de saída de taxa de dados duplas. O clock gerado deve ser criado sem qualquer informação inserida manualmente sobre clocks no design, porque o bloco de projeto pode ser instaurou em qualquer projeto com qualquer esquema de clocking.

O comando SDC a seguir mostra uma maneira simples de criar um clock gerado para o clock de saída síncrono de origem para o design na Figura 1, quando o local na hierarquia não é conhecido.

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

É uma abordagem simples que funciona para uma única instanização de reusable_block em qualquer lugar na hierarquia de design, mas não lida com múltiplas instações ou situações de multiclock. Quando o esquema de clocking é desconhecido, a restrição de clock gerada deve ser capaz de lidar com situações em que vários clocks foram definidos em um sinal de clock único que alimenta o bloco de projeto. Vários clocks em um sinal de clock único geralmente existem em designs que suportam velocidades diferentes de protocolo de E/S ou designs que suportam a comutação do clock para redundância. O exemplo de clock gerado simples acima falha em situações de multiclock porque não inclui a opção -master_clock para distinguir entre vários clocks de origem.

Para lidar com várias instações, use um loop para criar clocks gerados exclusivos para cada instantição. Para lidar com situações de multiclock, use um procedimento personalizado chamado get_clocks_driving_pin, descrito no exemplo de criação de pinos de alimentação de clocks. Para usar o procedimento personalizado, você deve copiá-lo da página Clocks Alimentando um exemplo de projeto de pino. Você pode salvá-lo como um arquivo SDC separado que é adicionado ao projeto, ou copiar e colar em um arquivo SDC com todas as outras restrições que restringem um bloco reutilizável. Se você salvá-lo como um arquivo SDC adicionado ao projeto, certifique-se de que ele está listado antes de qualquer arquivo SDC que use o procedimento get_clocks_driving_pin personalizado.

O código Tcl a seguir mostra como criar restrições de clock geradas em saídas de alto nível orientadas por registros de baixo nível no design mostrado na Figura 1. Os clocks gerados usam as saídas de alto nível como seus alvos, e os pinos de muxsel de altddio_output registram como suas fontes. O código usa um loop para iterar através de todas as instações de reusable_block no design, e um loop aninhado para lidar com situações de multiclock com o procedimento get_clocks_driving_pin personalizado. Ele assume que o procedimento get_clocks_driving_pin já foi definido.

# get_pins devolve um pino de muxsel para cada instanização de reusable_block # foreach_in_collection iterates sobre cada pino de
foreach_in_collection pin_id
[get_pins -compatibility_mode \ *|reusable_block_clock_out|altddio_out_component|auto_generated|ddio_outa[0]. |muxsel] { # pin_name tem a hierarquia de design completa do pino de muxsel para uma instanização # do conjunto
    reusable_block pin_name
    [get_node_info-name $pin_id]
    
    # Use o código mostrado acima, sem verificação de erro, para obter # o nome da saída de nível superior
    foreach_in_collection port_id [get_fanouts $pin_name] { break }
    set port_name [get_node_info -name $port_id] # Pode haver vários clocks alimentando o registro de altddio_output # Um clock gerado é necessário para cada clock que alimenta # um pino de
    muxsel. Cada clock alimentando o pino de muxsel é um relógio mestre.
    foreach master_clock [get_clocks_feeding_pin $pin_name] { post_message "Criando clock gerado em $port_name alimentado por $pin_name" # Crie o clock gerado com o clock mestre
        adequado.
        # A fonte é o pino de muxsel da célula altddio_output nº da instanização atual do
        reusable_block.
        # O nome é uma combinação do clock mestre e do
        # nome da hierarquia completa do pino de muxsel.
        # O destino é a porta de alto nível que é o fanout do pino de muxsel.
        create_generated_clock -add -master_clock $master_clock \
            -source [get_pins $pin_name] -name ${master_clock}-${pin_name} \
            [get_ports $port_name]
    }
}

Com este código em um arquivo SDC incluído no projeto, todas as instações de reusable_block são limitadas automaticamente com clocks gerados. Os clocks gerados estão sempre corretos e atualizados, mesmo nas seguintes situações:

  • reusable_block é instaurou ou mudou para outros pontos na hierarquia de projetos
  • E/S de alto nível são renomeados
  • O designer usa várias definições de clock no design

O conteúdo desta página é uma combinação de tradução humana e por computador do conteúdo original em inglês. Este conteúdo é fornecido para sua conveniência e apenas para informação geral, e não deve ser considerado completo ou exato. Se houver alguma contradição entre a versão em inglês desta página e a tradução, a versão em inglês prevalecerá e será a determinante. Exibir a versão em inglês desta página.