Verilog `ifdef: Bedingte Kompilierung erklärt
Verilog unterstützt einige Compiler-Direktiven, die im Wesentlichen den Compiler anweisen, den Code auf eine bestimmte Weise zu behandeln. Zum Beispiel kann ein Teil des Codes die Implementierung eines bestimmten Features darstellen, und es sollte eine Möglichkeit geben, den Code nicht in das Design einzubeziehen, wenn das Feature nicht verwendet wird.
Dies kann mit bedingter Kompilierung gelöst werden, bei der der Designer den Code in Compiler-Direktiven einpackt, die dem Compiler sagen, den Code für die Kompilierung entweder einzuschließen oder auszuschließen, wenn das gegebene benannte Flag gesetzt ist.
Syntax
Bedingte Kompilierung kann mit den Verilog-Schlüsselwörtern `ifdef und `ifndef erreicht werden. Diese Schlüsselwörter können an beliebiger Stelle im Design auftreten und können ineinander verschachtelt werden.
Das Schlüsselwort `ifdef sagt dem Compiler einfach, den Code bis zum nächsten `else oder `endif einzuschließen, wenn das gegebene Makro namens FLAG mit einer `define-Direktive definiert ist.
// Stil #1: Nur einzelnes `ifdef
`ifdef <FLAG>
// Anweisungen
`endif
// Stil #2: `ifdef mit `else-Teil
`ifdef <FLAG>
// Anweisungen
`else
// Anweisungen
`endif
// Stil #3: `ifdef mit zusätzlichen ifdefs
`ifdef <FLAG1>
// Anweisungen
`elsif <FLAG2>
// Anweisungen
`elsif <FLAG3>
// Anweisungen
`else
// Anweisungen
`endif
Das Schlüsselwort `ifndef sagt dem Compiler einfach, den Code bis zum nächsten `else oder `endif einzuschließen, wenn das gegebene Makro namens FLAG nicht mit einer `define-Direktive definiert ist.
Design-Beispiel mit `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
Beachten Sie, dass standardmäßig rstn nicht in die Kompilierung des Designs einbezogen wird und daher nicht in der Portliste erscheint. Wenn jedoch ein Makro namens INCLUDE_RSTN entweder in einer Verilog-Datei definiert wird, die Teil der Kompilierungsliste der Dateien ist, oder über die Befehlszeile an den Compiler übergeben wird, wird rstn in die Kompilierung einbezogen und das Design wird es haben.
Experimentieren Sie, indem Sie +define+INCLUDE_RSTN in den 'Compile & Run Options' im linken Bereich hinzufügen und entfernen, um den Unterschied zu sehen.
Verilog `ifdef `elsif Beispiel
Das folgende Beispiel hat zwei Display-Anweisungen in separaten `ifdef-Bereichen, die keinen Standard-`else-Teil haben. Das bedeutet, dass standardmäßig nichts angezeigt wird. Wenn entweder das Makro MACRO1 oder MACRO2 definiert ist, wird die entsprechende Display-Meldung eingeschlossen und während der Simulation angezeigt.
module tb;
initial begin
`ifdef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Simulationslog:
# Ohne definierte Makros ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+MACRO1 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Verilog `ifndef `elsif Beispiel
Derselbe Code kann mit `ifndef geschrieben werden, und die Ergebnisse sind genau entgegengesetzt.
module tb;
initial begin
`ifndef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
Simulationslog:
# Ohne definierte Makros ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+MACRO1 ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+MACRO2 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+MACRO1 +define+MACRO2 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Verilog Verschachteltes `ifdef Beispiel
`ifdef und seine Varianten können ineinander verschachtelt werden, um komplexe Arten der Code-Ein- und -Ausschluss mit definierten Makros zu erstellen.
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
Simulationslog:
# Ohne Definition irgendeines Makros ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # Mit +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. # Mit +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. # Mit +define+FLAG ncsim> run FLAG is defined Only FLAG is defined ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+WHITE ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # Mit +define+NEST1_A ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete.
Beachten Sie, dass solange das übergeordnete Makro nicht definiert ist, die Definition irgendeines anderen verschachtelten Makros innerhalb davon den Compiler nicht veranlasst, den verschachtelten Code aufzunehmen. Zum Beispiel führen NEST1_A- oder WHITE-Makrodefinitionen ohne FLAG nicht dazu, dass der Compiler den verschachtelten Code aufnimmt.
Verilog
- Verilog meistern: Komplettes Tutorial für digitales Schaltungsdesign
- Verilog Concatenation meistern: Praktischer Leitfaden
- Verilog Assignments verstehen: Typen, Syntax und Best Practices
- Verilog Blocking vs. Non-Blocking: Wichtige Unterschiede erklärt
- Verilog Functions meistern für effizientes RTL-Design
- Verilog Tasks verstehen: Functions vs. Tasks, Syntax und Verwendung
- Verilog Clock Generator: Design & Implementierungsleitfaden
- Verilog Display Tasks meistern: Effizientes Debugging & Logging
- Verilog Math Functions meistern für effizientes Hardware-Design
- Verilog $timeformat meistern: Präzision und Anzeigesteuerung