generate 構文の概要
Verilog における generate 構文は、ハードウェアの記述において反復的な構造や条件付きのインスタンス化を効率的に行うための機能です。この構文を用いることで、同じモジュールを多数並列に配置する場合や、パラメータに応じて回路構成を変更する場合に、コードの冗長性を削減し、保守性を向上させることができます。主に generate_for、generate_if、generate_case の 3 種類のブロックが存在します。
generate_for 構文
ループ処理を用いて、同一の回路ブロックを複数回生成したい場合に使用します。ループ変数には genvar 型を宣言する必要があります。この構文は、バスのビット幅変更やアレイ構造の作成に適しています。
generate
for (genvar idx = 0; idx < WIDTH; idx = idx + 1) begin : loop_label
// 繰り返し生成される回路記述
end
endgenerate
generate_if 構文
パラメータや定数条件に基づいて、特定の回路ブロックを生成するか否かを決定します。コンパイル時の条件分岐として機能するため、合成結果に直接影響を与えます。
generate
if (PARAM_FLAG) begin : true_block
// 条件が真の場合に生成される回路
end else begin : false_block
// 条件が偽の場合に生成される回路
end
endgenerate
generate_case 構文
式の評価値に応じて、複数の回路ブロックの中から一つを選択して生成します。複数の動作モードを持つ設計などで有用です。
generate
case (MODE_SELECT)
2'b00: begin : mode_idle
// モード 0 用の回路
end
2'b01: begin : mode_active
// モード 1 用の回路
end
default: begin : mode_default
// デフォルトの回路
end
endcase
endgenerate
実装例:パラメータ付きバス反転回路
以下の例では、generate_for を使用して、パラメータ DATA_WIDTH で指定されたビット幅分の反転ゲートを一括生成しています。
module BusInverter (
input wire [DATA_WIDTH-1:0] data_in,
output wire [DATA_WIDTH-1:0] data_out
);
parameter DATA_WIDTH = 8;
genvar k;
generate
for (k = 0; k < DATA_WIDTH; k = k + 1) begin : invert_loop
assign data_out[k] = ~data_in[k];
end
endgenerate
endmodule
実装例:条件付きデバッグロジック
generate_if を活用し、パラメータ ENABLE_DEBUG が 1 の場合のみ、監視用のレジスタ段を挿入する設計です。これにより、デバッグ機能の有無を合成時に切り替えられます。
module DebugWrapper (
input wire clk,
input wire raw_signal,
output reg processed_signal
);
parameter ENABLE_DEBUG = 1;
generate
if (ENABLE_DEBUG) begin : debug_path
always @(posedge clk) begin
processed_signal <= raw_signal;
end
end else begin : direct_path
assign processed_signal = raw_signal;
end
endgenerate
endmodule
実装例:動作モードによる回路選択
generate_case を使用して、入力されたモードコードに応じて異なる論理処理をハードウェアとして生成します。
module ModeSelector (
input wire [1:0] op_code,
input wire a, b,
output reg y
);
generate
case (op_code)
2'b00: begin : logic_and
always @(*) y = a & b;
end
2'b01: begin : logic_or
always @(*) y = a | b;
end
default: begin : logic_hold
always @(*) y = a;
end
endcase
endgenerate
endmodule
generate 構文の適用場面
大規模な反復構造
メモリアレイ、マルチビット加算器、シフトレジスタなど、同一セルを多数並べる必要がある設計では、generate_for を使用することで、手動でのコピー&ペーストを避け、ビット幅変更への対応を容易にします。
設定可能な機能ブロック
IP コアや汎用モジュールにおいて、特定の機能をオン・オフ切り替えたい場合、generate_if を使用します。これにより、単一のソースコードから多种多様な回路バリエーションを生成可能です。
多様な動作モードの実装
プロトコル制御や状態機械において、モードごとに全く異なる回路構成が必要な場合、generate_case を用いることで、各モード専用のハードウェアリソースを最適化して割り当てることができます。
コードの構造化と保守性
条件付きコンパイルディレクティブ(`ifdef`)を用いる方法と比較して、generate 構文は Verilog の文法として統合されているため、ツールの解析が容易で、コードの可読性と構造化が促進されます。