6.1 计数和复位使能测试

在之前已经完成了INT信号拉起的测试序列,根据状态机,最后就是当计数器递减到0以后,如果RESEN信号被设置成1,那么复位,对这个状态编写测试序列。
:::info
在seq_lib中新建apb_watchdog_res_en_virt_seq.sv并编辑; :::
``verilogifndef APB_WATCHDOG_RES_EN_VIRT_SEQ_SV `define APB_WATCHDOG_RES_EN_VIRT_SEQ_SVclass apb_watchdog_res_en_virt_seq extends apb_watchdog_base_virt_seq;
`uvm_object_utils(apb_watchdog_res_en_virt_seq)
function new(string name = “apb_watchdog_res_en_virt_seq”); super.new(name); endfunction
virtual task body(); super.body(); `uvm_info(“body”,”Entered…”,UVM_LOW)
// Enable apb_watchdog_reg and its interrupt generation`uvm_do(reg_en_intr)`uvm_do(reg_en_res)// Get load_val`uvm_do_with(reg_loadcount, {load_val == 'hFF;})// Get clear signal//`uvm_do_with(reg_intr_wait_clear, {intval == 50; delay == 1;})fork@(posedge vif.wdog_res);@(posedge vif.wdog_int);join#100us;`uvm_info("body", "EXited...", UVM_LOW)
endtask
endclass
`endif //APB_WATCHDOG_RES_EN_VIRT_SEQ_SV
> fork join的作用是等待一个reset和int中断信号的拉高信号;> 拉高以后再等100us。观察在这一段时间以内int和res的信号是否还有发生其他变化。:::info2. 在test中建立对应的测试文件并编辑;:::```verilog`ifndef APB_WATCHDOG_RES_EN_TEST_SV`define APB_WATCHDOG_RES_EN_TEST_SVclass apb_watchdog_res_en_test extends apb_watchdog_base_test;`uvm_component_utils(apb_watchdog_res_en_test)function new(string name = "apb_watchdog_res_en_test", uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctiontask run_phase(uvm_phase phase);apb_watchdog_res_en_virt_seq seq = apb_watchdog_res_en_virt_seq::type_id::create("this");super.run_phase(phase);phase.raise_objection(this);seq.start(env.virt_sqr);phase.drop_objection(this);endtaskendclass`endif //APB_WATCHDOG_RES_EN_TEST_SV
:::info
在element_seqs.svh文件中导入上一个seq; :::
``verilogifndef APB_WATCHDOG_REG_ENABLE_RESET_SV `define APB_WATCHDOG_REG_ENABLE_RESET_SVclass apb_watchdog_reg_enable_reset extends apb_watchdog_element_base_seq;
`uvm_object_utils(apb_watchdog_reg_enable_reset)
function new(string name = “apb_watchdog_reg_enable_reset”); super.new(name); endfunction
task body(); super.body();
uvm_info("body", "Entered...", UVM_LOW) rgm.WDOGCONTROL.RESEN.set(1'b1); rgm.WDOGCONTROL.update(status);uvm_info(“body”, “Exiting…”, UVM_LOW) endtaskendclass
`endif //APB_WATCHDOG_REG_ENABLE_RESET
:::info4. 在apb_watchdog_base_virt_seq中导入这个seq;:::```verilog`ifndef APB_WATCHDOG_BASE_VIRT_SEQ_SV`define APB_WATCHDOG_BASE_VIRT_SEQ_SVclass apb_watchdog_base_virt_seq extends uvm_sequence;apb_master_single_write_sequence apb_wr_seq;apb_master_single_read_sequence apb_rd_seq;apb_master_write_read_sequence apb_wr_rd_seq;apb_watchdog_reg_enable_intr reg_en_intr;apb_watchdog_reg_intr_wait_clear reg_intr_wait_clear;apb_watchdog_reg_loadcount reg_loadcount;apb_watchdog_reg_enable_reset reg_en_res;...endclass`endif //APB_WATCHDOG_BASE_VIRT_SEQ
:::info
- 在seq_lib中导入apb_watchdog_reset_en_virt_seq.sv;
- 在tests.svh中导入apb_watchdog_reset_enable_test.sv
:::
【调试及结果】

在class中查找res_en,在源代码中分别设置断点。 将DUT中寄存器上的reg_count信号添加到波形窗口中,将该波形的sim.do文件重新保存

根据波形: 当load的值是FF时,开始从FF向下递减,当递减到0的时候,INT信号拉高,由于没有重新编程,因此会重新loadFF值开始向下递减直到0。 当reset信号拉高以后,计数停止。
6.1.2 修改测试用例中的等待信号
:::info 在res_en_virt_seq中我们使用了@(posedge vif.xxx)的方法来等待watchdog寄存器上的INT和RES信号,为了对这些信号能够进行复用,将这些信号定义到base_virt_seq中的task中。 :::
`ifndef APB_WATCHDOG_BASE_VIRT_SEQ_SV`define APB_WATCHDOG_BASE_VIRT_SEQ_SVclass apb_watchdog_base_virt_seq extends uvm_sequence;apb_master_single_write_sequence apb_wr_seq;apb_master_single_read_sequence apb_rd_seq;apb_master_write_read_sequence apb_wr_rd_seq;apb_watchdog_reg_enable_intr reg_en_intr;apb_watchdog_reg_intr_wait_clear reg_intr_wait_clear;apb_watchdog_reg_loadcount reg_loadcount;apb_watchdog_reg_enable_reset reg_en_res;apb_watchdog_config cfg;virtual apb_watchdog_if vif;apb_watchdog_rgm rgm;bit [31:0] rd_val, wr_val;uvm_status_e status;`uvm_object_utils(apb_watchdog_base_virt_seq)`uvm_declare_p_sequencer(apb_watchdog_virtual_sequencer)function new(string name = "apb_watchdog_base_virt_seq");super.new(name);endfunctionvirtual task body();`uvm_info("body","Entered...",UVM_LOW)//Get cfg from p_sequencercfg = p_sequencer.cfg;vif = cfg.vif;rgm = cfg.rgm;`uvm_info("body","Exiting...",UVM_LOW)endtaskvirtual function void compare_data(logic[31:0] val1, logic[31:0] val2);cfg.seq_check_count++;if(val1 === val2)`uvm_info("CMPSUC", $sformatf("val1 'h%0x === val2 'h%0x", val1, val2), UVM_LOW)else begincfg.seq_check_error++;`uvm_error("CMPSUC", $sformatf("val1 'h%0x !== val2 'h%0x", val1, val2))endendfunctiontask wait_int_asserted();@(posedge vif.wdog_int);endtasktask wait_int_released();@(negedge vif.wdog_int);endtasktask wait_reset_asserted();@(posedge vif.wdog_res);endtasktask wait_reset_released();@(negedge vif.wdog_res);endtaskendclass`endif //APB_WATCHDOG_BASE_VIRT_SEQ
6.2 中断功能关闭测试
【思考】 INT拉高以后,在还没有将INT信号擦除的情况下直接对CONTROL寄存器进行配置将INT信号使能中断:
- 计数功能是否还会正常运行;
- Raw status寄存器是怎样的?
:::info 环境搭建与之前一致:
- 在element_seqs中添加apb_watchdog_reg_disable_intr.sv并将enable信号设置为低;
在element_sequences.svh中导入上个seq; :::
``verilogifndef APB_WATCHDOG_REG_DISABLE_INTR_SV `define APB_WATCHDOG_REG_DISABLE_INTR_SVclass apb_watchdog_reg_disable_intr extends apb_watchdog_element_base_seq;
`uvm_object_utils(apb_watchdog_reg_disable_intr)
function new(string name = “apb_watchdog_reg_disable_intr”); super.new(name); endfunction
task body(); super.body();
uvm_info("body", "Entered...", UVM_LOW) rgm.WDOGCONTROL.INTEN.set(1'b0); rgm.WDOGCONTROL.update(status);uvm_info(“body”, “Exiting…”, UVM_LOW) endtaskendclass
`endif //APB_WATCHDOG_REG_DISABLE_INTR
```verilog`ifndef APB_WATCHDOG_ELEMENT_SEQUENCES_SVH`define APB_WATCHDOG_ELEMENT_SEQUENCES_SVH`include "apb_watchdog_element_base_seq.sv"`include "apb_watchdog_reg_enable_intr.sv"`include "apb_watchdog_reg_loadcount.sv"`include "apb_watchdog_reg_intr_wait_clear.sv"`include "apb_watchdog_reg_enable_reset.sv"`include "apb_watchdog_reg_disable_intr.sv"`endif //APB_WATCHDOG_ELEMENT_SEQUENCES_SVH
:::info
- 在seq_lib目录下创建并编辑apb_watchdog_disable_intr_virt_seq.sv;
在seq_lib中的seq_lib.svh文件中导入上一个seq; :::
``verilogifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV `define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SVclass apb_watchdog_disable_intr_virt_seq extends apb_watchdog_base_virt_seq;
`uvm_object_utils(apb_watchdog_disable_intr_virt_seq)
function new(string name = “apb_watchdog_disable_intr_virt_seq”); super.new(name); endfunction
virtual task body(); super.body(); `uvm_info(“body”,”Entered…”,UVM_LOW)
// Enable apb_watchdog_reg and its interrupt generation`uvm_do(reg_en_intr)`uvm_do(reg_en_res)// Get load_val`uvm_do_with(reg_loadcount, {load_val == 'hFF;})// Get clear signal//`uvm_do_with(reg_intr_wait_clear, {intval == 50; delay == 1;})#10us;`uvm_do(reg_dis)forkwait_int_asserted();wait_reset_released();join#20us;`uvm_info("body", "EXited...", UVM_LOW)
endtask
endclass
`endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
> 第一轮等待了Int信号拉高,第二轮等待了reset信号拉高。```verilog`ifndef APB_WATCHDOG_SEQ_LIB_SVH`define APB_WATCHDOG_SEQ_LIB_SVH`include "apb_watchdog_element_sequences.svh"`include "apb_watchdog_base_virt_seq.sv"`include "apb_watchdog_integration_virt_seq.sv"`include "apb_watchdog_regacc_virt_seq.sv"`include "apb_watchdog_apbacc_virt_seq.sv"`include "apb_watchdog_countdown_virt_seq.sv"`include "apb_watchdog_res_en_virt_seq.sv"`include "apb_watchdog_disable_intr_virt_seq.sv"`endif //APB_WATCHDOG_SEQ_LIB.SVH
:::info
- 在test目录下创建并编辑apb_watchdog_disable_intr_test.sv
在tests.svh中导入上一个测试文件 :::
``verilogifndef APB_WATCHDOG_TESTS_SVH `define APB_WATCHDOG_TESTS_SVHinclude "apb_watchdog_base_test.sv"include “apb_watchdog_apbacc_test.sv”include "apb_watchdog_integration_test.sv"include “apb_watchdog_regacc_test.sv”include "apb_watchdog_countdown_test.sv"include “apb_watchdog_res_en_test.sv” `include “apb_watchdog_disable_intr_test.sv”
`endif //APB_WATCHDOG_TESTS_SVH
:::info❗编辑apb_watchdog_disable_intr_virt_seq.sv:::```verilog`ifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV`define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SVclass apb_watchdog_disable_intr_virt_seq extends apb_watchdog_base_virt_seq;`uvm_object_utils(apb_watchdog_disable_intr_virt_seq)function new(string name = "apb_watchdog_disable_intr_virt_seq");super.new(name);endfunctionvirtual task body();super.body();`uvm_info("body","Entered...",UVM_LOW)// Enable apb_watchdog_reg and its interrupt generation`uvm_do(reg_en_intr)// Get load_val`uvm_do_with(reg_loadcount, {load_val == 'hFF;})wait_int_asserted();// wait interrupt signal highcheck_reg_ris_mis(1'b1, 1'b1);repeat(20) @(posedge vif.wdg_clk);fork`uvm_do(reg_dis_intr) // disable reg_dis_intrwait_int_released(); // wait interrupt signal releasedjoincheck_reg_ris_mis(1'b1, 1'b0);#1us; // idle time monitoring count`uvm_info("body", "EXited...", UVM_LOW)endtasktask check_reg_ris_mis(input ris, input mis);rgm.WDOGRIS.mirror(status);compare_data(ris, rgm.WDOGRIS.RAWINT.get());rgm.WDOGMIS.mirror(status);compare_data(mis, rgm.WDOGMIS.INT.get());endtaskendclass`endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
WDOGRIS是INT寄存器的原始状态(RAW status); WDOGMIS是INT寄存器与INTEN使能信号与之后的状态。虽然将ENABLE信号拉低了,但是原始状态仍然为高,这里需要区分清除。
【调试及结果】

在class中输入dis并设置断点


波形图如上,等到了INT信号拉高并进行比较,两次结果相等; 不清除INT信号直接将使能信号中断,计数功能停止。Raw状态(后台状态,没有被清除的状态下仍然为高),但是软件状态一侧读取到的值为低,也就是MIS status。
6.3 中断功能关闭再使能测试
【思考】 将INTEN信号拉低以后,INT在后台状态仍然是拉高的,只是被mask掉了,那么思考: 将INTEN信号再次拉高以后,INT信号是否立刻为高呢?为此再进行以下测试:
:::info 在apb_watchdog_disable_intr_virt_seq.sv添加拉高INTEN的语句 :::
`ifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV`define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SVclass apb_watchdog_disable_intr_virt_seq extends apb_watchdog_base_virt_seq;`uvm_object_utils(apb_watchdog_disable_intr_virt_seq)function new(string name = "apb_watchdog_disable_intr_virt_seq");super.new(name);endfunctionvirtual task body();super.body();`uvm_info("body","Entered...",UVM_LOW)// Enable apb_watchdog_reg and its interrupt generation`uvm_do(reg_en_intr)// Get load_val`uvm_do_with(reg_loadcount, {load_val == 'hFF;})wait_int_asserted();// wait interrupt signal highcheck_reg_ris_mis(1'b1, 1'b1);repeat(20) @(posedge vif.wdg_clk);fork`uvm_do(reg_dis_intr) // disable reg_dis_intrwait_int_released(); // wait interrupt signal releasedjoincheck_reg_ris_mis(1'b1, 1'b0);// Enable interrupt signal again`uvm_do(reg_en_intr)// Check INT signal imediatelycompare_data(vif.wdog_int, 1'b1);check_reg_ris_mis(1'b1, 1'b1);#1us; // idle time monitoring count`uvm_info("body", "EXited...", UVM_LOW)endtasktask check_reg_ris_mis(input ris, input mis);rgm.WDOGRIS.mirror(status);compare_data(ris, rgm.WDOGRIS.RAWINT.get());rgm.WDOGMIS.mirror(status);compare_data(mis, rgm.WDOGMIS.INT.get());endtaskendclass`endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV

根据结果来看,INTEN重新使能以后,INT信号是立即拉高的,INT的两个status的值也都是1。
