Entendendo Atrasos Inter- e Intra-Atribuição em Verilog
Instruções de atraso em Verilog podem ter atrasos especificados no lado esquerdo ou direito do operador de atribuição.
Atrasos Inter-Atribuição (Inter-assignment Delays)
// Atraso especificado no lado esquerdo
#<atraso> <LHS> = <RHS>
Uma instrução de atraso inter-atribuição tem valor de atraso no LHS. Indica que a instrução é executada após o atraso expirar, sendo a forma mais comum de controle de atraso.
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// Inicializa todos sinais em 0 no tempo 0
a <= 0; b <= 0; c <= 0; q <= 0;
// Atraso inter-atribuição: espera #5 e atribui a e c = 1
// 'a' e 'c' atualizados no fim do timestep atual
#5 a <= 1; c <= 1;
// Atraso inter-atribuição: espera #5 e atribui q com valor avaliado do RHS
#5 q <= a & b | c;
#20;
end
endmodule
Note que q torna-se 1 no tempo 10 porque a instrução é avaliada em 10 unidades e RHS (combinação de a, b, c) avalia para 1.
Log de Simulação
xcelium> run [0] a=0 b=0 c=0 q=0 [5] a=1 b=0 c=1 q=0 [10] a=1 b=0 c=1 q=1 xmsim: *W,RNQUIE: Simulation is complete.
Atrasos Intra-Atribuição (Intra-assignment Delays)
// Atraso especificado no lado direito
<LHS> = #<atraso> <RHS>
Um atraso intra-atribuição tem atraso no RHS. Indica que a instrução é avaliada e valores de todos sinais no RHS são capturados primeiro. Então atribuído ao sinal resultante apenas após o atraso expirar.
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// Inicializa todos sinais em 0 no tempo 0
a <= 0; b <= 0; c <= 0; q <= 0;
// Atraso inter-atribuição: espera #5 e atribui a e c = 1
#5 a <= 1; c <= 1;
// Atraso intra-atribuição: primeiro executa a instrução,
// espera 5 unidades e atribui valor avaliado a q
q <= #5 a & b | c;
#20;
end
endmodule
Note que a atribuição a q está ausente no log!
Log de Simulação
xcelium> run [0] a=0 b=0 c=0 q=0 [5] a=1 b=0 c=1 q=0 xmsim: *W,RNQUIE: Simulation is complete.
Isso ocorre porque no tempo 5, a e c são atribuídos via non-blocking. O comportamento de non-blocking é avaliar RHS, mas atribuir à variável apenas no fim do timestep.
O valor de a e c é avaliado como 1 mas ainda não atribuído quando a próxima instrução non-blocking (q) executa. Ao avaliar RHS de q, a e c ainda têm valor antigo 0, então $monitor não detecta mudança para exibir.
Para observar a mudança, mudamos atribuições de a e c de non-blocking para blocking.
...
// Non-blocking mudado para blocking, resto igual
#5 a = 1; c = 1;
q <= #5 a & b | c;
...
Log de Simulação
xcelium> run [0] a=0 b=0 c=0 q=0 [5] a=1 b=0 c=1 q=0 [10] a=1 b=0 c=1 q=1 xmsim: *W,RNQUIE: Simulation is complete.
Verilog
- Verilog Básico: Projetando sua Primeira Porta AND
- Domine o Verilog: Tutorial Completo para Projeto de Circuitos Digitais
- Dominando Concatenação Verilog: Guia Prático
- Entendendo Atribuições em Verilog: Tipos, Sintaxe e Boas Práticas
- Verilog Blocking vs Non-Blocking: Diferenças Essenciais Explicadas
- Dominando Funções em Verilog para Design RTL Eficiente
- Entendendo Tasks em Verilog: Funções vs Tasks, Sintaxe e Uso
- Entendendo Controle de Atraso em Verilog: Técnicas de Timing e Boas Práticas
- Entendendo Atrasos de Porta em Verilog: Timing Preciso para Designs Digitais Confiáveis
- Gerador de Clock Verilog: Guia de Design e Implementação