发表更新12 分钟读完 (大约1795个字)
uvm_model
很早之前就说写一个简单的uvm环境
首先是一个简单的dut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| `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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| `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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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(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
1 2 3 4 5 6 7 8 9 10
| 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部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| 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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| 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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| 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
|