前回はこちら: msyksphinz.hatenablog.com
UVMのさらなるテストベンチを試行するために、以下のウェブサイトのサンプルを試してみることにした。
このページでは、別ページで作ったSystemVerilogのレジスタコントローラ(レジスタファイルみたいなもの)を検証するためのUVM環境を作り上げていくものになっている。
スコアボードの構成は、write()
を呼び出すことによってスコアボードを更新する。
virtual function write (reg_item item); if (item.wr) begin if (refq[item.addr] == null) begin refq[item.addr] = new; end refq[item.addr] = item; `uvm_info (get_type_name(), $sformatf("Store addr=0x%0h wr=0x%0h data=0x%0h", item.addr, item.wr, item.wdata), UVM_LOW) end
プロトコルが読み出し操作の時は、スコアボード内で比較して整合性をチェックしている:
if (!item.wr) begin if (refq[item.addr] == null) begin if (item.rdata != 'h1234) begin `uvm_error(get_type_name(), $sformatf("First time read, addr=0x%0h exp=1234 act=0x%0h", item.addr, item.rdata)) end else begin `uvm_info(get_type_name(), $sformatf("PASS! First time read, addr=0x%0h exp=1234 act=0x%0h", item.addr, item.rdata), UVM_LOW) end end else begin // if (refq[item.addr] == null) if (item.rdata != refq[item.addr].wdata) begin `uvm_error(get_type_name(), $sformatf("addr=0x%0h exp=0x%0h act=0x%0h", item.addr, refq[item.addr].wdata, item.rdata)) end else begin `uvm_info(get_type_name(), $sformatf("PASS! First time read, addr=0x%0h exp=0x%0h act=0x%0h", item.addr, refq[item.addr].wdata, item.rdata), UVM_LOW) end end // else: !if(refq[item.addr] == null) end // if (!item.wr) endfunction // write
tb_top.sv
を以下のように構成して、テストベンチを構築した:
`timescale 1ps/1ps module tb_top; // UVM class library `include "uvm_macros.svh" import uvm_pkg::*; // uvm user code `include "model.svh" `include "test.sv" ///////////////////////////////////// logic clk, rstz; reg_if vif(clk); // clk initial begin clk <= 1'b1; #100; forever #50 clk <= ~clk; end // rstz initial begin rstz <= 1'b0; #80 rstz <= 1'b1; end reg_ctrl u0 ( .clk (clk ), .rstn (vif.rstn ), .addr (vif.addr ), .sel (vif.sel ), .wr (vif.wr ), .wdata (vif.wdata), .rdata (vif.rdata), .ready (vif.ready) ); initial begin uvm_config_db #(virtual reg_if)::set(uvm_root::get(), "*.*", "reg_vif", vif); run_test(); end endmodule // tb_top
テストシーケンスは以下のように構築している:
class test extends uvm_test; `uvm_component_utils(test); function new(string name="test", uvm_component parent=null); super.new(name, parent); endfunction // new env e0; virtual reg_if vif; virtual function void build_phase(uvm_phase phase); super.build_phase(phase); e0 = env::type_id::create("e0", this); if (!uvm_config_db#(virtual reg_if)::get(this, "", "reg_if", vif)) `uvm_fatal("TEST", "Did not get vif") uvm_config_db #(virtual reg_if)::set(this, "e0.a0.*", "reg_vif", vif); endfunction // build_phase virtual task run_phase (uvm_phase phase); gen_item_seq seq = gen_item_seq::type_id::create("seq"); phase.raise_objection(this); apply_reset(); seq.randomize() with {num inside {[20:30]}; }; seq.start(e0.a0.s0); #200; phase.drop_objection(this); endtask // run_phase virtual task apply_reset(); vif.rstn <= 0; repeat(5) @ (posedge vif.clk); vif.rstn <= 1; repeat(10) @ (posedge vif.clk); endtask // apply_reset endclass // test
これでVivado Simulatorで走らせてみたが、uvm_config_db
が何となくうまくいっていないらしい。
UVM_FATAL test.sv(14) @ 0: uvm_test_top [TEST] Did not get vif