systemverilog 入門 - artgraphics.co.jp · systemverilog 入門 ©2018...

268
Artgraphics SystemVerilog 入門 Document Revision: 1.2, 2018.06.06

Upload: lenhan

Post on 01-Jul-2018

250 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

Artgraphics

SystemVerilog 入門

Document Revision: 1.2, 2018.06.06

Page 2: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

©2018 アートグラフィックス

〒124-0012 東京都葛飾区立石 8-14-1

www.artgraphics.co.jp

SystemVerilog Primer

©2018 Artgraphics. All rights reserved.

8-14-1, Tateishi, Katsushika-ku, Tokyo, 124-0012 Japan

www.artgraphics.co.jp

Page 3: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

1

はじめに

この入門書は SystemVerilog の基本的な知識を提供する為に書かれた学習用の素材です。特長は、

SystemVerilog特有の機能を出来るだけ明確に、且つ、正確に記述している事にあります。本書を

通じて、設計及び検証作業に役立つ知識を取得する事を主眼にしています。アサーション、及び、

ファンクショナル・カバレッジの基礎知識の習得にも役立ちます。

本文書中に引用する例は弊社の設計・検証ツールにより確認してありますが、絶対的に正しい記

述であるかは保障の限りではありません。それらの例を実践で使用する場合には、使用者の責任

において実行して下さい。

本書の記述対象である SystemVerilogは、IEEE Std 1800-2012標準規格を基にしています。この規

格を以下では原書(文献[1])と呼ぶ事にします。本書に記述されている記述に関しての更に詳し

い説明、又は、質問・疑問を解消する為には、原書をお読み下さい。

また、本書では原書で使用されている用語をそのままの形で引用する場合が多くなっています。

理由は、対応する適切な日本語訳が見つからないからです。読者自身で適切な翻訳を試みて下さ

い。

Page 4: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

1

変更履歴

日付 Revision 変更点

2018.02.28 1.0 第一版。

2018.04.30 1.1 ① SystemVerilogと Verilogの差異の記述を追加。

② その他、誤字を訂正。

2018.06.06 1.2 ① 各章に於いて説明を補足。

Page 5: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

1

目次

1 概要 ..................................................................................................................................... 1

1.1 設計、仕様、及び検証記述言語としての SYSTEMVERILOG ..............................................1

1.2 VERILOGとの主な差異 .......................................................................................................2

1.2.1 シミュレーションの実行タイミング(simulation semantics) ...............................2

1.2.2 初期化設定と時刻0におけるシミュレーション・イベント ......................................3

1.2.3 豊富なデータ・タイプ ................................................................................................4

1.2.4 信号値の初期値 ...........................................................................................................4

1.3 設計及び検証の為のビルディング・ブロック ...................................................................5

1.3.1 設計要素 ......................................................................................................................5

1.3.2 module ........................................................................................................................5 1.3.3 program ......................................................................................................................6 1.3.4 interface .....................................................................................................................7 1.3.5 checker .......................................................................................................................8 1.3.6 package .......................................................................................................................8 1.3.7 primitive .....................................................................................................................9 1.3.8 configuration ........................................................................................................... 10

1.4 検証パッケージ ............................................................................................................... 10

1.5 本書で用いるシンタックス記法 ...................................................................................... 10

2 データ・タイプ .................................................................................................................. 11

2.1 データ・タイプとデータ・オブジェクト ....................................................................... 11

2.2 LOGIC型 .......................................................................................................................... 11

2.3 単数系と集合系(SINGULAR AND AGGREGATE TYPES) ................................................. 12

2.4 ネットと変数(NETS AND VARIABLES) ......................................................................... 12

2.5 NET型 .............................................................................................................................. 13

2.6 TWO-STATE 型 ................................................................................................................. 13

2.7 FOUR-STATE型 ................................................................................................................ 14

2.8 REAL、SHORTREALと REALTIME..................................................................................... 15

2.9 VOID型 ............................................................................................................................ 15

2.10 CHANDLE型 .................................................................................................................... 15

2.11 CLASS .............................................................................................................................. 15 2.12 STRINGデータ・タイプ .................................................................................................. 15

2.13 EVENTデータ・タイプ ................................................................................................... 18

2.14 TYPEDEF .......................................................................................................................... 19 2.15 ENUM .............................................................................................................................. 20 2.16 CONSTANTS ..................................................................................................................... 22

2.17 CAST オペレータ ............................................................................................................. 23

2.18 $CAST ダイナミック型変換 ............................................................................................. 24

2.19 便利な初期値設定 ........................................................................................................ 25

2.19.1 リテラルの拡張 .................................................................................................... 25

2.19.2 インデックス指定 ................................................................................................. 26

3 メンバーで構成されるデータ・タイプ(AGGREGATE DATA TYPES) ......................... 28

3.1 ストラクチャ(STRUCTURES) ...................................................................................... 28

3.1.1 Packed ストラクチャ(packed structures) ......................................................... 29

3.1.2 ストラクチャへの値の設定 ...................................................................................... 29

3.2 ユニオン(UNIONS) ...................................................................................................... 30

3.2.1 Packedユニオン(packed unions)...................................................................... 31

Page 6: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

2

3.2.2 タグ付きユニオン(tagged unions) ..................................................................... 32

3.3 PACKED アレイと UNPACKEDアレイ(PACKED AND UNPACKED ARRAYS) ................... 32

3.3.1 Packed アレイ(packed arrays) .......................................................................... 32

3.3.2 Unpacked アレイ(unpacked arrays) ................................................................. 33

3.3.3 アレイの操作(operations on arrays) .................................................................. 33

3.3.4 アレイのアクセス(indexing and slicing of arrays) ........................................... 35

3.4 ダイナミック・アレイ(DYNAMIC ARRAYS) ................................................................. 36

3.4.1 New[ ]コンストラクタ ............................................................................................. 36

3.4.2 size()メソッド .......................................................................................................... 37

3.4.3 Delete()メソッド...................................................................................................... 38

3.5 アレイのコピー(ARRAY ASSIGNMENTS) ...................................................................... 38

3.6 ASSOCIATIVE アレイ ........................................................................................................ 40

3.6.1 Associative アレイの要素の登録 ............................................................................. 41

3.6.2 Associative アレイの関数 ........................................................................................ 42

3.6.3 Associative アレイ・リテラル( associative array literals) ............................... 43

3.7 キュー( QUEUES) ......................................................................................................... 44

3.7.1 キューの操作(queue operators) ......................................................................... 45

3.7.2 キューを操作する関数(queue methods) ............................................................ 46

3.8 アレイ情報取得関数(ARRAY QUERYING FUNCTIONS) .................................................. 47

3.9 アレイ操作関数(ARRAY MANIPULATION METHODS) .................................................... 48

3.9.1 アレイ検索関数(array locator methods) ............................................................ 48

3.9.2 アレイ要素の順序を操作する関数(array ordering methods) ............................ 50

3.9.3 アレイを計算する関数(array reduction methods) ............................................ 51

4 クラス(CLASSES)......................................................................................................... 54

4.1 クラスの概要 ................................................................................................................... 54

4.2 クラス・オブジェクト(クラス・インスタンス) ......................................................... 55

4.3 クラス・プロパーティ及びメソッドへのアクセス ......................................................... 55

4.4 コンストラクタ ............................................................................................................... 55

4.5 タイプ指定のコンストラクタ呼び出し ........................................................................... 56

4.6 STATICクラス・プロパーティ ........................................................................................ 57

4.7 STATICクラス・メソッド ............................................................................................... 58

4.8 STATICメンバーの参照 ................................................................................................... 58

4.9 THIS ................................................................................................................................. 59

4.10 ハンドルのアレイ ........................................................................................................ 59

4.11 クラスのコピー ........................................................................................................... 60

4.12 クラスの継承とサブクラス ......................................................................................... 60

4.13 $CAST............................................................................................................................... 61 4.14 VIRTUALメソッド(VIRTUAL METHODS) ...................................................................... 61

4.15 アブストラクト・クラスとピュア・バーチャル・メソッド ....................................... 62

4.16 クラススコープ・オペレータ(CLASS SCOPE RESOLUTION OPERATOR ::) ................ 63

4.17 メンバーへのアクセス制限(LOCAL AND PROTECTED) ............................................. 65

4.18 メソッドをクラスの外に記述する方法 ....................................................................... 65

4.19 パラメータによる汎用クラスの定義(PARAMETERIZED CLASSES) ........................... 66

4.20 クラスのフォワード宣言(TYPEDEF CLASS) ............................................................. 68

4.21 クラス・ハンドルの初期化 ......................................................................................... 70

5 プロセス(PROCESSES) ................................................................................................ 72

5.1 シミュレーション・プロシージャ(STRUCTURED PROCEDURES) ................................ 72

5.1.1 initialプロシージャ ................................................................................................ 72

Page 7: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

3

5.1.2 alwaysプロシージャ ............................................................................................... 73

5.1.3 finalプロシージャ ................................................................................................... 76

5.2 ブロック文(BLOCK STATEMENTS) ............................................................................... 76

5.2.1 begin-endブロック ................................................................................................. 76

5.2.2 fork-joinブロック .................................................................................................... 77

5.2.3 ブロック名(block names) ................................................................................... 80

5.3 タイミングによる実行制御(PROCEDURAL TIMING CONTROLS)................................... 80

5.3.1 遅延による制御(delay control) ........................................................................... 80

5.3.2 イベント制御(event control) .............................................................................. 80

5.3.3 レベル・センシティブ・イベント制御(level-sensitive event control) .............. 81

5.4 プロセス制御(PROCESS CONTROL) .............................................................................. 81

5.4.1 wait fork文 .............................................................................................................. 81

5.4.2 disable fork 文 ......................................................................................................... 83

5.5 ユーザ固有のプロセス制御(FINE-GRAIN PROCESS CONTROL) .................................... 84

6 代入文(ASSIGNMENT STATEMENTS) ...................................................................... 86

6.1 パターン指定による代入(ASSIGNMENT PATTERNS) .................................................... 86

6.2 アレイ・パターン指定代入文 ......................................................................................... 87

6.3 ストラクチャ・パターン指定代入文............................................................................... 88

6.4 UNPACKED ARRAYの初期化 ............................................................................................. 89

7 演算子と式(OPERATORS AND EXPRESSIONS) ........................................................ 92

7.1 演算子 .............................................................................................................................. 92

7.1.1 代入演算子(assignment operators) .................................................................... 92

7.1.2 インクリメント及びデクリメント演算子(++、--) ............................................ 92

7.1.3 冪乗 .......................................................................................................................... 92

7.1.4 比較演算子(equality operators) ......................................................................... 92

7.1.5 ワイルドカード比較演算子(wildcard equality operators) ................................ 93

7.1.6 結合演算子(concatenation operators) ................................................................ 95

7.1.7 inside オペレータ(set membership operator) ................................................... 95

7.1.8 ビット・ストリーム・オペレータ(<<、>>) ....................................................... 96

7.2 オペランド(OPERANDS) .............................................................................................. 98

7.2.1 パートセレクト(part-select) ............................................................................... 98

7.3 タグ付きメンバーの操作 ................................................................................................. 99

8 実行文(PROCEDURAL PROGRAMMING STATEMETNTS).................................... 101

8.1 IF文 ............................................................................................................................... 101

8.1.1 全ての条件を列挙(fully specified) .................................................................... 101

8.1.2 unique-if、unique0-if文 ....................................................................................... 101

8.1.3 priority-if文 .......................................................................................................... 102

8.2 CASE文 .......................................................................................................................... 102

8.2.1 unique-case、unique0-case文 ............................................................................. 103

8.2.2 priority-case 文 ...................................................................................................... 103

8.2.3 inside オペレータと if文及び case文 ................................................................... 104

8.3 ループ文(LOOP STATEMENTS) ................................................................................... 105

8.3.1 for文 ...................................................................................................................... 105

8.3.2 repeat文 ................................................................................................................ 106

8.3.3 foreach文 .............................................................................................................. 106

8.3.4 while 文 .................................................................................................................. 108

8.3.5 do-while 文............................................................................................................. 108

Page 8: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

4

8.4 FOREVER文.................................................................................................................... 109

8.5 RETURN文 ..................................................................................................................... 109

8.6 BREAK文 ........................................................................................................................ 110

8.7 CONTINUE文.................................................................................................................. 111

9 タスクとファンクション(TASKS AND FUNCTIONS) ............................................... 112

9.1 タスク ............................................................................................................................ 112

9.2 ポート・リスト ............................................................................................................. 112

9.3 タスク内の記述 ............................................................................................................. 112

9.4 ファンクション ............................................................................................................. 113

9.4.1 ファンクションの制限 ........................................................................................... 113

9.4.2 ポート・リスト ...................................................................................................... 113

9.4.3 ファンクション内でタイミング制御を行う方法 ................................................... 114

9.5 引数に標準値を指定する方法 ....................................................................................... 115

9.6 値を戻すファンクションの使用 .................................................................................... 117

9.7 再帰呼び出し ................................................................................................................. 117

9.8 クラスのメソッドと再帰呼び出し ................................................................................ 118

9.9 メソッド内での変数の初期化 ....................................................................................... 118

10 クロッキング・ブロック(CLOCKING BLOCKS) ....................................................... 121

10.1 最も簡単なクロッキング・ブロック ......................................................................... 121

10.2 クロッキング・スキュー(CLOCKING SKEW) ......................................................... 121

10.3 サイクル・ディレー(CYCLE DELAY) ..................................................................... 123

11 プロセス間の同期と交信 .................................................................................................. 125

11.1 セマフォ(SEMAPHORES) ........................................................................................ 125

11.2 メール・ボックス(MAILBOXES) ............................................................................ 126

11.3 パラメータ化したメール・ボックス(PARAMETERIZED MAILBOXES) .................... 128

11.4 名称付きイベント(NAMED EVENTS) ...................................................................... 129

11.4.1 triggered ................................................................................................................ 130 11.4.2 引数としてのイベント・オブジェクト .............................................................. 131

11.4.3 wait_order文 ......................................................................................................... 132

11.4.4 イベント資源の解放 ........................................................................................... 133

11.4.5 別名(alias) ..................................................................................................... 134

11.4.6 イベントの比較(events comparison) ............................................................ 134

12 アサーション(ASSERTIONS) ..................................................................................... 136

12.1 概要 ............................................................................................................................ 136

12.2 即時実行型アサーション(IMMEDIATE ASSERTIONS) ............................................. 136

12.3 並列型アサーション(CONCURRENT ASSERTIONS) ................................................. 137

12.3.1 アサーションはマルチ・スレッド ..................................................................... 138

12.3.2 サンプリング(sampling) ............................................................................... 138

12.3.3 アサーション・クロック .................................................................................... 138

12.4 ブーリアン式(BOOLEAN EXPRESSIONS) ................................................................ 138

12.5 シーケンス(SEQUENCES)とプロパーティ(PROPERTIES) .................................. 138

12.6 シーケンスの操作(SEQUENCE OPERATIONS) ......................................................... 141

12.6.1 ##m ........................................................................................................................ 142 12.6.2 ##[m:n] .................................................................................................................. 142 12.6.3 [*m] ........................................................................................................................ 143 12.6.4 [*m:n] ..................................................................................................................... 145

Page 9: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

5

12.6.5 [=m] ....................................................................................................................... 146 12.6.6 [=m:n] .................................................................................................................... 147 12.6.7 [->m] ..................................................................................................................... 149

12.6.8 [->m:n] .................................................................................................................. 149

12.6.9 sig throughout seq ................................................................................................ 150 12.6.10 seq1 within seq2 ................................................................................................ 151 12.6.11 seq1 and seq2 .................................................................................................... 152 12.6.12 seq1 or seq2 ....................................................................................................... 153 12.6.13 seq1 intersect seq2 ............................................................................................ 154 12.6.14 first_match (seq) ............................................................................................... 155

12.7 シーケンスへのパラメータ ....................................................................................... 155

12.8 便利なサンプル関数 .................................................................................................. 156

12.8.1 サンプル関数 ...................................................................................................... 156

12.8.2 レベル・センシティブ とエッジ・センシティブ............................................... 157

12.9 メソッド TRIGGERED ................................................................................................. 160

12.10 DEFAULTクロッキング .............................................................................................. 162

12.11 プロパーティ ............................................................................................................. 163

13 チェッカー(CHECKERS) ............................................................................................ 172

13.1 概要 ............................................................................................................................ 172

13.2 チェッカー・インスタンス ....................................................................................... 172

14 制約によるランダム・スティムラスの生成 ...................................................................... 174

14.1 概要 ............................................................................................................................ 174

14.2 ランダム変数(RANDOM VARIABLES) ...................................................................... 175

14.2.1 rand修飾子 ............................................................................................................ 175

14.2.2 randc修飾子 .......................................................................................................... 175

14.3 制約(CONSTRAINTS) .............................................................................................. 176

14.3.1 inside オペレータ .................................................................................................. 177

14.3.2 distオペレータ ...................................................................................................... 179

14.3.3 unique オペレータ ................................................................................................. 180

14.3.4 implication(->) ................................................................................................. 181

14.3.5 foreach ................................................................................................................... 182 14.3.6 乱数決定順序(solve a before b) ..................................................................... 184

14.4 乱数発生関数 ............................................................................................................. 185

14.5 実行時に制約を定義する方法(IN-LINE CONSTRAINTS) ......................................... 186

14.6 ランダム変数の制御 .................................................................................................. 187

14.7 制約の制御 ................................................................................................................. 189

14.8 RANDOMIZE関数によるランダム変数の制御 ................................................................ 190

14.9 STD::RANDOMIZE() ......................................................................................................... 191 14.10 システム関数とメソッド ........................................................................................... 191

14.11 ストラクチャ ............................................................................................................. 193

14.12 条件の否定 !(EXPRESSION INSIDE { SET }) .................................................................. 193

14.13 キューに乱数を発生 .................................................................................................. 194

14.14 チェッカーとしての制約(IN-LINE CONSTRAINT CHECKER) ................................... 195

14.15 制約をテストケース毎に指定する方法 ..................................................................... 197

14.16 RANDCASE .................................................................................................................. 198

15 ファンクショナル・カバレッジ(FUNCTIONAL COVERAGE) ................................... 200

15.1 カバレッジ・モデルの定義(COVERGROUP) ........................................................... 200

15.1.1 covergroup の定義 ................................................................................................. 200

Page 10: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

6

15.1.2 covergroup への引数 ............................................................................................. 201

15.1.3 サンプリングのタイミング指定 ......................................................................... 201

15.1.4 サンプリング関数(sample) ........................................................................... 201

15.1.5 簡単な使用例 ...................................................................................................... 202

15.2 クラス内の COVERGROUP .......................................................................................... 203

15.3 カバー・ポイントの定義(COVERAGE POINTS) ...................................................... 206

15.3.1 ビンの定義 ......................................................................................................... 206

15.3.2 カバー・ポイントの使用 .................................................................................... 208

15.3.3 信号値の遷移(transitions) ............................................................................ 211

15.4 クロス・カバレッジ(CROSS COVERAGE) ............................................................... 213

15.5 カバレッジ・オプション ........................................................................................... 217

16 システム・タスクとシステム関数 .................................................................................... 218

16.1 値変換(CONVERSION FUNCTIONS) ......................................................................... 218

16.2 情報取得関数 ............................................................................................................. 218

16.3 ビット VECTORシステム関数(BIT VECTOR SYSTEM FUNCTIONS) .......................... 220

16.4 エラー処理タスク ...................................................................................................... 221

16.5 $SFORMATと$SFORMATF .............................................................................................. 222

16.6 確率分布関数 ............................................................................................................. 222

16.7 その他のシステム・タスク及びシステム関数 .......................................................... 222

17 プログラム(PROGRAMS) ........................................................................................... 224

17.1 概要 ............................................................................................................................ 224

17.2 プログラムの制御 ...................................................................................................... 224

17.3 シミュレーションの終了 ........................................................................................... 226

18 インターフェース(INTERFACES) .............................................................................. 227

18.1 概要 ............................................................................................................................ 227

18.2 GENERICインターフェースに依る接続......................................................................... 228

18.3 MODPORT ....................................................................................................................... 228 18.4 クロッキング・ブロック ........................................................................................... 228

18.5 パラメータ化したインターフェース(PARAMETERIZED INTERFACES) ................... 228

18.6 VIRTUAL インターフェース(VIRTUAL INTERFACES) .................................................. 230

18.7 クロッキング・ブロックの使用例 ............................................................................ 232

19 パッケージ(PACKAGES) ............................................................................................ 234

19.1 概要 ............................................................................................................................ 234

19.2 パッケージ内のリゾースの参照 ................................................................................ 236

19.3 パッケージをモジュール・ヘッダで IMPORTする方法 ............................................. 236

19.4 STDパッケージ .............................................................................................................. 236

20 モジュール(MODULES) ............................................................................................. 240

20.1 概要 ............................................................................................................................ 240

20.2 ポート・リスト ......................................................................................................... 240

20.2.1 ポートの方向 ...................................................................................................... 240

20.3 パラメータ化したモジュール(PARAMETRIZED MODULES) .................................... 241

20.4 トップ・レベル・モジュール .................................................................................... 242

20.5 モジュール・インスタンス ....................................................................................... 242

20.6 未定義モジュールの宣言(EXTERN MODULES) ....................................................... 245

20.7 階層名称 .................................................................................................................... 246

Page 11: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

7

21 プリプロセッサ(COMPILER DIRECTIVES) .............................................................. 248

21.1 `INCLUDE文 ................................................................................................................... 248

21.2 `DEFINE文 ..................................................................................................................... 248

21.2.1 定数を定義する場合 ........................................................................................... 248

21.2.2 接頭辞及び接尾辞を持つ名称の創成 .................................................................. 250

21.3 文字列内のパラメータ展開 ....................................................................................... 250

21.4 ‘ENDIF文 ........................................................................................................................ 251

21.5 `__FILE__、`__LINE__ ................................................................................................ 251

22 シミュレーション実行モデル(SIMULATION SEMANTICS)...................................... 253

22.1 シミュレーション領域(SIMULATION REGIONS) ..................................................... 253

22.2 #0ディレーの効果 ........................................................................................................ 254

22.3 PROGRAMとクロック・ジェネレータ ........................................................................... 255

23 参考文献 .......................................................................................................................... 257

Page 12: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

1

1 概要

1.1 設計、仕様、及び検証記述言語としての SystemVerilog

SystemVerilogはハードウェア設計、仕様、及び検証を統一的に記述する為の言語です。単なる検

証言語ではありません。デザインを検証する為には仕様との比較が必要になります。その仕様が

検証に使用される言語と同じ言語で記述されていれば、効率的に、且つ、正確に検証を行う事が

出来ます。

例えば、「req 信号が発生したら、1~3クロック以内に ack信号が発生しなければならない」とい

う仕様の検証は、SystemVerilogでは以下の様に書く事が出来ます。

これは SystemVerilog でアサーションと呼ばれる機能です。この仕様をソース・コード中に記述

する事により、設計した内容が仕様に従っているかを検証する事が出来ます。しかも、仕様に従

っていない設計箇所を容易に特定する事が出来ます。

SystemVerilogでは多くのデータ型を使用する事が出来ますが、それらは主として検証作業で使用

されます。例えば、トランザクションの要素を以下の様に定義する事が出来ます。

assert property (@(posedge clk) req ##[1:3] ack)

else $display("@%0t: FAIL",$time);

module test(input clk,req,ack);

default clocking cb @(posedge clk); endclocking

sequence check_req_ack;

req ##[1:3] ack;

endsequence

assert property (check_req_ack)

else $display("@%0t: FAIL",$time);

...

endmodule

typedef enum bit { READ, WRITE } direction_e;

class packet_t;

rand bit [31:0] addr;

rand bit [31:0] data;

rand direction_enum direction;

rand int unsigned transmit_delay;

constraint word_boundary

{

addr[1:0] == 2’b00;

}

covergroup cg;

coverpoint addr;

coverpoint data;

endgroup

function new;

cg = new;

endfunction

endclass

Page 13: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

2

トランザクションのデータ項目値に対して乱数を割り当てる事が出来ます。クラスのメソッド

randomize()関数を呼ぶと rand 属性の付いた上記のメンバーに乱数が割り当てられます。また、制

約を与えて乱数を発生する事も出来ます。例えば、SystemVerilogでは addr の値をワード・バウ

ンダリーに制限する事は容易です。上記の様に制約をクラス内に定義します。必要な時に必要な

だけメソッド randomize()関数を呼ぶ事により効果的にトランザクションを作成する事が出来ます。

しかも、制約を一時的に無効にする事が出来ます。この機能を利用して、エラー状態を持つトラ

ンザクションを簡単に作成する事が出来ます。

ランダムに発生した信号値を基にしたトランザクションを使用して検証を行う場合、結果の検証

も自動的に行なわれなければなりません。所謂、チェッカー(DUT の結果と期待される結果と

の比較を行う機能)の概念が必要になります。SystemVerilogにはそれをサポートする為の機能が

あります。

更に、重複したトランザクションの作成を避け、無駄の無い様に検証を進めなければなりません。

幅広い範囲のトランザクションを効果的に定義する為には、検証が既にカバーした範囲を正しく

認識し、且つ、未検査の範囲を確実に把握する事が必要です。所謂、スコアボード機能が必要に

なります。SystemVerilogの functional coverage機能はその要望に答える機能を提供します。

上記の例では、addr、及び、data のカバレッジを求めています。カバレッジ情報をクラスの外

に定義する事も出来ます。然し、カバレッジ情報をクラス内部に定義するとカバレッジ変数(こ

の例では cg)が自動的に確保される利点があります。その他、カバレッジ・ポイントを自由に

参照する事が出来る利点があります。カバレッジは covergroup クラスのメソッド sample()関数を

呼ぶ事により収集する事が出来ます。例えば、次の様にしてカバレッジ情報を集めます。

この様に、指定したタイミングでカバレッジ情報を集める事が出来ますが、トランザクションが

発生した時は何時でもカバレッジを収集する事も出来ます。例えば、クラス内のメソッド

post_randomize()関数にカバレッジ収集機能を追加する事が出来ます。

この関数 post_randomize()は virtual 関数ではありませんが、クラス毎に異なる定義をする事が出

来ます。関数 randomize()が呼ばれると必ずこの関数も呼ばれます。

以上の例から検証に必要な多くの機能が SystemVerilogに備わっている事が分かります。

1.2 Verilogとの主な差異

1.2.1 シミュレーションの実行タイミング(simulation semantics)

SystemVerilog は単に Verilog に新しい構文を追加しただけではありません。レガシーVerilog と異

なり、SystemVerilog はシミュレーションに関して厳密にタイミングを定義しています。原書

([1])では、そのタイミングを「Simulation Semantics」と呼んでいます。この概念を正しく理解

packet_t packet;

...

assert(packet.randomize());

packet.cg.sample();

class packet_t;

...

function void post_randomize;

cg.sample();

endfunction

endclass

Page 14: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

3

する事が必要です。後章で概略を解説しますが詳細は、原書を参照して下さい。厳密さにより、

シミュレーション結果が Verilogと異なる場合が多く発生します。

1.2.2 初期化設定と時刻0におけるシミュレーション・イベント

SystemVerilogでは変数を宣言した際に初期値を与える事が出来ます。そして、初期値を設定する

シミュレーションのタイミングは Verilogと異なります([2])。次の様な記述を見てみます。

SystemVerilog では、初期値割り当て_reset = 0 はシミュレーションが開始する前に実行しま

す。従って、_reset に関するイベントは時刻 0 では起こりません。一方、アサイン文

request = 1 の様な記述ではシミュレーション時刻 0で requestに関するイベントが起こります。

この為、信号値の初期化の仕方によりシミュレーション結果が Verilogとは異なります。

その他、時刻 0 における初期化設定には注意が必要です。例えば、以下の記述では、状況により

異なるシミュレーション結果が発生します。

時刻 0 に於いて、もし①が②よりも先に実行すれば、②における negedge _reset のイベントは、

時刻 0 に於いて認識されません。逆に、②が①よりも先に実行すれば、時刻 0 に於いて negedge

_resetのイベントは正しく認識されます。この様な race conditionsを避ける為には、例えば、以下

の様にします。

module test;

logic _reset = 0;

logic request;

initial begin

request = 1;

...

end

...

endmodule

initial begin

_reset = 0; ①

...

end

...

always @(posedge clk,negedge _reset) ②

if( !_reset )

q <= 0;

else

q <= d;

initial begin

_reset <= 0; ③

...

end

...

always @(posedge clk,negedge _reset) ④

if( !_reset )

q <= 0;

else

q <= d;

Page 15: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

4

nonblockign assignment(NBA)③は通常の実行文④よりも後に実行します。従って、③が実行す

る前に、negedge _resetのイベントが待ち状態に入っています。

この他、テストベンチが実行するタイミングにも注意が必要です。SystemVerilog の program を使

用してテストベンチを記述すると Verilogのテストベンチと異なる動作をします。programのロジ

ックは reactive region で動作します。DUT で操作する信号の値が安定した後に program のロジッ

クが実行します。詳細は「Simulation Semantics」を参照して下さい。

1.2.3 豊富なデータ・タイプ

SystemVerilog の豊富なデータ・タイプは単なる便利性だけではありません。例えば、

SystemVerilog で追加された two-state データ型(bit、byte、shortin、int、longint 等)は、計算の単

純さからシミュレーションの実行速度の向上につながります。このデータ・タイプの追加により、

for ループの記述で four-state の Verilog integer 型を使用する必要がありません。例えば、for ルー

プを以下の様に記述する事が出来ます。

しかも、i++ は i=i+1よりも高速に実行します。

1.2.4 信号値の初期値

Verilog では信号を wire、reg、又は、integer で宣言する為 four-state です。この為、次のクロッ

ク・ジェネレータは動作しません。

clk の初期値は、clk==1’bx である為、上記のトグル命令が動作しません。先ず最初に、clk

の初期化を実行しなければなりません。Verilogでは、次の様に書かなければなりません。

この記述での問題は、clk = 0; が時刻 0 に於いて信号 clk に関するイベントを誘発してしま

う事です。この問題は、SystemVerilog では簡単に解決します。SystemVerilogには two-state の bit

型があります。bit型の初期値は 1’b0 です。従って、クロック・ジェネレータを次の様に書く事

が出来ます。

clk に初期値 1’b0 を設定する必要はありません。尚、DUT が Verilogスタイルで

for( int i = 0; i < 10; i++ ) begin

...

end

reg clk;

always

#10 clk = ~clk;

reg clk;

initial begin

clk = 0;

forever #10 clk = ~clk;

end

bit clk;

always

#10 clk = ~clk;

Page 16: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

5

の様に書かれていても接続上の問題はありません。

1.3 設計及び検証の為のビルディング・ブロック

1.3.1 設計要素

設計要素とは、module、program、interface、checker、package、primitive、及び、configuration で

す。これらの要素を使用して設計及び検証環境を構築します。

以下では、これらの設計要素の概略を例示しますが、SystemVerilog の知識が十分ではない状況で

本章の内容を理解する事は難しいと考えられます。最初は、本章の内容を参考的に読む事を薦め

ます。本書を読了した後、理解度を確認する意味で、再度本章を読むと効果があると思います。

1.3.2 module

module は基本的なビルディング・ブロックで、主として、デザインを記述する為に使用されます。

検証時のテストベンチを記述する際にも使用する事が出来ます。module は汎用的であり、

SystemVerilog の多くの機能を module 内に定義する事が出来ます。他の設計要素には、その様な

寛容性は許可されていません。例えば、moduleには以下の様な定義を含む事が出来ます。

ポート

データ宣言(信号、変数、struct、union)

コンスタント

class

パッケージに定義されているアイテムのインポート

サブルーティン

module、program、interface、及び primitiveのインスタンス

classオブジェクトのインスタンス

continuous assignment

procedural block

等等

以下に簡単な RTL module の例を示します。この例では、SystemVerilog を使用する利点がありま

せん。単に、従来のデザインをそのまま使用する事が出来る事を示しています。

一点だけ注意するとすれば、always_comb の記述です。Verilogスタイルで書くと

module dut(clk,...);

input clk;

...

endmodule

module FullAdder(output sum,cout,input a,b,cin);

wire w1, w2, w3;

HalfAdder m1(w1,w2,a,b);

HalfAdder m2(sum,w3,w1,cin);

or(cout,w2,w3);

endmodule

module HalfAdder(output sum,cout,input a,b);

always_comb

{cout,sum} = a+b;

endmodule

Page 17: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

6

となります。SystemVerilogにはセンシティビティ・リストを自動生成する機能があります。

1.3.3 program

program はテストベンチを構築する要素として使用されます。デザインに使用する事はありませ

ん。module と異なりインスタンスを持つ事は出来ません。然し、module と同種のデータ定義を

する事が出来ます。また、サブルーティン(タスク、及び、ファンクション)を定義する事も出

来ます。

moduleとの最も大きな差異は、programの実行が reactive regionで行われる事です。即ち、デザイ

ンを実行した後に program が実行します。従って、program が実行する時には、デザインで更新

した信号値が安定した状態にあります。これにより、race freeな環境を構築する事が出来ます。

program では always プロシージャを使用する事は出来ません。initial プロシージャを使用してテ

ストを記述しますが、program に含まれる全ての initial プロシージャが終了するとシミュレーシ

ョンが終了します。この為、UVM 等のパッケージでは program を使用する事は推奨されていま

せん。

program はテストベンチである為、高度なデータ・タイプが使用されるのが一般的です。下記の

例では interfaceを使用しています。

always @(a,b)

{cout,sum} = a+b;

interface simple_if(input bit clk);

logic [1:0] request, grant;

...

endinterface

program test(simple_if sif);

initial begin

@(posedge sif.clk) sif.request <= 1;

repeat (2) @( sif.clk);

...

end

...

endprogram

module top;

bit clk;

simple_if sif(clk);

test TEST(.*);

dut DUT(.*);

initial

forever #10 clk = ~clk;

...

endmodule

Page 18: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

7

1.3.4 interface

interface はポート型の一種で、概念的には、複数の信号を一つの集合に纏める機能であると定義

する事が出来ます。但し、単なる集合ではなく、各信号値を操作する為の手順(プロトコル)を

含む事が出来ます。また、interface を構成する信号の見方をモジュール毎に変える事も出来ます。

例えば、bus_request 信号は、master モジュールでは input であるのに対して、slave モジュールで

は outputとして操作をする事が出来ます。この機能は modportにより実現されます。

interfaceには以下の様な機能を含む事が出来ます。

インターフェース・ポート定義

modports

アサーション

initialプロシージャ

alwaysプロシージャ

finalプロシージャ

クロッキング・ブロック

等々

更に、class と連動すると interface 全体をポインターで引き渡す事が出来ます。この機能は virtual

interfaceとして知られています。この機能により、signalレベルから transaction レベル処理への移

行が可能になります。従って、より抽象度の高い記述を実現する事が出来ます。抽象度が高けれ

ば、記述の再利用度が向上します。究極的には、検証作業の生産性が向上すると同時に品質も向

上します。

以下に簡単な例を示します。例にある様に、クロッキング・ブロックの定義や modport の定義を

含む事が出来ます。その他、initial プロシージャに信号値の初期化処理を含む事が出来ます。こ

れらの機能に関しては、moduleと共通しています。

interfaceの使用法は moduleと良く似ています。例えば、次の様にしてインスタンスを作りテスト

ベンチに接続します。

interface simple_bus( input logic clk );

wire req, gnt;

wire [7:0] addr, data;

clocking sb @(posedge clk);

input gnt;

output req, addr;

inout data;

property p1;

req ##[1:3] gnt; endproperty

endclocking

modport DUT ( input clk, req, addr, output gnt, inout data );

modport STB ( clocking sb );

modport TB ( input gnt, output req, addr, inout data );

endinterface

Page 19: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

8

1.3.5 checker

checker はアサーション、及び、そのモデリングをグルーピングする為のコンストラクトです。

checkerを使用して、アサーションの記述が散乱する事を回避する事が出来ます。

以下に簡単な例を示します。例では、信号 a、b、c にランダムに値を設定しています。但し、a

と b には相互関係があり、同時に 1にならない様にしています。更に、生成した信号値を使用し

ているモジュールに戻しています。

checker を使用する側は、checker のインスタンスを作ります。これは interface を使用する場合と

同様です。例えば、次の様にしてインスタンスを作ります。

テストベンチで clockのイベントが起こると checker check が実行します。そして、信号 a、b、

及び、cには矛盾が無い様に値が設定されます。テストベンチが整然としているのは checkerの効

果です。

1.3.6 package

module、interface、program、及び checker はローカルな名称空間を生成します。それらの内部で

定義された名称は、直接には外部には見えません。従って、名称のコンフリクトがありません。

一方、package は定義を共有する為の機能です。package 内で定義した名称を他のビルディング・

ブロック内で使用する事が出来ます。

module top;

logic clk = 0;

simple_bus SBUS(clk);

test TEST(.*);

dut DUT(.*);

...

endmodule

checker check(event clk, output logic out1, out2, out3);

rand bit a, b, c;

m: assume property (@clk $onehot0({a, b}));

assign out1 = a;

assign out2 = b;

assign out3 = c;

endchecker : check

module test;

logic a, b, c;

bit clock;

check C1(posedge clock,a,b,c);

initial

repeat (10) #10 clock = ~clock;

always @(a,b,c)

$display("@%0t: a=%b b=%b c=%b", $time,a,b,c);

endmodule

Page 20: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

9

以下は簡単なパッケージの例です。通常は、データ・タイプの宣言、タスク、ファンクション等

の多くの機能を定義します。

パッケージで定義されているデータ・タイプ、変数、メソッド等を参照する為には、スコープ・

オペレータ(::)を使用しなければなりません。

スコープ・オペレータの使用を回避する為には、import 文を使用します。例えば、以下の様にし

ます。

package を深く学習する為には、UVM のソース・コードを読む事を勧めます。多くの重要な

SystemVerilog機能が使用されています。

1.3.7 primitive

ゲート・レベルの記述を可能にする機能です。SystemVerilogを高位の記述言語として使用する場

合には、primitive を必要とする可能性は低いと考えられます。以下に簡単な例を示しますが、本

書では primitiveの説明を省略します。

`ifndef PACKAGE_SVH

`define PACKAGE_SVH

package Package;

parameter OPERAND_WIDTH = 4;

parameter OPERATOR_WIDTH = 3;

typedef enum logic [OPERATOR_WIDTH-1:0]

{ ADD=3'b001, SUB=3'b010, XOR=3'b100 } opcode_e;

endpackage

`endif

`include "Packages.pkg "

module test;

Package::opcode_e op;

initial begin

op = Package::ADD;

...

end

endmodule

`include "Packages.pkg "

module test;

import Package::*;

opcode_e op;

initial begin

op = ADD;

...

end

endmodule

Page 21: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

10

例は 2入力の multiplexer を記述しています。例で示す様に、ゲートの記述を真理値表で記述しま

す。SystemVerilogの持つ機能を使用していません。

1.3.8 configuration

configuration はデザイン・コンフィグレーションを記述する為の機能ですが、本書では説明を省

略する事にします。

1.4 検証パッケージ

検証分野で広く使用されている標準的なパッケージが存在しますが、本書ではそれらの記述を省

略します。例えば、UVM は重要な SystemVerilog 検証パッケージですが解説を他の文献に委ねま

す([5])。

1.5 本書で用いるシンタックス記法

SystemVerilog機能のシンタックスを参照する際、原書の方法を使用する事にします。入門書であ

る事から、完全なシンタックスを記述する事を避けました。シンタックスの詳細については、原

書を参照して下さい。

// mux2

primitive mux2 (mux, control, dataA, dataB);

output mux;

input control, dataA, dataB;

table

// control dataA dataB mux

0 1 0 : 1 ;

0 1 1 : 1 ;

0 1 x : 1 ;

0 0 0 : 0 ;

0 0 1 : 0 ;

0 0 x : 0 ;

1 0 1 : 1 ;

1 1 1 : 1 ;

1 x 1 : 1 ;

1 0 0 : 0 ;

1 1 0 : 0 ;

1 x 0 : 0 ;

x 0 0 : 0 ;

x 1 1 : 1 ;

endtable

endprimitive

Page 22: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

11

2 データ・タイプ

2.1 データ・タイプとデータ・オブジェクト

データ・タイプは値の集合であり、それらの値に適用する演算を含みます。例えば、int は 32 ビ

ットの符号付き整数で-2147483648 から 2147483647 までの整数値で構成され、標準的な演算が定

義されています。データ・タイプには、SystemVerilog で予め定められたデータ・タイプとユーザ

が定義するデータ・タイプがあります。この章では主として前者のデータ・タイプを取扱います。

データ・タイプを使用してデータ・オブジェクトを宣言します。データ・オブジェクトは名称を

付けて宣言します。データ・オブジェクトには、名称、データ・タイプ、値、演算等が割り当て

られる事になります。

例 2-1

addr は 32ビットの logic型として宣言されています。addr は符号なしです。addr に対して標

準的な演算(例えば、+, -, *, /, &, |, ^等)を使用する事が出来ます。

delay は 32 ビットの整数型です。但し、two-state です。即ち、delay は値 x、又は、z の値を

取り得ません。

qは string(文字列型)型のデータを持つキューです。キューに対する操作はメソッドで行いま

す。

map は文字列型のキーを持つ辞書です。辞書のデータは実数型です。この様なアレイを

associative arrayと呼びます。

fixed は固定の大きさを持つアレイです。ここで、[10]は[0:9]の省略形です。

dynamic はダイナミックなアレイです。アレイの大きさを実行時に決定します。アレイの領域

も実行時に割り当てます。

2.2 Logic型

Logic型は4つの値(0, 1, x, z)を持ち得るデータ・タイプです。値 0は偽の意味を持ちます。同

様に、値 1は真の意味を持ちます。x は unknownを意味します。zは high-impedanceを意味しま

す。接続を遮断する場合等に用います。論理合成等では don’t care conditionsとして使用します。

x 及び z はハードウェアには存在しませんが、ソフトウェア的に状態を表現する為に使用されま

す。

SystemVerilog では、Verilog で使用される reg 型を使用せず、logic 型を使用します。reg はハード

ウェアのレジスタを連想させる為、極力使用しない事が勧められています。logic 信号は net を使

用する事が出来る場所であれば、何処でも使用する事が出来ます。但し、net 型と異なり、logic

型は複数のドライバーを持つ事は出来ません。違反した場合、コンパイル・エラーが発行されま

logic [31:0] addr;

int delay;

string q[$];

real map[string];

shortint fixed[10][20];

byte dynamic[];

Page 23: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

12

す。これは、logic 型は複数ドライバーに対して resolution のメカニズムを持っていない為です。

net型の場合には、wired orや wired andという resolutionのメカニズムが備わっています。

2.3 単数系と集合系(Singular and aggregate types)

データ・タイプは単数系(singular)と集合系(aggregate)に分類されます。単数形は文字通り一

つの要素で構成されます。集合系はストラクチャ(structures)やアレイの様に複数の要素で構成

されます。

Integral types(byte, shortint, int, longint, integer, logic, bit, reg, time等)は配列次元を持たなければ単

数系です。また、string 型も配列次元を持たなければ単数系です。但し、これらの型でもインデ

ックスを使用する事が出来ます。従って、アレイ要素に見える為、集合系と誤解する事が多いで

す。

例 2-2

addr は singular です。何故なら、addr = 0; の様に addr 単体で演算に使用する事が出来る

からです。addr[1]、又は、addr[3:0]の様に使用する事ができますが、所謂、アレイではあ

りません。それらは、あくまでも特定のビットを識別する為のアクセス法を示しています。

一方、addr_array は複数系です。addr_array = 0;の様な操作をする事は出来ません。必

ず、addr_array[0]、addr_array[expr]の様にして使用します。

変数名の前に定義されている[31:0]の様な宣言は SystemVerilog では packed dimension と呼ばれ

ます。それは、ビット構成を定義する為の便宜にしか過ぎません。これに対して、C/C++でいう

次元を SystemVerilog では unpacked dimension と呼びます。addr_array の[20]は unpacked

dimensionです。

2.4 ネットと変数(Nets and variables)

データ・オブジェクトは net 型と変数(variable)型に分類されます。net 型は、複数のドライバ

ーにより、常時値が設定されます。即ち、少なくとも一つのドライバーの値が変化すると、net

型のオブジェクトの値も変化します。一方、variable 型は割り当てる命令が実行される時のみ値

が設定されます。従って、モジュール間の接続やデータ・フローには net 型を使用し、behavior

の記述には variable型を使用します。

例 2-3

ここで a、及び、b は net 型です。a、又は、b の何れかが変化すると my_or に新しい値が設定

されます。この状態は常時繰り返します。以下の様に書き換える事も出来ます。

logic [31:0] addr, addr_array[20];

wire a, b, my_or;

assign my_or = a | b;

wire a, b, my_or;

logic tmp;

assign my_or = tmp;

always @(a,b)

tmp = a | b;

Page 24: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

13

この例で分かる様に、variable 型を使用する場合には、常時繰り返す動作を明示的に記述する必

要があります。

2.5 net型

net 型は logic 型と同様に 4 つの値を持ち得ます。net 型には、wire、tri、tri0、suppy0、wand、

triand、tri1、supply1、wor、trior、trireg、uwire等があります。

uwire は unresolved wire 又は unidriver wire を意味します。即ち、複数のドライバーを持つ事が出

来ない wireを意味します。

net型は Verilogと同様な概念を持ち、理解し易い型なので詳細を省略します。

2.6 Two-state 型

SystemVerilog には、bit、byte、shortint、int、longint 等の two-state 型があります。これらは、x、

及び、z の値を表現する事は出来ません。通常、値 0 で初期化されます。2 値しかもたない為、

一般的には、シミュレーションが高速化されます。また、初期値の設定を省く事が出来ます。

two-state型 意味

bit 1ビットの型で値 0、又は、1を表現する。符号なしです。

byte 8 ビット型で C/C++の char に相当する。符号付きの 8 ビット整

数です。

shortint 16 ビットの符号付きの整数を意味します。C/C++の short に相

当します。

int 32ビットの符号付きの整数を意味します。

longint 64ビットの符号付きの整数を意味します。C/C++の long long に

相当します。

符号無しにするには、修飾子 unsigned を使用します。例えば、byte unsigned は符号なしの 8 ビッ

ト整数型になります。SystemVerilogでは、C/C++と異なり、unsignedが型の後ろに位置します。

例 2-4

reset は1ビットで、0、又は、1の値を取ります。

data は 32 ビットの符号なし整数と同じです。但し、data[0]、data[3:2]の様に参照する事

が出来ます。

barray は 8 ビット整数のアレイです。ここで、barray[128]は barray[0:127]と同じ効果

を持ちます。

bit reset;

bit [31:0] data;

byte barray[128];

Page 25: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

14

例 2-5

clk は two-state型である為、値 0で初期化されます。従って、明示的に初期化をする必要性はあ

りません。一方、以下の様に logic 型を使用すると初期化が必要になります。シミュレーション

時刻 0において clkのイベント(negedge clk)が起こる事に注意して下さい。

時刻 0において clkのイベントを避ける為には、次の様にします。

2.7 Four-state型

net型に加えて以下の様なタイプがあります。

4-state型 意味

logic 4 値を持つ 1 ビットの型で値 0、1、x、又は、z を表現します。

符号なしです。

reg logicと同じ意味を持ちます。

regを使用をしない様に logic型が導入されました。

integer 4値を持つ 32ビットの符号付き整数です。

time 4値を持つ 64ビットの符号なしの整数を意味します。

integer のみ符号付きです。“ integer は int と同じ符号付き”と記憶すると良いでしょう。

SystemVerilog には two-state 型の int や longint がある為、integer や time を使用する機会は余りあ

りません。次の様に logic型を使用します。

four-state型の変数を使用する場合、値が two-stateであるか否かを判定する必要が出て来ます。そ

の様な場合、システム・ファンクション $isunknown が有効に働きます。

bit clk;

always

#10 clk = ~clk;

logic clk;

initial begin

clk = 0;

forever #10 clk = ~clk;

end

logic clk = 0;

initial begin

forever #10 clk = ~clk;

end

interface simple_if(input bit clk);

logic grant,

request,

reset;

endinterface

Page 26: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

15

2.8 real、shortrealと realtime

SystemVerilog には、実数型として real、shortreal、及び、realtime があります。real は C/C++の

double に相当します。shortreal は C/C++の float に相当します。realtime は real と同意語です。こ

れらの型を総称して real 型と呼びます。実数が整数型の変数に割り当てられる時、切り捨てられ

ずに、丸められた値が設定されます。例えば、

に於いて、numは 1になります。

2.9 void型

SystemVerilogには void型があります。主として、値を戻さない functionを定義する際に使用しま

す。

例 2-6

値を戻さない function を task の様に使用する事が出来ます。SystemVerilog/Verilog では、function

から task を呼び出すことは出来ません。task を void function として定義する事によりその制限を

解消する事が出来ます。

2.10 Chandle型

この型は、主として DPIで使用されます。

例 2-7

2.11 Class

Classもデータ・タイプです。後章で詳しく記述します。

2.12 Stringデータ・タイプ

この型は、8 ビット整数(byte)から構成される文字列です。C/C++の char*に相当します。const

char*ではありません。C/C++と異なり、文字列の終わりにナル(\0)を含みません。

logic [7:0] request;

...

if( $isunknown(request) )

$display("4-state value detected on request=%b",request);

real r;

int num;

r = 0.5;

num = r;

function void check();

// ...

endfunction

chandle variable_handle;

Page 27: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

16

文字列の長さを N とすると、string 型の変数には、インデックス 0 から N-1 を使用する事が出来

ます。インデックス 0 は最初の文字を指し、N-1 は文字列の最後の文字を指します。初期値を設

定しない string型の変数は、長さ 0の空文字列で初期化されます。

例 2-8

default_language[0]は S を指します。ここで、”SystemVerilog” は string 型のリテラル

と呼ばれます。この例の様に、string型の変数を同じ型の変数で初期化する事が出来ます。

string型のリテラルは string型だけで無く、integralデータ・タイプにも使用する事が出来ます。

変数 name には文字列 AB が設定されます。name を式の中で使用すると整数値 16706 として扱わ

れます。

前述した様に C++と異なり string型は const char* ではないので、文字列を変更する事が出来ます。

city の内容は Tokyoになります。

string 型の変数には以下の様な演算を適用する事が出来ます。特に、文字列の結合オペレータ{}

は非常に便利なオペレータです。

演算子 意味

str1 == str2 二つの文字列が等しければ 1 になります。等しくない時には 0

と評価されます。

str1 != str2 str1 == str2の否定形です。

str1 < str2

str1 <= str2

str1 > str2

str1 >= str2

二つの文字列を辞書引き順序で比較し、正しければ1を戻し、

偽の場合には 0を戻します。

{str1,str2,…,strn} 文字列を結合します。

{multiplier{str}} 文字列を指定した回数繰り返します。

str[index] index で指定した文字(byte 型)を戻します。index は 0 から

N-1 の範囲でなければなりません。ここで、N は文字列の長さを

示します。

str.method(…) string型に定義されている methodを実行します。

string default_language = “SystemVerilog”;

string current_project_language = default_language;

shortint name = “AB”;

string city = “tokyo”;

city[0] = “T”;

Page 28: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

17

例 2-9

実行すると以下の様な結果が得られます。

string型に定義されている methodには以下の様な functionがあります。

method 意味

function int len(); str.len()は文字列 str の長さを戻します。空文字列の

長さは 0です。

function void putc(int i, byte c); str.putc(i,c)は str[i]=cと同じです。

function byte getc(int i); x=str.getc(i)は x=str[i]と同じです。

function string toupper(); str.toupper()は大文字に変換した文字列を戻します。

strの内容は変わりません。

function string tolower(); str.tolower()は子文字に変換した文字列を戻します。

strの内容は変わりません。

function int compare(string s); str.compare(s)は C/C++の strcmp(str,s)と同じです。

function int icompare(string s); str.icompare(s)は C/C++の stricmp(str,c)と同じで

す。

function string substr(int i, int j); str.substr(i,j)はインデックス i から j までの部分文字

列を戻します。

function integer atoi();

function integer atohex();

function integer atooct();

function integer atobin();

str.atoi()は整数を表現している文字列が表す 10 進整

数を戻します。例えば、 str が ”123”であれば、

str.atoi()は 123を戻します。

atohex()は 16 進数、atooct()は 8 進数、atobin()は 2

進数です。

function real atoreal(); str.atoreal()は str が表現する実数を戻します。例え

ば、str が ”3.14” であれば、str.atoreal()は 3.14 を戻

します。

function void itoa(integer i);

function void hextoa(integer i);

function void octtoa(integer i);

function void bintoa(integer i);

function void realtoa(real r);

integer iを文字列に変換して strに設定します。

他の function も同様です。

string s,

system_verilog = "SystemVerilog",

is = "is",

great = "great",

na = "na";

s = {system_verilog," ",is," ",great,"!"};

$display("s=%s",s);

s = {"ba",2{na}};

$display("s=%s",s);

s=SystemVerilog is great!

s=banana

Page 29: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

18

例えば、

は、BANANAをプリントします。他のメソッドの例を以下に示します。

for-loop により、変数 s の文字列から一文字ずつ取り出してプリントしています。ループの終了

は s.len()で判定されます。

2.13 Eventデータ・タイプ

Event オブジェクトは同時に実行している複数のプロセスの同期を取る為に有効な手段を提供し

ます。プロセスは event オブジェクトを指定して、イベントが発生するまで待ち状態に入ります。

その間、そのプロセスは inactive になります。他のアクティブなプロセスは event オブジェクト

指定して trigger(オペレータ->)をかけ、待ち状態にあるプロセス再開します。

例 2-10

実行すると以下の様な結果を得ます。

string s;

s = { "ba",2{"na"} };

$display("%s",s.toupper());

string s;

...

s = "It's raining.";

for( int i = 0; i < s.len(); i++ ) begin

$write("%c",s.getc(i));

end

$display();

class X;

event ev;

task check;

$display("@%0t: waiting for ev to occur.",$time);

@ev;

$display("@%0t: ev released.", $time);

endtask

endclass

module test;

X x;

initial begin

x = new;

x.check();

$display("@%0t: main completed",$time);

end

initial begin

#10;

->x.ev;

end

endmodule

Page 30: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

19

@ev はエッジ・センシティブで、且つ、ev の状態を保存していません。従って、ev に trigger を

掛けるタイミングがずれると@ev は解除されません。例えば、以下の記述が与えられたとします。

もし、①が②より先に実行すれば、@ev は正しく解除されます。逆に、②が①よりも先に実行す

れば、@ev は解除されません。この様な race-conditions を避ける為には、レベル・センシティブ

な方法をします。

この方法に依れば、③と④の実行順序に依存しないで waitは正しく解除されます。

2.14 Typedef

既に定義されているデータ・タイプを用いて新しいデータ・タイプを定義する事が出来ます。こ

の方法を用いると既に存在するデータ・タイプの別名を定義する事も出来ます。定義には、

C/C++の様に typedef文が使用されます。

例 2-11

変数 uvalueは符号なし 32ビット整数型となります。

また、この機能を利用すると、まだ存在しないデータ・タイプを暫定的に定義する事が出来ます。

相互に参照しあう二つのデータ・タイプを定義する際には、この機能が必要になります。この機

能を forward typedef宣言と呼びます。C++の forward declarationに相当します。

@0: waiting for ev to occur.

@10: ev released.

@10: main completed

#-I Simulation completed at time 10 ticks

initial begin

@ev; ①

end

...

initial begin

->ev; ②

end

initial begin

wait( ev.triggered() ); ③

end

...

initial begin

->ev; ④

end

typedef int unsigned uint;

uint uvalue;

Page 31: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

20

例 2-12

二つのクラス Producer と Consumer が相互に参照しています。Consumer を定義する時、未だ

Producerの定義がされていない為、forward typedefが必要になります。

2.15 Enum

Enum データ・タイプは関連する値を持つコンスタントを定義する命令です。値を明示的に設定

する事が出来ますが、自動的に設定させる事も出来ます。

C++の enum 機能と類似していますが、異なる点もあります。例えば、enum データ・タイプに

integral type(logic、bit、byte、shortint, int等々)を指定する事が出来ます。また、enumデータ・

タイプには標準的な methods が定義されています。タイプが省略されると、int型が仮定されます。

以下に例を示します。

例 2-13

typedef Producer;

// Consumer

class Consumer;

string name;

Producer producer;

function new(string name);

this.name = name;

endfunction

function void setProducer(Producer p);

producer = p;

endfunction

endclass

// Producer

class Producer;

Consumer consumer;

string name;

function new(string name);

this.name = name;

endfunction

function void setConsumer(Consumer c);

consumer = c;

endfunction

endclass

enum {GREEN, YELLOW, RED} light1, light2;

enum bit[1:0] { READY, READ, WRITE } state, next;

enum { bronze=3, silver, gold } medal;

enum bit[3:0] { a=4'h3, b=4'h7, c } alphabet;

Page 32: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

21

light1、及び、light2 は int 型の enum データ・タイプです。GREEN=0、YELLOW=1、RED=2

となります。

state、及び、next は bit 型の enum データ・タイプです。サイズは 2 ビットです。

READY=2’b00、READ=2’b01、WRITE=2’b10 となります。

medal は int型の enumデータ・タイプです。bronze=3、silver=4、gold=5 となります。

alphabet は 4ビットの enumデータ・タイプです。a=4’h3、b=4’h7、c=4’h8 となります。

ここで、注意が必要です。変数は enum タイプの標準的な初期値により初期化が行われます。例

えば、light1 は int 型なので、light1 の初期値は 0 となります。従って、たまたま light1

の初期値は GREENと一致します。然し、何時もこの様に運が良いとは限りません。

medal は int型なので、初期値は 0となります。然し、0に該当する enumラベルが無い為、実質

的に無効な値が設定されている事になります([3])。この問題を避ける為には、以下の何れかの

対策が必要です。

変数を明示的に初期化する。例えば、medal=bronze; を追加する。

最初の enumラベルの値を 0に設定する。

以下は安全策を考慮した記述例です。

上記の様に使用される enum を anonymous enum と呼びます。通常、この様に使用せず、enum デ

ータ・タイプを定義します。そうする事により、グローバルなデータ・タイプとなります。

例 2-14

データ・タイプ controller_e を何処でも使える様になります。

enumには便利な methodが定義されています。

method 意味

function enum first(); 最初の enumラベルを戻します。

function enum last(); 最後の enumラベルを戻します。

function enum next( int unsigned N = 1 ); 現在より N 個先のラベルを戻します。最後の

ラベルの次は最初に戻ります。

function enum prev( int unsigned N = 1 ); 現在より N 個前のラベルを戻します。最初の

enum {GREEN, YELLOW, RED} light1=GREEN, light2=RED;

enum bit[1:0] { READY, READ, WRITE } state=READY, next=READ;

enum { bronze=3, silver, gold } medal=bronze;

enum bit[3:0] { a=4'h3, b=4'h7, c } alphabet=c;

typedef enum {GREEN, YELLOW, RED} controller_e;

controller_e light1=GREEN,

light2=RED;

Page 33: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

22

ラベルに行くと最後のラベルに戻ります。

function int num(); Enumに定義されているラベル数を戻します。

function string name(); 現在の enumラベル名を戻します。

例 2-15

上記のコードは color_e の全てのラベルを順にプリントします。実行結果は以下に様になりま

す。

2.16 Constants

Constants は名前の付いたオブジェクトで値が変化しません。SystemVerilog には、parameter、

localparam、及び、specparam があります。これらは、elaboration 時に値が決定します。それに加

えて、実行時に決定する constがあります。

SystemVerilog では、コードの中で使用する定数(例えば、100、4’b0101、”Tokyo” 等)をリテラ

ルと呼び、constant と区別します。リテラルは出現した時点で定数になっています。一方、

constantsはコンパイルが終了した時に初めて値が決定します。

例 2-16

例で示す様に名称とタイプを指定する事が出来ます。使用法は明瞭で説明の必要は無いと思いま

すが、一点だけ注意が必要です。

typedef enum { GREEN=1, YELLOW=3, RED=10 } color_e;

module test;

color_e c;

initial begin

c = c.first;

forever begin

$display("%s=%0d",c.name,c);

if( c == c.last )

break;

c = c.next;

end

end

endmodule

GREEN=1

YELLOW=3

RED=10

parameter left = 100,

right = 200;

parameter mid = (left+right)/2;

parameter real PI = 3.14;

parameter WIDTH = 4'hc;

parameter WIDTH32 = 12;

Page 34: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

23

WIDTHと WIDTH32に注目して下さい。同じ値 12が設定されていますが、WIDTHは 4ビット,

WIDTH32は 32 ビットのパラメータです([1])。注意を喚起する為に、例を書き直します。

実行すると、次の様な結果を得ます。

従って、

(WIDTH == WIDTH32) == 1’b1

となりますが、

({left,WIDTH} == {left,WIDTH32}) == 1’b0

となります。

2.17 Cast オペレータ

タイプを変換する為に使用します。type’(expr)の様にして使用します。例えば、

int’(2.0*3.1)

shortint’({8’hFA,8’hCE})

の様な使い方でタイプを変換します。type の代わりに整数を使用するとビット長を制限する事が

出来ます。例えば、

4’(-1)

は、4’b1111と同じです。また、typeの代わりに signed、及び、unsignedを使用する事が出来ます。

例えば、

parameter left = 100,

right = 200;

parameter mid = (left+right)/2;

parameter real PI = 3.14;

parameter WIDTH = 4'hc;

parameter WIDTH32 = 12;

module test;

initial begin

$display("left=%0d right=%0d mid=%0d",left,right,mid);

$display("PI=%g",PI);

$display("WIDTH=%b WIDTH32=%b",WIDTH,WIDTH32);

end

endmodule

left=100 right=200 mid=150

PI=3.14

WIDTH=1100 WIDTH32=00000000000000000000000000001100

Page 35: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

24

unsigned’(-4)

signed’(4’b1100)

の様な使い方が出来ます。以上を例として整理しておきます。

例 2-17

これを実行すると以下の様な結果を得ます。

2.18 $cast ダイナミック型変換

$cast システム・タスクは実行時にタイプ変換を行う為の関数です。function として呼ぶ場合と、

taskとして呼ぶ場合の二種類があります。

task として呼び出した場合、変換が fail した時には実行時にエラー・メッセージが発行されます。

functionとして呼び出した場合、変換が成功すれば 1を戻し、fail した時には 0を戻します。実行

時のエラー・メッセージは出ません。以下の様な使用法です。

function int $cast( singular dest_var, singular source_exp );

task $cast( singular dest_var, singular source_exp );

enum 変数に演算を適用した場合に$cast システム・タスクを利用する事が多いです。以下の例

を参考にして下さい。

module test;

int tmp;

logic [7:0] regA;

logic signed [7:0] regS;

string buffer;

initial begin

tmp = int'(2.0*3.1);

buffer = $sformatf("%h",shortint'({8'hFA,8'hCE}));

$display("tmp=%0d %s",tmp,buffer.toupper);

$display("%b",4'(-1));

regA = unsigned'(-4);

regS = signed'(4'b1100);

$display("regA=%b regS=%0d",regA,regS);

end

endmodule

tmp=6 FACE

1111

regA=11111100 regS=-4

Page 36: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

25

例 2-18

これを実行すると、以下の様な結果を得ます。today+2 は enum 型と見做されないので、強制的

に enum型に変換をしています。実行結果は以下の様になります。

2.19 便利な初期値設定

2.19.1 リテラルの拡張

Verilog ではリテラルの最上位のビットが x 又は z であれば、その値が左に拡張されます。例え

ば、

の場合、v は全てのビットが x に設定されます。然し、全てのビットを 1にする事は出来ません。

で全てのビットを 1 に設定する事が出来ますが、WIDTH が 64 になると動作しなくなります。即

ち、この方法は scalableではありません([2])。v = ~0;も可能ですが、0は 32ビットである為、

同様の制限があります。

SystemVerilog はこの問題を解消する為に、’0、’1、’x、’z 等を導入しました。これらのリテ

ラルは可変長で、長さは左辺の長さで決定されます。

可変長リテラル 機能

’0 全てのビット位置に 0を設定します。

’1 全てのビット位置に 1を設定します。

’x、又は、’X 全てのビット位置に xを設定します。

’z、又は、’Z 全てのビット位置に zを設定します。

typedef enum { Sunday, Monday, Tuesday, Wednesday, Thursday,

Friday, Saturday } week_e;

module test;

week_e today,day;

initial begin

today = Sunday;

$cast(day,today+2);

$display("today is %s and the day after tomorrow is %s.",

today.name, day.name);

end

endmodule

today is Sunday and the day after tomorrow is Tuesday.

parameter WIDTH = 32;

logic [WIDTH-1:0] v = ‘bx;

v = 32’ff_ff_ff_ff

Page 37: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

26

例 2-19

実行結果は以下の様になります。

2.19.2 インデックス指定

整数型の変数に初期値をビット単位で設定したい場合があります。この様な場合、SystemVerilog

ではビット位置を指定する機能があります。

parameter WIDTH = 32;

module test;

logic [WIDTH-1:0] val;

initial begin

val = 0; // all 0's

print("val",val);

val = 'bx; // all x's

print("val",val);

val = 'bz; // all z's

print("val",val);

val = '0; // all 0's

print("val",val);

val = '1; // all 1's

print("val",val);

val = 'z; // all z's

print("val",val);

val = 'x; // all x's

print("val",val);

end

function void print(string msg,logic [WIDTH-1:0] v);

$display("%s=%b",msg,v);

endfunction

endmodule

val=00000000000000000000000000000000

val=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

val=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

val=00000000000000000000000000000000

val=11111111111111111111111111111111

val=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

val=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Page 38: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

27

例 2-20

module test;

int state = '{ 31:0, 3:0, default:1 };

logic [15:0] value = '{ 15:1, 14:0, 0:1, default: 'bz };

initial begin

$display("state=%b",state);

$display("value=%b",value);

end

endmodule

state=01111111111111111111111111110111

value=10zzzzzzzzzzzzz1

Page 39: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

28

3 メンバーで構成されるデータ・タイプ(Aggregate data types)

複数のメンバーから構成される SystemVerilog データ・タイプを説明します。この章では、以下

のデータ・タイプ、及び、メソッドに注目します。

structure

union

array

array methods

クラスもメンバーで構成されるデータ・タイプですが、それ自身で主題を構成する大きな話題な

ので別の章で説明する事にします。

3.1 ストラクチャ(Structures)

Structure は幾つかのメンバーを一つのグループとして纏めたデータ・タイプです。各メンバーは

異なるデータ・タイプを持つ事が出来ます。メンバーを個別に参照、又は、操作する事が出来ま

す。グループ全体として参照する事も出来ます。

Structureには packed structureと unpacked structureがあります。unpacked structureが defaultで、修

飾子 unpackedを省きます。packed structureではメンバー全体が連続したメモリーに配置されます。

従って、structure 全体を一つの数値として操作する事が出来ます。その代り、packed structure の

メンバーは integral type でなければなりません。unpacked structure の場合には、メンバーが連続

したメモリーに配置される保証はありません。

例 3-1

pixel は anonymous structureを使用しています。一方、pixel_s 及び food_s はデータ・タイ

プとして定義されています。例にある様に、メンバーを参照する場合にはドットを使用します。

struct { bit [7:0] r, g, b; } pixel;

typedef struct { bit [7:0] r, g, b; } pixel_s;

typedef struct { string name; int price; } food_s;

module test;

pixel_s px;

food_s fd;

initial begin

pixel.r = 0;

pixel.g = 255;

pixel.b = 255;

px.r = 255;

px.g = 100;

px.b = 64;

$display("pixel=(%0d,%0d,%0d) px=(%0d,%0d,%0d)",

pixel.r,pixel.g,pixel.b,px.r,px.g,px.b);

fd.name = "bread";

fd.price = 250;

$display("food=(%s,%0d)",fd.name,fd.price);

end

endmodule

Page 40: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

29

メンバーのデータ・タイプを個別に指定する事が出来ます。pixel_s の定義の様にデータ・タ

イプが同じである場合には、メンバー名をカンマで区切る事が出来ます。

メンバー名は外には見えません。必ず、ストラクチャを示すオブジェクト、及び、ドットを使い

メンバー名を参照しなければなりません。

3.1.1 Packed ストラクチャ(packed structures)

packed structure の場合には、全体として扱う事が出来る為、便利な記述が出来ます。例を示すの

が一番分かり易いと思います。

例 3-2

実行すると以下の様な結果を得ます。

pack1 が 64ビットのオブジェクトとして認識されている事が分かります。pack1 をビット・ス

ライスで参照する事が出来る事も分かります。全てのメンバーが連続したメモリー領域に配置さ

れます。注意する事は、先頭のメンバーがビットの高位に位置する事です。

63 16 8 0

a(32ビット) b(16ビット) c(8ビット) d(8ビット)

3.1.2 ストラクチャへの値の設定

メンバーを個別に初期化する事が出来るのは明らかですが、全体としても初期化をする事が出来

ます。全体を初期化する場合には、structure literal ‘{...}を使用します。

struct packed signed {

int a;

shortint b;

byte c;

bit [7:0] d;

} pack1;

program automatic test;

initial begin

$display("$bits(pack1)=%0d",$bits(pack1));

pack1.b = -1;

pack1[15:8] = 8'hab; // access to c

pack1[62] = 1;

$display("pack1=%h pack1[15:8]=%h",pack1,pack1[15:8]);

end

endprogram

$bits(pack1)=64

pack1=40000000ffffab00 pack1[15:8]=ab

Page 41: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

30

例 3-3

これを実行すると、以下の様な結果を得られます。

3.2 ユニオン(unions)

Union は一つのオブジェクトを異なる名称で参照する事が出来るデータ・タイプです。structures

と同様に、packed union の概念があります。structures との違いは、メンバーが同じ領域を共有す

る事にあります。

領域を共有する事が目的である為、各メンバーのデータ・タイプは異なります。一見、メモリー

使用量の削減効果を持つ様に思えますが、実質的には実行上のオーバーヘッドが大きいという短

所を持っています。特別な目的を持たないのであれば、union は使用を避けるべきデータ・タイ

プの一つであると思えます。

const int START = 100;

typedef struct {

int addr = 1 + START;

int crc;

byte data [4] = '{4{1}};

} packet;

program automatic test;

packet pkt;

initial begin

print(pkt);

pkt = '{ 1, 2, '{ 3, 4, 5, 6} };

print(pkt);

end

function void print(packet p);

$display("addr=%0d crc=%0d data={%0d,%0d,%0d,%0d}",

p.addr, p.crc,

p.data[0], p.data[1], p.data[2],p.data[3] );

endfunction

endprogram

addr=101 crc=0 data={1,1,1,1}

addr=1 crc=2 data={3,4,5,6}

Page 42: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

31

例 3-4

3.2.1 Packedユニオン(packed unions)

Packed structuresと同様にオブジェクト全体として参照する事が出来ます。但し、packed unionsの

場合には、全てのメンバーが同じビット長を持たなければなりません。

例 3-5

これを実行すると、以下の様な結果を得ます。

typedef union {

int ivalue;

shortreal fvalue;

string svalue;

} value_u;

module test;

value_u val;

initial begin

val.ivalue = 100;

$display("val.ivalue=%0d",val.ivalue);

val.fvalue = 3.14;

$display("val.fvalue=%g",val.fvalue);

val.svalue = "IEEE";

$display("val.svalue=%s",val.svalue);

end

endmodule

typedef union packed {

shortint short_value;

bit[1:0][7:0] byte_value;

bit [15:0] bit_value;

} slice_u;

module test;

slice_u u;

initial begin

u = 16'habcd;

$display("u.short_value=%h",u.short_value);

$display("upper=%h lower=%h",u.byte_value[1],u.byte_value[0]);

$display("u[15:8]=%h u[7:0]=%h",u[15:8],u[7:0]);

$display("u=%h",u);

end

endmodule

Page 43: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

32

3.2.2 タグ付きユニオン(tagged unions)

Tagged unionsはタイプ・チェック機能を備えたデータ・タイプです。値を設定したタグと値を参

照するタグが一致しない場合、実行時にエラーとなります。

例 3-6

val.name に文字列 ”123.456” を設定した後に、val.r を参照している為に、タグの不一致

が起こっています。実行すると以下の様な結果が得られます。

3.3 Packed アレイと unpacked アレイ(packed and unpacked arrays)

SystemVerilog では、名称の前に位置する次元定義を packed array、名称の後に位置する次元定義

を unpacked arrayと呼びます。例えば、

bit [1:0][7:0] TwoBytesArray [20];

の定義に於いて、[1:0][7:0]は packed array、[20]は unpacked array です。この場合の packed

arrayは二次元ですが、一次元の packed arrayは vectorとも呼ばれます。

3.3.1 Packed アレイ(packed arrays)

Packed arrays は vector を階層的に操作する為の宣言手段です。Packed arrays のビットは連続領域

にとられる事が保障されています。

u.short_value=abcd

upper=ab lower=cd

u[15:8]=ab u[7:0]=cd

u=abcd

typedef union tagged {

real r;

string name;

} rvalue_u;

module test;

rvalue_u val;

initial begin

val = tagged r 123.456;

val = tagged name $sformatf("%g",val.r);

$display("val.name=%s",val.name);

$display("val.r=%g",val.r); // error on tag

end

endmodule

val.name=123.456

#-W Inconsistent use of a tagged member: write=name read=r

val.r=0.0

Page 44: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

33

例 3-7

bytes は 2バイトの領域を確保しています。bytes[2]と bytes[1]は物理的に連続した領域に

存在します。

bytes

bytes[2] bytes[1]

[7] [6] [5] [4] [3] [2] [1] [0] [7] [6] [5] [4] [3] [2] [1] [0]

全体を bytes として参照する事が出来ます。最上位のビットを bytes[2][7]、最下位のビッ

トを bytes[1][0]として参照する事が出来ます。

bytes[2]はビット位置として bytes[1]よりも高位の位置にあります。

3.3.2 Unpacked アレイ(unpacked arrays)

Unpacked arraysは packed arraysと異なり不連続なアレイです。即ち、アレイの要素が連続した場

所に存在する保障はありません。連続していない為に、unpackedと呼ばれます。

例 3-8

name は 4 バイトの大きさを持っています。name[0]、name[1]、name[2]、name[3]の様に

参照する事が出来ますが、それらのバイトは連続していません。

name[3] name[2] name[1] name[0]

Unpacked arrays はサイズを指定するだけで宣言を済ませる事が出来ます。例えば、次の二つの宣

言は同じです。

shortint matrix[0:7][0:127];

shortint matrix[8][128];

即ち、unpacked arrayの宣言に於いて、[N]は[0:N-1]と同じ効果を持ちます。packed arraysに対

してこの記法を使用する事は出来ません。

3.3.3 アレイの操作(operations on arrays)

Unpacked arraysに値を割り当てる場合には、array literals ‘{...}を使用します。例えば、

real r[3] = ‘{ 1.2, 3.4, 5.6 };

の様に使用します。この場合には、r[0]=1.2、r[1]=3.4、r[2]=5.6 となります。array

literalsでは繰り返し(replication operators)の指定をする事が出来ます。

bit [2:1][7:0] bytes;

bit [7:0] name[3:0];

Page 45: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

34

例 3-9

これを実行すると以下の結果を得ます。

array literalsにはアレイのインデックスを使用する事が出来ます。

例 3-10

この例は 1 月から 12 月までの各月の日数をプリントします。2 月が 28 日なので、2:28 と指定

しています。31日の月が多いので、default:31 としています。

月名を取得する為に、enum を使用しています。月と対応する様に、enum のラベルは 1 から始ま

っています。$cast を使用している事にも注意して下さい。enum を使用せずに他の方法もありま

す。例えば、associative arrays を使用すると簡単に出来ます。月を順に走査する為に foreach 文を

使用しています。

実行すると、結果は次の様になります。

module test;

int a[1:2][1:3] = '{ '{0,1,2}, '{3{4}} };

initial begin

$display("a[2]=(%0d,%0d,%0d)",a[2][1],a[2][2],a[2][3]);

$display("a[1]=(%0d,%0d,%0d)",a[1][1],a[1][2],a[1][3]);

end

endmodule

a[2]=(4,4,4)

a[1]=(0,1,2)

module test;

enum { January=1, February, March, April, May, June, July,

August, September, October, November, December } month;

int days[1:12] = '{ 2:28, 4:30, 6:30, 9:30, 11:30, default:31 };

initial begin

foreach(days[i]) begin

$cast(month,i);

$display("%s=%0d",month.name,days[i]);

end

end

endmodule

Page 46: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

35

アレイのコピーも簡単に出来ます。

例 3-11

アレイを taskや functionに引き渡す事も出来ます。print_foods を参考にして下さい。

これを実行すると以下の様な結果を得ます。

3.3.4 アレイのアクセス(indexing and slicing of arrays)

アレイの一部分を取り出すことは簡単に出来ます。例を見ると一目瞭然です。

January=31

February=28

March=31

April=30

May=31

June=30

July=31

August=31

September=30

October=31

November=30

December=31

module test;

string your_foods[5] =

'{ "bread", "milk", "rice", "fish", "meat" };

string my_foods[5];

initial begin

my_foods = your_foods;

my_foods[0] = "noodle";

print_foods("your foods:",your_foods);

print_foods("my foods:",my_foods);

end

function void print_foods(string msg,string foods[]);

$write(msg);

foreach(foods[i])

$write(" %s",foods[i]);

$display;

endfunction

endmodule

your foods: bread milk rice fish meat

my foods: noodle milk rice fish meat

Page 47: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

36

例 3-12

v32[24 +: 8]は「ビット位置 24 からビット上位方向に 8 ビット」という意味です。つまり、

8’hab を意味します。v32[23 -: 8]は「ビット位置 23からビット下位方向に 8ビット」とい

う意味です。つまり、8’hcd です。実行すると以下の結果を得ます。

3.4 ダイナミック・アレイ(dynamic arrays)

SystemVerilog ではアレイの大きさを実行時に決定する事が出来ます。この様なアレイを dynamic

arrays と呼びます。unpacked arrays にのみ適用される概念です。new オペレータを使用してアレ

イに領域を割り当てなければなりません。割り当てを行う前の dynamic arrays のサイズは 0 です。

領域を割り当てずにアレイを使用すると、一般的には、異常終了します。dynamic array の次元は

サイズを指定せずに宣言します。例えば、

int iarray[];

は dynamic array iarray を定義します。iarray を使用する前に領域を割り当てる必要がありま

す。この時点では、アレイの大きさは 0です。

ダイナミック・アレイには次のコンストラクタ、及び、メソッドがあります。

new[]コンストラクタ

size()メソッド

delete()メソッド

3.4.1 New[ ]コンストラクタ

dynamic arrays の初期化に new オペレータを使用します。アレイに領域を割り当てる際に、初期

値を設定する事が出来ます。また、他のアレイからコピーする事も出来ます。

module test;

logic [31:0] v32 = 32'hab_cd_ef_12;

logic [7:0] v8;

initial begin

v8 = v32[15:8]; // extract "ef"

$display("v8=8'h%h",v8);

v8 = v32[24 +: 8]; // extract "ab"

$display("v8=8'h%h",v8);

v8 = v32[23 -: 8]; // extract "cd"

$display("v8=8'h%h",v8);

end

endmodule

v8=8'hef

v8=8'hab

v8=8'hcd

Page 48: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

37

例 3-13

sarray はサイズが 5に割り当てられています。初期値は shortintの標準値 0です。

v10 はアレイ・サイズが 5です。アレイ要素は値 10で初期化されます。

fixed_s はサイズが 6に固定されたアレイです。初期値は(1,2,3,4,5,6)です。

copy_s は fixed_s をコピーしています。

実行すると以下の様な結果になります。

3.4.2 size()メソッド

アレイの大きさを戻す関数として次の様に定義されています。

function int size();

例えば、次の様に使用します。

module test;

shortint sarray[], v10[], copy_s[],

fixed_s[6] = { 1, 2, 3, 4, 5, 6 };

initial begin

sarray = new[5]; // (0,0,0,0,0)

print("sarray",sarray);

v10 = new[5](10); // (10,10,10,10,10)

print("v10",v10);

copy_s = new[fixed_s.size()](fixed_s); // (1,2,3,4,5,6)

print("copy_s",copy_s);

end

function void print(string msg,shortint a[]);

$write("%s=",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

sarray= 0 0 0 0 0

v10= 10 10 10 10 10

copy_s= 1 2 3 4 5 6

byte barray[];

if( barray.size == 0 )

barray = new[10];

...

Page 49: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

38

この関数は、ダイナミック・アレイに限らず、全てのアレイに対して使用する事が出来ます。例

えば、キューにも使用する事が出来ます。

3.4.3 Delete()メソッド

アレイを空にする関数として次の様に定義されています。

function void delete();

この関数を呼ぶと、アレイの大きさは 0 となります。空になると、アレイ要素の参照、或いは、

値を設定する事は出来ません。

例 3-14

これを実行すると以下の様な結果を得ます。

3.5 アレイのコピー(array assignments)

既に記述した以外のアレイ割り当ての例を示します。fixed array を dynamic array にコピーする事

が出来ます。アレイの大きさが 0 のダイナミック・アレイに対してもコピーする事が出来ます。

ここで、コピーとはダイナミック・アレイに領域を割り当てて、アレイ要素のコピーを行うとい

う意味です。ダイナミック・アレイに既に領域が割り当てられている場合には、delete メソッド

が最初に適用された状態になります。

byte q[$];

int week[string];

$display("q.size=%0d",q.size());

q = '{ 1, 2, 3, 4, 5 };

$display("q.size=%0d",q.size());

week = '{ "Sunday":0, "Monday":1 };

$display("week.size=%0d",week.size());

module test;

int i5[];

initial begin

i5 = new[5];

$display("size of i5=%0d",i5.size());

i5.delete;

$display("size of i5=%0d",i5.size());

end

endmodule

size of i5=5

size of i5=0

Page 50: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

39

例 3-15

アレイ b は dynamic array なので、本来は new オペレータで領域を割り当てる必要がありますが、

ここではサイズが決定しているアレイ aから直接コピーしています。

b = a;

により、b は aと同じ内容を持ちます。

ここでアレイ bのサイズは 10となりますが、

b = c;

により、アレイ b が再定義されます。具体的には、

b.delete();

b = new [c.size()](c);

というオペレーションに等しいです。結果として、アレイ bのサイズは 8となります。

実行結果は以下の様になります。

module test;

int a[10:1] = '{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int b[];

int c[] = new [8];

initial begin

print("a",a); // (1,2,3,4,5,6,7,8,9,10)

b = a;

print("b",b); // (1,2,3,4,5,6,7,8,9,10)

c = '{ 8{-2} };

b = c;

print("b",b); // (-2, -2, -2, ..., -2 )

end

function void print(string msg,int ar[]);

$write("%s:",msg);

foreach(ar[i])

$write(" %0d",ar[i]);

$display;

endfunction

endmodule

a: 1 2 3 4 5 6 7 8 9 10

b: 1 2 3 4 5 6 7 8 9 10

b: -2 -2 -2 -2 -2 -2 -2 -2

Page 51: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

40

例 3-16

new オペレータを使用せずに dynamic array ordered を定義しています。結果は以下の様になり

ます。

3.6 Associative アレイ

必要なアレイのサイズが算出可能で、且つ、使用するアレイのインデックスが連続している場合

には、dynamic arrays は便利な手段です。その条件を満たさない場合には、associative arrays を使

用する方が効率が良くなります。

associative arrays は、検索キーが与えられると対応するデータを戻すマップです。そして、キー

には自然な順序が付けられています。

associative arrays を離散的なアレイとして使用する事が出来ます。キーとしては様々なデータ・

タイプを指定する事が出来ます。associative arraysの定義は次の様に行ないます。

data_type array_id [ index_type ];

例えば、

bit state[process];

の様に宣言します。ダイナミック・アレイと異なり、宣言した時点でアレイが有効になります。

即ち、要素数が 0の associative arrayが作成されます。従って、newオペレータで領域を割り当て

る必要はありません。index_type として使用できる形式が幾つか存在します。

[index_type] 意味

[*] Wildcard index タイプと呼ばれ、任意の整数式をインデックスとし

て使用する事が出来ます。但し、four state の値をインデックスと

して使用する事は出来ません。

module test;

string random[1:5] = '{ "e", "b", "f", "c", "d" };

string ordered[];

initial begin

ordered = { "a", random[2], random[4:5], random[1],

random[3], "gLast" };

$write("ordered:");

foreach(ordered[i])

$write(" %s",ordered[i]);

$display;

end

endmodule

ordered: a b c d e f gLast

associative array key data

Page 52: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

41

[string] インデックスは string タイプです。空文字列もキーとして許されま

す。辞書引き順序が使用されます。

[class] クラス・オブジェクトをインデックスとします。オブジェクトは

C++でいうポインターに相当するので、インデックスとしてナル

(null)も許されます。キーの順序は定まっていますが、実装する

シミュレータにより異なります。一般的には、オブジェクトのアド

レスがキーになっていると考えて良いと思います。

[integer]

[int]

[shortint]

[byte]

[longint]等

整数系のインデックスを使用します。但し、four state の値をイン

デックスとして使用する事は出来ません。

3.6.1 Associativeアレイの要素の登録

associativeアレイの要素が存在しない時、次の何れかが発生します。

アレイ要素が LHSとして使用されている場合には、要素が自動的に割り当てられます。

アレイ要素が LHSとして使用されていない場合には、要素は割り当てられません。

SystemVerilog の associative arrays の特徴は、キーで示すアレイ要素が存在しない場合の条件を指

定できる便利さにあります。

例 3-17

price は string型をキーに持つ associative arrayです。定義に於いて標準値を 100に設定していま

す。もしキーで示すデータが存在しない場合には整数値 100 をデータとして price に登録しま

す。

最初は price.size==0 である為、price[key]は存在しません。定義により、price[key]

の要素が作られ、price[key]==100 となります。price[key]++の実行後に、price[key]

は 101になります。詰まり、price[“bread”]==101 です。

その後、price[key] += 20 により price[“bread”]==121 となります。

実行結果は以下の様になります。

module test;

int price[string] = '{ default : 100 };

string key;

initial begin

key = "bread";

price[key]++; // 101

$display("%s=%0d",key,price[key]);

price[key] += 20; // 121

$display("%s=%0d",key,price[key]);

end

endmodule

Page 53: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

42

3.6.2 Associative アレイの関数

アレイを操作する為に以下の様な methodsがあります。

method 意味

function int num();

function int size();

アレイに登録されている要素数を戻します。

function void delete( [input index] ); index が指定されれば、index をキーに持つ要

素を削除します。その要素が存在しない場合、

何も実行されません。

index が省略された場合、アレイの要素を全て

抹消します。

function int exists( input index ); 指定した index を持つ要素が存在するかチェッ

クします。存在すれば 1 を戻し、存在しなけれ

ば 0を戻します。

function int first( ref index ); アレイの最初のキーを indexにセットします。

アレイが空の場合、0 を戻します。空でない時

には、1を戻します。

function int last( ref index ); アレイの最後のキーを indexにセットします。

アレイが空の場合、0 を戻します。空でない時

には、1を戻します。

function int next( ref index ); 指定された index よりも次に大きいキーが存在

すれば index にセットして 1 を戻します。存在

しない場合、0 を戻します。index に変化はあ

りません。

function int prev( ref index ); 指定された index より一つ手前のキーが存在す

れば index にセットして 1 を戻します。存在し

ない場合、0 を戻します。index に変化はあり

ません。

例 3-18

この例は、出現した word の頻度を辞書に登録しています。登録した後、全ての words を順に取

り出してプリントします。キーが文字列であるので、自然な順序で words が取り出されています。

word が登録されていない状態では使用頻度の初期値は 0 となります。これは、word_count ア

レイのタイプが int であるからです。従って、最初の

word_count["river"]++;

を実行後には word_count[“river”]は 1 となります。二度目に”river”が現れると、

word_count[“river”]は 2となります。

bread=101

bread=121

Page 54: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

43

これを実行すると以下の様な結果を得ます。

3.6.3 Associativeアレイ・リテラル( associative array literals)

associative arraysの初期化にはアレイ・リテラル ‘{...} を使用します。

例 3-19

初期化には、キーとデータ値の対をコロン(:)で区切って指定します。ここでは指定をしてい

ませんが、default値も与える事が出来ます。実行すると以下の様な結果を得ます。

module test;

int word_count[string];

string word;

initial begin

word_count["river"]++;

word_count["sea"]++;

word_count["mountain"]++;

word_count["sky"]++;

word_count["star"]++;

word_count["river"]++;

$display("the number of words: %0d",word_count.size);

if( word_count.first(word) )

do

$display("%s=%0d",word,word_count[word]);

while (word_count.next(word));

end

endmodule

the number of words: 5

mountain=1

river=2

sea=1

sky=1

star=1

module test;

integer work_hours[string] = '{ "Sunday":0, "Monday":8,

"Tuesday":10, "Wednesday":10, "Thursday":8,

"Friday":8, "Saturday":0 };

string key;

initial begin

if( work_hours.first(key) )

do

$display("%s=%0d",key,work_hours[key]);

while( work_hours.next(key) );

end

endmodule

Page 55: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

44

3.7 キュー( queues)

Queues は伸縮自在なアレイです。データ構造の stacks、及び、queues として使用する事が出来ま

す。Queuesでは、アレイと同じ様に整数型インデックスにより要素にアクセスします。最初の要

素はインデックスが 0 です。最後の要素のアクセスにはインデックス $ を使用します。宣言は

以下の様に行ないます。

qi は整数を要素に持つ queueです。qs は string型の要素を持つ queueです。qs の最大の要素数

は 100 に設定されています。Associative arrays と同様に、宣言した時点で queues が有効になりま

す。即ち、宣言すると、要素数 0 の queue が確立します。new オペレータを使用する必要はあり

ません。

例 3-20

この例にある foods の様に、queue に初期値を割り当てる事が出来ます。foreach 文を見ると、

foods を通常のアレイと同じ様に扱える事が分かります。queue のサイズを N とすると、queue

は[0:N-1]のアレイに相当します。

この例を実行すると、以下の結果を得ます、

Friday=8

Monday=8

Saturday=0

Sunday=0

Thursday=8

Tuesday=10

Wednesday=10

int qi[$];

string qs[$:100];

module test;

byte empty_queue[$];

string foods[$] = { "bread", "milk", "meat", "rice", "noodle" };

int data[$] = { 1, 2, 3 };

real weight[$:100];

initial begin

$display("empty_queue.size=%0d",empty_queue.size);

$write("foods:");

foreach(foods[i])

$write(" %s",foods[i]);

$display;

end

endmodule

empty_queue.size=0

foods: bread milk meat rice noodle

Page 56: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

45

3.7.1 キューの操作(queue operators)

Queuesにはアレイと同様の演算を適用する事が出来ます。アレイと異なる点は、queues は伸縮自

在である事です。キュー q に対して q[a:b]もキューです。

キューの演算で、{} は空の queue を意味します。{}をキューを空にする為に使用する事が出来

ます。例えば。次の様にして使います。

q はリセットされます。

例 3-21

data は要素数 3の queue として定義されていますが、空の queue {}でリセットされています。実

行すると以下の結果を得ます。

アレイへの割り当てで以下の様な操作が可能でした。

q[a:b]は b-a+1 個の要素を持つキューです。但し、

もし a > bであれば、空のキューになります。

もし a == bであれば、ただ一つの要素を持つキューになります。

もし a < 0であれば、q[a:b]は q[0:b]と同じです。

string q[$];

...

q = {};

module test;

int data[$] = { 1, 2, 3 };

initial begin

print_data();

data = {};

print_data();

end

function void print_data;

$write("data:");

foreach(data[i])

$write(" %0d",data[i]);

$display;

$display("data.size=%0d",data.size);

endfunction

endmodule

data: 1 2 3

data.size=3

data:

data.size=0

Page 57: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

46

この種の操作をキューにも適用する事が出来ます。但し、キューの場合、左辺のキューと右辺の

キューは実質的に別の物です。例えば、

は、次の操作と同じです。

例 3-22

q を使って q を再定義しています。実行すると以下の結果を得ます。

3.7.2 キューを操作する関数(queue methods)

アレイの演算子に加えて以下の様な methods を使用する事が出来ます。メソッドの使用法により

データ構造は、スタック、又は、キューになります。

メソッド 意味

function int size(); Queue の要素数を戻します。

function void insert(input integer index,

input element_t item);

指定した位置(index)に要素を挿入します。

位置が正しくない場合、何も挿入されません。

function void delete( [input integer index] ); index が指定された場合、その index 位置にあ

る要素を削除します。

ordered = { "a", random[2], random[4:5], random[1],

random[3], "gLast" };

q = { q[0], q[$] };

tmp = { q[0], q[$] };

q = tmp;

module test;

int q[$] = { 2, 4, 8 },

one = 1;

initial begin

print("q",q); // {2,4,8}

q = { one, q[0], 3, q[1:$] }; // {1,2,3,4,8}

print("q",q);

end

function void print(string msg,int a[$]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

q: 2 4 8

q: 1 2 3 4 8

Page 58: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

47

index が省略された場合、queue の全ての要素

を削除します。

function element_t pop_front(); Queue の先頭の要素を削除して戻します。

function element_t pop_back(); Queue の最後の要素を削除して戻します。

function void push_front(input element_t

item);

Queue の先頭に要素を挿入します。

function void push_back(input element_t

item);

Queue の最後に要素を追加します。

例 3-23

実行すると以下の結果を得ます。

3.8 アレイ情報取得関数(array querying functions)

SystemVerilog はアレイの情報を取得する為のシステム関数を追加しました。例えば以下の様な

システム関数があります。

module test;

int q[$] = { 1, 4, 6 };

initial begin

print("q",q); // {1,4,6}

q.push_front(0);

q.push_back(7);

print("a",q); // {0,1,4,6,7}

q.insert(2,2);

print("q",q); // {0,1,2,4,6,7}

q.delete(0);

print("q",q); // {1,2,4,6,7}

q.delete;

print("q",q); // {}

end

function void print(string msg,int a[$]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

q: 1 4 6

a: 0 1 4 6 7

q: 0 1 2 4 6 7

q: 1 2 4 6 7

q:

Page 59: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

48

後章でこれらの関数の機能を紹介します。

3.9 アレイ操作関数(array manipulation methods)

SystemVerilogはアレイを操作する為に以下の様なビルトイン関数を備えています。

検索

順序付け

計算(reduction)

計算(reduction)はアレイから一つの値を導く関数を意味します。例えば、アレイ要素の和を求

める関数があります。

3.9.1 アレイ検索関数(array locator methods)

Array locator methods は queues を含む全ての unpacked arrays に適用する事が出来ます。これらの

メソッドはアレイの要素を与えられた条件で検索します。検索結果はリストとして queue に記録

されます。検索結果は要素のリスト、又は、要素へのインデックスのリストになります。検索条

件を with を使用して記述します。例えば、

の様に記述します。この検索は、3 より大きい要素のインデックスのリストを queue に戻します。

ここで、item はアレイの要素を示す変数でコンパイラーが自動的に定義します。

以下の methodsには検索条件 with が必要です。

method 意味

find() 検索条件を満たす全ての要素を戻します。

find_index() 検索条件を満たす要素へのインデックスのリス

トを戻します。

find_first() 検索条件を満たす最初の要素を戻します。

find_first_index() 検索条件を満たす最初の要素のインデックスを

戻します。

find_last() 検索条件を満たす最後の要素を戻します。

find_last_index() 検索条件を満たす最後の要素のインデックスを

戻します。

$left

$right

$low

$high

$increment

$size

$dimensions

$unpacked_dimensions

int qi[$];

...

qi = array.find_index with (item > 3);

Page 60: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

49

例 3-24

検索結果が一つの要素しかない場合でも、queue で結果を受け取らなればなりません。これを実

行すると以下の様になります。

以下の methodsに対しては、検索条件を省略する事が出来ます。

method 意味

min() 最小値を戻します。

max() 最大値を戻します。

unique() 重複の無い要素のリストを戻します。

unique_index() 重複の無い要素のインデックスのリストを戻し

ます。

module test;

int data[] = '{ 10, 1, 20, 30, 1, 50 },

q[$];

initial begin

q = data.find with (item >= 30);

print("q",q); // {30,50}

q = data.find_index with (item >= 30);

print("q",q); // {3,5}

q = data.find_last with (item == 1);

print("q",q); // {1}

q = data.find_last_index with (item ==1);

print("q",q); // {4}

q = data.find_first with (item < 0);

print("q",q); // {}

end

function void print(string msg,int a[$]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

q: 30 50

q: 3 5

q: 1

q: 4

q:

Page 61: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

50

例 3-25

以下の様な結果を得ます。

3.9.2 アレイ要素の順序を操作する関数(array ordering methods)

これらの methods はアレイ要素の順序を入れ替える機能を持っています。アレイ自身に適用され

て内容が更新されます。但し、associative arraysに適用する事は出来ません。

method 意味

reverse() アレイ要素の順序を逆に並べ替えます。with

条件を指定する事は出来ません。

sort() 要素を上昇順に並べ替えます。with 条件を指

定する事が出来ます。

rsort() 要素を下降順に並べ替えます。with 条件を指

定する事が出来ます。

shuffle() 要素をランダムな順に並べ替えます。with 条

件を指定する事は出来ません。

module test;

int data[] = '{ 1, 2, 3, 1, -3, 2, 6 },

q[$];

initial begin

q = data.min();

print("q",q); // {-3}

q = data.max();

print("q",q); // {6}

q = data.unique();

print("q",q); // {1,2,3,-3,6}

q = data.unique_index();

print("q",q); // {0,1,2,4,6}

end

function void print(string msg,int a[$]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

q: -3

q: 6

q: 1 2 3 -3 6

q: 0 1 2 4 6

Page 62: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

51

例 3-26

これを実行すると以下の様な結果を得ます。

3.9.3 アレイを計算する関数(array reduction methods)

その名が示す通り、アレイの複数の要素から一つの値を導き出す機能です。with clause を指定す

る事が出来ますが、with は値を作る為に使用されます。integral types の全ての unpacked arrays に

適用する事が出来ます。以下の様な methodsがあります。

method 意味

sum() アレイ要素の和を戻します。with 条件を指定

する事が出来ます。

product() アレイ要素の積を戻します。with 条件を指定

する事が出来ます。

and() アレイ要素のビット毎の AND(&)を戻しま

す。with条件を指定する事が出来ます。

or() アレイ要素のビット毎の OR(|)を戻しま

す。with条件を指定する事が出来ます。

xor() アレイ要素のビット毎の XOR(^)を戻しま

す。with条件を指定する事が出来ます。

戻される値のタイプは、原則として、アレイ要素と同じタイプです。

module test;

int data[] = '{ 10, 2, 4, 8, 10, 20 };

initial begin

print("data",data); // {10,2,4,8,10,20}

data.reverse();

print("data",data); // {20,10,8,4,2,10}

data.sort();

print("data",data); // {2,4,8,10,10,20}

data.rsort();

print("data",data); // {20,10,10,8,4,2}

data.shuffle();

print("data",data);

end

function void print(string msg,int a[]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

data: 10 2 4 8 10 20

data: 20 10 8 4 2 10

data: 2 4 8 10 10 20

data: 20 10 10 8 4 2

data: 10 10 2 4 20 8

Page 63: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

52

例 3-27

実行結果は以下の様になります。

最初の

r = data.sum;

は説明の余地はないと思います。r==15 になる事は容易に理解できます。では、次の文はどう

でしょうか?

r = data.sum with (item*2);

r==30 になります。この命令の意味は、「アレイ要素を2倍して和を取る」という意味です。

従って、30になります。

最後の sum は複雑です。3 より大きい要素の和を求める事が目的ですが、予想に反して複雑な式

が記述されています([3])。

r = data.sum with ((item>3)*item);

何故、(item>3)*item なのでしょうか?逆に言えば、次の様に記述してはいけないのでしょう

か?

r = data.sum with (item>3);

この場合、r==2 となります。item>3 を満たす要素は 4 と 5 の二つです。つまり、式 item>3

が真となるのは二回あります。真は 1なので、r==2となります。

((item>3)*item)は 3 より大きな要素の和を取る意味になっています。withクローズは計算を

する為に使用されます。検索の為ではありません。

module test;

int data[] = '{ 1, 2, 3, 4, 5 },

r;

initial begin

r = data.sum;

$display("r=%0d",r); // 1+2+3+4+5=15

r = data.sum with (item*2);

$display("r=%0d",r); // 2*(1+2+3+4+5)=30

r = data.sum with ((item>3)*item);

$display("r=%0d",r); // 4+5=9

end

endmodule

r=15

r=30

r=9

Page 64: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

53

今の例が示す様に array reduction methodsを使用する際には注意が必要です。注意が必要な例をも

う一つ紹介します。

例 3-28

結果は以下の様になります。

1+1+1==3 であるにも関わらず、state.sum は 1になっています([3])。state.sumのタイプは

stateの要素のタイプ bitと同じです。従って、1ビットのタイプです。この為、state.sumが1とな

っています。この問題を避ける為には、ビット長を拡張する必要があります。state の和は最大 5

なので、3ビットあれば十分です。その為に、3'b0+state.sum としました。

module test;

bit state[5] = '{ 1, 0, 0, 1, 1 };

initial begin

$write("state= ");

foreach(state[i])

$write("%b",state[i]);

$display;

$display("state.sum=%0d",state.sum);

$display("state.sum=%0d",3'b0+state.sum);

end

endmodule

state= 10011

state.sum=1

state.sum=3

Page 65: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

54

4 クラス(classes)

4.1 クラスの概要

クラスはデータ・タイプの一つで、データとサブルーティン(functions、及び tasks)から構成さ

れます。クラスでは、データをプロパーティ( properties)、サブルーティンをメソッド

(methods)と呼びます。クラスには new と呼ばれる特別なメソッドがあり、コンストラクタと

呼びます。コンストラクタはクラスのインスタンス(つまり、オブジェクト)を創成します。

SystemVerilogのクラスの概念は C++のそれより Javaのクラスに似ています。

例 4-1

簡単なトランザクションが simple_transaction としてパッケージ内に定義されています。

クラスにはメソッドとして、new、get_name、及び、 print が定義されています。

メンバーname は localとして宣言されている為、クラスの外から直接参照する事は出来ません。

クラスの外から name を参照する為には、ファンクション get_name()を使用しなければなりま

せん。

更に、クラスには staticなメンバーcounter が定義されています。このメンバーはクラスのイン

スタンス数を示します。static である為、このクラスの全てのインスタンスに対して唯一つの

counter が確保されます。データ・タイプは intなので、初期値は 0となっています。クラスの

package Pkg;

parameter ADDR_WIDTH = 32;

parameter DATA_WIDTH = 32;

typedef logic[ADDR_WIDTH-1:0] addr_t;

typedef logic[DATA_WIDTH-1:0] data_t;

class simple_transaction;

static int counter;

local string name;

addr_t addr;

data_t data;

function new(string name,addr_t a=100,data_t d=0);

this.name = name;

addr = a;

data = d;

counter++;

endfunction

function string get_name();

return name;

endfunction

virtual function void print;

$display("name=%s",name);

$display("addr=%h",addr);

$display("data=%h",data);

endfunction

endclass

endpackage

Page 66: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

55

インスタンスを作る時には、new コンストラクタが必ず呼ばれます。従って、new で counter

の更新をします。

print()関数は virtual として定義されています。このクラスから継承したクラスでこの関数を

書き換える事が出来ます。

4.2 クラス・オブジェクト(クラス・インスタンス)

クラスはデータ・タイプです。オブジェクトはクラスのインスタンスです。クラス・タイプを持

つ変数を定義して、次の様に変数にオブジェクトを割り当てます。

宣言と割り当てを個別に行う事も出来ます。

何れの方法でも変数にオブジェクトを割り当てる事が出来ます。SystemVerilogではこの変数をオ

ブジェクト・ハンドルと呼びます。オブジェクトを割り当てていないハンドルにはナル(null)

が割り当てられます。ナルのハンドルでプロパーティやメソッドにアクセスすると、一般的には、

異常終了します。例えば、次の様な操作をするとシミュレータが異常終了します。

従って、次の様に使用するのが一般的です。

4.3 クラス・プロパーティ及びメソッドへのアクセス

SystemVerilog では、プロパーティ及びメソッドへのアクセスにはハンドルとドット(.)を使用

します。C/C++の様な記法(->)は出来ません。例えば、次の様に使用します。

staticなメンバーへのアクセスは、スコープ・オペレータを使用する事が出来ます。例えば、

simple_transaction::counter

の様に参照する事が出来ます。

4.4 コンストラクタ

既に紹介した様に、クラスのコンストラクタを new と呼ばれる function として定義します。但し、

SystemVerilogでは戻りのタイプを指定せずに次の様に定義します。

simple_transaction tr = new(“TR1”);

simple_transaction tr;

tr = new(“TR1”);

simple_transaction tr;

tr.addr = 0;

simple_transaction tr;

...

if( tr == null )

tr = new(“TR1”);

simple_transaction tr;

tr = new(“TR1”);

tr.print();

Page 67: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

56

クラスを定義する際にコンストラクタの定義を省略すると、コンパイラーが自動的に次の様な空

のコンストラクタを定義します。

既存のクラスをベースにして新しいクラスを定義する場合には、コンストラクタの最初の命令は

super.new()でなければなりません。

例 4-2

以前定義したクラス simple_transaction を拡張して delayed_simple_transaction ク

ラスを定義しています。このクラスのコンストラクタの最初の文で元のクラスのコンストラクタ

を呼んでいます。また、メソッド printの機能も拡張しています。

ベース・クラス simple_transaction のコンストラクタ new では引数 name は必須のパラメ

ータとなっています。この為、サブクラス delayed_simple_transaction でもコンストラク

タを定義しなければなりません。

4.5 タイプ指定のコンストラクタ呼び出し

new コンストラクタのクラス・タイプは左辺の変数のクラス・タイプにより決定されます。例え

ば、

の場合、newのクラス・タイプは simple_transaction です。newの前にクラス・スコープを

指定する事によりコンストラクタを変える事が出来ます。例えば、

function new(...);

...

endfunction

function new;

endfunction

class delayed_simple_transaction extends simple_transaction;

int delay;

function new(string name,addr_t a=100,data_t d=0,int delay=0);

super.new(name,a,d);

this.delay = delay;

endfunction

function void print;

super.print();

$display("delay=%0d",delay);

endfunction

endclass

simple_transaction tr;

tr = new(“TR1”);

Page 68: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

57

tr2 のタイプは simple_transaction ですが、delayed_simple_transaction のコンス

トラクタを呼んでいます。この為、tr2 は実際には delayed_simple_transaction のイン

スタンスを指しています。従って、tr2.print は delayed_simple_transaction::print

を呼び出します。これは virtualメソッドの利点です。

4.6 Staticクラス・プロパーティ

クラスに定義したメンバーは、原則として、automatic です。従って、クラス・インスタンス毎に

存在します。しかも、メソッドが呼ばれると引数、及び、メソッド内の変数はスタック上に確保

されます。言い換えると、以前の状態は保存されていません。

同じクラス・タイプのインスタンス全てに共通なメンバーを定義する為には、static という修飾

子を使用します。プロパーティ、及び、メソッドに対してこの修飾子を適用する事が出来ます。

static メンバーは唯一つしか存在しないという性質から、クラス・スコープを使用して static メン

バーへのアクセスをする事が出来ます。クラスのインスタンスを作る必要はありません。

例 4-3

simple_transaction tr2;

tr2 = delayed_simple_transaction::new(.name(“TR2”),.delay(500));

class packet;

static int counter = 0;

logic [31:0] addr, data;

string name;

function new(logic [31:0] a=0,d=0);

addr = a;

data = d;

counter++;

name = $sformatf("packet_%04d",counter);

endfunction

virtual function void print;

$display("name=%s",name);

$display("addr=%h",addr);

$display("data=%h",data);

endfunction

endclass

module test;

packet p;

initial begin

p = new;

p.print;

$display("the number of instances=%0d",packet::counter);

end

endmodule

Page 69: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

58

counter は static なので、packet クラスに対して唯一つしか存在しません。即ち、全ての

packet のインスタンスに共通な変数です。この例では、packet オブジェクトのカウンターと

しての役割を持っています。

4.7 Staticクラス・メソッド

staticクラス・プロパーティと同様にメソッドも staticに確保する事が出来ます。但し、staticメソ

ッドでは、staticなプロパーティしかアクセスする事が出来ません。

例 4-4

getCounter は staticメソッドとして定義されています。この functionの中では、staticなプロパ

ーティ、又は、static なメソッドしか参照する事は出来ません。例えば、getCounter の中で

name を使用するとコンパイル・エラーとなります。

4.8 Staticメンバーの参照

Staticメンバーの参照は、クラス・スコープを使用します。例えば、

の様にして呼び出します。クラスの変数を使用して参照する事も出来ますが、余り勧められる方

法ではありません。例えば、

の様に参照する事が出来ます。ここで注意する事は sample がナル・ハンドルである事です。ナ

ル・ハンドルを使用してクラスのメンバーにアクセスすると、一般的には、異常終了しますが、

static メンバーへのアクセスは例外です。上記の方法は正常に動作します。然し、ナル・ハンド

ルは思わぬ問題を引き起こす原因に繋がる為、static メンバーへのアクセスはクラス・スコープ

を使用する事が望ましいと思えます。以下の記述法を参考にして下さい。

class static_sample;

static int counter = 0;

string name;

function new();

name = $sformatf("sample_%04d",++counter);

endfunction

function void print;

$display("name=%s",name);

endfunction

static function int getCounter();

return counter;

endfunction

endclass

static_sample::getCounter()

static_sample sample;

$display(“%0d”,sample.getCounter());

$display(“%0d”,sample.counter);

Page 70: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

59

4.9 This

これまでの例で何度も使用しています。メソッド内で同じ名称がメンバーと引数に存在する時、

現在のクラスのメンバーを特定する為等に使用します。例えば、次の記述を参照して下さい。

thisの使用は本質的です。thisの指定が無いと、引数の name を参照する事になります。

4.10 ハンドルのアレイ

クラス・オブジェクトのアレイを確保する事は出来ませんが、クラス・オブジェクトへのポイン

ターのアレイを確保する事は可能です。例えば、

上記の①はクラス sample_t へのハンドルのアレイを定義しています。アレイ・サイズは 10 と決

定していますが、クラスへのハンドルは定義されていません。即ち、C/C++と異なり、コンスト

ラクタは自動的に呼ばれません。従って、アレイの初期化を明示的に行なう必要があります。フ

ァンクション initArrayがその役目を果たしています。

$display(“%0d”, static_sample::getCounter());

$display(“%0d”, static_sample::counter);

class sample_t;

string name;

function new(string name);

this.name = name;

endfunction

endclass

class sample_t;

string name;

function new(string name);

this.name = name;

endfunction

...

endclass

...

module test;

sample_t sample_array[10]; ①

initial begin

initArray();

...

end

function void initArray();

foreach(sample_array[i])

sample_array[i] = new($sformatf("sample_%0d",i));

endfunction

endmodule

Page 71: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

60

4.11 クラスのコピー

クラス・ハンドルをコピーする事が出来ます。コピーすると、二つのハンドルが同じクラス・オ

ブジェクトを参照する事になります。クラス・オブジェクトを創成する事にはなりません。

例 4-5

s1 と s2 は同じクラス・オブジェクト参照しています。一方、s3 は s1 と異なるクラス・オブ

ジェクトを指しますが、メンバーの値は同じです。s3 は s1 の内容をコピーして作られました。

このコピーは、所謂、shallow copyです。即ち、recursiveにはコピーされません。

4.12 クラスの継承とサブクラス

既存のクラスから継承して新たなクラスを定義する事が出来ます。新しいクラスでは既存のクラ

スのメンバーをそのまま使用する事が出来ます。SystemVerilog では Java と同様に既存のクラス

を extends して新しいクラスを定義します。既存のクラスをベース・クラス(base class)、新し

いクラスをサブクラスと呼びます。

以前の例で示した delayed_simple_transaction は simple_transaction のサブクラス

です。サブクラス内にベース・クラスと同じメンバーを含む場合、サブクラス内でベース・クラ

スのメンバーを参照するには super.で明示します。例えば、super.printの様に参照します。

ベース・クラスの全てのメンバーがサブクラスに見えるわけではありません。ベース・クラスで

local属性を持つメンバーはサブクラス、及び、クラス外ではアクセスする事が出来ません。

class sample;

int identifier,

state;

function new(int id,int s);

identifier = id;

state = s;

endfunction

function void print;

$display("identifier=%0d state=%0d",identifier,state);

endfunction

endclass

module test;

sample s1, s2, s3;

initial begin

s1 = new(10,8);

s2 = s1;

// ...

s3 = new s1;

// ...

end

endmodule

class subclass extends baseclass

...

endclass

Page 72: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

61

メンバーへのアクセス制限をすると、そのメンバーへのアクセスを可能にする為には必ずアクセ

スする為の関数が必要になります。結果として、その関数呼び出しのオーバヘッドがシミュレー

タのパフォーマンスに影響します。その影響を念頭に置いてアクセス属性を定義する必要があり

ます。

4.13 $cast

クラス B がクラス A のサブクラスであれば、クラス B のオブジェクトをクラス A のハンドルに

割り当てる事が出来るのは容易に理解できます。複雑な継承関係にある場合には、ハンドルに設

定する事が可能か否か即時に明らかではありません。その様な場合、$cast 関数を使用する事が

出来ます。以前説明した$castと同様に、function形式と task形式があります。

function 形式ではハンドルの設定が可能であれば設定をして 1 を戻します。不可能の場合には、0

を戻します。task形式の場合には、不可能であればエラーとなります。

4.14 Virtualメソッド(virtual methods)

C++でいう virtual functions と同じ概念です。ベース・クラスに virtual メソッド vm を定義すると、

継承されたクラスのオブジェクトに一致するメソッド vm を呼び出します。言い換えると、クラ

ス・ハンドルがベース・クラスのタイプでも、ハンドルが継承されたクラスのインスタンスを示

していれば、継承されたクラスの vm を呼び出します。但し、継承したクラスにもメソッド vm

が定義されていなければなりません。例を示します。

例 4-6

function int $cast( singular dest_var, singular source_exp );

task $cast( singular dest_var, singular source_exp );

class base_transaction;

virtual function void print;

$display("base_transaction no members.");

endfunction

function void print_class;

$display("base_transaction");

endfunction

endclass

class transaction extends base_transaction;

rand bit [15:0] addr, data;

function new(bit [15:0] a=0,d=0);

addr = a;

data = d;

endfunction

function void print;

$display("transaction has two members: addr=%0d data=%0d",

addr,data);

endfunction

function void print_class;

$display("transaction");

endfunction

endclass

Page 73: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

62

クラスの定義は上記の様になっています。クラス transaction はベース・クラス

base_transaction の機能を拡張しています。base_transaction::print は virtualとして

宣言されています。サブクラスでは print を再定義していますが、virtual の修飾子を付ける必

要はありません。テストベンチは以下の様になっています。

実行すると以下の様な結果を得ます。

4.15 アブストラクト・クラスとピュア・バーチャル・メソッド

クラスを継承する事により、クラスの定義をより詳細に定義して行きます。例えば、サブクラス

はベース・クラスに比べてより多くの機能を保有します。その際、ベース・クラスの決めたルー

ル(メソッドの使用法)に従う事が原則となっています。

極端なベース・クラスの場合、ルールだけを定義する事が出来ます。この様なクラスをアブスト

ラクト・クラスと言います。サブクラスではルールに具体的な内容を定義します。アブストラク

ト・クラスは、次の様に定義します。

アブストラクト・クラスは未完成である為、インスタンスを作る事は出来ません。メソッドの定

義は署名(signatures)だけから構成する様にします。その場合、修飾子 pureを用います。

module test;

base_transaction base;

transaction tr;

initial begin

base = new;

tr = new(10,50);

base.print; // base_transaction::print

base.print_class; // base_transaction::print_class

tr.print; // transaction::print

tr.print_class; // transaction::print_class

base = tr;

base.print; // transaction::print

base.print_class; // base_transaction::print_class

end

endmodule

base_transaction no members.

base_transaction

transaction has two members: addr=10 data=50

transaction

transaction has two members: addr=10 data=50

base_transaction

virtual class abstract_class;

...

endclass

Page 74: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

63

サブクラスは print の定義をしなければなりません。具体的な定義をしない場合、サブクラス

もアブストクラスになり、インスタンスを作成する事は出来ません。

サブクラス some_class では print ファンクションを実装したので、some_class のインス

タンスを作る事が出来ます。

4.16 クラススコープ・オペレータ(class scope resolution operator ::)

クラスのパラメータ、データタイプ、static メンバーにアクセスする場合にはこのオペレータを

使用します。例えば、

の様に使用します。或いは、ターゲットを明確にする為にもスコープ・オペレータを使用します。

例えば、

の様に書く事が出来ます。この文を含むスコープ内に関数 randomize()が定義されている場合、

混乱を避ける事が出来ます。

ビルトイン・クラスを使用する場合には、クラススコープ・オペレータは必須となります。例え

ば、

に於いて、processオブジェクトを作る事は出来ない為、process:: は必須のオペレータです。

virtual class abstract_class;

pure virtual function print(string key,bit [31:0] data);

...

endclass

class some_class extends abstract_class;

virtual function print(string key,bit [31:0] data);

...

endfunction

...

endclass

static_sample::getCounter()

rs = std::randomize(a,b,c);

process job[] = new [3];

...

foreach(job[i])

fork automatic int k = i;

job[k] = process::self();

join_none

Page 75: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

64

例 4-7

クラス sample_t はパラメータとデータ・タイプの他に static なリスト・ヘッドを持っています。

コンストラクタにより、同じクラスのオブジェクトがリストに登録されます。リストは唯一つ必

要なので static属性が与えられています。

class sample_t;

parameter PI = 3.14;

typedef enum { RED, GREEN, YELLOW } color_e;

static sample_t head, tail;

sample_t next;

string name;

function new(string name);

this.name = name;

add_list(this);

endfunction

static function void add_list(sample_t obj);

if( tail == null ) begin

head = obj;

tail = obj;

end else begin

tail.next = obj;

tail = obj;

end

obj.next = null;

endfunction

endclass

module test;

sample_t::color_e color;

sample_t sample;

initial begin

color = sample_t::GREEN;

$display("PI=%g %s=%0d",

sample_t::PI, color.name,color);

sample = new("C1");

sample = new("C2");

sample = new("C3");

sample = sample_t::head;

while( sample != null ) begin

$display("%s",sample.name);

sample = sample.next;

end

end

endmodule

Page 76: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

65

4.17 メンバーへのアクセス制限(local and protected)

クラス・メンバーへのアクセスを制限する為に、local、及び、protected を使用する事が出来ます。

local 属性は、メンバーへのアクセスを同じクラスのタイプにだけ許します。protected 属性はサブ

クラスのみがアクセスできる様に制限します。

例 4-8

クラス extended から attribute にアクセスする事は出来ません。クラス other はクラス

base と無関係である為、name にアクセスする事は出来ません。

4.18 メソッドをクラスの外に記述する方法

メソッドの定義が多く存在する場合にはクラスの定義が長くなり、クラスの全容を把握しにくく

なります。その様な場合、複雑なメソッドの定義をクラスの外に移動する事が出来ます。extern

宣言をしたメソッドの署名をクラスに宣言し、クラスの外に実際の定義を記述します。

例 4-9

class base;

local int attribute = 0;

protected string name;

byte state;

endclass

class extended extends base;

function void check;

$display("%0d",attribute); // access error on attribute

$display("%0s",name); // ok

endfunction

endclass

class other;

extended e = new;

function void do_something;

$display("%s",e.name); // access error on name

endfunction

endclass

class packet;

static int counter = 0;

logic [31:0] addr, data;

string name;

function new(logic [31:0] a=0,d=0);

// ...

endfunction

extern virtual function void print(string msg);

endclass

function void packet::print(string msg);

// ...

endfunction

Page 77: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

66

クラスの外にメソッドを定義する際にクラス・スコープを使用します。外の定義には virtual が含

まれていない事に注意して下さい。

クラスの外にメソッドを定義する際、クラスが定義されているファイルと同じファイルにメソッ

ドを記述する事が望ましいと言えます。別のファイルに定義すると以下の問題が発生する恐れが

あります。

ファイルを`includeしなければならない。

正しい順にファイルを`includeしなければならない。

ファイルの管理が煩わしくなる。

4.19 パラメータによる汎用クラスの定義(parameterized classes)

多くのデータ構造には共通した機能があります。例えば、検索、及び、登録は辞書が持つ基本的

な機能です。共通した機能を一つのクラスに集約すると同じ処理を書く必要が無くなります。

SystemVerilog のクラスはパラメータにより汎用化する事が出来ます。この機能は C++の template

classに似ています。

整数をキーにする辞書と文字列をキーにする辞書は同じ機能を持ちます。異なる点は、キーのデ

ータ・タイプが異なるだけです。この様な場合、キーをパラメータ KEY、データのデータ・タ

イプをパラメータ DATATYPE としてクラスを定義します。そして、クラス内では、KEY と

DATATYPE を使用して論理を記述します。使用する側は、クラスのインスタンスを作る時に、

KEYと DATATYPEに実際のデータ・タイプを指定します。例えば、次の様に定義します。

利用する側の手順は以下の様になります。

class dictionary_t #(type KEY=int,DATATYPE=int);

DATATYPE data[KEY];

function int register(KEY key,DATATYPE data);

...

endfunction

function int exists(KEY key);

return data.exists(key);

endfunction

function void delete;

data.delete;

endfunction

...

endclass

module test;

dictionary_t#(int,string) dictionary = new;

...

if( !dictionary.exists(100) )

dictionary.register(100,”Books”);

...

endmodule

Page 78: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

67

例 4-10

このクラスは、associative array を多くのデータ・タイプに使用する事が出来る様に拡張したクラ

スです。標準は、整数型のキーを持ち、整数型のデータを持つ辞書になります。辞書へアクセス

する関数も装備しています。以下に使用例を示します。

class map #(type KEY = int,type DATA = int);

DATA array[KEY];

string name;

function new(string name);

this.name = name;

endfunction

function void put(KEY key,DATA data);

array[key] = data;

endfunction

function DATA get(KEY key);

return array[key];

endfunction

function int exists(KEY key);

return array.exists(key);

endfunction

function int first(output KEY key);

return array.first(key);

endfunction

function int next(output KEY key);

return array.next(key);

endfunction

function void delete(int key);

array.delete(key);

endfunction

function void clear();

array.delete();

endfunction

function void print;

KEY key;

$display("size=%0d",array.size());

if( array.first(key) )

do

$display("%-8s %8g",key,array[key]);

while( array.next(key) );

endfunction

endclass

Page 79: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

68

これを実行すると以下の様な結果を得ます。

4.20 クラスのフォワード宣言(typedef class)

未定義のクラスを参照する為には、フォワード宣言が必要です。時としてクラス間の相互参照が

起こります。同時に二つのクラスを定義する事は不可能なので、フォワード宣言が必要になりま

す。

例えば、次の様に二つのクラス C1、及び、C2 の相互参照が発生している場合、どちらかのクラ

スを先に暫定的に定義しなければなりません。

コンパイラーがクラス C1をコンパイルしている間は C2は未定義ですが、typedefにより C2が暫

定的に定義されているので、クラス C1 内でクラス C2 を参照していてもエラーにはなりません。

コンパイラーは相互参照関係をエラボレーション時に解決します。

module test;

map #(string,real) weight;

string key;

initial begin

weight = new("Foods Weight");

weight.put("meat",1000.3);

weight.put("bread",200.5);

weight.put("rice",5000.9);

$display("%s",weight.name);

weight.print;

weight.clear();

weight.print();

end

endmodule

Foods Weight

size=3

bread 200.5

meat 1000.3

rice 5000.9

size=0

typedef class C2;

class C1;

C2 c;

endclass

class C2;

C1 c;

endclass

Page 80: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

69

例 4-11

クラス producer はクラス consumer を参照していますが、consumer は未だ定義されていません。

従って、フォワード宣言が必要です。

関数 producer_t::print()の中で、未定義の consumer.name を参照しています。コンパイ

ラーは name への参照が正しいか否かをこの時点では判断する事は出来ません。但し、シンタッ

クス・チェックは行えます。consumer.name の意味論としての正当性チェックはエラボレーシ

ョン時に行われます。

クラスを使用する側は以下の様になります。

typedef consumer_t;

//

// producer

//

class producer_t;

consumer_t consumer;

string name;

function new(string name);

this.name = name;

endfunction

function void set_consumer(consumer_t con);

consumer = con;

endfunction

function void print;

$display("self=%s consumer=%s",name,consumer.name);

endfunction

endclass

//

// consumer

//

class consumer_t;

producer_t producer;

string name;

function new(string name);

this.name = name;

endfunction

function void set_producer(producer_t pro);

producer = pro;

endfunction

function void print;

$display("self=%s producer=%s",name,producer.name);

endfunction

endclass

Page 81: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

70

これを実行すると以下の様な結果を得ます。

4.21 クラス・ハンドルの初期化

クラス・ハンドルの宣言時にハンドルの初期化をする事が出来ますが、実行順序に依存する可能

性がある為、注意が必要です。例を用いて説明をします。

例 4-12

ここでは、virtual interface を使用した例を示します。クラス、及び、interface は次の様になって

います。

先ず、クラス・ハンドルを宣言時に初期化をする例を示します。

module test;

consumer_t c = new("C1");

producer_t p = new("P1");

initial begin

c.set_producer(p);

p.set_consumer(c);

c.print();

p.print();

end

endmodule

self=C1 producer=P1

self=P1 consumer=C1

interface simple_if;

logic [7:0] request;

initial begin

request = 0;

end

endinterface

class sample_t;

virtual simple_if vif;

function new(virtual simple_if sif);

vif = sif;

$display("sif.request=%b",sif.request);

endfunction

endclass

Page 82: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

71

この記述を実行すると以下の様な結果を得ます。

クラス・ハンドル sample にクラス・オブジェクトを割り当てるタイミングはシミュレーション

開始以前である為、インターフェースの initial プロシージャが実行していません。この為、

sif.request == ‘xとなっています。

次に、クラス・ハンドルの宣言と初期化を別に行う記述を示します。

この記述を実行すると以下の様な結果を得ます。

この場合、sample にクラス・オブジェクトを割り当てる際には、(偶然にも)インターフェース

の initialプロシージャが既に実行しています。従って、sif.request == 0となっています。

要約すると、クラス・ハンドルの宣言と初期化のタイミングは極めて重要になります。

module top;

sample_t sample = new(SIF);

simple_if SIF();

endmodule

sif.request=xxxxxxxx

module top2;

sample_t sample;

simple_if SIF();

initial begin

sample = new(SIF);

end

endmodule

sif.request=00000000

Page 83: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

72

5 プロセス(processes)

5.1 シミュレーション・プロシージャ(structured procedures)

シミュレーション・プロシージャは一定時期にシミュレータから起動される実行命令のブロック

です。以下のプロシージャから構成されます。

initialプロシージャ

alwaysプロシージャ

finalプロシージャ

タスク(task)

ファンクション(function)

initial プロシージャと always プロシージャはシミュレーション開始と共に実行を開始します。

initial プロシージャは唯一回実行し、プロシージャの最後の文が終了すればプロシージャ全体の

活動は終了します。一方、always プロシージャは繰り返し実行し、シミュレーションが終了する

まで実行を続けます。

5.1.1 initialプロシージャ

initial プロシージャはシミュレーションの開始時に一度だけ実行するプロシージャで、変数の初

期化等をする為に使用します。例えば、次の様な初期化処理を記述します。

initial プロシージャで記述された初期化は信号の値の変化によるイベントを起こします。例えば、

上記の記述の _reset = 0; により (nededge _reset) のイベントが時刻 0 で発生します。

従って、次の様な always プロシージャが存在すると時刻 0 でプロシージャの if 文が実行します。

一方、次の様な記述では、_reset に関するイベントは時刻 0 で起こりません。

initial begin

_reset = 0;

q = ‘{ 1, 2, 3, 4, 5 };

packet = new;

...

end

always @(posedge clk,negedge _reset)

if( !_reset )

q <= 0;

else

q <= d;

module test;

logic _reset = 0;

...

initial begin

q = ‘{ 1, 2, 3, 4, 5 };

packet = new;

...

end

...

endmodule

Page 84: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

73

SystemVerilog では、変数の初期化はシミュレーションが開始する前に行われます。この点は

Verilogと大きく異なります。

progarm では always プロシージャを使用する事が出来ない為、initial プロシージャで初期化以外

の処理を記述します。例えば、次の様な記述をします。

実際問題として、program ブロックの initial プロシージャは module に定義される initial プロシー

ジャとは意味が異なります。program 内の initial プロシージャは reactive region で活動する為、

DUTに関係する信号の初期化処理を記述する為には相応しくありません。

5.1.2 alwaysプロシージャ

alwaysプロシージャは繰り返し実行する命令群のブロックです。SystemVerilogには、

汎用 always

always_comb

always_latch

always_ff

等があります。

5.1.2.1 汎用 alwaysプロシージャ

alwaysプロシージャは単純なループです。C/C++で記述すると次の様になります。

従って、always プロシージャは何らかのタイミング制御命令を含まなければなりません。always

プロシージャに命令を含むだけでは不十分です。例えば、

は clock に値 0 と 1 を交互に割り当てるかも知れませんが、他のスレッドに時間が割り当てら

れない為、シミュレータはロックされた状態に陥ります。次の様にタイミング制御が必要になり

ます。以下の記述はクロック・ジェネレーションです。

最も良く使われる alwaysプロシージャの形式は以下の様になります。

program test(simple_if sif);

initial begin

#3 sif.request <= 1;

#7 sif.request <= 2;

#9 sif.request <= 3;

#35 $exit();

end

...

endprogram

while ( 1 ) ;

always clock = ~clock;

always #10 clock = ~clock;

always @(posedge clock)

q <= d;

Page 85: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

74

SystemVerilogでは実行中のプロセスがタイミング制御に遭遇してブロックすると、他のプロセス

(あるいはスレッド)に実行権が譲渡されます。たとえ遅延が 0のタイミング制御(#0)でもこ

の状況が起こります。逆に、この現象を利用して効果的な並列処理の制御を記述する事が出来ま

す。

例えば、以下の for ループで三つのテストケースをスレッドとして同時に実行する目的ですが、

それらのスレッドは即時には実行を開始しません。for ループ・ブロックを終了すると、タイミ

ング制御(#0)で親プロセスがブロックし、三つのテストケースの実行が開始します。その時に

は、j == 3 となっています。テストケースに、それぞれ、0、1、2 を割り当てる為に fork ブロッ

クの入り口で jの値を kに保存しています。三つの forkブロックは独自の kを保有します。

5.1.2.2 always_combプロシージャ

組み合わせ回路を記述する為のブロックです。Verilog にはない構造的ブロックです。Verilog で

組み合わせ回路を記述する場合、回路が依存する全ての信号をセンシティビティ・リスト

(@(...))として always プロシージャに記述しなければなりません。センシティビティ・リス

トに指定された信号が変化した時のみ組み合わせ回路が動作する為、不完全なセンシティビテ

ィ・リストの指定は正しくないシミュレーション結果に繋がります。

SystemVerilog の always_combプロシージャはセンシティビティ・リストを自動生成する機能を持

っています。例えば、

が与えられると、コンパイラーはセンシティビティ・リスト @(a,b) を自動生成します。この

他の利点もあります。always_comb プロシージャの左辺の変数に対して他のブロックでは値を設

定する事は出来ません。

或いは、論理が組み合わせ回路ではないと判断される場合、コンパイラーが警告を発します。例

えば、

の記述ではラッチが生成される為、コンパイラーは警告メッセージを発行します。

5.1.2.3 always_latchプロシージャ

always_latch プロシージャは always_comb と似ています。違いは、always_latch はラッチ回路を記

述する為のプロシージャです。即ち、プロシージャがラッチの記述になり得ない場合、コンパイ

ル時に警告が発行されます。例えば、次の記述は警告の対象になります。

for( int j = 0; j < 3; j++ )

fork automatic int k = j;

run_test(k);

join_none

#0 $display("Let them go.");

always_comb

{co,sum} = a+b;

always_comb begin

if( s )

a = b;

end

Page 86: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

75

制御信号 sel の値に関わらず、常に、q には値が設定されます。従って、ラッチの性質を満た

していません。一方、次の記述は正しくなります。

然し、次の記述は警告の対象になります。

この記述は以下の記述と同じです。

ラッチを生成する論理については論理合成のルールを参照して下さい。

5.1.2.4 always_ffプロシージャ

このプロシージャは論理合成可能なシーケンシャル回路を記述する為に考案された機能です。プ

ロシージャの先頭でイベント制御し、制御信号を posedge 又は negedge で制御しなければなりま

せん。また、ブロッキング・タイミング制御命令を使用する事が出来ません。例えば、次の記述

は正しいシーケンシャル回路です。

一方、次の記述にはクロック・イベントの指定が無い為、正しくありません。

また、次の記述には複数回のイベント制御がある為、エラーとなります。

always_latch

if( sel )

q = a;

else

q = b;

always_latch

if( sel )

q = d;

always_latch begin

q = a;

if( sel )

q = d;

end

always_latch begin

if( sel )

q = d;

else

q = a;

end

always_ff @(posedge clk)

q <= d;

always_ff

q <= d;

Page 87: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

76

5.1.3 finalプロシージャ

シミュレーションの実行が終了した時点で制御を受けるプロシージャです。シミュレーションは

終了している為、時間を消費する命令を final プロシージャに記述する事は出来ません。通常は、

シミュレーション結果を総括する情報をプリントする命令を記述します。

複数の final プロシージャを記述する事が出来ますが、それらのプロシージャは任意の順に実行

されます。

5.2 ブロック文(block statements)

ブロック文は一連の文を一つのグループに纏める文です。複数の文から構成されてもブロックと

して一つの文になります。ブロック文には、begin-endブロックと fork-joinブロックがあります。

5.2.1 begin-endブロック

ブロックを begin と end で囲んで記述します。ブロック内の文は上から順に実行します。文に遅

延が指定された場合、遅延値はその前に実行した文に対しての相対的な時間差を意味します。

例 5-1

実行すると以下の様な結果を得ます。

always_ff @(posedge clk) begin

@(negedge clk);

q <= d;

end

final begin

$display(...);

...

end

module test;

initial begin

#10 print(1);

#20 print(2);

#30 print(3);

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

@10 value=1

@30 value=2

@60 value=3

@60 main completed.

Page 88: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

77

5.2.2 fork-joinブロック

並列処理を記述する際に使用します。 SystemVerilog には、 fork-join、 fork-join_any、 fork-

join_none の三種類があります。ブロック内の文は同時に実行します。ブロック内の文は子プロセ

ス(スレッド)として実行します。対のキーワードにより機能が以下の様に異なります。

対のキーワード 意味

join 全ての子プロセスが終了するまで、親プロセスは待ち状態に入りま

す。

join_any 何れか一つの子プロセスが終了するまで、親プロセスは待ち状態に

入ります。

join_none 全ての子プロセスを生成しますが、親プロセスは実行を継続しま

す。生成された子プロセスは、親プロセスがブロックするか終了す

るまで実行を開始しません。

join_none を使用する場合、親プロセスがブロックするまで子プロセスの実行は開始しません。こ

の規約により、親プロセスは何処かの時点でタイミング制御により自身をブロックをして子プロ

セスに実行権を譲渡する必要があります。

join_none はプロセスをブロックしない為、ファンクション(function)でタイミング制御する時

に使用する事が出来ます。

例 5-2

親プロセスが三つの子プロセスを生成しています。その後、親プロセスは join 命令を実行します。

この命令により、親プロセスは自分自身の実行をブロックします。結果として、三つの子プロセ

スは実行権を受け取り、スケジューリングされます。三つの子プロセスの中で最後に終了した子

プロセスが親プロセスの実行再開を可能にします。

実行すると以下の様な結果を得ます。

function void q_process;

fork

wait( ev.triggered() ) q.push_back(1);

join_none

endfunction

module test;

initial begin

fork

#10 print(1);

#20 print(2);

#30 print(3);

join

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

Page 89: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

78

例 5-3

実行すると以下の様な結果を得ます。

例 5-4

実行すると以下の様な結果を得ます。

@10 value=1

@20 value=2

@30 value=3

@30 main completed.

module test;

initial begin

fork

#10 print(1);

#20 print(2);

#30 print(3);

join_any

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

@10 value=1

@10 main completed.

@20 value=2

@30 value=3

module test;

initial begin

fork

#10 print(1);

#20 print(2);

#30 print(3);

join_none

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

Page 90: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

79

ブロック内で生成された子プロセスは親プロセスがブロックするまで実行を開始しません。この

為、変数の参照には特別な注意が必要です。以下の例は良く知られています([1][3])。

例 5-5

forループの内部に fork-join_noneがあり、ループ制御変数 i の値をプリントしています。i の値

が 1、2、3 とプリントされる事を期待しているコーディングですが、予想に反して結果は以下の

様になります。

fork-join_noneにより$write のプロセスが生成されますが、親プロセスがブロックするまで、子

プロセスは開始しません。for ループが終了した時に親プロセスはブロックしますが、この時に

は i==4 となっています。従って、三つの$write のプロセスは 4をプリントします。

何らかの形で子プロセスの環境を保存する必要があります。

fork ブロック内の子プロセスは親プロセスと異なるタイミングで実行する為、現在の実行環境を

保存しておく必要があります。

例 5-6

@ 0 main completed.

@10 value=1

@20 value=2

@30 value=3

module test;

initial begin

for( int i = 1; i <= 3; i++ )

fork

$write("%0d",i);

join_none

#0 $display;

end

endmodule

444

module test;

initial begin

for( int i = 1; i <= 3; i++ )

fork automatic int k = i;

$write("%0d",k);

join_none

#0 $display;

end

endmodule

Page 91: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

80

fork 文が実行する時、i の値が k に保存されます。k は automatic である為、ループ回数だけ k

が確保されます。即ち、三つの子プロセスは独自の k を保有する事になります。それらは、順に

1、2、3です。従って以下の実行結果を得ます。

5.2.3 ブロック名(block names)

begin-end、及び、fork-join ブロックには名前を付ける事が出来ます。付けた名称を外部から参照

する事が出来ます。begin 及び fork キーワードの後にコロン(:)で区切って名称を添えます。対

のキーワードにも名称を付ける事が出来ます。例えば、次の様に名称を付けます。

5.3 タイミングによる実行制御(procedural timing controls)

タイミングの実行制御には、遅延(#で始まる式)による制御とイベント(@で始まる式)による

制御の二種類があります。

5.3.1 遅延による制御(delay control)

制御する命令に遭遇した時点から、指定した時間だけ経過した時点に実行を再開する機能を持ち

ます。制御命令に遭遇すると、遅延の値に関わらずそのプロセスは実行権を放棄します。以前の

例でこの状況を説明しましたが、もう一度見てみます。

親プロセスは、#0 の遅延制御をしています。実を言えば、意図的に遅延を置いています。for ル

ープ内で子プロセスを生成していますが、join_none を使用している為、親プロセスは実行を継続

します。生成された子プロセスは実行待ちの状態になっています。親プロセスがブロックするま

でその状態は継続します。従って、どこかで親プロセスは待ちの状態に入らなければなりません。

for ループが終了した後に、#0 のディレーを置いたのは、子プロセスに実行のチャンスを与える

為です。

5.3.2 イベント制御(event control)

ネットや変数の値の変化に同期して実行制御を行う方法がイベント制御です。良く知られている

イベントとしては、posedge、negedge、及び、edge があります。これらは、エッジ・センシティ

ブ・イベント制御(edge-sensitive event control)と呼ばれます。

イベント 意味

posedge 0から他の値への変化。或いは、x、又は、zから 1への変化。

negedge 1から他の値への変化。或いは、x、又は、zから 0への変化。

edge posedge、又は、negedgeのイベント。

123

begin: create_transaction

...

end: create_transaction

for( int i = 1; i <= 3; i++ )

fork automatic int k = i;

$write("%0d",k);

join_none

#0 $display;

Page 92: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

81

例えば、次の様にしてイベント制御を行います。

或いは、

unpacked アレイの変化を待つ場合、アレイ全体で待つ事は出来ません。例えば、次の記述はコン

パイル時にエラーとなります。

次の様な記述に書き直す必要があります。

5.3.3 レベル・センシティブ・イベント制御(level-sensitive event control)

ある条件が満たされるまで実行待ちをする制御がレベル・センシティブ・イベント制御です。通

常、wait文を使用します。関連する命令としては、wait fork、及び、wait_orderがあります。例え

ば、次の記述は、キューに要素が入れられるのを待っています。

wait 文が実行した時、もし q.size() == 0 であれば、q.size() > 0 になるまで、待ち状態

に入ります。一方、wait文が実行した時に q.size() > 0 であれば、実行は継続して即座に

index = q.pop_front

を実行します。この場合には、プロセスはブロックしません。

5.4 プロセス制御(process control)

5.4.1 wait fork文

この文は、現在のプロセスが直接生成した全ての子プロセスが終了するのを待ちます。但し、子

プロセスが生成した孫プロセスは除外されます。例えば、

always @(negedge clk)

assert( packet.randomize() )

else $display("randomization failed.");

always @(posedge clk)

q <= d;

bit state[3];

always @(state)

$display("@%0t:",$time,state.xor);

bit state[3];

always @(state[0] or state[1] or state[2])

$display("@%0t:",$time,state.xor);

int q[$], index;

...

wait( q.size() > 0 ) index = q.pop_front;

...

Page 93: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

82

に於いて、親プロセスは、proc1、proc2、proc3、及び、proc4が終了するまでブロックします。

先ず、proc1又は proc2が終了するまで親プロセスはブロックします。どちらかの子プロセスが終

了すると親プロセスは proc3、及び、proc4 を生成します。然し、これらのプロセスの実行は開始

していません。親プロセスが wait fork を実行すると待ち状態に入り、proc3、及び、proc4 の実行

が開始します。proc1又は proc2の実行が終了していなければ、親プロセスは最大三つの子プロセ

スの実行終了を待つ事になります。

例 5-7

最初の fork 文で三つの子プロセスが生成されます。その中の一つ子プロセスが終了するとメイ

ン・プロセスは三つの子プロセスを生成します。この時点で、五つの子プロセスが実行、又は、

fork

proc1();

proc2();

join_any

fork

proc3();

proc4();

join_none

wait fork;

親プロセス

proc1

proc2

module test;

initial begin

fork

#10 print(1);

#20 print(2);

#30 print(3);

join_any

fork

#1 print(4);

#2 print(5);

#3 print(6);

join_none

wait fork;

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

Page 94: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

83

待ち状態にあります。メイン・プロセスは、wait fork 文で全ての子プロセスが終了するまで待ち

ます。最初の fork で作られた子プロセス print(3)が最も遅く実行を終了します。親プロセスはそ

の後に実行を再開します。

実行結果は以下の様になります。

5.4.2 disable fork文

この文は、現在のプロセスが生成した全てのプロセスの実行を中止します。使用方法は簡単で以

下の様なシンタックスを持ちます。

複数の子プロセスを生成して、何れかの子プロセスが終了した時点で他の全ての子プロセスを終

了させる場合に有効な機能です。

例 5-8

メイン・プロセスは三つの子プロセスを生成しています。然し、その中の一つの子プロセスが終

了すると、他の子プロセスを終了します。従って、print(2)、及び、print(3) の実行はキャ

ンセルされます。結果は以下の様になります。

@10 value=1

@11 value=4

@12 value=5

@13 value=6

@20 value=2

@30 value=3

@30 main completed.

disable fork ;

module test;

initial begin

fork

#10 print(1);

#20 print(2);

#30 print(3);

join_any

disable fork;

$display("@%2t main completed.",$time);

end

function void print(int value);

$display("@%2t value=%0d", $time, value);

endfunction

endmodule

@10 value=1

@10 main completed.

#-I Simulation completed at time 10 ticks

Page 95: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

84

5.5 ユーザ固有のプロセス制御(fine-grain process control)

SystemVerilog では、プロセスはビルトイン・クラスです。即ち、process という class が存在しま

す。そのクラス・オブジェクトをタスクの引数としてパスする事により、詳細なプロセス制御を

実現する事が出来ます。processクラスは以下に様に定義されています。

process のオブジェクトは子プロセスが生成された時に内部的に作られます。new オペレータで

processのオブジェクトを作る事は出来ません。

メソッド 意味

self() この呼び出しを行っているプロセスのオブジェクトを戻します。 process p = process::self();

の様にして使用します。new オペレータで process オブジェクトを作

る事が出来ないので、この self()関数はプロセスを取得する為の唯一

の方法です。

status() プロセスの状態を戻します。

FINISHED:プロセスは正常に終了。

RUNNING:プロセスは現在実行中。

WAITING:プロセスは待ち状態に入っている。

SUSPENDED:一時的に中断されて、実行再開を待っている。

KILLED:強制的に終了された。

kill() プロセスを終了します。全ての子プロセスも終了します。

await() 他のプロセスの終了を待ちます。自分自身の終了を待つ事は出来ませ

ん。従って、p.await();の様に使用しなければなりません。ここ

で p!=process::self()です。

suspend() 自分自身又は他のプロセスを中断します。既に中断しているプロセス

に対しては何の効果もありません。

resume() 中断しているプロセスの実行を再開します。

status を調べる為には、process::FINISHED の様にスコープ・オペレータを使用しなければな

りません。同様に、static なメソッドを参照するには、process::self()に様に使用しなけれ

ばなりません。

process はクラスですが、コンストラクタ new は定義されていません。言い換えると、process を

new する事は出来ません。従って、プロセスを取り出す為には、process::self()を使用する

事が必要です。

class process;

typedef enum { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED } state;

static function process self();

function state status();

function void kill();

task await();

function void suspend();

function void resume();

function void srandom( int seed );

function string get_randstate();

function void set_randstate( string state );

endclass

Page 96: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

85

例 5-9

三つの子プロセスを生成しています。

job[0]:時刻 0で開始し、時刻 0で終了します。

job[1]:時刻 0で開始し、時刻 1で終了します。

job[2]:時刻 0で開始し、時刻 2で終了します。

時刻 0 では、全ての子プロセスが実行を開始しています。最初の子プロセスは時刻 0 で終了して

いるので、メイン・プロセスは時刻 0で終了します。

最後の子プロセスは時刻 2 で終了するので、シミュレーションは時刻 2 で終了します。実行結果

は以下の様になります。

module test;

process job[] = new [3];

initial begin

foreach(job[i])

fork automatic int k = i;

begin

job[k] = process::self();

#k $display("@%0t: process-%0d ended",

$time,k);

end

join_none

foreach (job[i]) // wait for all processes to start

wait( job[i] != null );

$display("@%0t: all processes started.",$time);

job[0].await(); // wait for first process to finish

$display("@%0t: main completed",$time);

end

endmodule

@0: all processes started.

@0: process-0 ended

@0: main completed

@1: process-1 ended

@2: process-2 ended

#-I Simulation completed at time 2 ticks

Page 97: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

86

6 代入文(assignment statements)

代入文には、データ・フロー文(continuous assignments)とビヘイビア文(procedural assignments)

があります。構文としては、Verilog と変わらないので説明を省略します。この章では、

SystemVerilog特有の記述のみ紹介します。

6.1 パターン指定による代入(assignment patterns)

ストラクチャ及びアレイに対して、パターンを指定して値を設定する事が出来ます。パターン

を、’{...}の様に指定します。{}の中には、メンバーに対応するキー、又は、インデックスを

指定する事が出来ます。キー、又は、インデックスを指定する方法は位置指定と呼ばれます。位

置を指定しない方法は、順序指定(positional notation)と呼ばれます。位置を指定する場合には、

位置と値をコロン(:)で挟んで指定します。例えば、

int ival = ‘{ 7:1, 0:1, defaut:0 };

の様に指定すると、右からビット 7 の位置に 1、ビット 0 の位置に 1、それ以外の位置には 0 を

設定します。従って、ival==32’h0000_0081 となります。

例 6-1

パターン指定を左辺に置く事が出来ますが、キー、又は、インデックスを指定する事は出来ませ

ん。この例を実行すると以下の様な結果を得ます。

typedef struct { real x, y; } real_point;

module test;

parameter SIZE = 5;

int iarray[SIZE] = '{ default: 1 };

integer state = '{ 31:1, 16:1, 1:1, default:0 };

real_point pt = '{ x:1.23, y:4.56 };

int a, b, c, d, e;

initial begin

$write("iarray:");

foreach(iarray[i])

$write(" %0d",iarray[i]);

$display;

$display("state=%h",state);

$display("pt={%g,%g}",pt.x,pt.y);

iarray = '{ 0, 1, 2, 3, 4 };

'{a,b,c,d,e} = iarray;

$display("a=%0d b=%0d c=%0d d=%0d e=%0d",a,b,c,d,e);

end

endmodule

iarray: 1 1 1 1 1

state=80010002

pt={1.23,4.56}

a=0 b=1 c=2 d=3 e=4

Page 98: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

87

6.2 アレイ・パターン指定代入文

packed array に値を設定する場合はビットでなければなりません。従って、パターン指定をする

事が出来ません。その代りに {...} を使用します。例えば、

bit [7:0] b8 = { 1’b1, 1’b0, 1’b1 };

の様に定義します。こうすると、b8 == 8’b0000_0101 となります。勿論、この場合は

bit [7:0] b8 = 8’h05;

と書いた方が分かり易いです。{...} はビットを構成する結合(concatenate)オペレータです。

{co,sum} = a+b;

等の使い方に慣れていると思います。一方、’{...} はアレイの初期化オペレータです。

{1’b1,1’b0,1’b0}は 3 ビット 3’b101 を作ります。{1,0,1}は 96 ビットを構成しま

す。’{1,0,1}はアレイを左から順に 1、0、1で初期化します。

ビット型でも、unpacked arrayの初期化ではパターン指定を行います。例えば、

bit ub[1:0] = ‘{ 1, 1 };

により、ub[1]==1’b1、ub[0]==1’b1 となります。ここで、実際には、二つの代入文が実行

しています。

左辺は 1ビットですが、ビット長に関数するエラー、又は、警告は発行されないのが普通です。

アレイの初期化には定数以外の式を使用する事が出来ます。

例 6-2

これを実行すると以下の様な結果を得ます。

ub[1] = 32’b1;

ub[0] = 32’b1;

module test;

int a = 1,

b = 2,

c = 3;

int iarray[3];

initial begin

iarray = '{ a, b, c };

$display("iarray: %0d %0d %0d",iarray[0],iarray[1],iarray[2]);

end

endmodule

iarray: 1 2 3

Page 99: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

88

6.3 ストラクチャ・パターン指定代入文

ストラクチャに値を設定する場合には、パターン指定は極めて便利な手段となります。キー、及

び、インデックスで値の設定をする事が出来ます。更に、データ・タイプ毎に値の設定をする事

が出来ます。例を示すと分かり易いと思います。

例 6-3

bottle の設定では、メンバー名称を使用しています。従って、指定する順序は任意となります。

unknown の設定は少し異なります。メンバーのデータ・タイプ毎に設定をしています。特に、

文字列の初期化が大切です。初期化をしないとナルが初期値である為、実行時に異常終了します。

これを実行すると以下の様な結果を得ます。

typedef struct { int price; real weight; int stock;

string name, producer; } item_t;

module test;

item_t bottle, unknown;

initial begin

bottle = '{ name:"water",producer:"A-company",

price:120, weight:1.5,stock:10 };

print(bottle);

$display;

unknown = '{ int:-1, string:"???", default:1.23 };

print(unknown);

end

function void print(item_t item);

$display("name=%s",item.name);

$display("producer=%s",item.producer);

$display("price=%0d",item.price);

$display("weight=%g",item.weight);

$display("stock=%0d",item.stock);

endfunction

endmodule

name=water

producer=A-company

price=120

weight=1.5

stock=10

name=???

producer=???

price=-1

weight=1.23

stock=-1

Page 100: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

89

例 6-4

これを実行すると以下の結果を得ます。

6.4 unpacked array の初期化

パターンを指定してアレイに値を割り当てる方法が一般的です。これは、パターンでは繰り返し

指定( ‘{ n{element} } )が出来る為です。パターンを用いずに、結合オペレータ

( {...} )を使用してアレイに値を割り当てる事が出来ます。{...}は、左辺が変数であれば、

ビットの結合になり、左辺がアレイであればアレイの結合オペレータとなります。

多少混乱すると思いますが、次の二つの方法は同じ結果になります。

左辺がアレイなので、{ 1, 2, 3 }はアレイの結合です。即ち、三つの整数から構成されるリ

ストを作ります。それが、要素数 3 のアレイ a3 を初期化します。従って、a3[1]==1、

a3[2]==2、a3[3]==3 となります。但し、次の記述は許されません。

一方、‘{ 1, 2, 3 }は順序指定によるアレイの初期化です。どちらの形式を使用するかは好み

によるでしょうが、アレイに値を設定する場合にはパターン指定を使用する方が間違いは少ない

と思えます。次の様に書く事も可能です。

typedef struct { logic [7:0] a; bit b; bit signed [31:0] c;

string name;} abcs_t;

module test;

abcs_t abcs = '{ a:1, b:0, c:256, name:"ABCS" };

initial begin

$display("a=%b b=%b c=%b name=%s",

abcs.a,abcs.b,abcs.c,abcs.name);

abcs = '{ default:'1, name:"" };

$display("a=%b b=%b c=%b name=%s",

abcs.a,abcs.b,abcs.c,abcs.name);

end

endmodule

a=00000001 b=0 c=00000000000000000000000100000000 name=ABCS

a=11111111 b=1 c=11111111111111111111111111111111 name=

int a3[1:3];

a3 = { 1, 2, 3 };

a3 = ‘{ 1, 2, 3 };

a3 = { 1:1, 2:2, 3:3 };

a3 = ‘{ 1:1, 2:2, 3:3 };

Page 101: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

90

例 6-5

これを実行すると以下の様になります。

結合(concatenation)オペレータの意味は、次の例により明確になります。

例 6-6

以下の様な結果を得ます。

module test;

int a3[1:3], a9[1:9];

initial begin

a3 = { 1, 2, 3 };

print("a3",a3);

a3 = '{ 1, 2, 3 };

print("a3",a3);

a9 = { a3, 4, 5, a3, 6 };

print("a9",a9);

a9 = '{9{1}};

print("a9",a9);

end

function void print(string msg,int a[]);

$write("%s:",msg);

foreach(a[i])

$write(" %0d",a[i]);

$display;

endfunction

endmodule

a3: 1 2 3

a3: 1 2 3

a9: 1 2 3 4 5 1 2 3 6

a9: 1 1 1 1 1 1 1 1 1

module test;

string hello_world, hello, s2[2];

initial begin

hello = "Hello";

hello_world = { hello, ", world!" };

$display(hello_world);

s2 = { hello, ", world!" };

$display(s2[0],s2[1]);

end

endmodule

Hello, world!

Hello, world!

Page 102: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

91

この機会にダイナミック・アレイ、及び、associative arrayの初期化も記しておきます。

例 6-7

以下の様な結果を得ます。

module test;

int da[];

byte aa[string];

initial begin

da = '{ 1, 2, 3, 4, 5 };

$write("da:");

foreach(da[i])

$write(" %0d",da[i]);

$display;

aa = '{ "bread":1, "noodle":2, "milk":3 };

foreach(aa[i])

$write("aa[%s]=%0d ",i,aa[i]);

$display;

end

endmodule

da: 1 2 3 4 5

aa[bread]=1 aa[milk]=3 aa[noodle]=2

Page 103: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

92

7 演算子と式(operators and expressions)

7.1 演算子

SystemVerilogに追加された演算子を中心に機能を整理します。

7.1.1 代入演算子(assignment operators)

C/C++と同じ様に以下のオペレータを使用する事が出来ます。

=、 +=、 -=、 *=、 /=、 %=、 &=、 |=、 ^=、 <<=、 >>=、 <<<=、 及び、>>>=

7.1.2 インクリメント及びデクリメント演算子(++、--)

C/C++と同じ様に++、及び、--を使用する事が出来ます。これらのオペレータは複合命令を実行

しますが、命令はブロッキングとして実行します。

これらのオペレータを associative array に適用する場合には注意を必要とします。例えば、

a[key]++ の操作で、a[key] が存在しない場合、要素 a[key] が自動的にアレイに登録され

ます。初期値は、予め associative array で定められた値になります。登録後、a[key]++ が実行

します。

7.1.3 冪乗

SystemVerilog では、冪乗の記法を使用する事が出来ます。𝑥𝑦を求める為には、x**y と記述しま

す。例えば、

とすると、x==8となります。

7.1.4 比較演算子(equality operators)

演算子 意味

a === b 一致すれば 1、そうでなければ 0 を戻します。比較は x、及び、z を

含んで行われます。判定結果が xになる事はありません。

a !==b a===b の否定形です。一致しなければ 1、そうでなければ 0を戻しま

す。比較は x、及び、zを含んで行われます。

a == b 一致すれば 1、そうでなければ 0 を戻します。但し、a、又は、b の

何れかが x、又は、z の値を含む場合には、比較結果は x となりま

す。

a != b a == bの否定形です。一致しなければ 1、そうでなければ 0を戻しま

す。但し、a、又は、b の何れかが x、又は、z の値を含む場合には、

比較結果は xとなります。

=== の場合には、x 及び z を含んで完全に一致する事を要求します。従って、結果は 0、又は、

1 の何れかです。一方、== は four state 値を含む場合には比較できないので、結果は x となりま

す。

x = 2;

x = x**3;

Page 104: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

93

例 7-1

以下の様な結果を得ます。

7.1.5 ワイルドカード比較演算子(wildcard equality operators)

ワイルド・カードは、0、1、x、及び、zの何れにもマッチします。

演算子 意味

a ==? b a == b と同じです。但し、b に含まれる x、又は、z はワイルドカー

ドとして扱われます。

a !=? b a ==? b の否定形です。a != bと同じです。但し、bに含まれる x、又

は、zはワイルドカードとして扱われます。

module test;

logic [3:0] a, b;

initial begin

a = 4'b0000;

b = 4'b0000;

print(a,b);

b = 4'b0101;

print(a,b);

a = 4'b010z;

print(a,b);

b = 4'b010z;

print(a,b);

a = 4'b010x;

print(a,b);

b = 4'b010x;

print(a,b);

end

function void print(logic [3:0] x,y);

$display("4'b%b == 4'b%b %b",x,y,x==y);

$display("4'b%b === 4'b%b %b",x,y,x===y);

endfunction

endmodule

4'b0000 == 4'b0000 1

4'b0000 === 4'b0000 1

4'b0000 == 4'b0101 0

4'b0000 === 4'b0101 0

4'b010z == 4'b0101 x

4'b010z === 4'b0101 0

4'b010z == 4'b010z x

4'b010z === 4'b010z 1

4'b010x == 4'b010z x

4'b010x === 4'b010z 0

4'b010x == 4'b010x x

4'b010x === 4'b010x 1

Page 105: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

94

a ==? b に於いて ? が b側に付いているので、b に現れる ? (つまり、x、及び、z)を don’t care

として扱うという意味です。a に現れる x、及び、z は wildcard ではありません。例えば、

4’b0101 ==? 4’b010z は真です。然し、4’b010z ==? 4’b0101 は unknown (x)です。

例 7-2

実行結果は以下の様になります。

module test;

logic [3:0] a, b;

initial begin

a = 4'b0000;

b = 4'b0000;

print(a,b);

b = 4'b0101;

print(a,b);

a = 4'b010z;

print(a,b);

b = 4'b010z;

print(a,b);

a = 4'b010x;

print(a,b);

b = 4'b010x;

print(a,b);

a = 4'b110x;

print(a,b);

end

function void print(logic [3:0] x,y);

$display("4'b%b ==? 4'b%b %b",x,y,x==?y);

$display("4'b%b !=? 4'b%b %b",x,y,x!=?y);

endfunction

endmodule

4'b0000 ==? 4'b0000 1

4'b0000 !=? 4'b0000 0

4'b0000 ==? 4'b0101 0

4'b0000 !=? 4'b0101 1

4'b010z ==? 4'b0101 x

4'b010z !=? 4'b0101 x

4'b010z ==? 4'b010z 1

4'b010z !=? 4'b010z 0

4'b010x ==? 4'b010z 1

4'b010x !=? 4'b010z 0

4'b010x ==? 4'b010x 1

4'b010x !=? 4'b010x 0

4'b110x ==? 4'b010x 0

4'b110x !=? 4'b010x 1

Page 106: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

95

7.1.6 結合演算子(concatenation operators)

結合演算子は{ }の形式を持つ演算子で値を連結します。{}の中に記述する式はビット長が

定まっていなければなりません。例えば、{ a, 1’b0 }は正しい記述ですが、{ a, ‘1 }は正

しくありません。

このオペレータはアレイ結合としても使われる事があります。アレイの初期化には、

{1,2,a[1:2],4}の様な使い方が出来ます。或いは、文字列の結合にも使われます。

7.1.7 insideオペレータ(set membership operator)

SystemVerilog には式の値が集合の中に含まれるかを調べる機能があります。inside オペレータは、

式の値が集合に含まれれば 1 を戻します。含まれなければ 0 を戻します。但し、式の値が集合に

含まれず、しかも、途中の比較で xが得られた場合、結果は xとなります。

整数型の比較にはワイルドカード 比較演算子 ==? が使用されます。inside オペレータの左辺は

式で、右辺は{}の中に式、又は、区間をカンマで区切って書きます。右辺は open range list と呼

ばれます。

例 7-3

open range listにアレイ、又は、キューが指定された場合、その要素の全てが検索の対象となりま

す。例えば、{ 1, 2, q } は{ 1, 2, 3, 4, 5 }と同じ効果を持ちます。

3’b101 inside { 3’b1?1 } は 1です。これは、3’b101 ==? 3’b1?1 と同じなので、1と

なります。

然し、3’bz11 inside { 3’b1?1, 3’b011 }は x となります。左辺にある z は don’t care で

はないので、結果が xとなります。

module test;

int q[$] = '{ 3, 4, 5 };

int val;

logic [2:0] a;

logic r;

byte b;

initial begin

val = 3;

r = val inside { 1, 2, q };

$display("r=%b",r); // 1

a = 3'b101;

r = a inside { 3'1?1 };

$display("r=%b",r); // 1

a = 3'bz11;

r = a inside { 3'b1?1, 3'b011 };

$display("r=%b",r); // x

b = 10;

r = b inside {[0:3], [8:20]};

$display("r=%b",r); // 1

b = 200;

r = b inside {[0:3], [8:20]};

$display("r=%b",r); // 0

end

endmodule

Page 107: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

96

これを実行すると以下の様な結果を得ます。

7.1.8 ビット・ストリーム・オペレータ(<<、>>)

ビット位置を反転する、又は、バイト・スワップ等の操作を簡単に行なえるオペレータです。右

辺に使用されたときは pack 操作になり、左辺に使用された時は unpack の操作となります。使い

方は、

{ stream_operator [ slice_size ] stream_concatenation }

の様になります。stream_operator は <<、又は、>>です。>> は左から右へビットを取り出します。

<< はその逆方向です。slice_sizeは一度に取り出すビット数を示します。標準値は 1です。

例えば、{ << { 4’b1110 } } は、右から 1ビットずつ取り出すので、4’b0111 になります。

一方、 { << 2 { 4’b1110 } } は、右から 2 ビットずつ取り出すので、4’b1011 となりま

す。

オペレータ >> は左からビットを順に取り出す為に、>> では slice_size を指定する必要はありま

せん。

例 7-4

r=1

r=1

r=x

r=1

r=0

module test;

int i,

j = { "A", "B", "C", "D" };

initial begin

i = { >> {j}}; // "A" "B" "C" "D"

$display("%s%s%s%s expected ABCD",

i[31:24],i[23:16],i[15:8],i[7:0]);

i = { << byte {j}}; // "D" "C" "B" "A"

$display("%s%s%s%s expected DCBA",

i[31:24],i[23:16],i[15:8],i[7:0]);

i = { << 16 {j}}; // "C" "D" "A" "B"

$display("%s%s%s%s expected CDAB",

i[31:24],i[23:16],i[15:8],i[7:0]);

i = { << { 8'b0011_0101 }}; // 'b1010_1100

$display("i=%h expected ac",i);

i = { << 4 { 6'b11_0101 }}; // 'b0101_11

$display("i=%h expected 17",i);

i = { >> 4 { 6'b11_0101 }}; // 'b1101_01

$display("i=%h expected 35",i);

i = { << 2 { { << { 4'b1101 }} }}; // 'b1110

$display("i=%h expected 0e",i);

end

endmodule

Page 108: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

97

実行すると以下の様な結果を得ます。

例 7-5

以下の様な結果を得ます。

左辺にダイナミック・アレイを使用する事が出来ます。

例 7-6

ABCD expected ABCD

DCBA expected DCBA

CDAB expected CDAB

i=000000ac expected ac

i=00000017 expected 17

i=00000035 expected 35

i=0000000e expected 0e

module test;

int a, b, c;

logic [10:0] up [3:0];

logic [11:1] p1, p2, p3, p4;

initial begin

{>>{ a, b, c }} = 96'h000000a1_000000a2_000000a3;

$display("a=%h b=%h c=%h",a,b,c);

{<< int { a, b, c }} = 96'b1;

$display("a=%h b=%h c=%h",a,b,c);

up[3] = 11'h1ab;

up[2] = 11'h2cd;

up[1] = 11'h3ef;

up[0] = 11'h412;

{ >> {p1, p2, p3, p4}} = up;

$display("p1=%h p2=%h p3=%h p4=%h",p1,p2,p3,p4);

end

endmodule

a=000000a1 b=000000a2 c=000000a3

a=00000001 b=00000000 c=00000000

p1=1ab p2=2cd p3=3ef p4=412

module test;

byte q[$];

int i;

initial begin

i = 32'h12_34_56_78;

{ >>{q}} = i;

$display("q: %h %h %h %h",q[0],q[1],q[2],q[3]);

{ << byte {q}} = i;

$display("q: %h %h %h %h",q[0],q[1],q[2],q[3]);

end

endmodule

Page 109: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

98

キューq で使用された内容は消去されて、右辺の値が設定されます。結果は以下の様になります。

左辺にダイナミック・アレイを使用する場合、時として、アレイに対する条件を指定する必要が

あります。

例 7-7

ub はダイナミック・アレイなので、要素数に制限はありません。要素数の制限をしないと、b1

及び b2に値は設定されません。実行結果は以下の様になります。

7.2 オペランド(operands)

7.2.1 パートセレクト(part-select)

連続した複数ビットにアクセスする為には次の様にパートセレクトを使用します。

msb_expr 及び lsb_expr は何れもコンスタントの式でなければなりません。従って、この形

式のパートセレクトはコンパイル時に決定します。コンスタントではない式を使用してパートセ

レクトを構成する事も出来ます。その方法は、インデックス付きパートセレクト(indexed part-

select)と呼ばれます。インデックス付きパートセレクトは以下の様な使用法になります。

base_expr は整数型の式ですが、width は正の整数(定数)でなければなりません。up_vect

はビット位置 base_expr から上方向に width ビット数アクセスします。down_vect はビット

位置 base_exprから下方向に widthビットだけアクセスします。例を示します。

q: 12 34 56 78

q: 78 56 34 12

module test;

byte ub[], b1, b2;

int i;

initial begin

i = 32'h12_34_56_78;

{ << byte { ub with [0:1],b1,b2 } } = i;

$display("ub[0]=%h ub[1]=%h b1=%h b2=%h",

ub[0], ub[1], b1, b2 );

end

endmodule

ub[0]=78 ub[1]=56 b1=34 b2=12

vect[msb_expr:lsb_expr]

up_vect[base_expr +: width]

down_vect[base_expr -: width]

Page 110: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

99

先ず、パートセレクトの区間を定め、その後、実際のビット方向に合わせる事が必要になります。

例 7-8

これを実行すると、以下様な結果を得ます。

7.3 タグ付きメンバーの操作

設定した値と参照する値の正当性をチェックをする為の機能です。タグの付いたユニオンのメン

バーは以下のシンタックスに従い操作します。

tagged member_identifier [ expression ]

この式でメンバー(member_identifier)に値を設定すると、タグはメンバー名称となります。

他のメンバー名を参照するとタグに関するエラーとなります。

logic [31: 0] a_vect;

logic [0 :31] b_vect;

a_vect[ 0 +: 8] [0:7] a_vect[7:0]

a_vect[15 -: 8] [15:8] a_vect[15:8]

b_vect[ 0 +: 8] [0:7] b_vect[0:7]

b_vect[15 -: 8] [15:8] b_vect[8:15]

module test;

logic [31: 0] a_vect;

logic [0 :31] b_vect;

initial begin

a_vect[ 0 +: 8] = 8'h12; // a_vect[7:0]

a_vect[15 -: 8] = 8'h34; // a_vect[15:8]

$display("a_vect=%h",a_vect);

b_vect[ 0 +: 8] = 8'hab; // b_vect[0:7]

b_vect[15 -: 8] = 8'hcd; // b_vect[8:15]

$display("b_vect=%h",b_vect);

end

endmodule

a_vect=xxxx3412

b_vect=abcdxxxx

Page 111: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

100

例 7-9

data にタグ i が付けられています。それ以外のメンバー名で参照するとエラーとなります。例

えば、data.r は参照エラーとなります。然し、r のタグで値を設定し直すと data.r の参照は

可能となります。実行すると以下様な結果を得ます。

typedef union tagged {

int i;

real r;

} data_t;

module Top;

data_t data;

initial begin

$display("--- Ch07_Ex_N009 ---");

data = tagged i 10*2;

$display("a.i=%0d",data.i); // ok

$display("a.r=%g",data.r); // error on tag

data = tagged r 3.14;

$display("a.r=%g",data.r); // ok

end

endmodule

a.i=20

#-W Inconsistent use of a tagged member: write=i read=r

a.r=0.0

a.r=3.14

Page 112: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

101

8 実行文(procedural programming statemetnts)

SystemVerilogで新たに付け加えられた機能、又は、良く用いられる機能を中心に記述します。

8.1 if文

if 文の一般形式は以下の様になっています。unique_priority が拡張機能です。

unique_priority は、条件の一致、又は、不一致に関する状態を制限する為のキーワードで

す。

8.1.1 全ての条件を列挙(fully specified)

unique-if と priority-if に於いて else クローズが存在しない場合、条件を満たさない状態が発生す

ると実行時にエラーの対象となります。但し、unique0 では、エラーが出ません。unique0 の 0 は

OFFに相当し、メッセージを suppressする意味です。例えば、

もし a が 1、3、4、5、又は、6であると、条件を満たす if-else-ifが存在しない為、実行時にエラ

ー・メッセージが発行されます。priority-if も同様です。RTL 論理合成の分野では、full case と呼

ばれる機能です。

8.1.2 unique-if、unique0-if文

if-else-if の条件にはオーバーラップが無い事を宣言する命令です。詰まり、条件は排他的である

為、条件判定は順序に依存しない事を意味します。この為、条件判定を並列的に処理する事が出

来ます。当然、条件のオーバーラップが発生するとエラーになります。但し、unique0-if はエラ

ー・メッセージを出しません。例えば、

conditional_statement ::=

[ unique_priority ] if ( cond_predicate ) statement_or_null

{ else if ( cond_predicate ) statement_or_null }

[ else statement_or_null ]

unique_priority ::= unique | unique0 | priority

bit [2:0] a;

...

unique if( a == 0 )

$display(“0”);

else if( a == 2 )

$display(“2”);

else if( a == 7 )

$display(“7”);

bit a, b, c;

a = 1;

b = 1;

c = 0;

unique if( a )

a = 0;

else if( b )

b = 0;

else if( c )

c = 0;

Page 113: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

102

は、最初の if条件と二番目の else-if条件が同時に成立する為、エラー・メッセージを発行させま

す。論理合成の分野では、parallel caseと呼ばれる機能です。unique宣言をする事により論理の最

適化につながります。

8.1.3 priority-if文

if-else-if の条件は記述した順に評価されなければならない事を指定する命令です。この制御は、

論理の最適化処理に影響します。

例 8-1

実行すると以下の様な結果を得ます。

8.2 case文

シンタックスは以下の様になっています。

module test;

logic [3:0] a;

initial begin

a = 0;

check(a);

a = 2;

check(a);

a = 3;

check(a);

end

task check(input [3:0] a);

unique if ((a==0) || (a==1)) $display("0 or 1");

else if (a == 2) $display("2");

else if (a == 4) $display("4");

endtask

endmodule

0 or 1

2

#-E D:/Users/Artgraphics/TestData/SVDesigner/SV/Primer/Ch08/

Ch08_Ex_N001.sv (L16) Nomatch violation: test

case_statement ::=

[ unique_priority ] case_keyword ( case_expression )

case_item { case_item } endcase

| [ unique_priority ] case_keyword (case_expression )matches

case_pattern_item { case_pattern_item } endcase

| [ unique_priority ] case ( case_expression ) inside

case_inside_item { case_inside_item } endcase

unique_priority ::= unique | unique0 | priority

case_keyword ::= case | casez | casex

Page 114: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

103

8.2.1 unique-case、unique0-case文

if-else-if文と同様に unique、及び、unique0を使用する事が出来ます。意味も同様です。即ち、

case-selectionで書かれた条件は排他的である事。

全ての条件が列挙されている事。

違反した場合、unique-case文ではエラーが出ます。

論理合成の様なアプリケーションでは、この宣言は論理の最適化に役立ちます。

例 8-2

key==6 の場合、二つの条件を満たす為、unique-case に違反します。結果は以下の様になります。

8.2.2 priority-case文

if-else-if 文の場合と同様です。全ての条件が列挙されている事。そして、条件は上から順に検索

される事です。もし case の条件を満たす case_item が存在しない場合、priority-case への違反のメ

ッセージが出ます。例えば、次の例で、a=4、5、6、又は、7の場合、違反となります。

module test;

logic [0:3] key;

logic [0:1] data;

initial begin

key = 0;

#10 key = 1;

#10 key = 2;

#10 key = 4;

#10 key = 8;

#10 key = 6;

end

initial $monitor("@%2t: data=%0d",$time,data);

always @(key)

unique casez (key)

4'b???1: data = 0;

4'b??10: data = 1;

4'b?1?0: data = 2;

4'b1000: data = 3;

default: data = 0;

endcase

endmodule

@ 0: data=0

@20: data=1

@30: data=2

@40: data=3

#-E D:/Users/Artgraphics/TestData/SVDesigner/SV/Primer/Ch08/

Ch08_Ex_N002.sv (L19) Unique-case violation: test

@50: data=1

Page 115: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

104

8.2.3 insideオペレータと if文及び case文

insideオペレータは if文及び case文でも使用する事が出来ます。

例 8-3

例 8-4

priority casez(a)

3'b00?: $display("0 or 1");

3'b0??: $display("2 or 3");

endcase

module test;

int iarray[5] = { 1, 2, 3, 4, 5 },

a;

initial begin

a = 11;

if( a inside { iarray, [8:20] } )

test1();

else

test2();

end

...

endmodule

module test;

parameter WIDTH=8;

logic [WIDTH-1:0] a;

initial begin

a = 1;

check(a);

a = 3;

check(a);

a = 11;

check(a);

a = 21;

check(a);

a = 65;

check(a);

end

task check(input logic [WIDTH-1:0] a);

case (a) inside

1: $display("a=1");

[2:4]:$display("a=%0d in [2:4]",a);

[10:12], [20:30]:

$display("a=%0d in [10:12] or [20:30]",a);

default:$display("unmatch a=%0d",a);

endcase

endtask

endmodule

Page 116: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

105

insideオペレータなので、区間を使用する事が出来ます。実行結果は以下の様になります。

8.3 ループ文(loop statements)

SystemVerilog で拡張された文について説明します。尚、ループ内では、一般に、continue、及び、

break文を使用する事が出来ます。

8.3.1 for文

SystemVerilog では for ループを制御する変数を定義する事が出来ます。定義した変数は、

automaticの属性を持ちループ内でのみ使用する事が出来ます。

例 8-5

C/C++と同じ様なシンタックスで for ループを記述する事が出来ます。但し、ループ内部は

C/C++と異なり begin-endで囲まなければなりません。

この例では、i++、及び、break 文を使用しています。ループの外では変数 i を参照する事は出

来ません。実行結果は以下の様になります。

この例の様な記述には、後述する foreach文の方が便利になります。

a=1

a=3 in [2:4]

a=11 in [10:12] or [20:30]

a=21 in [10:12] or [20:30]

unmatch a=65

module test;

int iarray[10];

initial begin

for( int i = 0; i < 100; i++ ) begin

if( i < iarray.size() )

iarray[i] = i;

else

break;

end

$write("iarray:");

for( int i = 0; i < iarray.size(); i++ )

$write(" %0d",iarray[i]);

$display;

end

endmodule

iarray: 0 1 2 3 4 5 6 7 8 9

Page 117: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

106

8.3.2 repeat文

指定した回数だけループを実行する命令です。回数を正しく評価できない場合、ループは実行し

ません。シンタックスは以下の様になります。

例えば、次の様に使用します。

8.3.3 foreach文

foreachループは、全てのアレイに適用する事が出来る便利なループ制御文です。アレイ名称とル

ープ制御変数名を指定するだけでループ処理を記述する事が出来ます。ループ制御変数は、コン

パイラーが自動的に確保します。制御変数は、automatic で read only です。シンタックスは以下

の通りです。

例 8-6

ループ制御変数 i は int型に確保されます。最初の foreachではアレイの初期化処理をしています。

次の foreach ではアレイ要素の値を順にプリントしています。二つの foreach で同じループ制御変

数名 iを使用していますが、これらは別々の変数です。

実行結果は以下の様になります。

repeat ( expression ) statement_or_null

module test;

int q[$];

initial begin

repeat( 8 )

q.push_back($urandom_range(0,255));

...

end

endmodule

foreach ( ps_or_hierarchical_array_identifier [ loop_variables ] )

statement

loop_variables ::= [ index_variable_identifier ]

{ , [ index_variable_identifier ] }

module test;

int iarray[10];

initial begin

foreach(iarray[i])

iarray[i] = i;

foreach(iarray[i])

$display("iarray[%0d] = %0d",i,iarray[i]);

end

endmodule

Page 118: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

107

foreach 文を各種のアレイに使用する事が出来ます。次の例は foreach をキューに適用しています。

キューに適用した場合、制御変数は int型に確保されます。

例 8-7

結果は以下の様になります。

次の例は associative アレイに適用します。この例の associative アレイのキーは string なので、自

動的に確保されるループ制御変数は string 型になります。キーの型に合わせて処理を記述する必

要があります。例えば、キー key をプリントする為には、

$display(“area_code[%s] = %0d”,key,area_code[key]);

の様に記述します。

iarray[0] = 0

iarray[1] = 1

iarray[2] = 2

iarray[3] = 3

iarray[4] = 4

iarray[5] = 5

iarray[6] = 6

iarray[7] = 7

iarray[8] = 8

iarray[9] = 9

module test;

string qs[$] = '{ "hello", "world", "from", "Tokyo" };

initial begin

foreach(qs[i])

$display("qs[%0d] = %s",i,qs[i]);

end

endmodule

qs[0] = hello

qs[1] = world

qs[2] = from

qs[3] = Tokyo

Page 119: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

108

例 8-8

文字型のキーを持つ associative アレイの例です。foreach に使用する制御変数はキーの型に合わせ

て確保されます。foreach文の内部でキーの値を直接参照する事が出来ます。

キーは string 型なので、キーは自然な辞書引き順序でソートされます。foreach 文でループすると

その順序でキーが戻されます。

結果は以下の様になります。

8.3.4 while文

while 文は条件が真(true)である限り、繰り返して文を実行します。以下のシンタックスを持ち

ます。

この命令が実行するする時に条件(expression)が真でなければ、while ループは終了し次の命令

に移ります。

8.3.5 do-while文

SystemVeilog では do-while 文を使用する事ができます。シンタックスは以下の様になっています。

statement_or_null を実行し、expression が真(true)である限り doブロックを繰り返し

ます。

module test;

int area_code[string] = '{

"San Francisco":415,

"San Jose":408,

"Berkeley":510,

"New York":212,

"Los Angeles":213 };

initial begin

$display("%-20s Area Code","City");

$display("-------------------------------");

foreach(area_code[i])

$display("%-20s %3d",i,area_code[i]);

end

endmodule

City Area Code

-------------------------------

Berkeley 510

Los Angeles 213

New York 212

San Francisco 415

San Jose 408

while ( expression ) statement_or_null

do statement_or_null while ( expression ) ;

Page 120: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

109

例 8-9

enum に定義されているラベルを順に取り出してプリントしています。少なくとも一つのラベル

が存在する事を仮定した処理になっています。enum のラベルを初めから順に取り出すと、最後

のラベルの次は最初のラベルに戻ります。その特性を利用してループ処理を記述しています。

実行すると以下の様な結果を得ます。

8.4 forever文

無限に実行を繰り返します。シンタックスは以下の通りです。

タイミング制御文が使用されないと、単純なループを繰り返します。結果として、シミュレーシ

ョンは進展しません。必ず、タイミング制御文が使用されなければなりません。例えば、次の様

に使用します。

8.5 return文

SystemVerilogでは C/C++と同様に return文を使用する事が出来ます。

typedef enum { RED, YELLOW, GREEN, BLUE, WHITE } color_e;

module test;

color_e color, first_color;

initial begin

first_color = color.first();

color = first_color;

do begin

$display("%-8s = %0d",color.name,color);

color = color.next();

end while( color != first_color );

end

endmodule

RED = 0

YELLOW = 1

GREEN = 2

BLUE = 3

WHITE = 4

forever statement_or_null

initial

forever #10 clk = ~clk;

Page 121: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

110

例 8-10

実行結果は以下の様になります。

8.6 break文

この文はループから抜け出す為に使用します。for ループ以外にも使用する事が出来ます。次の

例では break文を foreachループで使用しています。

例 8-11

実行結果は以下の様になります。

module test;

byte barray[5] = { 1, 2, 3, 4, 5 };

initial begin

$display("barray[0..4]=%0d",sum(barray,-1));

$display("barray[0..2]=%0d",sum(barray,2));

end

function int sum(byte ar[],int last_index);

sum = 0;

foreach(ar[i]) begin

sum += ar[i];

if( i == last_index )

return sum;

end

endfunction

endmodule

barray[0..4]=15

barray[0..2]=6

module test;

int q[$] = '{ 10, 20, 30, -1, 40, 50 },

val;

initial begin

foreach(q[i]) begin

val = q[i];

if( q[i] == -1 )

break;

$display("got: %0d",val);

end

end

endmodule

got: 10

got: 20

got: 30

Page 122: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

111

8.7 continue文

この文はループの終わりにジャンプして次のループを継続する命令です。即ち、この文以降の命

令をスキップする機能を持ちます。for ループ以外にも使用する事が出来ます。次の例では

continue文を foreachループで使用しています。

例 8-12

実行結果は以下の様になります。

module test;

int q[$] = '{ 10, 20, 30, -1, 40, 50 },

val;

initial begin

foreach(q[i]) begin

val = q[i];

if( q[i] == -1 )

continue;

$display("got: %0d",val);

end

end

endmodule

got: 10

got: 20

got: 30

got: 40

got: 50

Page 123: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

112

9 タスクとファンクション(tasks and functions)

SystemVerilogには以下の拡張があります。

タスク、及び、ファンクションの内部の記述を begin-endで囲む必要はありません。

値を戻さないファンクションを定義する事が出来ます。

この拡張により、ファンクションをタスクの様に扱う事が可能になりました。タイミング制御を

持たずに時間を消費しないタスクの場合、void function として定義する方が柔軟性が高くなりま

す。

9.1 タスク

9.2 ポート・リスト

ポートには以下の方向を指定する事が出来ます。

input

inout

output

ref

ポートの方向を指定しない場合、次のルールが適用されます。

最初のポートに方向が指定されていない場合、inputが仮定されます。

二番目以降のポートに方向が指定されていない場合、直前のポートの方向が採用されます。

例えば、

に於いて、ポート a、及び、b の方向は input、ポート u、及び、vの方向は outputです。

ポートにはデータ・タイプを指定する事が出来ます。データ・タイプを指定しない場合、次のル

ールが適用されます。

最初のポートにデータ・タイプが指定されていない場合、データ・タイプは logic になりま

す。

ポートの方向が指定されていてデータ・タイプの指定が無い場合、データ・タイプは logic

になります。

それ以外の場合は、直前のポートのデータ・タイプを仮定します。

例えば、

に於いて、ポート a、及び、b のデータ・タイプは logicです。

9.3 タスク内の記述

タスク内の記述を begin-endで囲む必要はありません。

task mytask(a, b,output logic [15:0] u, v);

...

endtask

task mycheck(input a,[1:0]b,output int q);

...

endtask

Page 124: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

113

例 9-1

Verilog と異なり、タスクの記述は簡略化されています。begin-end を用いずに内部を記述してい

ます。

9.4 ファンクション

SystemVerilogでは値を戻さないファンクションを使用する事が出来ますが、ファンクションの使

用に関する制限は Verilogと変わりません。

9.4.1 ファンクションの制限

以下の制限が適用されます。

ファンクションはシミュレーション時間を消費せずに戻らなければなりません。具体的には、

遅延(#、##)、fork-join、fork-join_any、wait、wait_order、expect 等を使用する事は出来ま

せん。

ファンクションからタスクを呼び出す事は出来ません。

最初の制限によると、一見、ファンクションではタイミング制御をする事が出来ない様に思えま

すが、それは誤解です。制限には fork-join_none が含まれていません。fork-join_none は時間を消

費しないのでファンクション内で自由に使用する事が出来ます。

9.4.2 ポート・リスト

ポートには以下の方向を指定する事が出来ます。

input

inout

output

ref

ポートの方向を指定しない場合、次のルールが適用されます。

最初のポートに方向が指定されていない場合、inputが仮定されます。

二番目以降のポートに方向が指定されていない場合、直前のポートの方向が採用されます。

module test;

bit clk;

initial begin

trigger(3);

$display("%0t: completed",$time);

$finish;

end

initial forever #10 clk = ~clk;

task trigger(int count);

repeat( count) @(posedge clk);

endtaskendtask

endmodule

Page 125: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

114

例えば、

に於いて、ポート a、及び、b の方向は input、ポート u、及び、vの方向は outputです。

ポートにはデータ・タイプを指定する事が出来ます。データ・タイプを指定しない場合、次のル

ールが適用されます。

最初のポートにデータ・タイプが指定されていない場合、データ・タイプは logic になりま

す。

ポートの方向が指定されていてデータ・タイプの指定が無い場合、データ・タイプは logic

になります。

それ以外の場合は、直前のポートのデータ・タイプを仮定します。

例えば、

に於いて、ポート a、及び、b のデータ・タイプは logicです。

9.4.3 ファンクション内でタイミング制御を行う方法

fork-join_noneを使用すると function内でもタイミング制御をする事が出来ます。fork-join_noneは

使用しているプロセスをブロックしないので、function 内で自由に使用する事が出来ます。但し、

functionが値を戻す場合には注意が必要です。

例 9-2

function logic [15:0] myf(int a,int b,output logic [15:0] u, v);

...

endtask

function void mycheck(input a,[1:0]b,output int q);

...

endtask

module test;

bit done;

initial begin

check;

$display("@%0t: returned from check.",$time);

wait( done );

$display("@%0t: main completed.",$time);

end

function void check;

fork

#10 $display("@%0t: checking...",$time);

#50 $display("@%0t: checking...",$time);

#60 begin

$display("@%0t: checking...",$time);

done = 1;

end

join_none

endfunction

endmodule

Page 126: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

115

この例ではファンクションをタスクの様に使用してタイミング制御を行っています。間接的です

がファンクション内でディレー制御をする事が出来るのを確認出来ます。ディレー制御に限らず

イベント制御(@ev、@(posedge sig)等)、及び、レベル・センシティブ制御(wait

(expr) 等)も可能です。

fork-join_none は便利に使用する事が出来る構文です。この例を実行すると以下の様な結果を得ま

す。ファンクション checkは呼ばれた時刻と同じ時刻に戻っています。

ファンクション内からイベント待ちを解除する(->ev)事も出来ます。解除命令はプロセスを

ブロックしません。

例 9-3

これを実行すると以下の様な結果を得ます。

9.5 引数に標準値を指定する方法

タスク、及び、ファンクションに引数がある時、多くの場合、引数には標準的な値が考慮されて

います。そして、標準値以外を指定する場合が少なければ、タスク、及び、ファンクションを呼

ぶ際に値を設定せずに済ませる様に設計するのが常です。SystemVerilogでは、それが可能です。

シンタックスは以下の様になっています。

@0: returned from check.

@10: checking...

@50: checking...

@60: checking...

@60: main completed.

#-I Simulation completed at time 60 ticks

module test;

event ev;

initial begin

@ev $display("%0t: main completed.",$time);

end

initial #60 trigger;

function void trigger;

->ev;

endfunction

endmodule

60: main completed.

#-I Simulation completed at time 60 ticks

subroutine( [ direction ] [ type ] argument = default_expression);

Page 127: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

116

引数に値を設定すれば標準値になります。サブルーティンを使用する側は、標準値を使用しない

場合だけ値を設定すれば良い事になります。例えば、

に於いて、check の呼び出しで left に対して値が指定されていなければ、left には 0が仮定

されます。同様に、right に対して値が指定されなければ-1 が仮定されます。必須なパラメー

タはアレイ名称だけです。

アレイ全体をチェックする場合には、check(array)の様に呼びます。アレイの一部だけをチェ

ックする場合には、check(array,3,10)の様に呼び出します。

サブルーティンを呼び出す際、名称でバインドする事が出来ます。例えば、

の様に呼び出す事が出来ます。

例 9-4

これを実行すると以下の様になります。

function void check(int a[],int left=0,int right=-1);

...

endfunction

check(.a(array));

check(.a(array),.left(3),.right(10));

check(.left(3),.a(array));

module test;

int iarray[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

initial begin

print(iarray); // 0..9

print(iarray,8); // 8..9

print(.a(iarray),.start(2),.last(5)); // 2..5

end

task print(int a[],int start=0,int last=-1);

int right = last==-1?a.size()-1:last;

$write("a[%0d..%0d]:",start,right);

for( int i = start; i <= right; i++ ) begin

$write(" %0d",a[i]);

end

$display;

endtask

endmodule

a[0..9]: 0 1 2 3 4 5 6 7 8 9

a[8..9]: 8 9

a[2..5]: 2 3 4 5

Page 128: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

117

9.6 値を戻すファンクションの使用

値を戻すファンクションを式の中で使う事が一般的です。単独に使用するとコンパイラーが警告

メッセージを発行します。例えば、

の様に記述するとコンパイラーは警告メッセージを発行します。この文ではファンクションが戻

す値を参照していない為、コンパイラーが警告を発行します。実際問題として、この場合の警告

は正しい措置です。乱数を発生する場合、何時も成功するとは限らないので、上記の記述は安全

ではありません。寧ろ、次の様に書き換えた方が望ましいと思えます。

書き換えをしないで警告を回避するには、

の様にしてファンクション・コールを voidファンクションを呼び出すかの様に見せかけます。

9.7 再帰呼び出し

タスク、及び、ファンクション内で再帰呼び出しを行う場合、automatic の宣言が必要です。

automatic宣言により、変数がスタックに確保されます。

例 9-5

ファンクション factorial を automaticとして宣言しています。この為、引数 n、及び、戻り値

factorial はスタック上に確保されます。従って、再帰呼び出しが正しく行われます。これを

実行すると以下の様になります。

std::randomize(a,b,c);

assert( std::randomize(a,b,c) )

else $display("%s(L%0d) randomize failed."

,`__FILE__,`__LINE__);

void’(std::randomize(a,b,c));

module test;

initial begin

for( int i = 0; i <= 7; i++ ) begin

$display("%0d! = %0d",i,factorial(i));

end

end

function automatic int factorial(int n);

if( n < 2 )

return 1;

else

return n*factorial(n-1);

endfunction

endmodule

Page 129: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

118

9.8 クラスのメソッドと再帰呼び出し

クラス内に定義されたメソッドは、デフォルトとして automatic です。この特性を利用すると安

全に再帰呼び出しを行う事が出来ます。前記の例をクラスのメソッドとして書き換えてみます。

但し、明示的な automatic修飾子の使用を避けてあります。

例 9-6

クラス sample_t 内にファンクション factorial()が定義されています。ファンクションには明示的

に automatic/static属性がついていない為、標準として automatic属性が付加されます。従って、再

帰呼び出しは成功します。

9.9 メソッド内での変数の初期化

static なメソッド内での変数の初期化の時期には注意が必要です。この注意は、static な begin/end

ブロックにも適用されます。

0! = 1

1! = 1

2! = 2

3! = 6

4! = 24

5! = 120

6! = 720

7! = 5040

class sample_t;

...

function int factorial(int n);

if( n < 2 )

return 1;

else

return n*factorial(n-1);

endfunction

endclass

module test;

sample_t sample;

initial begin

sample = new;

for( int i = 0; i <= 7; i++ ) begin

$display("%0d! = %0d",i,sample.factorial(i));

end

end

endmodule

Page 130: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

119

例 9-7

これを実行すると以下の様な結果を得ます。

結果を観察すると、T1.shift(1)、及び、T1.shift(2) が動作していない事が分かります。T1.shift() は

staticである為、

module top;

test1 T1();

test2 T2();

initial begin

T1.shift(1);

T1.shift(2);

T2.shift(1);

T2.shift(2);

end

endmodule

program test1;

function void shift(logic [7:0] data);

begin

logic [7:0] sdata = 1 << data;

$display("shifted=%h",sdata);

end

endfunction

endprogram

program automatic test2;

function void shift(logic [7:0] data);

begin

logic [7:0] sdata = 1 << data;

$display("shifted=%h",sdata);

end

endfunction

endprogram

shifted=01

shifted=01

shifted=02

shifted=04

logic [7:0] sdata = 1 << data;

Page 131: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

120

がシミュレーション開始直前に一度だけ実行します。この時点では、data == ‘x である為、sdata

== 1となります。しかも、シミュレーション実行中に、この初期化処理は実行しません。従って、

上記の様な結果になります。

一方、T2.shift()は automaticである為、

は beginブロックが実行する度に初期化処理が行われ、正しい結果を得ます。

次の例は、automaticメソッド内での static変数の初期化に関する注意を喚起します。

例 9-8

メソッド check()はクラス内で定義されているので automaticです。変数 flagは staticとして定義さ

れています。flag の初期化は、シミュレーション開始直前に一度だけ行われます。一方、変数 r

は automaticなので、初期化はメソッドが実行する度に行われます。

これを実行すると以下の様な結果を得ます。

logic [7:0] sdata = 1 << data;

class X;

task check();

static byte flag = 0;

real r = 123.4;

$display("flag=%0d r=%0g",flag,r);

flag = 12;

r = 101;

endtask

endclass

module test;

X x;

initial begin

x = new;

x.check();

x.check();

end

endmodule

flag=0 r=123.4

flag=12 r=123.4

Page 132: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

121

10 クロッキング・ブロック(clocking blocks)

クロッキング・ブロックは、クロックに同期して変化する信号のタイミング(skew)を設定する

構文です。タイミングを設定すると、クロックのイベントに同期して、指定したタイミングで信

号値が変化します。クロッキング・ブロックにより、個々の信号の変化を管理する必要は無くな

ります。

クロッキング・ブロックはキーワード clocking と endclocking を使用して記述します。clocking の

前に、default、又は、global を付ける事も出来ます。例えば、シンタックスは以下の様になりま

す。

clocking_event にはクロッキングが動作するイベントを指定します。例えば、@(posedge

clk)の様に指定をします。イベントには、posedge、negedge、及び、edge を使用する事が出来ま

す。edgeは DDR (Double Data Rate)の意味です。

default を付加すると標準クロッキング(default clocking)となります。クロッキング・イベント

が必要な SystemVerilog 機能に於いてクロッキングの指定を省略すると、標準クロッキングが採

用されます。例えば、アサーションの sequence や property で default clocking を使用します。

default clocking を定義すると、sequence や property の記述からクロッキング・イベントを省略す

る事が出来る為、より抽象度の高い記述をする事が出来ます。

構文自体がやや複雑なのでシンタックスには触れずに、例からクロッキングの使い方を学ぶ事に

します。シンタックスの詳細は原書をお読み下さい。

10.1 最も簡単なクロッキング・ブロック

最も簡単なクロッキング・ブロックは以下の様になります。

実は、これだけでも意味があります。@(posedge clk)の代わりに、簡単に @(cb) と書く事

が出来ます。更に、クロッキング・ブロック内の posedge を negedge に変えるだけで @(cb)

は @(negedge clk)に変わります。

10.2 クロッキング・スキュー(clocking skew)

クロッキング・ブロックでは信号に方向(input、output、inout)を定義する事が出来ます。ここ

で、inout は input 及び output を意味します。スキューは、クロックのイベントからどれだけの時

間間隔で信号値のサンプリングが行われるか、又は、値が設定されるかを意味します。

input 信号に対して、時間間隔は負の値として理解されます。即ち、クロッキング・イベントが

起こる前に input 信号のサンプリングが行われます。output 信号のスキューはクロッキング・イ

ベントの後の時間間隔を意味します。

clocking_declaration ::=

[ default ] clocking [ clocking_identifier ] clocking_event ;

{ clocking_item }

endclocking [ : clocking_identifier ]

| global clocking [ clocking_identifier ] clocking_event ;

endclocking [ : clocking_identifier ]

clocking cb @(posedge clk); endclocking

Page 133: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

122

例えば、次の様に指定する事が出来ます。

default を使用して、全ての信号に対して同時にスキューをしています。この指定によると、

@(posedge clk) のイベントが起こると、次の @(negede clk)で output信号に値が設定され

ます。逆に言えば、@(posedge clk) のイベントが起こった時、output 信号の値は直前の

@(negede clk)で設定された値を示しています。

クロッキング信号を個別に指定する為には、以下の様に記述します。

ローカル・ポートだけでなく外部から信号値を取り入れる事もできます。

スキューを指定する場合、定数でなければなりません。

clocking cb1 @(posedge clk);

default input #1step output negedge;

endclocking

clocking cb @(clk);

input #1ps address;

input #5 output #6 data;

endclocking

clocking bus @(posedge clock1);

default input #10ns output #2ns;

input data, ready,

enable = top.mem1.enable;

output negedge ack;

input #1step addr;

endclocking

クロック・イベント

input skew

output skew

Page 134: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

123

例 10-1

クロッキング・ブロックの定義により、@(posedge clk)のイベント発生後、2 ticks 後に信号 b

の値が更新されます。実行結果は以下の様になります。

10.3 サイクル・ディレー(cycle delay)

サイクル・ディレーはクロッキング・イベントが指定回数起こるのを待つ制御です。例えば、

##3 a = b;

は、3 クロック・サイクル後に a = b を実行します。ここで、サイクル・ディレーは標準クロ

ッキング(default clocking)で定めます。

アサーションでもサイクル・ディレーを使用します。この場合は、クロッキング・イベント

(leading clock)が property、又は、sequenceで指定されます。例えば、

に於いて、クロック・サイクル ##2 は property p_ab の @(posedge clk)により決定されます。

module test;

bit clk, a, b;

clocking cb @(posedge clk);

input #1 a;

output #2 b;

endclocking

initial #100 $finish;

initial $monitor("@%0t: b=%b",$time,b);

initial forever #10 clk = ~clk;

always @(cb)

cb.b <= ~cb.a;

initial begin

#20 a = 1;

#40 a = 0;

end

endmodule

@12: b=1

@32: b=0

@72: b=1

sequence s_ab;

a ##2 b;

endsequence

property p_ab;

@(posedge clk) z |-> s_ab;

endproperty

Page 135: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

124

例 10-2

この例では、default クロッキングを使用しています。また、サイクル・ディレーも使用していま

す。default クロッキングが定義されているので、アサーションではクロック・イベントを明記し

ていません。

実行結果は以下の様になります。

module test;

bit clk, req, gnt, check;

default clocking cb @(posedge clk);

property check_req_gnt;

$rose(check) |-> req ##[1:3] gnt;

endproperty

endclocking

assert property (check_req_gnt)

else

$display("@%0t: FAIL",$time);

cover property (check_req_gnt)

$display("@%0t: PASS",$time);

initial begin #20 req = 1; #20 req = 0; #20 req = 1; end

initial begin #40 gnt = 1; #20 gnt = 0; #20 gnt = 1; end

initial begin #20 check = 1; #20 check = 0; #20 check = 1;

#20 check = 0; end

initial repeat (10) #10 clk = ~clk;

endmodule

@50: PASS

@90: PASS

Page 136: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

125

11 プロセス間の同期と交信

11.1 セマフォ(semaphores)

セマフォは、複数のプロセスが共有する資源にアクセスする為の排他制御機能です。セマフォは

SystemVerilogのクラスとして実現されています。従って、クラス・ハンドルを定義して、ハンド

ルに newオペレータを使用してオブジェクトを割り当てる手順を取ります。例えば、

の様にして使用します。概念的には、セマフォは一定数のキーを保有するバケットです。利用可

能なキーが存在する限り共有資源にアクセスする事が出来ます。キーが存在しない場合、キーが

利用可能になるまでプロセスは待たなければなりません。

セマフォはロック機能を有するだけのシンプル性があります。共有するデータに関しての情報は

一切必要ありません。セマフォから継承(extends)して新たなクラスを定義する事も可能です。

継承により、メソッド get を独自に定義する事が出来ます。

セマフォはクラスである為、以下の様なメソッドを備えています。

method 意味

function new(int keyCount = 0 ); 指定した数のキーを持つセマフォを作成しま

す。バケットは指定されたキーの数で初期化さ

れます。

put()で戻すキーの数が get()したキーの数より

も多い場合、キーの数が keyCount を超える現

象が起こります。

function void put(int keyCount = 1); 指定した数のキーをセマフォに戻します。戻す

キー数の標準値は 1です。

もし、利用可能なキーを待っているプロセスに

十分な数のキーを戻す場合には、その待ち状態

のプロセスの実行が再開します。

task get(int keyCount = 1); 指定した数のキーを取得します。指定数のキー

が存在すれば呼び出しているプロセスの実行は

継続します。

もし、指定数のキーが存在しない場合には、呼

び出しているプロセスの実行がブロックされ、

キーの取得が可能になるまで待ち状態になりま

す。

function int try_get(int keyCount = 1); 指定した数のキーを取得します。但し、呼び出

しているプロセスをブロックしません。

もし、指定数のキーが存在すれば正の整数を戻

します。

もし、指定数のキーが存在しない場合には 0 を

戻します。

semaphore mutex

mutex = new;

Page 137: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

126

例 11-1

try_get がブロックせずに戻っている事を確認する事が出来ます。実行結果は以下の様になり

ます。

11.2 メール・ボックス(mailboxes)

メール・ボックスは producer と consumer をもつ FIFO リストです。FIFO リストは限られたサイ

ズ、又は、無限のサイズを持つ様に定義する事が出来ます。FIFO リストがフルの時は、producer

はデータを書き込む事は出来ません。FIFOリストが空の場合、 consumer は待たなければなりま

せん。

セマフォと同様に、メール・ボックスも SystemVerilog のクラスとして実現されています。ハン

ドルに newオペレータを使用してオブジェクトを割り当てる手順を取ります。例えば、

の様にして使用します。メール・ボックスはクラスであるので、以下の様なメソッドを備えてい

ます。

module test;

semaphore lock;

int rs;

initial begin

lock = new (3);

lock.get(3);

$display("@%0t: got %0d keys",$time,3);

lock.get(2);

$display("@%0t: got %0d keys",$time,2);

rs = lock.try_get(10);

if( rs )

$display("@%0t: try_get got %0d keys",$time,310);

else

$display("@%0t: try_get failed",$time);

end

initial #10 lock.put(2);

endmodule

@0: got 3 keys

@10: got 2 keys

@10: try_get failed

#-I Simulation completed at time 10 ticks

mailbox fifo

fifo = new(3);

producer consumer

mailbox (FIFO)

Page 138: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

127

method 意味

function new(int bound = 0); メール・ボックスを割り当てます。bound が 0

であるとメール・ボックスは無限のサイズを持

ち、producer は決してブロックしません。

bound が 0 でない場合、メール・ボックスは有

限のサイズとなります。

function int num(); メール・ボックスに存在するメッセージ数を戻

します。戻す値は、次の get、又は、put まで

有効な一時的な値です。

task put( singular message); メッセージをメール・ボックス(FIFO)に書

き込みます。メール・ボックスがフルの場合、

書き込むプロセスは、メール・ボックスに空き

が出来るまで待ち状態に入ります。

function int try_put( singular message); メッセージをメール・ボックス(FIFO)に書

き込みます。但し、ブロックしません。

メール・ボックスに空きがある場合、メッセー

ジを書き込み、正の整数を戻します。

メール・ボックスがフルの場合、0 を戻しま

す。

task get( ref singular message ); メール・ボックスから 1 メッセージを取り出し

ます。

メール・ボックスが空の場合、取り出すプロセ

スは、メールが届くまで待ち状態になります。

function int try_get( ref singular message ); メール・ボックスから 1 メッセージを取り出し

ます。但し、ブロックしません。

メール・ボックスが空の場合、0を戻します。

メッセージを正しく取得できれば正の整数を戻

します。正しく取り出せない場合は、負の整数

を戻します。

task peek( ref singular message ); メール・ボックスから 1 メッセージをコピーし

ます。

メール・ボックスが空の場合、コピーするプロ

セスは、メールが届くまで待ち状態になりま

す。

function int try_peek( ref singular

message );

メール・ボックスから 1 メッセージをコピーし

ます。但し、ブロックしません。

メール・ボックスが空の場合、0を戻します。

メッセージを正しくコピーできれば正の整数を

戻します。正しくコピー出来ない場合は、負の

整数を戻します。

producer が書き込んだメッセージの型と、consumer が取り出すメッセージの型が一致しない場合、

取り出しが正しく行えない可能性があります。その様な状況では、実行時に異常終了する事があ

ります。

Page 139: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

128

例 11-2

実行結果は以下の様になります。

値 300を書き込むとメール・ボックスがフルになる為、値 400の書き込みはブロックされます。

時刻 50 になるとメールの取り出しが行われる為、値 400 の書き込みが再開されます。100、200、

300を読み込み中に値 400が書き込まれます。

11.3 パラメータ化したメール・ボックス(parameterized mailboxes)

メール・ボックスのデータに関する producer/consumer のデータ型不一致は実行時の問題を引き起

こします。これを避ける為に、メール・ボックスにタイプを付加する事が出来ます。一般形式は、

以下の様になります。

mailbox #(type = dynamic_type)

この形式のメール・ボックスを使用すると、メール・ボックスの型がコンパイル時に明確になる

為、producer/consumer のデータ型の一致をコンパイル時に確認する事が出来ます。

module test;

mailbox mb;

shortint val;

initial begin

mb = new(3);

#10 mb.put(100); $display("@%0t: put val=%0d",$time,100);

#10 mb.put(200); $display("@%0t: put val=%0d",$time,200);

#10 mb.put(300); $display("@%0t: put val=%0d",$time,300);

#10 mb.put(400); $display("@%0t: put val=%0d",$time,400);

end

initial begin

#50;

while( mb.num > 0 ) begin

mb.get(val);

$display("@%0t: got val=%0d",$time,val);

end

end

endmodule

@10: put val=100

@20: put val=200

@30: put val=300

@50: got val=100

@50: got val=200

@50: got val=300

@50: put val=400

@50: got val=400

Page 140: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

129

例 11-3

コンパイル時にエラーとなる記述に error の印を付けましたが、コンパイラーによってはエラー

と判断しない場合があります。例えば、smb.put(lv)をエラーと見做さないコンパイラーが多

いと考えられます。

11.4 名称付きイベント(named events)

event データ型を持つ変数は名称付きイベントとなります。名称を使用してイベントの操作を行

います。イベントが発生するまで、実行をブロックする事が出来ます。イベント待ちは以下のシ

ンタックスを使用します。

class Mail extends mailbox#(string);

// ...

endclass

class Mail2#(type T=string) extends mailbox;

// ...

endclass

module test;

mailbox mb;

mailbox#(string) smb;

Mail mail;

Mail2#(string) mail2;

Mail2 mail3;

int idata;

logic [15:0] lv;

initial begin

mb.put("this");

mb.get(idata);

smb.put(lv); // error

smb.put("this");

smb.put(123); // error

smb.try_put(123); // error

smb.get(idata); // error

smb.try_get(idata); // error

smb.peek(idata); // error

smb.try_peek(idata); // error

mail.put("mail");

mail.put(123); // error

mail2.put("mail2");

mail2.put(123); // error

mail3.put("mail3");

mail3.put(10.3); // error

end

endmodule

@ hierarchical_event_identifier

Page 141: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

130

イベント待ちのプロセスをどこかで解除しなければなりません。イベントの解除(trigger)には

次のシンタックスを使用します。

例えば、次の様に使用します。

11.4.1 triggered

イベント待ち(@ev)はエッジ・センシティブですが、ev には値が無いので状態は残りません。

この為、@ev 待ちのプロセスがイベント解除をする時期を見逃してしまう可能性があります。

例 11-4

@ev はクロッキング・イベント @(posedge clk)、又は、@(negedge clk)と異なりエッジの

状態が残りません。この為、タイミングがずれるとイベントの解除を見逃してしまいます。以下

の例ではその状況が起きています。何れの initialプロシージャが先に実行しても、@ev1、又は、

@ev2 のどちらかが解除されません。

実行結果は以下の様になります。この場合には、@ev2は解除されていません。

-> hierarchical_event_identifier ;

event ev;

initial begin

@ev;

$display("@%0t: released",$time);

end

initial begin

...

#10 ->ev;

end

module test;

event ev1, ev2;

initial begin

->ev2;

@ev1;

$display("@%0t: ev1 released.",$time);

end

initial begin

->ev1;

@ev2;

$display("@%0t: ev2 released.",$time);

end

endmodule

@0: ev1 released.

Page 142: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

131

この問題を解決する為に、SystemVerilog ではイベントの状態を取得する関数 triggered を導入し

ました。使用方法は以下の通りです。

この関数は、現在のシミュレーション時刻にイベントが起こって(triggered)いれば 1’b1 を戻し

ます。起きていなければ 1’b0 を戻します。この関数を以下の様に使用するのが最も効果的であ

るといわれています。

たとえ、-> hierarchical_event_identifier がこの wait 命令よりも先に起きても、こ

の wait は解除されます。

例 11-5

この例では、@ev1、及び、@ev2 の代わりに、triggered を使用しています。この関数は状態を保

存している為、イベントが発生した事を確実に捉える事が出来ます。

実行結果は以下の様になります。

11.4.2 引数としてのイベント・オブジェクト

SystemVerilogではタスク、又は、ファンクションの呼び出しでイベント・オブジェクトをパラメ

ータとして引き渡す事が出来ます。例えば、次の様な記述をする事が可能です。

hierarchical_event_identifier.triggered

wait ( hierarchical_event_identifier.triggered )

module test;

event ev1, ev2;

initial begin

->ev2;

wait ( ev1.triggered() );

$display("@%0t: ev1 released.",$time);

end

initial begin

->ev1;

wait ( ev2.triggered() );

$display("@%0t: ev2 released.",$time);

end

endmodule

@0: ev2 released.

@0: ev1 released.

task trigger( event ev );

-> ev;

endtask

Page 143: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

132

例 11-6

実行結果は以下の様になります。

11.4.3 wait_order文

指定した順序にイベントが発生するまで、呼び出しているプロセスをブロックします。イベント

の発生が指定した順序に従わない場合、実行時にエラーとなります。シンタックスは以下の様に

なります。

action_block に文を書く事が出来ます。action_block には条件を満たした場合、及び、満

たさない場合の状況に対応した処理を書きます。

順序に従って起きたイベントが再び起きてもエラーにはなりません。例えば、

wait_order(a,b,c);

は、イベントが a -> b -> c の順に起こるまで、現在のプロセスをブロックします。イベン

トの発生が順序に従わない場合、エラーとなります。但し、一度起きたイベントに対しての制限

はありません。例えば、イベント a とイベント b がこの順に起きた場合、イベント c が起こる

前にイベント aが再び起こってもエラーにはなりません。

module test;

event ev;

initial begin

@ev;

$display("@%0t: main completed.",$time);

end

initial begin

#30 trigger(ev);

end

task trigger(event e);

#10 ->e;

endtask

endmodule

@40: main completed.

#-I Simulation completed at time 40 ticks

wait_order ( hierarchical_identifier { , hierarchical_identifier } )

action_block

Page 144: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

133

例 11-7

この例はイベントが順序通りに発生します。イベント c が起きた時点で wait_order は終了します。

実行結果は以下の様になります。

11.4.4 イベント資源の解放

イベント・ハンドルに null を設定するとハンドルとイベント制御の関連を切断します。もし、イ

ベントの解除を待っている対象が無い場合、イベントで使用されている資源が解放されます。例

えば、

の様にして使用します。但し、@ev で待っているプロセスが存在すると、イベント待ち状態にあ

るプロセスは決して終了しません。

nullイベントに対してイベント待ちをすると、結果がどの様になるか分かりません。例えば、

に於いて、@evの結果がどうなるか分かりません。

module test;

event a, b, c;

initial begin

wait_order(a,b,c)

$display("@%0t: success",$time);

else $display("@%0t: fail",$time);

$display("@%0t: main completed.",$time);

end

initial begin

#1 ->a;

#1 ->a;

#1 ->b;

#1 ->a;

#1 ->c;

end

endmodule

@5: success

@5: main completed.

event ev;

...

ev = null;

event ev = null;

@ev;

Page 145: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

134

例 11-8

この例では、イベント ev1 に null を設定しています。このイベントを待っているスレッドは決し

て終了しません。

実行結果は以下の様になります。ev1 のイベント待ちが解除されずにシミュレーションが終了し

ています。

11.4.5 別名(alias)

イベント・ハンドルに代入文を適用する事でイベントの別名を定義する事が出来ます。例えば、

により、ev1 と ev2が同じイベントとなります。

11.4.6 イベントの比較(events comparison)

イベント変数同士の比較にオペレータ == 及び、!= を使えます。例えば、

の様にして比較する事が出来ます。

module test;

event ev1, ev2;

initial begin

@ev1;

$display("@%3t: Initial-1 ended.",$time);

end

initial begin

@ev2;

$display("@%3t: Initial-2 ended.",$time);

end

initial begin

#100 $display("@%3t: Initial-3 ended.",$time);

end

initial begin

#10 ev1 = null;

->ev1;

->ev2;

end

endmodule

@ 10: Initial-2 ended.

@100: Initial-3 ended.

#-I Simulation completed at time 100 ticks

event ev1, ev2;

ev1 = ev2;

if( ev != null )

->ev;

Page 146: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

135

例 11-9

実行結果は以下の様になります。

module test;

event ev, ev2;

initial begin

ev2 = ev;

@ev;

$display("@%0t: step1 is released.",$time);

@ev;

$display("@%0t: step2 is released.",$time);

if( ev == ev2 )

$display("@%0t: ev and ev2 are the same.",$time);

else

$display("@%0t: this cannot happen.",$time);

end

initial begin

#1 ->ev2;

#5 ->ev;

end

endmodule

@1: step1 is released.

@6: step2 is released.

@6: ev and ev2 are the same.

#-I Simulation completed at time 6 ticks

Page 147: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

136

12 アサーション(assertions)

アサーションは広範囲に及ぶ複雑な検証機能から構成されています。この章ではアサーションの

基本機能について概説します。細かいシンタックス等には触れません。詳細に関しては、原書、

及び、該当するアサーションの専門書([4][6])を参照して下さい。

12.1 概要

アサーションは、仕様とデザイン(仕様を実装した内容)が一致する事をチェックする機能です。

一致しない場合、明瞭なレポートを作成する事が出来ます。アサーションには二種類あります。

即時実行型アサーション(immediate assertions)

並列型アサーション(concurrent assertions)

即時実行型アサーションは、通常の実行文と同様に実行して検証する機能です。一定の時間間隔

アクティブになっているわけではありません。簡単に言えば、検証用の if-then-else 文です。この

型のアサーションはアサーション以外でも使用される事が多く見られます。例えば、前提条件が

成立している事を確認する為に使用します。次の記述は、その一例です。

一方、並列型アサーションはシミュレーションと並行して実行しながら仕様を検証する機能です。

アサーションで記述しているイベントが発生すると、仕様とデザインの一致をチェックします。

このチェックはデザインのシミュレーションと独立しています。

アサーションというと、一般的には、並列型アサーションを意味します。

12.2 即時実行型アサーション(immediate assertions)

即時実行型アサーションには assert、assume、cover の三種類があります。それぞれのシン

タックスは以下の様になっています。

action_block は条件が成立、又は、不成立の際の処理を記述します。成立した場合、最初の文が

実行されます。この文は pass statementと呼ばれます。条件不成立の場合の処理は、elseクローズ

で指定します。この文は fail statementと呼ばれます。

assert 文は指定した式が成立する事を要求します。成立しない場合は、仕様に違反すると解釈さ

れます。違反が起きて、assert文に elseクローズが指定されていない場合、$errorが呼び出されま

す。

assume 文は指定した式が成立する事を仮定します。この文は、フォーマル・ベリフィケーション

等のツールに使用されます。シミュレータに対しては assert文と同様に扱われます。

packet_t p;

...

p = new;

assert( p.randomize() )

else $fatal(0,”packet_t::randomize() failed.”);

...

assert ( expression ) action_block

assume ( expression ) action_block

cover ( expression ) statement_or_null

action_block ::=

statement_or_null

| [ statement ] else statement_or_null

Page 148: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

137

cover文はカバレッジ情報を生成します。以下の情報を含みます。

式が評価された回数

式が成立した回数

簡単な例を示す事にします。

例 12-1

assert 文に対して、fail statement のみ指定しています。時刻 50 に於いては、a==0、及び、b==0

です。従って、条件に違反します。それ以外の時刻では、条件が成立します。

実行結果は以下の様になります。

12.3 並列型アサーション(concurrent assertions)

並列型アサーションはデザインのシミュレーションと並行して実行します。実行は、クロックの

イベントと同期します。アサーションはクロック・イベントが発生した時に評価されます。評価

式を構成する信号値の値は、サンプル値(sampled value)と呼ばれます。SystemVerilog ではサン

プル値の取得に関して厳密な取り決めをしています。アサーションの評価は observed region で行

われます。

module test;

bit clk, a, b;

initial begin

a = 1;

b = 1;

#100 $finish;

end

initial forever #10 clk = ~clk;

always @(posedge clk)

assert( a || b )

else $display("@%0t: assert failed.",$time);

initial begin

fork

begin

#20 a = 0;

#40 a = 1;

end

#40 b = 0;

join

end

endmodule

@50: assert failed.

Page 149: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

138

12.3.1 アサーションはマルチ・スレッド

アサーションの条件式を P とします。クロック・イベント T に於いて P のインスタンス p1 が評

価されますが、p1 の評価は、一般に、時刻 T で終了しません。次のクロック・イベントでも p1

の評価が続行されます。即ち、時刻 Tで発生した Pのインスタンスの評価は幾つかのクロック・

イベントで評価されて結論が出ます。一方、T の次のクロック・イベントでも、P の別のインス

タンス p2 が発生します。従って、アサーションの条件式が唯一つであっても、その複数個のイ

ンスタンスが同時に実行します。それぞれのインスタンスはスレッドとして実行する為、アサー

ションはマルチ・スレッドになります。極端な場合、あるインスタンスはシミュレーション終了

時まで実行し続けます。しかも、これらのマルチ・スレッドは通常のデザインのシミュレーショ

ンと並列に実行します。

12.3.2 サンプリング(sampling)

アサーションの評価に使用されるサンプル値は、例外はありますが、preponed region に於ける信

号値を意味します。

preponed region は時刻 T のシミュレーション・タイム・スロットの最初の領域です。サンプル値

は、時刻 T のシミュレーションを開始する直前の信号値を意味します。preponed region の反意語

は postponed region です。これは、時刻 T のシミュレーション・タイム・スロットの最後の領域

です。

例外は、automatic 変数、又は、ローカル変数等です。これらの変数の値は評価する時点の値を参

照します。preponed regionの値ではありません。例えば、forループで確保した制御変数は現在の

値を参照します。サンプル値の概念は、アサーションを理解するにつれて次第に明らかになりま

す。現時点では、この程度の理解で十分だと思います。

12.3.3 アサーション・クロック

アサーションはクロックをベースにして条件を評価します。サンプル値はクロック・イベントが

発生した時に取得されます。

12.4 ブーリアン式(boolean expressions)

アサーションの条件式の評価結果は boolean で、通常の式の評価と同じです。即ち、結果が 0、x、

又は、zであれば、偽(false)となり、それ以外であれば、真(true)となります。

12.5 シーケンス(sequences)とプロパーティ(properties)

アサーションの条件式(即ち、検証すべき仕様)はプロパーティ(properties)で記述されます。

プロパーティはシーケンスから組み立てられます。シーケンスはシーケンス・オペレータとブー

リアン式から構成されます。極端な場合、ブーリアン式はプロパーティになりますが、ブーリア

ン式は時間を含まない(non-temporal)為、並列型アサーションを使用する理由はありません。

意味のあるアサーションにはシーケンス・オペレータが必要になります。単なるブーリアン式で

あれば、即時実行型アサーション(immediate assertions)で済む場合が多いです。

data

T

時刻 Tに於ける dataのサンプル値は 1’b1です。1’b0ではありません。

simulation

time step

Page 150: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

139

シーケンス(及びプロパーティ)は複数のクロック・イベントを経過して評価を終了します。評

価終了時に真となれば、仕様とデザインが一致(match)する事と判断されます。途中で評価が

偽となれば、仕様とデザインが一致しないと判定されます。本書では、この判定結果をマッチ、

及び、マッチしないと表現します。或いは、pass、及び、failとも表現します。

簡単なシーケンスとプロパーティの例を示します。

|->は implication operator と呼ばれ、if の意味を持ちます。オペレータの左辺(antecedent)が真

であれば、右辺(consequent)を評価します。左辺が偽の場合、右辺には関心が無い為、全体は

マッチする事になります。但し、その場合のマッチは本来の意味のマッチとは意味が異なる為、

この様なマッチを vacuous pass(真偽判定不能なパス)と呼びます。

プロパーティ ex1 に於いて、a が真であると、s1 の評価が始まります。s1 に於いて、c が真で

あると 1クロック・サイクル後に b の評価をします。b が真であると、ex1 の評価は終了して、

マッチすると結論されます。

シーケンス s1 はクロック・サイクルを参照している為、クロックの定義がどこかで明確にされ

ていなければなりません。プロパーティ ex1 ではクロックの定義がされていません。従って、

プロパーティ ex1 を呼ぶプロパーティでクロックの定義がされているか、又は、default

clocking の定義が必要になります。例えば、ex1 を呼ぶ側で以下の様にクロック・イベントを

定義します。

この様にして定義されたクロックを leading clockと呼びます。

実際問題として、シーケンス、及び、プロパーティだけでは実行しません。実際に実行するのは、

assert、assume、cover、及び、restrict等の文です。それらの文は leading clockのイベントが起こる

と自動的に実行を開始します。一旦実行を開始するとそのアサーションは評価が終了するまで実

行を継続します。

この例が示す様に、一般には、プロパーティやシーケンスにクロックの定義を含みません。クロ

ックの定義を含まない事でプロパーティやシーケンスの抽象度が増し、より多くの検証に適用す

る事が出来るからです。このアプローチにより検証系の財産の蓄積に繋がります。

尚、implication operatorには類似したオペレータ|=>があります。このオペレータは、右辺の評価

を 1クロック・サイクル後に開始します。

sequence s1;

c ##1 b;

endsequence

property ex1;

a |-> s1;

endproperty

assert property (@(posedge clk) ex1)

$display("passed @%0t",$time);

else

$display("failed @%0t",$time);

Page 151: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

140

例 12-2

これを実行すると以下の様な結果を得ます。

4 つのパスが報告されていますが、この中には vacuous pass が含まれます。どのパスが真のパス

かは調べるまで分かりません。最近はアサーションのスレッド表示機能を持つシミュレーショ

ン・ツールが普及しています。次に示す図はその一例です。

図に於いて、緑の▽は真のパス、赤の▽は fail、黄色の▽は vacuous pass です。青の△はスレッ

ドの開始を意味します。緑色の線分はスレッドの活動区間を示します。数字はスレッド番号を示

します。

module test;

logic a, b, c;

bit clk;

sequence s1;

c ##1 b;

endsequence

property ex1;

a |-> s1;

endproperty

assert property (@(posedge clk) ex1)

$display("passed @%0t",$time);

else $display("failed @%0t",$time);

initial repeat (10) #10 clk = ~clk;

initial begin a = 0; #20 a = 1; #20 a = 0;

#20 a = 1; #20 a = 0; end

initial begin b = 0; #40 b = 1; #20 b = 0; end

initial begin c = 0; #5 c = 1; end

endmodule

passed @10

passed @50

passed @50

failed @90

passed @90

Page 152: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

141

以下の様に変更すると vacuous passのレポートを抑止する事が出来ます。

cover propertyは vacuous pass を無視するのでログ・ファイルには vacuous pass はプリントされま

せん。以下の様な結果を得ます。

12.6 シーケンスの操作(sequence operations)

シーケンスに使用できる主なオペレータは以下の様に纏められます。

オペレータ 意味

[*m]

[*m:n] 連続した繰り返しを意味します。例えば、

a[*3] は、1クロックのディレーをおいて a が

三回繰り返す事を意味します。即ち, a[*3] は a ##1 a ##1 a

と同じです。

[=m]

[=m:n] 不連続の繰り返しを意味します。

[->m]

[->m:n goto オペレータと呼ばれます。

不連続の繰り返しを意味します。

##m

##[m:n] クロック・ディレーを意味します。

sig throughout seq seq を評価している間、sig は真でなければな

りません。sig は信号又は信号の式です。シー

ケンスを指定する事は出来ません。

seq1 within seq2 seq1は seq2に含まれるを意味します。

seq1 intersect seq2 and と同じですが、両オペランドは同時に終了

しなければなりません。

seq1 and seq2 両オペランドがマッチすれば全体としてマッチ

します。更に、両オペランドは同時に開始しな

ければなりません。

seq1 or seq2 どちらかがマッチすれば、全体としてマッチし

ます。

first_match 複数のマッチが存在する時、最も早く終了する

マッチを採択し、他のマッチを破棄します。

[=]と[->]オペレータは非常に似ています。単独で使用すると意味は同じですが、後続のオペラ

ンドが存在すると意味が全く異なります。先ずは、基本的なオペレータから機能を学習する事に

します。

assert property (@(posedge clk) ex1)

else $display("failed @%0t",$time);

cover property (@(posedge clk) ex1)

$display("passed @%0t",$time);

passed @50

failed @90

Page 153: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

142

12.6.1 ##m

##m は m 回のクロッキンッグ・エッジ(クロック・サイクル)のディレーを置く意味です。例

えば、クロッキング・エッジが @(posedge clk)であるとすると、##2 は 2 回 @(posege

clk)が起こるまで待つ事を意味します。次のシーケンス

a ##2 b

は、現在のクロッキング・エッジで a は真で、2クロック・サイクル後に b は真である事を記述

しています。この条件が満たされると、上記のシーケンスはマッチする事になります。

m==0 の場合は、ディレーはありません。従って、

a ##0 b

は、a && bと同じです。##0 はフュージョン(fusion)と呼ばれます([6])。

例 12-3

cover property を使用して、vacuous pass をプリントしない様にしています。assert property 及び

cover propertyではプロパーティ ab を呼び出しています。これらの文だけでは leading clockが未

知です。プロパーティ abの内容を精査して初めて leading clockが分かります。

実行結果は以下の様になります。

12.6.2 ##[m:n]

m から nクロック・サイクルのディレーを置く意味です。例えば、

request ##[1:3] grant

module test;

bit clk, a, b, z;

sequence seq;

a ##2 b;

endsequence

property ab;

@(posedge clk) z |-> seq;

endproperty

assert property (ab)

else $display("@%0t: FAIL",$time);

cover property (ab)

$display("@%0t: PASS",$time);

initial begin #20 z = 1; #40 z = 0; end

initial begin #20 a = 1; #40 a = 0; end

initial begin #40 b = 1; #40 b = 0; end

initial repeat (11) #10 clk = ~clk;

endmodule

@70: PASS

@90: FAIL

Page 154: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

143

は、request が来たら、1 から 3クロック・サイクル以内に grant が真にならなければならな

い事を意味します。1 から 3 クロック・サイクル以内に grant が真になった時点で評価は終了

します。たとえ 1 から 3 クロック・サイクルの間、grant ==1’b1 であっても、pass するのは

最初の一回です。三回ではありません。

例 12-4

実行すると以下の結果を得ます。

12.6.3 [*m]

ユーナリー・オペレータで、 b[*m] の様にして使います。b[*m] がマッチするには、b は連続

した m クロックの間、常に真でなければなりません。そして、オペレーションは(m-1)クロッ

ク・サイクル後に終了します。bが偽であれば、その時点でオペレーションは終了します。

module test;

bit clk, a, b, z;

sequence seq;

a ##[1:2] b;

endsequence

property ab;

@(posedge clk) z |-> seq;

endproperty

assert property (ab)

else $display("@%0t: FAIL",$time);

cover property (ab) $display("@%0t: PASS",$time);

initial begin #20 z = 1; #20 z = 0; #20 z = 1; #20 z = 0; end

initial begin #20 a = 1; #20 a = 0; #20 a = 1; #20 a = 0; end

initial begin #40 b = 1; #40 b = 0; end

initial repeat (11) #10 clk = ~clk;

endmodule

@50: PASS

@110: FAIL

Page 155: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

144

例 12-5

実行結果は以下の様になります。

module test;

bit clk, a, b, z;

sequence seq;

a ##1 b[*2];

endsequence

property ab;

@(posedge clk)z |=> seq;

endproperty

assert property (ab)

else $display("@%0t: FAIL",$time);

cover property (ab) $display("@%0t: PASS",$time);

initial begin #5 z = 1; #10 z = 0; #30 z = 1; #10 z = 0; end

initial begin #15 a = 1; #10 a = 0; #30 a = 1; #10 a = 0; end

initial begin #25 b = 1; #20 b = 0; #20 b = 1; #10 b = 0; end

initial begin clk = 1; repeat (16) #5 clk = ~clk; end

endmodule

@40: PASS

@80: FAIL

a ##1 b[*2] a ##1 b ##1 b

a

b

Page 156: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

145

12.6.4 [*m:n]

[*m]と同様にユーナリー・オペレータです。b[*m:n]がマッチする為には、連続したクロック・

エッジの間で b は常に真でなければなりません。そして、クロック・エッジ数は最少 m 回、最

大 n 回である事が条件です。その条件を満たす最初のクロックでオペレーションは終了します。

但し、注意が必要です([4])。例えば、b[*2:4]は

(b ##1 b) || (b ##1 b ##1 b) || (b ##1 b ##1 b ##1 b)

と同じです。(b ##1 b)が真であれば、オペレーションは終了します。一方、(b ##1 b)が偽

であると他のサブシーケンスも偽になります。従って、

b[*2:4] == b[*2]

となります。言い換えると、:4 は無効になっています。何故、[*m:n]のオペレータが存在する

のか疑問になります。答えは次の様になります。

オペレータ[*m:n]が単独に使用された場合[*m]と同じ働きですが、後続のオペランドが存在す

ると[*m:n]!= [*m]となります。例えば、b[*2:4] ##1 c は

(b ##1 b ##1 c) || (b ##1 b ##1 b ##1 c) || (b ##1 b ##1 b ##1 b ##1 c)

となります。明らかに、(b[*2:4] ##1 c) != (b[*2] ##1 c)です。

例 12-6

実行結果は以下の様になります。

module test;

bit clk, a, b, c, z;

sequence seq;

a ##1 b[*2:5] ##1 c;

endsequence

property ab;

@(posedge clk) z |-> seq;

endproperty

assert property (ab)

else $display("@%0t: FAIL",$time);

cover property (ab) $display("@%0t: PASS",$time);

initial begin #20 z = 1; a = 1; #20 z = 0; a = 0;

#20 z = 1; a = 1; #20 z = 0; a = 0; end

initial begin #80 b = 1; #60 b = 0; end

initial begin #140 c = 1; #20 c = 0; end

initial repeat (16) #10 clk = ~clk;

endmodule

@50: FAIL

@150: PASS

Page 157: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

146

12.6.5 [=m]

b[=m]は、必ずしも連続しないクロック・エッジにおいて b は m 回真である事が求められます。

例えば、b[=2]を正則表現的で書くと

...b...b...

という事になります。ここで、b は b==1’b1 を意味します。最後の...には b==1’b1 があって

はなりません。例えば、b[=2] ##1 c は、

...b...b...c

となります。二番目の b が真の後、三番目の b==1’b1 が来る前に c が真になる事を意味してい

ます。尚、cは bの直後とは限りません。従って、次の意味ではありません。

...b...bc (実は、これは gotoです。)

例 12-7

これを実行すると以下の様な結果を得ます。

module test;

bit clk, a, b, c;

property p;

@(posedge clk) a |=> b [=2] ##1 c;

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial #270 $finish;

initial forever #10 clk = ~clk;

initial begin #20 a = 1; #20 a = 0; #100 a = 1; #20 a = 0; end

initial begin #40 b = 1; #20 b = 0; #20 b = 1; #20 b = 0;

#60 b = 1; #20 b = 0; #20 b = 1; #20 b = 0; #20 b = 1;

#20 b = 0; end

initial begin #120 c = 1; #20 c = 0; end

endmodule

Page 158: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

147

30nsから開始したスレッドが

a.b.b.c

を 130nsで実現しています。従って、@130: PASSがプリントされています。一方、150nsで開始

したスレッドが、cが真になる前に、250nsに於いて

a.b.b.b

となっています。従って、@250: FAILとなります。

12.6.6 [=m:n]

b[=m:n]は b が必ずしも連続ではないクロック・エッジにおいて b は m から n 回真となる事を

求めています。区間を指定するので、単独で使用するとオペレータの意味はありません。必ず、

他のオペランドが後に続く必要があります。

例えば、b[=2:3] ##1 c を正則表現的に書くと

...b...b...c 、又は、 ...b...b...b...c

となります。即ち、b が 2から 3回真になっている間に c も真になる事が必要です。次の様な状

態はマッチしません。

@130: PASS

@250: FAIL

bbbbc

b...b...b...b...c

Page 159: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

148

例 12-8

実行結果は以下の様になります。

30nsから開始したスレッドが

ab.bc

を 110nsで実現しています。従って、@110: PASSをプリントしています。また、130nsで開始し

たスレッドが cが真になる前に、250nsに於いて

abbbbbb

となっています。従って、@250: FAILとなります。

module test;

bit clk, a, b, c;

property p;

@(posedge clk) a |=> b [=2:5] ##1 c;

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial begin

#270 $finish;

end

initial forever #10 clk = ~clk;

initial begin #20 a = 1; #20 a = 0; #80 a = 1; #20 a = 0; end

initial begin #40 b = 1; #20 b = 0; #20 b = 1;

#20 b = 0; #40 b = 1; end

initial begin #100 c = 1; #20 c = 0; end

endmodule

@110: PASS

@250: FAIL

Page 160: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

149

12.6.7 [->m]

non-consecutive goto オペレータとも呼ばれます。後続のオペランドが無ければ[=m]と同じです。

後続のオペランドがあると[=m]と異なります。b [->2] ##1 c を正則表現的に書くと、

...b...bc

となります。

例 12-9

実行結果は以下の様になります。

12.6.8 [->m:n]

[->m]に対して区間となっている違いがありますが、意味的には理解し易いと思います。

module test;

bit clk, a, b, c;

property ab;

@(posedge clk) a |=> b [->2] ##1 c;

endproperty

assert property (ab)

else $display("@%0t: FAIL",$time);

cover property (ab) $display("@%0t: PASS",$time);

initial begin #20 a = 1; #20 a = 0; #60 a = 1; #20 a = 0; end

initial begin #40 b = 1; #20 b = 0; #20 b = 1; #20 b = 0;

#20 b = 1; #20 b = 0; #20 b = 1; #20 b = 0;

#20 b = 1; #20 b = 0; end

initial begin #100 c = 1; #20 c = 0; end

initial repeat (22) #10 clk = ~clk;

endmodule

@110: PASS

@190: FAIL

Page 161: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

150

例 12-10

実行結果は以下の様になります。

12.6.9 sig throughout seq

シーケンス seq を評価中は sig が常に真でなければならない事を要求します。sig は信号又は

信号の式で、シーケンスを使用する事は出来ません。

sig が真の間に seq がマッチすると判定されれば sig throughout seq はマッチします。逆

に言えば、sig、又は、seq の何れかが偽となると sig throughout seq はマッチしません。

module test;

bit clk, a, b, c;

property p;

@(posedge clk) a |=> b [->2:5] ##1 c;

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial begin

#270 $finish;

end

initial

forever #10 clk = ~clk;

initial begin #20 a = 1; #20 a = 0; #80 a = 1; #20 a = 0; end

initial begin #40 b = 1; #20 b = 0; #20 b = 1; #20 b = 0;

#40 b = 1; #100 b = 0; end

initial begin #100 c = 1; #20 c = 0; end

endmodule

@110: PASS

@250: FAIL

Page 162: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

151

例 12-11

実行結果は以下の様になります。

12.6.10 seq1 within seq2

両方のシーケンスがマッチしなければなりません。更に、seq1 は seq2 と同時、又は、後に評価

を開始し、seq2の評価終了より遅くない時期に seq1の評価が終了しなければなりません。

module test;

bit clk, a, b, z;

property p;

@(posedge clk) $rose(z) |-> a throughout b[*3];

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (18) #10 clk = ~clk;

initial begin #20 a = 1; #80 a = 0; #20 a = 1; #40 a = 0; end

initial begin #20 b = 1; #60 b = 0; #40 b = 1; end

initial begin #20 z = 1; #20 z = 0; #80 z = 1; #20 z = 0; end

endmodule

@70: PASS

@170: FAIL

sig

seq

T1 T2

sigは T1から T2の間、真(true)でなければならない。

Page 163: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

152

例 12-12

実行結果は以下の様になります。

12.6.11 seq1 and seq2

両方のシーケンスが同時に開始してマッチしなければなりません。終了時刻は一致しなくても構

いません。

module test;

bit clk, z, a, b, c;

property p;

@(posedge clk) $rose(z) |-> a[*2] within b ##1 c[*3];

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (19) #10 clk = ~clk;

initial begin #20 z = 1; #20 z = 0; #60 z = 1; #20 z = 0; end

initial begin #40 a = 1; #40 a = 0; #80 a = 1; #40 a = 0; end

initial begin #20 b = 1; #40 b = 0; #40 b = 1; #20 b = 0; end

initial begin #40 c = 1; #60 c = 0; #20 c = 1; #60 c = 0; end

endmodule

@90: PASS

@170: FAIL

seq1

seq2

T1 T2

seq1は T1から T2の間でマッチしなければならない。

Page 164: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

153

例 12-13

実行結果は以下の様になります。

12.6.12 seq1 or seq2

何れかのシーケンスがマッチすれば全体としてマッチした事になります。何れかがマッチしたら

オペレーションは終了します。

module test;

bit clk, a, b, c, d, e, z;

property p;

@(posedge clk) $rose(z)|->(a ##1 b) and (c ##1 d ##1 e);

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (16) #10 clk = ~clk;

initial begin #20 z = 1; #20 z = 0; #60 z = 1; #20 z = 0; end

initial begin #20 a = 1; #40 a = 0; #40 a = 1; #20 a = 0; end

initial begin #40 b = 1; #20 b = 0; #60 b = 1; #20 b = 0; end

initial begin #20 c = 1; #40 c = 1; #40 c = 1; #20 c = 0; end

initial begin #40 d = 1; #20 d = 0; #60 d = 1; #20 d = 0; end

initial begin #60 e = 1; #20 e = 0; end

endmodule

@70: PASS

@150: FAIL

seq1

seq2

T1 T2

seq1と seq2の何れかががマッチしなければならない。何れかがマッチすると終了。

seq1

seq2

T1 T2

seq1と seq2は同時に開始しなければならない。

seq1と seq2の両方がマッチしなければならない。

Page 165: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

154

例 12-14

実行結果は以下の様になります。

12.6.13 seq1 intersect seq2

and オペレータと似ていますが、両方のシーケンスが同時に終了しなければない条件が付加され

ます。即ち、両方のシーケンスは同時に開始し、同時に終了し、同時にマッチしなければなりま

せん。

seq1 and seq2 よりも強い条件と言えます。

module test;

bit clk, a, b, c, d, z;

property p;

@(posedge clk) $rose(z) |-> a[*2] or (b ##1 c ##1 d);

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (15) #10 clk = ~clk;

initial begin #20 z = 1; #20 z = 0; #40 z = 1; #20 z = 0; end

initial begin #20 a = 1; #40 a = 0; #20 a = 1; #20 a = 0; end

initial begin #20 b = 1; #20 b = 0; #40 b = 1; #20 b = 0; end

initial begin #40 c = 1; #20 c = 0; #40 c = 1; #20 c = 0; end

endmodule

@50: PASS

@130: FAIL

seq1

seq2

T1 T2

seq1と seq2は同時に開始しなければならない。

seq1と seq2は同時に終了しなければならない

seq1と seq2の両方がマッチしなければならない。

Page 166: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

155

例 12-15

実行結果は以下の様になります。

12.6.14 first_match (seq)

複数のマッチが存在する時、最も早く終了するマッチを採択し、他のマッチを破棄します。

12.7 シーケンスへのパラメータ

シーケンスの記述にパラメータを使用する事が出来ます。パラメータにより、シーケンスは汎用

化されます。例えば、

の様に定義して、s1(request,grant)の様に使用すると、

と同じ事になります。サイクル・ディレーの値をパラメータにする事も出来ます。例えば、

の様に定義して、s2(request,grant,1,3)の様に使用すると、

module test;

bit clk, a, b, c, d, z;

property p;

@(posedge clk) $rose(z) |-> (a ##[1:3] b) intersect (c

##2 d[*2]);

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (19) #10 clk = ~clk;

initial begin #20 z = 1; #20 z = 0; #80 z = 1; #20 z = 0; end

initial begin #20 a = 1; #20 a = 0; #80 a = 1; #20 a = 0; end

initial begin #80 b = 1; #20 b = 0; #60 b = 1; #20 b = 0; end

initial begin #20 c = 1; #20 c = 0; #80 c = 1; #20 c = 0; end

initial begin #60 d = 1; #40 d = 0; #60 d = 1; #40 d = 0; end

endmodule

@90: PASS

@190: FAIL

sequence s1(a,b);

a ##[1:3] b

endsequence

request ##[1:3] grant

sequence s2(a,b,left,right);

a ##[left:right] b

endsequence

request ##[1:3] grant

Page 167: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

156

と同じ事になります。s2(request,grant,1,$)は

の様に展開されます。クロッキング・イベントは event タイプのパラメータで受けます。例えば、

の様に定義して、s3(posedge clk)の様に使用します。この呼び出しは、

となります。但し、エッジ・イベントの信号を受ける時には、event タイプで受ける事は出来ま

せん。例えば、次の様に受けます。

こうすると、s4(clk)は

と展開されます。

12.8 便利なサンプル関数

12.8.1 サンプル関数

信号値の状態変化を検出する為の便利な関数を記します。

関数 意味

$sampled( expression ) サンプル値を戻します。

$rose ( expression

[, [clocking_event] ] ) expression の LSB が 1 に変化したら真(true)を戻し

ます。それ以外は、偽(false)を戻します。

$fell ( expression

[, [clocking_event] ] ) expression の LSB が 0 に変化したら真(true)を戻し

ます。それ以外は、偽(false)を戻します。

$stable ( expression

[, [clocking_event] ] ) expression の値に変化が無ければ真(true)を戻しま

す。それ以外は、偽(false)を戻します。

$changed ( expression

[ , [ clocking_event ] ] ) expression の値が変化すれば真(true)を戻します。

それ以外は、偽(false)を戻します。

$past ( expression1

[, [number_of_ticks ]

[, [expression2 ]

[, [clocking_event]]] ] )

expression で示す信号の過去の値を戻します。

number_of_ticks:遡るクロック数。標準値は 1。

expression2:クロック gating。標準値は 1’b1。

clocking_event:クロックイベント。

request ##[1:$] grant

sequence s3(event ev);

@(ev) a ##1 b

endsequence

@(posedge clk) a ##1 b

sequence s4 (reg sig);

@(posedge sig) x ##1 y;

endsequence

@(posedge clk) x ##1 y

Page 168: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

157

例 12-16

$past(code)が直前のクロック・サイクルにおける code の値を取得している事が確認できま

す。

12.8.2 レベル・センシティブ とエッジ・センシティブ

オペレータ |->、及び、|=> を使用する時は、関数 $rose、及び、$fell が有効に働きます。例え

ば、レベル・センシティブ

の場合、z == 1’b1 であり限り、右辺を評価します。極端な場合、シミュレーション終了時ま

で、z == 1’b1であると、クロック・イベントが起こる度に右辺の計算を行う事になります。

module test;

bit clk;

logic a, b;

logic [3:0] code;

always @(posedge clk)

$display("@%0t: $sample=%0d $past=%0d",

$time, $sampled(code), $past(code) );

initial begin

code = 0;

#25 code = 1;

#20 code = 2;

#20 code = 3;

#20 code = 4;

end

initial

repeat (10) #10 clk = ~clk;

endmodule

@10: $sample=0 $past=x

@30: $sample=1 $past=0

@50: $sample=2 $past=1

@70: $sample=3 $past=2

@90: $sample=4 $past=3

@(posedge clk) z |-> a ##1 b

a ##1 b は@(posedge clk)が起こる度に評価される為、効率は良くない。

z

@(posedge clk) z |-> a ##1 b

Page 169: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

158

検証すべき仕様にも依存しますが、z の信号値が 1’b1、又は、1’b0 に変化した時にのみ、右辺が

成り立つ事を確認するすれば良い場合が多いです。その様な仕様の場合には、エッジ・センシテ

ィブな記述

はレベル・センシティブより遥かに効率が良いアサーションとなります。

例 12-17

この例では、エッジ・センシティブな関数 $rose を antecedent に使用しています。歴然とした

差が出てきます。

実行結果は以下の様になります。

@(posedge clk) $rose(z) |-> a ##1 b

module test;

bit clk, a, b;

property p;

@(posedge clk) $rose(a) |=> $rose(b);

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (14) #10 clk = ~clk;

initial #20 a = 1;

initial begin #40 b = 1; #20 b = 0; #60 b = 1; #20 b = 0; end

endmodule

@50: PASS

@(posedge clk) $rose(z) |-> a ##1 b

a ##1 b は$rose(z)が真になる直後の@(posedge clk)にのみ評価される為、

効率は良い。

z

Page 170: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

159

スレッド・ダイアグラムに依ると、30ns のみ右辺の評価をしています。他の@(posedge clk)

イベント時には、vacuous passとなっています。次にレベル・センシティブに変更して見ます。

実行結果は以下の様になります。

module test;

bit clk, a, b;

property p;

@(posedge clk) a |=> $rose(b);

endproperty

assert property (p)

else $display("@%0t: FAIL",$time);

cover property (p) $display("@%0t: PASS",$time);

initial repeat (14) #10 clk = ~clk;

initial #20 a = 1;

initial begin #40 b = 1; #20 b = 0; #60 b = 1; #20 b = 0; end

endmodule

@50: PASS

@70: FAIL

@90: FAIL

@110: FAIL

@130: PASS

Page 171: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

160

スレッド・ダイアグラムに依ると@(posedge clk)イベントが起こる度に右辺の評価が行われ

ています。エッジ・センシティブと比較して、アクティブなスレッド数が多くなっています。

12.9 メソッド triggered

他のシーケンスがマッチしたか否かを調べる事が出来ます。マッチしていれば、真(1’b1)を戻

し、そうでなければ偽(1’b0)を戻します。使用方法は以下の様になります。パラメータを指定

する事も出来ます。

例えば、

の様にして使用します。ここで、s1 と s2 は独立したシーケンスです。a が真になった 1 クロッ

ク・サイクル後に、s1 はマッチしなければなりません。s1 が何時開始されるかは問題ではあり

ません。

sequence_instance.triggered

or

formal_argument_sequence.triggered

sequence s2;

@(posedge clk) a ##1 s1.triggered ##1 b;

endsequence

a

sequence s2;

@(posedge clk) a ##1 s1.triggered ##1 b;

s1

b s2 はマッチ

Page 172: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

161

例 12-18

二つのシーケンスが独立に実行します。シーケンス ex2 は 2 サイクル後に ex1 が一致したかを調

べます。一致していれば 1 サイクル後に信号 f を調べます。ex1 が一致していなければ、その時

点で ex2は失敗(一致していない事)になります。

実行結果は以下の通りです。

これだけでは分かり難いので、ダイアグラムを使用します。

module test;

logic a, b, c,

d, e, f;

bit clk;

int pass, fail;

sequence ex1;

@(posedge clk) $rose(a) ##1 b ##1 c;

endsequence

sequence ex2;

d ##1 e ##1 ex1.triggered ##1 f;

endsequence

asp: assert property (@(posedge clk) ex2)

$display("@%0t: PASS",$time);

else

$display("@%0t: FAIL",$time);

initial begin

fork begin a = 0; #20 a = 1; #20 a = 0; end

begin b = 0; #40 b = 1; end

begin c = 0; #60 c = 1; end

begin d = 0; #20 d = 1; #40 d = 0; end

begin e = 0; #20 e = 1; #80 e = 0; end

begin f = 0; #80 f = 1; end

join

end

initial repeat (10) #10 clk = ~clk;

endmodule

@10: FAIL

@70: FAIL

@90: PASS

@90: FAIL

@90: FAIL

Page 173: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

162

上半分が ex2、下半分が ex1のアクティビティです。

d ##1 e ##1 ex1.triggered ##1 f

がスレッド 8 として 30ns で開始し、70ns で ex1.triggered を呼んでいます。この時、ex1(スレッ

ド 7)が一致しています。従って、スレッド 8は 1サイクル後に fを調べます。90nsに f==1なの

で、スレッド 8はパスします。ダイアグラムで 8.7はスレッドの関係を示しています。

同様な解析をすると 90ns でスレッド 11 が失敗している事が分かります。理由は 90ns に於いて

ex1(スレッド 16)が一致していないからです。

12.10 defaultクロッキング

今までの例ではクロッキング・イベントをシーケンスに含んでいましたが、default クロッキング

を使用するとシーケンスは単純になります。

default クロッキングが定義されていると、シーケンスにクロッキング・イベントを指定する必要

が無くなります。例えば、次の様にして default clocking を定義して置きます。

アサーション、シーケンス、及び、プロパーティにクロッキング・イベントの指定が無い場合、

default clockingが仮定されます。詰まり、この場合には @(posedge clk)が仮定されます。

次の例では defaultクロッキング・ブロック内にプロパーティを定義します。

default clocking cb @(posedge clk); endclocking

property check_request_grant;

request ##[1:3] grant;

endproperty

assert property (check_request_grant);

Page 174: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

163

例 12-19

実行結果は以下の様になります。

12.11 プロパーティ

これまでの例でプロパーティを示しましたが、使用している機能はその一部です。プロパーティ

にはこの他多くのオペレータが存在し、複雑な仕様記述をする事が出来ます。然し、それらの記

述は入門書の範囲を超えるので、ここでは簡単なオペレータだけを紹介します。

オペレータ 意味

#-#

#=# followed-by オペレータと呼ばれます。シーケ

ンス・オペレータ|->及び|=>に対応していま

す。

followed-byオペレータには vacuous passがあ

りません。即ち、両辺がパスする時のみ全体が

パスします。

#-# にはオーバーラップがあります。左辺が

パスした時刻に右辺の評価を開始します。

#=# は左辺がパスすると 1 クロックサイクル

後に右辺の評価を開始します。

always property_expr property_expr が常に成立すればパスします。

s_always [ constant_range ]

property_expr property_expr がシミュレーション実行中に常

に成立すればパスします。

nexttime property_expr もし次のクロックが存在すれば、その時の式の

module test;

bit clk, req, gnt, check;

default clocking cb @(posedge clk);

property req_gnt;

$rose(check) |-> req ##[1:3] gnt;

endproperty

endclocking

asp: assert property (req_gnt)

else $display("@%0t: FAIL",$time);

cop: cover property (req_gnt)

$display("@%0t: PASS",$time);

initial begin #20 req = 1; #20 req = 0;

#20 req = 1; #20 req = 0; end

initial begin #60 gnt = 1; #20 gnt = 0;

#60 gnt = 1; #20 gnt = 0; end

initial begin #20 check = 1; #20 check = 0;

#20 check = 1; #20 check = 0; end

initial repeat (15) #10 clk = ~clk;

endmodule

@70: PASS

@130: FAIL

Page 175: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

164

評価が真(true)であればパスします。次のク

ロックが存在しない場合もパスします。

nexttime [constant_expression]

property_expr constant_expression で示すクロック後に式が

真(true)と評価されればパスします。クロッ

クが存在しない場合、評価の結論を出せない

為、パスとなります。

s_nexttime property_expr 次のクロックが存在して式が真と評価されれば

パスします。それ以外は、failになります。

s_nexttime [constant_expression]

property_expr constant_expression で示すクロック後に式が

真(true)と評価されればパスします。クロッ

クが存在しなければ、failになります。

例 12-20

request 信号が連続して三回 true になり、1 クロック後に grant が true になればパスします。それ

以外は、failになります。

実行結果は以下の様になります。結果が示す様に vacuous passはありません。

module test;

bit clk, request, grant;

default clocking cb @(posedge clk); endclocking

property p;

request [*3] #=# grant;

endproperty

assert property (p)

$display("@%0t: PASS",$time);

else $display("@%0t: FAIL",$time);

initial repeat(13) #10 clk = ~clk;

initial begin

#20 request = 1;

#60 request = 0;

end

initial begin

#80 grant = 1;

end

endmodule

@10: FAIL

@90: PASS

@90: FAIL

@90: FAIL

@90: FAIL

@110: FAIL

@130: FAIL

Page 176: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

165

次の例は興味深い例です。例は followed-by #-# オペレータと always オペレータを使用していま

す。例では

always !reset

が成り立つ事を要求しています。常に成り立つか否かは結論が出ません。たとえ、シミュレーシ

ョンが終了しても上記の条件が常に成立するかどうかを立証する事は出来ません。確実に言える

事は、「シミュレーション実行中に条件が成立しない状況が発生しなかった」という事です。そ

の意味で、この種の always は weak always と呼ばれます。以下の例では、fail しなかった場合

PASS とプリントされていますが weakの意味での passとして理解して下さい。

例 12-21

実行結果は以下の様になります。

module test;

bit clk, done, reset;

default clocking cb @(posedge clk); endclocking

property p;

##[0:5] done #-# always !reset;

endproperty

assert property (p)

$display("@%0t: PASS",$time);

else $display("@%0t: FAIL",$time);

initial repeat(13) #10 clk = ~clk;

initial begin

#40 done = 1;

#20 done = 0;

end

initial begin

#20 reset = 1;

#20 reset = 0;

end

endmodule

Page 177: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

166

ダイアグラムではパスが vacuous passとして解釈されています。

例 12-22

この例では、s_always を使用します。strong プロパーティなので条件が絶対的に成り立たなけれ

ばなりません。s_always の評価中にシミュレーションが終了する場合、結論は fail となります。

この点が、weak alwaysと異なる所です。

実行結果は以下の様になります。

@130: PASS

@130: PASS

@130: PASS

#-I Simulation completed at time 130 ticks

module test;

bit clk, a;

default clocking cb @(posedge clk); endclocking

property p;

s_always [2:3] a;

endproperty

assert property (p)

$display("@%3t: PASS",$time);

else $display("@%3t: FAIL",$time);

initial repeat(11) #10 clk = ~clk;

initial begin

#60 a = 1;

end

endmodule

Page 178: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

167

ダイアグラムを見ると時間切れで failした状況を確認する事が出来ます。

例 12-23

この例は、nexttime property_expr です。次のクロック・ティックがあれば式の評価で結論を出し

ます。次のクロック・ティックが無い場合には、結論を出せないので「fail ではないの意味のパ

ス」と結論を出します。

実行結果は以下の様になります。時刻 100のパスは、時間切れの意味でのパスです。

@ 50: FAIL

@ 90: PASS

@110: PASS

@110: FAIL

@110: FAIL

@110: FAIL

module test;

bit clk, a;

default clocking cb @(posedge clk); endclocking

property p;

nexttime a;

endproperty

assert property (p)

$display("@%3t: PASS",$time);

else $display("@%3t: FAIL",$time);

initial repeat(10) #10 clk = ~clk;

initial begin

#20 a = 1;

#60 a = 0;

end

endmodule

Page 179: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

168

ダイアグラムを見ると、時間切れのパスが出ている事を確認する事が出来ます。

例 12-24

実行結果は以下の様になります。

ダイアグラムにより時間切れのパスを確認する事が出来ます。

@ 30: PASS

@ 50: PASS

@ 70: PASS

@ 90: FAIL

@100: PASS

#-I Simulation completed at time 100 ticks

module test;

bit clk, a;

default clocking cb @(posedge clk); endclocking

property p;

nexttime [2] a;

endproperty

assert property (p)

$display("@%3t: PASS",$time);

else $display("@%3t: FAIL",$time);

initial repeat(10) #10 clk = ~clk;

initial begin

#40 a = 1;

#40 a = 0;

end

endmodule

@ 50: PASS

@ 70: PASS

@ 90: FAIL

@100: PASS

@100: PASS

#-I Simulation completed at time 100 ticks

Page 180: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

169

例 12-25

実行結果は以下の様になります。

ダイアグラムのより、時間切れの failを確認する事が出来ます。

module test;

bit clk, a;

default clocking cb @(posedge clk); endclocking

property p;

s_nexttime a;

endproperty

assert property (p)

$display("@%3t: PASS",$time);

else $display("@%3t: FAIL",$time);

initial repeat(10) #10 clk = ~clk;

initial begin

#20 a = 1;

#60 a = 0;

end

endmodule

@ 30: PASS

@ 50: PASS

@ 70: PASS

@ 90: FAIL

@100: FAIL

#-I Simulation completed at time 100 ticks

Page 181: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

170

例 12-26

実行結果は以下の様になります。

ダイアグラムにより時間切れの failを確認する事が出来ます。

module test;

bit clk, a;

default clocking cb @(posedge clk); endclocking

property p;

s_nexttime [2] a;

endproperty

assert property (p)

$display("@%3t: PASS",$time);

else $display("@%3t: FAIL",$time);

initial repeat(10) #10 clk = ~clk;

initial begin

#40 a = 1;

#40 a = 0;

end

endmodule

@ 50: PASS

@ 70: PASS

@ 90: FAIL

@100: FAIL

@100: FAIL

#-I Simulation completed at time 100 ticks

Page 182: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

171

その他のプロパーティの詳細を割愛します。アサーションに関する専門書をお読み下さい。一方、

これまで説明したシーケンスの機能によりアサーションの概念を十分に把握する事が出来ます。

最初は、シーケンスのオペレータに慣れる事が必要だと思います。

Page 183: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

172

13 チェッカー(Checkers)

13.1 概要

簡単に言えば、チェッカーは検証機能を秩序良く纏める為のコンテイナーです。例えば、アサー

ションはプロパーティとシーケンスから構成されますが、それらが至る所に散乱している状態は

望ましくありません。チェッカーはそれらの道具を纏めるだけでなく、必要な環境を備える事が

出来ます。

チェッカーは以下のスコープ内に定義する事が出来ます。

module

interface

program

checker

package

generate

コンパイル・ユニット($unit)

チェッカーには以下の様な機能を含む事が出来ます。

並列型アサーション

チェッカー

カバレッジ(covergroups)定義

default clocking

プロシージャ(initial、always、always_comb、always_latch、always_ff、final)

13.2 チェッカー・インスタンス

チェッカーを使用するにはインスタンスを作ります。インスタンスはアサーションを使用する事

が出来る場所であればどこでも作れます。チェッカー・インスタンスをプロシージャ内に作る事

が出来ます。或いは、モジュール・インスタンスの様にモジュール内にチェッカー・インスタン

スを置く事も出来ます。但し、チェッカー・インスタンスは reactive regionで実行します。

例 13-1

checker mutex(logic [31:0] sig,event clock,output bit failure);

assert property (@clock $onehot0(sig) )

failure = 1'b0;

else

failure = 1'b1;

endchecker : mutex

module test;

logic [31:0] bus;

logic res;

bit clk;

mutex check_bus(bus,posedge clk,res);

always @(posedge clk)

scan <= res;

initial $monitor("@%0t: scan=%b",$time,scan);

initial repeat (10) #10 clk = ~clk;

initial begin #20 bus = 1; #40 bus = 3; #20 bus = 0; end

endmodule

Page 184: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

173

このチェッカーは排他制御の確認をする為に、$onehot0 を使用しています。時刻 60 ticks で

bus==3 となる為、違反が起こります。それ以外の時には正常です。

違反を検知する時刻は 70 ticksです。チェッカーmutex は、時刻 70 の時に failure に 1’b1 を

セットします。然し、チェッカーは reactive region で実行している為、モジュール test 内の

scan 信号には値の変化が伝わりません。scan は前のクロック・イベントにおける failure の

値を示しています。従って、以下の様な結果を得ます。

チェッカー・インスタンスをプロシージャで使用する事が出来ます。

例 13-2

実行すると以下の様な結果を得ます。

時刻 50で state==1’b1となりますが、その値は st として時刻 70でプリントされます。

@30: scan=0

@90: scan=1

checker ex1(x,y,event clock,output logic state);

assert property (@clock x ##1 y)

state = 1;

else

state = 0;

endchecker

module test;

logic a, b, st;

bit clk;

always @(posedge clk) begin

ex1 C1(a,b,posedge clk,st);

end

always @(posedge clk)

$display("@%0t st=%b",$time,st);

initial begin #20 a = 1; #40 a = 0; end

initial begin #40 b = 1; end

initial repeat (10) #10 clk = ~clk;

endmodule

@10 st=x

@30 st=0

@50 st=0

@70 st=1

@90 st=0

Page 185: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

174

14 制約によるランダム・スティムラスの生成

14.1 概要

SystemVerilogには、効率よく、且つ、効果的にランダム・スティムラスを生成する機能がありま

す。制約を付けてランダム・スティムラスを生成する事により、目的に即したテスト・データを

確実に準備する事が出来ます。

生成の仕方は直接的で明確です。テスト・データに乱数発生の情報を付加するだけで準備が終了

します。後は、乱数を発生すべきタイミングを選び乱数を発生させます。例えば、次の様にして

パケットを準備します。

クラスには乱数を発生する関数 randomize()が定義されているので、次の様にして乱数を発生す

る事が出来ます。

関数 randomize()は addr 及び data に自動的に乱数を割り当てます。一方、state には乱数発

生情報が付加されていない為、乱数は割り当てられません。

この例では制約を付けていない為、意味のないテスト・データが生成される可能性があります。

そこで、次の様にして制約を追加する事が出来ます。

この制約により addr は常に 4の倍数となる様に乱数が割り当てられます。data は 32ビットな

ので、制約なしで乱数を発生させても余り意味がありません。然し、どの様な制約を定義するか

はテスト・ケースに依存する可能性があります。この様な状況に於いては、クラスの特性を利用

する方法が得策です。即ち、クラスの継承をして制約を追加します。

クラスの継承なので、small_packet_t には制約 boundary_condition も有効になっていま

す。実は、もう少し一般的にする事が出来ます。small 以外に、medium、及び、large に備える事

で応用が広くなります。例えば、次の様にします。

class packet_t;

rand bit [15:0] addr;

rand bit [31:0] data;

int unsigned state;

endclass

packet_t packet;

packet = new;

...

assert( packet.randomize() );

class packet_t;

rand bit [15:0] addr;

rand bit [31:0] data;

int unsigned state;

constraint boundary_condition { addr[1:0] == 2’b00; }

endclass

class small_packet_t extends packet_t;

constraint small_data { data inside { [0:128], [512:1024] }; }

endclass

Page 186: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

175

この例では、テスト・ケースに従って、data の値の範囲を設定しています。テスト・ケースは 3

種類あります。data の値はテストケースに依存する為、先ずテスト・ケースをランダムに定め、

次に dataをランダムに決定しています。この依存関係を

solve test_size before data;

で表現しています。test_size と data を同時に決定するのではなく、先ず test_size を決

定しています。

この様にしてテスト・データを効果的に準備する事が出来ます。SystemVerilogには多くの制約機

能があります。それらの機能を組み合わせてテスト・データのカバレッジを向上する事が出来ま

す。

14.2 ランダム変数(random variables)

ランダム変数は rand、又は、randc の修飾子を付けて宣言します。これらの修飾子をアレイ変数

にも適用する事が出来ます。

ダイナミック・アレイをランダム変数に定義すると、アレイ・サイズもランダムに決定されます。

アレイ・サイズに制約を設定しないと膨大なアレイが生成されて、殆どシミュレーションが完了

しない状況に陥ります。必ず、アレイ・サイズに制約を設定する事が必要です。

14.2.1 rand修飾子

単純に乱数割り当てる為の宣言です。例えば、

rand bit [7:0] size;

と定義すると、size には 0から 255の間の数がランダムに割り当てられます。

14.2.2 randc修飾子

random-cyclicの意味の修飾子です。詰まり、ランダムに順列を作ります。例えば、

randc bit [1:0] state

と定義すると、randomizer は初期の順列、例えば、

0312

を作り、 randomize()の呼び出しに対して値を順に引き渡します。最後の 2 を渡すと、次に

randomize()が呼ばれると、また新たな順列を作成して、同様の事を繰り返します。

typedef enum { SMALL, MEDIUM, LARGE } test_size_e;

class simple_packet_t extends packet_t;

rand test_size_e test_size;

constraint addr_selection {

solve test_size before data;

test_size == SMALL -> data inside { [0:32] };

test_size == MEDIUM -> data inside { [30000:32000] };

test_size == LARGE -> data inside { [100000:200000] };

}

endclass

Page 187: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

176

例 14-1

実行結果は以下の様になります。ランダム変数 stateの最初の順列は

2013

です。二番目の順列は、

1302

です。

14.3 制約(constraints)

単に乱数を発生するだけでは意味のあるテスト・データを作成する事は出来ません。制約を付け

る事が必要になります。但し、複雑過ぎる制約を与えると、制約ソルバーに負担がかかりシミュ

レーションのパフォーマンスが低下します。検証目的に即した適切な制約を設定する事が必要で

す。制約のシンタックスは以下様になっています。

キーワード constraint の後に制約名称(constraint_identifier)を記します。そして、{} の中に制

約を列挙します。ここで、制約名称は必須です。乱数発生機能を一時的にオフにしたりする制御

にこの名称を使用する事が出来ます。

class sample_t;

rand bit [7:0] size;

randc bit [1:0] state;

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

sample.randomize();

$display("size=%3d state=%0d",

sample.size,sample.state);

end

end

endmodule

size=168 state=2

size=118 state=0

size=193 state=1

size=252 state=3

size= 31 state=1

size=100 state=3

size= 70 state=0

size=230 state=2

[ static ] constraint constraint_identifier constraint_block

constraint_block ::= { { constraint_block_item } }

Page 188: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

177

制約には多くの機能がありますが、細かいシンタックスを説明するよりも、例を使用して学ぶ方

が入門書としては適切なアプローチだと思います。以下では例を中心にして制約の持つ機能を理

解します。

14.3.1 insideオペレータ

このオペレータは以前にも出てきましたが、ここでは乱数発生の制約として使用します。 inside

オペレータの左辺に式を書き、右辺に値域を {} の中に記述します。{} の中には個別に値を書

くか、又は、区間を指定して値を指定します。例えば、{ 1, 2, [10:20] }の様に指定します。

特徴的なのは、値域として変数を指定する事が出来る事です。例えば、

{ a, [b: b*2] }

の様に値のリストを定義する事が出来ます。但し、定数の値域と異なり、制約ソルバーにはより

難易度の高い問題となる事を理解しておく必要があります。即ち、a、及び、b に関して適切な

制約を与えないと、ソルバーが問題を解けない可能性もあります。

例 14-2

制約を与えてランダム変数 size の値域を制限しています。この例では、定数で値域を構成して

います。実行結果は以下の様になります。

例 14-3

この例では値域をランダム変数で構成しています。前例よりも複雑な制約となっています。

class constant_sample_t;

rand byte unsigned size;

constraint C

{

size inside { 2, 4, 8, [20:24], [100:108] };

}

endclass

module test;

constant_sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

sample.randomize();

$display("size=%0d", sample.size);

end

end

endmodule

size=101

size=107

size=23

size=107

size=2

size=23

size=101

size=106

Page 189: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

178

これを実行すると以下の様な結果を得ます。a==c になっているケースはありません。この問題

を解くのは難しい事が分かります。

アレイを使用すると、値域に値を指定する事を避ける事が出来ます。非常に便利な記述方式です。

例 14-4

class sample_t;

rand byte unsigned a, b, c;

constraint C

{

a inside { 2, 4, 8, [b:b*2], c };

}

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 10; i++ ) begin

assert( sample.randomize() );

$display("a=%4d b=%4d c=%4d",

sample.a,sample.b,sample.c);

end

end

endmodule

a= 170 b= 93 c= 164

a= 0 b= 0 c= 118

a= 132 b= 104 c= 3

a= 66 b= 42 c= 86

a= 35 b= 19 c= 21

a= 214 b= 212 c= 6

a= 53 b= 40 c= 202

a= 57 b= 34 c= 63

a= 70 b= 55 c= 144

a= 213 b= 145 c= 98

class sample_t;

int fibonacci[] = '{ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 };

rand int fib;

constraint C { fib inside fibonacci; }

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

$display("fib=%d",sample.fib);

end

end

endmodule

Page 190: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

179

これを実行すると以下の様な結果を得ます。

14.3.2 distオペレータ

乱数が出現する頻度を制御する為のオペレータです。inside オペレータでは、指定されている値

は平等に選択される可能性があります。時として、ある数は他の数よりも多く出現して欲しい場

合があります。その様な状況に於いて使用するオペレータです。

dist オペレータは inside オペレータと殆ど同じシンタックスです。違いは、値の後に重みを定義

する部分にあります。シンタックスを示すと以下の様になります。

例えば、次の様にして制約を記述します。

:= は重さ(weight)を割り当てます。区間に属する値にそれぞれ同じ重さが割り当てられます。

一行目の[1:3]のそれぞれ 1~3 には重さ 20 が割り当てられます。従って、a==0には割合 10/70

が割り当てられます。a==1 には割合 20/70が割り当てられます。

:/ は重さを分配します。0 :/ 20 は一つの数字に重さ 20 を割り当てます。[1:3] :/ 30 は三つの数

全体に重さ 30 を割り当てます。従って、b==0 には割合 20/50 が割り当てられます。また、b==1

には割合 10/50が割り当てられます。

制約を纏めると以下の様になります。

値 割合 値 割合

a == 0 10/70 b == 0 20/50

a == 1 20/70 b == 1 10/50

a == 2 20/70 b == 2 10/50

a == 3 20/70 b == 3 10/50

insideオペレータは、値に対する割合が全て同じである特別なケーとして考える事が出来ます。

fib= 3

fib= 34

fib= 0

fib= 1

fib= 13

fib= 3

fib= 1

fib= 1

dist_item ::= value_range [ dist_weight ]

dist_weight ::=

:= expression

| :/ expression

a dist { 0 := 10, [1:3] := 20 };

b dist { 0 :/ 20, [1:3] :/ = 30 };

Page 191: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

180

例 14-5

理論的な割合は以の様になります。

値 割合 値 割合

a == 0 40/220 b == 0 40/100

a == 1 60/220 b == 1 20/100

a == 2 60/220 b == 2 20/100

a == 3 60/220 b == 3 20/100

実行すると以下の様な結果を得ます。

14.3.3 uniqueオペレータ

同じ値を割り当てられない様にする為の制約です。正式なシンタックスは以下の様になります。

具体的には、次の様に使用します。

この場合、a、b、c には異なった値が設定される様に乱数を割り当てます。

class sample_t;

rand int a, b;

constraint C

{

a dist { 0 := 40, [1:3] := 60 };

b dist { 0 :/ 40, [1:3] :/ 60 };

}

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

$display("a=%0d b=%0d",sample.a,sample.b);

end

end

endmodule

a=1 b=3

a=2 b=3

a=0 b=3

a=1 b=3

a=1 b=2

a=1 b=0

a=3 b=3

a=1 b=0

uniqueness_constraint ::= unique { open_range_list }

rand byte a, b, c;

constraint different_abc { unique { a, b, c }; }

Page 192: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

181

例 14-6

実行結果は以下の様になります。

14.3.4 implication(->)

ある条件が成立した場合に満たすべき制約を与える為のオペレータです。正式なシンタックスは

以下の様になっています。

expression が真であれば、右側の制約を満たさなければなりません。但し、expression が

偽の場合には、右側の制約は don’t careになります。

具体的には、次の様に使用します。

a == b -> c > 100;

これは、もし a == b であれば、c > 100 でなければならない事を意味します。但し、a !=

b の場合には、cに関する制約はありません。

class sample_t;

rand bit[3:0] a[5], b, c;

constraint C

{

unique { a[2], a[3], b, c };

}

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

$display("a[0]=%3d a[1]=%3d a[2]=%3d a[3]=%3d a[4]=%3d b=%3d c=%3d",

sample.a[0],sample.a[1],sample.a[2],sample.a[3],

sample.a[4],sample.b,sample.c);

end

end

endmodule

a[0]= 14 a[1]= 4 a[2]= 0 a[3]= 8 a[4]= 1 b= 10 c= 2

a[0]= 11 a[1]= 10 a[2]= 7 a[3]= 5 a[4]= 4 b= 2 c= 8

a[0]= 13 a[1]= 4 a[2]= 7 a[3]= 13 a[4]= 4 b= 8 c= 6

a[0]= 1 a[1]= 15 a[2]= 8 a[3]= 11 a[4]= 8 b= 4 c= 14

a[0]= 10 a[1]= 13 a[2]= 2 a[3]= 12 a[4]= 13 b= 11 c= 15

a[0]= 10 a[1]= 9 a[2]= 6 a[3]= 11 a[4]= 3 b= 5 c= 2

a[0]= 3 a[1]= 0 a[2]= 6 a[3]= 8 a[4]= 14 b= 9 c= 1

a[0]= 10 a[1]= 2 a[2]= 3 a[3]= 6 a[4]= 13 b= 1 c= 7

expression –> constraint_set

Page 193: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

182

例 14-7

実行結果は以下の様になります。

14.3.5 foreach

アレイ要素に乱数を発生する時、foreach文を使用してアレイ要素に制約を定義する事が出来ます。

正式なシンタックスは以下の様になっています。

ビヘイビア記述で使用する foreach 文と同じ様な構造を持っています。例えば、次の様に使用し

ます。

class sample_t;

rand bit [3:0] a, b;

constraint C

{

a < 5 -> a < b;

}

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

$display("a=%3d b=%3d",sample.a,sample.b);

end

end

endmodule

a= 10 b= 2

a= 14 b= 12

a= 5 b= 10

a= 13 b= 13

a= 0 b= 7

a= 12 b= 15

a= 1 b= 12

a= 12 b= 11

foreach ( ps_or_hierarchical_array_identifier [ loop_variables ] )

constraint_set

loop_variables ::= [ index_variable_identifier ]

{ , [ index_variable_identifier ] }

rand bit[15:0] addr[5];

constraint C

{

foreach (addr[i])

addr[i][1:0] == 2'b00;

}

Page 194: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

183

全てのアレイ要素は 4 の倍数に設定されます。この例ではアレイの大きさが固定されていますが、

foreach文をダイナミック・アレイ、associative arrays、キュー等にも適用する事が出来ます。

例 14-8

ダイナミック・アレイに関する例です。制約 C1 でアレイ・サイズを決定しています。非常に大

事な制約です。

制約 C2 でアレイ要素の制約をしています。制約 C2 はアレイ要素を上昇順にソートする様に制

限をしています。

実行結果は以下の様になります。

次にアレイ・サイズが固定されている例を示します。

class sample_t;

rand bit signed [7:0] ar[];

constraint C1

{

ar.size inside { [1:5] };

}

constraint C2

{

foreach (ar[i])

(i < ar.size-1) -> ar[i+1] > ar[i];

}

function void print();

$write("size=%3d, ",ar.size());

foreach(ar[i])

$write("ar[%1d]=%4d ",i,ar[i]);

$display;

endfunction

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

sample.print();

end

end

endmodule

size= 1, ar[0]= 56

size= 2, ar[0]= 57 ar[1]= 127

size= 1, ar[0]= 18

size= 5, ar[0]= 84 ar[1]= 86 ar[2]= 101 ar[3]= 102 ar[4]= 106

size= 3, ar[0]= 17 ar[1]= 60 ar[2]= 94

size= 1, ar[0]= 149

size= 4, ar[0]= 83 ar[1]= 94 ar[2]= 105 ar[3]= 118

size= 1, ar[0]= 0

Page 195: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

184

例 14-9

実行結果は以下の様になります。

14.3.6 乱数決定順序(solve a before b)

ランダム変数同士に依存関係がある場合には、乱数決定順序を規定する事が出来ます。一般に、

依存関係がある場合、順序規定が必要になります。規定をしないと、ソルバーが問題を解く事が

出来ない場合が生じます。正式なシンタックスは以下の様になっています。

例えば、次の様にして使用します。

class sample_t;

rand shortint A[8];

constraint C

{

foreach (A[i])

A[i] inside { [i*3:i*3+2] };

}

function void print();

foreach(A[i])

$write("A[%0d]=%3d ",i,A[i]);

$display();

endfunction

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

sample.print;

end

end

endmodule

A[0]= 1 A[1]= 5 A[2]= 8 A[3]=11 A[4]=13 A[5]=16 A[6]=19 A[7]=23

A[0]= 1 A[1]= 4 A[2]= 6 A[3]=11 A[4]=13 A[5]=15 A[6]=19 A[7]=23

A[0]= 2 A[1]= 4 A[2]= 7 A[3]=11 A[4]=12 A[5]=16 A[6]=19 A[7]=21

A[0]= 2 A[1]= 3 A[2]= 8 A[3]= 9 A[4]=12 A[5]=15 A[6]=19 A[7]=23

A[0]= 2 A[1]= 3 A[2]= 8 A[3]= 9 A[4]=12 A[5]=15 A[6]=19 A[7]=21

A[0]= 0 A[1]= 3 A[2]= 8 A[3]= 9 A[4]=14 A[5]=17 A[6]=19 A[7]=21

A[0]= 1 A[1]= 4 A[2]= 8 A[3]=10 A[4]=12 A[5]=15 A[6]=18 A[7]=21

A[0]= 0 A[1]= 5 A[2]= 7 A[3]=10 A[4]=12 A[5]=17 A[6]=18 A[7]=23

solve solve_before_list before solve_before_list ;

solve_before_list ::= solve_before_primary { , solve_before_primary }

solve_before_primary ::= [ implicit_class_handle . | class_scope ]

hierarchical_identifier select

solve a before b;

Page 196: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

185

例 14-10

この例では、変数 d は変数 s に依存しています。もし、同時に値を決定しようとすると d に関

する制約を解けない場合が存在します。解けたとしても、多大の計算時間が必要です。効率良い

乱数発生をする為には、決定順序を規定する方法は効果的です。実行結果は以下の様になります。

14.4 乱数発生関数

クラスで使用する事が出来る乱数発生に関するメソッドには以下の関数があります。

関数 意味

virtual function int randomize(); 乱数発生に成功すると 1 を戻します。失敗

すると 0を戻します。

function void pre_randomize(); randomize を 呼 び 出 す と 、 最 初 に

pre_randomize が呼び出されます。ここで初

期値設定等をする事が出来ます。virtual 関

数ではありませんが、virtual 関数の様に動

作します。

function void post_randomize(); randomize が乱数発生を終了すると自動的

にこの関数を呼び出します。ここで後処理を

する事が出来ます。virtual 関数ではありま

せんが、virtual関数の様に動作します。

class sample_t;

rand bit s;

rand bit [31:0] d;

constraint C1 { solve s before d; }

constraint C2 { s -> d == 0; }

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert( sample.randomize() );

$display("s=%b d=%10d",sample.s,sample.d);

end

end

endmodule

s=1 d= 0

s=0 d=4090006777

s=1 d= 0

s=0 d=2432002085

s=1 d= 0

s=1 d= 0

s=0 d=3338683523

s=1 d= 0

Page 197: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

186

例 14-11

pre_randomize()、及び、post_randomize()が毎回呼び出されている事を確認する事が出

来ます。

実行結果は以下の様になります。

14.5 実行時に制約を定義する方法(in-line constraints)

制約を実行時に定義(追加)する事が出来ます。その為には、with クローズを使用します。with

クローズ内でクラスのメンバーを直接参照す事が出来ます。

class sample_t;

int tries;

rand shortint value;

constraint C

{

value inside { [tries:tries*3] };

}

function void pre_randomize;

$display("tries=%0d",++tries);

endfunction

function void post_randomize;

$display("value=%0d",value);

endfunction

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 8; i++ ) begin

assert ( sample.randomize() );

end

end

endmodule

tries=1

value=1

tries=2

value=6

tries=3

value=7

tries=4

value=11

tries=5

value=10

tries=6

value=18

tries=7

value=17

tries=8

value=19

Page 198: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

187

例 14-12

前半では、 a+b+c==32 の制約だけですが、後半では (a < b) && (b < c) の制約を追加し

ています。クラスの外からメンバーを直接参照できるのは強力な機能です。実行結果は以下の様

になります。

14.6 ランダム変数の制御

rand_mode メソッドを使用してランダム変数を active、又は、inactiveにする事が出来ます。

メソッド 意味

task object[.random_variable]::

rand_mode( bit on_off ); ランダム変数を active 、又は、

inactive にします。1 を指定すると

activeになります。

.random_variable を省略すると全

ての変数に適用されます。

function int object.random_variable::

rand_mode(); ランダム変数の状態を戻します。

active であれば 1 を inactive であれば

0を戻します。

class sample_t;

rand bit [7:0] a, b, c;

constraint C { a + b + c == 32; }

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 4; i++ ) begin

assert( sample.randomize() );

$display("a=%2d b=%2d c=%2d",

sample.a,sample.b,sample.c);

end

$display("-------------------------");

for( int i = 0; i < 4; i++ ) begin

assert( sample.randomize()

with { (a < b) && (b < c); } );

$display("a=%2d b=%2d c=%2d",

sample.a,sample.b,sample.c);

end

end

endmodule

a=21 b= 4 c= 7

a= 0 b=15 c=17

a= 4 b=23 c= 5

a= 5 b=17 c=10

-------------------------

a= 0 b=12 c=20

a= 0 b=11 c=21

a= 0 b= 5 c=27

a= 7 b=10 c=15

Page 199: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

188

例 14-13

実行結果は以下の様になります。

class sample_t;

rand bit [7:0] a, b;

function void post_randomize;

$display("a=%3d b=%3d",a,b);

endfunction

endclass

module test;

sample_t sample = new;

initial begin

$display("--- all active");

for( int i = 0; i < 4; i++ ) begin

assert( sample.randomize() );

end

$display("--- all inactive");

sample.rand_mode(0);

for( int i = 0; i < 2; i++ ) begin

assert( sample.randomize() );

end

$display("--- only a is active");

sample.a.rand_mode(1);

for( int i = 0; i < 4; i++ ) begin

assert( sample.randomize() );

end

$display("--- all active");

sample.rand_mode(1);

for( int i = 0; i < 4; i++ ) begin

assert( sample.randomize() );

end

end

endmodule

--- all active

a=168 b= 36

a=231 b=207

a= 93 b=164

a=214 b=210

--- all inactive

a=214 b=210

a=214 b=210

--- only a is active

a= 0 b=210

a=118 b=210

--- all active

a=193 b=252

a= 31 b=184

a=198 b=176

a= 45 b=134

Page 200: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

189

14.7 制約の制御

ランダム変数の制御と同様に制約を active、又は、inactiveにする事が出来ます。

メソッド 意味

task object[.constraint_identifier]::

constraint_mode( bit on_off ); 制約を active、又は、inactive にしま

す。1 を指定すると active になりま

す。

.constraint_identifier を省略すると全

ての変数に適用されます。

function int

object.constraint_identifier::

constraint_mode();

制約の状態を戻します。active であれ

ば 1 を inactive であれば 0 を戻しま

す。

例 14-14

実行結果は以下の様になります。

class sample_t;

rand bit [7:0] a, b, c;

constraint C1 { a + b + c == 32; }

constraint C2 { (a < b) && (b < c);}

function void post_randomize;

$display("a=%2d b=%2d c=%2d",a,b,c);

endfunction

endclass

module test;

sample_t sample = new;

initial begin

$display("--- all active");

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize() );

end

$display("--- all inactive");

sample.constraint_mode(0);

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize() );

end

$display("--- ony C1 is active");

sample.C1.constraint_mode(1);

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize() );

end

end

endmodule

Page 201: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

190

14.8 randomize関数によるランダム変数の制御

rand_mode メソッドを使わずにランダム変数を active、又は、inactive にする制御をする事が出来

ます。randomizeを呼ぶ出す際に、引数として与えた変数だけがランダム変数となります。

例 14-15

--- all active

a= 0 b= 15 c= 17

a= 0 b= 12 c= 20

a= 0 b= 11 c= 21

--- all inactive

a= 3 b= 40 c=202

a=157 b= 86 c=222

a=122 b=190 c=169

--- only C1 is active

a= 4 b= 8 c= 20

a= 7 b= 18 c= 7

a= 18 b= 12 c= 2

class packet_t;

rand bit [15:0] addr;

rand bit [31:0] data;

endclass

...

packet_t packet = new;

packet.randomize(); // addr 及び dataはランダム変数

packet.randomize(addr); // addr のみがランダム変数

class sample_t;

rand bit [15:0] addr;

rand bit [31:0] data;

function void post_randomize;

$display("addr=%h data=%h",addr,data);

endfunction

endclass

module test;

sample_t sample = new;

initial begin

$display("--- all active");

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize() );

end

$display("--- only addr is active");

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize(addr) );

end

$display("--- only data is active");

for( int i = 0; i < 3; i++ ) begin

assert( sample.randomize(data) );

end

end

endmodule

Page 202: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

191

実行結果は以下の様になります。

14.9 std::randomize()

クラスを用いずに乱数を発生する事が出来ます。std::randomize()関数の引数として与えると、乱

数が割り当てられます。制約条件を withクローズで指定する事が出来ます。

例 14-16

実行結果は以下の様になります。

14.10 システム関数とメソッド

以下の様な関数があります。単に乱数を発生するだけであれば、クラスを定義せずに以下の関数

を呼ぶ事が出来ます。乱数に制約が無い場合にはこれらの方法を利用する方が得策です。

--- all active

addr=f2b5 data=90d4df10

addr=c480 data=0f013967

addr=44b7 data=fc913a8f

--- only addr is active

addr=de22 data=fc913a8f

addr=16e6 data=fc913a8f

addr=3369 data=fc913a8f

--- only data is active

addr=3369 data=a93770ac

addr=3369 data=0c9109d1

addr=3369 data=e91b388d

module test;

bit [7:0] a, b, c;

initial begin

for( int i = 0; i < 3; i++ ) begin

assert( std::randomize(a,b,c));

$display("a=%3d b=%3d c=%3d",a,b,c);

end

$display("-------------------------");

for( int i = 0; i < 3; i++ ) begin

assert (randomize(a,b,c) with { a+b == c; });

$display("a=%3d b=%3d c=%3d",a,b,c);

end

end

endmodule

a= 26 b=141 c= 12

a= 77 b=239 c=116

a=225 b=242 c= 70

-------------------------

a=168 b= 36 c=204

a= 0 b=118 c=118

a= 31 b=184 c=215

Page 203: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

192

メソッド 意味

function int unsigned $urandom

[ (int seed ) ] ; 32 ビットの符号無し整数をランダムに

生成します。seed を与える事も出来ま

す。

function int unsigned $urandom_range

( int unsigned maxval,

int unsigned minval = 0 );

指定した範囲内の整数にある乱数を発

生します。もし maxval < minval であ

れば、両者はスワップされます。例え

ば、$urandom_range(2,10)と

$urandomrange(10,2)は同じです。

function void srandom( int seed ); 乱数発生器のシードを定義します。

function string get_randstate(); 乱数発生器の状態を戻します。

function void set_randstate

( string state ); 乱数発生器の状態をセットします。

例 14-17

$urandom()は単に乱数を生成するだけです。一般に、大きな整数が割り当てられます。

$urandom_range() 関数を使用して、16と 32の間の整数を発生しています。

これらの方法を使うとクラスの定義をする必要が無くて便利です。実行結果は以下の様になりま

す。

module test;

int unsigned ui32;

bit [7:0] value;

bit [3:0] b4;

initial begin

for( int i = 0; i < 4; i++ ) begin

ui32 = $urandom();

b4 = ui32 & 15;

value = $urandom_range(16,32);

$display("ui32=%0d b4=%2d value=%3d",

ui32,b4,value);

end

end

endmodule

ui32=1160842890 b4=10 value= 17

ui32=4088827367 b4= 7 value= 25

ui32=4191218676 b4= 4 value= 16

ui32=2433247010 b4= 2 value= 21

Page 204: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

193

14.11 ストラクチャ

クラスのメンバーにストラクチャが定義されていて、ストラクチャのメンバーに rand/randc 修飾

子が付いていると、ストラクチャのメンバーに乱数が割り当てられます。

例 14-18

実行結果は以下の様になります。

14.12 条件の否定 !(expression inside { set })

inside オペレータは便利なオペレータですが、時には、その否定形が必要な事があります。例え

ば、2 でも 4 でも 8 でも 10 でも 20 でもない二桁の正の整数を求める時、条件式は複雑になりま

す。この様な時、insideオペレータに否定形を使う事が出来ます。一般形は、

!(expression inside { set })

です。否定形を使うと

(a > 0) && (a < 100) && !(a inside { 2, 4, 8, 10, 20 })

の様に書く事が出来ます。

typedef struct { rand int x, y; } point_t;

class sample_t;

rand bit [7:0] a, b;

rand point_t p;

constraint C

{

a < b;

b < 64;

p.x > 0 && p.x < 256;

p.y > 0 && p.y < 256;

}

endclass

module test;

sample_t sample;

initial begin

sample = new;

repeat(5) begin

assert( sample.randomize() );

$display("a=%3d b=%3d p.x=%3d p.y=%3d",

sample.a,sample.b,sample.p.x,sample.p.y);

end

end

endmodule

a= 9 b= 42 p.x=231 p.y=207

a= 8 b= 21 p.x=146 p.y= 20

a= 3 b= 35 p.x=242 p.y=212

a= 39 b= 50 p.x= 87 p.y=223

a= 20 b= 42 p.x= 60 p.y=109

Page 205: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

194

例 14-19

a は 6、11、又は、12の何れかです。実行結果は以下の様になります。

14.13 キューに乱数を発生

キューに対しても乱数を発生する事が出来ます。但し、キューのサイズに関する制約が必要です。

例 14-20

class sample_t;

rand bit[3:0] a, b;

constraint C { !(a inside { [0:5], [7:10], [13:15] }); }

endclass

module test;

sample_t sample = new;

initial begin

repeat( 8 ) begin

assert( sample.randomize() );

$display("a=%3d b=%3d",sample.a,sample.b);

end

end

endmodule

a= 12 b= 10

a= 12 b= 5

a= 11 b= 15

a= 11 b= 12

a= 6 b= 2

a= 6 b= 0

a= 11 b= 4

a= 12 b= 15

class sample_t;

rand byte q[$];

rand bit [2:0] size;

constraint C { q.size == size; size > 0; }

function void post_randomize;

$write("size=%0d q[0..%0d]:",size,q.size-1);

foreach(q[i])

$write(" %4d",q[i]);

$display;

endfunction

endclass

module test;

sample_t sample = new;

initial begin

repeat (8) assert( sample.randomize() );

end

endmodule

Page 206: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

195

実行結果は以下の様になります。

14.14 チェッカーとしての制約(in-line constraint checker)

クラスにランダム変数が定義さていなければ randomize() 関数は乱数を生成しませんが、制約の

チェックは必ず行われます。この機能を利用するとデータの無矛盾性を達成する事が出来ます。

例 14-21

size=5 q[0..4]: -92 103 79 -35 36

size=6 q[0..5]: 82 -128 -10 65 124 -97

size=6 q[0..5]: 70 48 -83 6 12 -24

size=1 q[0..0]: -28

size=2 q[0..1]: 102 57

size=7 q[0..6]: 34 -86 -42 -95 18 -109 -107

size=4 q[0..3]: 80 7 13 -115

size=7 q[0..6]: 84 -122 -36 -125 -88 74 29

class sample_t;

bit [3:0] a, b;

constraint C

{

a[1:0] == 2'b00;

(b < 6) && (b > 0);

}

endclass

module test;

sample_t sample = new;

initial begin

sample.b = 1;

check_members(); // ok

sample.a = 12;

check_members(); // ok

sample.a = 7;

check_members(); // error

sample.a = 12;

sample.b = 8;

check_members(); // error

end

function void check_members();

if( sample.randomize() )

$display("PASS: a=%2d b=%2d",sample.a,sample.b);

else

$display("FAIL: a=%2d b=%2d",sample.a,sample.b);

endfunction

endmodule

Page 207: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

196

この例のクラスのメンバーにはランダム変数はありませんが、制約を与えています。a は 4 の倍

数で、bは 1から 5の間の整数でなければなりません。randomize関数を呼ぶと制約を満たすかチ

ェックする事が出来ます。実行結果は以下の様になります。

クラスがランダム変数を含む場合でも制約をチェッカーとして利用する事が出来ます。この必要

性は度々起こります。例えば、randomize() を呼び出して乱数を割り当てた後に、一部のランダム

変数の値を変更したとします。新しい値の状態が制約を満たしている事を確認しなければなりま

せん。どの様にしたら確認できるのでしょうか?randomize()を再び呼ぶと新たな乱数が発生して

しまいます。

解答は randomize(null)と呼び出す事です。パラメータとして null を渡すと、randomizer はランダ

ム変数をノンランダム変数として扱います。これにより、制約チェッカーとしての機能だけを遂

行します。この機能を次の例で確認します。

例 14-22

この例では、乱数を割り当てた後にランダム変数の値を変更して、制約を満たしているかをチェ

ックしています。その為に、sample.randomize(null)で呼び出しをしています。呼び出して

も、乱数は割り当てられずに制約のチェックだけが行われている事が分かります。

PASS: a= 0 b= 1

PASS: a=12 b= 1

FAIL: a= 7 b= 1

FAIL: a=12 b= 8

class sample_t;

rand bit [3:0] a, b;

constraint C

{

a[1:0] == 2'b00;

(b < 6) && (b > 0);

}

endclass

module test;

sample_t sample = new;

initial begin

sample.randomize();

$display("a=%2d b=%2d",sample.a,sample.b);

sample.a = 2;

if( sample.randomize(null) )

$display("PASS: a=%2d b=%2d",sample.a,sample.b);

else

$display("FAIL: a=%2d b=%2d",sample.a,sample.b);

end

endmodule

Page 208: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

197

実行結果は以下の様になります。

14.15 制約をテストケース毎に指定する方法

制約をクラスの外部に定義する事が出来ます。この機能を使用する事により、制約条件がテスト

ケース毎に異なる場合に効率良く作業を進める事が出来ます。手順は以下の様になります。

制約名称だけを与えた空の制約を宣言する。

クラスの外部で制約の内容を定義する。

以下に例を示します。

例 14-23

クラス内に制約 setup_size が宣言されていますが、内容が定義されていません。その内容は

テストベンチ testで定義されています。

実行結果は以下の様になります。

a= 8 b= 1

FAIL: a= 2 b= 1

class sample_t;

rand bit [7:0] array_size;

rand bit [7:0] array[];

constraint size_constraint { array.size == array_size; }

constraint setup_size;

function void print;

$write("array_size=%0d array.size=%0d:",

array_size, array.size);

foreach(array[i])

$write(" %3d",array[i]);

$display;

endfunction

endclass

module test;

sample_t sample = new;

constraint sample_t::setup_size { array_size inside {[1:8]}; }

initial begin

repeat (10) begin

assert (sample.randomize() );

sample.print();

end

end

endmodule

Page 209: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

198

14.16 randcase

SystemVerilogは、case 文をランダム化した機能 randcase 文を持っています。この文はランダムに

case-itemを選択して実行します。一般形式は以下の様になっています。

expression は 0以上の整数値を示す式で、case-itemが選択される重み(weight)を定義します。

全ての case-itemの重みの和で case-itemの重みを割った値がその case-itemが選択される確率とな

ります。例えば、

最初の case-itemが選択される確率は 3/8=0.375となります。重みが 0の case-itemは決して実行さ

れません。expressionは定数でなくても構いません。

例 14-24

実行結果は以下の様になります。

array_size=8 array.size=8: 242 225 116 239 77 12 141 26

array_size=6 array.size=6: 181 84 64 39 85 70

array_size=1 array.size=1: 61

array_size=8 array.size=8: 204 1 120 132 215 15 229 236

array_size=7 array.size=7: 28 14 54 255 232 76 194

array_size=5 array.size=5: 41 7 177 134 96

array_size=1 array.size=1: 240

array_size=8 array.size=8: 171 116 87 70 80 4 47 45

array_size=6 array.size=6: 211 74 114 223 67 184

array_size=2 array.size=2: 141 63

randcase randcase_item { randcase_item } endcase

randcase_item ::= expression : statement_or_null

randcase

3 : x = 1;

1 : x = 2;

4 : x = 3;

endcase

module test;

initial begin

for( int i = 0; i < 8; i++ ) begin

randcase

1: test_case1();

1: test_case2();

8: test_case3();

endcase

end

end

task test_case1();$display("test_case1");endtask

task test_case2();$display("test_case2");endtask

task test_case3();$display("test_case3");endtask

endmodule

Page 210: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

199

例 14-25

実行結果は以下の様になります。

test_case2

test_case3

test_case1

test_case3

test_case3

test_case3

test_case3

test_case3

module test;

byte a, b;

initial begin

a = $urandom_range(1,5);

b = $urandom_range(1,10);

for( int i = 0; i < 8; i++ ) begin

randcase

a: test_case1();

b: test_case2();

a+b: test_case3();

endcase

end

end

task test_case1();$display("test_case1");endtask

task test_case2();$display("test_case2");endtask

task test_case3();$display("test_case3");endtask

endmodule

test_case1

test_case2

test_case3

test_case2

test_case3

test_case3

test_case2

test_case2

Page 211: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

200

15 ファンクショナル・カバレッジ(functional coverage)

ファンクショナル・カバレッジは仕様のどれだけの部分が検査されたかを示す指標です。デザイ

ンを検証する意味ではなく、寧ろ、検査者、又は、検査計画の進捗度を示します。ゴールは、勿

論、100%のカバレッジです。

ファンクショナル・カバレッジは仕様を基にして確認をします。確認を漏れなく、重複が無い様

に進める必要があります。例えば、

rand bit [2:0] port;

に於いて、port には乱数が割り当てられます。検査で port が 0 から 7 の全ての値をとればカ

バレッジは 100%となりますが、一部の値を取らない場合、乱数発生に制約を追加して取り得る

値を拡張しなければなりません。

SystemVerilog ファンクショナル・カバレッジでは、信号値だけでなく信号の値の遷移

(transitions)の計測も行う事ができます。

SystemVerilogでは、ファンクショナル・カバレッジの仕様をソース・コード中に記述する事が出

来ます。しかも、記述されたカバレッジ仕様はシミュレータにより実行されます。

15.1 カバレッジ・モデルの定義(covergroup)

15.1.1 covergroupの定義

SystemVeriog covergroup はカバレッジ仕様を定義する為の構文です。実際には、クラスと同じ様

にデータ・タイプです。covergroupには以下の機能を含む事が出来ます。

カバレッジ情報を取得するタイミングを示すクロック・イベント

カバー・ポイント

クロス・カバレッジ

カバレッジ・オプション

covergroup を、package、module、program、interface、checker、及び、classの中で使用する事が出

来ます。classの中に covergroup を定義する方法が最も一般的です。しかも、それは最も便利な方

法です。例えば、次の様にして covergroupを定義します。

この例では、port のカバレッジ、及び、data と port の対のカバレッジを収集しています。

クラス内に covergroupを定義すると、その名称を持つ変数(この例では cov)が自動的に確保さ

class sample_t;

bit [31:0] data;

bit [2:0] port;

covergroup cov;

coverpoint port;

dataXport: cross data, port;

endgroup

function new;

cov = new;

endfunction

endclass

Page 212: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

201

れます。コンストラクタ newで cov にオブジェクトを割り当てています。covergroupを使用する

為には、必ず、オブジェクトを割り当てなければなりません。

data、及び、port には rand/randcが付いていないので、テストベンチ内で、それらに値を割り

当てる事を前提としています。そして、その際に、カバレッジ情報を収集します。

port が coverpointとして指定されているので、port がとる値の頻度がシミュレータにより計測

されます。頻度の計算にビンが使用されます。クロス・カバレッジ(dataXport)も同様です。

data と port の値の対の出現頻度が計測されます。

15.1.2 covergroupへの引数

covergroup の定義に引数を添える事が出来ます。これにより、covergroup は汎用化します。例え

ば、次の様に引数を指定します。

cov を new する時に、low、及び、high に対して値をパスしなければなります。例えば、

new(0,100)の様にして使用します。

15.1.3 サンプリングのタイミング指定

covergroup の定義にサンプリングのタイミング指定する事が出来ます。例えば、次の様に指定し

ます。

イベント@sw が起こる時にカバレッジ情報が収集されます。従って、テストベンチでは特別なサ

ンプリング動作を記述する必要はありません。

同じシミュレーション時刻 T に於いてイベントが複数回起こる場合、複数回カバレッジの計算が

行われます。時刻 T に於いて複数回イベントが起こっても唯一回のカバレッジ計算で済ませる為

には、covergroup の type_option.strobe に 1 を設定しなければなりません。このオプションの標準

値は 0になっています。

15.1.4 サンプリング関数(sample)

covergroup の定義にサンプリングのタイミングを指定しない場合、テストベンチでサンプリング

を明確に記述しなければなりません。次の様にサンプリングは sample()を呼び出して行います。

covergroup cov(int low,int high);

coverpoint a

{

bins b[] ={ [low:high] };

}

endgroup

covergroup cov @sw;

coverpoint a

{

bins fb[] = (1=>2=>3=>4), (6=>7);

ignore_bins ignore_vals = (2=>3);

bins others = default sequence;

}

endgroup

Page 213: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

202

ここで使用している sampleはビルトイン(built-in)関数でパラメータを引き渡すことが出来ませ

ん。パラメータを引き渡す為には、sample を定義し直す必要があります。この機能により、

covergroupでアクセスする事が出来ない変数のカバレッジを収集する事が出来ます。

例えば、次の様にして sample関数を定義します。

15.1.5 簡単な使用例

以上の機能の幾つかを使用した例を示します。

例 15-1

port のカバレッジを計測しています。単なる例を示す目的なので、意味のない記述になってい

ます。シミュレーションが終了するとカバレッジ情報がデータベースに記録されます。ファイル

形式はベンダーにより異なります。以下は、総括情報の例です。

covergroup cov(int low,int high);

coverpoint a { bins b[] ={ [low:high] }; }

endgroup

...

cov cg1 = new(0,100);

...

cg1.sample();

covergroup cov with function sample(bit a,logic [1:0] x);

coverpoint a;

coverpoint x;

endgroup

module test;

class sample_t;

rand bit [31:0] data;

rand bit [2:0] port;

endclass

sample_t sample = new;

covergroup coverport_t;

coverpoint sample.port;

endgroup

initial begin

coverport_t cp = new;

repeat (32) begin

assert(sample.randomize());

cp.sample();

end

end

endmodule

Page 214: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

203

データベースには詳細な情報が書き込まれます。例えば、port==0 が何回発生したか等の情報

が記録されます。

この例の様な簡単な場合には意味がありませんが、もっと複雑なケースでは GUIベースのカバレ

ッジ表示機能は有効な手段となります。以下の GUIの一例を示します。これは、データベースの

情報を表示した例です。

15.2 クラス内の covergroup

クラス内に covergroupを定義すると以下の利点があります。

covergroupの名称を持つハンドルが自動的に確保される。

簡単にクラス・プロパーティのカバレッジを収集する事が出来る。

クラス内に定義された covergroup は embedded covergroup と呼ばれます。ハンドルに covergroup

のインスタンスを割り当てる為には、コンストラクタ内で行います。それ以外の場所で割り当て

る事は出来ません。

CoverGroupType: test::coverport_t

Cumulative Coverage: 100.00%

Goal: 100.00%

Comment: ""

MergeInstances: 0

coverpoint coverage goal

------------------------------------

cp$1 100.00% 100.00%

------------------------------------

Page 215: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

204

例 15-2

クラス内に covergroup cg を定義しているので、コンパイラーが自動的にハンドル cg を確保し

ます。コンストラクタは、ハンドルに covergroup のインスタンスを割り当てなければなりません。

この例では、プロパーティ sw の値が変化するイベントが発生すると自動的に a、及び、b のカ

バレッジを収集します。テストベンチで cg.sample()を呼び出す必要はありません。

プロパーティ a、及び、b はそれぞれ 16 個の値を取り得る為、カバレッジは共に 2/16 となりま

す。

シミュレーション時刻 0 に於いて 2 回イベントが起こり 2 回カバレッジ計算が行われている事に

注意して下さい。

上記の例と異なり、同じシミュレーション時刻には唯一回のカバレッジ計算で済ませる為には、

以下の例の様にします。

class packet_t;

bit [3:0] a, b;

bit sw;

covergroup cg @sw;

coverpoint a;

coverpoint b;

endgroup

function new;

cg = new;

endfunction

endclass

module test;

packet_t packet = new;

initial begin

packet.a = 1; packet.b = 2; packet.sw = 1;

packet.a = 3; packet.b = 4; packet.sw = 0;

end

endmodule

coverpoint coverage goal

------------------------------------

a 12.50% 100.00%

b 12.50% 100.00%

------------------------------------

Page 216: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

205

例 15-3

type_option.strobe を ON にしています。この設定により、シミュレーション時刻 T の最後に一回

だけカバレッジ計算をします。この場合には以下の様な結果になります。

同じクラス内に複数の covergroupを定義する事も出来ます。次の例を参考にして下さい。

class packet_t;

bit [3:0] a, b;

bit sw;

covergroup cg @sw;

type_option.strobe = 1;

coverpoint a;

coverpoint b;

endgroup

function new;

cg = new;

endfunction

endclass

module test;

packet_t packet = new;

initial begin

packet.a = 1; packet.b = 2; packet.sw = 1;

packet.a = 3; packet.b = 4; packet.sw = 0;

end

endmodule

coverpoint coverage goal

------------------------------------

a 6.25% 100.00%

b 6.25% 100.00%

------------------------------------

class packet_t;

bit [3:0] a, b;

bit sw, clk;

covergroup cg1 @sw;

coverpoint a;

endgroup

covergroup cg2 @(posedge clk);

coverpoint b;

endgroup

function new;

cg1 = new;

cg2 = new;

endfunction

endclass

Page 217: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

206

15.3 カバー・ポイントの定義(coverage points)

カバレッジの基本はカバー・ポイントです。カバー・ポイントの定義は、やや複雑なシンタック

スを持ちます。細かいシンタックスには触れずに代表的なカバー・ポイントの定義法をマスター

する事を目的とします。先ず、全体的なシンタックスは以下の様になります。

[ [ data_type_or_implicit ] cover_point_identifier : ]

coverpoint expression [ iff ( expression ) ] bins_or_empty

簡単に言えば、coverpoint 文でカバー・ポイントを定義します。カバー・ポイントには名称

(cover_point_identifier)を定義する事が出来ます。省略すると変数名称がカバー・ポイ

ント名称になります。

カバレッジの収集を制御する為には、iff ( expression )を指定します。条件が成立する時

のみカバレッジが収集されます。

bins_or_empty でカバレッジのビンを定義します。ビンはカバレッジを計算する為のグルーピ

ングを意味します。例えば、32ビットの整数型変数のカバレッジを求める際、全ての整数値のカ

バレッジを求める事は意味が無いと同時に不可能です。寧ろ、32ビットの整数値を大、中、小の

グループに分けてカバレッジを求める方が効率的です。ビンはその様なグルーピングを可能にし

ます。ビンの定義が省略されるとシミュレータは自動的にビンを定義します。それらのビンを

auto binsと言います。autoビンの数をカバレッジ・オプション auto_bin_maxで制御する事が出来

ます。

15.3.1 ビンの定義

15.3.1.1 固定数のビン

固定数のビンを定義する為には、例えば、以下の様にします。

各ビンに値を一様に分配します。与えられた値の数は 13 個です。ビンは、value[0]、

value[1]、value[2]、value[3]の 4 個になります。13/4 個の数を順に value[0]から割当

てます。余った値を最後のビンに入れます。この宣言により、4 つのビンが以下の様に定義され

ます。

a が値 2を取ると、value[0]の計測値は 1 だけ加算されます。a が他の値を取る時も同様です。

15.3.1.2 それぞれの値にビンを確保する方法

それぞれの値に対してビンを定義するには以下の様にします。

covergroup cg;

coverpoint a

{

bins value[4] = { [1:10], 1, 4, 7 };

}

endgroup

value[0] ::= { 1, 2, 3 }

value[1] ::= { 4, 5, 6 }

value[2] ::= { 7, 8, 9 }

value[3] ::= { 10, 1, 4, 7 }

Page 218: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

207

この宣言により、10個のビンが以下の様に定義されます。

15.3.1.3 唯一つのビン

複数の値に対して唯一つのビンを定義する為には以下の様にします。

15.3.1.4 autoビン

ビンの定義を省略するとシミュレータが自動的にビンを定義します。各値に対して一つのビンを

割り当てる様にビンを定義します。

例えば、3 ビットの変数に対しては、8 個のビンが割り当てられます。ビン数の最大値は

auto_bin_max(標準値は 64)を超えない様に定義されます。例えば、32ビットの変数に対しては

64個のビンが定義されます。

次の記述ではビンの指定が無いので、autoビンが割り当てられます。変数 a は 4ビットなので、

auto[0]から auto[15]までの 16個のビンが作成されます。

15.3.1.5 defaultビン

定義したビンに属しない値を受け取る為のビンです。このビンはカバレッジ計算の対象外になり

ます。以下の様にして定義します。

covergroup cg;

coverpoint a

{

bins value[] = { [1:10], 1, 4, 7 };

}

endgroup

value[0] ::= { 1 }

value[1] ::= { 2 }

...

value[9] ::= { 10 }

covergroup cg;

coverpoint a

{

bins value = { [1:10], [12:15] };

}

endgroup

class sample_t;

bit [3:0] a;

covergroup cg;

coverpoint a;

endgroup

function new;

cg = new;

endfunction

endclass

Page 219: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

208

a が 4、6、又は、7であるとビン othersに割り当てられます。

15.3.1.6 illegal_bins

信号値としてあり得ない値が出現した場合の計測を illegal_bins 文で指定します。このビンに記録

された値はカバレッジから除外されます。更に、実行時のエラー・メッセージの対象になります。

即ち、ilegal_bins に集計される値が出現した場合、エラー・メッセージが発行されます。例えば、

次の様に定義します。

15.3.1.7 ignore_bins

カバレッジの対象外の値をこの文で指定します。このビンに登録される値はカバレッジから除外

されます。エラー・メッセージも発行されません。

15.3.2 カバー・ポイントの使用

以上の機能の幾つかの例を示します。

class sample_t;

bit [3:0] a;

covergroup cg;

coverpoint a

{

bins zero = { 0 };

bins low = { [1:3], 5 };

bins high[] = { [8:$] };

bins others = default;

}

endgroup

function new;

cg = new;

endfunction

endclass

covergroup cg;

coverpoint b

{

illegal_bins bad_value = {1,2,3};

illegal_bins bad_transition = (4=>5=>6);

}

endgroup

covergroup cg;

coverpoint a

{

ignore_bins ignore_vals = {7,8};

ignore_bins ignore_trans = (1=>3=>5);

}

endgroup

Page 220: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

209

例 15-4

変数 a のカバレッジを計算する例です。a は 3 ビットなので、8 個の値を取り得ます。従って 8

個のビンが必要ですが、ここではビン数を 4 に制限しています。それらのビンは、[0:1]、[2:3]、

[4:5]、[6:7] に対応します。

区間[0:1]は ignore_binsにより削除されます。区間[4:5]、及び、[6:7]は ignore_binsの一部を含みま

すが値 4、及び、7を計測し得る為、これらの区間は有効です。

実際に a がとる値は、2、4、及び、7 ですが有効な区間の全てで値が収集されているので 100%

カバレッジを実現しています。

module test;

bit [2:0] a;

covergroup cov;

a: coverpoint a

{

option.auto_bin_max = 4;

ignore_bins ig = { [0:1], [5:6] };

}

endgroup

cov cg = new;

initial begin

a = 2;

cg.sample();

a = 4;

cg.sample();

a = 7;

cg.sample();

end

endmodule

COVERPOINT "a";

COVERAGE 100.00 3 3;

GOAL 100;

WEIGHT 1;

COMMENT "";

ATLEAST 1;

ABIN "auto" 1 1 "{[2:3]}";

ABIN "auto" 2 1 "{[4:5]}";

ABIN "auto" 3 1 "{[6:7]}";

ENDCOVERPOINT

Page 221: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

210

例 15-5

この例では、covergroupの外で定義されている値のカバレッジを求めています。

例 15-6

module test;

bit s;

covergroup cov with function sample(bit a,logic [1:0] x);

coverpoint a;

coverpoint x;

endgroup

initial begin

cov cg;

cg = new;

s = 0; cg.sample(s,0);

s = 1; cg.sample(s,1);

s = 0; cg.sample(s,2);

s = 1; cg.sample(s,3);

end

endmodule

interface intf(input bit clk);

logic [7:0] adr;

covergroup cov @(posedge clk);

coverpoint adr { bins x[4] = { [0:255] }; }

endgroup

cov cg;

task setupCg();

cg = new;

endtask

endinterface

module test;

bit clk;

intf INTF(clk);

initial INTF.setupCg();

initial repeat (10) #10 clk = ~clk;

initial begin

INTF.adr = 0;

#20 INTF.adr = 100;

#20 INTF.adr = 160;

#20 INTF.adr = 200;

end

endmodule

Page 222: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

211

interface 内の covergroup の例です。クロック・イベントに同期してカバレッジを計測しています。

covergroup のインスタンスが生成されない限りカバレッジ情報は収集されません。従って、次の

命令は本質的に必要です。

INTF.setupCg();

15.3.3 信号値の遷移(transitions)

信号値の状態の変化を=>で記します。例えば、

value1 => value2

は連続する二つのサンプリングで信号値が value1 から value2 に変化する事を意味します。

変化する状態を幾つか連続する事が出来ます。例えば、

value1 => value2 => value3 => value4 => value5

の様に変遷を記述する事が出来ます。変遷のリストを両辺に指定する事が出来ます。例えば、

1, 2 => 3, 4

は、

(1=>3), (1=>4), (2=>3), (2=>4)

と同じです。繰り返し記号[*m]も使えます。例えば、

1 [*5]

1 => 1 => 1 => 1 => 1

と同じです。アサーションと同様に gotoオペレータ[->m]が存在します。例えば、

1 [->3]

...=>1...=>1...=>1

と同じです。ここで、...には値 1が現れない事とします。同様に、不連続な繰り返し[=m]も存

在します。

1 [=3] => 2

...=>1...=>1...=>1...=>2

と同じです。

信号値の遷移をビンの定義に指定する事が出来ます。例えば、次の様に信号値の変化をビンに定

義する事が出来ます。

Page 223: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

212

single_binには以下の遷移が含まれます。

4=>5=>6, 7=>11, 8=>11, 9=>11, 10=>11, 7=>12, 8=>12, 9=>12, 10=>12

array_binは次の様に定義されます。

array_bin[4=>5=>6], array_bin[7=>11], ...,array_bin[10=>12]

例 15-7

実行結果は以下の様になります。

bit clk;

bit [3:0] a;

covergroup cov @(posedge clk);

coverpoint a

{

bins single_bin = (4 => 5 => 6), ([7:9],10 => 11,12);

bins array_bin[] = (4 => 5 => 6), ([7:9],10 => 11,12);

}

endgroup

module test;

logic [3:0] a;

bit clk;

covergroup cov @(posedge clk);

coverpoint a

{

bins single_bin = (4 => 5 => 6), ([7:9],10 => 11,12);

bins array_bin[] = (4 => 5 => 6), ([7:9],10 => 11,12);

}

endgroup

initial begin

cov cg;

cg = new;

end

initial repeat (23) #10 clk = ~clk;

initial begin

a = 4; #20 a = 5; #20 a = 6; #20 a = 7; #20 a = 11;

#20 a = 8; #20 a = 12; #20 a = 4; #20 a = 5; #20 a = 8;

#20 a = 11;

end

endmodule

Page 224: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

213

15.4 クロス・カバレッジ(cross coverage)

クロス・カバレッジはカバー・ポイントの組のカバレッジです。組になるカバー・ポイントの数

に制限はありません。組である為、ビンの数は大きくなる傾向があります。例えば、

カバー・ポイント a 及び b のビン数はそれぞれ 8ですが、クロス・カバレッジ aBYb のビン数は

64になります。

クロス・カバレッジのシンタックスは多少複雑ですが、一般形式は以下の様になります。

cross_body でクロス・カバレッジの定義をします。定義を省略すると、可能な全ての組み合

わせの対が構成されます。cross_body のシンタックスは複雑ですが、簡単な定義法もありま

す。

binsof を使用すると比較的簡単にビンを定義する事が出来ます。binsof のシンタックスは以

下の様になっています。

COVERPOINT "a";

COVERAGE 50.00 5 10;

GOAL 100;

WEIGHT 1;

COMMENT "";

ATLEAST 1;

TBIN "single_bin" 4;

LBIN "array_bin" 0 1 "(4=>5=>6)";

LBIN "array_bin" 1 1 "(7=>11)";

LBIN "array_bin" 2 1 "(8=>11)";

LBIN "array_bin" 3 0 "(9=>11)";

LBIN "array_bin" 4 0 "(10=>11)";

LBIN "array_bin" 5 0 "(7=>12)";

LBIN "array_bin" 6 1 "(8=>12)";

LBIN "array_bin" 7 0 "(9=>12)";

LBIN "array_bin" 8 0 "(10=>12)";

ENDCOVERPOINT

class sample_t;

bit [2:0] a, b;

covergroup cg;

aBYb: cross a,b;

endgroup

function new;

cg = new;

endfunction

endclass

[ cross_identifier : ]

cross list_of_cross_items [ iff ( expression ) ] cross_body

cross_body ::= { { cross_body_item ; } } | ;

select_condition ::=

binsof ( bins_expression ) [ intersect { covergroup_range_list } ]

Page 225: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

214

例えば、次の様に定義します。

クロス・プロダクト x1は次の 4つのビンから構成されます。

ビン i_tenは i==10を含む i のビンから次の様に構成されます。

この他に自動的にビンを定義するので、x2は次の 3つのビンから構成されます。

例 15-8

結果を纏めると以下の様になります。

covergroup cov;

coverpoint i { bins i[] = { [10:11] }; }

coverpoint j { bins j[] = { [10:11] }; }

x1: cross i, j;

x2: cross i, j {

bins i_ten = binsof(i) intersect {10};

}

endgroup

<i[0],j[0]>

<i[0],j[1]>

<i[1],j[0]>

<i[1],j[1]>

<i[0],j[0]>

<i[0],j[1]>

i_ten

<i[1],j[0]>

<i[1],j[1]>

module test;

int i, j;

covergroup cov;

coverpoint i { bins i[] = { [10:11] }; }

coverpoint j { bins j[] = { [10:11] }; }

x1: cross i, j;

x2: cross i, j {

bins i_ten = binsof(i) intersect {10};

}

endgroup

initial begin

cov cg = new;

i = 10;

j = 10;

cg.sample;

i = 11;

cg.sample;

j = 11;

cg.sample;

end

endmodule

Page 226: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

215

x1 x2

<i[0],j[0]> covered i_ten covered

<i[0],j[1]>

<i[1],j[0]> covered <i[1],j[0]> covered

<i[1],j[1]> covered <i[1],j[1]> covered

例 15-9

カバー・ポイントと異なり、クロス・カバレッジ 100% を達成するのは容易ではありません。こ

こでは、その一例を示します。

a は 16 通り、b は 8 通りの数を取るので、クロス・カバレッジは 128 個のビンから構成されます。

この例では、a及び bにランダムに数を与える事を 256回繰り返しています。a及び bには十分過

coverpoint coverage goal

------------------------------------

i 100.00% 100.00%

j 100.00% 100.00%

------------------------------------

cross coverage goal

------------------------------------

x1 75.00% 100.00%

x2 100.00% 100.00%

class sample_t;

rand bit [3:0] a;

rand bit [2:0] b;

covergroup cg;

coverpoint a;

coverpoint b;

aBYb: cross a, b;

endgroup

function new;

cg = new;

endfunction

endclass

module test;

sample_t sample = new;

initial begin

for( int i = 0; i < 256; i++ ) begin

sample.a = $urandom_range(0,15);

sample.b = $urandom_range(0,7);

sample.cg.sample();

end

end

endmodule

Page 227: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

216

ぎる試行回数ですが、クロス・カバレッジには不十分です。カバレッジのサマリは以下の様にな

ります。

上記のテキスト・ファイルを見れば明らかですが、GUIでは更に明確になります。

クロス・カバレッジは 87.5%です。カバレッジ・データベースの詳細を調べてみると以下の様に

なっています。

CoverGroupType: sample_t::cg

Cumulative Coverage: 95.83%

Goal: 100.00%

Comment: ""

MergeInstances: 0

coverpoint coverage goal

------------------------------------

a 100.00% 100.00%

b 100.00% 100.00%

------------------------------------

cross coverage goal

------------------------------------

aBYb 87.50% 100.00%

------------------------------------

Page 228: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

217

112個のクロス・ビンしかカバーされていません。

15.5 カバレッジ・オプション

オプションは、covergroup、coverpoint、及び、cross のそれぞれに対してあります。そして、イン

スタンス毎のオプションとインスタンスに依存しないオプションがあります。後者のオプション

を type_optionとして参照します。詳細に関しては、原書を参照して下さい。

CROSS "aBYb";

CROSSITEM "a" "b";

COVERAGE 87.50 112 128;

GOAL 100;

WEIGHT 1;

COMMENT "";

ATLEAST 1;

CBIN "auto<auto[0],auto[0]>" 5;

CBIN "auto<auto[0],auto[1]>" 6;

CBIN "auto<auto[0],auto[2]>" 2;

CBIN "auto<auto[0],auto[4]>" 2;

CBIN "auto<auto[0],auto[5]>" 2;

CBIN "auto<auto[0],auto[6]>" 4;

CBIN "auto<auto[0],auto[7]>" 2;

CBIN "auto<auto[1],auto[0]>" 3;

...

Page 229: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

218

16 システム・タスクとシステム関数

SystemVerilogには多くのシステム・タスクと関数があります。ここでは、部分的に紹介をします。

16.1 値変換(conversion functions)

関数 機能

integer $rtoi ( real_val ) 実数値を integer に変換します。但し、少数

部分を切り捨てます。

real $itor ( int_val ) integer 型を実数型に変換します。

[63:0] $realtobits ( real_val ) 実数値を 64ビットの vectorに変換します。

real $bitstoreal ( bit_val ) $realtobits で変換されたビット vector を実数

値に戻します。

[31:0] $shortrealtobits ( shortreal_val ) shortreal 型の値を 32 ビットの vector に変換

します。

shortreal $bitstoshortreal ( bit_val ) $shortrealtobits で変換された 32 ビットの

vector を shortreal型の値に戻します。

例 16-1

実行結果は以下の様になります。

16.2 情報取得関数

関数 機能

$typename ( expression )

| $typename ( data_type )

値の示す型を文字列として戻します。

$bits ( expression )

| $bits ( data_type )

値を表現する為に必要なビット数を戻しま

す。例えば、 byte v;

に対して、$bits(v)は 8を戻します。

$isunbounded ( constant_expression ) 値が$であれば 1を戻します。例えば、

parameter P = $;

に対して、$isunbounded(P)は 1 を戻しま

typedef union { int ival;real rval; } ir_t;

module test;

parameter PI = 3.14;

ir_t ir;

initial begin

ir.ival = $rtoi(PI);

$display("ir.ival=%0d",ir.ival);

ir.rval = $itor(ir.ival)/2;

$display("ir.rval=%g",ir.rval);

end

endmodule

ir.ival=3

ir.rval=1.5

Page 230: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

219

す。

array_query_function ::=

array_dimension_function

( array_identifier

[ , dimension_expression ] )

| array_dimension_function ( data_type

[ , dimension_expression ] )

| array_dimensions_function

( array_identifier )

| array_dimensions_function ( data_type )

array_dimensions_function ::=

$dimensions

| $unpacked_dimensions

array_dimension_function ::=

$left

| $right

| $low

| $high

| $increment

| $size

dimension_expression ::= expression

$dimensioonsは全ての次元数を戻します。

$unpacked_dimensions は unpacked アレイ

の次元数を戻します。

$leftは次元の左側を戻します。

$rightは次元の右側を戻します。

$increment は$left>=$right であれば 1 を戻

します。そうでなければ、―1を戻します。

$low は次元の小さい方を戻します。即ち、

$incremen が- 1 であれば、 $left を、

$incremen が 1 であれば、$right を戻しま

す。

$highは次元の大きい方を戻します。

$sizeは$high-$low+1と同じです。

例 16-2

次元は unpacked dimesnionから数え始めます。一番左の次元数は 1です。例えば、

bit [7:0] data[10][20];

に於いて、最初の次元 1 は[0:9]です。次は、次元 2 で[0:19]です。最後に、次元 3 で[7:0]

です。

実行結果は以下の様になります。

module test;

bit [7:0] b;

bit [31:0] ba[10][5];

initial begin

$display("$dimensions(b)=%0d",$dimensions(b));

$display("$dimensions(ba)=%0d",$dimensions(ba));

$display("$unpacked_dimensions(ba)=%0d",

$unpacked_dimensions(ba));

$display("$left(b)=%0d $right(b)=%0d",

$left(b),$right(b));

$display("$left(ba,1)=%0d $right(ba,1)=%0d",

$left(ba,1),$right(ba,1));

end

endmodule

Page 231: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

220

16.3 ビット vectorシステム関数(bit vector system functions)

関数 機能

$countbits ( expression , control_bit { ,

control_bit } )

指定したビット(0、1、x、z)の出現数を戻

します。例えば、

$countbits (expression, '1)は expression に含

まれるビット 1の数を戻します。

$countbits (expression, '1,’0)は expression に

含まれるビット 1、又は、0 の数を戻しま

す。

$countbits (expression, 'x,’z)は expression に

含まれるビット x、又は、zの数を戻します。

$countones ( expression ) $countbits(expression,'1)と同じです。

$onehot ( expression ) $countbits(expression,'1)==1 であれば true

を戻し、そうでなければ false を戻します。

$onehot0 ( expression ) $countbits(expression,'1)<=1 であれば true

を戻し、そうでなければ false を戻します。

$isunknown ( expression ) $countbits(expression,'x,'z)!=0 であれば true

を戻し、そうでなければ false を戻します。

例 16-3

実行結果は以下の様になります。

$dimensions(b)=1

$dimensions(ba)=3

$unpacked_dimensions(ba)=2

$left(b)=7 $right(b)=0

$left(ba,1)=0 $right(ba,1)=9

module test;

logic [3:0] v;

initial begin

v = 'x;

print_countbits();

v = 'z;

print_countbits();

v = '1;

print_countbits();

v = 4'b10xz;

print_countbits();

end

function void print_countbits;

$display(

"v=%b $countbits(v,1)=%0d $countbits(v,'x)=%0d $countbits(v,'1,'0,'x,'z)=%0d",

v, $countbits(v,'1), $countbits(v,'x), $countbits(v,'1,'0,'x,'z) );

endfunction

endmodule

Page 232: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

221

16.4 エラー処理タスク

関数 機能

severity_message_task ::=

fatal_message_task

| nonfatal_message_task

fatal_message_task ::=

$fatal [ ( finish_number

[ , list_of_arguments ] ) ] ;

nonfatal_message_task ::=

severity_task [ ( [ list_of_arguments ] ) ] ;

severity_task ::= $error | $warning | $info

finish_number ::= 0 | 1 | 2

$fatalはシミュレーションを終了します。

list_of_arguments は定数、又は、プリント書

式です。

例 16-4

実行結果は以下の様になります。

v=xxxx $countbits(v,1)=0 $countbits(v,'x)=4 $countbits(v,'1,'0,'x,'z)=4

v=zzzz $countbits(v,1)=0 $countbits(v,'x)=0 $countbits(v,'1,'0,'x,'z)=4

v=1111 $countbits(v,1)=4 $countbits(v,'x)=0 $countbits(v,'1,'0,'x,'z)=4

v=10xz $countbits(v,1)=1 $countbits(v,'x)=1 $countbits(v,'1,'0,'x,'z)=4

class sample_t;

rand bit [15:0] addr;

rand bit [31:0] data;

constraint C { addr[1:0] == 2'b00; }

function void post_randomize;

$display("addr=%h data=%h",addr,data);

endfunction

endclass

module test;

sample_t sample = new;

initial begin

repeat (10)

assert ( sample.randomize() )

else $fatal(0,"randomize failed.");

end

endmodule

addr=9080 data=f3a56d03

addr=0ed8 data=c71d83c8

addr=fbc0 data=44fda954

addr=16e4 data=df1a9c49

addr=a878 data=33e0452c

addr=e804 data=0c9109d1

addr=583c data=65ad4755

addr=ec48 data=ed6da32f

addr=6be0 data=fc50c471

addr=50c8 data=fecb46ea

Page 233: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

222

16.5 $sformatと$sformatf

これらのタスク及び関数は便利なので紹介しておきます。

関数 機能

$sformat ( output_var , format_string

[ , list_of_arguments ] ) ;

$sformat はタスクです。$display システ

ム・タスクと同じです。但し、出力を

output_var にセットします。

string

$sformatf(format_string[,list_of_arguments ] )

$sformatf は文字列を戻すファンクションで

す。$sformat と同じ機能を持ちますが、出

力を戻します。

例 16-5

エラー・メッセージの書式を作る為に、make_message 内で $sformatf が使われています。エ

ラー・メッセージの形式を変更する場合、make_message に変更を加えるだけで済みます。メ

ッセージを出力する個々のコードには影響しません。

16.6 確率分布関数

関数 機能

$random [ ( seed ) ] ランダムに発生した 32 ビットの符号付き整

数を戻します。

乱数発生に使用する seed を指定する事も出来

ます。

16.7 その他のシステム・タスク及びシステム関数

関数 機能

$system ( [ " terminal_command_line " ] ) C/C++の system()を呼び出し、戻り値をその

まま戻します。例えば、

void’($system(“dir *.sv”));

の様にして使用します。

module test;

shortint a, b;

initial begin

assert( std::randomize(a,b) with { a < b; } )

else $display("%s",make_message("randomize failed",

`__FILE__,`__LINE__));

end

function string make_message(string message,string filename,

int line_count);

return $sformatf("%s(L%0d) %s",filename,line_count,message);

endfunction

endmodule

Page 234: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

223

例 16-6

この例では、シミュレーションを実行する際に、現在設定されている作業ディレクトリ名をプリ

ントします。

実行結果は以下の様になります。

module test;

initial begin

void'($system("echo Current Directory is $PWD"));

end

endmodule

Current Directory is /cygdrive/d/Users/Artgraphics/TestData

Page 235: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

224

17 プログラム(programs)

17.1 概要

プログラムはテストベンチの要素でありデザインを記述する為の機能ではありません。モジュー

ルと同じ様な機能を持ちますが、以下の点で大きく異なります。

プログラムはデザイン階層を持つ事が出来ません。例えば、モジュールのインスタンスをプ

ログラム内に置く事は出来ません。

プログラム内では alwaysプロシージャを使用する事は出来ません。

プログラムのロジックは reactive regionで実行します。

プログラム内の全ての initial プロシージャの実行が終了するとそのプログラムは終了します。

17.2 プログラムの制御

プログラムを終了する為には、$exit タスクを使用する事が出来ます。$exit を呼び出すと全ての

initialプロシージャを終了させます。

例 17-1

この例では、$exit の使用法と効果を示します。この例により、$exit がイベント待ちのスレッド

を終了させている事が分かります。

実行結果は以下の様になります。

例 17-2

この例では、programのロジックが reactive regionで実行される事の意義を明確にしたいと思いま

す。トップ・モジュールは以下の様になっています。

program test;

initial begin

fork

#10 $display("@%0t: thread-1 started.",$time);

#50 $display("@%0t: thread-2 started.",$time);

join

end

initial begin

#20 $exit;

end

final begin

$display("@%0t: main completed.",$time);

end

endprogram

@10: thread-1 started.

@20: main completed.

#-I Simulation completed at time 20 ticks

Page 236: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

225

dutと testは以下の様になっています。

トップ・モジュールで request 信号に 1 又は 0 をクロック・イベント毎にセットしています。ノ

ンブロッキング(<=)なので、クロック・イベントが起きた時には、未だ値がセットされていま

せん。従って、dut は常に request==0 を見ています。

一方、 test は program である為、 reactive region で実行します。この region では、

INTF.request <= 1 が実行した後に命令が実行するので、test は常に request==1 を見ま

す。

実行結果は以下の様になります。

interface simple_if(input bit clk);

bit request;

endinterface

module top;

bit clk;

simple_if INTF(clk);

test TEST(INTF);

dut DUT(INTF);

always @(posedge clk) INTF.request <= 1;

always @(negedge clk) INTF.request <= 0;

initial repeat (5) #10 clk = ~clk;

endmodule

program test(simple_if intf);

initial

forever @(posedge intf.clk)

$display("@%0t: test.intf.request=%b",

$time,intf.request);

endprogram

module dut(simple_if intf);

always @(posedge intf.clk)

$display("@%0t: dut.intf.request=%b",$time,intf.request);

endmodule

@10: dut.intf.request=0

@10: test.intf.request=1

@30: dut.intf.request=0

@30: test.intf.request=1

@50: dut.intf.request=0

@50: test.intf.request=1

Page 237: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

226

17.3 シミュレーションの終了

program の実行が終了するとシミュレーションの実行が終了します。たとえトップ・モジュール

がイベント待ちであってもシミュレーションが終了します。次の例は、program の initial プロシ

ージャが終了した時点でシミュレーションが終了する事を示しています。

例 17-3

トップ・モジュールは時刻 100 でメッセージをプリントする予定ですが、この文は実行されずに

シミュレーションが終了します。実行結果は以下の様になります。

module top;

test TEST();

initial begin

$display("@%0t: top started.",$time);

#100 $display("@%0t: top completed.",$time);

end

endmodule

program test;

initial begin

fork

#10 $display("@%0t: thread-1 started.",$time);

#20 $display("@%0t: thread-2 started.",$time);

join

$display("@%0t: all threads completed.",$time);

end

endprogram

@0: top started.

@10: thread-1 started.

@20: thread-2 started.

@20: all threads completed.

#-I Simulation completed at time 20 ticks

Page 238: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

227

18 インターフェース(interfaces)

18.1 概要

SystemVerilogのインターフェースはモジュール間の接続を簡素化する為に作られました。機能的

には、インターフェースはモジュール・ポートを一般化した概念です。

インターフェースは、モジュールと同じ様にインスタンスを作る事が出来ます。そして、インタ

ーフェースのインスタンスをポートして使用し、モジュール間の接続に使用します。インターフ

ェースは幾つもの信号を含む事が出来ます。しかも、それらの信号の向き(input、inout、 output

等)をモジュール毎に変える事が出来ます。この機能は modport により実現されます。モジュー

ル間の接続変更はインターフェース内の定義変更だけで済みます。それぞれのモジュールのポー

ト・リストを変更する必要はありません。

インターフェースには initial、及び、always プロシージャを記述する事が出来ます。信号値の初

期化、及び、プロトコルのチェック等を容易に行なう事が出来ます。以下はインターフェースの

例です。

インターフェースを定義しただけでは動作しないので、トップ・レベルのモジュールにインスタ

ンスを作ります。

dut、及び、testではインターフェースの信号を直接アクセスする事が出来ます。

interface simple_if(input bit clk);

logic [1:0] grant, request;

logic reset;

clocking cb @(posedge clk);

output request;

input grant;

endclocking

modport TEST (output request, reset,input grant,clk);

modport DUT (input request,reset,clk,output grant);

modport MONITOR (input request,grant,reset,clk);

initial begin

grant <= 0;

request <= 0;

reset <= 0;

end

endinterface

module top;

bit clk;

initial forever #10 clk = ~clk;

simple_if INTF(clk);

dut DUT(INTF);

test TEST(INTF);

endmodule

Page 239: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

228

18.2 genericインターフェースに依る接続

インターフェースが明確に定まらない状況、又は、複数のインターフェースが接続される場合、

generic なインターフェースで接続する事が出来ます。先程の例を次の様に書き換える事が出来ま

す。

intf はモジュール test のインスタンスに接続されたインターフェースに置き換わります。こ

れは SystemVerilogコンパイラーの仕事です。

18.3 modport

インターフェースには多くの信号が定義されていますが、一般に、一つのモジュールは一部の信

号にしかアクセスしません。その様な場合、modport を使用して信号へのアクセスを制限します。

例えば、次の様に modportを使用します。

testでは、modport TESTに定義されているポート以外を見る事は出来ません。

18.4 クロッキング・ブロック

modport にクロッキング・ブロックのポートを指定する事が出来ます。例えば、simple_if に次の

様な modportを追加する事が出来ます。

18.5 パラメータ化したインターフェース(parameterized interfaces)

インターフェースにパラメータと追加する事で汎用化する事が出来ます。例えば、simple_if にパ

ラメータを追加すると以下の様になります。

module test(simple_if intf);

initial begin

@(posedge intf.clk) intf.request <= 2'b01;

// ...

end

endmodule

module test(interface intf);

initial begin

@(posedge intf.clk) intf.request <= 2'b01;

// ...

end

endmodule

module test(simple_if.TEST intf);

initial begin

@(posedge intf.clk) intf.request <= 2'b01;

// ...

end

endmodule

modport SYNCTEST (clocking cb);

Page 240: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

229

インターフェースのインスタンスを作る際にビット幅を指定する事が出来ます。

simple_ifはパラメータ化しているので、dut、及び、testは直接 simple_ifを参照する事は出来ませ

ん。次の様に genericな interfaceを使用します。

dut、及び、testは simple_ifのビット幅に合わせて動作します。

interface simple_if #(WIDTH=2) (input bit clk);

logic [WIDTH-1:0] grant, request;

logic reset;

clocking cb @(posedge clk);

output request;

input grant;

endclocking

modport TEST (output request, reset,input grant,clk);

modport DUT (input request,reset,clk,output grant);

modport MONITOR (input request,grant,reset,clk);

initial begin

grant <= 0;

request <= 0;

reset <= 0;

end

endinterface

module top;

bit clk;

initial forever #10 clk = ~clk;

simple_if #(.WIDTH(8)) INTF(clk);

dut DUT(INTF);

test TEST(INTF);

endmodule

module test(interface intf);

initial begin

@(posedge intf.clk) intf.request <= 2'b01;

// ...

end

endmodule

module dut(interface intf);

// ...

endmodule

Page 241: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

230

18.6 virtual インターフェース(virtual interfaces)

virtual インターフェースはインターフェースのインスタンスを示す変数です。いわば、インター

フェース・オブジェクトへのポインターです。このポインターをクラスのハンドルと同じ様に使

用する事が出来ます。クラス内にはインターフェースを定義する事は出来ませんが、クラスは

virtualインターフェースを持つ事が出来ます。

virtual インターフェースは null で初期化される為、使用するまでにインターフェースのインスタ

ンスで初期化しなければなりません。通常は、コンストラクタ newで virtualインターフェースの

初期化をします。例えば、以下の様にします。

例 18-1

virtual インタフェースを使用する例を示します。クラス内にはインターフェースを定義する事が

出来ないので、クラス定義の前にインターフェースの定義が必要です。

class simple_driver;

virtual simple_if vif;

function new(simple_if sif);

vif = sif;

endfunction

endclass

interface simple_if (input bit clk);

logic [1:0] grant, request;

logic reset;

modport TEST (output request, reset,input grant,clk);

modport DUT (input request,reset,clk,output grant);

initial begin

grant <= 0;

request <= 0;

reset <= 0;

end

endinterface

class simple_driver;

virtual simple_if vif;

function new(virtual simple_if sif);

vif = sif;

endfunction

task request;

vif.request <= 2'b01;

endtask

task wait_grant;

wait (vif.grant == 2'b01 );

vif.request = 2'b00;

endtask

endclass

Page 242: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

231

トップ・モジュールは以下の様になっています。

testは以下の様になっています。

dutは次の様になっています。

実行結果は以下の様です。

module top;

bit clk;

simple_if intf(clk);

test TEST(intf);

dut DUT(intf);

initial repeat (10) #10 clk = ~clk;

endmodule

module test(simple_if.TEST intf);

simple_driver driver;

initial begin

driver = new(intf);

@(posedge intf.clk);

driver.request();

driver.wait_grant();

repeat (2) @(posedge intf.clk);

driver.request();

driver.wait_grant();

end

initial $monitor("@%2t: grant=%b",$time,intf.grant);

endmodule

module dut(simple_if.DUT intf);

always @(posedge intf.clk)

if( intf.reset )

intf.request <= 2'b00;

else if( intf.request == 2'b01 )

intf.grant <= 2'b01;

else

intf.grant <= 2'b10;

endmodule

@ 0: grant=00

@10: grant=10

@30: grant=01

@50: grant=10

@90: grant=01

Page 243: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

232

18.7 クロッキング・ブロックの使用例

例 18-2

インターフェースにクロッキング・ブロックが定義されている例を示します([3])。インターフ

ェースは次の様になっています。

トップ・モジュールは以下の様に定義されています。

testは以下の様になっています。

dutは以下の様になっています。

interface simple_if(input bit clk);

logic [1:0] grant, request;

logic rst;

clocking cb @(posedge clk);

output request;

input grant;

endclocking

modport TEST(clocking cb,output rst);

modport DUT(input request,rst,output grant);

endinterface

module top;

bit clk;

always #5 clk = ~clk;

simple_if INTF(clk);

dut DUT(INTF);

test TEST(INTF);

end

endmodule

program test(simple_if.TEST intf);

initial begin

$monitor("@%0t: grant=%h",$time,intf.cb.grant);

#50ns $display("@%0t: test completed.",$time);

$exit;

end

endprogram

Page 244: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

233

実行結果は以下の様です。

dutでは時刻 25に於いて grantに 3を設定していますが、testでは 2をプリントしています。この

理由は次の様に説明されます。

時刻 25 で@(posedge clk)が起こり、dut では grant に 3 を設定しています。その時刻に、test で

grant 信号を見ますが、それはクロッキング・ブロックで定義された cb.grant 信号です。然し、

cb.grantには入力 skewが設定されている為、@(posedge clk)イベントの直前に於ける cb.grant信号

値を参照します。即ち、2です。

time 0 time 5 time 7 time 15 time 17 time 25 time35

dut.grant x x 1 1 2 3 3

test.grant x x x 1 1 2 3

上の表で緑色の列はクロッキング・イベントが発生した時刻の状況を示しています。尚、test に

program を使用していますが、特別な意味はありません。module でも同様の現象が起こります。

但し、moduleでは$exitを使用する事は出来ないので$finishに置き換える必要があります。

module dut(simple_if.DUT intf);

initial begin

#7 intf.grant = 1;

#10 intf.grant = 2;

#8 intf.grant = 3;

end

endmodule

@15: grant=1

@25: grant=2

@35: grant=3

@50: test completed.

#-I Simulation completed at time 50 ticks

Page 245: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

234

19 パッケージ(packages)

19.1 概要

パッケージは共有するリゾース(パラメータ、データ・タイプ、タスク、ファンクション等)の

コンテイナーです。構文としては一番外側に位置します。即ち、他のスコープにパッケージを含

む事は出来ません。

パッケージにはタスク、及び、ファンクションを含む事が出来ますが、initial や always 等のプロ

シージャを含む事は出来ません。

パッケージを個別のファイルに定義した場合、他のファイルでパッケージを参照する為には

`include文を使用します。例えば、次の様にファイルを引用します。

`include “my_package.sv”

パッケージ内に定義されているリゾースを参照する為には、パッケージ名称にスコープ・オペレ

ータ(::)を適用します。例えば、パッケージ Pkg に定義されているパラメータ PI をモジュ

ール内で参照する為には、

$display(“PI=%g”,Pkg::PI);

の様にして参照します。スコープ・オペレータの使用を省略する為には、パッケージを import し

なければなりません。言い換えると、パッケージ内のリゾースを他のスコープから直接見る事は

出来ません。逆に言えば、名称のコンフリクトが無いという利点があります。

importする際、個別に名称を指定する事が出来ます。例えば、

の様にして importする事が出来ます。但し、enumデータ・タイプを importしても、enumラベル

は importされません。enumラベルを個別に importしなければなりません。

個別に import する代わりに、パッケージの全てのメンバーを同時に import する為には ::* を

使用します。例えば、次の様にして使用します。

モジュール test内ではパッケージ Pkgの全ての内容を参照する事が出来ます。

例 19-1

下記のコードはパッケージの例です。パッケージが何度も参照(include される)場合、コンパイ

ラー制御文(`ifndef、及び、`define文)が必要になります。

module test;

import Pkg::ARRAY_SIZE;

import Pkg::setup, Pkg::print;

int elm[];

...

module test;

import Pkg::*;

int elm[];

...

Page 246: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

235

ここで、ファンクション make_format は、幅 w が与えられるとプリント書式 %wd を作ります。

例えば、幅が 4であると書式 %4d が作られます。

参照する側の test の記述は以下の様になります。この test とパッケージ Pkg は別のファイ

ルに定義されています。

setup と print を呼んでいますが、それぞれ Pkg::setup、及び、Pkg::print と同じです。

モジュール test 内のアレイ elm 名称は、パッケージにあるローカルなアレイ名称 elm と一致し

ています。test内で参照している elm は、test内で定義している elm を指します。

`ifndef PKG_H

`define PKG_H

package Pkg;

parameter ARRAY_SIZE = 16;

typedef enum { RED, YELLOW, GREEN } color_e;

function void setup(output int elm[]);

foreach(elm[i])

elm[i] = i+1;

endfunction

function void print(string msg,int width,int elm[]);

string format;

format = make_format(width);

$write("%s:",msg);

foreach(elm[i])

$write(format,elm[i]);

$display;

endfunction

function string make_format(int width);

return $sformatf("%%%0dd",width);

endfunction

endpackage

`endif

`include "Ch19_Pkg.pkg"

module test;

import Pkg::*;

int elm[];

initial begin

elm = new [ARRAY_SIZE];

setup(elm);

print("elm",3,elm);

end

endmodule

Page 247: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

236

パッケージを import しても、ローカル変数(例えば、タスクやファンクションの引数)は test に

は見えません。

実行結果は以下の様になります。

19.2 パッケージ内のリゾースの参照

スコープ・オペレータを使用してパッケージ内の項目を参照する事が出来ます。例えば、

elm = new [Pkg::ARRAY_SIZE];

の様に参照します。スコープ・オペレータの使用を避ける為には、

import Pkg::*;

の様にします。この命令により、パッケージ内の項目が見える様になります。

19.3 パッケージをモジュール・ヘッダで importする方法

パッケージをモジュール内で参照する場合には、モジュール内でパッケージを import しますが、

それが不可能な場合があります。例えば、

に於いて、color_e がモジュール・ヘッダで参照されています。このままではコンパイル・エ

ラーになるので、例えば、次の様にします。

これで、この問題は解決するのですが、また新たな問題が発生します。他のモジュールにも

enumタイプ color_e が見えてしまいます。モジュール m1 だけに見える様にするには、次の様

にします。

この方法に依り、他のモジュールからパッケージの項目を隠す事が出来ます。

19.4 stdパッケージ

SystemVerilog にはビルトイン・パッケージが定義されています。例えば、mailbox や semaphore

はビルトイン・パッケージに定義されています。ビルトイン・パッケージに定義されているデー

タ・タイプを使用する際には、スコープ std::を使用する事が出来ます。例えば、

std::mailbox mb = new;

elm: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

module m1(input color_e,...);

...

endmodule

import Pkg::*;

module m1(input color_e,...);

...

endmodule

module m1 import Pkg::*; (input color_e,...);

...

endmodule

Page 248: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

237

の様にして使用します。名称の矛盾が無ければ、std::を省略する事が出来ます。

stdパッケージには以下の様なクラス、及び、メソッドが定義されています。

クラス又はメソッド 機能

class semaphore;

function new(int keyCount = 0);

function void put(int keyCount = 1);

task get(int keyCount = 1);

function int try_get(int keyCount = 1);

endclass

排他制御用のクラスです。

通常のクラスと同じ様に使用する事ができま

す。

class mailbox

#(type T = dynamic_singular_type) ;

function new(int bound = 0);

function int num();

task put( T message);

function int try_put( T message);

task get( ref T message );

function int try_get( ref T message );

task peek( ref T message );

function int try_peek( ref T message );

endclass

FIFOリストを実現する為のクラスです。

通常のクラスと同じ様に使用する事ができま

す。

function int randomize( ... )

[ with constraint_block ];

乱数発生関数です。

class process;

enum state { FINISHED, RUNNING,

WAITING, SUSPENDED, KILLED };

static function process self();

function state status();

function void kill();

task await();

function void suspend();

function void resume();

endclass

プロセスはクラスとして実現されています。

コンストラクタ new が定義されていない事に

注意して下さい。

例 19-2

module test;

mailbox #(string) mbs;

string data[] = { "bread", "milk", "ham" },

msg;

initial begin

mbs = new;

foreach(data[i])

mbs.put(data[i]);

while( mbs.num() ) begin

mbs.get(msg);

$display("got message: %s",msg);

end

end

endmodule

Page 249: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

238

mailbox は string 型のメッセージを持つ為、mailbox のメソッドを使用する時、型の互換性チェッ

クが行われます。例えば、

mbs.put(100);

はコンパイル時にエラーとなります。実行結果は以下の様になります。

例 19-3

実行結果は以下の様になります。

got message: bread

got message: milk

got message: ham

module test;

process q[$];

initial begin

process p;

$display("@%0t: Initial-1 started.",$time);

p = process::self();

q.push_back(p);

p.suspend();

$display("@%0t: Initial-1 ended.",$time);

end

initial begin

process p;

$display("@%0t: Initial-2 started.",$time);

p = process::self();

q.push_back(p);

p.suspend();

$display("@%0t: Initial-2 ended.",$time);

end

initial begin

#50;

foreach(q[i])

q[i].resume();

end

endmodule

@0: Initial-1 started.

@0: Initial-2 started.

@50: Initial-1 ended.

@50: Initial-2 ended.

#-I Simulation completed at time 50 ticks

Page 250: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

239

次の例はモジュール内に定義されている変数に乱数を割り当てます。但し、単に割り当てるので

は無く、制約を満たす様に乱数を割り当てます。クラスを使用すればこの種の事を簡単に出来る

事は既に分かっていますが、クラスを定義する程に複雑な要求ではないので、in-line 的な制約を

定義して乱数を発生します。この手法は比較的汎用で応用性も広いと思われます。

例 19-4

実行結果は以下の様になります。

module test;

bit [7:0] a, b;

initial begin

repeat (10) begin

assert( std::randomize(a,b) with { (a < b); } )

$display("a=%3d b=%3d",a,b);

else

$display("randomize failed.");

end

end

endmodule

a= 3 b= 39

a= 35 b=214

a= 78 b=192

a=160 b=239

a= 0 b=118

a= 89 b=253

a= 31 b=193

a=149 b=223

a= 39 b=153

a= 83 b=154

Page 251: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

240

20 モジュール(modules)

20.1 概要

モジュールはデザインを記述する為の基本要素です。多くの構文をモジュール内で使用する事が

出来ます。クラスやインターフェースと同様にパラメータ化する事が出来ます。

モジュールで使用する多くの機能は既に記述されているので、この章では特記すべき事項のみ解

説します。

20.2 ポート・リスト

モジュール・ヘッダのポート・リストがポート名称だけから構成されると、モジュール・ヘッダ

は Verilog スタイルになります。この場合、ヘッダの後にポートの定義が必要です。例えば、次

の例は Verilogスタイルのモジュールです。

SystemVerilogでは、この種の記述法を推奨しません。ポート・リストには、ポートの方向、デー

タ・タイプ等の宣言を設定する事が望ましいです。例えば、次の様にポート・リストを定義しま

す。

以下では Verilogスタイルを扱いません。

20.2.1 ポートの方向

最初のポートに方向が付いていないと、inout となります。データ・タイプが省略されると、原

則として、logicが採用されます。

二番目以降のポートに名称以外の指定が無い場合、その前のポートの定義が適用されます。名称

以外の指定がある場合には、次の原則が適用されます。

ポートの方向が省略されると直前のポートの方向を適用します。

ポート・タイプが省略されると logicになります。

モジュール・ヘッダ 効果

module mh(wire x); ポート xは inout wire logic になります。

module mh(integer x); ポート xは inout wire integer になります。

module mh(inout integer x); ポート xは inout wire integer になります。

module mh([5:0] x); ポート x は inout wire logic [5:0]になりま

す。

module mh(wire x, y[7:0]); ポート xは inout wire logic になります。

ポート y は inout wire logic [7:0]になりま

す。

module verilog_style(a,b,sum);

input logic a, b;

output logic[1:0] sum;

assign sum = a+b;

endmodule

module better_style(input logic a,b,output logic [1:0] sum);

assign sum = a+b;

endmodule

Page 252: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

241

module mh(integer x, signed [5:0] y); ポート xは inout wire integerになります。

ポート yは inout wire logic signed [5:0]にな

ります。

20.3 パラメータ化したモジュール(parametrized modules)

パラメータをポート・リストの直前に定義してモジュールを記述します。例えば、次の様にしま

す。

パラメータ化したモジュールのインスタンスを次の様に作ります。

パラメータは定数だけに限らず、データ・タイプも指定できます。次の例は、データ・タイプを

パラメータに指定しています。

例 20-1

module BinaryCounter #(NBITS=2)

(input Ck,UpDown,PresetClear,LoadData,

input [NBITS-1:0] DataIn,output [NBITS-1:0] Q,QN);

...

endmodule

BinaryCounter #(.NBITS(8)) M1(.*);

module adder #(parameter type DATATYPE = logic) (input DATATYPE a, b,

output DATATYPE sum,output logic co);

assign {co,sum} = a+b;

endmodule

typedef logic [3:0] adder_type;

module top;

adder_type a, b, sum;

logic co;

adder #(.DATATYPE(adder_type)) DUT(.*);

initial begin

a = 0;

b = 0;

#10 a = 1;

#10 b = 1;

#10 a = 15;

end

initial

$monitor("@%2t: a=%b b=%b sum=%b co=%b",

$time,a,b,sum,co);

endmodule

Page 253: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

242

元のモジュールは 1 ビットの full adder ですが、この例では、4 ビットの full adder を実現してい

ます。モジュール adderの定義にある様に、パラメータ宣言を

#(parameter type DATATYPE = logic)

の様にしなければなりません。標準値は 1 ビットの full adder です。この例の実行結果は以下の

様になります。

20.4 トップ・レベル・モジュール

トップ・レベル・モジュールは、ソース・コード中でモジュール内のイスタンスとして参照され

ないモジュールを意味します。

トップ・レベル・モジュールをルートにしてデザインの階層が構築されます。この階層はエラボ

レーション時に固定されます。

20.5 モジュール・インスタンス

モジュールを定義しても、それを使用しなければ意味がありません。使用する為には、引用、又

は、インスタンスを作ります。例えば、次の様にしてインスタンスを作ります。

かなりの冗長性があります。この場合、ポート名称と接続するネット名称が一致しているので、

SystemVerilogdでは以下の様に書けます。

ポート名称と接続するネット名称が一致している場合、ポート名称を指定するだけで十分です。

SystemVerilogでは、更に簡単に記述できます。例えば、上の例の場合、

で十分です。全ての接続に於いて、ポート名称と接続するネット名称が一致する場合には、この

記述を使用する事が出来ます。もし、一致しないポートが存在する場合、その接続だけを追加す

れば済みます。例えば、

の様に書く事が出来ます。

@ 0: a=0000 b=0000 sum=0000 co=0

@10: a=0001 b=0000 sum=0001 co=0

@20: a=0001 b=0001 sum=0010 co=0

@30: a=1111 b=0001 sum=0000 co=1

BinaryCounter DUT(.Ck(Ck), .UpDown(UpDown),

.PresetClear(PresetClear), .LoadData(LoadData),

.DataIn(DataIn), .Q(Q), .QN(QN) );

BinaryCounter DUT(.Ck, .UpDown,

.PresetClear, .LoadData,

.DataIn, .Q, .QN );

BinaryCounter DUT(.*);

BinaryCounter DUT(.*, .Ck(clk) );

Page 254: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

243

例 20-2

この例ではパッケージ、及び、インターフェースを使用します。それぞれの定義は以下の様にな

っています。

パッケージ内にはインターフェースを定義する事が出来ないので、パッケージの外にインターフ

ェースを定義しています。

トップ・モジュールは以下の様になっています。モジュールの接続では、簡略化した接続法(.*)

を使用しています。

テストベンチは以下の様になっています。

package Pkg;

typedef enum logic [1:0] { ST0 = 2'b00, ST1 = 2'b01,

ST2 = 2'b10 } MealyState;

parameter WIDTH = 32;

endpackage

interface mealy_intf(input logic A,ClkB,Reset,output logic Z);

modport DUT(input A,ClkB,Reset,output Z);

modport TEST(output A,Reset,input ClkB,Z);

endinterface

module top;

logic A;

logic ClkB;

logic unsigned Reset;

logic unsigned Z;

MealyFSM DUT(.*);

mealy_intf mealy(.*);

test TEST(.*);

initial begin

ClkB = 0;

forever #10 ClkB = ~ClkB;

end

initial begin

A = 0;

forever #20 A = ~A;

end

initial #120 $stop;

endmodule

Page 255: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

244

DUT は以下の様に定義されています。モジュール・ヘッダに於いてパッケージを import してい

る事に注意して下さい。

実行結果は以下の様になります。

module test(mealy_intf.TEST mealy);

initial begin

mealy.Reset = 0;

#5 mealy.Reset = 1;

#5 mealy.Reset = 0;

end

initial

$monitor("@%3t: ClkB=%b A=%b Reset=%b Z=%b",

$time,mealy.ClkB,mealy.A,mealy.Reset,mealy.Z);

endmodule

module MealyFSM import Pkg::*; (mealy_intf.DUT mealy);

MealyState state, next_state;

always @(posedge mealy.Reset or posedge mealy.ClkB)

if( mealy.Reset )

state <= ST0;

else

state <= next_state;

always @(state or mealy.A)

case (state)

ST0: begin

mealy.Z = (mealy.A) ? 1 : 0;

next_state = (mealy.A) ? ST2 : ST0;

end

ST1: begin

mealy.Z = (mealy.A) ? 1 : 0;

next_state = (mealy.A) ? ST0 : ST1;

end

ST2: begin

mealy.Z = 0;

next_state = (mealy.A) ? ST1 : ST2;

end

default: begin

mealy.Z = 0;

next_state = ST0;

end

endcase

endmodule

Page 256: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

245

20.6 未定義モジュールの宣言(extern modules)

モジュール内でインスタンスとして参照しているモジュールはコンパイル時に何処かのファイル

内に存在しなければなりません。存在しない場合、エラボレーション時にエラーとなります。そ

のエラーを回避する為には、extern module宣言をする必要があります。

extern module 宣言したモジュールは、モジュールの定義が存在しなくてもエラボレーション時に

エラーになりません。例えば、下記のコードだけをコンパイルしてもエラーは出ません。コード

には dut 及び test の記述が含まれていませんが、何れも extern 宣言しているので、正常にコンパ

イルが終了します。

多くのエンジニアで構成されているプロジェクトの初期段階では、未定義のモジュールが多々存

在します。その様な場合、extern 宣言は便利な機能となります。

@ 0: ClkB=0 A=0 Reset=0 Z=0

@ 5: ClkB=0 A=0 Reset=1 Z=0

@ 10: ClkB=1 A=0 Reset=0 Z=0

@ 20: ClkB=0 A=1 Reset=0 Z=1

@ 30: ClkB=1 A=1 Reset=0 Z=0

@ 40: ClkB=0 A=0 Reset=0 Z=0

@ 50: ClkB=1 A=0 Reset=0 Z=0

@ 60: ClkB=0 A=1 Reset=0 Z=0

@ 70: ClkB=1 A=1 Reset=0 Z=1

@ 80: ClkB=0 A=0 Reset=0 Z=0

@ 90: ClkB=1 A=0 Reset=0 Z=0

@100: ClkB=0 A=1 Reset=0 Z=1

@110: ClkB=1 A=1 Reset=0 Z=1

interface simple_if(input bit clk);

bit request;

endinterface

extern module dut(simple_if intf);

extern program test(simple_if intf);

module top;

bit clk;

simple_if intf(clk);

test TEST(intf);

dut DUT(intf);

always

@(posedge clk) INTF.request <= 1;

always

@(negedge clk) INTF.request <= 0;

initial repeat (5) #10 clk = ~clk;

endmodule

Page 257: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

246

多くの人が同じ extern 宣言をするのは無駄が多いと共に間違う可能性も高いので、extern 宣言を

含むファイルを準備すると良いと思います。そして、extern 宣言を必要とする場合には、その宣

言ファイルを`includeするだけで済みます。

extern 宣言があるとモジュール・インスタンスに対して、簡略化接続記法(.*)を使用する事が

出来ます。

更に、extern 宣言があると実際にモジュールを定義する際に、ポート・リストとして .* を使用

する事が出来ます。

20.7 階層名称

デザイン階層のインスタンスは一意的に定まります。インスタンスは、階層のトップから順にイ

ンスタンス名をドット(.)で接続して階層名称を構成します。トップ・レベル・モジュールは

自身がインスタンスとなります。正式なシンタックスは以下の様になります。

$rootはデザイン階層のトップからの名称を明示している事を示します。例えば、

...

extern module dut(simple_if intf);

extern program test(simple_if intf);

module top;

...

simple_if intf(clk);

test TEST(.*);

dut DUT(.*);

...

endmodule

extern module test(a,b,q);

extern module BinaryCounter #(NBITS=2)

(input Ck,UpDown,PresetClear,LoadData,

input [NBITS-1:0] DataIn,output [NBITS-1:0] Q,QN);

module test(.*);

input a, b;

output q;

...

endmodule

module BinaryCounter(.*);

...

endmodule

[ $root . ] { identifier constant_bit_select . } identifier

top.DUT

top.TEST

$root.top.DUT

$root.top.TEST

Page 258: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

247

の様な階層名称を使用する事が出来ます。インスタンスを特定すれば、インスタンス内の変数も

参照する事が出来ます。

top.DUT.state

の様に参照する事が出来ます。値を設定する事も可能です。例えば、

$root.top.DUT.state = Pkg::ST0;

の様に値を設定する事が出来ます。デバッグ時はこうした特殊なアクセス法が重宝になります。

Page 259: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

248

21 プリプロセッサ(compiler directives)

プリプロセッサはコンパイルする過程を制御する命令です。ここでは、良く使用すると思われる

制御文のみ紹介します。全ての制御文の説明は原書を参照して下さい。

ここでは以下の文を紹介します。プリプロセッサは便利である反面、理解しにくい面もあります。

一般的には使用する機会は少ないと思われます。

プリプロセッサ 機能

`__FILE__ 現在のファイル名称を文字列として展開します。

`__LINE__ 現在の行番号を展開します。

`define マクロ・シンボルを定義します。

`include ファイルをインクルードします。

`ifdef マクロ・シンボルが定義されていれば、この文以降 `endif ま

でをコンパイルします。

`ifndef マクロ・シンボルが定義されていなければ、この文以降 `endif

までをコンパイルします。

`endif `ifdef、又は、`ifndefの終わりを示します。

21.1 `include文

最も良く使用される制御文は`include文だと思います。例えば、

`include “fsm_package.sv”

の様にして使用します。一方、ファイル fsm_package.sv 内には、パッケージ fsm_package

が定義されています。このパッケージは、必要な所であれば何処でも引用されます。従って、二

重に引用される事もあり得ます。二重引用はコンパイル・エラーの対象となる為、パッケージで

は、次の様に制御します。

この制御により、パッケージが一度コンパイルされると二度とコンパイルされません。

21.2 `define文

既に紹介した例で`define 文を使用しています。一般には、その様な簡単な利用法が多く見られま

す。複雑な定義も可能ですが、定義をした人自身にのみ解読可能なマクロは望ましくありません。

21.2.1 定数を定義する場合

次の記述は簡単な例です。

この定義を使用すると、以下のマクロ引用

`ifndef FSM_PACKAGE_SVH

`define FSM_PACKAGE_SVH

package fsm_package;

...

endpackage

`endif

`define mh(name) module name();

`define me endmodule

Page 260: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

249

と展開されます。

Verilog時代には、次の様な記述が多く見られました。

又は、

何れも正しい使用法で SystemVerilog でも通用する記法です。然し、アプリケーションによって

は、これらの記法では最適な効果を得られない場合があります。

例えば、RTL 論理合成において、上記のシンボルを構成するビット数が未知である為、full case

の取り扱いが困難になります。即ち、余計な論理が生成される可能性が非常に高くなります。こ

の場合には、寧ろ、以下の様な記述が望ましいと考えられます。

enumを使用する効果を以下の記述で説明する事が出来ます。

この if文は colorがとり得る値の全ての状況を網羅しています。詰まり、full caseになっています。

この if文には elseクローズがありませんがラッチは生成されません。`define、又は、parameterを

使用した場合には、この種の最適化処理を期待する事は出来ません。

`define文を定数を定義する為に使用する場合には、再度考えてみる事が必要であると言えます。

`mh(test)

`me

module test();

endmodule

`define RED 0

`define YELLOW 1

`define GREEN 2

parameter RED = 0,

YELLOW = 1,

GREEN = 2;

typedef enum [1:0] { RED=0, YELLOW, GREEN } color_e;

color_e color;

...

if( color == GREEN )

...

else if( color == YELLOW )

...

else if( color == RED )

...

Page 261: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

250

21.2.2 接頭辞及び接尾辞を持つ名称の創成

`define マクロのパラメータは、マクロの定義内ではトークンとして単独に存在します。その為、

他の文字と結合する事は出来ません。例えば、

_name = name;

という命令を `define マクロで次の様に定義すると

`define set(a) _a = a;

`set(name)は

_a = name;

と展開され、期待する内容になりません。引数 a とトークン_a の関連がマクロに認識されてい

ない事が原因です。

SystemVerilogはこの問題を解決し、引数に文字列を添える事が可能です。例えば、以下の様に定

義します。

`define set(a) _``a = a;

この様に定義すると、`set(name)は

_name = name;

として展開されます。

21.3 文字列内のパラメータ展開

`define マクロではマクロのパラメータが文字列の内部にあっても展開されません。例えば、マク

ロを次の様に定義します。

`print1(sum)、及び、`print(sum)は次の様に展開されます。

マクロの文字列内ではマクロのパラメータを認識する事ができません。この為、上記の様な展開

になります。SystemVerilog では、この制限を `” で解決します。文字列を`” で囲むと文字列内

のパラメータが展開します。例えば、

の様に定義すると、`print(sum)は

と展開します。

`define print1(val) $display("`val = %0d",val);

`define print2(val) $display("val = %0d",val);

$display("`val = %0d",sum);

$display("val = %0d",sum);

`define print(val) $display(`"val = %0d`",val);

$display("sum = %0d",sum);

Page 262: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

251

21.4 ‘endif文

この文を書き忘れると、ありとあらゆるエラー・メッセージが発行されると思う事が必要です。

コンパイラーが正しい処理を行なえない為、無意味のエラー・メッセージが列挙される可能性が

極めて高いです。エラー・メッセージの解析をせずに、`endif 文を挿入してリコンパイルする事

を勧めます。

一番確実な方法は、`ifdef、又は、`ifndef 文を書いた時点で、`endif を書く事だと思います。この

習慣により、対の`endifを書き忘れる事が無くなります。

一般に、SystemVerilogでは対を成す構文が多いです。構文対を最初に書き、内部の記述をその次

に記述するのは良い習慣かもしれません。例えば、package … endpackage等があります。

21.5 `__FILE__、`__LINE__

これらの制御文の用途は極めて限られていると考えられます。デバッグ時、又は、異常処理時に

当該箇所を明示する為に使用する事が出来ます。

`__FILE__は文字列としてファイル名称を展開します。従って、string 型の変数で受ける事が出来

ます。或いは、%s でファイル名をプリントする事が出来ます。

`__LINE__は行番号を整数として展開します。%d で行番号をプリントする事が出来ます。以下に

使用例を示します。

例 21-1

この例では、クラスのプロパーティに値を設定し、使用条件を満たしているか否かをチェックし

ます。仕様は簡単で

(a + b == 15) && (a < b)

です。その為に、クラスにメンバー a ,及び、bを定義して制約を与えます。

プロパーティ a、及び、b はランダム変数ではない事に注意して下さい。テストベンチでそれら

の変数に値を設定して仕様のチェックをします。制約をチェッカーとして利用します。

テストベンチは以下の様になっています。

class sample_t;

bit [3:0] a, b;

constraint C

{

a + b == 15;

a < b;

}

endclass

Page 263: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

252

実行結果は以下の様になります。

module test;

sample_t sample = new;

initial begin

check_constraint(7,8,`__FILE__,`__LINE__);

check_constraint(8,7,`__FILE__,`__LINE__);

end

function void check_constraint(int a,b,string filename,

int line_number);

sample.a = a;

sample.b = b;

assert( sample.randomize() )

print();

else

print_error("constraint violation",

filename,line_number);

endfunction

function void print;

$display("a=%2d b=%2d",sample.a,sample.b);

endfunction

function void print_error(string msg,string filename,int

line_number);

$display("%s(L%0d) %s: a=%2d b=%2d",

filename,line_number,msg,sample.a,sample.b);

endfunction

endmodule

a= 7 b= 8

D:/Users/Test/Ch21_Ex_N001.sv(L18) constraint violation: a= 8 b= 7

Page 264: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

253

22 シミュレーション実行モデル(simulation semantics)

22.1 シミュレーション領域(simulation regions)

時刻 T に於いてシミュレーションが開始されると、プロセス(あるいはスレッド)は、時系列的

に分類された領域(regions)で実行します。ある領域のプロセスは他の領域のプロセスよりも先

に実行します。この実行順序制約により、状態が安定した信号値を基にしてシミュレーションの

論理が確立します。例えば、a = b; が実行する領域は q <= d; が実行する領域よりも早く

実行します。その他の例として、programで記述されたテストベンチの論理は DUT の信号値が安

定した状態になってから実行します。

SystemVerilogでは以下の様に領域を分類しています。

① Preponed

② Pre-Active

③ Active

④ Inactive

⑤ Pre-NBA

⑥ NBA

⑦ Post-NBA

⑧ Pre-Observed

⑨ Observed

⑩ Post-Observed

⑪ Reactive

⑫ Re-Inactive

⑬ Pre-Re-NBA

⑭ Re-NBA

⑮ Post-Re-NBA

⑯ Pre-Postponed

⑰ Postponed

領域はこの順序で実行します。これらの全ての領域を理解する事が必要ですが、入門編の範囲を

超える事は確かです。この章では、これらの領域の中の一部について記述します。

時系列的な領域の実行順序を原書から参照して図示しました。但し、明確さの為に一部を除外し

てあります。図の右側には、代表的な SystemVerilog命令が実行する時期を明記してあります。

領域は類推し易くなっています。例えば、Re-Inactive 領域が存在しますが、それは Inactive 領域

の対です。従って、Inactive領域を見て下さい。それを見れば、Re-Inactive領域では programで記

述された

#0 a = b;

が実行する領域である事が分かります。

原書には全ての領域が記述されている為、理解する為には複雑過ぎると思えます。その為に、簡

略化した図を準備しました。

Page 265: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

254

22.2 #0ディレーの効果

ディレー0(# 0)の制御が極めて有効に働く理由は、このダイアグラムを見て理解する事が出

来ます。

a = b;

#0 a = b;

Preponed

Active

Inactive

NBA

Observed

Reactive

Postponed

直前の time slot

現在の time slot

次の time slot

信号値はこの領域でサンプ

リングされます。

module のブロッキング命令

a = b; 等が実行されます。

命令 #0 a = b; 等が実行され

ます。

non-blocking 命令 q <= d; 等

が実行されます。

アサーションの評価が実行

します。

program のブロッキング命令

が実行します。

concurrent assertions の action

ブロックが実行します。

Re-inactive

Re-NBA

reactive region の命令 #0 a =

b; 等が実行されます。

reactive regionの non-blocking

命令 q <= d; 等が実行されま

す。

Page 266: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

255

は全く異なる記述です。更に、両者は、a <= b とも全く異なります。記述の違いはシミュレー

ション結果の差として現れます。以前、取り上げた例をもう一度復習してみます。

fork-join_none で子プロセスを生成している例を再考します。for ループで三つの子プロセスが生

成されています。

SystemVerilogのシミュレーション・アルゴリズムにより、親プロセスはブロックしない限り実行

権を放棄しません。for ループ内には親プロセスをブロックする命令が無いので、三つの子プロ

セスは実行待ちの状態から解放されません。

for ループを出るとディレー0(# 0)の制御に遭遇して、親プロセスは実行権を放棄します。こ

の時、親プロセスは Inactive region に登録されます。その後、三つの子プロセスが実行権を取得

して実行を開始します。

三つの子プロセスの実行が終了し、もし他のアクティビティが無ければ、Inactive regionが実行さ

れます。即ち、親プロセスの実行が再開します。

22.3 programとクロック・ジェネレータ

program はテストベンチ専用の論理を書く為の構文です。その論理は Reactive region で実行しま

す。もし、クロック・ジェネレータを program 内に記述するとテストベンチが正しく動作しなく

なります。例えば、

の様に、クロック・ジェネレータを program 内に定義すると、clk 及び request の信号値の変

化が同時に dut に伝搬します。どちらの信号値の変化が先に到達するかで結果が異なり、所謂、

race conditionが発生します([3])。従って、テストベンチが正しく動作しない場合が出てきます。

この問題を回避する為には、クロック・ジェネレータを module 内で定義する必要があります。

一般的には、トップ・モジュール内にクロック・ジェネレータを定義する事が望ましいと考えら

れています。

module test;

...

for( int i = 1; i <= 3; i++ )

fork automatic int k = i;

$write("%0d",k);

join_none

#0 $display;

...

endmodule

program bad_clock_generator(output bit clk,request);

initial

forever #10 clk <= ~clk;

initial

forever @(posedge clk)

request <= ~request;

endprogram

Page 267: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

256

module top;

bit clk;

always #10 clk = ~clk;

test TEST(.*);

dut DUT(.*);

endmodule

program test(...);

initial

forever @(posedge clk)

request <= ~request;

...

endprogram

module dut(...);

...

endmodule

test dut

top

Page 268: SystemVerilog 入門 - artgraphics.co.jp · SystemVerilog 入門 ©2018 アートグラフィックス 〒124-0012 東京都葛飾区立石8-14-1  SystemVerilog Primer

SystemVerilog入門

Copyright © 2018 Artgraphics. All rights reserved.

257

23 参考文献

以下の文献を学習する事を薦めます。

[1] IEEE Std 1800-2012: IEEE Standard for SystemVerilog – Unified Hardware Design, Specification

and Verification Language.

[2] Stuart Sutherland, Simon Davidmann, and Peter Flake: SystemVerilog for Design, 2nd

Edition,

Springer 2006.

[3] Chris Spear: SystemVerilog for Verification, 2nd Edition, Springer 2008.

[4] Ashok B. Mehta: SystemVerilog Assertions and Functional Coverage, Springer 2014.

[5] Kathleen A. Meade and Sharon Rosenberg: A Practical Guide to Adopting the Universal Verification

Methodology (UVM), 2nd

Edition Cadence Design Systems, Inc. 2013.

[6] Ben Cohen, Srinivasan Venkataramanan, Ajeetha Kumari, and Lisa Piper: SystemVerilog Assertions

Handbook, 4th

Edition, VhdlCohen Publishing, 2016.