Verilog `ifdef:条件付きコンパイルの解説
Verilogはいくつかのコンパイラディレクティブをサポートしており、これらは本質的にコンパイラにコードを特定の方法で扱うよう指示します。例えば、コードの一部がある機能の実装を表しており、その機能が使用されない場合はコードを設計に含めない方法が必要です。
これは条件付きコンパイルで解決できます。設計者はコードをコンパイラディレクティブでラップし、与えられた名前付きフラグが設定されているときにコードをコンパイルに含めるか除外するかをコンパイラに指示できます。
構文
条件付きコンパイルは、Verilogの`ifdefと`ifndefキーワードで実現できます。これらのキーワードは設計のどこにでも出現でき、互いにネストできます。
キーワード`ifdefは、`defineディレクティブを使用して与えられたマクロ(FLAGと呼ばれる)が定義されている場合、次の`elseまたは`endifまでのコード片を含めるようコンパイラに指示します。
// スタイル #1: 単一の`ifdefのみ
`ifdef <FLAG>
// 文
`endif
// スタイル #2: `else部分ありの`ifdef
`ifdef <FLAG>
// 文
`else
// 文
`endif
// スタイル #3: 追加のifdefありの`ifdef
`ifdef <FLAG1>
// 文
`elsif <FLAG2>
// 文
`elsif <FLAG3>
// 文
`else
// 文
`endif
キーワード`ifndefは、`defineディレクティブを使用して与えられたマクロ(FLAGと呼ばれる)が定義されていない場合、次の`elseまたは`endifまでのコード片を含めるようコンパイラに指示します。
`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
テストベンチ
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
デフォルトでは、rstnは設計のコンパイル時に含まれず、ポートリストに現れません。しかし、コンパイル対象ファイルリストに含まれる任意のVerilogファイルで、またはコンパイラへのコマンドライン引数として、INCLUDE_RSTNというマクロが定義されている場合、rstnはコンパイルに含まれ、設計に現れます。
左ペインの'Compile & Run Options'から+define+INCLUDE_RSTNを追加/削除して違いを確認してください。
Verilog `ifdef `elsif の例
以下の例では、デフォルトの`else部分を持たない別々の`ifdefスコープ内に2つのdisplay文があります。したがって、デフォルトでは何も表示されません。マクロMACRO1またはMACRO2のいずれかが定義されている場合、対応する表示メッセージが含まれ、シミュレーション中に表示されます。
module tb;
initial begin
`ifdef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
# マクロ未定義の場合 ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # +define+MACRO1の場合 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # +define+MACRO2の場合 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Verilog `ifndef `elsif の例
同じコードを`ifndefで書くと、結果は逆になります。
module tb;
initial begin
`ifndef MACRO1
$display ("This is MACRO1");
`elsif MACRO2
$display ("This is MACRO2");
`endif
end
endmodule
# マクロ未定義の場合 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # +define+MACRO1の場合 ncsim> run ncsim: *W,RNQUIE: Simulation is complete. # +define+MACRO2の場合 ncsim> run This is MACRO1 ncsim: *W,RNQUIE: Simulation is complete. # +define+MACRO1 +define+MACRO2の場合 ncsim> run This is MACRO2 ncsim: *W,RNQUIE: Simulation is complete.
Verilog ネストした `ifdef の例
`ifdefとその変種は、複雑なコードの包含/除外を定義済みマクロで作成するために、互いにネストできます。
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
# マクロ未定義の場合 ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # +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. # +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. # +define+FLAGのみの場合 ncsim> run FLAG is defined Only FLAG is defined ncsim: *W,RNQUIE: Simulation is complete. # +define+WHITEのみの場合 ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete. # +define+NEST1_Aのみの場合 ncsim> run FLAG is not defined ncsim: *W,RNQUIE: Simulation is complete.
親マクロが定義されていない限り、その中にネストされた他のマクロの定義はコンパイルされないことに注意してください。例えば、FLAGなしでNEST1_AやWHITEマクロを定義しても、コンパイラはネストされたコードを拾いません。
Verilog
- Verilogマスター:デジタル回路設計のための完全チュートリアル
- Verilog連結マスター:実践ガイド
- Verilog代入文の理解:種類、構文、ベストプラクティス
- Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
- Verilog関数のマスター:効率的なRTL設計のために
- Verilogタスクの理解:関数との違い、構文、使用法
- Verilogクロックジェネレータ:設計と実装ガイド
- Verilog表示タスクのマスター:効率的なデバッグとログ出力
- Verilog数学関数のマスター:効率的なハードウェア設計のために
- Verilog $timeformatのマスター:精度と表示制御
- 任意のスコープでのVerilog timescale理解と表示