restrição de tempo para circuitos sincronizadores de barramento

10

Eu tenho um circuito sincronizador de barramento para passar um amplo registro nos domínios do relógio.

Fornecerei uma descrição simplificada, omitindo a lógica de redefinição assíncrona.

Os dados são gerados em um relógio. As atualizações são muitas (pelo menos uma dúzia) de bordas do relógio separadas:

PROCESS (src_clk)
BEGIN
   IF RISING_EDGE(clock) THEN
      IF computation_done THEN
          data <= computation;
          ready_spin <= NOT ready_spin;
      END IF;
   END IF;
END PROCESS;

O sinal de controle para novos dados, que são codificados por NRZI (uma palavra válida no barramento corresponde a uma transição no sinal de controle). O sinal de controle passa por uma cadeia DFF atuando como um sincronizador.

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      ready_spin_q3 <= ready_spin_q2;
      ready_spin_q2 <= ready_spin_q1;
      ready_spin_q1 <= ready_spin;
   END IF;
END PROCESS;

O circuito sincronizador apresenta um pequeno atraso, que fornece bastante tempo para a estabilização do barramento de dados; o barramento de dados é amostrado diretamente sem risco de metaestabilidade:

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      IF ready_spin_q3 /= ready_spin_q2 THEN
         rx_data <= data;
      END IF;
   END IF;
END PROCESS;

Isso compila e funciona bem quando sintetizado em um FPGA Cyclone II. No entanto, o TimeQuest relata violações de configuração e retenção, porque não reconhece o sincronizador. Pior, o manual Quartus diz

Concentre-se em melhorar os caminhos que mostram a pior folga. O Montador trabalha mais duro em caminhos com a pior folga. Se você corrigir esses caminhos, o Ajustador poderá melhorar os outros caminhos de tempo com falha no design.

Então, eu quero adicionar as restrições de tempo corretas ao meu projeto para que o Quartus gaste seu esforço do Fitter em outras áreas do design.

Tenho certeza de que esse set_multicycle_pathé o comando SDC (Synopsis Design Constraint) adequado, pois as linhas de dados terão vários ciclos do relógio de destino para estabilizar, mas não consigo encontrar exemplos completos usando esse comando para descrever a lógica de cruzamento de domínio do relógio .

Eu realmente aprecio algumas orientações sobre como escrever restrições de tempo SDC para sincronizadores. Se você encontrar algum problema com essa abordagem, informe-me também.


Detalhe do relógio:

Gerador de clock externo: dois canais, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz e relacionados).

Altera PLL: src_clk = refclk * 9/5 = 36 MHz

Altera PLL: dest_clk = refclk2 * 10 = 100 MHz

Eu também tenho dados indo na outra direção, com 100 MHz src_clk e 36 MHz dest_clk.


TL; DR: Quais são as restrições de tempo SDC corretas para o código acima?

Ben Voigt
fonte
11
Isso seria melhor no site de design FPGA proposto, mas essa proposta ainda não chegou à versão beta.
Ben Voigt
Você pode postar as definições de relógio para src_clk e dest_clk? Eles estão relacionados de alguma forma (múltiplos síncronos)? Se eles são relógios não relacionados, é comum usar set_false_path nessa situação.
Andy
@ Andy: eu adicionei alguns dos detalhes. Obrigado por ajudar com isso.
Ben Voigt

Respostas:

9

Não tenho experiência com Quartus, portanto, trate isso como um conselho geral.

Ao trabalhar em caminhos entre domínios de relógio, as ferramentas de temporização expandem os relógios para o múltiplo menos comum de seus períodos e selecionam o par de arestas mais próximo.

Para caminhos de um relógio de 36 MHz (27.777 ns) a um relógio de 100 MHz (10 ns), se eu fiz meus cálculos rápidos corretamente, o par mais próximo de arestas ascendentes é 138.888 ns no relógio de origem e 140 ns no relógio de destino. Essa é efetivamente uma restrição de 900 MHz para esses caminhos! Dependendo do arredondamento (ou de relógios sem relação), o resultado pode ser pior do que isso.

Existem pelo menos três maneiras de escrever restrições para essa estrutura. Vou chamar os relógios fast_clke, slow_clkcomo acho mais claro, para ilustração.

Opção 1: desativar o tempo com set_false_path

A solução mais fácil é usar set_false_pathpara desativar o tempo entre os relógios:

set_false_path -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_false_path -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Isso não é estritamente correto, pois há requisitos de tempo para o sincronizador funcionar corretamente. Se a implementação física atrasar demais os dados em relação ao sinal de controle, o sincronizador não funcionará. No entanto, como não há lógica no caminho, é improvável que a restrição de tempo seja violada. set_false_pathé comumente usado para esse tipo de estrutura, mesmo em ASICs, onde o esforço versus troca de risco por falhas de baixa probabilidade é mais cauteloso do que para FPGAs.

Opção 2: relaxe a restrição com set_multicycle_path

Você pode permitir tempo adicional para determinados caminhos com set_multicycle_path. É mais comum usar caminhos multiciclos com relógios intimamente relacionados (por exemplo, relógios 1X e 2X interagindo), mas funcionará aqui se a ferramenta o suportar suficientemente.

set_multicycle_path 2 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -setup
set_multicycle_path 1 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -hold

