🤨

SystemVerilogにおけるforeachステートメントまとめ

に公開

foreach は SystemVerilog の配列要素を反復処理するループ構文です。固定配列、動的配列、連想配列、キューなど、幅広い配列型に対応します。


1. 基本構文

string words[2] = '{ "hello", "world" };

foreach (words[i])
  $display("index=%0d, value=%s", i, words[i]);
  • i はループ変数(事前宣言不要)。
  • 暗黙の begin-end ブロックが生成され、変数はローカルスコープ。
  • 配列名と同じ名前をループ変数に使うのはエラー。

2. 型とループ変数

  • 固定/動的配列 → インデックスは int に暗黙キャスト。
  • 連想配列 → インデックス型がそのままループ変数型に。
  • 読み取り専用 → ループ変数は書き換え不可。
int arr[5] = '{0,1,2,3,4};
foreach (arr[i]) $display("%0d", arr[i]);

bit [7:0] aa[string];
aa["apple"] = 1;
foreach (aa[key]) $display("%s=%0d", key, aa[key]);

3. 多次元配列と反復順序

unpacked 多次元配列

unpacked 配列は 次元宣言の左から右へ 順に処理されます。
ネストされた for ループと等価。

//   次元番号 → 1    2    3
int A[2][3][4];

foreach (A[i, j, k]) begin
  $display("A[%0d][%0d][%0d]", i, j, k);
end
// i:0→1, j:0→2, k:0→3 の順に反復

packed 配列 + unpacked 配列の混在

unpacked 配列の次元が より高い優先順位でループ変数に割り当てられます。
反復順序は unpacked 次元 → packed 次元 の順。

// packed : [3:0][2:1] → 次元番号 3,4
// unpacked : [5:1][4] → 次元番号 1,2
bit [3:0][2:1] B [5:1][4];

foreach (B[q, r, , s]) begin
  $display("q=%0d r=%0d s=%0d", q, r, s);
end

// q : 5→1
// r : 0→3
// s : 2→1
// (3番目のインデックスはスキップ)

⚠️ 注意:

  • ループ変数の並び順は配列宣言次元の順序に従う。
  • スキップしたい次元はカンマを残して省略可能。

4. 制約ブロックでの利用

制約ブロックでは 配列要素ごとに制約を課す用途でよく使われます。

class Packet;
  rand bit [7:0] data[4];

  constraint c {
    foreach (data[i]) data[i] inside { [0:15] };
  }
endclass

まとめ

  • foreach は配列専用のループで、ループ変数は暗黙に宣言される。
  • 反復順序は unpacked → packed の優先順位を守る。
  • 多次元配列のループ変数数は次元数以下で、スキップも可能。

Discussion