SystemVerilog

SystemVerilogとは?

SystemVerilogはハードウェア記述言語の一種です。1980年代にVerilog-HDLやVHDLといったハードウェア記述言語が開発され、大規模な論理回路を言語で設計することが可能となりましたが、設計対象の回路規模が大きくなるにつれて検証の作業量が膨大になってきており、検証に関する機能が強化されたSystemVerilogが登場しました。SystemVerilogはVerilog-HDLを拡張した言語になっているため、Verilog-HDLで書かれた既存の資産があればそのまま移行して利用することができます。以前は設計用言語のVerilog-HDL(IEEE 1364-)と検証用言語のSystemVerilog(IEEE 1800-)として別々に規格策定されていましたが、2024年に公開された仕様(IEEE Std 1800-2023)ではSystemVerilogがVerilog-HDLの後継として統合されたことが強調されています。

さて、SystemVerilogとは実際にどのような記述になるのでしょうか。これまでハードウェア記述言語というとVerilog-HDLとVHDLがあります。Verilog-HDLは記述が簡潔で習得が容易な点が利点であり、一方のVHDLは文法的な曖昧さが少なく、設計者の意図した通りの回路が記述しやすい、といった点が利点として挙げられてきました。SystemVerilogはVerilog-HDLの後継という位置付けですが、設計、仕様と検証を統一的に記述できる言語であり、そこが大きな利点となります。また、Verilog-HDLの問題点が解消され、多くの便利機能が追加されています。まずは簡単な設計例として非同期リセット付きの8ビットレジスタをSystemVerilogで記述してみましょう。

HDL Coderの画面と、8ビットレジスタのSystemVerilog例。module registerでclk,xrst,din[7:0],q_outを宣言。always_ff@(posedge clk or negedge xrst)で非同期Lowリセット時q_out=0、それ以外はdinを保持。注釈付き。

図1. 8ビットレジスタをSystemVerilogで記述

ここでalways_ff文が利用されていますが、これはVerilog-HDLにはなかった構文です。同じ回路をVerilog-HDLで記述すると以下のようになりますが、always文を利用します。

module register (
  input        clk,
  input        xrst,
  input  [7:0] i_in,
  output reg [7:0] o_out
);
always @(posedge clk or negedge xrst) begin
  if (~rst_x) o_out <= 8'h0;
  else o_out <= i_in;
end
endmodule

always文の問題点として、センシティビティ・リストに必要な信号を全て記述しておかないと意図した動作にならない場合があったり、if文などで条件漏れによって意図しないラッチが生成されていたりという問題がありました。この問題に対応するためにalways_ff文(FlipFlop用)、always_comp文(組み合わせ回路用)、always_latch文(ラッチ記述用)が追加されました。

また、他のハードウェア記述言語 -VHDL- との比較はどうでしょうか。VHDLで同じ回路を記述すると以下の様になります。

entity register is
  port (
    clk : in std_logic;
    xrst : in std_logic;
    i_in : in std_logic_vector(7 downto 0);
    o_out : out std_logic_vector(7 downto 0)
  );
end register;

