Vivado Simulatorを使ってUVMに入門する (25. 2ポートArbiterのUVMを考える) - FPGA開発日記

FPGA開発日記

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

Vivado Simulatorを使ってUVMに入門する (25. 2ポートArbiterのUVMを考える)

前回はこちら:msyksphinz.hatenablog.com

UVMを使って、2ポートのArbiterを検証することを考えたい。

2ポートのRound Robin Arbiterは、現在のPriorityに応じてAcceptするポートを変えるArbiterだ。

  • arbiter2_rr.sv
always_comb begin
  w_curr_ptr_next = r_curr_ptr;

  case (r_curr_ptr)
    'h0 : begin
      if (i_valid0) begin
        w_curr_ptr_next = 1;
        o_data = i_data0;
      end else begin
        o_data = i_data1;
      end
    end
    default : begin // 'h1 : begin
      if (i_valid1) begin
        w_curr_ptr_next = 0;
        o_data = i_data1;
      end else begin
        o_data = i_data0;
      end
    end
  endcase // case (r_curr_ptr)

  o_valid = i_valid0 | i_valid1;

end // always_comb

always_ff @ (posedge i_clk, negedge i_reset_n) begin
  if (!i_reset_n) begin
    r_curr_ptr <= 0;
  end else begin
    r_curr_ptr <= w_curr_ptr_next;
  end
end

UVMのスコアボードに、これを再現するための検証チェッカーのコードを追加してみる。

  • arbiter2_rr_scoreboard.sv
  virtual function write (arbiter2_rr_seq_item item);

    `uvm_info (get_type_name(), $sformatf("pointer=%d, Scoreboard found packet %s", curr_pointer, item.convert2str()), UVM_LOW)

    if ((item.i_valid1 | item.i_valid0) &&
        !item.o_valid) begin
        `uvm_error (get_type_name(),
                    $sformatf ("valid3-0 activated, but output not activated"));
    end

    case (curr_pointer)
      'h0 : begin
        if (item.i_valid0) begin
          curr_pointer = 1;
          if (item.o_data != item.i_data0) begin
            `uvm_error (get_type_name(),
                        $sformatf ("valid0 activated, but data different. o_data=0x%04h data0=0x%h",
                                   item.o_data, item.i_data0));
          end
        end else if (item.i_valid1) begin
          curr_pointer = 0;
          if (item.o_data != item.i_data1) begin
            `uvm_error (get_type_name(),
                        $sformatf ("valid1 activated, but data different. o_data=0x%04h data1=0x%h",
                                   item.o_data, item.i_data1));
          end
        end
      end // case: 'h0
      'h1 : begin
        if (item.i_valid1) begin
          curr_pointer = 0;
          if (item.o_data != item.i_data1) begin
            `uvm_error (get_type_name(),
                        $sformatf ("valid1 activated, but data different. o_data=0x%04h data1=0x%h",
                                   item.o_data, item.i_data1));
          end
        end else if (item.i_valid0) begin
          curr_pointer = 1;
          if (item.o_data != item.i_data0) begin
            `uvm_error (get_type_name(),
                        $sformatf ("valid0 activated, but data different. o_data=0x%04h data0=0x%h",
                                   item.o_data, item.i_data0));
          end
        end
      end // case: 'h1
    endcase // case (curr_pointer)
  endfunction // write

実行してみると、正しく検証できることが確認できた。