UVM验证平台

时间:2023-03-10 10:48:02 买帖  | 投诉/举报

篇首语:本文由小编为大家整理,主要介绍了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验证平台的主要内容,如果未能解决你的问题,请参考以下文章