はじめに
UVM環境でクロック生成モデルを作成します。
構成とサンプルコード
UVMモデルの構成
Sequence_item
class clock_sequence_item extends uvm_sequence_item;
`uvm_object_utils(clock_sequence_item)
rand bit en;
function new(string name="clock_sequence_item");
super.new(name);
endfunction
endclass
Sequencer
class clock_sequencer extends uvm_sequencer #(clock_sequence_item);
`uvm_component_utils(clock_sequencer)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
Driver
class clock_driver extends uvm_driver #(clock_sequence_item);
`uvm_component_utils(clock_driver)
virtual clock_if vif;
function new(string name, uvm_component parent);
super.new(name, parent);
if (!uvm_config_db #(virtual clock_if)::get(this, "clock", "vif", vif))
`uvm_fatal(this.get_name(), "vif is invalid")
endfunction
task run_phase(uvm_phase phase);
vif.en = 0;
forever begin
seq_item_port.get_next_item(req);
vif.en = req.en;
seq_item_port.item_done(rsp);
end
endtask
endclass
Agent
class clock_agent extends uvm_agent;
`uvm_component_utils(clock_agent)
clock_driver driver;
clock_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);
driver = clock_driver::type_id::create("driver", this);
sequencer = clock_sequencer::type_id::create("sequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction
endclass
Sequence
class clock_seq extends uvm_sequence #(clock_sequence_item);
`uvm_object_utils(clock_seq)
rand bit en;
function new(string name="clock_seq");
super.new(name);
set_automatic_phase_objection(1); // おまじない
endfunction
virtual task body();
`uvm_create(req)
req.en = en;
`uvm_send(req)
endtask
endclass
package
package clock_pkg;
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "clock_sequence_item.svh"
`include "clock_sequencer.svh"
`include "clock_driver.svh"
`include "clock_agent.svh"
`include "clock_seq.svh"
endpackage
Interface
※クロック生成回路付き。
interface clock_if;
logic en;
endinterface
module clock #(
parameter HIGH = 1,
parameter LOW = 1
)(
output logic clk
);
`include "uvm_macros.svh"
import uvm_pkg::*;
clock_if vif();
always begin
clk = 0;
@(vif.en === 1);
fork
begin
@(vif.en === 0);
clk = 0;
end
begin
forever begin
#LOW;
clk = ~clk;
#HIGH;
clk = ~clk;
end
end
join_any
disable fork;
end
initial begin
uvm_config_db #(virtual clock_if)::set(null, "*clock*", "vif", vif);
end
endmodule
サンプル動作環境
Virtual Sequencer
class sample_vsequencer extends uvm_sequencer;
`uvm_component_utils(sample_vsequencer)
clock_sequencer seqr;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
Virtual Sequence
class sample_vseq extends uvm_sequence;
`uvm_object_utils(sample_vseq)
`uvm_declare_p_sequencer(sample_vsequencer)
clock_seq seq;
function new(string name="sample_vseq");
super.new(name);
set_automatic_phase_objection(1);
endfunction
virtual task body();
seq = clock_seq::type_id::create("seq");
for (int i = 0; i < 2; i++) begin
`uvm_do_on_with(seq, p_sequencer.seqr, {
en == 0; // 0のときクロックは停止する。
})
#50;
`uvm_do_on_with(seq, p_sequencer.seqr, {
en == 1; // 1のときクロックが動き出す。
})
#50;
end
endtask
endclass
Test
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
clock_agent agent;
sample_vsequencer vsequencer;
function new(string name="sample_test", uvm_component parent=null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(uvm_object_wrapper)::set(
this, "vsequencer.run_phase",
"default_sequence", sample_vseq::type_id::get());
agent = clock_agent::type_id::create("agent", this);
vsequencer = sample_vsequencer::type_id::create("vsequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
$cast(vsequencer.seqr, agent.sequencer);
endfunction
endclass
テストベンチ
`include "clock_pkg.svh"
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
import clock_pkg::*;
`include "sample_vsequencer.svh"
`include "sample_vseq.svh"
`include "sample_test.svh"
initial begin
run_test("sample_test");
end
logic clk;
clock #(
.HIGH(2),
.LOW(1)
) i_clock(clk);
endmodule
まとめ
UVM環境でクロック生成モデルを作成しました。
コメント