(数字ic验证)从零开始的apb_watchdog验证模块搭建(四、事件触发器与计数检查器)

apb_watchdog验证模块搭建(三、事件触发器与计数检查器)文章目录



前言

本章我们继续完成watchdog的验证工作,在验证环境中添加事件触发器与计数检查器。


一、事件触发器

事件触发器subscriber是指在环境中定义的事件触发模块,无论是scoreboard检查器还是覆盖率收集都需要基于一些事件的触发来进行功能比较与覆盖率收集。因此比较方便的做法是定义一个subscriber来完成事件的定义与一些事件的触发,而scoreboard与coverage模块继承于此父类,从而可以使用其中的事件与方法。

subscriber的代码如下:

`ifndef RKV_WATCHDOG_SUBSCRIBER_SV
`define RKV_WATCHDOG_SUBSCRIBER_SV

`uvm_analysis_imp_decl(_apb)

class rkv_watchdog_subscriber extends uvm_component;

  rkv_watchdog_config cfg;
  rkv_watchdog_rgm rgm;
  virtual rkv_watchdog_if vif;
  local uvm_event_pool _ep;
  uvm_event wdg_inten_e;          //interrupt enable event
  uvm_event wdg_resen_e;          //restet enable event
  uvm_event wdg_load_e;           //load access event
  uvm_event wdg_reg_fd_e;         //register access event(frontdoor)
  uvm_event wdg_reg_bd_e;         //
  uvm_event wdg_assert_inrt_e;    //interrupt asserted event 
  uvm_event wdg_int_clr_e;        //interrupt clear event
  uvm_event wdg_intdis_e;         //interrupt disable event
  uvm_event wdg_assert_res_e;     //reset asserted event
  bit enable; 

  uvm_analysis_imp_apb #(apb_transfer, rkv_watchdog_subscriber) apb_trans_observed_imp;

  `uvm_component_utils(rkv_watchdog_subscriber)

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    apb_trans_observed_imp = new("apb_trans_observed_imp",this);
    if(!uvm_config_db#(rkv_watchdog_config)::get(this, "", "cfg",cfg)) begin
      `uvm_fatal("GTCFG","cannot get cfg from configdb")
    end
    if(!uvm_config_db#(rkv_watchdog_rgm)::get(this, "", "rgm",rgm)) begin
      `uvm_fatal("GTCFG","cannot get rgm from confgdb")
    end
    _ep = new("_ep");
    wdg_reg_fd_e = _ep.get("wdg_reg_fd_e");
    wdg_reg_bd_e = _ep.get("wdg_reg_bd_e");
    wdg_load_e = _ep.get("wdg_load_e");
    wdg_inten_e = _ep.get("wdg_inten_e");
    wdg_resen_e = _ep.get("wdg_resen_e");
    wdg_assert_inrt_e = _ep.get("wdg_assert_inrt_e");
    wdg_int_clr_e = _ep.get("wdg_int_clr_e");
    wdg_intdis_e = _ep.get("wdg_intdis_e");
    wdg_assert_res_e = _ep.get("wdg_assert_res_e");
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    vif = cfg.vif;
    
  endfunction

  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    do_events_check();
  endtask
  virtual function write_apb(apb_transfer t);
    uvm_reg r;
    r = rgm.map.get_reg_by_offset(t.addr);
    wdg_reg_fd_e.trigger(r);
  endfunction

  virtual task do_events_check();
   uvm_object tmp;
   uvm_reg r;
   fork
    begin
      forever begin
        fork 
          wdg_reg_fd_e.wait_trigger_data(tmp);
          wdg_reg_fd_e.wait_trigger_data(tmp);
        join_any
        disable fork;
        void'($cast(r, tmp));
        #1ps; // get the updated value from predictor
        if(r.get_name() == "WDOGCONTROL") begin
          if(rgm.WDOGCONTROL.INTEN.get() == 'b1) wdg_inten_e.trigger();
          if(rgm.WDOGCONTROL.RESEN.get() == 'b0) wdg_resen_e.trigger();
          if(rgm.WDOGCONTROL.INTEN.get() == 'b0) wdg_intdis_e.trigger();
        end
        else if(r.get_name() == "WDOGLOAD") begin
          if(rgm.WDOGLOAD.LOADVAL.get() != 'b0 ) wdg_load_e.trigger();
        end
        else if(r.get_name() == "WDOGINTCLR") begin
          if(rgm.WDOGINTCLR.INTCLR.get() == 'b1 ) wdg_int_clr_e.trigger();
        end
      end
    end
   join_none

  endtask
endclass
`endif // RKV_WATCHDOG_subscriber_SV

subscriber中除了定义所需的interface,register model与config之外。提供了大量的事件,这些事件的触发可用于后面对scoreboard的行为进行影响(如计时开始,结束与重载等)。

同样的,为了实现事件的触发,subscriber必须从monitor中得到当前的寄存器访问信号。与之前寄存器配置中predictor的访问方式相同,apb vip中提供的analysis tlm port:item_collected_port能够帮助完成信号的访问监测。对于写入端(imp),需要完成write函数以实现访问,即上述代码中的write_apb()。在每次寄存器访问时会触发,并将访问的地址传递至触发等待端。触发等待端并得到地址之后,通过地址的值判断访问的事件进行相应的事件触发。

二、scoreboard

scoreboard继承于subscriber,能够完成计数检查,并在不同事件触发时开始,结束或者中断计数的触发。

scoreboard代码如下:

`ifndef RKV_WATCHDOG_SCOREBOARD_SV
`define RKV_WATCHDOG_SCOREBOARD_SV

class rkv_watchdog_scoreboard extends rkv_watchdog_subscriber;
    int cur_load;                           //load value from load reg
    int cur_count;                          //count value which will decrease when counting  
    bit inten_status = 0;                   //value of inten in reg
    bit load_set = 0;                       //value of load in watchdog 
    bit inrt_asserted = 0;                  //means watchdog int has asserted
    bit res_asserted = 0;                   //means watchdog res has asserted
    bit res_able_check = 0;                 //reset check enable
  `uvm_component_utils(rkv_watchdog_scoreboard)

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
  endfunction
 
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    do_countdown_check();
  endtask
  
  virtual task do_countdown_check();
    fork
        forever begin: wait_inten
          wdg_inten_e.wait_trigger();
          inten_status = 1;
          disable load_count_check;
        end
        forever begin: wait_resen
          wdg_resen_e.wait_trigger();
          res_able_check = 1;
        end
        forever begin: wait_int_disable
          wdg_intdis_e.wait_trigger();
          inten_status = 0;
          disable load_count_check;
        end
        forever begin: wait_load_count_val
          wdg_load_e.wait_trigger();
          load_set = 1;
          disable load_count_check;
        end
        forever begin: wait_int_clr
          wdg_int_clr_e.wait_trigger();
          inrt_asserted = 0;
          disable load_count_check;
        end
        forever begin 
          begin: load_count_check
            do_localcount();
          end
        end
    join_none
  endtask

  virtual function bit do_count_able_check();
    if( inten_status && load_set && cfg.enable_scb ) return 1;
    else return 0;
  endfunction

  virtual task do_localcount();
        bit count_check;
        count_check = do_count_able_check();
        @(posedge vif.wdg_clk iff count_check );
        cur_load = rgm.WDOGLOAD.LOADVAL.get();
        cur_count = cur_load;
        do begin
          @(posedge vif.wdg_clk);
          cur_count--;
        end while( cur_count != 0 );
        repeat(2) @(negedge vif.wdg_clk); //in load and clear check need one more clock to reload
        res_able_check = rgm.WDOGCONTROL.RESEN.get(); 
        if( !inrt_asserted && !res_asserted ) begin
          wdg_assert_inrt_e.trigger();
          if( vif.wdogint !=1 ) begin
            cfg.scb_error_count++;
            `uvm_error("CNTDWN", "wdogint is not asserted!!")
          end
          inrt_asserted = 1;
          cfg.scb_check_count++;
        end
        else if( inrt_asserted && !res_asserted && res_able_check ) begin
          if( !vif.wdogres) begin
            cfg.scb_error_count++;
            `uvm_error("CNTDWN","wdogres is not asserted!!!")
          end
            wdg_assert_res_e.trigger();
            res_asserted = 1;
            cfg.scb_check_count++;
        end
  endtask
endclass
`endif //

在scoreboard中对计数进行检查与事件触发监测。这里对do_localcount的逻辑功能进行简单介绍,在满足检查条件(检查器打开,inten为高,watchdog完成计数值加载)时会进行计数检查,计数检查完成之后,若中断信号未触发且watchdog复位信号未触发时,会进行中断触发检查。若中断已经触发且watchdog复位信号也未触发且watchdog复位使能为高时,会进行复位触发检查。

do_countdown_check的逻辑是同时不停地进行不同事件的触发等待以及do_localcount计数等待工作,不同的事件会将计数状态改变,比如中断清除事件会将inrt_asserted = 0;使得中断状态处于未触发状态,并重新开始计数检查。每一个forever begin中就包含了一次会对计数造成影响的寄存器访问行为。

这样,除去上锁功能,其他功能下的计数检查器就已经完成了。

仿真运行结果

运行不同的test,并在计数完成的检查判断中设置断点可得到如下仿真结果:
在这里插入图片描述
并且在report中也完成了scoreboard的检查。
在这里插入图片描述
可知scoreboard的计数检查是比较准确的。


总结

本章完成了watchdog的自动化计数检查,在不同事件的触发下,scoreboard会像watchdog一样对计数行为进行改变从而实现自动化的计数检查,下一章我们将完成watchdog的验证工作,即完成覆盖率的收集。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DW_apb_uart验证功能点是指对DW_apb_uart模块进行测试和验证时要检查的功能点。根据所提供的参考内容,可以得出一些可能的功能点验证如下: 1. 波特率设置:验证DW_apb_uart模块是否能够正确设置和支持不同的波特率,例如9600或115200。 2. 传输速率:验证DW_apb_uart模块是否能够按照设定的波特率进行正确的数据传输,即每秒钟传输的二进制位数是否符合设定的值。 3. 数据传输准确性:验证DW_apb_uart模块是否能够准确地传输数据,包括发送和接收数据的准确性,以及数据的顺序是否正确。 4. UART接口标准规范支持:验证DW_apb_uart模块是否符合UART接口标准规范,如RS232、RS499、RS423、RS422和RS485等,以确保其在嵌入式设备中的兼容性和稳定性。 5. 错误检测和处理:验证DW_apb_uart模块是否能够正确地检测和处理传输过程中的错误,如校验错误、数据丢失等。 6. 中断和DMA支持:验证DW_apb_uart模块是否能够正确地支持中断和DMA功能,以提高数据传输的效率和响应速度。 7. 帧格式支持:验证DW_apb_uart模块是否能够支持不同的帧格式,如数据位、停止位、校验位等的设置和识别。 总之,DW_apb_uart验证功能点是为了确保该模块在实际应用中能够正常、稳定地进行数据传输,并符合相关的接口标准和要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [uart项目验证(一)-uart协议与uart ip的理解](https://blog.csdn.net/whddddddddddd/article/details/125091050)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值