1. 株式会社PALTEK
  2. TECHブログ
  3. 技術情報
  4. 検証を楽にするSystemVerilogコーディング術(Design and Verification LANDSCAPE 2020-Vol5)

TECHブログ

検証を楽にするSystemVerilogコーディング術(Design and Verification LANDSCAPE 2020-Vol5)

検証を楽にするSystemVerilogコーディング術(Design and Verification LANDSCAPE 2020-Vol5)

Verilog HDLは1984年ごろに開発され、1995年にIEEE1364-1995として標準化された。その後、言語の曖昧さを正す目的でIEEE1364-2001へと改版された。しかし開発当時から時が経ち、最新のシステム設計や検証に追従する目的で、SystemVerilogとして大幅な機能追加が行われ、2005年にIEEE1800-2005標準が完成した。しかしVerilog HDLとSystemVerilogの2つの標準活動が個別に行われていたため、さまざまな互換性や一貫性の欠如が指摘された。

そこでIEEEはこの2つの標準をマージし、VerilogとしてはIEEE1364-2005を最終版として策定し、SystemVerilogはIEEE1800-2009として改版した。IEEE1800はその後2012年、2017年と改版が続いている。

SystemVerilogは検証用の言語であるとの誤解が生じるほど、機能検証に関する言語仕様は豊富だが、論理設計や合成に関する言語仕様も多く追加されている。
そこで本稿ではSystemVerilogの言語仕様の中で、設計コーディングの観点から機能検証の効率を上げると期待される記述について解説する。

ただしリントでチェックされるような再利用性を目的としたレキシカルな記述の見直しではなく、あくまでも機能検証の生産性を上げることを目的とする。そのすべてを網羅できるわけではないが、従来のVerilogの記述に対してSystemVerilogだからこそ検証上の利点が得られる記述方法について取り上げる。

目次

変数タイプとネットタイプ

Verilog HDLで主に使われていた変数とネットタイプはregとwireである。SystemVerilogではlogicがregの置き換えとなっており、またlogicによりwireの機能も果たす。このlogicは実際にはデータタイプであり、4値(0/1/Z/X)を取り得る変数かネットに対して使用される。logicで宣言されれば変数であり、モジュールのoutputポート宣言時に使用される場合も変数であるが、モジュールのinput、もしくはinoutポート宣言時に使用される場合にはネットタイプとなる。

従来のregは、特に初心者にはハードウェアとしてのregisterを推定するのではないかという誤解を生じやすい。実際には組合せ論理でもシーケンシャル論理でも使用される。しかしFPGAやASIC、SoC設計は、設計担当者以外の検証エンジニアやソフトウェア設計者がテストすることもある。logicというデータタイプ名はregに比べ、より分かりやすく、正確に体現するキーワードである。

またlogicの信号に対しては、プロシーデュアルアサインもコンティニュアスアサインも可能である。つまりコードのほとんどをlogicのみで表現することができる。その例外は設計者が複数ドライバを意図して設計する場合である。logicに対しては複数のドライバを持たせることができない。逆に複数ドライバの問題はコンパイラにより検出されるため、機能検証にまで持ち込まないという利点がある。もし複数ドライバによる記述が必要な場合には、明示的にwireを使えばCMOSでの振舞いに準じた解決をしてくれる。

SystemVerilogではwireの他にuwireというネットタイプも追加されている。uwireでは複数ドライバが使えないので、意図しない複数ドライバはコンパイラで検出可能であり、機能検証にまで持ち込まない。

暗示的に変数やネットの役割をさせるコード例

図1. 暗示的に変数やネットの役割をさせるコード例


図1.ではポート宣言にlogicを用いている。これによりツールは暗示的なwireや変数として取り扱う。また宣言しない信号に対しても暗示的なワイヤの役割を果たす。このコード例で分かるとおり、SystemVerilogでは、ほぼすべての場所でlogicを使えば良い。ただしwireの代わりにuwireを暗示させたい場合には、moduleの直前に以下の一行を加えれば、暗示されるネットのタイプを変更することができる。

暗示されるネットのタイプをuwireに変更

図2. 暗示されるネットのタイプをuwireに変更


プロシーデュアルブロック

従来のVerilog HDLでモデルを記述する際のプロシーデュアルブロックはalwaysブロックである。
このalwaysブロックは、テストベンチで用いられ合成の対象とならないモデルと、組合せロジック、ラッチロジック、シーケンシャルロジックなど合成を対象としたモデルで使用されてきた。論理合成ツールはその中身の記述を評価、解釈することで設計の意図を推測し、例えばラッチが生成されるなどのメッセージを出力する。設計意図が分からずに記述で推測しなくてはならないこの方法は、特に検証エンジニアがテストベンチやスティミュラス、スコアボードなどを作成する上で負担となる。

SystemVerilogで合成対象となるプロシーデュアルブロックにはalways_comb、always_latch、always_ffという3つの種類のブロックが追加された。それぞれ組合せ動作、ラッチ動作、シーケンシャル動作を意図して記述するという意味合いがある。設計意図がドキュメント的に示されており、検証する際にも分かりやすいという大きなメリットがある。さらにシミュレータ、リント、論理合成などのツールにおいても、その意図を持って使われるプロシーデュアルブロックのタイプと動作記述とに矛盾があるかどうかをチェックすることができる。
例えばalways_ffであればクロックの有無を判断したり、always_latchであればセンシティビティリストに関する正しい判断ができるようになる。

always_combを用いた記述例

図3. always_combを用いた記述例


いずれにしても、設計意図が伝わりやすいこと、そして機能検証の前に従来以上のチェックが適切に実行できる点は、機能検証に余計な負荷を与えないという利点をもたらす。


厳格にチェックされる列挙型

従来のVerilogのネットタイプと変数は、その定義が緩やかであり厳格さに欠く問題があり、値のアサイン時においてもほとんどチェックがされていない。
その一つの例として簡単なステートマシンのRTL記述を図4.に示す。
このRTL記述は構文的には正しいものの、6つの機能的なバグがある。論理合成ツールの中にはワーニング・メッセージを出すツールもあるが、バグを含んだままゲートレベルのネットリストを出力してしまう。一方で検証エンジニアは、その状態を作るためのスティミュラスを作成し、問題を検出するためのスコアボードなどを作る労力を負担することになる。そしてデバッグ作業により問題の原因を特定し、RTLを変更してから再度、リグレッションを流すことになる。

※画像クリックで大きな画像が表示されます。

Verilog HDLで記述されたバグを含むRTL記述例

図4. Verilog HDLで記述されたバグを含むRTL記述例


SystemVerilogでは、より厳格にタイプ定義された列挙型(enumelation)が追加されている。基本構文は
enum { RED, GREEN, BLUE } rgb_e
のようにラベルを列挙し、定義する。
ネットや変数に列挙型を使用すると、正しいラベルに対して特定の正当な値のみが許可される。列挙型のチェックには以下のような項目が含まれる。

  • 各要素に割り当てられるラベルは一意的でなくてはならない
  • 変数のサイズとラベルのサイズは等しくなくてはならない
  • ラベルは列挙されたリスト、もしくは同じ定義で他に列挙された別のラベルでなくてはならない

図4.で示したVerilog記述のステートマシンをSystemVerilogの列挙型を用いて記述した例を図5.に示す。このコードのコメントでは//BUGの代わりに//Errorとしているが、これはコンパイル時に構文エラーとなることを意味している。

※画像クリックで大きな画像が表示されます。

SystemVerilogで記述された構文エラーを含むRTL記述例

図5. SystemVerilogで記述された構文エラーを含むRTL記述例


図4.のVerilog記述では6つのバグは構文エラーとならず、したがって検証工程へと進み、デバッグして初めて判定されることになる。これが図5.に示すように、列挙型を用いて記述すると、検証前のコンパイル時に構文エラーとして検出される。また論理合成でも構文エラーとなるため、バグを含んだままのネットリストとして出力されることはない。

配列に関する操作

従来のVerilogは、1次元、多次元配列をサポートしており、これを用いてルックアップテーブルやレジスタファイルを表すことができる。ただし、一度にアクセスできるのは1つの配列要素に限られている。そこである配列から別の配列へデータをコピーしたり、初期化をする場合するには、配列の各要素を順番に指定するループ構造を記述する必要がある。

図6.はフレームレジスタにRGBを8ビットで16個格納し、それの初期化や別のフレームレジスタにコピーする記述を含むVerilogコード例である。
Verilogでは配列要素は一度に1つしかコピーできないという制限があるため、ループ文を使って要素ごとにコピーする必要がある。またポートを介した信号の受け渡しも、配列のすべての要素を参照可能なベクターポートを作成する必要がある。出力ポートであれば、配列の中身をパッキングしてからベクターポートに出力する。入力ポートであれば、ベクターポートの内容をアンパッキングする処理が必要となる。図6.で分かるように、比較的小さな配列であっても、比較的単純な配列操作であっても、ループのネスティングやパッキング、アンパッキングなどの記述が必要となり、複雑化しやすい。

配列操作の記述を含むVerilogコード例

図6. 配列操作の記述を含むVerilogコード例

 

SystemVerilogでは配列全体のコピーが可能であり、1つのステートメントで記述できる。ただしコピー元と先は次元数が同じであり各次元の要素数が同じ、かつ各要素のビット数とタイプが同じでなくてはならない。また配列に対してリスト`{ }をコピーすることも可能である。その記述例を図7.に示す。

配列操作の記述を含むSystemVerilogコード例

図7. 配列操作の記述を含むSystemVerilogコード例

 

図7.は図6.のVerilogコードをSystemVerilogで置き換えたものである。図6.に比べると少ない記述量で表現できる。この記述例では配列のコピーやリストによる入力、アレイポートなどが示されているが、その他タスクやファンクションの引数でも同様に扱うことができる。
このようにSystemVerilogでは配列の扱いが著しく改善されており、記述自体を簡素化することができる。記述の簡素化によりバグを機能検証に持ち込まない、あるいはバグとなってしまってもデバッグ効率が上がることが期待できる。

インタフェース

※画像クリックで大きな画像が表示されます。

AHBバスによるマスタ/スレーブ接続

図8. AHBバスによるマスタ/スレーブ接続

まず図8に示すAHBバスによるマスタ/スレーブ接続についてみていただきたい。バス用のhclk、hrstNなどの他に、アドレスやデータ、サイズ、レディ信号などが接続されている。この例ではマスタのモジュールが1つとスレーブのモジュールが1つだけであるが、SoCなどの設計では数多くのスレーブモジュールが接続されるため、接続だけでも相当量の記述を要する。このような接続に対して、SystemVerilogではインタフェースという概念が取り入れられている。

インタフェース機能を使用すると、図8.のAHB接続は図9.のようなイメージになる。

インタフェースを用いたAHB接続

図9. インタフェースを用いたAHB接続

 

アドレスやデータ、サイズ、レディなどの信号は個々のポートどうしを接続するのではなく、まとまったポートとして接続されるのが大きな特徴である。このインタフェースに対する記述にはinterface〜endinterfaceで囲まれるブロックを使用する。その記述例を図10.に示す。

インタフェースの記述例

図10. インタフェースの記述例

 

この記述においてmodportはモジュールポートの意味があり、インタフェースを構成する信号へのアクセスを制約し、入出力を規定する。ここにあるようにマスタ接続用、スレーブ接続用だけでなく、テストベンチ接続用、メモリアクセス用など、さまざまな目的で定義することができる。実際に接続する際には、このインタフェースをインスタンス化し、同じくインスタンス化されたマスタとスレーブに接続する。その記述例を図11.に示す。

※画像クリックで大きな画像が表示されます。

マスタ、スレーブの記述例およびトップレベルにおける接続例

図11. マスタ、スレーブの記述例およびトップレベルにおける接続例

 

このように接続するポートをインタフェースのビューとして定義し、それを用いて接続することにより、各モジュールへの接続の記述量を削減することができる。ポート名の変更やポートの追加、削除があった場合も修正の記述量が限定的となる。またインタフェースには、そのメソッドとしてタスクやファンクションを記述することもできる。
例えば転送するデータのパリティチェックを行う記述を追加することも可能である。さらにアサーションを追加すればバス転送のプロトコルを常に監視する機能を盛り込むこともできる。このような工夫を行うことで、機能検証における労力を削減することにつながる。
またUVMを用いたテストベンチでは、インタフェースを介したテストベンチへの接続が一般的であり、クラス記述されるテストベンチに対して仮想的なインタフェースとして定義し、そのハンドルをコンフィギュレーションから取得することで、ピンレベルとの接続を行う。

まとめ

VerilogHDLとしての標準規格はIEEE1364-2005が最終版である。この版が発行されてからすでに15年が経過している。設計時の記述においてIEEE-1800SystemVerilogを積極的に取り入れることで、設計労力が削減されるだけでなく、実は機能検証での労力の削減につながることが多い。今回取り上げた内容は、それでもほんの一部に過ぎない。設計の規模と複雑度が増し、プロジェクトにおいて機能検証が占める割合が70%にも及ぶ現状に対して、時代に即した言語を使用することは非常に重要である。

参考文献
[1] IEEE Computer Society and the IEEE Standards Association Corporate Advisory Group, IEEE Standard for SystemVerilog— Unified Hardware Design, Specification, and Verification Language
[2] Stuart Sutherland and Don Mills, “Can My Synthesis Compiler Do That?”, DVCon US 2014 paper
[3] Stuart Sutherland, “RTL Modeling with SystemVerilog for Simulation and Synthesis using SystemVerilog for ASIC and FPGA design”, SUTHERLAND HDL published book
[4] Verification Horizon 2019 December Issue, Mentor A Siemens Business

「Design and Verification LANDSCAPE」技術情報メールニュース

PALTEKでは本ブログ「Design and Verification LANDSCAPE」シリーズの技術情報をメールで年に3-4回発信しています。
ご登録いただいた方には、最新の情報をメールニュースとしてお届けします。
ご希望の方はこちらのフォームよりご登録ください。

※競合製品取り扱い企業様の申込については、お断りする場合がありますので予めご了承ください。

 

このブログのシリーズ

Design and Verification LANDSCAPEシリーズ一覧は下記になります。是非あわせてお読みください。