For Good FPGA Design

UVMの環境構築!(3) Driver

UVMの環境構築第3回では、ドライバーの定義(作成)方法について解説していきます。

なお、ソースコードはGitHubに公開しています。

目次

シリーズ目次

UVMの環境構築!シリーズの目次は、第1回 解説編の一番下をご覧ください。

ドライバーの概要

ドライバーはuvm_driverまたはそのサブクラスを継承して定義します。

ドライバーはシーケンサーからトランザクションを取得し、シグナルレベルに変換します。そして、DUTをドライブします。

DUTのドライブはvirtual interfaceを使用します。DUTのポートに接続したinterfaceと、ドライバーに定義したvirtual interfaceはつながっています(やり方はmy_driver_base.svで説明します)。したがって、ドライバーのvirtual interfaceの信号を変化させると、DUTのポートにも反映されます。

図1 UVMにおけるドライバー

ドライバーの定義方法

ドライバーを定義する際は、DUTによらずお決まりで書くことがあります。したがって、次の手順で記述するとよいです。

  • uvm_driverを継承し、お決まりの部分だけ記述したベースクラスmy_driver_baseを定義
  • my_driver_baseを継承し、DUTに対応させたmy_driverを定義

また、シーケンサーからトランザクションを取得するTLMポートは、uvm_driverで以下のseq_item_portとして定義されているため、ユーザーが新たに定義する必要はありません。

1
2
3
4
5
6
class uvm_driver #(type REQ=uvm_sequence_item, type RSP=REQ) extends uvm_component;
 
  uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;
  ...
  ...
endclass

my_driver_base

それでは、ソースコードを見ながら、ドライバーの定義方法について説明します。

my_driver_base.sv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
virtual class my_driver_base #(type REQ = uvm_sequence_item, type RSP = REQ)
    extends uvm_driver #(REQ, RSP);
 
    VIF_DRIVER  vif;
 
    /* Constructor */
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
 
    /* Build phase */
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
 
        if (!uvm_config_db #(VIF_DRIVER)::get(this, get_full_name(), "vif", vif))
            `uvm_error("VIF_NOT_SET", {"No interface assigned to ", get_full_name(), ".vif"});
    endfunction
 
    /* Run phase */
    task run_phase (uvm_phase phase);
        forever begin
            get_drive_item();
        end
    endtask
 
    /* Sub class must implement this behaviour */
    pure virtual task get_drive_item();
 
endclass
  • 1~2行目:uvm_driverを継承して、my_driver_baseを定義します。REQはトランザクションのタイプです。RSPはシーケンサーに戻すトランザクションのタイプです。
  • 4行目:virtual interfaceを定義します。pkg.svの中で、インターフェースのタイプVIF_DRIVERを次のように定義しています。
1
2
/* Typedef */
typedef virtual my_if VIF_DRIVER;
  • 6~9行目:コンストラクタを定義します。
  • 11~17行目:Build phaseを定義します。super.build_phase(phase)は必ず必要です。uvm_config_dbにより、virtual interfaceの設定をします。
  • 19~24行目:Run phaseでは、シーケンサーからトランザクションを受け取り、DUTをドライブするメソッドget_drive_item()を無限に繰り返します。
  • 26~27行目:my_driver_baseのサブクラス(my_driver)では、必ずget_drive_item()の動作を実装する必要があります。

my_driver_baseはDUTに依存しません。あらかじめmy_driver_baseを用意しておくことで、効率的にドライバーを定義することができます。

my_driver

my_driver_baseを継承して、DUTに対応したmy_driverを定義します。

my_driver.sv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class my_driver extends my_driver_base #(my_item);
    `uvm_component_utils(my_driver)
    /* Constructor */
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    /* Get transaction and drive DUT in Run phase */
    task get_drive_item();
        seq_item_port.get_next_item(req);
        drive_item(req);
        seq_item_port.item_done();
    endtask
    /* Drive DUT */
    task drive_item(input REQ item);
        @ (posedge vif.clk);
        vif.rst     <=  item.rst;
        @ (posedge vif.clk);
        vif.a_in    <=  item.a_in;
        vif.b_in    <=  item.b_in;
        vif.start   <=  1'b1;
        @ (posedge vif.clk);
        vif.start   <=  1'b0;
        for (int i = 0; i < `BW_A; i++)
             @ (posedge vif.clk);
 
    endtask
 
endclass
  • 1行目:my_driver_baseを継承して、my_driverを定義します。トランザクションのタイプREQは、my_itemにします。my_itemは、my_item.svで定義しています。
  • 2行目:UVMマクロを書きます。
  • 3~6行目:コンストラクタを定義します。
  • 7~12行目:get_drive_item()の動作を実装します。
    • seq_item_port.get_next_item(req)で、シーケンサーからトランザクションを取得します。
    • drive_item(req)で、DUTをドライブします。
    • seq_item_port.item_done()で、トランザクションについての処理が完了したことを通知します。
  • 13~26行目:virtual interfaceの信号を操作します。このvirtual interfaceはuvm_config_dbによって、DUTに接続されたinterfaceとつながっています。したがって、このメソッドでDUTがドライブされます。

まとめ

今回は、ドライバーの定義方法について解説しました。シリーズを通してご覧いただけると、UVM検証環境が構築できるようになりますので、ぜひ他のコンポーネントの解説もご覧ください。

シリーズ目次はこちら

アバター画像
この記事を書いた人
ジーノ。大手電機メーカーで、基板設計の全般と、FPGAの設計に従事した経験を活かし、FPGAについて情報発信中。
RTL設計、シミュレーション、タイミング・クロージャ、FPGAまわりのハードウェア開発まで、幅広く取り扱っております。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA