はじめに
前回は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に期待値比較する機能を実装しました。
コメント