A relação de borda padrão para a configuração é de ciclo único, ou seja set_multicycle_path 1. Esses comandos permitem mais um ciclo do relógio do nó de extremidade ( -end) para caminhos de configuração. O -holdajuste com um número um a menos do que a restrição de configuração é quase sempre necessário ao definir caminhos de vários ciclos, para mais detalhes, veja abaixo.

Para restringir os caminhos na outra direção da mesma forma (relaxando a restrição em um período do relógio mais rápido), altere -endpara -start:

set_multicycle_path 2 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -setup
set_multicycle_path 1 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -hold

Opção 3: especifique o requisito diretamente com set_max_delay

Isso é semelhante ao efeito de, set_multicycle_pathmas evita a necessidade de pensar nas relações de borda e no efeito das restrições de retenção.

set_max_delay 10 -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_max_delay 10 -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Você pode associá-lo set_min_delaya verificações de retenção ou deixar a verificação de retenção padrão no lugar. Você também pode set_false_path -holddesabilitar as verificações de retenção, se sua ferramenta suportar.


Detalhes sangrentos da seleção de arestas para trajetos de vários ciclos

Para entender o ajuste de espera que é emparelhado com cada ajuste de configuração, considere este exemplo simples com um relacionamento 3: 2. Cada dígito representa uma borda do relógio crescente:

1     2     3
4   5   6   7

A verificação de configuração padrão usa as bordas 2 e 6. A verificação de retenção padrão usa as bordas 1 e 4.

A aplicação de uma restrição de ciclo múltiplo de 2 com -endajusta as verificações de configuração e retenção padrão para usar a próxima aresta depois do que estavam usando originalmente, o que significa que a verificação de configuração agora usa as arestas 2 e 7 e a verificação de retenção usa as arestas 1 e 5. Por dois relógios na mesma frequência, esse ajuste faz sentido - cada inicialização de dados corresponde a uma captura de dados e, se a borda de captura for movida uma a uma, a verificação de espera também deverá ser movida uma. Esse tipo de restrição pode fazer sentido para duas ramificações de um único relógio se uma das ramificações tiver um grande atraso. No entanto, para a situação aqui, uma verificação de retenção usando as arestas 1 e 5 não é desejável, pois a única maneira de corrigi-la é adicionar um ciclo inteiro de atraso no caminho.

A restrição de retenção de vários ciclos de 1 (para espera, o padrão é 0) ajusta a borda do relógio de destino usado para verificações de espera para trás em uma borda. A combinação das restrições MCP de configuração de 2 ciclos e MCP de retenção de 1 ciclo resultará em uma verificação de configuração usando as arestas 2 e 7 e uma verificação de retenção usando as arestas 1 e 4.

Andy
fonte
2

Não sei a resposta para Altera, mas no Xilinx Land você pode definir o atraso de um domínio do relógio para o próximo. Você terá que elaborar a matemática (depende do design), mas geralmente é o mais curto dos dois períodos do relógio. Pense neste momento como a inclinação máxima entre dois sinais (incluindo o seu sinal de controle) e você pode descobrir se o seu circuito de sincronização conseguirá lidar com isso.

set_mulicycle_path não é a coisa correta a ser usada, porque isso normalmente lidaria com casos em que a origem e o destino estão no mesmo domínio do relógio. Novamente, estou baseando isso na minha experiência com o Xilinx para que sua milhagem possa variar.


fonte
1

Eu acho que é seguro colocar um set_false_path sobre o sincronizador.

Além disso, você pode colocar "set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO" no qsf para ajudar o Quartus a localizar o sincronizador.

fbo
fonte
Como seria isso? set_false_path -from ready_spin -to ready_spin_q2? E set_false_path -from data -to rx_data?
Ben Voigt
set_false_path -from src_clk -to ready_spinNão tenho certeza se é apropriado colocar o caminho falso nos dados, pois você não os está sincronizando.
fbo
0

Suspeito que o problema seja que, embora você saiba que os sinais de barramento não mudem nem perto do ponto em que estão travados, o software não sabe disso. Sua melhor aposta é provavelmente dizer explicitamente ao software que os sinais de barramento recebidos estão sincronizados com o relógio do barramento e desativar qualquer otimização antes do local onde você realmente os trava (um otimizador poderia, teoricamente, substituir seu circuito por um que seria equivalente se as entradas realmente fossem síncronas, mas que poderiam ser acionadas para um loop se elas mudassem nos ciclos de clock que o circuito que você desenhou não se importaria).

supercat
fonte
Não set_multicycle_pathseria a maneira de informar ao sintetizador / analisador de tempo quantas vezes os sinais de origem podem mudar? E não sei bem o que você quer dizer com "relógio de ônibus", há um ônibus de sinal aqui cruzando domínios de relógio, então qual relógio você está chamando de "relógio de ônibus"? Acho que você está certo de que ainda pode haver metaestabilidade se o sintetizador apresentar falhas durante períodos em que não estou atualizando data. Acho que eu poderia blocos DFF especificamente instanciar há :(
Ben Voigt
@BenVoigt: Eu acho que "set_multicycle_path" é mais frequentemente usado para informar ao validador de temporização que uma cadeia de lógica combinatória entre dois pontos de travamento deve receber N (Tc) -Ts-Tp (N vezes o tempo do ciclo menos o tempo da amostra menos o tempo da amostra tempo de propagação) em vez de apenas Tc-Ts-Th. Não sei como isso interage com a trava de relógios diferentes.
Supercat