[rbox] Added the design files
Signed-off-by: Eric Shiu <eshiu@google.com>
diff --git a/hw/ip/rbox/rtl/rbox.sv b/hw/ip/rbox/rtl/rbox.sv
index cada269..d0ab6f8 100644
--- a/hw/ip/rbox/rtl/rbox.sv
+++ b/hw/ip/rbox/rtl/rbox.sv
@@ -45,8 +45,10 @@
rbox_hw2reg_t hw2reg;
logic pwrb_int, key0_int, key1_int, key2_int, ac_present_int;
- logic pwrb_out_hw, key0_out_hw, key1_out_hw, key2_out_hw, ec_rst_l_hw;
+ logic pwrb_out_hw, key0_out_hw, key1_out_hw, key2_out_hw, ec_rst_l_hw, bat_disable_hw;
logic pwrb_out_int, key0_out_int, key1_out_int, key2_out_int, bat_disable_int;
+ logic rbox_combo_intr, rbox_key_intr;
+ logic nc_intg_err_o;//FIXME
//Always-on pins
assign cio_ec_rst_l_en_o = 1'b1;
@@ -64,6 +66,7 @@
.tl_o(tl_o),
.reg2hw(reg2hw),
.hw2reg(hw2reg),
+ .intg_err_o(nc_intg_err_o),
.devmode_i (1'b1)
);
@@ -77,6 +80,8 @@
.key0_int(key0_int),
.key1_int(key1_int),
.key2_int(key2_int),
+ .auto_block_debounce_ctl_i(reg2hw.auto_block_debounce_ctl),
+ .auto_block_out_ctl_i(reg2hw.auto_block_out_ctl),
.pwrb_out_hw(pwrb_out_hw),
.key0_out_hw(key0_out_hw),
.key1_out_hw(key1_out_hw),
@@ -97,6 +102,7 @@
.key1_out_int(key1_out_int),
.key2_out_int(key2_out_int),
.bat_disable_int(bat_disable_int),
+ .key_invert_ctl_i(reg2hw.key_invert_ctl),
.pwrb_int(pwrb_int),
.key0_int(key0_int),
.key1_int(key1_int),
@@ -127,6 +133,10 @@
.key2_out_hw(key2_out_hw),
.bat_disable_hw(bat_disable_hw),
.ec_rst_l_hw(ec_rst_l_hw),
+ .pin_allowed_ctl_i(reg2hw.pin_allowed_ctl),
+ .pin_out_ctl_i(reg2hw.pin_out_ctl),
+ .pin_out_value_i(reg2hw.pin_out_value),
+ .pin_in_value_o(hw2reg.pin_in_value),
.pwrb_out_int(pwrb_out_int),
.key0_out_int(key0_out_int),
.key1_out_int(key1_out_int),
@@ -146,7 +156,11 @@
.key1_int(key1_int),
.key2_int(key2_int),
.ac_present_int(ac_present_int),
- .cio_ec_rst_l_i(cio_ec_rst_l_i)
+ .cio_ec_rst_l_i(cio_ec_rst_l_i),
+ .key_intr_ctl_i(reg2hw.key_intr_ctl),
+ .key_intr_debounce_ctl_i(reg2hw.key_intr_debounce_ctl),
+ .key_intr_status_o(hw2reg.key_intr_status),
+ .rbox_key_intr(rbox_key_intr)
);
//Instantiate combo module
@@ -155,12 +169,19 @@
.rst_ni(rst_ni),
.clk_aon_i(clk_aon_i),
.rst_slow_ni(rst_slow_ni),
- .pwrb_int(pwr_int),
+ .pwrb_int(pwrb_int),
.key0_int(key0_int),
.key1_int(key1_int),
.key2_int(key2_int),
.ac_present_int(ac_present_int),
.cio_ec_rst_l_i(cio_ec_rst_l_i),
+ .ec_rst_ctl_i(reg2hw.ec_rst_ctl),
+ .key_intr_debounce_ctl_i(reg2hw.key_intr_debounce_ctl),
+ .com_sel_ctl_i(reg2hw.com_sel_ctl),
+ .com_det_ctl_i(reg2hw.com_det_ctl),
+ .com_out_ctl_i(reg2hw.com_out_ctl),
+ .combo_intr_status_o(hw2reg.combo_intr_status),
+ .rbox_combo_intr(rbox_combo_intr),
.bat_disable_hw(bat_disable_hw),
.gsc_rst_o(gsc_rst_o),
.ec_rst_l_hw(ec_rst_l_hw)
@@ -170,8 +191,25 @@
rbox_intr i_intr (
.clk_i(clk_i),
.rst_ni(rst_ni),
+ .rbox_combo_intr(rbox_combo_intr),
+ .rbox_key_intr(rbox_key_intr),
+ .intr_state_i(reg2hw.intr_state),
+ .intr_enable_i(reg2hw.intr_enable),
+ .intr_test_i(reg2hw.intr_test),
+ .intr_state_o(hw2reg.intr_state),
.rbox_intr_o(rbox_intr_o)
);
+ // All outputs should be known value after reset
+ `ASSERT_KNOWN(IntrRboxOKnown, rbox_intr_o)
+ `ASSERT_KNOWN(GSCRstOKnown, gsc_rst_l_o)
+ `ASSERT_KNOWN(TlODValidKnown, tl_o.d_valid)
+ `ASSERT_KNOWN(TlOAReadyKnown, tl_o.a_ready)
+ `ASSERT_KNOWN(BatOKnown, cio_bat_disable_o)
+ `ASSERT_KNOWN(ECRSTOKnown, cio_ec_rst_l_o)
+ `ASSERT_KNOWN(PwrbOKnown, cio_pwrb_out_o)
+ `ASSERT_KNOWN(Key0OKnown, cio_key0_out_o)
+ `ASSERT_KNOWN(Key1OKnown, cio_key1_out_o)
+ `ASSERT_KNOWN(Key2OKnown, cio_key2_out_o)
endmodule
diff --git a/hw/ip/rbox/rtl/rbox_autoblock.sv b/hw/ip/rbox/rtl/rbox_autoblock.sv
new file mode 100644
index 0000000..87f94c3
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_autoblock.sv
@@ -0,0 +1,166 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description RBOX PWRB autoblock module
+
+module rbox_autoblock import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input clk_i,
+ input rst_ni,
+
+ input pwrb_int,
+ input key0_int,
+ input key1_int,
+ input key2_int,
+
+ input rbox_reg2hw_auto_block_debounce_ctl_reg_t auto_block_debounce_ctl_i,
+ input rbox_reg2hw_auto_block_out_ctl_reg_t auto_block_out_ctl_i,
+
+ output pwrb_out_hw,
+ output key0_out_hw,
+ output key1_out_hw,
+ output key2_out_hw
+
+);
+
+ logic cfg_auto_block_en;
+ logic load_auto_block_timer;
+ logic [15:0] cfg_auto_block_timer;
+ logic [15:0] cfg_auto_block_timer_d;
+ logic cfg_key0_o_sel;
+ logic cfg_key1_o_sel;
+ logic cfg_key2_o_sel;
+ logic cfg_key0_o_q;
+ logic cfg_key1_o_q;
+ logic cfg_key2_o_q;
+
+ logic ab_cond_met;
+ logic pwrb_int_i;
+
+ //nc_ means no connect
+ logic nc_auto_block_enable;
+
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_auto_block_en (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_debounce_ctl_i.auto_block_enable.q),
+ .q_o(cfg_auto_block_en)
+ );
+
+ assign nc_auto_block_enable = auto_block_debounce_ctl_i.auto_block_enable.qe;
+
+ prim_fifo_async #(
+ .Width(16),
+ .Depth(2)
+ ) i_cfg_auto_block_timer (
+ .clk_wr_i (clk_i),
+ .rst_wr_ni (rst_ni),
+ .wvalid_i (auto_block_debounce_ctl_i.debounce_timer.qe),
+ .wready_o (),
+ .wdata_i (auto_block_debounce_ctl_i.debounce_timer.q),
+ .wdepth_o (),
+
+ .clk_rd_i (clk_aon_i),
+ .rst_rd_ni (rst_slow_ni),
+ .rvalid_o (load_auto_block_timer),
+ .rready_i (1'b1),
+ .rdata_o (cfg_auto_block_timer_d),
+ .rdepth_o ()
+ );
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_cfg_auto_block_timer_reg
+ if (!rst_slow_ni) begin
+ cfg_auto_block_timer <= '0;
+ end else if (load_auto_block_timer) begin
+ cfg_auto_block_timer <= cfg_auto_block_timer_d;
+ end
+ end
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_o_sel (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key0_out_sel.q),
+ .q_o(cfg_key0_o_sel)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_o_sel (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key1_out_sel.q),
+ .q_o(cfg_key1_o_sel)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_o_sel (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key2_out_sel.q),
+ .q_o(cfg_key2_o_sel)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_o_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key0_out_value.q),
+ .q_o(cfg_key0_o_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_o_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key1_out_value.q),
+ .q_o(cfg_key1_o_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_o_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(auto_block_out_ctl_i.key2_out_value.q),
+ .q_o(cfg_key2_o_q)
+ );
+
+ //synchronize between GPIO and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_pwrb_in_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pwrb_int),
+ .q_o(pwrb_int_i)
+ );
+
+ rbox_timerfsm # (
+ .TIMERBIT(16)
+ ) i_ab_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(pwrb_int_i),
+ .cfg_timer_i(cfg_auto_block_timer),
+ .cfg_l2h_en_i(1'b0),
+ .cfg_h2l_en_i(cfg_auto_block_en),
+ .timer_l2h_cond_met(),
+ .timer_h2l_cond_met(ab_cond_met)
+ );
+
+ assign pwrb_out_hw = pwrb_int;
+ assign key0_out_hw = (ab_cond_met & cfg_key0_o_sel) ? cfg_key0_o_q : key0_int;
+ assign key1_out_hw = (ab_cond_met & cfg_key1_o_sel) ? cfg_key1_o_q : key1_int;
+ assign key2_out_hw = (ab_cond_met & cfg_key2_o_sel) ? cfg_key2_o_q : key2_int;
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_combo.sv b/hw/ip/rbox/rtl/rbox_combo.sv
new file mode 100644
index 0000000..f2fd25d
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_combo.sv
@@ -0,0 +1,392 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX combo Module
+//
+module rbox_combo import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input clk_i,
+ input rst_ni,
+
+ input pwrb_int,
+ input key0_int,
+ input key1_int,
+ input key2_int,
+ input ac_present_int,
+ input cio_ec_rst_l_i,
+
+ input rbox_reg2hw_ec_rst_ctl_reg_t ec_rst_ctl_i,
+ input rbox_reg2hw_key_intr_debounce_ctl_reg_t key_intr_debounce_ctl_i,
+ input rbox_reg2hw_com_sel_ctl_mreg_t [NumCombo-1:0] com_sel_ctl_i,
+ input rbox_reg2hw_com_det_ctl_mreg_t [NumCombo-1:0] com_det_ctl_i,
+ input rbox_reg2hw_com_out_ctl_mreg_t [NumCombo-1:0] com_out_ctl_i,
+
+ output rbox_hw2reg_combo_intr_status_reg_t combo_intr_status_o,
+ output rbox_combo_intr,
+
+ output bat_disable_hw,
+ output gsc_rst_o,
+ output ec_rst_l_hw
+);
+
+ //There are four possible combos
+ //Each key combo can select different triggers
+ logic [NumCombo-1:0] cfg_key0_in_sel_com;
+ logic [NumCombo-1:0] cfg_key1_in_sel_com;
+ logic [NumCombo-1:0] cfg_key2_in_sel_com;
+ logic [NumCombo-1:0] cfg_pwrb_in_sel_com;
+ logic [NumCombo-1:0] cfg_ac_present_sel_com;
+
+ logic [31:0] cfg_combo_timer [NumCombo];
+ logic [15:0] cfg_debounce_timer;
+
+ logic [NumCombo-1:0] load_combo_timer;
+ logic load_debounce_timer;
+
+ logic [31:0] cfg_combo_timer_d [NumCombo];
+ logic [15:0] cfg_debounce_timer_d;
+
+ logic [NumCombo-1:0] cfg_bat_disable_com;
+ logic [NumCombo-1:0] cfg_intr_com;
+ logic [NumCombo-1:0] cfg_ec_rst_com;
+ logic [NumCombo-1:0] cfg_gsc_rst_com;
+
+ logic pwrb_int_i;
+ logic key0_int_i, key1_int_i, key2_int_i;
+ logic ac_present_int_i;
+
+ logic [NumCombo-1:0] trigger_h;
+ logic [NumCombo-1:0] trigger_l;
+ logic [NumCombo-1:0] cfg_combo_en;
+ logic [NumCombo-1:0] combo_det;
+
+ logic [NumCombo-1:0] combo_bat_disable;
+ logic [NumCombo-1:0] combo_intr_pulse;
+ logic [NumCombo-1:0] combo_ec_rst_l;
+ logic [NumCombo-1:0] combo_gsc_rst;
+
+ logic ec_rst_l_int_i;
+
+ logic combo0_h2l_intr, combo1_h2l_intr, combo2_h2l_intr, combo3_h2l_intr;
+
+ //synchronize between GPIO and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_ec_rst_l_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(cio_ec_rst_l_i),
+ .q_o(ec_rst_l_int_i)
+ );
+
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_com_sel
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_sel_key0 (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_sel_ctl_i[k].key0_in_sel.q),
+ .q_o(cfg_key0_in_sel_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_sel_key1 (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_sel_ctl_i[k].key1_in_sel.q),
+ .q_o(cfg_key1_in_sel_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_sel_key2 (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_sel_ctl_i[k].key2_in_sel.q),
+ .q_o(cfg_key2_in_sel_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_sel_pwrb (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_sel_ctl_i[k].pwrb_in_sel.q),
+ .q_o(cfg_pwrb_in_sel_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_sel_ac_present (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_sel_ctl_i[k].ac_present_sel.q),
+ .q_o(cfg_ac_present_sel_com[k])
+ );
+ end
+
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_com_det
+ prim_fifo_async #(
+ .Width(32),
+ .Depth(2)
+ ) i_cfg_combo_timer (
+ .clk_wr_i (clk_i),
+ .rst_wr_ni (rst_ni),
+ .wvalid_i (com_det_ctl_i[k].qe),
+ .wready_o (),
+ .wdata_i (com_det_ctl_i[k].q),
+ .wdepth_o (),
+
+ .clk_rd_i (clk_aon_i),
+ .rst_rd_ni (rst_slow_ni),
+ .rvalid_o (load_combo_timer[k]),
+ .rready_i (1'b1),
+ .rdata_o (cfg_combo_timer_d[k]),
+ .rdepth_o ()
+ );
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_cfg_combo_timer_reg
+ if (!rst_slow_ni) begin
+ cfg_combo_timer[k] <= '0;
+ end else if (load_combo_timer[k]) begin
+ cfg_combo_timer[k] <= cfg_combo_timer_d[k];
+ end
+ end
+ end
+
+ prim_fifo_async #(
+ .Width(16),
+ .Depth(2)
+ ) i_cfg_debounce_timer (
+ .clk_wr_i (clk_i),
+ .rst_wr_ni (rst_ni),
+ .wvalid_i (key_intr_debounce_ctl_i.qe),
+ .wready_o (),
+ .wdata_i (key_intr_debounce_ctl_i.q),
+ .wdepth_o (),
+
+ .clk_rd_i (clk_aon_i),
+ .rst_rd_ni (rst_slow_ni),
+ .rvalid_o (load_debounce_timer),
+ .rready_i (1'b1),
+ .rdata_o (cfg_debounce_timer_d),
+ .rdepth_o ()
+ );
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_cfg_debounce_timer_reg
+ if (!rst_slow_ni) begin
+ cfg_debounce_timer <= '0;
+ end else if (load_debounce_timer) begin
+ cfg_debounce_timer <= cfg_debounce_timer_d;
+ end
+ end
+
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_com_out
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_bat_disable (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_out_ctl_i[k].bat_disable.q),
+ .q_o(cfg_bat_disable_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_intr (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_out_ctl_i[k].interrupt.q),
+ .q_o(cfg_intr_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_ec_rst (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_out_ctl_i[k].ec_rst.q),
+ .q_o(cfg_ec_rst_com[k])
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_com_gsc_rst (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(com_out_ctl_i[k].gsc_rst.q),
+ .q_o(cfg_gsc_rst_com[k])
+ );
+ end
+
+ //synchronize between GPIO and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_pwrb_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pwrb_int),
+ .q_o(pwrb_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key0_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key0_int),
+ .q_o(key0_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key1_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key1_int),
+ .q_o(key1_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key2_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key2_int),
+ .q_o(key2_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_ac_present_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(ac_present_int),
+ .q_o(ac_present_int_i)
+ );
+
+ //generate the trigger for each combo
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_combo_trigger
+ rbox_combotrg i_combo_trg (
+ .cfg_in0_sel(cfg_pwrb_in_sel_com[k]),
+ .cfg_in1_sel(cfg_key0_in_sel_com[k]),
+ .cfg_in2_sel(cfg_key1_in_sel_com[k]),
+ .cfg_in3_sel(cfg_key2_in_sel_com[k]),
+ .cfg_in4_sel(cfg_ac_present_sel_com[k]),
+ .in0(pwrb_int_i),
+ .in1(key0_int_i),
+ .in2(key1_int_i),
+ .in3(key2_int_i),
+ .in4(ac_present_int_i),
+ .trigger_h_o(trigger_h[k]),
+ .trigger_l_o(trigger_l[k])
+ );
+ assign cfg_combo_en[k] = cfg_pwrb_in_sel_com[k] | cfg_key0_in_sel_com[k] |
+ cfg_key1_in_sel_com[k] | cfg_key2_in_sel_com[k] |
+ cfg_ac_present_sel_com[k];
+ end
+
+ //Instantiate the combo detection state machine
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_combofsm
+ rbox_combofsm # (
+ .TIMER1BIT(16),
+ .TIMER2BIT(32)
+ ) i_combo_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_h_i(trigger_h[k]),
+ .trigger_l_i(trigger_l[k]),
+ .cfg_timer1_i(cfg_debounce_timer),
+ .cfg_timer2_i(cfg_combo_timer[k]),
+ .cfg_h2l_en_i(cfg_combo_en[k]),
+ .timer_h2l_cond_met(combo_det[k])
+ );
+ end
+
+ //Instantiate the combo action module
+ for (genvar k = 0 ; k < NumCombo ; k++) begin : gen_combo_act
+ rbox_comboact i_combo_act (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .cfg_intr_en(cfg_intr_com[k]),
+ .cfg_bat_disable_en(cfg_bat_disable_com[k]),
+ .cfg_ec_rst_en(cfg_ec_rst_com[k]),
+ .cfg_gsc_rst_en(cfg_gsc_rst_com[k]),
+ .combo_det(combo_det[k]),
+ .ec_rst_l_i(ec_rst_l_int_i),
+ .ec_rst_ctl_i(ec_rst_ctl_i),
+ .combo_intr_pulse(combo_intr_pulse[k]),
+ .bat_disable_o(combo_bat_disable[k]),
+ .gsc_rst_o(combo_gsc_rst[k]),
+ .ec_rst_l_o(combo_ec_rst_l[k])
+ );
+ end
+
+ //bat_disable
+ //If any combo triggers bat_disable, assert the signal
+ assign bat_disable_hw = |(combo_bat_disable);
+
+ //If any combo triggers GSC or EC RST(active low), assert the signal
+ assign gsc_rst_o = |(combo_gsc_rst);
+ assign ec_rst_l_hw = &(combo_ec_rst_l);
+
+ //Synchronize from 200KHz always-onclock to 24MHz cfg clock
+ prim_pulse_sync i_combo0_intr (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (combo_intr_pulse[0]),
+ .dst_pulse_o (combo0_h2l_intr)
+ );
+
+ assign combo_intr_status_o.combo0_h2l.de = combo0_h2l_intr;
+
+ prim_pulse_sync i_combo1_intr (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (combo_intr_pulse[1]),
+ .dst_pulse_o (combo1_h2l_intr)
+ );
+
+ assign combo_intr_status_o.combo1_h2l.de = combo1_h2l_intr;
+
+ prim_pulse_sync i_combo2_intr (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (combo_intr_pulse[2]),
+ .dst_pulse_o (combo2_h2l_intr)
+ );
+
+ assign combo_intr_status_o.combo2_h2l.de = combo2_h2l_intr;
+
+ prim_pulse_sync i_combo3_intr (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (combo_intr_pulse[3]),
+ .dst_pulse_o (combo3_h2l_intr)
+ );
+
+ assign combo_intr_status_o.combo3_h2l.de = combo3_h2l_intr;
+
+ assign rbox_combo_intr = combo0_h2l_intr | combo1_h2l_intr | combo2_h2l_intr | combo3_h2l_intr;
+
+ //To write into interrupt status register
+ assign combo_intr_status_o.combo0_h2l.d = 1'b1;
+ assign combo_intr_status_o.combo1_h2l.d = 1'b1;
+ assign combo_intr_status_o.combo2_h2l.d = 1'b1;
+ assign combo_intr_status_o.combo3_h2l.d = 1'b1;
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_comboact.sv b/hw/ip/rbox/rtl/rbox_comboact.sv
new file mode 100644
index 0000000..930c2db
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_comboact.sv
@@ -0,0 +1,162 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX combo action Module
+//
+module rbox_comboact import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input clk_i,
+ input rst_ni,
+
+ input cfg_intr_en,
+ input cfg_bat_disable_en,
+ input cfg_ec_rst_en,
+ input cfg_gsc_rst_en,
+ input combo_det,
+ input ec_rst_l_i,
+
+ input rbox_reg2hw_ec_rst_ctl_reg_t ec_rst_ctl_i,
+
+ output combo_intr_pulse,
+ output bat_disable_o,
+ output gsc_rst_o,
+ output ec_rst_l_o
+);
+
+ logic [15:0] cfg_ec_rst_timer;
+ logic load_ec_rst_timer;
+ logic [15:0] cfg_ec_rst_timer_d;
+
+ logic combo_det_q;
+ logic combo_gsc_pulse;
+ logic combo_bat_disable_pulse;
+ logic bat_disable_q, bat_disable_d;
+ logic gsc_rst_q, gsc_rst_d;
+ logic combo_ec_rst_pulse;
+ logic ec_rst_l_q, ec_rst_l_d;
+
+ logic [15:0] timer_cnt_d, timer_cnt_q;
+ logic timer_cnt_clr, timer_cnt_en;
+
+ logic ec_rst_l_int, ec_rst_l_det;
+
+ //delay the level signal to generate a pulse
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_combo_det
+ if (!rst_slow_ni) begin
+ combo_det_q <= 1'b0;
+ end else begin
+ combo_det_q <= combo_det;
+ end
+ end
+
+ //bat_disable logic
+ assign combo_bat_disable_pulse = cfg_bat_disable_en && (combo_det_q == 1'b0) &&
+ (combo_det == 1'b1);
+
+ assign bat_disable_d = combo_bat_disable_pulse ? 1'b1 : bat_disable_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_combo_bat_disable
+ if (!rst_slow_ni) begin
+ bat_disable_q <= 1'b0;
+ end else begin
+ bat_disable_q <= bat_disable_d;
+ end
+ end
+
+ assign bat_disable_o = bat_disable_q;
+
+ //Interrupt logic
+ assign combo_intr_pulse = cfg_intr_en && (combo_det_q == 1'b0) && (combo_det == 1'b1);
+
+ //ec_rst_logic
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ prim_fifo_async #(
+ .Width(16),
+ .Depth(2)
+ ) i_cfg_ec_rst_pulse (
+ .clk_wr_i (clk_i),
+ .rst_wr_ni (rst_ni),
+ .wvalid_i (ec_rst_ctl_i.qe),
+ .wready_o (),
+ .wdata_i (ec_rst_ctl_i.q),
+ .wdepth_o (),
+
+ .clk_rd_i (clk_aon_i),
+ .rst_rd_ni (rst_slow_ni),
+ .rvalid_o (load_ec_rst_timer),
+ .rready_i (1'b1),
+ .rdata_o (cfg_ec_rst_timer_d),
+ .rdepth_o ()
+ );
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_cfg_ec_rst_timer_reg
+ if (!rst_slow_ni) begin
+ cfg_ec_rst_timer <= '0;
+ end else if (load_ec_rst_timer) begin
+ cfg_ec_rst_timer <= cfg_ec_rst_timer_d;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_ec_rst_l_int
+ if (!rst_slow_ni) begin
+ ec_rst_l_int <= 1'b1;//active low signal
+ end else begin
+ ec_rst_l_int <= ec_rst_l_i;
+ end
+ end
+
+ //ec_rst_l_i high->low detection
+ assign ec_rst_l_det = (ec_rst_l_int == 1'b1) && (ec_rst_l_i == 1'b0);
+
+ //combo with EC RST CFG enable
+ assign combo_ec_rst_pulse = cfg_ec_rst_en && (combo_det_q == 1'b0) && (combo_det == 1'b1);
+
+ //GSC reset will also reset EC
+ assign ec_rst_l_d = (combo_ec_rst_pulse | combo_gsc_pulse | ec_rst_l_det) ? 1'b0 :
+ timer_cnt_clr ? 1'b1 : ec_rst_l_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_combo_ec_rst_l
+ if (!rst_slow_ni) begin
+ ec_rst_l_q <= 1'b0;//asserted when power-on-reset is asserted
+ end else begin
+ ec_rst_l_q <= ec_rst_l_d;
+ end
+ end
+
+ assign timer_cnt_en = (ec_rst_l_q == 1'b0);
+
+ assign timer_cnt_clr = (ec_rst_l_q == 1'b0) && (timer_cnt_q == cfg_ec_rst_timer);
+
+ assign timer_cnt_d = (timer_cnt_en) ? timer_cnt_q + 1'b1 : timer_cnt_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: timer_cnt_regs
+ if (!rst_slow_ni) begin
+ timer_cnt_q <= '0;
+ end
+ else if (timer_cnt_clr) begin
+ timer_cnt_q <= '0;
+ end else begin
+ timer_cnt_q <= timer_cnt_d;
+ end
+ end
+
+ assign ec_rst_l_o = ec_rst_l_q;
+
+ //gsc_rst_logic
+ assign combo_gsc_pulse = cfg_gsc_rst_en && (combo_det_q == 1'b0) && (combo_det == 1'b1);
+
+ assign gsc_rst_d = combo_gsc_pulse ? 1'b1 : gsc_rst_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_combo_gsc_rst
+ if (!rst_slow_ni) begin
+ gsc_rst_q <= 1'b0;
+ end else begin
+ gsc_rst_q <= gsc_rst_d;
+ end
+ end
+
+ assign gsc_rst_o = gsc_rst_q;
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_combofsm.sv b/hw/ip/rbox/rtl/rbox_combofsm.sv
new file mode 100644
index 0000000..67ed3d4
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_combofsm.sv
@@ -0,0 +1,157 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description RBOX combo detection FSM module
+
+module rbox_combofsm #(
+ parameter int unsigned TIMER1BIT = 16,
+ parameter int unsigned TIMER2BIT = 32
+ ) (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input trigger_h_i,//input vector is all "1"
+ input trigger_l_i,//input vector is all "0"
+ input [TIMER1BIT-1:0] cfg_timer1_i,//debounce
+ input [TIMER2BIT-1:0] cfg_timer2_i,//detection
+ input cfg_h2l_en_i,
+ output logic timer_h2l_cond_met
+
+);
+
+ logic trigger_h_q, trigger_l_q;
+ logic trigger_h2l, trigger_l2h, trigger_h2h, trigger_l2l;
+
+ logic [TIMER1BIT-1:0] timer1_cnt_d, timer1_cnt_q;
+ logic timer1_cnt_clr, timer1_cnt_en;
+ logic [TIMER2BIT-1:0] timer2_cnt_d, timer2_cnt_q;
+ logic timer2_cnt_clr, timer2_cnt_en;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_trigger_h_reg
+ if (!rst_slow_ni) begin
+ trigger_h_q <= 1'b0;
+ end else begin
+ trigger_h_q <= trigger_h_i;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_trigger_l_reg
+ if (!rst_slow_ni) begin
+ trigger_l_q <= 1'b0;
+ end else begin
+ trigger_l_q <= trigger_l_i;
+ end
+ end
+
+ assign trigger_h2l = (trigger_h_q == 1'b1) && (trigger_l_i == 1'b1);
+ assign trigger_l2h = (trigger_l_q == 1'b1) && (trigger_h_i == 1'b1);
+ assign trigger_h2h = (trigger_h_q == 1'b1) && (trigger_h_i == 1'b1);
+ assign trigger_l2l = (trigger_l_q == 1'b1) && (trigger_l_i == 1'b1);
+
+ //Four-state FSM
+ //IDLE->WAIT1->WAIT2->DONE
+ //FSM will detect a H2L transition to enter the wait1 state
+ //debounce timer defines the time for input to stablize
+ //FSM will check the input after the debounce period
+ //If the input stays at low, enter the wait2 state
+ //Detection timer defines the time for input to be held(pressed)
+ //FSM will enter the done state after the detection period
+ typedef enum logic [1:0] {
+ IDLE = 2'h0,
+ WAIT1 = 2'h1,
+ WAIT2 = 2'h2,
+ DONE = 2'h3
+ } timer_state_e;
+
+ timer_state_e timer_state_q, timer_state_d;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer_state_reg
+ if (!rst_slow_ni) begin
+ timer_state_q <= IDLE;
+ end else begin
+ timer_state_q <= timer_state_d;
+ end
+ end
+
+ assign timer1_cnt_d = (timer1_cnt_en) ? timer1_cnt_q + 1'b1 : timer1_cnt_q;
+ assign timer2_cnt_d = (timer2_cnt_en) ? timer2_cnt_q + 1'b1 : timer2_cnt_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer1_cnt_reg
+ if (!rst_slow_ni) begin
+ timer1_cnt_q <= '0;
+ end
+ else if (timer1_cnt_clr) begin
+ timer1_cnt_q <= '0;
+ end else begin
+ timer1_cnt_q <= timer1_cnt_d;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer2_cnt_reg
+ if (!rst_slow_ni) begin
+ timer2_cnt_q <= '0;
+ end
+ else if (timer2_cnt_clr) begin
+ timer2_cnt_q <= '0;
+ end else begin
+ timer2_cnt_q <= timer2_cnt_d;
+ end
+ end
+
+ always_comb begin: timer_fsm
+ timer_state_d = timer_state_q;
+ //outputs
+ timer_h2l_cond_met = 1'b0;
+ timer1_cnt_clr = 1'b0;
+ timer1_cnt_en = 1'b0;
+ timer2_cnt_clr = 1'b0;
+ timer2_cnt_en = 1'b0;
+
+ unique case (timer_state_q)
+ IDLE: begin
+ if (cfg_h2l_en_i && trigger_h2l) begin
+ timer_state_d = WAIT1;
+ end
+ end
+
+ WAIT1: begin
+ if (timer1_cnt_q != cfg_timer1_i) begin
+ timer1_cnt_en = 1'b1;
+ end
+ else if (!trigger_l2l && (timer1_cnt_q == cfg_timer1_i)) begin
+ timer_state_d = IDLE;
+ timer1_cnt_clr = 1'b1;
+ end
+ else if (trigger_l2l && (timer1_cnt_q == cfg_timer1_i)) begin
+ timer_state_d = WAIT2;
+ timer1_cnt_clr = 1'b1;
+ end
+ end
+
+ WAIT2: begin
+ if (timer2_cnt_q != cfg_timer2_i) begin
+ timer2_cnt_en = 1'b1;
+ end
+ else if (!trigger_l2l && (timer2_cnt_q == cfg_timer2_i)) begin
+ timer_state_d = IDLE;
+ timer2_cnt_clr = 1'b1;
+ end
+ else if (trigger_l2l && (timer2_cnt_q == cfg_timer2_i)) begin
+ timer_state_d = DONE;
+ timer2_cnt_clr = 1'b1;
+ end
+ end
+
+ DONE: begin
+ if (trigger_l2l) begin
+ timer_h2l_cond_met = 1'b1;
+ end
+ else if (trigger_l2h) begin
+ timer_state_d = IDLE;
+ end
+ end
+ default: timer_state_d = IDLE;
+ endcase
+ end
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_combotrg.sv b/hw/ip/rbox/rtl/rbox_combotrg.sv
new file mode 100644
index 0000000..20cb809
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_combotrg.sv
@@ -0,0 +1,158 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description RBOX combo trigger module
+
+module rbox_combotrg (
+ input cfg_in0_sel,
+ input cfg_in1_sel,
+ input cfg_in2_sel,
+ input cfg_in3_sel,
+ input cfg_in4_sel,
+ input in0,
+ input in1,
+ input in2,
+ input in3,
+ input in4,
+ output logic trigger_h_o,
+ output logic trigger_l_o
+);
+
+ logic [4:0] cfg_input_sel;
+
+ assign cfg_input_sel = {cfg_in0_sel, cfg_in1_sel, cfg_in2_sel, cfg_in3_sel, cfg_in4_sel};
+
+ always_comb begin: trigger_combo
+
+ unique case (cfg_input_sel)
+ 5'b00001: begin
+ trigger_h_o = (in4 == 1'b1);
+ trigger_l_o = (in4 == 1'b0);
+ end
+ 5'b00010: begin
+ trigger_h_o = (in3 == 1'b1);
+ trigger_l_o = (in3 == 1'b0);
+ end
+ 5'b00011: begin
+ trigger_h_o = (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b00100: begin
+ trigger_h_o = (in2 == 1'b1);
+ trigger_l_o = (in2 == 1'b0);
+ end
+ 5'b00101: begin
+ trigger_h_o = (in2 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in2 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b00111: begin
+ trigger_h_o = (in2 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in2 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b01000: begin
+ trigger_h_o = (in1 == 1'b1);
+ trigger_l_o = (in1 == 1'b0);
+ end
+ 5'b01001: begin
+ trigger_h_o = (in1 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b01010: begin
+ trigger_h_o = (in1 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b01011: begin
+ trigger_h_o = (in1 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b01100: begin
+ trigger_h_o = (in1 == 1'b1) && (in2 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in2 == 1'b0);
+ end
+ 5'b01101: begin
+ trigger_h_o = (in1 == 1'b1) && (in2 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in2 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b01110: begin
+ trigger_h_o = (in1 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b01111: begin
+ trigger_h_o = (in1 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in1 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b10000: begin
+ trigger_h_o = (in0 == 1'b1);
+ trigger_l_o = (in0 == 1'b0);
+ end
+ 5'b10001: begin
+ trigger_h_o = (in0 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b10010: begin
+ trigger_h_o = (in0 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b10011: begin
+ trigger_h_o = (in0 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b10100: begin
+ trigger_h_o = (in0 == 1'b1) && (in2 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in2 == 1'b0);
+ end
+ 5'b10101: begin
+ trigger_h_o = (in0 == 1'b1) && (in2 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in2 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b10110: begin
+ trigger_h_o = (in0 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b10111: begin
+ trigger_h_o = (in0 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b11000: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0);
+ end
+ 5'b11001: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b11010: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b11011: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in3 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in3 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b11100: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in2 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in2 == 1'b0);
+ end
+ 5'b11101: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in2 == 1'b1) && (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in2 == 1'b0) && (in4 == 1'b0);
+ end
+ 5'b11110: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0);
+ end
+ 5'b11111: begin
+ trigger_h_o = (in0 == 1'b1) && (in1 == 1'b1) && (in2 == 1'b1) && (in3 == 1'b1) &&
+ (in4 == 1'b1);
+ trigger_l_o = (in0 == 1'b0) && (in1 == 1'b0) && (in2 == 1'b0) && (in3 == 1'b0) &&
+ (in4 == 1'b0);
+ end
+ default: begin
+ trigger_h_o = 1'b0;
+ trigger_l_o = 1'b0;
+ end
+ endcase
+ end
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_intr.sv b/hw/ip/rbox/rtl/rbox_intr.sv
new file mode 100644
index 0000000..2355b30
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_intr.sv
@@ -0,0 +1,37 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX interrupt Module
+//
+module rbox_intr import rbox_reg_pkg::*; (
+ input clk_i,
+ input rst_ni,
+ input rbox_combo_intr,
+ input rbox_key_intr,
+ input rbox_reg2hw_intr_state_reg_t intr_state_i,
+ input rbox_reg2hw_intr_enable_reg_t intr_enable_i,
+ input rbox_reg2hw_intr_test_reg_t intr_test_i,
+ output rbox_hw2reg_intr_state_reg_t intr_state_o,
+ output rbox_intr_o
+);
+
+ logic rbox_event;
+
+ assign rbox_event = rbox_combo_intr | rbox_key_intr;
+
+ // instantiate interrupt hardware primitive
+ prim_intr_hw #(.Width(1)) i_rbox_intr_o (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .event_intr_i (rbox_event),
+ .reg2hw_intr_enable_q_i (intr_enable_i.q),
+ .reg2hw_intr_test_q_i (intr_test_i.q),
+ .reg2hw_intr_test_qe_i (intr_test_i.qe),
+ .reg2hw_intr_state_q_i (intr_state_i.q),
+ .hw2reg_intr_state_de_o (intr_state_o.de),
+ .hw2reg_intr_state_d_o (intr_state_o.d),
+ .intr_o (rbox_intr_o)
+ );
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_inv.sv b/hw/ip/rbox/rtl/rbox_inv.sv
new file mode 100644
index 0000000..cb63c6c
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_inv.sv
@@ -0,0 +1,154 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX pin inversion Module
+//
+
+module rbox_inv import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+
+ input cio_pwrb_in_i,
+ input cio_key0_in_i,
+ input cio_key1_in_i,
+ input cio_key2_in_i,
+ input cio_ac_present_i,
+
+ input pwrb_out_int,
+ input key0_out_int,
+ input key1_out_int,
+ input key2_out_int,
+ input bat_disable_int,
+
+ input rbox_reg2hw_key_invert_ctl_reg_t key_invert_ctl_i,
+
+ output pwrb_int,
+ output key0_int,
+ output key1_int,
+ output key2_int,
+ output ac_present_int,
+
+ output cio_bat_disable_o,
+ output cio_pwrb_out_o,
+ output cio_key0_out_o,
+ output cio_key1_out_o,
+ output cio_key2_out_o
+
+);
+
+ logic cfg_pwrb_i_inv;
+ logic cfg_key0_i_inv;
+ logic cfg_key1_i_inv;
+ logic cfg_key2_i_inv;
+ logic cfg_ac_present_i_inv;
+ logic cfg_pwrb_o_inv;
+ logic cfg_key0_o_inv;
+ logic cfg_key1_o_inv;
+ logic cfg_key2_o_inv;
+ logic cfg_bat_disable_o_inv;
+
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_pwrb_i_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.pwrb_in.q),
+ .q_o(cfg_pwrb_i_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_i_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key0_in.q),
+ .q_o(cfg_key0_i_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_i_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key1_in.q),
+ .q_o(cfg_key1_i_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_i_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key2_in.q),
+ .q_o(cfg_key2_i_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ac_present_i_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.ac_present.q),
+ .q_o(cfg_ac_present_i_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_pwrb_o_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.pwrb_out.q),
+ .q_o(cfg_pwrb_o_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_o_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key0_out.q),
+ .q_o(cfg_key0_o_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_o_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key1_out.q),
+ .q_o(cfg_key1_o_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_o_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.key2_out.q),
+ .q_o(cfg_key2_o_inv)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_bat_disable_o_inv (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_invert_ctl_i.bat_disable.q),
+ .q_o(cfg_bat_disable_o_inv)
+ );
+
+ assign cio_pwrb_out_o = cfg_pwrb_o_inv ? ~pwrb_out_int : pwrb_out_int;
+ assign cio_key0_out_o = cfg_key0_o_inv ? ~key0_out_int : key0_out_int;
+ assign cio_key1_out_o = cfg_key1_o_inv ? ~key1_out_int : key1_out_int;
+ assign cio_key2_out_o = cfg_key2_o_inv ? ~key2_out_int : key2_out_int;
+ assign cio_bat_disable_o = cfg_bat_disable_o_inv ? ~bat_disable_int : bat_disable_int;
+
+ assign pwrb_int = cfg_pwrb_i_inv ? ~cio_pwrb_in_i : cio_pwrb_in_i;
+ assign key0_int = cfg_key0_i_inv ? ~cio_key0_in_i : cio_key0_in_i;
+ assign key1_int = cfg_key1_i_inv ? ~cio_key1_in_i : cio_key1_in_i;
+ assign key2_int = cfg_key2_i_inv ? ~cio_key2_in_i : cio_key2_in_i;
+ assign ac_present_int = cfg_ac_present_i_inv ? ~cio_ac_present_i : cio_ac_present_i;
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_keyfsm.sv b/hw/ip/rbox/rtl/rbox_keyfsm.sv
new file mode 100644
index 0000000..0a41a96
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_keyfsm.sv
@@ -0,0 +1,155 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description RBOX key press and release FSM module
+
+module rbox_keyfsm #(
+ parameter int unsigned TIMERBIT = 16
+ ) (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input trigger_i,
+ input [TIMERBIT-1:0] cfg_timer_i,
+ input cfg_l2h_en_i,
+ input cfg_h2l_en_i,
+ output logic timer_l2h_cond_met,
+ output logic timer_h2l_cond_met
+
+);
+
+ logic trigger_q;
+ logic trigger_h2l, trigger_l2h, trigger_l2l, trigger_h2h;
+ logic trigger_tgl, trigger_sty;
+
+ logic [TIMERBIT-1:0] timer_cnt_d, timer_cnt_q;
+ logic timer_cnt_clr, timer_cnt_en;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_trigger_reg
+ if (!rst_slow_ni) begin
+ trigger_q <= 1'b0;
+ end else begin
+ trigger_q <= trigger_i;
+ end
+ end
+
+ assign trigger_h2l = (trigger_q == 1'b1) && (trigger_i == 1'b0);
+ assign trigger_l2h = (trigger_q == 1'b0) && (trigger_i == 1'b1);
+ assign trigger_l2l = (trigger_q == 1'b0) && (trigger_i == 1'b0);
+ assign trigger_h2h = (trigger_q == 1'b1) && (trigger_i == 1'b1);
+ assign trigger_tgl = trigger_q != trigger_i;
+ assign trigger_sty = trigger_q == trigger_i;
+
+ //five-state FSM
+ //IDLE->WAITH2L->DONEH2L->WAITL2H->DONEL2H or
+ //IDLE->WAITL2H->DONEL2H->WAITH2L->DONEH2L
+ //The inputs can be inverted, hence two possible paths
+ //When a key or button is pressed, the non-inverted input signal goes from high to low.
+ //When a key or button is released, the non-inverted input signal goes from low to high.
+ //FSM will be able to detect a key or button being pressed then
+ //releaseed in one complete path
+ typedef enum logic [2:0] {
+ IDLE = 3'h0,
+ WAITL2H = 3'h1,
+ WAITH2L = 3'h2,
+ DONEL2H = 3'h3,
+ DONEH2L = 3'h4
+ } timer_state_e;
+
+ timer_state_e timer_state_q, timer_state_d;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer_state_reg
+ if (!rst_slow_ni) begin
+ timer_state_q <= IDLE;
+ end else begin
+ timer_state_q <= timer_state_d;
+ end
+ end
+
+ assign timer_cnt_d = (timer_cnt_en) ? timer_cnt_q + 1'b1 : timer_cnt_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer_cnt_reg
+ if (!rst_slow_ni) begin
+ timer_cnt_q <= '0;
+ end
+ else if (timer_cnt_clr) begin
+ timer_cnt_q <= '0;
+ end else begin
+ timer_cnt_q <= timer_cnt_d;
+ end
+ end
+
+ always_comb begin: timer_fsm
+ timer_state_d = timer_state_q;
+ //outputs
+ timer_l2h_cond_met = 1'b0;
+ timer_h2l_cond_met = 1'b0;
+ timer_cnt_clr = 1'b0;
+ timer_cnt_en = 1'b0;
+
+ unique case (timer_state_q)
+ IDLE: begin
+ if (cfg_l2h_en_i && trigger_l2h) begin
+ timer_state_d = WAITL2H;
+ end
+ else if (cfg_h2l_en_i && trigger_h2l) begin
+ timer_state_d = WAITH2L;
+ end
+ end
+
+ WAITL2H: begin
+ if (timer_cnt_q != cfg_timer_i) begin
+ timer_cnt_en = 1'b1;
+ end
+ else if (!trigger_h2h && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = IDLE;
+ timer_cnt_clr = 1'b1;
+ end
+ else if (trigger_h2h && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = DONEL2H;
+ timer_cnt_clr = 1'b1;
+ end
+ end
+
+ DONEL2H: begin
+ if (trigger_h2h) begin
+ timer_l2h_cond_met = 1'b1;
+ end
+ else if (!cfg_h2l_en_i && trigger_h2l) begin
+ timer_state_d = IDLE;
+ end
+ else if (cfg_h2l_en_i && trigger_h2l) begin
+ timer_state_d = WAITH2L;
+ end
+ end
+
+ WAITH2L: begin
+ if (timer_cnt_q != cfg_timer_i) begin
+ timer_cnt_en = 1'b1;
+ end
+ else if (!trigger_l2l && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = IDLE;
+ timer_cnt_clr = 1'b1;
+ end
+ else if (trigger_l2l && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = DONEH2L;
+ timer_cnt_clr = 1'b1;
+ end
+ end
+
+ DONEH2L: begin
+ if (trigger_l2l) begin
+ timer_h2l_cond_met = 1'b1;
+ end
+ else if (!cfg_l2h_en_i && trigger_l2h) begin
+ timer_state_d = IDLE;
+ end
+ else if (cfg_l2h_en_i && trigger_l2h) begin
+ timer_state_d = WAITL2H;
+ end
+ end
+ default: timer_state_d = IDLE;
+ endcase
+ end
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_keyintr.sv b/hw/ip/rbox/rtl/rbox_keyintr.sv
new file mode 100644
index 0000000..906d7ff
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_keyintr.sv
@@ -0,0 +1,609 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX key-triggered interrupt Module
+//
+module rbox_keyintr import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input clk_i,
+ input rst_ni,
+
+ input pwrb_int,
+ input key0_int,
+ input key1_int,
+ input key2_int,
+ input ac_present_int,
+ input cio_ec_rst_l_i,
+
+ input rbox_reg2hw_key_intr_ctl_reg_t key_intr_ctl_i,
+ input rbox_reg2hw_key_intr_debounce_ctl_reg_t key_intr_debounce_ctl_i,
+
+ output rbox_hw2reg_key_intr_status_reg_t key_intr_status_o,
+ output rbox_key_intr
+
+);
+
+ logic cfg_pwrb_in_h2l;
+ logic cfg_key0_in_h2l;
+ logic cfg_key1_in_h2l;
+ logic cfg_key2_in_h2l;
+ logic cfg_ac_present_h2l;
+ logic cfg_ec_rst_l_h2l;
+ logic cfg_pwrb_in_l2h;
+ logic cfg_key0_in_l2h;
+ logic cfg_key1_in_l2h;
+ logic cfg_key2_in_l2h;
+ logic cfg_ac_present_l2h;
+ logic cfg_ec_rst_l_l2h;
+
+ logic [15:0] cfg_key_intr_timer;
+ logic load_key_intr_timer;
+ logic [15:0] cfg_key_intr_timer_d;
+
+ logic pwrb_int_i;
+ logic key0_int_i, key1_int_i, key2_int_i;
+ logic ac_present_int_i;
+ logic ec_rst_l_int_i;
+ logic pwrb_intr_h2l_det, pwrb_intr_h2l_det_q, pwrb_intr_h2l_pulse;
+ logic pwrb_intr_l2h_det, pwrb_intr_l2h_det_q, pwrb_intr_l2h_pulse;
+ logic key0_intr_h2l_det, key0_intr_h2l_det_q, key0_intr_h2l_pulse;
+ logic key0_intr_l2h_det, key0_intr_l2h_det_q, key0_intr_l2h_pulse;
+ logic key1_intr_h2l_det, key1_intr_h2l_det_q, key1_intr_h2l_pulse;
+ logic key1_intr_l2h_det, key1_intr_l2h_det_q, key1_intr_l2h_pulse;
+ logic key2_intr_h2l_det, key2_intr_h2l_det_q, key2_intr_h2l_pulse;
+ logic key2_intr_l2h_det, key2_intr_l2h_det_q, key2_intr_l2h_pulse;
+ logic ac_present_intr_h2l_det, ac_present_intr_h2l_det_q, ac_present_intr_h2l_pulse;
+ logic ac_present_intr_l2h_det, ac_present_intr_l2h_det_q, ac_present_intr_l2h_pulse;
+ logic ec_rst_l_intr_h2l_det, ec_rst_l_intr_h2l_det_q, ec_rst_l_intr_h2l_pulse;
+ logic ec_rst_l_intr_l2h_det, ec_rst_l_intr_l2h_det_q, ec_rst_l_intr_l2h_pulse;
+
+ logic pwrb_h2l_intr, pwrb_l2h_intr;
+ logic key0_in_h2l_intr, key0_in_l2h_intr;
+ logic key1_in_h2l_intr, key1_in_l2h_intr;
+ logic key2_in_h2l_intr, key2_in_l2h_intr;
+ logic ac_present_h2l_intr, ac_present_l2h_intr;
+ logic ec_rst_l_h2l_intr, ec_rst_l_l2h_intr;
+
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_pwrb_in_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.pwrb_in_h2l.q),
+ .q_o(cfg_pwrb_in_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_in_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key0_in_h2l.q),
+ .q_o(cfg_key0_in_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_in_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key1_in_h2l.q),
+ .q_o(cfg_key1_in_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_in_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key2_in_h2l.q),
+ .q_o(cfg_key2_in_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ac_present_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.ac_present_h2l.q),
+ .q_o(cfg_ac_present_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ec_rst_l_h2l (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.ec_rst_l_h2l.q),
+ .q_o(cfg_ec_rst_l_h2l)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_pwrb_in_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.pwrb_in_l2h.q),
+ .q_o(cfg_pwrb_in_l2h)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_in_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key0_in_l2h.q),
+ .q_o(cfg_key0_in_l2h)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_in_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key1_in_l2h.q),
+ .q_o(cfg_key1_in_l2h)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_in_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.key2_in_l2h.q),
+ .q_o(cfg_key2_in_l2h)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ac_present_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.ac_present_l2h.q),
+ .q_o(cfg_ac_present_l2h)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ec_rst_l_l2h (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key_intr_ctl_i.ec_rst_l_l2h.q),
+ .q_o(cfg_ec_rst_l_l2h)
+ );
+
+ prim_fifo_async #(
+ .Width(16),
+ .Depth(2)
+ ) i_cfg_key_intr_timer (
+ .clk_wr_i (clk_i),
+ .rst_wr_ni (rst_ni),
+ .wvalid_i (key_intr_debounce_ctl_i.qe),
+ .wready_o (),
+ .wdata_i (key_intr_debounce_ctl_i.q),
+ .wdepth_o (),
+
+ .clk_rd_i (clk_aon_i),
+ .rst_rd_ni (rst_slow_ni),
+ .rvalid_o (load_key_intr_timer),
+ .rready_i (1'b1),
+ .rdata_o (cfg_key_intr_timer_d),
+ .rdepth_o ()
+ );
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_cfg_key_intr_timer_reg
+ if (!rst_slow_ni) begin
+ cfg_key_intr_timer <= '0;
+ end else if (load_key_intr_timer) begin
+ cfg_key_intr_timer <= cfg_key_intr_timer_d;
+ end
+ end
+
+ //synchronize between GPIO and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_pwrb_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pwrb_int),
+ .q_o(pwrb_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key0_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key0_int),
+ .q_o(key0_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key1_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key1_int),
+ .q_o(key1_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_key2_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(key2_int),
+ .q_o(key2_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_ac_present_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(ac_present_int),
+ .q_o(ac_present_int_i)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_ec_rst_l_int_i (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(cio_ec_rst_l_i),
+ .q_o(ec_rst_l_int_i)
+ );
+
+ //Instantiate the key state machine
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_pwrbintr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(pwrb_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_pwrb_in_l2h),
+ .cfg_h2l_en_i(cfg_pwrb_in_h2l),
+ .timer_l2h_cond_met(pwrb_intr_l2h_det),
+ .timer_h2l_cond_met(pwrb_intr_h2l_det)
+ );
+
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_key0intr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(key0_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_key0_in_l2h),
+ .cfg_h2l_en_i(cfg_key0_in_h2l),
+ .timer_l2h_cond_met(key0_intr_l2h_det),
+ .timer_h2l_cond_met(key0_intr_h2l_det)
+ );
+
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_key1intr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(key1_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_key1_in_l2h),
+ .cfg_h2l_en_i(cfg_key1_in_h2l),
+ .timer_l2h_cond_met(key1_intr_l2h_det),
+ .timer_h2l_cond_met(key1_intr_h2l_det)
+ );
+
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_key2intr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(key2_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_key2_in_l2h),
+ .cfg_h2l_en_i(cfg_key2_in_h2l),
+ .timer_l2h_cond_met(key2_intr_l2h_det),
+ .timer_h2l_cond_met(key2_intr_h2l_det)
+ );
+
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_ac_presentintr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(ac_present_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_ac_present_l2h),
+ .cfg_h2l_en_i(cfg_ac_present_h2l),
+ .timer_l2h_cond_met(ac_present_intr_l2h_det),
+ .timer_h2l_cond_met(ac_present_intr_h2l_det)
+ );
+
+ rbox_keyfsm # (
+ .TIMERBIT(16)
+ ) i_ec_rst_lintr_fsm (
+ .clk_aon_i(clk_aon_i),
+ .rst_slow_ni(rst_slow_ni),
+ .trigger_i(ec_rst_l_int_i),
+ .cfg_timer_i(cfg_key_intr_timer),
+ .cfg_l2h_en_i(cfg_ec_rst_l_l2h),
+ .cfg_h2l_en_i(cfg_ec_rst_l_h2l),
+ .timer_l2h_cond_met(ec_rst_l_intr_l2h_det),
+ .timer_h2l_cond_met(ec_rst_l_intr_h2l_det)
+ );
+
+
+ //delay the level signal to generate a pulse
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_pwrb_intr_h2l_det
+ if (!rst_slow_ni) begin
+ pwrb_intr_h2l_det_q <= 1'b0;
+ end else begin
+ pwrb_intr_h2l_det_q <= pwrb_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_pwrb_intr_l2h_det
+ if (!rst_slow_ni) begin
+ pwrb_intr_l2h_det_q <= 1'b0;
+ end else begin
+ pwrb_intr_l2h_det_q <= pwrb_intr_l2h_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key0_intr_h2l_det
+ if (!rst_slow_ni) begin
+ key0_intr_h2l_det_q <= 1'b0;
+ end else begin
+ key0_intr_h2l_det_q <= key0_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key0_intr_l2h_det
+ if (!rst_slow_ni) begin
+ key0_intr_l2h_det_q <= 1'b0;
+ end else begin
+ key0_intr_l2h_det_q <= key0_intr_l2h_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key1_intr_h2l_det
+ if (!rst_slow_ni) begin
+ key1_intr_h2l_det_q <= 1'b0;
+ end else begin
+ key1_intr_h2l_det_q <= key1_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key1_intr_l2h_det
+ if (!rst_slow_ni) begin
+ key1_intr_l2h_det_q <= 1'b0;
+ end else begin
+ key1_intr_l2h_det_q <= key1_intr_l2h_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key2_intr_h2l_det
+ if (!rst_slow_ni) begin
+ key2_intr_h2l_det_q <= 1'b0;
+ end else begin
+ key2_intr_h2l_det_q <= key2_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_key2_intr_l2h_det
+ if (!rst_slow_ni) begin
+ key2_intr_l2h_det_q <= 1'b0;
+ end else begin
+ key2_intr_l2h_det_q <= key2_intr_l2h_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_ac_present_intr_h2l_det
+ if (!rst_slow_ni) begin
+ ac_present_intr_h2l_det_q <= 1'b0;
+ end else begin
+ ac_present_intr_h2l_det_q <= ac_present_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_ac_present_intr_l2h_det
+ if (!rst_slow_ni) begin
+ ac_present_intr_l2h_det_q <= 1'b0;
+ end else begin
+ ac_present_intr_l2h_det_q <= ac_present_intr_l2h_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_ec_rst_l_intr_h2l_det
+ if (!rst_slow_ni) begin
+ ec_rst_l_intr_h2l_det_q <= 1'b0;
+ end else begin
+ ec_rst_l_intr_h2l_det_q <= ec_rst_l_intr_h2l_det;
+ end
+ end
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_ec_rst_l_intr_l2h_det
+ if (!rst_slow_ni) begin
+ ec_rst_l_intr_l2h_det_q <= 1'b0;
+ end else begin
+ ec_rst_l_intr_l2h_det_q <= ec_rst_l_intr_l2h_det;
+ end
+ end
+
+ //generate a pulse for interrupt status CSR
+ assign pwrb_intr_l2h_pulse = (pwrb_intr_l2h_det_q == 1'b0) && (pwrb_intr_l2h_det == 1'b1);
+ assign pwrb_intr_h2l_pulse = (pwrb_intr_h2l_det_q == 1'b1) && (pwrb_intr_h2l_det == 1'b0);
+ assign key0_intr_l2h_pulse = (key0_intr_l2h_det_q == 1'b0) && (key0_intr_l2h_det == 1'b1);
+ assign key0_intr_h2l_pulse = (key0_intr_h2l_det_q == 1'b1) && (key0_intr_h2l_det == 1'b0);
+ assign key1_intr_l2h_pulse = (key1_intr_l2h_det_q == 1'b0) && (key1_intr_l2h_det == 1'b1);
+ assign key1_intr_h2l_pulse = (key1_intr_h2l_det_q == 1'b1) && (key1_intr_h2l_det == 1'b0);
+ assign key2_intr_l2h_pulse = (key2_intr_l2h_det_q == 1'b0) && (key2_intr_l2h_det == 1'b1);
+ assign key2_intr_h2l_pulse = (key2_intr_h2l_det_q == 1'b1) && (key2_intr_h2l_det == 1'b0);
+ assign ac_present_intr_l2h_pulse = (ac_present_intr_l2h_det_q == 1'b0) &&
+ (ac_present_intr_l2h_det == 1'b1);
+ assign ac_present_intr_h2l_pulse = (ac_present_intr_h2l_det_q == 1'b1) &&
+ (ac_present_intr_h2l_det == 1'b0);
+ assign ec_rst_l_intr_l2h_pulse = (ec_rst_l_intr_l2h_det_q == 1'b0) &&
+ (ec_rst_l_intr_l2h_det == 1'b1);
+ assign ec_rst_l_intr_h2l_pulse = (ec_rst_l_intr_h2l_det_q == 1'b1) &&
+ (ec_rst_l_intr_h2l_det == 1'b0);
+
+ //Synchronize from 200KHz always-onclock to 24MHz cfg clock
+ prim_pulse_sync i_pwrb_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (pwrb_intr_h2l_pulse),
+ .dst_pulse_o (pwrb_h2l_intr)
+ );
+
+ assign key_intr_status_o.pwrb_h2l.de = pwrb_h2l_intr;
+
+ prim_pulse_sync i_pwrb_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (pwrb_intr_l2h_pulse),
+ .dst_pulse_o (pwrb_l2h_intr)
+ );
+
+ assign key_intr_status_o.pwrb_l2h.de = pwrb_l2h_intr;
+
+ prim_pulse_sync i_key0_in_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key0_intr_h2l_pulse),
+ .dst_pulse_o (key0_in_h2l_intr)
+ );
+
+ assign key_intr_status_o.key0_in_h2l.de = key0_in_h2l_intr;
+
+ prim_pulse_sync i_key0_in_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key0_intr_l2h_pulse),
+ .dst_pulse_o (key0_in_l2h_intr)
+ );
+
+ assign key_intr_status_o.key0_in_l2h.de = key0_in_l2h_intr;
+
+ prim_pulse_sync i_key1_in_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key1_intr_h2l_pulse),
+ .dst_pulse_o (key1_in_h2l_intr)
+ );
+
+ assign key_intr_status_o.key1_in_h2l.de = key1_in_h2l_intr;
+
+ prim_pulse_sync i_key1_in_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key1_intr_l2h_pulse),
+ .dst_pulse_o (key1_in_l2h_intr)
+ );
+
+ assign key_intr_status_o.key1_in_l2h.de = key1_in_l2h_intr;
+
+ prim_pulse_sync i_key2_in_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key2_intr_h2l_pulse),
+ .dst_pulse_o (key2_in_h2l_intr)
+ );
+
+ assign key_intr_status_o.key2_in_h2l.de = key2_in_h2l_intr;
+
+ prim_pulse_sync i_key2_in_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (key2_intr_l2h_pulse),
+ .dst_pulse_o (key2_in_l2h_intr)
+ );
+
+ assign key_intr_status_o.key2_in_l2h.de = key2_in_l2h_intr;
+
+ prim_pulse_sync i_ac_present_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (ac_present_intr_h2l_pulse),
+ .dst_pulse_o (ac_present_h2l_intr)
+ );
+
+ assign key_intr_status_o.ac_present_h2l.de = ac_present_h2l_intr;
+
+ prim_pulse_sync i_ac_present_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (ac_present_intr_l2h_pulse),
+ .dst_pulse_o (ac_present_l2h_intr)
+ );
+
+ assign key_intr_status_o.ac_present_l2h.de = ac_present_l2h_intr;
+
+ prim_pulse_sync i_ec_rst_l_h2l (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (ec_rst_l_intr_h2l_pulse),
+ .dst_pulse_o (ec_rst_l_h2l_intr)
+ );
+
+ assign key_intr_status_o.ec_rst_l_h2l.de = ec_rst_l_h2l_intr;
+
+ prim_pulse_sync i_ec_rst_l_l2h (
+ .clk_src_i (clk_aon_i),
+ .clk_dst_i (clk_i),
+ .rst_src_ni (rst_slow_ni),
+ .rst_dst_ni (rst_ni),
+ .src_pulse_i (ec_rst_l_intr_l2h_pulse),
+ .dst_pulse_o (ec_rst_l_l2h_intr)
+ );
+
+ assign key_intr_status_o.ec_rst_l_l2h.de = ec_rst_l_l2h_intr;
+
+ assign rbox_key_intr = pwrb_h2l_intr | pwrb_l2h_intr |
+ key0_in_h2l_intr | key0_in_l2h_intr |
+ key1_in_h2l_intr | key1_in_l2h_intr |
+ key2_in_h2l_intr | key2_in_l2h_intr |
+ ac_present_h2l_intr | ac_present_l2h_intr |
+ ec_rst_l_h2l_intr | ec_rst_l_l2h_intr;
+
+ //To write into interrupt status register
+ assign key_intr_status_o.pwrb_h2l.d = 1'b1;
+ assign key_intr_status_o.pwrb_l2h.d = 1'b1;
+ assign key_intr_status_o.key0_in_h2l.d = 1'b1;
+ assign key_intr_status_o.key0_in_l2h.d = 1'b1;
+ assign key_intr_status_o.key1_in_h2l.d = 1'b1;
+ assign key_intr_status_o.key1_in_l2h.d = 1'b1;
+ assign key_intr_status_o.key2_in_h2l.d = 1'b1;
+ assign key_intr_status_o.key2_in_l2h.d = 1'b1;
+ assign key_intr_status_o.ac_present_h2l.d = 1'b1;
+ assign key_intr_status_o.ac_present_l2h.d = 1'b1;
+ assign key_intr_status_o.ec_rst_l_h2l.d = 1'b1;
+ assign key_intr_status_o.ec_rst_l_l2h.d = 1'b1;
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_pin.sv b/hw/ip/rbox/rtl/rbox_pin.sv
new file mode 100644
index 0000000..1c660e6
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_pin.sv
@@ -0,0 +1,408 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: RBOX pin visibility and override Module
+//
+
+module rbox_pin import rbox_reg_pkg::*; (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input clk_i,
+ input rst_ni,
+
+ input cio_pwrb_in_i,
+ input cio_key0_in_i,
+ input cio_key1_in_i,
+ input cio_key2_in_i,
+ input cio_ac_present_i,
+ input cio_ec_rst_l_i,
+
+ input pwrb_out_hw,
+ input key0_out_hw,
+ input key1_out_hw,
+ input key2_out_hw,
+ input bat_disable_hw,
+ input ec_rst_l_hw,
+
+ input rbox_reg2hw_pin_allowed_ctl_reg_t pin_allowed_ctl_i,
+ input rbox_reg2hw_pin_out_ctl_reg_t pin_out_ctl_i,
+ input rbox_reg2hw_pin_out_value_reg_t pin_out_value_i,
+
+ output rbox_hw2reg_pin_in_value_reg_t pin_in_value_o,
+
+ output pwrb_out_int,
+ output key0_out_int,
+ output key1_out_int,
+ output key2_out_int,
+ output bat_disable_int,
+ output cio_ec_rst_l_o
+
+);
+
+ logic cfg_ac_present_i_pin;
+ logic cfg_ec_rst_l_i_pin;
+ logic cfg_pwrb_in_i_pin;
+ logic cfg_key0_in_i_pin;
+ logic cfg_key1_in_i_pin;
+ logic cfg_key2_in_i_pin;
+
+ logic cfg_bat_disable_0_allow;
+ logic cfg_ec_rst_l_0_allow;
+ logic cfg_pwrb_out_0_allow;
+ logic cfg_key0_out_0_allow;
+ logic cfg_key1_out_0_allow;
+ logic cfg_key2_out_0_allow;
+ logic cfg_bat_disable_1_allow;
+ logic cfg_ec_rst_l_1_allow;
+ logic cfg_pwrb_out_1_allow;
+ logic cfg_key0_out_1_allow;
+ logic cfg_key1_out_1_allow;
+ logic cfg_key2_out_1_allow;
+
+ logic cfg_bat_disable_ov;
+ logic cfg_ec_rst_l_ov;
+ logic cfg_pwrb_out_ov;
+ logic cfg_key0_out_ov;
+ logic cfg_key1_out_ov;
+ logic cfg_key2_out_ov;
+
+ logic cfg_bat_disable_q;
+ logic cfg_ec_rst_l_q;
+ logic cfg_pwrb_out_q;
+ logic cfg_key0_out_q;
+ logic cfg_key1_out_q;
+ logic cfg_key2_out_q;
+
+ //Synchronize between GPIO and cfg(24MHz)
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ac_present_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_ac_present_i),
+ .q_o(cfg_ac_present_i_pin)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_ec_rst_l_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_ec_rst_l_i),
+ .q_o(cfg_ec_rst_l_i_pin)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_pwrb_in_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_pwrb_in_i),
+ .q_o(cfg_pwrb_in_i_pin)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key0_in_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_key0_in_i),
+ .q_o(cfg_key0_in_i_pin)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key1_in_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_key1_in_i),
+ .q_o(cfg_key1_in_i_pin)
+ );
+
+ prim_flop_2sync # (
+ .Width(1)
+ ) i_cfg_key2_in_i_pin (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .d_i(cio_key2_in_i),
+ .q_o(cfg_key2_in_i_pin)
+ );
+
+ //Use the raw input(not inverted)
+ assign pin_in_value_o.ac_present.d = cfg_ac_present_i_pin;
+ assign pin_in_value_o.ec_rst_l.d = cfg_ec_rst_l_i_pin;
+ assign pin_in_value_o.pwrb_in.d = cfg_pwrb_in_i_pin;
+ assign pin_in_value_o.key0_in.d = cfg_key0_in_i_pin;
+ assign pin_in_value_o.key1_in.d = cfg_key1_in_i_pin;
+ assign pin_in_value_o.key2_in.d = cfg_key2_in_i_pin;
+
+ assign pin_in_value_o.ac_present.de = 1'b1;
+ assign pin_in_value_o.ec_rst_l.de = 1'b1;
+ assign pin_in_value_o.pwrb_in.de = 1'b1;
+ assign pin_in_value_o.key0_in.de = 1'b1;
+ assign pin_in_value_o.key1_in.de = 1'b1;
+ assign pin_in_value_o.key2_in.de = 1'b1;
+
+ //synchronize between cfg(24MHz) and always-on(200KHz)
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_bat_disable_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.bat_disable_0.q),
+ .q_o(cfg_bat_disable_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue(1'b1)//ec_rst_l_0_allow is enabled by default
+ ) i_cfg_ec_rst_l_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.ec_rst_l_0.q),
+ .q_o(cfg_ec_rst_l_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_pwrb_out_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.pwrb_out_0.q),
+ .q_o(cfg_pwrb_out_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key0_out_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key0_out_0.q),
+ .q_o(cfg_key0_out_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key1_out_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key1_out_0.q),
+ .q_o(cfg_key1_out_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key2_out_0_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key2_out_0.q),
+ .q_o(cfg_key2_out_0_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_bat_disable_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.bat_disable_1.q),
+ .q_o(cfg_bat_disable_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_ec_rst_l_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.ec_rst_l_1.q),
+ .q_o(cfg_ec_rst_l_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_pwrb_out_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.pwrb_out_1.q),
+ .q_o(cfg_pwrb_out_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key0_out_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key0_out_1.q),
+ .q_o(cfg_key0_out_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key1_out_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key1_out_1.q),
+ .q_o(cfg_key1_out_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key2_out_1_allow (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_allowed_ctl_i.key2_out_1.q),
+ .q_o(cfg_key2_out_1_allow)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_bat_disable_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.bat_disable.q),
+ .q_o(cfg_bat_disable_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue(1'b1)//ec_rst_l override is enabled by default
+ ) i_cfg_ec_rst_l_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.ec_rst_l.q),
+ .q_o(cfg_ec_rst_l_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_pwrb_out_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.pwrb_out.q),
+ .q_o(cfg_pwrb_out_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key0_out_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.key0_out.q),
+ .q_o(cfg_key0_out_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key1_out_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.key1_out.q),
+ .q_o(cfg_key1_out_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key2_out_ov (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_ctl_i.key2_out.q),
+ .q_o(cfg_key2_out_ov)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_bat_disable_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.bat_disable.q),
+ .q_o(cfg_bat_disable_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_ec_rst_l_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.ec_rst_l.q),
+ .q_o(cfg_ec_rst_l_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_pwrb_out_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.pwrb_out.q),
+ .q_o(cfg_pwrb_out_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key0_out_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.key0_out.q),
+ .q_o(cfg_key0_out_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key1_out_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.key1_out.q),
+ .q_o(cfg_key1_out_q)
+ );
+
+ prim_flop_2sync # (
+ .Width(1),
+ .ResetValue('0)
+ ) i_cfg_key2_out_q (
+ .clk_i(clk_aon_i),
+ .rst_ni(rst_slow_ni),
+ .d_i(pin_out_value_i.key2_out.q),
+ .q_o(cfg_key2_out_q)
+ );
+
+ assign pwrb_out_int = (cfg_pwrb_out_ov && cfg_pwrb_out_0_allow && !cfg_pwrb_out_q) ? 1'b0 :
+ ((cfg_pwrb_out_ov && cfg_pwrb_out_1_allow && cfg_pwrb_out_q) ? 1'b1 : pwrb_out_hw);
+
+ assign key0_out_int = (cfg_key0_out_ov && cfg_key0_out_0_allow && !cfg_key0_out_q) ? 1'b0 :
+ ((cfg_key0_out_ov && cfg_key0_out_1_allow && cfg_key0_out_q) ? 1'b1 : key0_out_hw);
+
+ assign key1_out_int = (cfg_key1_out_ov && cfg_key1_out_0_allow && !cfg_key1_out_q) ? 1'b0 :
+ ((cfg_key1_out_ov && cfg_key1_out_1_allow && cfg_key1_out_q) ? 1'b1 : key1_out_hw);
+
+ assign key2_out_int = (cfg_key2_out_ov && cfg_key2_out_0_allow && !cfg_key2_out_q) ? 1'b0 :
+ ((cfg_key2_out_ov && cfg_key2_out_1_allow && cfg_key2_out_q) ? 1'b1 : key2_out_hw);
+
+ assign bat_disable_int =
+ (cfg_bat_disable_ov && cfg_bat_disable_0_allow && !cfg_bat_disable_q) ? 1'b0 :
+ ((cfg_bat_disable_ov && cfg_bat_disable_1_allow && cfg_bat_disable_q) ? 1'b1 :
+ bat_disable_hw);
+
+ assign cio_ec_rst_l_o = (cfg_ec_rst_l_ov && cfg_ec_rst_l_0_allow && !cfg_ec_rst_l_q) ? 1'b0 :
+ ((cfg_ec_rst_l_ov && cfg_ec_rst_l_1_allow && cfg_ec_rst_l_q) ? 1'b1 : ec_rst_l_hw);
+
+endmodule
diff --git a/hw/ip/rbox/rtl/rbox_timerfsm.sv b/hw/ip/rbox/rtl/rbox_timerfsm.sv
new file mode 100644
index 0000000..91ebf53
--- /dev/null
+++ b/hw/ip/rbox/rtl/rbox_timerfsm.sv
@@ -0,0 +1,147 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description RBOX timer-based FSM module
+
+module rbox_timerfsm #(
+ parameter int unsigned TIMERBIT = 16
+ ) (
+ input clk_aon_i,
+ input rst_slow_ni,
+ input trigger_i,
+ input [TIMERBIT-1:0] cfg_timer_i,
+ input cfg_l2h_en_i,
+ input cfg_h2l_en_i,
+ output logic timer_l2h_cond_met,
+ output logic timer_h2l_cond_met
+
+);
+
+ logic trigger_q;
+ logic trigger_h2l, trigger_l2h, trigger_h2h, trigger_l2l;
+ logic trigger_tgl, trigger_sty;
+
+ logic [TIMERBIT-1:0] timer_cnt_d, timer_cnt_q;
+ logic timer_cnt_clr, timer_cnt_en;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_trigger_reg
+ if (!rst_slow_ni) begin
+ trigger_q <= 1'b0;
+ end else begin
+ trigger_q <= trigger_i;
+ end
+ end
+
+ assign trigger_h2l = (trigger_q == 1'b1) && (trigger_i == 1'b0);
+ assign trigger_l2h = (trigger_q == 1'b0) && (trigger_i == 1'b1);
+ assign trigger_h2h = (trigger_q == 1'b1) && (trigger_i == 1'b1);
+ assign trigger_l2l = (trigger_q == 1'b0) && (trigger_i == 1'b0);
+ assign trigger_tgl = trigger_q != trigger_i;
+ assign trigger_sty = trigger_q == trigger_i;
+
+ //three-state FSM
+ //IDLE->WAITL2H->DONEL2H or IDLE->WAITH2L->DONEH2L
+ //The input signals can be inverted. Hence, both paths
+ //FSM will detect a L2H or H2L transition to enter the wait state
+ //debounce timer defines the time to wait for input to stablize
+ //FSM will check the input after the debounce period
+ typedef enum logic [2:0] {
+ IDLE = 3'h0,
+ WAITL2H = 3'h1,
+ WAITH2L = 3'h2,
+ DONEL2H = 3'h3,
+ DONEH2L = 3'h4
+ } timer_state_e;
+
+ timer_state_e timer_state_q, timer_state_d;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer_state_reg
+ if (!rst_slow_ni) begin
+ timer_state_q <= IDLE;
+ end else begin
+ timer_state_q <= timer_state_d;
+ end
+ end
+
+ assign timer_cnt_d = (timer_cnt_en) ? timer_cnt_q + 1'b1 : timer_cnt_q;
+
+ always_ff @(posedge clk_aon_i or negedge rst_slow_ni) begin: i_timer_cnt_reg
+ if (!rst_slow_ni) begin
+ timer_cnt_q <= '0;
+ end
+ else if (timer_cnt_clr) begin
+ timer_cnt_q <= '0;
+ end else begin
+ timer_cnt_q <= timer_cnt_d;
+ end
+ end
+
+ always_comb begin: timer_fsm
+ timer_state_d = timer_state_q;
+ //outputs
+ timer_l2h_cond_met = 1'b0;
+ timer_h2l_cond_met = 1'b0;
+ timer_cnt_clr = 1'b0;
+ timer_cnt_en = 1'b0;
+
+ unique case (timer_state_q)
+ IDLE: begin
+ if (cfg_l2h_en_i && trigger_l2h) begin
+ timer_state_d = WAITL2H;
+ end
+ else if (cfg_h2l_en_i && trigger_h2l) begin
+ timer_state_d = WAITH2L;
+ end
+ end
+
+ WAITL2H: begin
+ if (timer_cnt_q != cfg_timer_i) begin
+ timer_cnt_en = 1'b1;
+ end
+ else if (!trigger_h2h && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = IDLE;
+ timer_cnt_clr = 1'b1;
+ end
+ else if (trigger_h2h && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = DONEL2H;
+ timer_cnt_clr = 1'b1;
+ end
+ end
+
+ DONEL2H: begin
+ if (trigger_h2h) begin
+ timer_l2h_cond_met = 1'b1;
+ end
+ else if (trigger_h2l) begin
+ timer_state_d = IDLE;
+ end
+ end
+
+ WAITH2L: begin
+ if (timer_cnt_q != cfg_timer_i) begin
+ timer_cnt_en = 1'b1;
+ end
+ else if (!trigger_l2l && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = IDLE;
+ timer_cnt_clr = 1'b1;
+ end
+ else if (trigger_l2l && (timer_cnt_q == cfg_timer_i)) begin
+ timer_state_d = DONEH2L;
+ timer_cnt_clr = 1'b1;
+ end
+ end
+
+ DONEH2L: begin
+ if (trigger_l2l) begin
+ timer_h2l_cond_met = 1'b1;
+ end
+ else if (trigger_l2h) begin
+ timer_state_d = IDLE;
+ end
+ end
+ default: timer_state_d = IDLE;
+ endcase
+ end
+
+endmodule
diff --git a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
index 5390d81..019c380 100644
--- a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
+++ b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
@@ -142,6 +142,11 @@
}
]
},
+ { name: rbox
+ fusesoc_core: lowrisc:ip:rbox
+ import_cfgs: ["{proj_root}/hw/lint/tools/dvsim/common_lint_cfg.hjson"]
+ rel_path: "hw/ip/rbox/lint/{tool}"
+ },
{ name: rstmgr
fusesoc_core: lowrisc:ip:rstmgr
import_cfgs: ["{proj_root}/hw/lint/tools/dvsim/common_lint_cfg.hjson"],