SystemVerilogは、 IEEE(米国電気電子学会)によってIEEE 1800として標準化された、ハードウェア記述およびハードウェア検証言語であり、半導体および電子設計業界において、電子システムのモデリング、設計、シミュレーション、テスト、実装に広く用いられています。SystemVerilogはVerilogの拡張版です。
SystemVerilogは、2002年にスタートアップ企業のCo-Design AutomationがAccelleraにSuperlog言語を寄贈したことから始まりました。 [ 1 ]検証機能の大部分は、Synopsysが寄贈したOpenVera言語に基づいています。2005年に、SystemVerilogはIEEE標準1800-2005として採用されました。 [ 2 ] 2009年には、この標準は基本Verilog(IEEE 1364-2005)標準と統合され、IEEE標準1800-2009が作成されました。
SystemVerilog 標準はその後、2012 年、[ 3 ] 2017 年、[ 4 ]および直近では 2023 年 12 月に更新されました。 [ 5 ]
SystemVerilogの機能セットは、大きく2つの役割に分けられます。
この記事の残りの部分では、Verilog-2005には存在しないSystemVerilogの機能について説明します。
SystemVerilogでは、静的変数と自動変数という2種類のデータライフタイムが規定されています。自動変数は、プログラムの実行がその変数のスコープに入った瞬間に作成されます。静的変数は、プログラムの実行開始時に作成され、実行中に新しい値が割り当てられない限り、プログラムの実行期間中ずっと同じ値を保持します。
タスクまたは関数内で型を指定せずに宣言された変数は、自動変数とみなされます。変数が静的であることを指定するには、宣言の型の前に「 static」キーワードstatic int x;を配置します(例:「 」)。「automatic」キーワードも同様に使用されます。
拡張変数型により、 Verilogの「reg」型に新たな機能が追加されます。
ロジック[ 31 : 0 ] my_var ;Verilog-1995 および -2001 では、reg 変数はRTL コードなどの動作ステートメントに限定されています。SystemVerilog では、reg 型を拡張して、gate や module などの単一のドライバで駆動できるようにしています。SystemVerilog では、この型に「logic」という名前を付けて、この追加機能があることをユーザーに知らせ、ハードウェア レジスタではないことを知らせています。「logic」と「reg」は互換性があります。複数のドライバを持つ信号 (汎用入出力用のトライステート バッファなど) は、SystemVerilog が最終的な値を解決できるように、「wire」などのネット型として宣言する必要があります。
多次元パック配列は、 Verilogの「レジスタ」と「メモリ」の概念を統合し、拡張するものです。
ロジック[ 1 : 0 ][ 2 : 0 ] my_pack [ 32 ];従来の Verilog では、変数名の左側に宣言できる次元は 1 つだけでした。SystemVerilog では、このような「パックされた」次元をいくつでも宣言できます。パック配列型の変数は、整数演算値に 1:1 で対応します。上記の例では、 の各要素は、my_pack式の中で 6 ビット整数として使用できます。名前の右側の次元 (この場合は 32) は、「アンパックされた」次元と呼ばれます。Verilog -2001と同様に、アンパックされた次元はいくつでも宣言できます。
列挙型データ型(enums)を使用すると、数値に意味のある名前を付けることができます。列挙型として宣言された変数は、キャストせずに別の列挙型の変数に代入することはできません。これはパラメータには当てはまりません。パラメータは、Verilog-2005 で列挙型の推奨実装手法でした。
typedef enum logic [ 2 : 0 ] { RED , GREEN , BLUE , CYAN , MAGENTA , YELLOW } color_t ;color_t my_color = GREEN ; initial $ display ( "色は%sです" , my_color.name ( ));上記のように、設計者はlogic [2:0]列挙値を表すために使用される基となる算術型(この場合は)を指定できます。メタ値XとZは、不正な状態を表すために使用できます。組み込み関数は、name()現在の列挙値のASCII文字列を返します。これは、検証やテストに役立ちます。
新しい整数型: SystemVerilog ではbyte、shortint、 、intをlongintそれぞれ 8、16、32、64 ビットの 2 状態符号付き整数型として定義しています。bit型は、 とよく似た動作をする可変幅の 2 状態型ですlogic。 2 状態型には、従来の Verilog のXおよびZメタ値がありません。これらの型を使用すると、シミュレーションが高速化される場合があります。
構造体と共用体は、 C 言語とほぼ同じように動作します。SystemVerilog の拡張機能には、 packed属性とtagged属性があります。packedtagged属性を使用すると、共用体のどのメンバーが現在使用されているかをランタイムで追跡できます。taggedpacked属性を使用すると、構造体または共用体が、ビットのパック配列に 1:1 でマッピングされます。データ型の内容は、C および C++ のビットフィールドstructと同様に、ギャップのない連続したメモリブロックを占有します
typedef struct packed { bit [ 10 : 0 ] expo ; bit sign ; bit [ 51 : 0 ] mant ; } FP ;FPゼロ= 64'b0 ;この例に示すように、SystemVerilog はC や C++ と同様にtypedefもサポートしています。
SystemVerilog では、ハードウェアをモデル化するための 3 つの新しい手続き型ブロックが導入されました。always_comb(組み合わせ論理回路をモデル化するための)、always_ff(フリップフロップ用)、always_latch(ラッチ用) です。Verilog では、異なるタイプのハードウェア構造をモデル化するために単一の汎用alwaysブロックを使用していましたが、SystemVerilog の新しいブロックはそれぞれ特定のタイプのハードウェアをモデル化することを目的としており、ブロックによって記述されるハードウェアがモデルの意図された用途と一致するように意味的な制約を課しています。HDL コンパイラまたは検証プログラムは、意図されたタイプの動作のみが発生するように追加の手順を実行できます。
ブロックは組み合わせ論理always_combをモデル化します。シミュレータは、含まれるステートメントからすべての変数を感度リストとして推論します。
always_comb begin tmp = b * b - 5'h4 * a * c ; no_root = ( tmp < 0 ); endこのalways_latchブロックは、レベルセンシティブなラッチをモデル化します。ここでも、センシティブリストはコードから推測されます。
always_latch if ( en ) q <= d ;ブロックは同期論理(特にエッジセンシティブな順序論理)always_ffをモデル化します。
always_ff @( posedge clk ) count <= count + 4'd1 ;電子設計自動化(EDA)ツールは、ハードウェアモデルがブロック使用のセマンティクスに違反していないことを確認することで、設計意図を検証できます。例えば、新しいブロックでは、変数への代入を1つのソースのみに制限していますが、Verilogのalwaysブロックでは複数の手続き型ソースからの代入が許可されていました。
RTLコードで静的数値リテラルを用いて算術演算を行う場合、意図しない切り捨て、リンティング違反、合成の問題を回避するために、定数のビット幅を明示的に指定することが重要です。これは、組み合わせ論理ブロックや順序論理ブロックにおいて特に重要です。オペランドに明示的なビット指定がない場合、シミュレータや合成ツールはコンテキストに基づいて幅を推測したり、実装固有のサイズをデフォルトとして使用したりする可能性があり、シミュレーションやハードウェア実装中にデータ損失や予期しない動作を引き起こす可能性があります。
小規模な設計の場合、Verilogのポートはモジュールと周囲環境との接続性を簡潔に記述します。しかし、大規模な設計階層内の主要ブロックは通常、数千ものポートを持ちます。SystemVerilogでは、接続されたモジュール間のポート名宣言の冗長性を削減し、関連する信号をユーザーが宣言したバンドルにグループ化して抽象化するために、インターフェースの概念が導入されています。さらに、論理接続の方向を示すmodportという概念もあります。
例:
interface intf ; logic a ; logic b ; modport in ( input a , output b ); modport out ( input b , output a ); endinterfacemodule top ; intf i (); u_a m1 (. i1 ( i . in )); u_b m2 (. i2 ( i . out )); endmodulemodule u_a ( intf . in i1 ); endmodulemodule u_b ( intf . out i2 ); endmodule以下の検証機能は通常、合成不可能であり、HDLコードに基づいてハードウェアに実装することはできません。その代わりに、拡張性と柔軟性に優れたテストベンチの作成を支援します。
このstringデータ型は、可変長のテキスト文字列を表します。例:
string s1 = "Hello" ; string s2 = "world" ; string p = ".?!" ; string s3 = { s1 , ", " , s2 , p [ 2 ]}; // 文字列連結$ display ( "[%d] %s" , s3 . len (), s3 ); // シミュレーションでは、"[13] Hello, world!" と出力されます設計で使用される静的配列に加えて、SystemVerilogは動的配列、連想配列、キューを提供します。
int cmdline_elements ; // 動的配列の要素数int da []; // 動的配列int ai [ int ]; // int でインデックス付けされた連想配列 int as [ string ] ; // string でインデックス付けされた連想配列int qa [$]; // 配列として、または組み込みメソッドでインデックス付けされたキューinitial begin cmdline_elements = 16 ; da = new [ cmdline_elements ]; // 16個の要素を持つ配列を割り当てますend動的配列は、アンパック配列とよく似た動作をしますが、実行時に動的に割り当てられるという利点があります(上記参照)。パック配列のサイズはコンパイル時に定数または定数式から知る必要がありますが、動的配列のサイズは別の実行時変数から初期化できるため、必要に応じて配列のサイズを任意に指定および変更できます。
連想配列は、ユーザーが指定したキー型とデータ型を持つ二分探索木と考えることができます。キーは順序付けを意味し、連想配列の要素は辞書式順序で読み出すことができます。最後に、キューはC++ STLのdeque型の多くの機能を提供します。要素は両端から効率的に追加および削除できます。これらのプリミティブにより、大規模な設計のスコアボードに必要な複雑なデータ構造を作成できます。
SystemVerilogはオブジェクト指向プログラミングモデルを提供する。
SystemVerilogでは、クラスは単一継承モデルをサポートしていますが、いわゆる「インターフェースクラス」(interfaceJavaの機能と概念的に同一)を使用することで、多重継承に類似した機能を実装できます。クラスは型によってパラメータ化でき、 C++テンプレートの基本的な機能を提供します。ただし、テンプレートの特殊化と関数テンプレートはサポートされていません。
SystemVerilogのポリモーフィズム機能はC++のものと類似しています。プログラマは、virtual派生クラスがその関数を制御できるように、関数を明示的に記述することができます。詳細については、「仮想関数」を参照してください。
カプセル化とデータ隠蔽はlocal、およびキーワードを使用して実現されます。protectedこれらのキーワードは、隠蔽するすべての項目に適用する必要があります。デフォルトでは、すべてのクラスプロパティはパブリックです。
クラスインスタンスはnewキーワードを使用して動的に作成されます。で示されるコンストラクタfunction newを定義できます。SystemVerilogには自動ガベージコレクションがあるため、 new演算子によって作成されたインスタンスを明示的に破棄する言語機能はありません。
例:
virtual class Memory ; virtual function bit [ 31 : 0 ] read ( bit [ 31 : 0 ] addr ); endfunction virtual function void write ( bit [ 31 : 0 ] addr , bit [ 31 : 0 ] data ); endfunction endclassclass SRAM #( parameter AWIDTH = 10 ) extends Memory ; bit [ 31 : 0 ] mem [ 1 << AWIDTH ];仮想関数bit [ 31 : 0 ] read ( bit [ 31 : 0 ] addr ); return mem [ addr ]; endfunction仮想関数void write ( bit [ 31 : 0 ] addr , bit [ 31 : 0 ] data ); mem [ addr ] = data ; endfunction endclassクラス定義で定義された整数値、または何らかのレキシカルスコープ内の独立した変数として定義された整数値には、一連の制約に基づいてランダムな値を割り当てることができます。この機能は、検証のためのランダムなシナリオを作成する際に役立ちます。
クラス定義内では、randおよびrandc修飾子は、ランダム化の対象となる変数を示します。 は順列ベースrandcのランダム化を指定し、変数は可能なすべての値を一度ずつ取り、その後、同じ値が繰り返されます。修飾子のない変数はランダム化されません。
class eth_frame ; rand bit [ 47 : 0 ] dest ; rand bit [ 47 : 0 ] src ; rand bit [ 15 : 0 ] f_type ; rand byte payload []; bit [ 31 : 0 ] fcs ; rand bit [ 31 : 0 ] fcs_corrupt ;constraint basic { payload.size inside {[ 46 : 1500 ] } ; }constraint good_fr { fcs_corrupt == 0 ; } endclassこの例では、fcsフィールドはランダム化されていません。実際には、CRCジェネレータを使用して計算され、そのfcs_corruptフィールドはFCSエラーを注入するために破損させるために使用されます。示されている2つの制約は、準拠するイーサネットフレームに適用されます。制約は選択的に有効にすることができます。上記の例では、破損したフレームを生成するためにこの機能が必要になります。制約は、変数間の相互関係、含意、および反復を含む、任意に複雑にすることができます。SystemVerilog制約ソルバーは、解が存在する場合にそれを見つける必要がありますが、これは一般にNP困難問題(ブール充足可能性)であるため、それに必要な時間については保証されません。
SystemVerilogの各クラスには、ランダム化のための3つの定義済みメソッド(pre_randomize、randomize、post_randomize)があります。randomizeメソッドは、クラス変数をランダム化するためにユーザーが呼び出します。pre_randomizeメソッドは、ランダム化の前にrandomizeメソッドによって呼び出され、post_randomizeメソッドは、ランダム化の後にrandomizeメソッドによって呼び出されます。
class eth_frame ; rand bit [ 47 : 0 ] dest ; rand bit [ 47 : 0 ] src ; rand bit [ 15 : 0 ] f_type ; rand byte payload []; bit [ 31 : 0 ] fcs ; rand bit corrupted_frame ;constraint basic { payload . size inside {[ 46 : 1500 ]}; } function void post_randomize () this . calculate_fcs (); // ランダム化されたフレームに従って fcs フィールドを更新しますif ( corrupted_frame ) // このフレームが破損している場合this . corrupt_fcs (); // fcs を破損しますendfunction endclassconstraint_mode() メソッドと random_mode() メソッドは、ランダム化を制御するために使用されます。constraint_mode() は特定の制約をオン/オフにするために使用され、random_mode は特定の変数のランダム化をオン/オフにするために使用されます。以下のコードは、イーサネットフレームを記述し、手順的にテストします。
class eth_frame ; rand bit [ 47 : 0 ] dest ; rand bit [ 47 : 0 ] src ; rand bit [ 15 : 0 ] f_type ; rand byte payload []; bit [ 31 : 0 ] fcs ; rand bit corrupted_frame ;constraint basic { payload . size inside {[ 46 : 1500 ]}; } constraint one_src_cst { src == 48'h1f00 }constraint dist_to_fcs { fcs dist { 0 :/ 30 ,[ 1 : 2500 ] :/ 50 }; // 30 と 50 は重みです (この例では 30/80 または 50/80) }endclass . . . eth_frame my_frame ;my_frame.one_src_cst.constraint_mode ( 0 ); // 制約 one_src_cst は考慮されません。 my_frame.f_type.random_mode ( 0 ) ; //このフレームインスタンスではf_type 変数はランダム化されません。my_frame.randomize ( ) ;アサーションは、特定の条件や状態に達した後に現れる設計の特性を検証するのに役立ちます。SystemVerilogには、プロパティ仕様言語に似た独自のアサーション仕様言語があります。アサーションに用いられるSystemVerilog言語構造のサブセットは、一般的にSystemVerilog AssertionまたはSVAと呼ばれます。[ 6 ]
SystemVerilogのアサーションは、シーケンスとプロパティから構成されます。プロパティはシーケンスの上位集合であり、任意のシーケンスをプロパティのように使用できますが、通常は有用ではありません。
シーケンスは、時間演算子で拡張されたブール式で構成されます。最も単純な時間演算子は、連結を実行する演算子です。##
シーケンスS1 ; @( posedge clk ) req ## 1 gnt ;シーケンス終了このシーケンスは、gnt信号がハイになった1クロックサイクル後に信号reqがハイになった場合に一致します。なお、すべてのシーケンス操作はクロックに同期しています。
その他の逐次演算子には、繰り返し演算子や各種論理積演算子などがあります。これらの演算子を用いることで、設計者は設計要素間の複雑な関係性を表現できます。
アサーションは、シーケンスまたはプロパティを継続的に評価することで機能します。プロパティが満たされない場合、アサーションは失敗します。上記のシーケンスは、req値が低い場合に失敗します。要件を正確に表現するには、gnt次のreqプロパティが必要です。
property req_gnt ; @( posedge clk ) req |=> gnt ; endpropertyassert_req_gnt: assert property ( req_gnt ) else $ error ( "req の後に gnt が続いていません。" );この例は含意演算子を示しています|=>。含意の左側の節は前件、右側の節は後件と呼ばれます。 含意の 評価は、まず前件の評価を繰り返し行うことから始まります。前件が成功すると、後件が試され、アサーションの成否は後件の成否に依存します。この例では、がハイになるまで後件は試されずreq、その後、gnt次のクロックでがハイでない場合、プロパティは失敗します。
SystemVerilogは、アサーションに加えて、仮定とプロパティのカバレッジをサポートしています。仮定は、形式論理証明ツールが真であると仮定しなければならない条件を確立します。アサーションは、真であると証明されなければならないプロパティを指定します。シミュレーションでは、アサーションと仮定の両方がテスト刺激に対して検証されます。プロパティのカバレッジにより、検証エンジニアは、アサーションが設計を正確に監視していることを検証できます。
ハードウェア検証言語におけるカバレッジとは、シミュレーション内のサンプリングイベントに基づいて収集される統計情報のことです。カバレッジは、被試験デバイス(DUT)が十分な種類の刺激にさらされ、DUTが正しく機能していると確信できるタイミングを判断するために使用されます。これは、設計コードに計測器を組み込んで設計内のすべてのコード行が実行されたことを確認するコードカバレッジとは異なります。機能カバレッジは、設計空間におけるすべての望ましいコーナーケースとエッジケースが検証された。
SystemVerilogのカバレッジグループは、関連付けられた変数の値のヒストグラムを格納する「ビン」のデータベースを作成します。クロスカバレッジを定義することもでき、これは複数の変数の直積を表すヒストグラムを作成します。
サンプリングイベントは、サンプルが取得されるタイミングを制御します。サンプリングイベントは、Verilogイベント、コードブロックの開始または終了、あるいはカバレッジグループのメソッド呼び出しなどです。データが意味のある場合にのみサンプリングされるように注意が必要です。sample
例えば:
class eth_frame ; // 上記の定義covergroup cov ; coverpoint dest { bins bcast [ 1 ] = { 48'hFFFFFFFFFFFF }; bins ucast [ 1 ] = default ; } coverpoint f_type { bins length [ 16 ] = { [ 0 : 1535 ] }; bins typed [ 16 ] = { [ 1536 : 32767 ] }; bins other [ 1 ] = default ; } psize: coverpoint payload . size { bins size [] = { 46 , [ 47 : 63 ], 64 , [ 65 : 511 ], [ 512 : 1023 ], [ 1024 : 1499 ], 1500 }; }sz_x_t: cross f_type , psize ; endgroup endclassこの例では、検証エンジニアはブロードキャストフレームとユニキャストフレームの分布、サイズ/f_typeフィールド、およびペイロードサイズに関心を持っています。ペイロードサイズの範囲は、最小サイズフレームと最大サイズフレームを含む、注目すべき特殊なケースを反映しています。
複雑なテスト環境は、相互に通信する必要のある再利用可能な検証コンポーネントで構成されます。Verilog の「イベント」プリミティブは、異なる手続きステートメントのブロックが互いにトリガーすることを可能にしましたが、スレッド同期の強制はプログラマの(巧妙な)使用法に委ねられていました。SystemVerilog は、スレッド間同期専用の2 つのプリミティブ、 mailboxとsemaphoreを提供しています。mailbox はFIFOメッセージ キューとしてモデル化されます。オプションで、FIFO を型パラメータ化して、指定された型のオブジェクトのみが通過できるようにすることができます。通常、オブジェクトはトランザクションを表すクラス インスタンスです。トランザクションとは、検証コンポーネントによって実行される基本的な操作 (たとえば、フレームの送信) です。semaphore は、カウント セマフォとしてモデル化されます。
上記の新機能に加え、SystemVerilogはVerilogの既存の言語機能の使いやすさを向上させています。以下に、その改善点の一部を示します。
x++, ++x, x--, ) がサポートされており、 C 言語やその派生言語と同様に、他の複合代入演算子 ( , , , , , , , , , )もサポートされています。--xx += ax -= ax *= ax /= ax %= ax <<= ax >>= ax &= ax ^= ax |= aさらに、SystemVerilogは、SystemVerilog DPI(Direct Programming Interface)によって、C/C++などの外国語との便利なインターフェースを提供します。
設計検証の役割において、SystemVerilogはチップ設計業界で広く使用されています。大手EDAベンダー3社(Cadence Design Systems、Mentor Graphics、Synopsys)は、SystemVerilogを自社の混合言語HDLシミュレータに組み込んでいます。まだどのシミュレータもSystemVerilog言語リファレンスマニュアル全体をサポートしているとは主張できないため、テストベンチの相互運用性は課題となっていますが、ベンダー間の互換性を促進する取り組みが進められてい ます。2008年、CadenceとMentorは、再利用可能なテストベンチと既製の検証IPの開発を容易にするためのオープンソースのクラスライブラリと使用フレームワークであるOpen Verification Methodologyをリリースしました。SystemVerilogクラスライブラリ(VMM)を最初に公開したSynopsysは、その後、独自のVMMを一般に公開することで対応しました。多くのサードパーティプロバイダーがSystemVerilog検証IPを発表または既にリリースしています。
設計合成(ハードウェア設計記述をゲートネットリストに変換する)の役割において、SystemVerilogの採用は遅れています。多くの設計チームは、異なるベンダーの複数のツールを使用する設計フローを採用しています。ほとんどの設計チームは、フロントエンドツールスイート全体(リンター、形式検証ツール、自動テスト構造ジェネレーターなど)が共通の言語サブセットをサポートするまで、SystemVerilog RTL設計に移行できません。