Compilação condicional Verilog `ifdef
A Verilog suporta algumas diretivas de compilador que essencialmente direcionam o compilador a tratar o código de uma determinada maneira. Por exemplo, uma parte do código pode representar uma implementação de um determinado recurso e deve haver alguma maneira de não incluir o código no design se o recurso não for usado.
Isso pode ser resolvido com condicional compilação onde o designer pode envolver o código dentro das diretivas do compilador que informam ao compilador para incluir ou excluir o código para compilação quando o sinalizador nomeado fornecido for definido.
Sintaxe
A compilação condicional pode ser obtida com o Verilog
`ifdef
e `ifndef
palavras-chave. Essas palavras-chave podem aparecer em qualquer lugar no design e podem ser aninhadas uma dentro da outra. A palavra-chave
`ifdef
simplesmente diz ao compilador para incluir a parte do código até o próximo `else
ou `endif
se a macro dada chamada FLAG for definida usando um `define
diretiva.
// Style #1: Only single `ifdef
`ifdef <FLAG>
// Statements
`endif
// Style #2: `ifdef with `else part
`ifdef <FLAG>
// Statements
`else
// Statements
`endif
// Style #3: `ifdef with additional ifdefs
`ifdef <FLAG1>
// Statements
`elsif <FLAG2>
// Statements
`elsif <FLAG3>
// Statements
`else
// Statements
`endif
A palavra-chave
`ifndef
simplesmente diz ao compilador para incluir a parte do código até o próximo `else
ou `endif
se a macro dada chamada FLAG for não definido usando um `define
diretiva. 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
Banco de teste
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
Observe que, por padrão, rstn não será incluído durante a compilação do projeto e, portanto, não aparecerá na lista de portões. No entanto, se uma macro chamada INCLUDE_RSTN for definida em qualquer arquivo Verilog que faça parte da lista de arquivos de compilação ou passada pela linha de comando para o compilador, rstn será incluído na compilação e o design o terá.
Experimente adicionando e removendo +define+INCLUDE_RSTN de 'Compile &Run Options' no painel esquerdo para saber a diferença.
Exemplo do Verilog `ifdef `elsif
O exemplo a seguir tem duas instruções de exibição dentro de
`ifdef
separadas escopos que não possuem um padrão `else
parte para isso. Portanto, isso significa que, por padrão, nada será exibido. Se a macro ou MACRO estiver definida, a mensagem de exibição correspondente será incluída e será exibida durante a simulação
module tb;
initial begin
`ifdef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Registro de simulação # With no macros defined ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # With +define+MACRO1 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # With +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Exemplo Verilog `ifndef `elsif
O mesmo código pode ser escrito com
`ifndef
e os resultados serão exatamente o oposto.
module tb;
initial begin
`ifndef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Registro de simulação # With no macros defined ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # With +define+MACRO1 ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # With +define+MACRO2 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # With +define+MACRO1 +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Exemplo de ifdef aninhado em Verilog
`ifdef
e seus sabores podem ser aninhados um dentro do outro para criar formas complexas de inclusão e exclusão de código com macros definidas.
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
Registro de simulação # Without defining any macro ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # With +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. # With +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. # With +define+FLAG ncsim> run FLAG is defined Only FLAG is defined ncsim: *W,RNQUIE: Simulation is complete. # With +define+WHITE ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # With +define+NEST1_A ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete.
Observe que, enquanto a macro pai não estiver definida, a definição de qualquer outra macro aninhada dentro dela não será compilada. Por exemplo, definições de macro NEST1_A ou WHITE sem FLAG não fazem o compilador pegar o código aninhado.
Verilog