🤨
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