FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Vivado Simulatorを使ってUVMに入門する (8. スコアボードの導入)

sites.google.com

次は、期待値の自動比較を考えていく。 スコアボードを導入するというわけだ。

1000回のランダム書き込みの後、1000回リードして比較をする、ということを自動化できるようにする。

このために、スコアボードを組み込む。このためにはモニタにanalysis_portというものを導入する。 まずはスコアボードのアイテムを定義しよう。これはスコアボードのエントリフィールドに相当するものだと思う。

class sample_scrbd_item extends uvm_object;
  bit [7:0] addr, data;
  `uvm_object_utils_begin(sample_scrbd_item)
    `uvm_field_int(addr, UVM_DEFAULT)
    `uvm_field_int(data, UVM_DEFAULT)
  `uvm_object_utils_end
  function new (string name="sample_scrbd_item");
    super.new(name);
  endfunction
endclass

そしてこのクラスを使って、analysis_portを使い挙動を書き込む:

  • 期待値用のanalysis_portを組み込む
  • 観測値用のanalysis_portを組み込む
  • analysis_portを用いて、スコアボードに書き込む

これらをsample_master_monitorに埋め込んでおく。

  • model/sample_master_monitor.sv
class sample_master_monitor extends uvm_monitor;
  virtual sample_if vif;
  uvm_analysis_port #(sample_scrbd_item) ap_write;
  uvm_analysis_port #(sample_scrbd_item) ap_read;
  event scrbd_e;  //イベント定義
  `uvm_component_utils(sample_master_monitor)
  function new (string name, uvm_component parent);
    super.new(name, parent);
    ap_write = new("ap_write", this);
    ap_read  = new("ap_read", this);
  endfunction

テストベンチ側のumv_envクラスを定義する(tb_env.sv)。なんとなく、sample_envgp_scoreboardをさらに上位で囲ったような構造をしている。

class tb_env extends uvm_env;
  sample_env    sample_model;
  gp_scoreboard #(sample_scrbd_item) sample_scrbd;  // Generic score-board
/* ... 途中省略 ... */

sample_test.svは以下のような構成になっている。

  • sample_test.sv
class sample_test extends uvm_test;

  `uvm_component_utils(sample_test)
  tb_env env;
/* ... 途中省略 ... */
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    uvm_config_db #(uvm_object_wrapper)::set(this,
      "env.sample_model.master.sequencer.run_phase", "default_sequence",
      write_read_seq::type_id::get()
      );
    uvm_config_db #(uvm_object_wrapper)::set(this,
      "env.sample_model.slave.sequencer.run_phase",  "default_sequence",
      normal_response_seq::type_id::get()
      );
    env = tb_env::type_id::create("env", this);
  endfunction // build_phase
UVM_INFO @ 0: uvm_test_top.env.sample_model.slave.driver [SLAVE] write access accept. addr=10h, data=5ah
UVM_INFO @ 0: uvm_test_top.env.sample_model.master.monitor [MON] write addr=10h wdata=5ah
UVM_INFO @ 0: uvm_test_top.env.sample_scrbd [SCRBD] write expected data
UVM_INFO @ 0: uvm_test_top.env.sample_model.master.driver [DRIVER] Hi
UVM_INFO @ 1000: uvm_test_top.env.sample_model.slave.driver [SLAVE] read access accept. adr=10h
UVM_INFO @ 1000: uvm_test_top.env.sample_model.slave.driver [SLAVE] read data is = 5ah
UVM_INFO @ 1000: uvm_test_top.env.sample_model.master.monitor [MON] read  addr=10h rdata=5ah
UVM_INFO @ 1000: uvm_test_top.env.sample_scrbd [SCRBD] write observed data
UVM_INFO @ 1000: uvm_test_top.env.sample_scrbd [SCRBD] data compare OK
UVM_INFO @ 1000: uvm_test_top.env.sample_model.master.driver [DRIVER] Hi