BFM(バスファンクショナルモデル)の、UVMでのclass構成を示します。
以下に示したclassをextendsして構成します。
他に
が必要になりますが、これだけ別だしなのは、uvm_env以下にインスタンスして使わないからです。
個々のclassを簡単に説明します。
rstz ____|~~~~~~~~~~~~~~~~~~~~~~~~~~~~clk ~~~~~|___|~~~|___|~~~|___|~~~|___valid _________|~~~~~~~|_______________addr XXXXXXXXXX addr XXXXXXXXXXXXXXXXdata XXXXXXXXXX data XXXXXXXXXXXXXXXXclass sample_seq_item extends uvm_sequence_item; logic [7:0] addr, data; `uvm_object_utils_begin(sample_seq_item) `uvm_field_int (addr, UVM_DEFAULT)
`uvm_field_int (data, UVM_DEFAULT)
`uvm_object_utils_end function new (string name = "sample_seq_item_inst"); super.new(name); endfunction : newendclassclass sample_sequencer extends uvm_sequencer #(sample_seq_item); `uvm_component_utils(sample_sequencer) `uvm_new_funcendclass----- ./src/macros/uvm_object_defines.svh, line=396`define uvm_new_func \ function new (string name, uvm_component parent); \ super.new(name, parent); \ endfunctionclass sample_driver extends uvm_driver #(sample_seq_item); `uvm_component_utils(sample_driver) virtual sample_if vif; function new (string name="sample_driver", uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif)) `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"}); endfunction: build_phase task run_phase(uvm_phase phase); sample_seq_item trans_item; // while reset vif.valid = 1'b0; @(posedge vif.rstz);// wait negate reset forever begin seq_item_port.get_next_item(trans_item); // get several value from trans_item and drive // signals, receive signals via virtual interface @(posedge vif.clk); vif.valid <= 1'b1; vif.addr <= trans_item.addr; vif.data <= trans_item.data; @(posedge vif.clk) vif.valid <= 1'b0; seq_item_port.item_done(); end endtaskendclassinterface sample_if(input logic clk, rstz); logic [7:0] addr, data; logic valid;endinterfaceclass sample_monitor extends uvm_monitor; `uvm_component_utils(sample_monitor) virtual sample_if vif; function new (string name="sample_monitor", uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif)) `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"}); endfunction: build_phase task run_phase(uvm_phase phase); fork //check_clock; check_trans; join endtask task check_trans; forever begin @(posedge vif.valid) uvm_report_info("MON", $sformatf("addr=%02Xh, data=%02Xh", vif.addr, vif.data)); end endtask task check_clock; forever begin wait(vif.clk===1'b0); uvm_report_info("MON", "fall clock"); wait(vif.clk===1'b1); uvm_report_info("MON", "rise clock"); end endtaskendclassclass sample_agent extends uvm_agent; `uvm_component_utils(sample_agent) `uvm_new_func sample_driver driver; sample_sequencer sequencer; sample_monitor monitor; function void build_phase(uvm_phase phase); super.build_phase(phase); `build_component(sample_driver,driver) `build_component(sample_sequencer,sequencer) `build_component(sample_monitor,monitor) endfunction function void connect_phase(uvm_phase phase); driver.seq_item_port.connect(sequencer.seq_item_export); endfunctionendclass`define build_component(NAME,INST) \ INST = NAME::type_id::create(`"INST`", this);class sample_env extends uvm_env; `uvm_component_utils(sample_env) `uvm_new_func sample_agent agent; function void build_phase(uvm_phase phase); super.build_phase(phase); `build_component(sample_agent,agent) endfunctionendclassclass test extends uvm_test; `uvm_component_utils(test) `uvm_new_func sample_env env; virtual function void build_phase(uvm_phase phase); uvm_config_db#(uvm_object_wrapper)::set(this, "env.agent.sequencer.run_phase","default_sequence", issue_one_trans_seq::type_id::get()); `build_component(sample_env,env) super.build_phase(phase); endfunctionendclassvirtual class sample_base_sequence extends uvm_sequence #(sample_seq_item); function new(string name="sample_base_seq"); super.new(name); endfunction virtual task pre_body(); if (starting_phase!=null) begin `uvm_info(get_type_name(), $sformatf("%s pre_body() raising %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM); starting_phase.raise_objection(this); end endtask // Drop the objection in the post_body so the objection is removed when // the root sequence is complete. virtual task post_body(); if (starting_phase!=null) begin `uvm_info(get_type_name(), $sformatf("%s post_body() dropping %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM); starting_phase.drop_objection(this); end endtaskendclass///////////////////////////////////////////////class issue_one_trans_seq extends sample_base_sequence; `seq_head(issue_one_trans_seq) virtual task body(); sample_seq_item trans_item; $display("I am issue_one_trans_seq"); `uvm_create(trans_item) trans_item.addr = 8'h00; trans_item.data = 8'h10; `uvm_send(trans_item) #1000ns; endtaskendclass`define seq_head(NAME) \ function new(string name=`"NAME`"); \ super.new(name); \ endfunction \\ `uvm_object_utils(NAME)`timescale 1ps/1psmodule tb_top;// UVM //////////////////////////////////////////////// `include "./uvm-1.1d/src/uvm_macros.svh" import uvm_pkg::*; // model `include "sample.svh" `include "test.sv"////////////////////////////////////////////////////// logic rstz, clk;//// rstz _________|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// clk ^^^^^^^^^^^^^^|__|^^|__|^^|__|^^|__|^^|__|^^// sample_if sif(clk, rstz);// interface initial begin fork begin clk = 1'b1; #100ns; forever #50ns clk = ~clk; end begin rstz = 1'b0; #100ns; rstz = 1'b1; end join end initial begin uvm_config_db#(virtual sample_if)::set(uvm_root::get(), "*", "vif", sif); run_test(); endendmodule