Compilación condicional de Verilog `ifdef
Verilog admite algunas directivas del compilador que esencialmente le indican al compilador que trate el código de cierta manera. Por ejemplo, una parte del código puede representar una implementación de una función determinada y debe haber alguna forma de no incluir el código en el diseño si la función no se usa.
Esto se puede resolver con condicional compilación donde el diseñador puede envolver el código dentro de las directivas del compilador que le indican al compilador que incluya o excluya el código para la compilación cuando se establece el indicador con nombre dado.
Sintaxis
La compilación condicional se puede lograr con Verilog `ifdef
y `ifndef
palabras clave Estas palabras clave pueden aparecer en cualquier parte del diseño y pueden anidarse una dentro de otra.
La palabra clave `ifdef
simplemente le dice al compilador que incluya el fragmento de código hasta el próximo `else
o `endif
si la macro dada llamada FLAG se define usando un `define
directiva.
// 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
La palabra clave `ifndef
simplemente le dice al compilador que incluya la pieza de código hasta el siguiente `else
o `endif
si la macro dada llamada FLAG es no definido usando un `define
directiva.
Ejemplo de diseño con `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 pruebas
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
Tenga en cuenta que, de forma predeterminada, rstn no se incluirá durante la compilación del diseño y, por lo tanto, no aparecerá en la lista de puertos. Sin embargo, si se define una macro denominada INCLUDE_RSTN en cualquier archivo Verilog que forme parte de la lista de archivos de compilación o se pasa a través de la línea de comandos al compilador, rstn se incluirá en la compilación y el diseño lo tendrá.
Experimente agregando y eliminando +define+INCLUDE_RSTN de 'Opciones de compilación y ejecución' en el panel izquierdo para conocer la diferencia.
Ejemplo de Verilog `ifdef `elsif
El siguiente ejemplo tiene dos declaraciones de visualización dentro de `ifdef
separados ámbitos que no tienen un `else
predeterminado parte de ello. Esto significa que, de forma predeterminada, no se mostrará nada. Si se define la macro MACRO, se incluye el mensaje de visualización correspondiente y se mostrará durante la simulación
module tb;
initial begin
`ifdef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Registro de simulación # 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.
Ejemplo de Verilog `ifndef `elsif
El mismo código se puede escribir con `ifndef
y los resultados serán todo lo contrario.
module tb;
initial begin
`ifndef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Registro de simulación # 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.
Ejemplo de `ifdef anidado de Verilog
`ifdef
y sus sabores se pueden anidar uno dentro del otro para crear formas complejas de inclusión y exclusión de código con 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 simulación # 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.
Tenga en cuenta que mientras la macro principal no esté definida, la definición de cualquier otra macro anidada dentro de ella no se compila. Por ejemplo, las definiciones de macro NEST1_A o WHITE sin FLAG no hacen que el compilador recoja el código anidado.
Verilog