【UVM】ScoreBoardを作成する~期待値比較する~【#3】

Systemverilog

はじめに

前回はuvm_tlm_analysis_fifoを使用してFIFOを実装しました。

今回はDUTの出力を取得してScoreBoardで期待値比較します。

サンプルコード

dut.sv

入力データをそのまま出力するだけの回路です。

validがHighのときが有効データです。

module dut(
    input clk,
    input rst_n,

    input valid,
    input [3:0] data,
    output logic ready,

    output logic out_valid,
    output logic [3:0] dout
);

    assign ready = '1;

    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            dout <= '0;
        end
        else begin
            if (valid && ready) begin
                dout <= data;
            end
        end
    end

    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            out_valid <= '0;
        end
        else begin
            if (valid && ready) begin
                out_valid <= '1;
            end
            else begin
                out_valid <= '0;
            end
        end
    end
endmodule
sample_scoreboard.svh

run_phaseで期待値比較します。

check_phaseはシミュレーション終了時に呼ばれるメソッドで、期待値、DUTの出力がFIFOに残っていないかをチェックします。

class sample_scoreboard extends uvm_scoreboard;
    `uvm_component_utils(sample_scoreboard)

    uvm_tlm_analysis_fifo#(sample_sequence_item) exp_fifo;  // 期待値
    uvm_tlm_analysis_fifo#(sample_sequence_item) act_fifo;  // DUTの出力

    function new(string name, uvm_component parent);
        super.new(name, parent);
        exp_fifo = new("exp_fifo", this);
        act_fifo = new("act_fifo", this);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
    endfunction

    virtual task run_phase(uvm_phase phase);
        sample_sequence_item item_act, item_exp;
        super.run_phase(phase);
        forever begin
            fork
                exp_fifo.get(item_exp);  // 期待値を取得
                act_fifo.get(item_act);  // DUTの出力を取得
            join
            if (item_act.data == item_exp.data) begin
                `uvm_info(this.get_name(), $sformatf(
                    "act:%d, exp:%d",item_act.data, item_exp.data), UVM_NONE)
            end
            else begin
                `uvm_error(this.get_name(), $sformatf(
                    "act:%d, exp:%d",item_act.data, item_exp.data))
            end
        end
    endtask

    // シミュレーション終了時にFIFOの中身が残っていないかチェックする
    virtual function void check_phase(uvm_phase phase);
        super.check_phase(phase);
        if (exp_fifo.used() != 0) begin
            `uvm_error(this.get_name(), $sformatf(
                "Remain Expected Data:%d",exp_fifo.used()))
        end
        if (act_fifo.used() != 0) begin
            `uvm_error(this.get_name(), $sformatf(
                "Remain Actual Data:%d",act_fifo.used()))
        end
    endfunction
endclass
sample_agent.svh
class sample_agent extends uvm_agent;
    `uvm_component_utils(sample_agent)

    sample_driver driver;
    sample_monitor monitor;
    sample_sequencer sequencer;

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if (get_is_active() == UVM_ACTIVE) begin  // モニターはDriverを動かす必要がないので条件分岐
            driver = sample_driver::type_id::create("driver", this);
            sequencer = sample_sequencer::type_id::create("sequencer", this);
        end
        monitor = sample_monitor::type_id::create("monitor", this);
    endfunction

    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        if (this.get_is_active() == UVM_ACTIVE) begin
            driver.seq_item_port.connect(sequencer.seq_item_export);
        end
    endfunction
endclass
sample_env.svh

出力をモニタするAgent(mon)はDriverを動かさないのでmon.is_active = UVM_PASSIVEを設定します。

class sample_env extends uvm_env;
    `uvm_component_utils(sample_env)

    sample_agent agent;  // DUTを動かすAgent
    sample_agent mon;  // 出力をモニタするAgent
    sample_scoreboard scoreboard;

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        agent = sample_agent::type_id::create("agent", this);
        mon = sample_agent::type_id::create("mon", this);
        mon.is_active = UVM_PASSIVE;  // Driverを動かさないのでUVM_PASSIVEに設定
        scoreboard = sample_scoreboard::type_id::create("scoreboard", this);
    endfunction

    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        agent.monitor.item_collected_port.connect(scoreboard.exp_fifo.analysis_export);  // 期待値のFIFOへ
        mon.monitor.item_collected_port.connect(scoreboard.act_fifo.analysis_export);  // DUTの出力のFIFOへ
    endfunction
endclass

まとめ

ScoreBoardに期待値比較する機能を実装しました。

コメント

タイトルとURLをコピーしました