uvm_model
很早之前就说写一个简单的uvm环境
首先是一个简单的dut
`timescale lns/10fs
module mul(
clk,
rst_n,
num_a,
num_b,
num_c
);
input clk;
input rst__n;
input [7:0] num__a;
input [7:0] num__b;
output [7:0] num__c;
reg [7:0] a;
reg [7:0] b;
reg [7:0] c;
assign num_c = c;
always @(posedge clk or negedge rst_n)begin
if (!rst_n == l'bl)begin
c <= 8'h0;
end else begin
c <= num_a + num_b;
end
end
endmodule
`timescale lns/10fs
module top(
clk,
rst_n,
num_a,
num_b,
num_c
);
input clk;
input rst_n;
input [7:0] num_a;
input [7:0] num_b;
output [7:0] num_c;
mul U_MUL(
. clk(clk),
. rst_n(rst_n),
. num_a(num_a),
. num_b(num_b),
. num_c(num_c)
);
endmodule
之后是harness
module harness;
logic elk;
logic rst_n;
logic [7:0] num_a;
logic [7:0] num_b;
logic [7:0] num_c;
initial begin
clk = 0;
rst_n = 0;
#100ns rst_n = 1;
end
always begin
#5ns clk = ~clk;
end
my_interface tx_if(clk,rst_n);
my_interface rx_if(clk,rst_n);
top dut(
.clk(clk),
.rst_n(rst_n),
.num_a(num_a),
.num_b(num_b),
.num_c(num_c)
);
initial begin
uvm_config_db #(virtual my_interface) :: set(null, "uvm_test_top.env_.rx_agt*", "vif", rx_if);
uvm_config_db #(virtual my_interface) :: set(null, "uvm_test_top.env_.tx_agt*", "vif", tx_if);
end
initial begin
run_test();
end
assign num_a = tx_if.a;
assign num_b = tx_if.b;
assign rx_if.c = num_c;
initial begin
$vcdpluson;
$fsdbDumpon;
end
endmodule
之后是interface
interface my_interface(input bit clk,input bit rst_n);
logic [7:0] a;
logic [7:0] b;
logic [7:0] c;
clocking mon_cb@(posedge clk);
inout a;
inout b;
inout c;
endclocking
endinterface
之后是transaction
class my_transaction extends extends uvm_sequence_item;
rand bit [7:0] a;
rand bit [7:0] b;
rand bit [7:0] c;
rand byte kk[];
constraint k_cons{
kk.size >= 10;
kk.size <= 90;
}
`uvm_object_utils_begin(my_transaction)
//'uvm_field_int(a,UVM_ALL_0N)
//'uvm_field_int(b,UVM_ALL_0N)
`uvm_field_int(c,UVM_ALL_0N)
`uvm_field_array_int(kk,UVM_ALL_0N)
`uvm_object_utils_end
extern function new(string name = "my_transaction");
endclass
function my_transaction::new(string name = "my_transaction");
super.new(name);
endfunction
之后是sequencer
class my_sequencer extends uvm_sequencer #(my_transaction);
`uvm_component_utils(my_sequencer)
extern function new(string name, uvm_component parent);
endclass
function my_sequencer::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
之后是tx部分
class tx_driver extends uvm_driver #(my_transaction);
virtual my_interface vif;
`uvm_component_utils(tx_driver)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task reset_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function tx_driver::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void tx_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
`uvm_fatal("tx_driver","virtual interface get fail !");
endfunction
task tx_driver::reset_phase(uvm_phase phase);
vif.a <= $urandom_range(8'hff,8'h0);
vif.b <= $urandom_range(8'hff,8'h0);
endtask
task tx_driver::main_phase(uvm_phase phase);
my_transaction tx_tr;
super.main_phase(phase);
while(l)begin
seq_item_port.get_next_item(req);
tx_tr = req;
vif.a <= tx_tr.a;
vif.b <= tx_tr.b;
seq_item_port.item_done();
end
endtask
class tx_monitor extends uvm_monitor;
virtual my_interface vif;
uvm_analysis_port #(my_transaction) tx_mon_ap;
`uvm_component_utils(tx_monitor)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function tx_monitor::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void tx_monitor::build_phase(uvm_phase phase);
super.build_phase(phase);
tx_mon_ap = new("tx_mon_ap", this);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
`uvm_fatal("tx_monitor","virtual interface get fail !");
endfunction
task tx_monitor::main_phase(uvm_phase phase);
my_transaction tx_tr;
super.main_phase(phase);
while(l)begin
tx_tr = new();
tx_tr.a = vif.a;
tx_tr.b = vif.b;
tx_mon_ap.write(tx_tr);
@(posedge vif.clk);
end
endtask
class tx_agent extends uvm_agent;
tx_monitor mon;
tx_driver drv;
my_sequencer sqr;
uvm_analysis_port #(my_transaction) ap;
`uvm_component_utils(tx_agent)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function tx_agent::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void tx_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
mon = tx_monitor ::type_id:: create ("mon", this);
drv = tx_driver ::type_id:: create ("drv", this);
sqr = my_sequencer ::type_id:: create ("sqr", this);
endfunction
function void tx_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap = mon.tx_mon_ap;
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction
task tx_agent::main_phase(uvm_phase phase);
super.main_phase(phase);
endtask
之后是rx部分
class rx_monitor extends uvm_monitor;
virtual my_interface vif;
uvm_analysis_port #(my_transaction) rx_mon_ap;
`uvm_component_utils(rx_monitor)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function rx_monitor::new(string new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void rx_monitor::build_phase(uvm_phase phase);
super.build_phase(phase);
rx_mon_ap = new("rx_mon_ap", this);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
'uvm_fatal("rx_monitor","virtual interface get fail !");
endfunction
task rx_monitor::main_phase(uvm_phase phase);
my_transaction rx_tr;
super.main_phase(phase);
while(l)begin
rx_tr=new();
@(posedge vif.clk);
rx_tr.c = vif.c;
rx_mon_ap.write (rx_tr);
end
endtask
class rx_agent extends uvm_agent;
rx_monitor mon;
uvm_analysis_port #(my_transaction) ap;
`uvm_component_utils(rx_agent)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function rx_agent::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void rx_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
mon = rx_monitor::type_id::create("mon",this);
endfunction
function void rx_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap = mon.rx_mon_ap;
endfunction
task rx_agent::main_phase(uvm_phase phase);
super.main_phase(phase);
endtask
之后是env
class env extends uvm_env;
rx_agent rx_agt;
tx_agent tx_agt;
rm rm_;
scoreboard sc;
`uvm_component_utils(env)
uvm_tlm_analysis_fifo #(my_transaction) mon_rm_fifo;
uvm_tlm_analysis_fifo #(my_transaction) rm_sc_fifo;
uvm_tlm_analysis_fifo #(my_transaction) sc_mon_fifo;
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task configure_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function env::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void env::build_phase(uvm_phase phase);
super.build_phase(phase);
rx_agt = rx_agent ::type_id:: create ("rx_agt", this);
tx_agt = tx_agent ::type_id:: create ("tx_agt", this);
rm_ = rm ::type_id:: create ("rm_ " , this);
sc = scoreboard ::type_id:: create ("sc " , this);
mon_rm_fifo = new("mon_rm_fifo", this);
rm_sc_fifo = new("rm_sc_fifo", this);
sc_mon_fifo = new("sc_mon_fifo", this);
endfunction
function void env::connect_phase(uvm_phase phase);
super.connect_phase(phase);
tx_agt.ap. connect(mon_rm_fifo.analysis_export);
rm_.port. connect(mon_rm_fifo.blocking_get_export);
rm_.rm_ap. connect (rm_sc_fifo.analysis_export);
sc.rm_port. connect (rm_sc_fifo.blocking_get_export);
rx_agt.ap. connect(sc_mon_fifo.analysis_export);
sc.dut_port.connect(sc_mon_fifo.blocking_get_export);
endfunction
task env::configure_phase(uvm_phase phase);
super.configure_phase(phase);
endtask
task env::main_phase(uvm_phase phase);
super,main_phase(phase);
endtask
之后是rm
class rm extends uvm_component;
uvm_blocking_get_port #(my_transaction) port;
uvm_analysis_port #(my_transaction) rm_ap;
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
`uvm_component_utils(rm)
endclass
function rm::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void rm::build_phase(uvm_phase phase);
super.build_phase(phase);
port = new("port", this);
rm_ap = new("rm_ap",this);
endfunction
task rm::main_phase(uvm_phase phase);
my_transaction tr;
my_transaction send_tr;
super.main_phase(phase);
while(l)begin
port.get(tr);
send_tr = new("send_tr");
send_tr = tr;
send_tr.c = send_tr.a + send_tr.b;
rm_ap.write(send_tr);
end
endtask
class scoreboard extends extends uvm_scoreboard;
my_transaction rm_queue[$];
uvm_blocking_get_port #(my_transaction) rm_port;
uvm_blocking_get_port #(my_transaction) dut_port;
`uvm_component_utils(scoreboard)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);
endclass
function scoreboard::new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void scoreboard::build_phase(uvm_phase phase);
super.build_phase(phase);
rm_port = new("rm_port ",this);
dut_port = new("dut_port", this);
endfunction
function void scoreboard::connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction
task scoreboard::main_phase(uvm_phase phase);
my_transaction rm_tr, dut_tr, chk_tr;
super.main_phase(phase);
fork
while(l)begin
rm_port.get(rm_tr);
rm_queue.push_back(rm_tr);
end
while(l)begin
dut_port.get(dut_tr);
if (rm_queue.size() > 0)begin
chk_tr = rm_queue.pop_front();
if(dut_tr.compare(chk_tr)) begin
`uvm_info("scoreboard", "ok", UVM_L0W);
dut_tr.print ();
chk_tr.print ();
end else begin
`uvm_error("scoreboard", "fail");
end
end
join
endtask
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
新车首发,新的一年,只带想赚米的人
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com