| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| class chip_sw_sysrst_ctrl_ec_rst_l_vseq extends chip_sw_base_vseq; |
| `uvm_object_utils(chip_sw_sysrst_ctrl_ec_rst_l_vseq) |
| |
| `uvm_object_new |
| |
| localparam time AON_CYCLE_PERIOD = 5us; |
| localparam bit [1:0] OUTPUT_ALL_SET = 2'b11; |
| localparam bit [1:0] OUTPUT_NONE_SET = 2'b00; |
| localparam uint TIMEOUT_VALUE = 5000000; |
| localparam int EC_RST_TIMER = 512; |
| |
| localparam string PWRMGR_RSTREQ_PATH = "tb.dut.top_earlgrey.u_pwrmgr_aon.rstreqs_i[0]"; |
| localparam string RST_AON_NI_PATH = "tb.dut.top_earlgrey.u_sysrst_ctrl_aon.rst_aon_ni"; |
| |
| typedef enum { |
| PhaseSetup = 0, |
| PhaseCheckComboReset = 1, |
| PhaseOverrideSetup = 2, |
| PhaseOverrideZeros = 3, |
| PhaseOverrideOnes = 4, |
| PhaseDone = 5 |
| } test_phases_e; |
| |
| logic [1:0] output_pad_read_values; |
| logic output_ec_rst_read_values; |
| logic ec_rst_timer_over; |
| |
| virtual task pre_start(); |
| super.pre_start(); |
| // Initialize the pad input to 0 to avoid having X values in the initial test phase. |
| cfg.chip_vif.sysrst_ctrl_if.pins_pd[SysrstCtrlPadKey0] = 1; |
| cfg.chip_vif.sysrst_ctrl_if.pins_pd[SysrstCtrlPadKey1] = 1; |
| cfg.chip_vif.sysrst_ctrl_if.pins_pd[SysrstCtrlPadKey2] = 1; |
| cfg.chip_vif.pwrb_in_if.pins_pd[0] = 1; |
| endtask |
| |
| virtual function void write_test_phase(input test_phases_e phase); |
| sw_symbol_backdoor_overwrite("kTestPhase", {<<8{phase}}); |
| endfunction |
| |
| virtual task set_combo0_pads_low(); |
| cfg.chip_vif.sysrst_ctrl_if.drive_pin(SysrstCtrlPadKey0, 0); |
| cfg.chip_vif.sysrst_ctrl_if.drive_pin(SysrstCtrlPadKey1, 0); |
| endtask |
| |
| virtual task set_combo0_pads_high(); |
| cfg.chip_vif.sysrst_ctrl_if.drive_pin(SysrstCtrlPadKey0, 1); |
| cfg.chip_vif.sysrst_ctrl_if.drive_pin(SysrstCtrlPadKey1, 1); |
| endtask |
| |
| virtual task check_ec_rst_pads(bit exp_ec_rst_l); |
| #(3 * AON_CYCLE_PERIOD); |
| `DV_CHECK_EQ_FATAL(cfg.chip_vif.ec_rst_l_if.sample_pin(0), exp_ec_rst_l) |
| endtask |
| |
| virtual task check_output_pads(bit exp_ec_rst_l, bit exp_flash_wp_l); |
| #(3 * AON_CYCLE_PERIOD); |
| `DV_CHECK_EQ_FATAL(cfg.chip_vif.ec_rst_l_if.sample_pin(0), exp_ec_rst_l) |
| `DV_CHECK_EQ_FATAL(cfg.chip_vif.flash_wp_l_if.sample_pin(0), exp_flash_wp_l) |
| endtask |
| |
| virtual task sync_with_sw(); |
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInWfi) |
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest) |
| endtask |
| |
| virtual task control_ec_rst_low(int min_exp_cycles); |
| int timeout_count = 0; |
| `DV_WAIT(cfg.chip_vif.ec_rst_l_if.pins[0] === 0) |
| // wait until ec_rst is de-active and check the length. |
| `DV_SPINWAIT( |
| forever begin |
| if (cfg.chip_vif.ec_rst_l_if.sample_pin(0) == 0) begin |
| timeout_count++; |
| if (timeout_count >= EC_RST_TIMER) begin |
| ec_rst_timer_over = 1; // set this for the other thread to continue |
| end |
| end else begin |
| break; |
| end |
| // Some amount of delay between samples of ec_rst. |
| #(AON_CYCLE_PERIOD); |
| end) |
| `DV_CHECK(timeout_count > min_exp_cycles) // check ec_rst length |
| endtask |
| |
| virtual task check_ec_rst_with_transition(string path, int exp_value); |
| bit retval = 0; |
| int timeout_count = 0; |
| forever begin |
| `DV_CHECK(uvm_hdl_read(path, retval)); |
| if (retval == exp_value) begin |
| timeout_count++; |
| if (timeout_count >= TIMEOUT_VALUE) begin |
| `uvm_error(`gfn, $sformatf("Timed out waiting for %0s to go to %d \n", |
| path, exp_value)) |
| end |
| end else begin |
| break; |
| end |
| cfg.clk_rst_vif.wait_clks(1); |
| end |
| // Check that ec_rst is low. |
| cfg.clk_rst_vif.wait_clks(1); |
| if (cfg.chip_vif.ec_rst_l_if.sample_pin(0) == 1) begin |
| `uvm_error(`gfn, "Unexpected ec_rst high after reset request.") |
| end |
| endtask |
| |
| virtual task body(); |
| super.body(); |
| |
| // TODO(lowRISC/opentitan:#13373): Revisit pad assignments. |
| // pinmux_wkup_vif (at Iob7) is re-used for PinZ3WakeupOut |
| // due to lack of unused pins. Disable the default drive |
| // to this pin. |
| cfg.chip_vif.pinmux_wkup_if.drive_en_pin(0, 0); |
| set_combo0_pads_high(); |
| |
| // At this point WP_L and EC_RST_L have not been released yet after reset. |
| `DV_CHECK_EQ(cfg.chip_vif.flash_wp_l_if.pins, 0) |
| `DV_CHECK_EQ(cfg.chip_vif.ec_rst_l_if.pins, 0) |
| |
| write_test_phase(PhaseSetup); |
| |
| // The sysrst_ctrl initialization in PhaseSetup releases |
| // both flash_wp and ec_rst. Wait for them to go high here. |
| fork |
| `DV_WAIT(cfg.chip_vif.flash_wp_l_if.pins, |
| "Timed out waiting for flash_wp to go high.", |
| TIMEOUT_VALUE /* ns */) |
| `DV_WAIT(cfg.chip_vif.ec_rst_l_if.pins, |
| "Timed out waiting for ec_rst to go high.", |
| TIMEOUT_VALUE /* ns */) |
| join |
| |
| // Make sure software is waiting for a reset. |
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInWfi) |
| set_combo0_pads_low(); |
| ec_rst_timer_over = 0; |
| |
| fork |
| begin |
| control_ec_rst_low(EC_RST_TIMER); |
| end |
| begin |
| check_ec_rst_with_transition(PWRMGR_RSTREQ_PATH, 1'b0); |
| check_ec_rst_with_transition(RST_AON_NI_PATH , 1'b0); |
| sync_with_sw(); |
| write_test_phase(PhaseCheckComboReset); |
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest) |
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInWfi) |
| `DV_WAIT(ec_rst_timer_over) |
| |
| write_test_phase(PhaseOverrideSetup); |
| sync_with_sw(); |
| check_ec_rst_pads(1'b0); |
| |
| write_test_phase(PhaseOverrideZeros); |
| sync_with_sw(); |
| check_output_pads(1'b0, 1'b0); |
| |
| write_test_phase(PhaseOverrideOnes); |
| sync_with_sw(); |
| check_output_pads(1'b1, 1'b1); |
| |
| write_test_phase(PhaseDone); |
| end |
| join |
| endtask |
| endclass |