Verilog `ifdef: Compilação Condicional Explicada
Verilog suporta diretivas de compilador que direcionam como o código deve ser tratado. Por exemplo, uma parte do código pode implementar um recurso e deve haver forma de não incluí-lo se o recurso não for usado.
Isso é resolvido com compilação condicional, onde o designer envolve o código em diretivas que dizem ao compilador para incluir ou excluir o código quando uma flag nomeada está definida.
Sintaxe
Compilação condicional usa `ifdef e `ifndef. Podem aparecer em qualquer lugar no design e ser aninhadas.
`ifdef diz ao compilador para incluir o código até o próximo `else ou `endif se a macro FLAG estiver definida via `define.
// Estilo #1: Apenas `ifdef
`ifdef <FLAG>
// Instruções
`endif
// Estilo #2: `ifdef com `else
`ifdef <FLAG>
// Instruções
`else
// Instruções
`endif
// Estilo #3: `ifdef com `elsif adicionais
`ifdef <FLAG1>
// Instruções
`elsif <FLAG2>
// Instruções
`elsif <FLAG3>
// Instruções
`else
// Instruções
`endif
`ifndef inclui o código se a macro FLAG não estiver definida via `define.
Exemplo de Design com `ifdef
module my_design (
input clk, d,
`ifdef INCLUDE_RSTN
input rstn,
`endif
output reg q
);
always @ (posedge clk) begin
`ifdef INCLUDE_RSTN
if (!rstn) begin
q <= 0;
end else
`endif
begin
q <= d;
end
end
endmodule
Testbench
module tb;
reg clk, d, rstn;
wire q;
reg [3:0] delay;
my_design u0 (
.clk(clk),
.d(d),
`ifdef INCLUDE_RSTN
.rstn(rstn),
`endif
.q(q)
);
always #10 clk = ~clk;
initial begin
integer i;
{d, rstn, clk} <= 0;
#20 rstn <= 1;
for (i = 0; i < 20; i=i+1) begin
delay = $random;
#(delay) d <= $random;
end
#20 $finish;
end
endmodule
Por padrão, rstn não será incluído na compilação e não aparecerá na portlist. Se a macro INCLUDE_RSTN for definida em qualquer arquivo Verilog da lista de compilação ou passada via linha de comando, rstn será incluído.
Experimente adicionar/remover +define+INCLUDE_RSTN em 'Compile & Run Options' para ver a diferença.
Exemplo Verilog `ifdef `elsif
Duas instruções display em escopos `ifdef` separados sem `else` padrão. Por padrão nada é exibido. Se MACRO1 ou MACRO2 for definida, a mensagem correspondente é incluída.
module tb;
initial begin
`ifdef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Log de Simulação
# Sem macros definidas ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # Com +define+MACRO1 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Com +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Exemplo Verilog `ifndef `elsif
Mesmo código com `ifndef, resultados opostos.
module tb;
initial begin
`ifndef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Log de Simulação
# Sem macros definidas ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Com +define+MACRO1 ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # Com +define+MACRO2 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Com +define+MACRO1 +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Exemplo Verilog `ifdef Aninhado
`ifdef e variantes podem ser aninhadas para criar formas complexas de inclusão/exclusão.
module tb;
initial begin
`ifdef FLAG
$display ("FLAG is defined");
`ifdef NEST1_A
$display ("FLAG and NEST1_A are defined");
`ifdef NEST2
$display ("FLAG, NEST1_A and NEST2 are defined");
`endif
`elsif NEST1_B
$display ("FLAG and NEST1_B are defined");
`ifndef WHITE
$display ("FLAG and NEST1_B are defined, but WHITE is not");
`else
$display ("FLAG, NEST1_B and WHITE are defined");
`endif
`else
$display ("Only FLAG is defined");
`endif
`else
$display ("FLAG is not defined");
`endif
end
endmodule
Log de Simulação
# Sem definir macro ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # Com +define+FLAG +define+NEST1_B ncsim> run FLAG is defined FLAG and NEST1_B are defined FLAG and NEST1_B are defined, but WHITE is not ncsim: *W,RNQUIE: Simulation is complete. # Com +define+FLAG +define+NEST1_B +define+WHITE ncsim> run FLAG is defined FLAG and NEST1_B are defined FLAG, NEST1_B and WHITE are defined ncsim: *W,RNQUIE: Simulation is complete. # Com +define+FLAG ncsim> run FLAG is defined Only FLAG is defined ncsim: *W,RNQUIE: Simulation is complete. # Com +define+WHITE ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # Com +define+NEST1_A ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete.
Note que enquanto o macro pai não for definido, definições de macros aninhadas não são compiladas. Por exemplo, NEST1_A ou WHITE sem FLAG não fazem o compilador incluir o código aninhado.
Verilog
- 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
- Gerador de Clock Verilog: Guia de Design e Implementação
- Dominando Tarefas de Display do Verilog: Depuração e Logging Eficientes
- Dominando Funções Matemáticas do Verilog para Design de Hardware Eficiente
- Dominando $timeformat do Verilog: Precisão e Controle de Exibição