[Verilog][SystemVerilog] generate の使い方:for(genvar)・if・case で複数インスタンス

Verilog 2001 から generate 構文を使って、module, assertion 等のインスタンスや、assign による接続などができます。ここではループを使った生成の話です。

Loop generate

for loop 構文を使って複数インスタンスができます。loop generate の場合、genvar で generate 用の変数を宣言して for loop 内で使います。

gistfile1.v
genvar i;
for (i = 0; i < SIZE; i = i + 1) begin
    // module m を SIZE 個インスタンス
    m i_m(.clk(clk), .rst_n(rst_n), .x(x[i]), .y(y));
end

変数 i はコンパイル時のみ使われ、シミュレーション時には存在しません。

generate ~ endgenerate キーワード

generate ~ endgenerate というキーワードを使って、generate 箇所を明示できます。Verilog 2005(IEEE 1364-2005)からは書いても書かなくても同じです(Verilog 2001 では必須でした)。

genvar は generate ~ endgenerate の内外どちらにも記述できますが、変数のスコープは影響しないので、外側に書く方がわかりやすいと思う。

gistfile1.v
generate
    genvar i;
    for (i = 0; i < SIZE; i = i + 1) begin
        m i_m(.clk(clk), .rst_n(rst_n), .x(x[i]), .y(y));
    end
endgenerate

generate
    for (i = 0; i < SIZE; i = i + 1) begin // 上記宣言の genvar i が有効
        m i_m(.clk(clk), .rst_n(rst_n), .x(x[i]), .y(y));
    end
endgenerate

genvar の有効範囲を for の中だけにしたい場合は、後述の SystemVerilog の書き方を使います。

階層の名前付け

loop generate によりひとつ新しい階層ができます。
ラベルを付けて、generate block の名前を決められます。

gistfile1.v
// foo[0].i_m ~ foo[SIZE-1].i_m がインスタンスされる
for (i = 0; i < SIZE; i = i + 1) begin : foo
    m i_m(.clk(clk), .rst_n(rst_n), .x(x[i]), .y(y));
end

名前を付けない場合

ラベルを付けないと、genblk1 のような名前が自動で付きます(数字は、そのモジュールの中で何番目の generate 構文か)。インスタンスの階層名は genblk1[0].i_m のようになります。階層名で参照することがあるなら、ラベルを付けておくほうが確実です。

SystemVerilog の記述

SystemVerilog の場合、for 内に genvar を記述できます。

gistfile1.v
for (genvar i = 0; i < SIZE; i++) begin
    m i_m(.clk(clk), .rst_n(rst_n), .x(x[i]), .y(y));
end

この場合、変数 i は、この for loop 内でのみ有効です。

条件による generate(if / case)

パラメーターの値によって、インスタンスするものを切り替えることもできます。条件はコンパイル時に決まる値(パラメーターなど)でなければなりません。

generate
    if (USE_FIFO) begin : g_fifo
        fifo i_buf(.clk(clk), .rst_n(rst_n), .x(x), .y(y));
    end
    else begin : g_reg
        reg_buf i_buf(.clk(clk), .rst_n(rst_n), .x(x), .y(y));
    end
endgenerate

case でも書けます。

case (WIDTH)
    8:       begin : g8   m8   i_m(.x(x), .y(y)); end
    16:      begin : g16  m16  i_m(.x(x), .y(y)); end
    default: begin : gdef mdef i_m(.x(x), .y(y)); end
endcase

See Also

  • IEEE Std 1364™-2005: 12.4.1 Loop generate constructs、12.4.2 Conditional generate constructs、12.4.3 External names for unnamed generate blocks
  • IEEE Std 1800™-2012: 27.4 Loop generate constructs、27.5 Conditional generate constructs、27.6 External names for unnamed generate blocks