はじめに
Register階層(Register Layer)を作成します。
UVMではレジスタをuvm_regを継承したクラスで定義します。
1レジスタごとに1クラスを作成して、uvm_reg_blockを継承したクラスで1まとめにします。
サンプルコード
sample_reg_block.svh
レジスタクラスSTATUS_regを作成してsample_reg_blockの要素にします。
class STATUS_reg extends uvm_reg; // レジスタクラス。
`uvm_object_utils(STATUS_reg)
function new(string name="STATUS_reg");
super.new(name, 8, UVM_NO_COVERAGE);
endfunction
rand uvm_reg_field status;
function void build();
status = uvm_reg_field::type_id::create("status");
status.configure(
.parent(this), // とりあえずthisでOK。
.size(8), // レジスタのビット幅
.lsb_pos(0), // LSBの開始位置
.access("RW"), // アクセスタイプ
.volatile(0), // わからん。
.reset(0), // 初期値
.has_reset(1), // リセット値を持つかどうか。
.is_rand(1), // 乱数対応
.individually_accessible(0) // わからん。
);
endfunction
endclass
class sample_reg_block extends uvm_reg_block; // レジスタクラスをまとめる。
rand STATUS_reg STATUS; // 作成したレジスタクラスを羅列する。
`uvm_object_utils(sample_reg_block)
function new(string name="sample_reg_block");
super.new(name, build_coverage(UVM_NO_COVERAGE));
endfunction
function void build();
STATUS = STATUS_reg::type_id::create("STATUS");
STATUS.configure(this);
STATUS.build();
default_map = create_map("", 0, 1, UVM_LITTLE_ENDIAN);
default_map.add_reg(STATUS, 'h1); // レジスタクラスを追加する。
endfunction
endclass
sample_env.svh
sample_reg_blockをぶら下げます。
class sample_env extends uvm_env;
`uvm_component_utils(sample_env)
sample_reg_block regmodel;
function new(string name="sample_env", uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
regmodel = sample_reg_block::type_id::create("regmodel");
regmodel.build(); // buildを実行する
regmodel.lock_model(); // コンフィグをこれ以降変更できないようにする。
uvm_config_db#(sample_reg_block)::set(uvm_root::get(), "*", "regmodel", regmodel);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
regmodel.default_map.set_base_addr('h0); // 開始アドレスを設定する。
endfunction
endclass
sample_vsequencer.svh
Virtual Sequenceで使用するようにregmodelを宣言します。
class sample_vsequencer extends uvm_sequencer;
`uvm_component_utils(sample_vsequencer)
sample_reg_block regmodel;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
sample_vseq.svh
class sample_vseq extends uvm_sequence;
`uvm_object_utils(sample_vseq)
`uvm_declare_p_sequencer(sample_vsequencer)
function new(string name="sample_vseq");
super.new(name);
set_automatic_phase_objection(1);
endfunction
virtual task body();
byte data;
data = p_sequencer.regmodel.STATUS.get_address(); // アドレスを取得する。
`uvm_info(this.get_name(), $sformatf("%h", data), UVM_NONE)
endtask
endclass
その他のファイル
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "sample_reg_block.svh"
`include "sample_env.svh"
`include "sample_vsequencer.svh"
`include "sample_vseq.svh"
`include "sample_test.svh"
initial begin
run_test("sample_test");
end
bit clk = 0;
always #1 clk = ~clk;
bit rst_n = 0;
initial #10 rst_n = 1;
logic write_en;
logic [7:0] addr;
logic [7:0] data;
regbus i_regbus (
.clk(clk),
.rst_n(rst_n),
.write_en(write_en),
.addr(addr),
.data(data)
);
endmodule
interface regbus_if (
logic clk,
logic rst_n
);
logic write_en;
logic [7:0] addr;
logic [7:0] data;
endinterface
module regbus #(
)(
input clk,
input rst_n,
output logic write_en,
output logic [7:0] addr,
output logic [7:0] data
);
`include "uvm_macros.svh"
import uvm_pkg::*;
regbus_if vif(
.clk(clk),
.rst_n(rst_n)
);
assign data = vif.data;
assign addr = vif.addr;
assign write_en = vif.write_en;
initial begin
uvm_config_db #(virtual regbus_if)::set(null, "*regbus*", "vif", vif);
end
endmodule
class sample_test extends uvm_test;
`uvm_component_utils(sample_test)
sample_env env;
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());
env = sample_env::type_id::create("env", this);
vsequencer = sample_vsequencer::type_id::create("vsequencer", this);
endfunction
function void connect_phase(uvm_phase phase);
$cast(vsequencer.regmodel, env.regmodel);
endfunction
endclass
実行結果
[UVM_INFO][sample_vseq] 01
まとめ
Register階層を作成しました。
コメント