blob: 8719eb093be79cfa8a873d10743e621d94891265 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Description: sysrst_ctrl combo Module
//
module sysrst_ctrl_combo import sysrst_ctrl_reg_pkg::*; (
input clk_aon_i,
input rst_aon_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_in_l_i,
input sysrst_ctrl_reg2hw_ec_rst_ctl_reg_t ec_rst_ctl_i,
input sysrst_ctrl_reg2hw_key_intr_debounce_ctl_reg_t key_intr_debounce_ctl_i,
input sysrst_ctrl_reg2hw_com_sel_ctl_mreg_t [NumCombo-1:0] com_sel_ctl_i,
input sysrst_ctrl_reg2hw_com_det_ctl_mreg_t [NumCombo-1:0] com_det_ctl_i,
input sysrst_ctrl_reg2hw_com_out_ctl_mreg_t [NumCombo-1:0] com_out_ctl_i,
output sysrst_ctrl_hw2reg_combo_intr_status_reg_t combo_intr_status_o,
output sysrst_ctrl_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_aon_ni),
.d_i(cio_ec_rst_in_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_ni) begin: i_cfg_combo_timer_reg
if (!rst_aon_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_aon_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_aon_ni) begin: i_cfg_debounce_timer_reg
if (!rst_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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_aon_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
sysrst_ctrl_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
sysrst_ctrl_combofsm # (
.TIMER1BIT(16),
.TIMER2BIT(32)
) i_combo_fsm (
.clk_aon_i(clk_aon_i),
.rst_aon_ni(rst_aon_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
sysrst_ctrl_comboact i_combo_act (
.clk_aon_i(clk_aon_i),
.rst_aon_ni(rst_aon_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_aon_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_aon_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_aon_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_aon_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 sysrst_ctrl_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