O que "tempo" significa em Verilog
Verilog não tem uma noção embutida de segundos. O simulador avança "unidades de tempo" - ticks inteiros arbitrários - e seu código usa #N para esperar N delas. A diretiva `timescale é o que mapeia esses ticks para tempo real.
`timescale 1ns / 1ps
module test;
initial begin
$display("t = %0t", $time); // 0
#5;
$display("t = %0t", $time); // 5 ns
#1.5;
$display("t = %0t", $time); // 6500 ps (ou 6.5 ns)
$finish;
end
endmodule
Dois parâmetros:
- Unidade (primeiro número): o que
#1significa.1nsdiz que um tick é um nanossegundo. - Precisão (segundo número): com que finura a simulação rastreia tempo dentro daquela unidade.
1psdiz que delays fracionários são arredondados para picossegundos.
A precisão não pode ser mais grossa que a unidade (1ps / 1ns é ilegal). Escolhas comuns:
1ns / 1ps- o padrão de fato. Tudo em nanossegundos, precisão sub-nanossegundo para qualquer delay de gate.1ps / 1ps- quando se modela circuitos extremamente rápidos ou quando cada delay é sub-nanossegundo.1us / 1ns- para simulações lentas, em escala embarcada (tempos de byte UART, protocolos lentos).
Onde colocá-la
`timescale é uma diretiva de compilador, não uma construção de nível de module. Vai bem no topo de um arquivo, antes de qualquer module:
`timescale 1ns / 1ps
module foo(...);
// ...
endmodule
Seu escopo é "deste ponto em diante na ordem de compilação, até o próximo `timescale ou fim da compilação". Isso tem uma implicação sutil: um arquivo sem `timescale explícito herda o que o arquivo previamente compilado declarou, o que depende da ordem em que o compilador lê os arquivos. Evite a surpresa: coloque `timescale no topo de cada arquivo.
O editor do navegador nestes docs define um timescale padrão para você (tipicamente 1ns / 1ps), que é por isso que os exemplos em docs anteriores funcionaram sem declarar um. Em um projeto real você seria explícito.
#delay na prática
Depois de `timescale 1ns / 1ps:
#5 // espera 5 ns
#100 // espera 100 ns
#1.5 // espera 1.5 ns (precisao permite)
#0.001 // espera 1 ps (so um pouco acima da precisao)
#0 // delay zero; util para ordenar eventos no mesmo tempo
Dentro de um bloco initial ou always, #N bloqueia o fluxo procedural por N unidades de tempo. O simulador pausa este bloco (outros blocos concorrentes continuam rodando) e retoma depois do delay.
Você pode prefixar uma atribuição com um delay:
#10 a = 1; // espera 10 ns, depois atribui
data <= #2 new_value; // agenda a non-blocking assignment 2 ns no futuro
A primeira forma é o feijão com arroz do testbench. A segunda (non-blocking com delay) é usada em simulação no nível de gate para modelar delay de propagação.
Gerando um clock
O padrão clássico:
`timescale 1ns / 1ps
module test;
reg clk = 0;
always #5 clk = ~clk;
// ...
endmodule
Com timescale 1ns / 1ps, #5 é 5 ns. O clock alterna a cada 5 ns, dando um período de 10 ns - um clock de 100 MHz. Para mudar a frequência, mude o delay:
| Meio-período | Período | Frequência |
|---|---|---|
#1 | 2 ns | 500 MHz |
#2.5 | 5 ns | 200 MHz |
#5 | 10 ns | 100 MHz |
#10 | 20 ns | 50 MHz |
#25 | 50 ns | 20 MHz |
#50 | 100 ns | 10 MHz |
Se você quer um meio-período fracionário (#2.5), sua precisão precisa suportar isso - precisão 1ps lida com qualquer coisa até 0.001 ns, então qualquer frequência razoável está bem.
Misturando timescales entre arquivos
Um design real tem muitos arquivos, e eles podem declarar timescales diferentes. O simulador usa o timescale de cada arquivo para interpretar os delays naquele arquivo. Se module_a.v diz `timescale 1ns / 1ps e usa #5, isso é 5 ns. Se module_b.v diz `timescale 1us / 1ns e usa #5, isso é 5 us.
Isso é principalmente invisível porque o simulador apresenta um eixo de tempo global independente disso - mas significa que o mesmo #N em dois arquivos pode significar coisas muito diferentes. A correção: escolha um timescale (padrão da indústria é 1ns / 1ps) e coloque no topo de cada arquivo. Não misture.
Delays não são sintetizáveis
Ponto crucial: #delay só existe para simulação. A ferramenta de síntese lê:
// Em RTL sintetizavel - ERRADO
always @(posedge clk) begin
out <= #2 in;
end
…e ou ignora o #2 (a maioria das ferramentas) ou rejeita a construção (linters mais rigorosos). O timing do hardware real é determinado pelo clock e pelo delay de propagação dos gates - ambos invisíveis ao código fonte.
A regra: use # só em testbenches. RTL sintetizável não tem delays #. Se você se pegar querendo um delay em código sintetizável, na verdade quer um contador que decrementa no clock - é assim que hardware real "espera".
$time vs $realtime
Duas formas de ler o tempo de simulação atual:
$timeretorna um inteiro de 64 bits em unidades da unidade do timescale atual.$realtimeretorna umrealem unidades da unidade do timescale atual, mas com precisão completa.
Para logging de testbench, $time é quase sempre o suficiente. Recorra a $realtime apenas quando precisar de precisão sub-tick em declarações de print.
Dicas práticas
- Sempre declare
`timescaleno topo de cada arquivo.1ns / 1psé o default seguro. - Use
#delaysó em testbenches. Trate sua ausência em código sintetizável como uma regra estática. - Combine períodos de clock com sua frequência alvo. Se você está simulando um design de 50 MHz, use um período de clock de 20 ns - períodos mal combinados podem mascarar bugs sensíveis ao timing.
- Para estímulo contado por ciclos, use
@(posedge clk)em vez de#. É robusto contra mudanças no período do clock.
O que vem a seguir
Você agora viu cada doc destes tutoriais Verilog. Dos fundamentos da linguagem (wire vs reg, modules, operadores), passando por blocos procedurais e controle de fluxo, em design síncrono e máquinas de estado, e finalmente o ferramental de testbench que prova que tudo funciona. Hora de construir algo - o playground ao lado destes docs é o mesmo simulador que usamos ao longo de tudo, pronto para o que quer que você esboce.
Perguntas frequentes
O que `timescale 1ns / 1ps significa em Verilog?
Diz ao simulador: 'uma unidade de tempo neste arquivo é um nanossegundo, e tempos são rastreados com precisão de picossegundo'. Depois dessa diretiva, #5 espera 5 ns, #1.5 espera 1.5 ns (arredondado para picossegundos) e $time é reportado em nanossegundos. O primeiro número é a unidade; o segundo é a precisão.
Preciso de `timescale em cada arquivo Verilog?
Boa prática: sim. O escopo da diretiva termina no próximo \timescaleou no fim da compilação, então arquivos sem uma herdam o que o arquivo previamente compilado declarou. Isso torna o timing não-determinístico entre builds. Coloque`timescale 1ns / 1ps` no topo de cada arquivo fonte - é a convenção mais comum - e você nunca terá surpresa.
O que #5 significa em Verilog?
#5 avança o tempo de simulação em 5 unidades de tempo. A unidade vem da diretiva \timescaleativa. Com`timescale 1ns / 1ps, #5é 5 nanossegundos. Com`timescale 1us / 1ns, #5é 5 microssegundos. O número pode ser fracionário -#1.5` funciona se sua precisão é mais fina que a unidade.
#delay é sintetizável em Verilog?
Não. #delay só afeta simulação - a ferramenta de síntese ignora ou rejeita. O timing do hardware real vem do sinal de clock e do delay de propagação dos gates, não de declarações #. Use # livremente em testbenches; nunca escreva em RTL sintetizável.