UVMの環境構築第2回では、トランザクションとインターフェースの定義(作成)方法について解説していきます。
なお、ソースコードはGitHubに公開しています。
目次
UVMの環境構築!シリーズの目次は、第1回 解説編の一番下をご覧ください。
DUTについては第1回 解説編の下記の記事で説明したものを使います。
DUTのポートのビット幅は、defineした値を使って、トップモジュールで指定します。このdefineの値はトランザクションとインターフェースの定義でも使用しています。
my_definitions.sv
1 2 3 4 5 6 7 | /* DUT parameters */ `define BW_A 8 `define BW_B 4 /* Sequence */ `define N_TRIAL_MIN 10 `define N_TRIAL_MAX 20 |
トランザクションはUVMのコンポーネント間の通信で使われるデータです。たとえば、次のように使われます。
では、早速トランザクションのソースコードを見ながら解説していきます。
再利用性を高めるため、my_item_baseとmy_itemに分けて作成します。
my_item_base.sv
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class my_item_base extends uvm_sequence_item; rand bit rst; rand bit [`BW_A - 1:0] a_in; rand bit [`BW_A - 1:0] b_in; logic [`BW_A + `BW_B - 1:0] mult_out; `uvm_object_utils_begin(my_item_base) `uvm_field_int(rst, UVM_DEFAULT) `uvm_field_int(a_in, UVM_DEFAULT) `uvm_field_int(b_in, UVM_DEFAULT) `uvm_field_int(mult_out, UVM_DEFAULT) `uvm_object_utils_end function new(string name = "my_item_base"); super.new(name); endfunction endclass |
my_item.sv
1 2 3 4 5 6 7 8 | class my_item extends my_item_base; `uvm_object_utils(my_item) constraint CA { (a_in >= 1) && (a_in <= 200); } constraint CB { (b_in >= 1) && (b_in <= 10); } function new(string name = "my_item"); super.new(name); endfunction endclass |
rand属性をつけたフィールドに制約を与えます。制約を与えることで、実際に入力され得る値の中で乱数を発生させることができます。
制約はテストケースによる場合が多いため、my_item_baseには制約をつけません。テストケースによって制約を変え、my_item1, my_item2,…というのを定義していくとよいです。
UVMではvirtual interfaceを使用して、ドライバーとDUT、またはコレクターとDUTを接続するので、インターフェースの定義が必須となります。
以下に定義を示します。インターフェースとDUTの接続は、トップモジュールの記事で解説します。
my_if.sv
1 2 3 4 5 6 7 8 9 10 11 | interface my_if (input bit clk); logic rst; logic [`BW_A - 1:0] a_in; logic [`BW_B - 1:0] b_in; logic start; logic [`BW_A + `BW_B - 1:0] mult_out; logic valid; clocking cb @ (posedge clk); endclocking endinterface |
今回は、トランザクションとインターフェースの定義方法について解説しました。UVMではどちらの定義も必要となります。
次回からは、UVM環境を構成するコンポーネントの作成方法について解説していきます。
シリーズ目次はこちら