很早之前就说写一个简单的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

标签: UVM, SV

已有 3 条评论

  1. 新盘 上车集合 留下 我要发发 立马进裙coinsrore.com

  2. 新车首发,新的一年,只带想赚米的人

  3. 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

添加新评论