UVM验证平台搭建二:apb_agent

10 篇文章 25 订阅


一、概述

在搭建UVM验证平台过程中,AMBA总线是会被经常用到的,一般情况下在对寄存器的读写都会用到apb和ahb总线。本文在上章生成的spi_reg_model的基础上,来搭建UVM验证平台的组件apb agent,该组件其实是可以直接调用vip的,而且像apb、ahb这种在不同的项目中,重用性还是很高的,在当前项目中用完,后续项目也可以直接移植该agent到新的项目。下文根据apb总线协议来实现UVM验证平台中的apb agent组件。

二、apb interface

interface apb_if(input bit pclk, input bit  presetn);
    
    logic [9:0]     paddr;
    logic [31:0]    prdata;
    logic [31:0]    pwdata;
    logic           psel;
    logic           penable;
    logic           pwrite;
    logic           pready;
    logic           pslverr;
    logic  [3:0]    pstrb;
    
    clocking master_ck @(posedge pclk);
        input   preadgy;
        output  pwrite;
        output  paddr;
        output  pwdata;
        output  psel;
        output  penable;
        output  pstrb;
        output  prdata;
    endcloking
    
    clocking slave _ck @(posedge pclk);
        input   pwrite;
        input   paddr;
        input   pwdata;
        input   psel;
        input   penable;
        output  prdata;
    endclocking
    
    clocking passive_ck @(posedge pclk);
        input   pwrite;
        input   paddr;
        input   pwdata;
        input   psel;
        input   penable;
        input   prdata;
    endclocking
    
    modport master_if(clocking master_ck);
    modport slave_if(clocking slave_ck);
    modport passive_if(clocking passive_ck);
endinterface

三、apb transaction

class apb_trans extends uvm_sequence_item;
    
    typedef enum {READ,WRITE} op_kind;
    
    logic [31:0]    data;
    rand            op_kind,kind;
    logic [9:0]     addr;
    logic [15:0]    tdr_data;
    logic [15:0]    rdr_data;
    logic [3:0]     pstrb;
    
    `uvm_object_utils_begin(apb_trans)
        `uvm_field_int(addr, UVM_ALL_ON);
        `uvm_field_int(data, UVM_ALL_ON);
        `uvm_field_int(tdr_data, UVM_ALL_ON);
        `uvm_field_int_rdr_data, UVM_ALL_ON);
        `uvm_field_int(op_kind,kind,UVM_ALL_ON);
        `uvm_field_int(pstrb);
    `uvm_object_utils_end

    function new(string name = "apb_trans");
        super.new(name);
    endfunctuion
endclass

四、apb sequencer

class apb_sequencer extends uvm_sequencer#(apb_trans);

    ral_block_reg_model p_rm;
    
    function new(string name = "apb_sequencer", uvm_component parent);
        super.new(name,parent);
    endfunction
    
    `uvm_component_utils(apb_sequencer)
endclass

五、apb adapter

class apb_adapt extnds uvm_adapter);
    
    function new(string name = "apb_adapter");
        super.new(name);
    endfunction
    
    virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
        apb_trans apb;
        apb = apb_trans::type_id::create("apb_trans");
        apb.kind = (rw.kind == UVM_READ) ? apb_trans::READ : apb_trans::WRITE;
        apb.addr = rw.addr;
        apb.data = rw.data;
        return apb;
    endfunction
    
    virtual function void bus2reg(uvm_sequence_item bus_item,ref uvm_reg_bus_op rw);
        apb_trans apb;
        if(!$cast(apb,bus_item)) begin
            `uvm_fatal("NO APB TYPE","Provided bus_item is not of the correct type!")
            return;
        end
        rw.kind = (apb.kind == apb_trans::READ) ? UVM_READ : UVM_WRITE;
        rw.addr = apb.addr;
        rw.data = apb.data;
        rw.status = UVM_IS_OK;
    endfunction
    
endclass 

六、apb_driver

