前回はこちら:msyksphinz.hatenablog.com
前回までで作っているUVMの環境では、DUTは入力を即時出力するようなデザインなのでイマイチ面白くない。
UVMのスコアボードは、中間結果を取っておいてそれを使って比較できるはずなので、メモリなどの記憶素子も検証できるはずだ。
前回のメモリのデザインを検証するために、以下のようなスコアボードとモニタを作ってみた。
mem_rw_monitor.sv
これのポイントは、メモリが1サイクル遅れてデータを読み出すためにアドレスとの同期をとるためのバッファを1つ入れているのだが、これが合っているのか分からん。というか、波形が見えないのでUVMはどうやって検証したらいいんだ。
virtual task run_phase (uvm_phase phase); logic read_req; super.run_phase (phase); // This task monitors the interface for a complete // transactions and writes into analysis port when complete forever begin logic prev_read_req; logic [7:0] prev_read_addr; mem_rw_seq_item item = new; item.i_valid = 1'b0; @ (posedge vif.clk); // Check current cycle read request read_req = 0; if (vif.i_valid && !vif.i_rw) begin prev_read_req = 1'b1; prev_read_addr = vif.i_addr; end if (vif.i_valid && vif.i_rw) begin item = mem_rw_seq_item::type_id::create("write_tr", this); item.i_valid = vif.i_valid; item.i_addr = vif.i_addr; item.i_rw = vif.i_rw; item.i_data = vif.i_data; item.o_data = 'x; `uvm_info (get_type_name(), $sformatf("Monitor found packet %s", item.convert2str()), UVM_LOW) mon_analysis_port.write(item); end if (prev_read_req) begin item = mem_rw_seq_item::type_id::create("read_tr", this); item.i_valid = 1'b1; item.i_addr = prev_read_addr; item.i_rw = 0; // Read item.i_data = 'x; item.o_data = vif.o_data; `uvm_info (get_type_name(), $sformatf("Monitor found packet %s", item.convert2str()), UVM_LOW) mon_analysis_port.write(item); prev_read_req = 1'b0; end end // forever begin endtask // run_phase
mem_rw_scoreboard.sv
スコアボード側は、インタフェースの情報を受け取って単純に比較する。
virtual function write (mem_rw_seq_item item); if (item.i_valid) begin if (item.i_rw) begin // 書き込み操作:期待値メモリを更新 expected_mem[item.i_addr] = item.i_data; end else begin // 読み出し操作:データを比較 if (expected_mem[item.i_addr] !== item.o_data) begin `uvm_error("DATA_MISMATCH", $sformatf("Address 0x%0h: Expected 0x%0h, Got 0x%0h", item.i_addr, expected_mem[item.i_addr], item.o_data)) end else begin `uvm_info("DATA_MATCH", $sformatf("Address 0x%0h: Data matches (0x%0h)", item.i_addr, item.o_data), UVM_LOW) end end end `uvm_info (get_type_name(), $sformatf("Scoreboard found packet %s", item.convert2str()), UVM_LOW)
とりあえずまあ、テストケース事態はFailしまくりなのだが、コンパイルは通っているのでもうちょっと解析したい。
UVM_INFO ./model/mem_rw_driver.sv(21) @ 156600000: uvm_test_top.e0.a0.d0 [DRV] Wait for item from sequencer UVM_INFO ./model/mem_rw_sequence.sv(21) @ 156600000: uvm_test_top.e0.a0.s0@@seq [SEQ] Generate new item: ------------------------------------------------------------------------------- Name Type Size Value ------------------------------------------------------------------------------- item mem_rw_seq_item - @26437 i_valid integral 1 'h1 i_rw integral 1 'h0 i_addr integral 8 'h37 i_data integral 32 'hd8f3ff1c o_data integral 32 'h0 begin_time time 64 156600000 depth int 32 'd2 parent sequence (name) string 3 seq parent sequence (full name) string 25 uvm_test_top.e0.a0.s0.seq sequencer string 21 uvm_test_top.e0.a0.s0 ------------------------------------------------------------------------------- UVM_INFO ./model/mem_rw_driver.sv(21) @ 156700000: uvm_test_top.e0.a0.d0 [DRV] Wait for item from sequencer UVM_INFO ./model/mem_rw_monitor.sv(61) @ 156700000: uvm_test_top.e0.a0.m0 [mem_rw_monitor] Monitor found packet i_valid=1, i_rw=0, i_addr=0x37, i_data=0x0, o_data=0x1ac20d02 UVM_ERROR ./model/mem_rw_scoreboard.sv(28) @ 156700000: uvm_test_top.e0.sb0 [DATA_MISMATCH] Address 0x37: Expected 0xb45b99d3, Got 0x1ac20d02 UVM_INFO ./model/mem_rw_scoreboard.sv(35) @ 156700000: uvm_test_top.e0.sb0 [mem_rw_scoreboard] Scoreboard found packet i_valid=1, i_rw=0, i_addr=0x37, i_data=0x0, o_data=0x1ac20d02 UVM_INFO ./model/mem_rw_sequence.sv(21) @ 156700000: uvm_test_top.e0.a0.s0@@seq [SEQ] Generate new item: