I2C学习笔记——00apb_slv侧 drv变化

APB slave侧:

apb_slave_driver.svh:

        例化config;注册;virtual vif;增加了 bit[31:0] mem [bit[31:0]]来存放数据;

     声明函数new (string name, uvm_component parent); 任务run()、get_and_drive()、drive_transfer(lvc_apb_transfer t)变为drive_response()、reset_listener()、do_idle()、do_write(lvc_apb_transfer t)、do_read(lvc_apb_transfer t);

`ifndef LVC_APB_SLAVE_DRIVER_SVH
`define LVC_APB_SLAVE_DRIVER_SVH

class lvc_apb_slave_driver extends uvm_driver #(lvc_apb_transfer);

  //
  //
  //  Public interface (Component users may manipulate these fields/methods)
  //
  //
  lvc_apb_config cfg;

  // USER: Add your fields here
  bit[31:0] mem [bit[31:0]];

  // This macro performs UVM object creation, type control manipulation, and 
  // factory registration
  `uvm_component_utils_begin(lvc_apb_slave_driver)
     // USER: Register fields here
  `uvm_component_utils_end

  // new - constructor
  extern function new (string name, uvm_component parent);

  // uvm run phase
  extern virtual task run();

  //
  //
  //  Implementation (private) interface
  //
  //

  // The virtual interface used to drive and view HDL signals.
  virtual lvc_apb_if vif;

  // This is the method that is responsible for getting sequence transactions 
  // and driving the transaction into the DUT
  extern virtual protected task get_and_drive();
  
  // This method drives response onto the interface
  extern virtual protected task drive_response();
  // This method that is drive idle respone
  extern protected task do_idle();
  // This method that is proceed write transaction
  extern protected task do_write();
  // This method that is proceed read transaction
  extern protected task do_read();
  

  // This method reset interface signals
  extern virtual protected task reset_listener();
  
endclass : lvc_apb_slave_driver

`endif // LVC_APB_SLAVE_DRIVER_SVH

apb_slave_driver.sv:

         实现头文件中各函数任务;run()→get_and_drive()→get_next_item、drive_transfer(req)中判断trans_kind读写(如下),克隆、id、itemdone→reset_listener(对于vif下)将paddr pwrite psel penable pwdata置0 将总线上prdata pslverr 置0、pready由cfg中SLAVE配置参数确定、将mem清空→drive_response()等待一上升沿,如果psel=1 penable=0(说明总线上有控制信号了)判断读写(如下),否则do idle(对于vif.cb_slv下prdata pslverr置0 pready cfg确定);

        写do_write(t):定义32位addr、data变量和两个存放cfg中随机pready次数pslverr状态的变量;当penable=1将vif 中paddr pwdata存入变量,并放入mem对应地址;根据pready次数决定等待周期并根据pslverr状态回应;第一拍给paddr、pwrite=1、psel=1、penable=0,t.data给pwdata;第二拍penable=1传输数据;10ps后等待接口上pready等于1后,1ps判断接口上pslverr如果为1,状态转为ERROR,不为1转为OK;

        读do_read(t):定义32位addr、data变量和两个存放cfg中随机pready次数pslverr状态的变量;当penable=1将vif 中paddr 存入变量,判断mem中addr如果有数据提出存入data变量,无数据给默认值;根据pready次数决定等待周期并根据pslverr状态回应,data给vif prdata;

`ifndef LVC_APB_SLAVE_DRIVER_SV
`define LVC_APB_SLAVE_DRIVER_SV

function lvc_apb_slave_driver::new (string name, uvm_component parent);
  super.new(name, parent);
endfunction : new

task lvc_apb_slave_driver::run();
   fork
     get_and_drive();
     reset_listener();
     drive_response();
   join_none
endtask : run

task lvc_apb_slave_driver::get_and_drive();
  forever begin
    seq_item_port.get_next_item(req);
    `uvm_info(get_type_name(), "sequencer got next item", UVM_HIGH)
    void'($cast(rsp, req.clone()));
    rsp.set_sequence_id(req.get_sequence_id());
    seq_item_port.item_done(rsp);
    `uvm_info(get_type_name(), "sequencer item_done_triggered", UVM_HIGH)
  end
endtask : get_and_drive

task lvc_apb_slave_driver::drive_response();
  `uvm_info(get_type_name(), "drive_response", UVM_HIGH)
  forever begin
    @(vif.cb_slv);
    if(vif.cb_slv.psel === 1'b1 && vif.cb_slv.penable === 1'b0) begin
      case(vif.cb_slv.pwrite)
        1'b1    : this.do_write();
        1'b0    : this.do_read();
        default : `uvm_error(get_type_name(), "ERROR pwrite signal value")
      endcase
    end
    else begin
      this.do_idle();
    end
  end
endtask : drive_response

task lvc_apb_slave_driver::reset_listener();
  `uvm_info(get_type_name(), "reset_listener ...", UVM_HIGH)
  fork
    forever begin
      @(negedge vif.rstn); // ASYNC reset
      vif.prdata <= 0;
      vif.pslverr <= 0;
      vif.pready <= cfg.slave_pready_default_value;
      this.mem.delete(); // reset internal memory
    end
  join_none
endtask: reset_listener

task lvc_apb_slave_driver::do_idle();
  `uvm_info(get_type_name(), "do_idle", UVM_HIGH)
  vif.cb_slv.prdata <= 0;
  vif.cb_slv.pready <= cfg.slave_pready_default_value;
  vif.cb_slv.pslverr <= 0;
endtask: do_idle

task lvc_apb_slave_driver::do_write();
  bit[31:0] addr;
  bit[31:0] data;
  int pready_add_cycles = cfg.get_pready_additional_cycles();
  bit pslverr_status =  cfg.get_pslverr_status();
  `uvm_info(get_type_name(), "do_write", UVM_HIGH)
  wait(vif.penable === 1'b1);
  addr = vif.cb_slv.paddr;
  data = vif.cb_slv.pwdata;
  mem[addr] = data;
  if(pready_add_cycles > 0) begin
    #1ps;
    vif.pready  <= 0;
    repeat(pready_add_cycles) @(vif.cb_slv);
  end
  #1ps;
  vif.pready  <= 1;
  vif.pslverr <= pslverr_status;
  fork
    begin
      @(vif.cb_slv);
      vif.cb_slv.pready <= cfg.slave_pready_default_value;
      vif.cb_slv.pslverr <= 0;
    end
  join_none
endtask: do_write

task lvc_apb_slave_driver::do_read();
  bit[31:0] addr;
  bit[31:0] data;
  int pready_add_cycles = cfg.get_pready_additional_cycles();
  bit pslverr_status =  cfg.get_pslverr_status();
  `uvm_info(get_type_name(), "do_read", UVM_HIGH)
  wait(vif.penable === 1'b1);
  addr = vif.cb_slv.paddr;
  if(mem.exists(addr))
    data = mem[addr];
  else
    data = DEFAULT_READ_VALUE;
  if(pready_add_cycles > 0) begin
    #1ps;
    vif.pready  <= 0;
    repeat(pready_add_cycles) @(vif.cb_slv);
  end
  #1ps;
  vif.pready  <= 1;
  vif.pslverr <= pslverr_status;
  vif.prdata  <= data;
  fork
    begin
      @(vif.cb_slv);
      vif.cb_slv.pready <= cfg.slave_pready_default_value;
      vif.cb_slv.pslverr <= 0;
    end
  join_none
endtask: do_read

`endif // LVC_APB_SLAVE_DRIVER_SV

apb_slave_monitor.svh:无变化 apb_slave_monitor.sv:---

apb_slave_sequencer.svh、.sv:无变化  apb_slave_agent.svh、.sv:无变化

你可能感兴趣的:(学习,笔记)