class apb_driver extends uvm_driver#(apb_trans);
    
    `uvm_component_utils(apb_driver)
    virtual apb_if bif;
    process precesses[string];
    
    function new(string name, uvm_component parent);
        super.new(name,parent);
    endfunction
    
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if(!uvm_config_db#(virtual apb_if)::get(this,"","bif",bif)) begin
            `uvm_fatal("apb_driver",No driver intreface specifed for this driver interface!)
        end
    endfunction
    
    virtual task run_phase(uvm_phase phase);
        process proc_apb_driver;
        super.run_phase(phase);
        
        this.bif.master_ck.psel     <= 'b0;
        this.bif.master_ck.penable  <= 'b0;
        this.bif.master_ck.pwdata   <= 32'h0;
        this.bif.master_ck.paddr    <= 10'h0;
        this.bif.master_ck.pwrite   <= 'b0;
        
        fork 
            begin
                while(!bif.presetn)
                    @(posedge bif.pclk);
                forever begin
                    apb_trans tr;
                    proc_apb_driver = process::self();
                    processes["proc_apb_driver"] = proc_apb_driver;
                    @(this.bif.master_ck);
                    seq_item_port.get_next_item(tr);
                    case(tr.kind)
                        apb_trans::READ: this.read(tr.addr, tr.data);
                        apb_trans::WRITE: this.write(tr.addr, tr.data);
                    endcase
                    seq_item_port.item_done();
                end
            end
            begin
                wait_reset();
            end
        join
    endtask
    
    virtual protected task read(input logic [31:0] addr, ouput logic [31:0] data);
        @(this.bif.master_ck);
        this.bif.master_ck.psel     <= '1;
        this.bif.master_ck.penable  <= '0;
        this.bif.master_ck.pwrite   <= '0;
        this.bif.master_ck.paddr    <= addr;
        @(this.bif.master_ck);
        this.bif.master_ck.penable  <= '1;
        @(this.bif.master_ck);
        while(~this.bif.master_ck.pready)
            @(this.bif.master_ck);
        data <= this.bif.master_ck.prdata;
        this.bif.master_ck.psel     <= '0;
        this.bif.master_ck.penable  <= '0;
    endtask
    
    virtual protected task write(input logic [31:0] addr, output logic [31:0] data);
        @(this.bif.master_ck);
        this.bif.master_ck.paddr    <= addr;
        this.bif.master_ck.pwdata   <= data;
        this.bif.master_ck.pwrite   <= '1;
        this.bif.master_ck.psel     <= '1;
        this.bif.master_ck.penable  <= '0;
        @(this.bif.master_ck);
        this.bif.master_ck.penable  <= '1;
        @(this.bif.master_ck);
        while(~this.bif.master_ck.pready)
            @(this.bif.master_ck);
        this.bif.master_ck.psel     <= '0;
        this.bif.master_ck.penable  <= '0;
        this.bif.master_ck.pwdata   <= '0;
    endtask
    
    virtual protected task wait_reset();
        forever begin
            @(posedge bif.presetn);
            foreach(process[i])
                processes[i].kill();
            @(posedge bif.presetn);
        end
    endtask
endclass

七、apb agent

class apb_agent extends uvm_agent;

    apb_driver drv;
    apb_sequencer sqr;
    
    `uvm_component_utils_begin(apb_agetn)
        `uvm_field_object(drv,UVM_ALL_ON);
        `uvm_field_object(sqr,UVM_ALL_ON);
    `uvm_component_utils_end
    
    function new(string name, uvm_component parent);
        super.new(name,parent);
    endfunction
    
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        drv = apb_driver::type_id::create("drv",this);
        sqr = apb_sequencer::type_id::create("sqr",this);
    endfunction
    
    virtual function void connect_phase(uvm_phase phase);
        drv.seq_item_port.connect(sqr.seq_item_export);
    endfunction
endclass

八、apb agent pkg

package apb_agent_pkg;

    import uvm_pkg::*:
    `include "uvm_macros.svh"
    import spi_reg_pkg::*;
    
    `include "apb_transaction.svh"
    `include "apb_sequencer.svh"
    `include "apb_driver.svh"
    `include "apb_adapter.svh"
    `include "apb_agent.svh"
    
endpackage: apb_agent_pkg
  • 2
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值