篇首语:本文由小编为大家整理,主要介绍了UVM验证平台相关的知识,希望对你有一定的参考价值。
参考:《UVM实战》 张强 著
文章目录
- UVM 框架
- DUT
- testbench top
- interface
- my_case0
- base_test
- env
- agent
- tarnsaction
- sequence
- sequencer
- driver
- monitor
- reference_model
- scoreboard
UVM 框架
DUT
1 module dut(clk,2 rst_n,3 rxd,4 rx_dv,5 txd,6 tx_en);7 input clk;8 input rst_n;9 input[7:0] rxd;10 input rx_dv;11 output [7:0] txd;12 output tx_en;1314 reg[7:0] txd;15 reg tx_en;1617 always @(posedge clk) begin18 if(!rst_n) begin19 txd <= 8"b0;20 tx_en <= 1"b0;21end22 else begin23 txd <= rxd;24 tx_en <= rx_dv;25 end26 end27 endmodule
testbench top
1 `timescale 1ns/1ps 2 `include "uvm_macros.svh" 3 4 import uvm_pkg::*; 5 `include "my_if.sv" 6 `include "my_transaction.sv" 7 //`include "my_sequence.sv" 8 `include "my_driver.sv" 9 `include "my_monitor.sv"10 `include "my_sequencer.sv"11 `include "my_agent.sv"12 `include "my_model.sv"13 `include "my_scoreboard.sv"14 `include "my_env.sv"15 `include "base_test.sv"16 `include "my_case0.sv"17 `include "my_case1.sv"18 19 module top_tb;20 21 reg clk;22 reg rst_n;23 reg[7:0] rxd;24 reg rx_dv;25 wire[7:0] txd;26 wire tx_en;27 28 my_if input_if(clk, rst_n);29 my_if output_if(clk, rst_n);30 31 dut my_dut(.clk(clk),32 .rst_n(rst_n),33 .rxd(input_if.data),34 .rx_dv(input_if.valid),35 .txd(output_if.data),36 .tx_en(output_if.valid));37 38 initial begin39 clk = 0;40 forever begin41 #100 clk = ~clk;42 end43 end44 45 initial begin46 rst_n = 1"b0;47 #1000;48 rst_n = 1"b1;49 end50 51 initial begin52 //run_test("my_env");53 run_test();54 end55 56 initial begin57 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);58 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);59 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);60 end61 62 endmodule
interface
1 `ifndef MY_IF__SV 2 `define MY_IF__SV 3 4 interface my_if(input clk, input rst_n); 5 6 logic [7:0] data; 7 logic valid; 8 endinterface 9 10 `endif
my_case0
1 `ifndef MY_CASE0__SV 2 `define MY_CASE0__SV 3 class case0_sequence extends uvm_sequence #(my_transaction); 4 my_transaction m_trans; 5 6 function new(string name= "case0_sequence"); 7 super.new(name); 8 endfunction 9 10 virtual task body();11 if(starting_phase != null) 12 starting_phase.raise_objection(this);13 repeat (10) begin14 `uvm_do(m_trans)15 end16 #100;17 if(starting_phase != null) 18 starting_phase.drop_objection(this);19 endtask20 21 `uvm_object_utils(case0_sequence)22 endclass23 24 25 class my_case0 extends base_test;26 27 function new(string name = "my_case0", uvm_component parent = null);28 super.new(name,parent);29 endfunction 30 extern virtual function void build_phase(uvm_phase phase); 31 `uvm_component_utils(my_case0)32 endclass33 34 35 function void my_case0::build_phase(uvm_phase phase);36 super.build_phase(phase);37 38 uvm_config_db#(uvm_object_wrapper)::set(this, 39 "env.i_agt.sqr.main_phase", 40 "default_sequence", 41 case0_sequence::type_id::get());42 endfunction43 44 `endif
base_test
1 `ifndef BASE_TEST__SV 2 `define BASE_TEST__SV 3 4 class base_test extends uvm_test; 5 6 my_env env; 7 8 function new(string name = "base_test", uvm_component parent = null); 9 super.new(name,parent);10 endfunction11 12 extern virtual function void build_phase(uvm_phase phase);13 extern virtual function void report_phase(uvm_phase phase);14 `uvm_component_utils(base_test)15 endclass16 17 18 function void base_test::build_phase(uvm_phase phase);19 super.build_phase(phase);20 env = my_env::type_id::create("env", this); 21 //uvm_config_db#(uvm_object_wrapper)::set(this,22 //"env.i_agt.sqr.main_phase",23 //"default_sequence",24 // my_sequence::type_id::get());25 endfunction26 27 function void base_test::report_phase(uvm_phase phase);28 uvm_report_server server;29 int err_num;30 super.report_phase(phase);31 32 server = get_report_server();33 err_num = server.get_severity_count(UVM_ERROR);34 35 if (err_num != 0) begin36 $display("TEST CASE FAILED");37 end38 else begin39 $display("TEST CASE PASSED");40 end41 endfunction42 43 `endif
env
1 `ifndef MY_ENV__SV2 `define MY_ENV__SV34 class my_env extends uvm_env;5 6 my_agent i_agt;7 my_agent o_agt;8 my_model mdl;9 my_scoreboard scb;10 11 uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;12 uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;13 uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;14 15 function new(string name = "my_env", uvm_component parent);16 super.new(name, parent);17 endfunction1819 virtual function void build_phase(uvm_phase phase);20 super.build_phase(phase);21 i_agt = my_agent::type_id::create("i_agt", this);22 o_agt = my_agent::type_id::create("o_agt", this);23 i_agt.is_active = UVM_ACTIVE;24 o_agt.is_active = UVM_PASSIVE;25 mdl = my_model::type_id::create("mdl", this);26 scb = my_scoreboard::type_id::create("scb", this);27 agt_scb_fifo = new("agt_scb_fifo", this);28 agt_mdl_fifo = new("agt_mdl_fifo", this);29 mdl_scb_fifo = new("mdl_scb_fifo", this);3031 endfunction3233 extern virtual function void connect_phase(uvm_phase phase);34 35 `uvm_component_utils(my_env)36 endclass3738 function void my_env::connect_phase(uvm_phase phase);39 super.connect_phase(phase);40 i_agt.ap.connect(agt_mdl_fifo.analysis_export);41 mdl.port.connect(agt_mdl_fifo.blocking_get_export);42 mdl.ap.connect(mdl_scb_fifo.analysis_export);43 scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);44 o_agt.ap.connect(agt_scb_fifo.analysis_export);45 scb.act_port.connect(agt_scb_fifo.blocking_get_export); 46 endfunction4748 `endif
agent
1 `ifndef MY_AGENT__SV 2 `define MY_AGENT__SV 3 4 class my_agent extends uvm_agent ; 5 my_sequencer sqr; 6 my_driver drv; 7 my_monitor mon; 8 9 uvm_analysis_port #(my_transaction) ap;10 11 function new(string name, uvm_component parent);12 super.new(name, parent);13 endfunction 14 15 extern virtual function void build_phase(uvm_phase phase);16 extern virtual function void connect_phase(uvm_phase phase);17 18 `uvm_component_utils(my_agent)19 endclass 20 21 22 function void my_agent::build_phase(uvm_phase phase);23 super.build_phase(phase);24 if (is_active == UVM_ACTIVE) begin25 sqr = my_sequencer::type_id::create("sqr",this);26 drv = my_driver::type_id::create("drv", this);27 end28 mon = my_monitor::type_id::create("mon", this);29 endfunction 30 31 function void my_agent::connect_phase(uvm_phase phase);32 super.connect_phase(phase);33 if(is_active == UVM_ACTIVE)begin34 drv.seq_item_port.connect(sqr.seq_item_export); 35 end36 ap = mon.ap;37 endfunction38 39 `endif
tarnsaction
1 `ifndef MY_TRANSACTION__SV 2 `define MY_TRANSACTION__SV 3 4 class my_transaction extends uvm_sequence_item; 5 6 rand bit[47:0] dmac; 7 rand bit[47:0] smac; 8 rand bit[15:0] ether_type; 9 rand byte pload[];10 rand bit[31:0] crc;11 12 constraint pload_cons13 pload.size >= 46;14 //pload.size <= 1500;15 pload.size <= 200;16 dmac == 48"h01_02_03_04_05_06;17 smac == 48"h60_50_40_30_20_10;18 19 20 21 function bit[31:0] calc_crc();22 return 32"h0;23 endfunction24 25 function void post_randomize();26 crc = calc_crc;27 endfunction28 29 //`uvm_object_utils(my_transaction)30 `uvm_object_utils_begin(my_transaction)31 `uvm_field_int(dmac,UVM_ALL_ON)32 `uvm_field_int(smac,UVM_ALL_ON)33 `uvm_field_int(ether_type,UVM_ALL_ON)34 `uvm_field_array_int(pload,UVM_ALL_ON)35 `uvm_field_int(crc,UVM_ALL_ON)36 `uvm_object_utils_end37 38 function new(string name = "my_transaction");39 super.new();40 endfunction41 42 /*function void my_print();43 $display("dmac = %0h", dmac);44 $display("smac = %0h", smac);45 $display("ether_type = %0h", ether_type);46 for(int i = 0; i < pload.size; i++) begin47 $display("pload[%0d] = %0h", i, pload[i]);48 end49 $display("crc = %0h", crc);50 endfunction51 52 function void my_copy(my_transaction tr);53 if(tr == null)54 `uvm_fatal("my_transaction", "tr is null!!!!")55 dmac = tr.dmac;56 smac = tr.smac;57 ether_type = tr.ether_type;58 pload = new[tr.pload.size()];59 for(int i = 0; i < pload.size(); i++) begin60 pload[i] = tr.pload[i];61 end62 crc = tr.crc;63 endfunction64 65 function bit my_compare(my_transaction tr);66 bit result;67 68 if(tr == null)69 `uvm_fatal("my_transaction", "tr is null!!!!")70 result = ((dmac == tr.dmac) &&71 (smac == tr.smac) &&72 (ether_type == tr.ether_type) &&73 (crc == tr.crc));74 if(pload.size() != tr.pload.size())75 result = 0;76 else 77 for(int i = 0; i < pload.size(); i++) begin78 if(pload[i] != tr.pload[i])79 result = 0;80 end81 return result; 82 endfunction*/83 84 endclass85 `endif
sequence
1 class my_sequence extends uvm_sequence #(my_transaction); 2 my_transaction m_trans; 3 4 function new(string name="my_sequence"); 5 super.new(name); 6 endfunction 7 8 virtual task body(); 9 if(starting_phase != null)10 starting_phase.raise_objection(this);11 12 repeat(10) begin13 `uvm_do(m_trans)14 end15 #1000;16 17 if(starting_phase != null)18 starting_phase.drop_objection(this);19 endtask20 21 `uvm_object_utils(my_sequence)22 23 endclass
sequencer
1 `ifndef MY_SEQUENCER__SV 2 `define MY_SEQUENCER__SV 3 4 class my_sequencer extends uvm_sequencer #(my_transaction); 5 6 function new(string name, uvm_component parent); 7 super.new(name, parent); 8 endfunction 9 10 `uvm_component_utils(my_sequencer)11 endclass12 13 `endif
driver
1 `ifndef MY_DRIVER__SV 2 `define MY_DRIVER__SV 3 class my_driver extends uvm_driver#(my_transaction); 4 5 virtual my_if vif; 6 7 `uvm_component_utils(my_driver) 8 function new(string name = "my_driver", uvm_component parent = null); 9 super.new(name, parent);10 endfunction11 12 virtual function void build_phase(uvm_phase phase);13 super.build_phase(phase);14 if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))15 `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")16 endfunction17 18 extern task main_phase(uvm_phase phase);19 extern task drive_one_pkt(my_transaction tr);20 endclass21 22 /*task my_driver::main_phase(uvm_phase phase);23 my_transaction tr;24 phase.raise_objection(this);25 vif.data <= 8"b0;26 vif.valid <= 1"b0;27 while(!vif.rst_n)28 @(posedge vif.clk);29 for(int i = 0; i < 2; i++) begin 30 req = new("req");31 assert(req.randomize() with pload.size == 200;32 dmac == 48"h01_02_03_04_05_06;33 smac == 48"h60_50_40_30_20_10;34 35 );36 drive_one_pkt(req);37 end38 repeat(5) @(posedge vif.clk);39 phase.drop_objection(this);40 endtask*/41 42 task my_driver::main_phase(uvm_phase phase);43 vif.data <= 8"b0;44 vif.valid <= 1"b0;45 46 while(!vif.rst_n)47 @(posedge vif.clk);48 49 while(1)begin50 seq_item_port.get_next_item(req);51 drive_one_pkt(req);52 seq_item_port.item_done();53 end54 endtask55 56 task my_driver::drive_one_pkt(my_transaction tr);57 58 byte unsigned data_q[];59 int unsigned data_size;60 61 data_size = tr.pack_bytes(data_q)/8;//fill data_q on the order in uvm_object_utils of transaction62 `uvm_info("my_driver","begin to drive one pkt" 以上是关于UVM验证平台的主要内容,如果未能解决你的问题,请参考以下文章