architecture rtl of register is
signal r_out : std_logic_vector(7 downto 0);
begin
  process (clk, xrst) begin
    if (xrst = '0') then
       r_out <= (others => '0');
    elsif (clk'event and clk = '1') then
      r_out <= i_in;
    end if;
  end process;
  o_out <= r_out;
end rtl;

実際の記述を見てどのような印象を持たれたでしょうか?記述量についてはVerilog-HDL/SystemVerilogに軍配が上がりそうですね。このようにVerilog-HDLはデザインを簡潔に記述できるのが特徴で、SystemVerilogはその利点を引継ぎつつ機能改善が図られた、と理解するのが良いでしょう。先ほどご紹介したalways_ff/always_comp/always_latch以外にも多くの機能が追加されています。

  • 多次元配列のサポート、豊富なデータタイプ
  • 並列処理を記述するための機能追加
  • 便利な初期値設定(可変長対応のリテラル)
  • 様々な便利構文(foreach文、Return文、Do while文等)の追加

SystemVerilogは従来のハードウェア記述言語に比べて様々な改善が図られていますが、それでもハードウェア設計に携わったご経験の無い方にとってはハードルの高い言語です。普段アルゴリズムの開発を主体とされていて、試作のためにハードウェア記述が必要、という事であれば、MATLABやSimulinkといった開発環境を利用することもできます。

MATLABやSimulinkは制御・信号処理画像処理や通信といった各種アルゴリズムの開発に幅広く利用されており、豊富なライブラリを利用することでコンパクトかつ直観的な記述でアルゴリズムやテストベンチを記述できます。また、MATLABやSimulinkで記述されたコード・モデルからSystemVerilogを生成できますので、FPGA等ハードウェアに実装して動作を確認できます。

ハードウェア検証のためのSystemVerilog

さて、SystemVerilogによるデザイン記述について簡単に紹介しましたが、SystemVerilogと言えば検証、といった印象をお持ちの方も多いかもしれません。実際、SystemVerilogでは高度な検証機能が提供されています。

ハードウェア記述言語でデザインを記述したとして、デザインが意図した通りに動いているかをどのように確認できるでしょうか?従来、デザインの入力に検証用のデータを与え、期待通りの出力が得られているかを確認する、というのが一般的に行われていた検証ですが、特定のデータ(入力パターン)でないと発生しない問題があるなど課題がありました。

機能を検証するための手法はランダム検証や機能カバレッジ検証など色々ありますが、その一つとして、アサーション・ベース検証があります。アサーション・ベース検証は出力端での期待値比較とは異なり、各ブロックの入力条件など回路内の重要な動きを仕様として定義し、その仕様に違反していないかどうかを監視します。一例として以下のような仕様を定義できます。

“あるサイクルで信号reqがHighになり、その4サイクル後にackがHighになるというシーケンスが検出された場合、その次のサイクルでは信号rdyがHighでなければならない”

モデルベースデザインから生成されたHDLのコードレポート画面、レジスタのSystemVerilog記述例(always_ffと非同期リセットxrstの説明)、およびクロックと信号のタイミング波形。赤丸はアサーション検証の観測点。

図2. アサーション・ベース検証の例

このような検証を行いたい場合、SystemVerilogではSVA(SystemVerilog Assertions)という言語が提供されています。上記のような仕様を定義したい場合、SVAでは以下のように記述ができます。

property mytest;
@(posedge clk) req ##4 ack |=> rdy;
endproperty

“|=>”はインプリメンテーション演算子と呼ばれ、左辺の条件が成立した場合にプロパティを確認することを意味します。非常にコンパクトな記述で検証仕様が定義できていることがわかります。デザインを検証するためには仕様との比較が必要になってきますが、このように設計で利用する言語と検証に利用する言語が同じ言語であることは効率面で大きなメリットがあります。

さて、SystemVerilogではアサーション・ベース検証のための言語が提供されており、コンパクトな記述で仕様を定義できることがわかりました。但し、設計者はどのようなアサーションが効果的かを考える必要がありますし、アサーションを入れる場所や量というのも重要です。アサーションに限らず、検証について社内で既に指針が示されている・ガイドラインがある、という場合は良いですが、そうでない場合は既存の検証用ライブラリを活用する方法もあります。SystemVerilogの場合、UVM (Universal Verification Methodology)と呼ばれる検証用ライブラリが利用できます。

SystemVerilog DPI

SystemVerilogにはCの関数を呼び出せるDPI(Direct Programming Interface)と呼ばれる機能が存在します。この機能を利用することで、既存のCライブラリを含むC言語のファンクションをSystemVerilogのテストベンチで利用できるようになります。SystemVerilogからCファンクションを利用するには、以下の様にインポートを行います。

import “DPI-C” function  function_name(arguments);
 

SystemVerilogは多次元配列や列挙データ型をサポートしているのでVerilog-HDLよりもテストベンチの記述は楽になりましたが、それでもハードウェア記述言語ではありますので複雑な処理はC言語で記述するのが良いでしょう。また、C言語からSystemVerilogコードを呼び出す、ということも可能ですので、ホスト側のソフトウェアで処理時間を要する機能をハードウェアで処理するようなアクセラレータ的な使い方もできますし、ハードウェアのテストプログラムをC言語で記述する、といったハード・ソフトの協調検証に利用することができます。

さて、SystemVerilogのDPI機能によりC言語で記述された複雑なテストベンチの利用が可能になりますが、例えC言語を用いたとしても複雑な処理を記述するというのはエンジニアにとって楽な作業ではありません。テストベンチの記述に苦労されているのであれば、MATLABやSimulinkといった環境でテストベンチを記述する方法もあります。

以下は無線通信システムをSimulinkでモデル化した例ですが、PHYの信号処理からRFアナログ部まで、豊富なライブラリでコンパクトに記述でき、所望のブロック出力をテストベンチとして利用できます。

RF Satellite LinkのSimulinkブロック図。上段は衛星ダウンリンク送信機(ビット生成→16‑QAM→RRC→HPA非線形/プリディストーション→送信増幅器→アンテナ)。中段は伝搬路(自由空間損失、ドップラー誤差、周波数オフセット)。下段は地上局受信機(RF前段→RRC→AGC→ADC→I/Q不均衡補正→復調)。右側にBERやコンステレーション等の解析スコープ。

図3. RF Satellite Link

SimulinkによるSystemVerilog DPIコンポーネントの作成

MATLABやSimulinkでテストベンチが記述できることを述べましたが、SystemVerilogの環境にはどのように接続できるでしょうか。MATLABやSimulinkで記述されたコード・モデルからは検証用のコンポーネントを生成する機能があり、SystemVerilog DPIコンポーネントとしてコード生成が可能です。複雑なテストベンチの記述に苦労している場合は一つの選択肢として検討できるでしょう。

Simulinkではコード生成時の各種オプションを設定できるGUIが提供されていますが、このGUI上でデータ型等の必要な設定を行い、コード生成を実行すればSystemVerilog DPIコンポーネントの生成が行えます。また、生成されたDPIコンポーネントが正しく動作しているかを検証するためのテストベンチも同時に生成可能で、各種HDLシミュレータですぐに検証が可能です。

SystemVerilogのコンポーネントテストベンチ構成図。中央にDPI Component(C)、左にStimuli、右にChecker。上部のTiming Controllerが両者を制御し、矢印でStimuli→DPI→Checkerへのデータ流れとバッファを示しています。

図4. Component TB (SystemVerilog)

著者

MathWorks Japan アプリケーションエンジニアリング部 部長 大塚 慶太郎

MathWorks Japan アプリケーションエンジニアリング部 部長 大塚 慶太郎

前職では無線通信エンジニアとして3G基地局やフルカスタム衛星携帯などの研究開発に従事。電子情報通信学会等での活動、研究から得た技術の権利化から量産開発、アプリケーションサポートまで、無線通信に関する研究開発の一連の流れを経験。2013年に現職のMathWorks Japanに入社し、電気・通信業界におけるモデルベースデザインの普及に努める。通信工学専攻。


参考: HDL Coder, HDL Verifier, FPGA、ASIC、および SoC 開発, ミックスドシグナル システム, 半導体, UVM 検証, ASIC 設計, ASIC 検証, 高位合成 (HLS)