6.1 计数和复位使能测试

image.png

在之前已经完成了INT信号拉起的测试序列,根据状态机,最后就是当计数器递减到0以后,如果RESEN信号被设置成1,那么复位,对这个状态编写测试序列。

:::info

  1. 在seq_lib中新建apb_watchdog_res_en_virt_seq.sv并编辑; ::: ``verilogifndef APB_WATCHDOG_RES_EN_VIRT_SEQ_SV `define APB_WATCHDOG_RES_EN_VIRT_SEQ_SV

    class 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)

    1. // Enable apb_watchdog_reg and its interrupt generation
    2. `uvm_do(reg_en_intr)
    3. `uvm_do(reg_en_res)
    4. // Get load_val
    5. `uvm_do_with(reg_loadcount, {load_val == 'hFF;})
    6. // Get clear signal
    7. //`uvm_do_with(reg_intr_wait_clear, {intval == 50; delay == 1;})
    8. fork
    9. @(posedge vif.wdog_res);
    10. @(posedge vif.wdog_int);
    11. join
    12. #100us;
    13. `uvm_info("body", "EXited...", UVM_LOW)

    endtask

    endclass

`endif //APB_WATCHDOG_RES_EN_VIRT_SEQ_SV

  1. > fork join的作用是等待一个resetint中断信号的拉高信号;
  2. > 拉高以后再等100us。观察在这一段时间以内intres的信号是否还有发生其他变化。
  3. :::info
  4. 2. test中建立对应的测试文件并编辑;
  5. :::
  6. ```verilog
  7. `ifndef APB_WATCHDOG_RES_EN_TEST_SV
  8. `define APB_WATCHDOG_RES_EN_TEST_SV
  9. class apb_watchdog_res_en_test extends apb_watchdog_base_test;
  10. `uvm_component_utils(apb_watchdog_res_en_test)
  11. function new(string name = "apb_watchdog_res_en_test", uvm_component parent);
  12. super.new(name, parent);
  13. endfunction
  14. function void build_phase(uvm_phase phase);
  15. super.build_phase(phase);
  16. endfunction
  17. task run_phase(uvm_phase phase);
  18. apb_watchdog_res_en_virt_seq seq = apb_watchdog_res_en_virt_seq::type_id::create("this");
  19. super.run_phase(phase);
  20. phase.raise_objection(this);
  21. seq.start(env.virt_sqr);
  22. phase.drop_objection(this);
  23. endtask
  24. endclass
  25. `endif //APB_WATCHDOG_RES_EN_TEST_SV

:::info

  1. 在element_seqs.svh文件中导入上一个seq; ::: ``verilogifndef APB_WATCHDOG_REG_ENABLE_RESET_SV `define APB_WATCHDOG_REG_ENABLE_RESET_SV

    class 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) endtask

    endclass

`endif //APB_WATCHDOG_REG_ENABLE_RESET

  1. :::info
  2. 4. apb_watchdog_base_virt_seq中导入这个seq
  3. :::
  4. ```verilog
  5. `ifndef APB_WATCHDOG_BASE_VIRT_SEQ_SV
  6. `define APB_WATCHDOG_BASE_VIRT_SEQ_SV
  7. class apb_watchdog_base_virt_seq extends uvm_sequence;
  8. apb_master_single_write_sequence apb_wr_seq;
  9. apb_master_single_read_sequence apb_rd_seq;
  10. apb_master_write_read_sequence apb_wr_rd_seq;
  11. apb_watchdog_reg_enable_intr reg_en_intr;
  12. apb_watchdog_reg_intr_wait_clear reg_intr_wait_clear;
  13. apb_watchdog_reg_loadcount reg_loadcount;
  14. apb_watchdog_reg_enable_reset reg_en_res;
  15. ...
  16. endclass
  17. `endif //APB_WATCHDOG_BASE_VIRT_SEQ

:::info

  1. 在seq_lib中导入apb_watchdog_reset_en_virt_seq.sv;
  2. 在tests.svh中导入apb_watchdog_reset_enable_test.sv :::

    【调试及结果】

    image.png

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

image.png

根据波形: 当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中。 :::

  1. `ifndef APB_WATCHDOG_BASE_VIRT_SEQ_SV
  2. `define APB_WATCHDOG_BASE_VIRT_SEQ_SV
  3. class apb_watchdog_base_virt_seq extends uvm_sequence;
  4. apb_master_single_write_sequence apb_wr_seq;
  5. apb_master_single_read_sequence apb_rd_seq;
  6. apb_master_write_read_sequence apb_wr_rd_seq;
  7. apb_watchdog_reg_enable_intr reg_en_intr;
  8. apb_watchdog_reg_intr_wait_clear reg_intr_wait_clear;
  9. apb_watchdog_reg_loadcount reg_loadcount;
  10. apb_watchdog_reg_enable_reset reg_en_res;
  11. apb_watchdog_config cfg;
  12. virtual apb_watchdog_if vif;
  13. apb_watchdog_rgm rgm;
  14. bit [31:0] rd_val, wr_val;
  15. uvm_status_e status;
  16. `uvm_object_utils(apb_watchdog_base_virt_seq)
  17. `uvm_declare_p_sequencer(apb_watchdog_virtual_sequencer)
  18. function new(string name = "apb_watchdog_base_virt_seq");
  19. super.new(name);
  20. endfunction
  21. virtual task body();
  22. `uvm_info("body","Entered...",UVM_LOW)
  23. //Get cfg from p_sequencer
  24. cfg = p_sequencer.cfg;
  25. vif = cfg.vif;
  26. rgm = cfg.rgm;
  27. `uvm_info("body","Exiting...",UVM_LOW)
  28. endtask
  29. virtual function void compare_data(logic[31:0] val1, logic[31:0] val2);
  30. cfg.seq_check_count++;
  31. if(val1 === val2)
  32. `uvm_info("CMPSUC", $sformatf("val1 'h%0x === val2 'h%0x", val1, val2), UVM_LOW)
  33. else begin
  34. cfg.seq_check_error++;
  35. `uvm_error("CMPSUC", $sformatf("val1 'h%0x !== val2 'h%0x", val1, val2))
  36. end
  37. endfunction
  38. task wait_int_asserted();
  39. @(posedge vif.wdog_int);
  40. endtask
  41. task wait_int_released();
  42. @(negedge vif.wdog_int);
  43. endtask
  44. task wait_reset_asserted();
  45. @(posedge vif.wdog_res);
  46. endtask
  47. task wait_reset_released();
  48. @(negedge vif.wdog_res);
  49. endtask
  50. endclass
  51. `endif //APB_WATCHDOG_BASE_VIRT_SEQ

6.2 中断功能关闭测试

【思考】 INT拉高以后,在还没有将INT信号擦除的情况下直接对CONTROL寄存器进行配置将INT信号使能中断:

  1. 计数功能是否还会正常运行;
  2. Raw status寄存器是怎样的?

:::info 环境搭建与之前一致:

  1. 在element_seqs中添加apb_watchdog_reg_disable_intr.sv并将enable信号设置为低;
  2. 在element_sequences.svh中导入上个seq; ::: ``verilogifndef APB_WATCHDOG_REG_DISABLE_INTR_SV `define APB_WATCHDOG_REG_DISABLE_INTR_SV

    class 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) endtask

    endclass

`endif //APB_WATCHDOG_REG_DISABLE_INTR

  1. ```verilog
  2. `ifndef APB_WATCHDOG_ELEMENT_SEQUENCES_SVH
  3. `define APB_WATCHDOG_ELEMENT_SEQUENCES_SVH
  4. `include "apb_watchdog_element_base_seq.sv"
  5. `include "apb_watchdog_reg_enable_intr.sv"
  6. `include "apb_watchdog_reg_loadcount.sv"
  7. `include "apb_watchdog_reg_intr_wait_clear.sv"
  8. `include "apb_watchdog_reg_enable_reset.sv"
  9. `include "apb_watchdog_reg_disable_intr.sv"
  10. `endif //APB_WATCHDOG_ELEMENT_SEQUENCES_SVH

:::info

  1. 在seq_lib目录下创建并编辑apb_watchdog_disable_intr_virt_seq.sv;
  2. 在seq_lib中的seq_lib.svh文件中导入上一个seq; ::: ``verilogifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV `define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV

    class 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)

    1. // Enable apb_watchdog_reg and its interrupt generation
    2. `uvm_do(reg_en_intr)
    3. `uvm_do(reg_en_res)
    4. // Get load_val
    5. `uvm_do_with(reg_loadcount, {load_val == 'hFF;})
    6. // Get clear signal
    7. //`uvm_do_with(reg_intr_wait_clear, {intval == 50; delay == 1;})
    8. #10us;
    9. `uvm_do(reg_dis)
    10. fork
    11. wait_int_asserted();
    12. wait_reset_released();
    13. join
    14. #20us;
    15. `uvm_info("body", "EXited...", UVM_LOW)

    endtask

    endclass

`endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV

  1. > 第一轮等待了Int信号拉高,第二轮等待了reset信号拉高。
  2. ```verilog
  3. `ifndef APB_WATCHDOG_SEQ_LIB_SVH
  4. `define APB_WATCHDOG_SEQ_LIB_SVH
  5. `include "apb_watchdog_element_sequences.svh"
  6. `include "apb_watchdog_base_virt_seq.sv"
  7. `include "apb_watchdog_integration_virt_seq.sv"
  8. `include "apb_watchdog_regacc_virt_seq.sv"
  9. `include "apb_watchdog_apbacc_virt_seq.sv"
  10. `include "apb_watchdog_countdown_virt_seq.sv"
  11. `include "apb_watchdog_res_en_virt_seq.sv"
  12. `include "apb_watchdog_disable_intr_virt_seq.sv"
  13. `endif //APB_WATCHDOG_SEQ_LIB.SVH

:::info

  1. 在test目录下创建并编辑apb_watchdog_disable_intr_test.sv
  2. 在tests.svh中导入上一个测试文件 ::: ``verilogifndef APB_WATCHDOG_TESTS_SVH `define APB_WATCHDOG_TESTS_SVH

    include "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

  1. :::info
  2. ❗编辑apb_watchdog_disable_intr_virt_seq.sv
  3. :::
  4. ```verilog
  5. `ifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
  6. `define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
  7. class apb_watchdog_disable_intr_virt_seq extends apb_watchdog_base_virt_seq;
  8. `uvm_object_utils(apb_watchdog_disable_intr_virt_seq)
  9. function new(string name = "apb_watchdog_disable_intr_virt_seq");
  10. super.new(name);
  11. endfunction
  12. virtual task body();
  13. super.body();
  14. `uvm_info("body","Entered...",UVM_LOW)
  15. // Enable apb_watchdog_reg and its interrupt generation
  16. `uvm_do(reg_en_intr)
  17. // Get load_val
  18. `uvm_do_with(reg_loadcount, {load_val == 'hFF;})
  19. wait_int_asserted();// wait interrupt signal high
  20. check_reg_ris_mis(1'b1, 1'b1);
  21. repeat(20) @(posedge vif.wdg_clk);
  22. fork
  23. `uvm_do(reg_dis_intr) // disable reg_dis_intr
  24. wait_int_released(); // wait interrupt signal released
  25. join
  26. check_reg_ris_mis(1'b1, 1'b0);
  27. #1us; // idle time monitoring count
  28. `uvm_info("body", "EXited...", UVM_LOW)
  29. endtask
  30. task check_reg_ris_mis(input ris, input mis);
  31. rgm.WDOGRIS.mirror(status);
  32. compare_data(ris, rgm.WDOGRIS.RAWINT.get());
  33. rgm.WDOGMIS.mirror(status);
  34. compare_data(mis, rgm.WDOGMIS.INT.get());
  35. endtask
  36. endclass
  37. `endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV

WDOGRIS是INT寄存器的原始状态(RAW status); WDOGMIS是INT寄存器与INTEN使能信号与之后的状态。虽然将ENABLE信号拉低了,但是原始状态仍然为高,这里需要区分清除。

【调试及结果】

image.png

在class中输入dis并设置断点

image.png
image.png

波形图如上,等到了INT信号拉高并进行比较,两次结果相等; 不清除INT信号直接将使能信号中断,计数功能停止。Raw状态(后台状态,没有被清除的状态下仍然为高),但是软件状态一侧读取到的值为低,也就是MIS status。


6.3 中断功能关闭再使能测试

【思考】 将INTEN信号拉低以后,INT在后台状态仍然是拉高的,只是被mask掉了,那么思考: 将INTEN信号再次拉高以后,INT信号是否立刻为高呢?为此再进行以下测试:

:::info 在apb_watchdog_disable_intr_virt_seq.sv添加拉高INTEN的语句 :::

  1. `ifndef APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
  2. `define APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV
  3. class apb_watchdog_disable_intr_virt_seq extends apb_watchdog_base_virt_seq;
  4. `uvm_object_utils(apb_watchdog_disable_intr_virt_seq)
  5. function new(string name = "apb_watchdog_disable_intr_virt_seq");
  6. super.new(name);
  7. endfunction
  8. virtual task body();
  9. super.body();
  10. `uvm_info("body","Entered...",UVM_LOW)
  11. // Enable apb_watchdog_reg and its interrupt generation
  12. `uvm_do(reg_en_intr)
  13. // Get load_val
  14. `uvm_do_with(reg_loadcount, {load_val == 'hFF;})
  15. wait_int_asserted();// wait interrupt signal high
  16. check_reg_ris_mis(1'b1, 1'b1);
  17. repeat(20) @(posedge vif.wdg_clk);
  18. fork
  19. `uvm_do(reg_dis_intr) // disable reg_dis_intr
  20. wait_int_released(); // wait interrupt signal released
  21. join
  22. check_reg_ris_mis(1'b1, 1'b0);
  23. // Enable interrupt signal again
  24. `uvm_do(reg_en_intr)
  25. // Check INT signal imediately
  26. compare_data(vif.wdog_int, 1'b1);
  27. check_reg_ris_mis(1'b1, 1'b1);
  28. #1us; // idle time monitoring count
  29. `uvm_info("body", "EXited...", UVM_LOW)
  30. endtask
  31. task check_reg_ris_mis(input ris, input mis);
  32. rgm.WDOGRIS.mirror(status);
  33. compare_data(ris, rgm.WDOGRIS.RAWINT.get());
  34. rgm.WDOGMIS.mirror(status);
  35. compare_data(mis, rgm.WDOGMIS.INT.get());
  36. endtask
  37. endclass
  38. `endif //APB_WATCHDOG_DISABLE_INTR_VIRT_SEQ_SV

image.png

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