News and Views 2015 Spring / Vol. 13: 上流設計&組込み

イーサネットの検証IPをテストベンチに統合する「いろは」

はじめに

2015年はムーアの法則が生まれて50年目にあたります。微細化のペースは従来ほどではないものの、FinFETのような立体構造のトランジスタの出現により、微細化のトレンドは今後も続くとみられます。しかし、それ以上のペースで複雑化しているのが機能検証です。開発時間やリソースの70%以上が機能検証に費やされているにも関わらず、機能バグがシリコンリスピンの最大の原因となっていることに変わりはありません。

IPがSoCに統合される段階に入ると、機能検証の難しさに新たな面が見えてきます。それがテストベンチの構築です。テストベンチでモデル化するSoCには、DDR、イーサネット、USB、PCI Expressなど多数のインタフェースが搭載されます。ここで大きな助けとなるのが検証IPです。

今日の商用検証IPは、概ね以下のような特徴を備えています。

  • 仕様で規定されたすべての機能が網羅されている
  • UVM/OVMなどの検証メソドロジやSystemC環境との統合が可能である
  • インタフェース仕様に準拠していることを検証するモニタ、プロトコルチェッカを内蔵している
  • 仕様に準拠したトラフィックとそうでないトラフィックの両方を扱い、設計のコンプライアンステストが実施できる
  • カバレッジエンジンがコーナーケースを見つけ検証クロージャを達成できる
  • 特定アプリケーション用トラフィックを用いた目標性能の機能検証ができる

図1. メンター・グラフィックスの検証IP – MVIPのブロック構成図1. メンター・グラフィックスの検証IP – MVIPのブロック構成

図1は、メンター・グラフィックスが提供している検証IP、MVIP(Mentor Verification IP)のブロック図です。

メンター・グラフィックスのMVIPはすべて一貫した手法で開発されており、プロトコルによって使い方が異なるということはありません。ここではその中からイーサネットを取り上げ、テストベンチに統合する手順についてご紹介します。

MVIPインスタンスの設定

MVIPはUVMネイチャーの検証IPで、プロトコルに規定されたSystemVerilogのインタフェースを中心に構成されています。イーサネットのMVIPの場合、mgc_ethernetという表記のインタフェースをトップモジュール下に置きます。

mgc_ethernet ethernet_if (.iclk_0(1’bz),
.iclk_1(1’bz),
.ireset(1’bz),
.iMDC(1’bz),
.ian_clk_0(1’bz),
.ian_clk_1(1’bz))

ここでは、ethernet_ifとしてクロック信号やリセット信号を含む形でインスタンス化します。トップモジュールでクロックやリセットを供給する場合には、インタフェースのポート接続を行います。

トップモジュールでは、MVIPインタフェースはDUTとも接続する必要があります。方向としてはDUTの送信データと制御信号をMVIPの入力で受信する形です。

assign ethernet_if.XD[1][0] = dut.txd[0]
assign ethernet_if.XD[1][1] = dut.txd[1]
assign ethernet_if.XD[1][2] = dut.txd[2]
assign ethernet_if.XD[1][3] = dut.txd[3]
assign ethernet_if.XC[1][0] = dut.txc[0]
assign ethernet_if.XC[1][1] = dut.txc[1]
assign ethernet_if.XC[1][2] = dut.txc[2]
assign ethernet_if.XC[1][3] = dut.txc[3]

逆にMVIPから出力するデータは、DUTの受信データと制御信号として接続します。

assign dut.rxd[0] = ethernet_if.XD[0][0]
assign dut.rxd[1] = ethernet_if.XD[0][1]
assign dut.rxd[2] = ethernet_if.XD[0][2]
assign dut.rxd[3] = ethernet_if.XD[0][3]
assign dut.rxc[0] = ethernet_if.XC[0][0]
assign dut.rxc[1] = ethernet_if.XC[0][1]
assign dut.rxc[2] = ethernet_if.XC[0][2]
assign dut.rxc[3] = ethernet_if.XC[0][3]

SystemVerilogのインタフェースを、UVMのコンフィギュレーションデータベース – uvm_config_dbに対して仮想インタフェースを定義し、ハンドルを付与します。

typedef virtual mgc_ethernet bfm_type
uvm_config_db #( bfm_type )::set(null , “uvm_test_top” , “ETHERNET_IF” , ethernet_if )

uvm_config_dbにおいて、ethernet_ifにETHERNET_IFという名前を付け、bfm_typeのハンドルを付与しています。これはトップモジュールのinitialブロックで定義する必要があります。

UVM_TESTNAMEに基づいてUVM環境を構築するために、以下のようにuvm_testのrun_testメソッドをコールします。

run_test(“”)

図2. イーサネットのエージェント図2. イーサネットのエージェント

イーサネットMVIPのエージェント

エージェントの役割はインタフェースにおける動作を駆動し、モニタすることです。通常エージェントにはドライバ、シーケンサ、コンフィギュレーションなどが含まれます。環境であるenvはエージェントを始め、スコアボード、カバレッジコレクタなどの解析コンポーネントを配置します。図2はethernet_agentというクラスです。

このクラスでは個別検証要件に合わせたコンフィギュレーション設定も行います。例えばアクティブ/パッシブの設定、インターフェースタイプの設定、クロック/リセットの設定などです。

<cfg_obj>.agent_cfg.is_active = 1;
<cfg_obj>.agent_cfg.is_tx = 1;

上記コードは、エージェントが持つオプションによって、アクティブモード、送信モードに設定されています。

<cfg_obj>.agent_cfg.if_type = ETHERNET_XGMII;

イーサネットの転送にはXGMII、CGMII、10GBASE-Rなどがありますが、上記コードではそのタイプをXGMIIに設定しています。

<cfg_obj>.agent_cfg.ext_clock = 1;
<cfg_obj>.agent_cfg.ext_reset = 1;

エージェントにはクロックとリセットの供給源を決める設定があり、上記コードはテストベンチなどの外部から供給する場合の設定です。このオプションが0の場合、MVIPから供給することを意味します。クロックは内部クロックを使い、リセットは外部から供給することも、また外部に供給するように設定することも可能です。

<cfg_obj>.agent_cfg.txn_ltnr.data_frame = 1;
<cfg_obj>.agent_cfg.txn_ltnr.cntrl_frame = 1;

上記コードはリスナの設定です。MVIPには送受信端におけるデータ、制御、種別などのイーサネットフレームに共有のリスナを内蔵しています。ここではデータフレームおよび制御フレームのリスナを有効にしています。

<cfg_obj>.agent_cfg.en_cvg.tx.frames = 1;
<cfg_obj>.agent_cfg.en_cvg.rx.frames = 1;

上記コードはカバレッジコレクタに関する設定です。イーサネットインターフェースの送信端にあるカバレッジコレクタ、受信端のカバレッジコレクタを有効にしています。これで送信、受信したフレームからカバレッジデータが収集されます。

<cfg_obj>.agent_cfg.en_cvg.rx.if_specific = 1;

また上記オプション設定は、選択したインタフェースに合わせたカバレッジコレクタを設定します。例えば、インタフェースとして10GBASE-Rを選定すると、10GBASE-Rのカバレッジコレクタが設定されます。