FPGA開発日記

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

Vivado Simulatorを使ってUVMに入門する (21. スコアボードを活用するDUTを作りたい)

前回はこちら: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: