AHB-to-APB Bridge——04apb_tran、apb_if、apb_drv、mem、apb_mon、apb_agt

 

apb_if放入所有apb需要的信号,以及cb

`ifndef APB_IF_SV
`define APB_IF_SV

interface apb_if;
    logic                                    pclk;
    logic                                    prst;

    logic                                    penable;
    logic                                    psel;
    logic                                    pwrite;
    logic[31 : 0]  							 prdata;
    logic[31 : 0]   						 pwdata;
    logic[31 : 0]  							 paddr;
    logic[2:0]                               prot;
    logic[3:0]                               pstrb;
    logic                                    pready;
    logic                                    pslverr;

clocking slv_cb@(posedge pclk);
   default input #1ps output #1ps;
   input penable,psel,pwrite,pwdata,paddr,prot,pstrb;
   output prdata,pready,pslverr;
endclocking:slv_cb

clocking mon_cb@(posedge pclk);
   default input #1ps output #1ps;
   input penable,psel,pwrite,pwdata,paddr,prot,pstrb;
   input prdata,pready,pslverr;
endclocking:mon_cb

endinterface

`endif // APB_IF_SV

slv_tran的Read or Write,AHB-ram是在types文件里定义,这个在package里定义了

`ifndef APB_TRAN_SV
`define APB_TRAN_SV
    
class apb_tran extends uvm_sequence_item;

rand logic[31 : 0] pdata;
rand logic[31 : 0] paddr;
rand logic[2:0]    prot; 
rand logic[3:0]    pstrb;
rand bit           pslverr;
rand int  unsigned nready_num;//cycle number

rand pkind_type_enum  pkind_type;
//Read or Write 之前是在types文件里定义 这个在package里定义了

    `uvm_object_utils_begin(apb_tran)
        `uvm_field_int(paddr,UVM_DEFAULT)
        `uvm_field_int(pdata,UVM_DEFAULT)
        `uvm_field_int(prot,UVM_DEFAULT)
        `uvm_field_int(pstrb,UVM_DEFAULT)
        `uvm_field_int(pslverr,UVM_DEFAULT)
        `uvm_field_int(nready_num,UVM_DEFAULT)
        `uvm_field_enum(pkind_type_enum,pkind_type,UVM_DEFAULT)
    `uvm_object_utils_end

    function new (string name = "apb_tran");
        super.new(name);
    endfunction

endclass
`endif//APB_TRAN_SV

apb_drv:  使用一个mem(32,32)存放数据,传递vif(之前在agent传递并连接drv、mon);get and run要确保penable=0 psel=1时开始;在drive_one_t中根据tran中的nready_num测试没有准备好的状态;写操作放入mem;读操作从mem提出;

`ifndef APB_SLV_DRV_SV
`define APB_SLV_DRV_SV
class apb_slv_drv extends uvm_driver#(apb_tran);
 
  `uvm_component_utils(apb_slv_drv)
  virtual apb_if vif;
  apb_mem#(32,32) mem;//存放写data数据
  apb_tran 		    t;
  function new(string name = "apb_slv_drv", uvm_component parent);
      super.new(name,parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
	t=apb_tran::type_id::create("pkt",this);
	mem=apb_mem#(32,32)::type_id::create("apb_mem",this);
	if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))begin
      `uvm_fatal("NO VIF","vif is not found");//传递vif 之前是在agent传递并连接drv、mon
    end
  endfunction

  virtual task run_phase(uvm_phase phase);
    super.run_phase(phase);
	vif.slv_cb.pready  <= 1'b1;//初始化ready、slverr
    vif.slv_cb.pslverr <= 1'b0;
	fork
		get_and_drive();
	join_none
  endtask
  
  virtual task get_and_drive();
	forever begin
	  @(vif.slv_cb)
	  if(!vif.slv_cb.penable & vif.slv_cb.psel)begin//sel阶段
		seq_item_port.get_next_item(t);
		`uvm_info(get_type_name(),"sequencer got next item",UVM_HIGH)
		drive_one_t(t);
        seq_item_port.item_done(t);
        `uvm_info(get_type_name(), "sequencer item_done_triggered", UVM_HIGH)
	  end
	end 
  endtask:get_and_drive
  
  virtual task drive_one_t(apb_tran t);
	int nready_cnt;
	nready_cnt = t.nready_num;//测试nready
	while(nready_cnt != 0)begin
		vif.slv_cb.pready <= 1'b0;
		nready_cnt--;
		@(vif.slv_cb);
	end
    vif.slv_cb.pready <= 1'b1;
    vif.slv_cb.pslverr<= t.pslverr;

    if(vif.slv_cb.pwrite)
      do_write(t);
    else
      do_read(t);
  endtask
  
  virtual task do_write(apb_tran t);//写操作放入mem
    if(!t.pslverr)begin
      mem.put_data(vif.slv_cb.paddr,vif.slv_cb.pwdata);
    end
  endtask

  virtual task do_read(apb_tran t);//读操作从mem提出
   if(!t.pslverr)begin
      vif.slv_cb.prdata <= mem.get_data(vif.slv_cb.paddr);
    end
    else begin
      vif.slv_cb.prdata <= t.pdata;
    end
  endtask

endclass

`endif//APB_SLV_DRV_SV


mem:写入put进去  读出时判断是否存在写入过的地址

class apb_mem#(DW=32,AW=32) extends uvm_object;

  `uvm_object_param_utils(apb_mem)
  logic [DW-1:0] mem[int];

  function new(string name = "apb_mem");
    super.new(name);
  endfunction

  task put_data(int addr,logic[DW-1:0] data);
    this.mem[addr] = data;
    `uvm_info(get_full_name(), $sformatf("APB-Memory Write.Address:%0h. Data:%0h.",addr,data),UVM_MEDIUM)
  endtask

  function logic[DW-1:0] get_data(int addr);
    if(this.mem.exists(addr))begin//判断mem中是否有这个地址写入过
      get_data = this.mem[addr];
      `uvm_info(get_full_name(), $sformatf("APB-Memory pre-defined Read.Address:%0h. Data:%0h.",addr,get_data),UVM_MEDIUM)
    end
    else begin
      get_data = $urandom_range(32'hffff_ffff);
      `uvm_info(get_full_name(), $sformatf("APB-Memory un-defined Read.Address:%0h. Data:%0h.",addr,get_data),UVM_MEDIUM)
    end
  endfunction
endclass

mon:

`ifndef APB_SLV_MON
`define APB_SLV_MON

class apb_slv_mon extends uvm_monitor;
  `uvm_component_utils(apb_slv_mon)
  uvm_analysis_port #(apb_tran) item_port;
  virtual apb_if vif;


  function new(string name = "apb_slv_mon", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
	item_port = new("item_observed_port", this);
	 if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))begin
      `uvm_fatal("No vif","vif is not found")
    end
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
	apb_tran t;
	while(1)begin
      @(vif.mon_cb);
      if(vif.mon_cb.penable & vif.mon_cb.pready &vif.mon_cb.psel & vif.mon_cb.presetn)begin
        t = apb_tran::type_id::create("t",this);
        t.paddr = vif.mon_cb.paddr;
        t.prot = vif.mon_cb.prot;
        t.pslverr = vif.mon_cb.pslverr;
        t.pkind_type = vif.mon_cb.pwrite ? WRITE:READ;
        t.pdata = vif.mon_cb.pwrite ? vif.mon_cb.pwdata : vif.mon_cb.prdata;
        item_port.write(t);
      end
    end
  endtask
endclass

`endif // APB_SLV_MON

apb_agt: 如果is_active为1例化sqr、drv,否则只例化mon

                方便芯片集成以后只接收别的模块来的信号,不需要自己发送激励

`ifndef APB_SLV_AGT_SV
`define APB_SLV_AGT_SV

class apb_slv_agt extends uvm_agent;

  apb_slv_drv drv;
  apb_slv_mon mon;
  apb_slv_sqr sqr;

  virtual apb_if vif;

  `uvm_component_utils(apb_slv_agt)

  function new(string name = "apb_slv_agt", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))begin
        `uvm_fatal("GETVIF","cannot get vif handle from config DB")
    end

    mon = apb_slv_mon::type_id::create("mon",this);
	uvm_config_db#(virtual apb_if)::set(this,"mon_i","vif",vif);
	
    void'(uvm_config_db#(uvm_active_passive_enum)::get(this,"","is_active",is_active));	
	if(is_active == UVM_ACTIVE)begin
      sqr_i = apb_slv_sqr::type_id::create("sqr_i",this);
      drv_i = apb_slv_drv::type_id::create("drv_i",this);
      uvm_config_db#(virtual apb_if)::set(this,"drv_i","vif",vif);
    end
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(is_active == UVM_ACTIVE)begin
      drv_i.seq_item_port.connect(sqr_i.seq_item_export);
    end
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
  endtask

endclass


`endif // APB_SLV_AGT_SV

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RCC_AHB1PeriphClockCmd和RCC_APB2PeriphClockCmd是用于STM32系列微控制器的RCC(Reset and Clock Control)模块的函数。 RCC_AHB1PeriphClockCmd函数用于使能或禁用AHB1总线上的外设时钟。AHB1总线上的外设包括GPIO端口、DMA、CRC等。函数原型如下: ```c void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); ``` 其中,RCC_AHB1Periph参数指定要使能或禁用的外设,可以使用逻辑或运算符(|)同时指定多个外设。NewState参数指定要设置的状态,可以是ENABLE(使能)或DISABLE(禁用)。 例如,要使能GPIOA和GPIOB的时钟,可以使用以下代码: ```c RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE); ``` RCC_APB2PeriphClockCmd函数用于使能或禁用APB2总线上的外设时钟。APB2总线上的外设包括USART、SPI、ADC等。函数原型如下: ```c void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); ``` 其中,RCC_APB2Periph参数指定要使能或禁用的外设,可以使用逻辑或运算符(|)同时指定多个外设。NewState参数指定要设置的状态,可以是ENABLE(使能)或DISABLE(禁用)。 例如,要使能USART1和SPI1的时钟,可以使用以下代码: ```c RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_SPI1, ENABLE); ``` 需要注意的是,具体使用哪个函数取决于外设所连接的总线。AHB1总线连接的外设使用RCC_AHB1PeriphClockCmd函数,而APB2总线连接的外设使用RCC_APB2PeriphClockCmd函数。请根据具体的外设和总线类型选择适当的函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值