[pwrmgr] Add pwrmgr_cdc module

- contains all cdc handling logic
- moved to a more traditional synchronization scheme

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/pwrmgr/data/pwrmgr.hjson b/hw/ip/pwrmgr/data/pwrmgr.hjson
index 620b4ac..db5df8b 100644
--- a/hw/ip/pwrmgr/data/pwrmgr.hjson
+++ b/hw/ip/pwrmgr/data/pwrmgr.hjson
@@ -70,6 +70,34 @@
   regwidth: "32",
   registers: [
 
+    { name: "CFG_CDC_SYNC",
+      swaccess: "rw",
+      hwaccess: "hrw",
+      hwqe: "true",
+      desc: '''
+      The configuration registers CONTROL, WAKEUP_EN, RESET_EN are all written in the
+      fast clock domain but used in the slow clock domain.
+
+      The configuration are not propogated across the clock boundary until this
+      register is triggered and read.  See fields below for more details
+      ''',
+
+      fields: [
+        { bits: "0",
+          swaccess: "wo",
+          name: "SYNC",
+          desc: '''
+            Configuration sync.  When this bit is written to 1, a sync pulse is generated.  When
+            the sync completes, this bit then self clears.
+
+            Software should write this bit to 1, wait for it to clear, before assuming the slow clock
+            domain has assumed the programmaed values.
+          ''',
+          resval: "0",
+        },
+      ]
+    },
+
     { name: "CTRL_CFG_REGWEN",
       swaccess: "rw0c",
       hwaccess: "hwo",
diff --git a/hw/ip/pwrmgr/fpv/vip/pwrmgr_csr_assert_fpv.sv b/hw/ip/pwrmgr/fpv/vip/pwrmgr_csr_assert_fpv.sv
index a215592..60131f2 100644
--- a/hw/ip/pwrmgr/fpv/vip/pwrmgr_csr_assert_fpv.sv
+++ b/hw/ip/pwrmgr/fpv/vip/pwrmgr_csr_assert_fpv.sv
@@ -87,45 +87,49 @@
   // read/write assertions for register: intr_test
   `ASSERT(intr_test_wr_A, wr_ext_P(0, 6'h8, i_pwrmgr.reg2hw.intr_test.q, 0))
 
+  // read/write assertions for register: cfg_cdc_sync
+  `ASSERT(cfg_cdc_sync_wr_A, wr_P(0, 6'hc, i_pwrmgr.reg2hw.cfg_cdc_sync.q, 0))
+  `ASSERT(cfg_cdc_sync_rd_A, rd_P(0, 6'hc, i_pwrmgr.hw2reg.cfg_cdc_sync.d))
+
   // read/write assertions for register: ctrl_cfg_regwen
-  `ASSERT(ctrl_cfg_regwen_wr_A, wr_ext_P(0, 6'hc, i_pwrmgr.reg2hw.ctrl_cfg_regwen.q, 0))
-  `ASSERT(ctrl_cfg_regwen_rd_A, rd_ext_P(0, 6'hc, i_pwrmgr.hw2reg.ctrl_cfg_regwen.d))
+  `ASSERT(ctrl_cfg_regwen_wr_A, wr_ext_P(0, 6'h10, i_pwrmgr.reg2hw.ctrl_cfg_regwen.q, 0))
+  `ASSERT(ctrl_cfg_regwen_rd_A, rd_ext_P(0, 6'h10, i_pwrmgr.hw2reg.ctrl_cfg_regwen.d))
 
   // read/write assertions for register: control
-  `ASSERT(control_wr_A, wr_P(6, 6'h10, i_pwrmgr.reg2hw.control.q, i_pwrmgr.i_reg_top.ctrl_cfg_regwen_qs))
+  `ASSERT(control_wr_A, wr_P(6, 6'h14, i_pwrmgr.reg2hw.control.q, i_pwrmgr.i_reg_top.ctrl_cfg_regwen_qs))
   `ASSERT(control_stable_A, wr_regen_stable_P(i_pwrmgr.i_reg_top.ctrl_cfg_regwen_qs, i_pwrmgr.reg2hw.control.q))
-  `ASSERT(control_rd_A, rd_P(6, 6'h10, i_pwrmgr.hw2reg.control.d))
+  `ASSERT(control_rd_A, rd_P(6, 6'h14, i_pwrmgr.hw2reg.control.d))
 
   // read/write assertions for register: wakeup_en_regwen
-  `ASSERT(wakeup_en_regwen_wr_A, wr_P(0, 6'h14, i_pwrmgr.i_reg_top.wakeup_en_regwen_we, 0))
-  `ASSERT(wakeup_en_regwen_rd_A, rd_P(0, 6'h14, i_pwrmgr.i_reg_top.wakeup_en_regwen_qs))
+  `ASSERT(wakeup_en_regwen_wr_A, wr_P(0, 6'h18, i_pwrmgr.i_reg_top.wakeup_en_regwen_we, 0))
+  `ASSERT(wakeup_en_regwen_rd_A, rd_P(0, 6'h18, i_pwrmgr.i_reg_top.wakeup_en_regwen_qs))
 
   // read/write assertions for register: wakeup_en
-  `ASSERT(wakeup_en_wr_A, wr_P(15, 6'h18, i_pwrmgr.reg2hw.wakeup_en.q, i_pwrmgr.i_reg_top.wakeup_en_regwen_qs))
+  `ASSERT(wakeup_en_wr_A, wr_P(15, 6'h1c, i_pwrmgr.reg2hw.wakeup_en.q, i_pwrmgr.i_reg_top.wakeup_en_regwen_qs))
   `ASSERT(wakeup_en_stable_A, wr_regen_stable_P(i_pwrmgr.i_reg_top.wakeup_en_regwen_qs, i_pwrmgr.reg2hw.wakeup_en.q))
-  `ASSERT(wakeup_en_rd_A, rd_P(15, 6'h18, i_pwrmgr.reg2hw.wakeup_en.q))
+  `ASSERT(wakeup_en_rd_A, rd_P(15, 6'h1c, i_pwrmgr.reg2hw.wakeup_en.q))
 
   // read/write assertions for register: wake_status
-  `ASSERT(wake_status_rd_A, rd_P(15, 6'h1c, i_pwrmgr.i_reg_top.wake_status_qs))
+  `ASSERT(wake_status_rd_A, rd_P(15, 6'h20, i_pwrmgr.i_reg_top.wake_status_qs))
 
   // read/write assertions for register: reset_en_regwen
-  `ASSERT(reset_en_regwen_wr_A, wr_P(0, 6'h20, i_pwrmgr.i_reg_top.reset_en_regwen_we, 0))
-  `ASSERT(reset_en_regwen_rd_A, rd_P(0, 6'h20, i_pwrmgr.i_reg_top.reset_en_regwen_qs))
+  `ASSERT(reset_en_regwen_wr_A, wr_P(0, 6'h24, i_pwrmgr.i_reg_top.reset_en_regwen_we, 0))
+  `ASSERT(reset_en_regwen_rd_A, rd_P(0, 6'h24, i_pwrmgr.i_reg_top.reset_en_regwen_qs))
 
   // read/write assertions for register: reset_en
-  `ASSERT(reset_en_wr_A, wr_P(1, 6'h24, i_pwrmgr.reg2hw.reset_en.q, i_pwrmgr.i_reg_top.reset_en_regwen_qs))
+  `ASSERT(reset_en_wr_A, wr_P(1, 6'h28, i_pwrmgr.reg2hw.reset_en.q, i_pwrmgr.i_reg_top.reset_en_regwen_qs))
   `ASSERT(reset_en_stable_A, wr_regen_stable_P(i_pwrmgr.i_reg_top.reset_en_regwen_qs, i_pwrmgr.reg2hw.reset_en.q))
-  `ASSERT(reset_en_rd_A, rd_P(1, 6'h24, i_pwrmgr.reg2hw.reset_en.q))
+  `ASSERT(reset_en_rd_A, rd_P(1, 6'h28, i_pwrmgr.reg2hw.reset_en.q))
 
   // read/write assertions for register: reset_status
-  `ASSERT(reset_status_rd_A, rd_P(1, 6'h28, i_pwrmgr.i_reg_top.reset_status_qs))
+  `ASSERT(reset_status_rd_A, rd_P(1, 6'h2c, i_pwrmgr.i_reg_top.reset_status_qs))
 
   // read/write assertions for register: wake_info_capture_dis
-  `ASSERT(wake_info_capture_dis_wr_A, wr_P(0, 6'h2c, i_pwrmgr.reg2hw.wake_info_capture_dis.q, 0))
-  `ASSERT(wake_info_capture_dis_rd_A, rd_P(0, 6'h2c, i_pwrmgr.reg2hw.wake_info_capture_dis.q))
+  `ASSERT(wake_info_capture_dis_wr_A, wr_P(0, 6'h30, i_pwrmgr.reg2hw.wake_info_capture_dis.q, 0))
+  `ASSERT(wake_info_capture_dis_rd_A, rd_P(0, 6'h30, i_pwrmgr.reg2hw.wake_info_capture_dis.q))
 
   // read/write assertions for register: wake_info
-  `ASSERT(wake_info_wr_A, wr_ext_P(17, 6'h30, i_pwrmgr.reg2hw.wake_info.q, 0))
-  `ASSERT(wake_info_rd_A, rd_ext_P(17, 6'h30, i_pwrmgr.hw2reg.wake_info.d))
+  `ASSERT(wake_info_wr_A, wr_ext_P(17, 6'h34, i_pwrmgr.reg2hw.wake_info.q, 0))
+  `ASSERT(wake_info_rd_A, rd_ext_P(17, 6'h34, i_pwrmgr.hw2reg.wake_info.d))
 
 endmodule
diff --git a/hw/ip/pwrmgr/pwrmgr.core b/hw/ip/pwrmgr/pwrmgr.core
index 31fc4e1..c751ef7 100644
--- a/hw/ip/pwrmgr/pwrmgr.core
+++ b/hw/ip/pwrmgr/pwrmgr.core
@@ -15,7 +15,7 @@
       - rtl/pwrmgr_reg_pkg.sv
       - rtl/pwrmgr_reg_top.sv
       - rtl/pwrmgr.sv
-      - rtl/pwrmgr_cdc_pulse.sv
+      - rtl/pwrmgr_cdc.sv
       - rtl/pwrmgr_slow_fsm.sv
       - rtl/pwrmgr_fsm.sv
       - rtl/pwrmgr_wake_info.sv
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr.sv b/hw/ip/pwrmgr/rtl/pwrmgr.sv
index 26b210f..4f3fb79 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr.sv
@@ -60,7 +60,7 @@
   pwrmgr_reg2hw_t reg2hw;
   pwrmgr_hw2reg_t hw2reg;
 
-  pwr_peri_rsp_t ext_reqs, ext_reqs_masked;
+  pwr_peri_rsp_t ext_reqs_masked;
   logic req_pwrup;
   logic ack_pwrup;
   logic req_pwrdn;
@@ -80,10 +80,11 @@
   pwrmgr_reg2hw_wakeup_en_reg_t slow_wakeup_en;
   pwrmgr_reg2hw_reset_en_reg_t slow_reset_en;
 
-  pwr_ast_rsp_t slow_ast_q;
+  pwr_ast_rsp_t slow_ast;
   pwr_peri_rsp_t slow_ext_reqs, slow_ext_reqs_masked;
 
   pwrup_cause_e slow_pwrup_cause;
+  logic slow_pwrup_cause_toggle;
   logic slow_req_pwrup;
   logic slow_ack_pwrup;
   logic slow_req_pwrdn;
@@ -129,78 +130,54 @@
   assign hw2reg.ctrl_cfg_regwen.d = lowpwr_cfg_regwen;
 
   ////////////////////////////
-  ///  cdc handling - clk_i
+  ///  cdc handling
   ////////////////////////////
 
-  // finds a clk_slow edge in clk domain to know when it is safe to sync over
-  // this signal is only safe to use within the pwrmgr module when the source
-  // and destination clock domains are both clear
-  logic cdc_safe;
-
-  // pwrup is synced directly as it acts as a start signal to the pulse module
-  prim_flop_2sync # (
-    .Width(1)
-  ) i_pwrup_sync (
+  pwrmgr_cdc i_cdc (
     .clk_i,
     .rst_ni,
-    .d(slow_req_pwrup),
-    .q(req_pwrup)
-  );
-
-  pwrmgr_cdc_pulse i_cdc_pulse (
     .clk_slow_i,
-    .clk_i,
-    .rst_ni,
-    .start_i(req_pwrup),
-    .stop_i(req_pwrdn),
-    .pulse_o(cdc_safe)
+    .rst_slow_ni,
+
+    // slow domain signals
+    .slow_req_pwrup_i(slow_req_pwrup),
+    .slow_ack_pwrdn_i(slow_ack_pwrdn),
+    .slow_pwrup_cause_toggle_i(slow_pwrup_cause_toggle),
+    .slow_pwrup_cause_i(slow_pwrup_cause),
+    .slow_wakeup_en_o(slow_wakeup_en),
+    .slow_reset_en_o(slow_reset_en),
+    .slow_main_pdb_o(slow_main_pdb),
+    .slow_io_clk_en_o(slow_io_clk_en),
+    .slow_core_clk_en_o(slow_core_clk_en),
+    .slow_req_pwrdn_o(slow_req_pwrdn),
+    .slow_ack_pwrup_o(slow_ack_pwrup),
+    .slow_ast_o(slow_ast),
+    .slow_ext_reqs_o(slow_ext_reqs),
+    .slow_ext_reqs_masked_i(slow_ext_reqs_masked),
+
+    // fast domain signals
+    .req_pwrdn_i(req_pwrdn),
+    .ack_pwrup_i(ack_pwrup),
+    .cfg_cdc_sync_i(reg2hw.cfg_cdc_sync.qe & reg2hw.cfg_cdc_sync.q),
+    .cdc_sync_done_o(hw2reg.cfg_cdc_sync.de),
+    .wakeup_en_i(reg2hw.wakeup_en.q),
+    .reset_en_i(reg2hw.reset_en.q),
+    .main_pdb_i(reg2hw.control.main_pdb.q),
+    .io_clk_en_i(reg2hw.control.io_clk_en.q),
+    .core_clk_en_i(reg2hw.control.core_clk_en.q),
+    .ack_pwrdn_o(ack_pwrdn),
+    .req_pwrup_o(req_pwrup),
+    .pwrup_cause_o(pwrup_cause),
+    .ext_reqs_o(ext_reqs_masked),
+
+    // AST signals
+    .ast_i(pwr_ast_i),
+
+    // peripheral signals
+    .peri_i(pwr_peri_i)
   );
 
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      ack_pwrdn   <= '0;
-      pwrup_cause <= Por;
-    end else if (cdc_safe) begin
-      ack_pwrdn   <= slow_ack_pwrdn;
-      pwrup_cause <= slow_pwrup_cause;
-    end
-  end
-
-  ////////////////////////////
-  ///  cdc handling - clk_slow_i
-  ////////////////////////////
-
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      slow_wakeup_en <= '0;
-      slow_reset_en  <= '0;
-      slow_main_pdb  <= '0;
-      slow_io_clk_en <= '0;
-      slow_core_clk_en <= '0;
-      slow_ack_pwrup <= '0;
-      slow_req_pwrdn <= '0;
-    end else if (cdc_safe) begin
-      slow_wakeup_en <= reg2hw.wakeup_en.q;
-      slow_reset_en  <= reg2hw.reset_en.q;
-      slow_main_pdb  <= reg2hw.control.main_pdb.q;
-      slow_io_clk_en <= reg2hw.control.io_clk_en.q;
-      slow_core_clk_en <= reg2hw.control.core_clk_en.q;
-      slow_ack_pwrup <= ack_pwrup;
-      slow_req_pwrdn <= req_pwrdn;
-    end
-  end
-
-  // TODO
-  // Need to vote on the differential signals to ensure they are stable
-  prim_flop_2sync # (
-    .Width($bits(pwr_ast_rsp_t))
-  ) i_pok_sync (
-    .clk_i  (clk_slow_i),
-    .rst_ni (rst_slow_ni),
-    .d      (pwr_ast_i),
-    .q      (slow_ast_q)
-  );
-
+  assign hw2reg.cfg_cdc_sync.d = 1'b0;
 
   ////////////////////////////
   ///  Wakup and reset capture
@@ -213,28 +190,7 @@
   // scale approximately the same across all domains.
   //
   // This also implies that these signals must be at least 1 clk_slow pulse long
-
-  prim_flop_2sync # (
-    .Width(HwRstReqs + WakeUpPeris)
-  ) i_slow_ext_req_sync (
-    .clk_i  (clk_slow_i),
-    .rst_ni (rst_slow_ni),
-    .d      (pwr_peri_i),
-    .q      (slow_ext_reqs)
-  );
-
-  assign slow_ext_reqs_masked.wakeups = slow_ext_reqs.wakeups & slow_wakeup_en;
-  assign slow_ext_reqs_masked.rstreqs = slow_ext_reqs.rstreqs & slow_reset_en;
-
-  prim_flop_2sync # (
-    .Width(HwRstReqs + WakeUpPeris)
-  ) i_ext_req_sync (
-    .clk_i,
-    .rst_ni,
-    .d (slow_ext_reqs),
-    .q (ext_reqs)
-  );
-
+  //
   // Since resets are not latched inside pwrmgr, there exists a corner case where
   // non-always-on reset requests may get wiped out by a graceful low power entry
   // It's not clear if this is really an issue at the moment, but something to keep
@@ -244,38 +200,37 @@
   // should clear it and when that should happen. If the clearing does not work
   // correctly, it is possible for the device to end up in a permanent reset loop,
   // and that would be very undesirable.
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      ext_reqs_masked <= '0;
-    end else if (cdc_safe) begin
-      ext_reqs_masked.wakeups <= ext_reqs.wakeups & reg2hw.wakeup_en;
-      ext_reqs_masked.rstreqs <= ext_reqs.rstreqs & reg2hw.reset_en;
-    end
-  end
+
+  assign slow_ext_reqs_masked.wakeups = slow_ext_reqs.wakeups & slow_wakeup_en;
+  assign slow_ext_reqs_masked.rstreqs = slow_ext_reqs.rstreqs & slow_reset_en;
+
+
+
 
   ////////////////////////////
   ///  clk_slow FSM
   ////////////////////////////
 
   pwrmgr_slow_fsm i_slow_fsm (
-    .clk_i           (clk_slow_i),
-    .rst_ni          (rst_slow_ni),
-    .wakeup_i        (|slow_ext_reqs_masked.wakeups),
-    .reset_req_i     (|slow_ext_reqs_masked.rstreqs),
-    .ast_i           (slow_ast_q),
-    .req_pwrup_o     (slow_req_pwrup),
-    .pwrup_cause_o   (slow_pwrup_cause),
-    .ack_pwrup_i     (slow_ack_pwrup),
-    .req_pwrdn_i     (slow_req_pwrdn),
-    .ack_pwrdn_o     (slow_ack_pwrdn),
+    .clk_i                (clk_slow_i),
+    .rst_ni               (rst_slow_ni),
+    .wakeup_i             (|slow_ext_reqs_masked.wakeups),
+    .reset_req_i          (|slow_ext_reqs_masked.rstreqs),
+    .ast_i                (slow_ast),
+    .req_pwrup_o          (slow_req_pwrup),
+    .pwrup_cause_o        (slow_pwrup_cause),
+    .pwrup_cause_toggle_o (slow_pwrup_cause_toggle),
+    .ack_pwrup_i          (slow_ack_pwrup),
+    .req_pwrdn_i          (slow_req_pwrdn),
+    .ack_pwrdn_o          (slow_ack_pwrdn),
 
-    .main_pdb_i      (slow_main_pdb),
-    .io_clk_en_i     (slow_io_clk_en),
-    .core_clk_en_i   (slow_core_clk_en),
+    .main_pdb_i           (slow_main_pdb),
+    .io_clk_en_i          (slow_io_clk_en),
+    .core_clk_en_i        (slow_core_clk_en),
 
     // outputs to AST - These are on the slow clock domain
     // TBD - need to check this with partners
-    .ast_o           (pwr_ast_o)
+    .ast_o                (pwr_ast_o)
   );
 
 
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv b/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv
new file mode 100644
index 0000000..5d73a3a
--- /dev/null
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv
@@ -0,0 +1,300 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Power Manager CDC handling
+//
+
+`include "prim_assert.sv"
+
+module pwrmgr_cdc import pwrmgr_pkg::*;
+(
+ // Clocks and resets
+ input clk_slow_i,
+ input clk_i,
+ input rst_slow_ni,
+ input rst_ni,
+
+ // slow domain signals,
+ input slow_req_pwrup_i,
+ input slow_ack_pwrdn_i,
+ input slow_pwrup_cause_toggle_i,
+ input pwrup_cause_e slow_pwrup_cause_i,
+ output pwrmgr_reg_pkg::pwrmgr_reg2hw_wakeup_en_reg_t slow_wakeup_en_o,
+ output pwrmgr_reg_pkg::pwrmgr_reg2hw_reset_en_reg_t slow_reset_en_o,
+ output logic slow_main_pdb_o,
+ output logic slow_io_clk_en_o,
+ output logic slow_core_clk_en_o,
+ output logic slow_req_pwrdn_o,
+ output logic slow_ack_pwrup_o,
+ output pwr_ast_rsp_t slow_ast_o,
+ output pwr_peri_rsp_t slow_ext_reqs_o,
+ input pwr_peri_rsp_t slow_ext_reqs_masked_i,
+
+ // fast domain signals
+ input req_pwrdn_i,
+ input ack_pwrup_i,
+ input cfg_cdc_sync_i,
+ input pwrmgr_reg_pkg::pwrmgr_reg2hw_wakeup_en_reg_t wakeup_en_i,
+ input pwrmgr_reg_pkg::pwrmgr_reg2hw_reset_en_reg_t reset_en_i,
+ input main_pdb_i,
+ input io_clk_en_i,
+ input core_clk_en_i,
+ output logic ack_pwrdn_o,
+ output logic req_pwrup_o,
+ output pwrup_cause_e pwrup_cause_o,
+ output pwr_peri_rsp_t ext_reqs_o,
+ output logic cdc_sync_done_o,
+
+ // peripheral inputs, mixed domains
+ input pwr_peri_rsp_t peri_i,
+
+ // AST inputs, unknown domain
+ input pwr_ast_rsp_t ast_i
+
+);
+
+  ////////////////////////////////
+  // Sync from clk_i to clk_slow_i
+  ////////////////////////////////
+
+  logic slow_cdc_sync;
+  pwr_ast_rsp_t slow_ast_q, slow_ast_q2;
+
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_req_pwrdn_sync (
+    .clk_i(clk_slow_i),
+    .rst_ni(rst_slow_ni),
+    .d(req_pwrdn_i),
+    .q(slow_req_pwrdn_o)
+  );
+
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_ack_pwrup_sync (
+    .clk_i(clk_slow_i),
+    .rst_ni(rst_slow_ni),
+    .d(ack_pwrup_i),
+    .q(slow_ack_pwrup_o)
+  );
+
+  prim_pulse_sync i_slow_cdc_sync (
+    .clk_src_i(clk_i),
+    .rst_src_ni(rst_ni),
+    .src_pulse_i(cfg_cdc_sync_i),
+    .clk_dst_i(clk_slow_i),
+    .rst_dst_ni(rst_slow_ni),
+    .dst_pulse_o(slow_cdc_sync)
+  );
+
+  // Even though this is multi-bit, the bits are individual request lines.
+  // So there is no general concern about recombining as there is
+  // no intent to use them in a related manner.
+  prim_flop_2sync # (
+    .Width(HwRstReqs + WakeUpPeris)
+  ) i_slow_ext_req_sync (
+    .clk_i  (clk_slow_i),
+    .rst_ni (rst_slow_ni),
+    .d      (peri_i),
+    .q      (slow_ext_reqs_o)
+  );
+
+
+  // Some of the AST signals are multi-bits themselves (such as clk_val)
+  // thus they need to be delayed one more stage to check for stability
+  prim_flop_2sync # (
+    .Width($bits(pwr_ast_rsp_t)),
+    .ResetValue(PWR_AST_RSP_SYNC_DEFAULT)
+  ) i_ast_sync (
+    .clk_i  (clk_slow_i),
+    .rst_ni (rst_slow_ni),
+    .d      (ast_i),
+    .q      (slow_ast_q)
+  );
+
+  always_ff @(posedge clk_slow_i or negedge rst_slow_ni) begin
+    if (!rst_slow_ni) begin
+      slow_ast_q2 <= PWR_AST_RSP_SYNC_DEFAULT;
+    end else begin
+      slow_ast_q2 <= slow_ast_q;
+    end
+  end
+
+  // if possible, we should simulate below with random delays through
+  // flop_2sync
+  always_ff @(posedge clk_slow_i or negedge rst_slow_ni) begin
+    if (!rst_slow_ni) begin
+      slow_ast_o <= PWR_AST_RSP_SYNC_DEFAULT;
+    end else if (slow_ast_q2 == slow_ast_q) begin
+      // Output only updates whenever sync and delayed outputs both agree.
+      // If there are delays in sync, this will result in a 1 cycle difference
+      // and the output will hold the previous value
+      slow_ast_o <= slow_ast_q2;
+    end
+  end
+
+  // only register configurations can be sync'd using slow_cdc_sync
+  always_ff @(posedge clk_slow_i or negedge rst_slow_ni) begin
+    if (!rst_slow_ni) begin
+      slow_wakeup_en_o <= '0;
+      slow_reset_en_o <= '0;
+      slow_main_pdb_o <= '0;
+      slow_io_clk_en_o <= '0;
+      slow_core_clk_en_o <= '0;
+    end else if (slow_cdc_sync) begin
+      slow_wakeup_en_o <= wakeup_en_i;
+      slow_reset_en_o <= reset_en_i;
+      slow_main_pdb_o <= main_pdb_i;
+      slow_io_clk_en_o <= io_clk_en_i;
+      slow_core_clk_en_o <= core_clk_en_i;
+    end
+  end
+
+  ////////////////////////////////
+  // Sync from clk_slow_i to clk_i
+  ////////////////////////////////
+
+  logic pwrup_cause_toggle_q, pwrup_cause_toggle_q2;
+  logic pwrup_cause_chg;
+
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_req_pwrup_sync (
+    .clk_i,
+    .rst_ni,
+    .d(slow_req_pwrup_i),
+    .q(req_pwrup_o)
+  );
+
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_ack_pwrdn_sync (
+    .clk_i,
+    .rst_ni,
+    .d(slow_ack_pwrdn_i),
+    .q(ack_pwrdn_o)
+  );
+
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_pwrup_chg_sync (
+    .clk_i,
+    .rst_ni,
+    .d(slow_pwrup_cause_toggle_i),
+    .q(pwrup_cause_toggle_q)
+  );
+
+  prim_pulse_sync i_scdc_sync (
+    .clk_src_i(clk_slow_i),
+    .rst_src_ni(rst_slow_ni),
+    .src_pulse_i(slow_cdc_sync),
+    .clk_dst_i(clk_i),
+    .rst_dst_ni(rst_ni),
+    .dst_pulse_o(cdc_sync_done_o)
+  );
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      pwrup_cause_toggle_q2 <= 1'b0;
+    end else begin
+      pwrup_cause_toggle_q2 <= pwrup_cause_toggle_q;
+    end
+  end
+
+  assign pwrup_cause_chg = pwrup_cause_toggle_q2 ^ pwrup_cause_toggle_q;
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      pwrup_cause_o <= Por;
+    end else if (pwrup_cause_chg) begin
+      pwrup_cause_o <= slow_pwrup_cause_i;
+    end
+  end
+
+  prim_flop_2sync # (
+    .Width(HwRstReqs + WakeUpPeris)
+  ) i_ext_req_sync (
+    .clk_i,
+    .rst_ni,
+    .d (slow_ext_reqs_masked_i),
+    .q (ext_reqs_o)
+  );
+
+
+endmodule
+
+
+// An alternative solution relying on finding slow clock edges
+// Keep it around just in case
+
+/*
+  // finds a clk_slow edge in clk domain to know when it is safe to sync over
+  // this signal is only safe to use within the pwrmgr module when the source
+  // and destination clock domains are both clear
+  logic cdc_safe;
+
+  // pwrup is synced directly as it acts as a start signal to the pulse module
+  prim_flop_2sync # (
+    .Width(1)
+  ) i_pwrup_sync (
+    .clk_i,
+    .rst_ni,
+    .d(slow_req_pwrup),
+    .q(req_pwrup)
+  );
+
+  pwrmgr_cdc_pulse i_cdc_pulse (
+    .clk_slow_i,
+    .clk_i,
+    .rst_ni,
+    .start_i(req_pwrup),
+    .stop_i(req_pwrdn),
+    .pulse_o(cdc_safe)
+  );
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      ack_pwrdn   <= '0;
+      pwrup_cause <= Por;
+    end else if (cdc_safe) begin
+      ack_pwrdn   <= slow_ack_pwrdn;
+      pwrup_cause <= slow_pwrup_cause;
+    end
+  end
+
+  ////////////////////////////
+  ///  cdc handling - clk_slow_i
+  ////////////////////////////
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      slow_wakeup_en <= '0;
+      slow_reset_en  <= '0;
+      slow_main_pdb  <= '0;
+      slow_io_clk_en <= '0;
+      slow_core_clk_en <= '0;
+      slow_ack_pwrup <= '0;
+      slow_req_pwrdn <= '0;
+    end else if (cdc_safe) begin
+      slow_wakeup_en <= reg2hw.wakeup_en.q;
+      slow_reset_en  <= reg2hw.reset_en.q;
+      slow_main_pdb  <= reg2hw.control.main_pdb.q;
+      slow_io_clk_en <= reg2hw.control.io_clk_en.q;
+      slow_core_clk_en <= reg2hw.control.core_clk_en.q;
+      slow_ack_pwrup <= ack_pwrup;
+      slow_req_pwrdn <= req_pwrdn;
+    end
+  end
+
+  // TODO
+  // Need to vote on the differential signals to ensure they are stable
+  prim_flop_2sync # (
+    .Width($bits(pwr_ast_rsp_t))
+  ) i_pok_sync (
+    .clk_i  (clk_slow_i),
+    .rst_ni (rst_slow_ni),
+    .d      (pwr_ast_i),
+    .q      (slow_ast_q)
+  );
+*/
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_cdc_pulse.sv b/hw/ip/pwrmgr/rtl/pwrmgr_cdc_pulse.sv
index dad86e1..e8391fc 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_cdc_pulse.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_cdc_pulse.sv
@@ -41,7 +41,7 @@
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       valid <= 1'b0;
-    end else if (valid & stop_i) begin
+    end else if (valid && stop_i) begin
       valid <= 1'b0;
     end else if (!valid && toggle && start_i) begin
       valid <= 1'b1;
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
index a50a123..0c263bb 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
@@ -8,45 +8,45 @@
 `include "prim_assert.sv"
 
 module pwrmgr_fsm import pwrmgr_pkg::*; (
-    input clk_i,
-    input rst_ni,
+  input clk_i,
+  input rst_ni,
 
-    // interface with slow_fsm
-    input req_pwrup_i,
-    input pwrup_cause_e pwrup_cause_i,
-    output logic ack_pwrup_o,
-    output logic req_pwrdn_o,
-    input ack_pwrdn_i,
-    input low_power_entry_i,
-    input main_pdb_i,
-    input reset_req_i,
+  // interface with slow_fsm
+  input req_pwrup_i,
+  input pwrup_cause_e pwrup_cause_i,
+  output logic ack_pwrup_o,
+  output logic req_pwrdn_o,
+  input ack_pwrdn_i,
+  input low_power_entry_i,
+  input main_pdb_i,
+  input reset_req_i,
 
-    // consumed in pwrmgr
-    output logic wkup_o,        // generate wake interrupt
-    output logic wkup_record_o, // enable wakeup recording
-    output logic fall_through_o,
-    output logic abort_o,
-    output logic clr_cfg_lock_o,
+  // consumed in pwrmgr
+  output logic wkup_o,        // generate wake interrupt
+  output logic wkup_record_o, // enable wakeup recording
+  output logic fall_through_o,
+  output logic abort_o,
+  output logic clr_cfg_lock_o,
 
-    // rstmgr
-    output pwr_rst_req_t pwr_rst_o,
-    input pwr_rst_rsp_t pwr_rst_i,
+  // rstmgr
+  output pwr_rst_req_t pwr_rst_o,
+  input pwr_rst_rsp_t pwr_rst_i,
 
-    // clkmgr
-    output logic ips_clk_en_o,
+  // clkmgr
+  output logic ips_clk_en_o,
 
-    // otp
-    output logic otp_init_o,
-    input otp_done_i,
-    input otp_idle_i,
+  // otp
+  output logic otp_init_o,
+  input otp_done_i,
+  input otp_idle_i,
 
-    // lc
-    output logic lc_init_o,
-    input lc_done_i,
-    input lc_idle_i,
+  // lc
+  output logic lc_init_o,
+  input lc_done_i,
+  input lc_idle_i,
 
-    // flash
-    input flash_idle_i
+  // flash
+  input flash_idle_i
 );
 
   // state enum
@@ -97,7 +97,7 @@
   logic otp_init;
   logic lc_init;
 
-  assign pdb_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:1] == '0 &&
+  assign pdb_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:1] == '0 &
                              pwr_rst_i.rst_sys_src_n[PowerDomains-1:1] == '0;
 
   assign all_rsts_asserted = pwr_rst_i.rst_lc_src_n == '0 &&
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
index 1db70ea..17e9cf3 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
@@ -37,6 +37,13 @@
     main_pok: 1'b1
   };
 
+  parameter pwr_ast_rsp_t PWR_AST_RSP_SYNC_DEFAULT = '{
+    slow_clk_val: 2'b01,
+    core_clk_val: 2'b01,
+    io_clk_val: 2'b10,
+    main_pok: 1'b0
+  };
+
   // pwrmgr to rstmgr
   typedef struct packed {
     logic [PowerDomains-1:0] lc_rst_req;
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_reg_pkg.sv b/hw/ip/pwrmgr/rtl/pwrmgr_reg_pkg.sv
index c31e224..54a03f2 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_reg_pkg.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_reg_pkg.sv
@@ -23,6 +23,11 @@
   } pwrmgr_reg2hw_intr_test_reg_t;
 
   typedef struct packed {
+    logic        q;
+    logic        qe;
+  } pwrmgr_reg2hw_cfg_cdc_sync_reg_t;
+
+  typedef struct packed {
     struct packed {
       logic        q;
     } low_power_hint;
@@ -72,6 +77,11 @@
 
   typedef struct packed {
     logic        d;
+    logic        de;
+  } pwrmgr_hw2reg_cfg_cdc_sync_reg_t;
+
+  typedef struct packed {
+    logic        d;
   } pwrmgr_hw2reg_ctrl_cfg_regwen_reg_t;
 
   typedef struct packed {
@@ -98,9 +108,10 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    pwrmgr_reg2hw_intr_state_reg_t intr_state; // [47:47]
-    pwrmgr_reg2hw_intr_enable_reg_t intr_enable; // [46:46]
-    pwrmgr_reg2hw_intr_test_reg_t intr_test; // [45:44]
+    pwrmgr_reg2hw_intr_state_reg_t intr_state; // [49:49]
+    pwrmgr_reg2hw_intr_enable_reg_t intr_enable; // [48:48]
+    pwrmgr_reg2hw_intr_test_reg_t intr_test; // [47:46]
+    pwrmgr_reg2hw_cfg_cdc_sync_reg_t cfg_cdc_sync; // [45:44]
     pwrmgr_reg2hw_control_reg_t control; // [43:40]
     pwrmgr_reg2hw_wakeup_en_reg_t wakeup_en; // [39:24]
     pwrmgr_reg2hw_reset_en_reg_t reset_en; // [23:22]
@@ -112,7 +123,8 @@
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    pwrmgr_hw2reg_intr_state_reg_t intr_state; // [22:22]
+    pwrmgr_hw2reg_intr_state_reg_t intr_state; // [24:24]
+    pwrmgr_hw2reg_cfg_cdc_sync_reg_t cfg_cdc_sync; // [23:22]
     pwrmgr_hw2reg_ctrl_cfg_regwen_reg_t ctrl_cfg_regwen; // [21:22]
     pwrmgr_hw2reg_control_reg_t control; // [21:18]
     pwrmgr_hw2reg_wake_info_reg_t wake_info; // [17:-3]
@@ -122,16 +134,17 @@
   parameter logic [5:0] PWRMGR_INTR_STATE_OFFSET = 6'h 0;
   parameter logic [5:0] PWRMGR_INTR_ENABLE_OFFSET = 6'h 4;
   parameter logic [5:0] PWRMGR_INTR_TEST_OFFSET = 6'h 8;
-  parameter logic [5:0] PWRMGR_CTRL_CFG_REGWEN_OFFSET = 6'h c;
-  parameter logic [5:0] PWRMGR_CONTROL_OFFSET = 6'h 10;
-  parameter logic [5:0] PWRMGR_WAKEUP_EN_REGWEN_OFFSET = 6'h 14;
-  parameter logic [5:0] PWRMGR_WAKEUP_EN_OFFSET = 6'h 18;
-  parameter logic [5:0] PWRMGR_WAKE_STATUS_OFFSET = 6'h 1c;
-  parameter logic [5:0] PWRMGR_RESET_EN_REGWEN_OFFSET = 6'h 20;
-  parameter logic [5:0] PWRMGR_RESET_EN_OFFSET = 6'h 24;
-  parameter logic [5:0] PWRMGR_RESET_STATUS_OFFSET = 6'h 28;
-  parameter logic [5:0] PWRMGR_WAKE_INFO_CAPTURE_DIS_OFFSET = 6'h 2c;
-  parameter logic [5:0] PWRMGR_WAKE_INFO_OFFSET = 6'h 30;
+  parameter logic [5:0] PWRMGR_CFG_CDC_SYNC_OFFSET = 6'h c;
+  parameter logic [5:0] PWRMGR_CTRL_CFG_REGWEN_OFFSET = 6'h 10;
+  parameter logic [5:0] PWRMGR_CONTROL_OFFSET = 6'h 14;
+  parameter logic [5:0] PWRMGR_WAKEUP_EN_REGWEN_OFFSET = 6'h 18;
+  parameter logic [5:0] PWRMGR_WAKEUP_EN_OFFSET = 6'h 1c;
+  parameter logic [5:0] PWRMGR_WAKE_STATUS_OFFSET = 6'h 20;
+  parameter logic [5:0] PWRMGR_RESET_EN_REGWEN_OFFSET = 6'h 24;
+  parameter logic [5:0] PWRMGR_RESET_EN_OFFSET = 6'h 28;
+  parameter logic [5:0] PWRMGR_RESET_STATUS_OFFSET = 6'h 2c;
+  parameter logic [5:0] PWRMGR_WAKE_INFO_CAPTURE_DIS_OFFSET = 6'h 30;
+  parameter logic [5:0] PWRMGR_WAKE_INFO_OFFSET = 6'h 34;
 
 
   // Register Index
@@ -139,6 +152,7 @@
     PWRMGR_INTR_STATE,
     PWRMGR_INTR_ENABLE,
     PWRMGR_INTR_TEST,
+    PWRMGR_CFG_CDC_SYNC,
     PWRMGR_CTRL_CFG_REGWEN,
     PWRMGR_CONTROL,
     PWRMGR_WAKEUP_EN_REGWEN,
@@ -152,20 +166,21 @@
   } pwrmgr_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] PWRMGR_PERMIT [13] = '{
+  parameter logic [3:0] PWRMGR_PERMIT [14] = '{
     4'b 0001, // index[ 0] PWRMGR_INTR_STATE
     4'b 0001, // index[ 1] PWRMGR_INTR_ENABLE
     4'b 0001, // index[ 2] PWRMGR_INTR_TEST
-    4'b 0001, // index[ 3] PWRMGR_CTRL_CFG_REGWEN
-    4'b 0001, // index[ 4] PWRMGR_CONTROL
-    4'b 0001, // index[ 5] PWRMGR_WAKEUP_EN_REGWEN
-    4'b 0011, // index[ 6] PWRMGR_WAKEUP_EN
-    4'b 0011, // index[ 7] PWRMGR_WAKE_STATUS
-    4'b 0001, // index[ 8] PWRMGR_RESET_EN_REGWEN
-    4'b 0001, // index[ 9] PWRMGR_RESET_EN
-    4'b 0001, // index[10] PWRMGR_RESET_STATUS
-    4'b 0001, // index[11] PWRMGR_WAKE_INFO_CAPTURE_DIS
-    4'b 0111  // index[12] PWRMGR_WAKE_INFO
+    4'b 0001, // index[ 3] PWRMGR_CFG_CDC_SYNC
+    4'b 0001, // index[ 4] PWRMGR_CTRL_CFG_REGWEN
+    4'b 0001, // index[ 5] PWRMGR_CONTROL
+    4'b 0001, // index[ 6] PWRMGR_WAKEUP_EN_REGWEN
+    4'b 0011, // index[ 7] PWRMGR_WAKEUP_EN
+    4'b 0011, // index[ 8] PWRMGR_WAKE_STATUS
+    4'b 0001, // index[ 9] PWRMGR_RESET_EN_REGWEN
+    4'b 0001, // index[10] PWRMGR_RESET_EN
+    4'b 0001, // index[11] PWRMGR_RESET_STATUS
+    4'b 0001, // index[12] PWRMGR_WAKE_INFO_CAPTURE_DIS
+    4'b 0111  // index[13] PWRMGR_WAKE_INFO
   };
 endpackage
 
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_reg_top.sv b/hw/ip/pwrmgr/rtl/pwrmgr_reg_top.sv
index 4e567f0..7a63697 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_reg_top.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_reg_top.sv
@@ -79,6 +79,8 @@
   logic intr_enable_we;
   logic intr_test_wd;
   logic intr_test_we;
+  logic cfg_cdc_sync_wd;
+  logic cfg_cdc_sync_we;
   logic ctrl_cfg_regwen_qs;
   logic ctrl_cfg_regwen_wd;
   logic ctrl_cfg_regwen_we;
@@ -196,6 +198,32 @@
   );
 
 
+  // R[cfg_cdc_sync]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("WO"),
+    .RESVAL  (1'h0)
+  ) u_cfg_cdc_sync (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (cfg_cdc_sync_we),
+    .wd     (cfg_cdc_sync_wd),
+
+    // from internal hardware
+    .de     (hw2reg.cfg_cdc_sync.de),
+    .d      (hw2reg.cfg_cdc_sync.d ),
+
+    // to internal hardware
+    .qe     (reg2hw.cfg_cdc_sync.qe),
+    .q      (reg2hw.cfg_cdc_sync.q ),
+
+    .qs     ()
+  );
+
+
   // R[ctrl_cfg_regwen]: V(True)
 
   prim_subreg_ext #(
@@ -514,22 +542,23 @@
 
 
 
-  logic [12:0] addr_hit;
+  logic [13:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[ 0] = (reg_addr == PWRMGR_INTR_STATE_OFFSET);
     addr_hit[ 1] = (reg_addr == PWRMGR_INTR_ENABLE_OFFSET);
     addr_hit[ 2] = (reg_addr == PWRMGR_INTR_TEST_OFFSET);
-    addr_hit[ 3] = (reg_addr == PWRMGR_CTRL_CFG_REGWEN_OFFSET);
-    addr_hit[ 4] = (reg_addr == PWRMGR_CONTROL_OFFSET);
-    addr_hit[ 5] = (reg_addr == PWRMGR_WAKEUP_EN_REGWEN_OFFSET);
-    addr_hit[ 6] = (reg_addr == PWRMGR_WAKEUP_EN_OFFSET);
-    addr_hit[ 7] = (reg_addr == PWRMGR_WAKE_STATUS_OFFSET);
-    addr_hit[ 8] = (reg_addr == PWRMGR_RESET_EN_REGWEN_OFFSET);
-    addr_hit[ 9] = (reg_addr == PWRMGR_RESET_EN_OFFSET);
-    addr_hit[10] = (reg_addr == PWRMGR_RESET_STATUS_OFFSET);
-    addr_hit[11] = (reg_addr == PWRMGR_WAKE_INFO_CAPTURE_DIS_OFFSET);
-    addr_hit[12] = (reg_addr == PWRMGR_WAKE_INFO_OFFSET);
+    addr_hit[ 3] = (reg_addr == PWRMGR_CFG_CDC_SYNC_OFFSET);
+    addr_hit[ 4] = (reg_addr == PWRMGR_CTRL_CFG_REGWEN_OFFSET);
+    addr_hit[ 5] = (reg_addr == PWRMGR_CONTROL_OFFSET);
+    addr_hit[ 6] = (reg_addr == PWRMGR_WAKEUP_EN_REGWEN_OFFSET);
+    addr_hit[ 7] = (reg_addr == PWRMGR_WAKEUP_EN_OFFSET);
+    addr_hit[ 8] = (reg_addr == PWRMGR_WAKE_STATUS_OFFSET);
+    addr_hit[ 9] = (reg_addr == PWRMGR_RESET_EN_REGWEN_OFFSET);
+    addr_hit[10] = (reg_addr == PWRMGR_RESET_EN_OFFSET);
+    addr_hit[11] = (reg_addr == PWRMGR_RESET_STATUS_OFFSET);
+    addr_hit[12] = (reg_addr == PWRMGR_WAKE_INFO_CAPTURE_DIS_OFFSET);
+    addr_hit[13] = (reg_addr == PWRMGR_WAKE_INFO_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -550,6 +579,7 @@
     if (addr_hit[10] && reg_we && (PWRMGR_PERMIT[10] != (PWRMGR_PERMIT[10] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[11] && reg_we && (PWRMGR_PERMIT[11] != (PWRMGR_PERMIT[11] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[12] && reg_we && (PWRMGR_PERMIT[12] != (PWRMGR_PERMIT[12] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[13] && reg_we && (PWRMGR_PERMIT[13] != (PWRMGR_PERMIT[13] & reg_be))) wr_err = 1'b1 ;
   end
 
   assign intr_state_we = addr_hit[0] & reg_we & ~wr_err;
@@ -561,50 +591,53 @@
   assign intr_test_we = addr_hit[2] & reg_we & ~wr_err;
   assign intr_test_wd = reg_wdata[0];
 
-  assign ctrl_cfg_regwen_we = addr_hit[3] & reg_we & ~wr_err;
-  assign ctrl_cfg_regwen_wd = reg_wdata[0];
-  assign ctrl_cfg_regwen_re = addr_hit[3] && reg_re;
+  assign cfg_cdc_sync_we = addr_hit[3] & reg_we & ~wr_err;
+  assign cfg_cdc_sync_wd = reg_wdata[0];
 
-  assign control_low_power_hint_we = addr_hit[4] & reg_we & ~wr_err;
+  assign ctrl_cfg_regwen_we = addr_hit[4] & reg_we & ~wr_err;
+  assign ctrl_cfg_regwen_wd = reg_wdata[0];
+  assign ctrl_cfg_regwen_re = addr_hit[4] && reg_re;
+
+  assign control_low_power_hint_we = addr_hit[5] & reg_we & ~wr_err;
   assign control_low_power_hint_wd = reg_wdata[0];
 
-  assign control_core_clk_en_we = addr_hit[4] & reg_we & ~wr_err;
+  assign control_core_clk_en_we = addr_hit[5] & reg_we & ~wr_err;
   assign control_core_clk_en_wd = reg_wdata[4];
 
-  assign control_io_clk_en_we = addr_hit[4] & reg_we & ~wr_err;
+  assign control_io_clk_en_we = addr_hit[5] & reg_we & ~wr_err;
   assign control_io_clk_en_wd = reg_wdata[5];
 
-  assign control_main_pdb_we = addr_hit[4] & reg_we & ~wr_err;
+  assign control_main_pdb_we = addr_hit[5] & reg_we & ~wr_err;
   assign control_main_pdb_wd = reg_wdata[6];
 
-  assign wakeup_en_regwen_we = addr_hit[5] & reg_we & ~wr_err;
+  assign wakeup_en_regwen_we = addr_hit[6] & reg_we & ~wr_err;
   assign wakeup_en_regwen_wd = reg_wdata[0];
 
-  assign wakeup_en_we = addr_hit[6] & reg_we & ~wr_err;
+  assign wakeup_en_we = addr_hit[7] & reg_we & ~wr_err;
   assign wakeup_en_wd = reg_wdata[15:0];
 
 
-  assign reset_en_regwen_we = addr_hit[8] & reg_we & ~wr_err;
+  assign reset_en_regwen_we = addr_hit[9] & reg_we & ~wr_err;
   assign reset_en_regwen_wd = reg_wdata[0];
 
-  assign reset_en_we = addr_hit[9] & reg_we & ~wr_err;
+  assign reset_en_we = addr_hit[10] & reg_we & ~wr_err;
   assign reset_en_wd = reg_wdata[1:0];
 
 
-  assign wake_info_capture_dis_we = addr_hit[11] & reg_we & ~wr_err;
+  assign wake_info_capture_dis_we = addr_hit[12] & reg_we & ~wr_err;
   assign wake_info_capture_dis_wd = reg_wdata[0];
 
-  assign wake_info_reasons_we = addr_hit[12] & reg_we & ~wr_err;
+  assign wake_info_reasons_we = addr_hit[13] & reg_we & ~wr_err;
   assign wake_info_reasons_wd = reg_wdata[15:0];
-  assign wake_info_reasons_re = addr_hit[12] && reg_re;
+  assign wake_info_reasons_re = addr_hit[13] && reg_re;
 
-  assign wake_info_fall_through_we = addr_hit[12] & reg_we & ~wr_err;
+  assign wake_info_fall_through_we = addr_hit[13] & reg_we & ~wr_err;
   assign wake_info_fall_through_wd = reg_wdata[16];
-  assign wake_info_fall_through_re = addr_hit[12] && reg_re;
+  assign wake_info_fall_through_re = addr_hit[13] && reg_re;
 
-  assign wake_info_abort_we = addr_hit[12] & reg_we & ~wr_err;
+  assign wake_info_abort_we = addr_hit[13] & reg_we & ~wr_err;
   assign wake_info_abort_wd = reg_wdata[17];
-  assign wake_info_abort_re = addr_hit[12] && reg_re;
+  assign wake_info_abort_re = addr_hit[13] && reg_re;
 
   // Read data return
   always_comb begin
@@ -623,45 +656,49 @@
       end
 
       addr_hit[3]: begin
-        reg_rdata_next[0] = ctrl_cfg_regwen_qs;
+        reg_rdata_next[0] = '0;
       end
 
       addr_hit[4]: begin
+        reg_rdata_next[0] = ctrl_cfg_regwen_qs;
+      end
+
+      addr_hit[5]: begin
         reg_rdata_next[0] = control_low_power_hint_qs;
         reg_rdata_next[4] = control_core_clk_en_qs;
         reg_rdata_next[5] = control_io_clk_en_qs;
         reg_rdata_next[6] = control_main_pdb_qs;
       end
 
-      addr_hit[5]: begin
+      addr_hit[6]: begin
         reg_rdata_next[0] = wakeup_en_regwen_qs;
       end
 
-      addr_hit[6]: begin
+      addr_hit[7]: begin
         reg_rdata_next[15:0] = wakeup_en_qs;
       end
 
-      addr_hit[7]: begin
+      addr_hit[8]: begin
         reg_rdata_next[15:0] = wake_status_qs;
       end
 
-      addr_hit[8]: begin
+      addr_hit[9]: begin
         reg_rdata_next[0] = reset_en_regwen_qs;
       end
 
-      addr_hit[9]: begin
+      addr_hit[10]: begin
         reg_rdata_next[1:0] = reset_en_qs;
       end
 
-      addr_hit[10]: begin
+      addr_hit[11]: begin
         reg_rdata_next[1:0] = reset_status_qs;
       end
 
-      addr_hit[11]: begin
+      addr_hit[12]: begin
         reg_rdata_next[0] = wake_info_capture_dis_qs;
       end
 
-      addr_hit[12]: begin
+      addr_hit[13]: begin
         reg_rdata_next[15:0] = wake_info_reasons_qs;
         reg_rdata_next[16] = wake_info_fall_through_qs;
         reg_rdata_next[17] = wake_info_abort_qs;
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
index be2e78c..c080250 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
@@ -17,6 +17,7 @@
 
   // interface with fast fsm
   output logic req_pwrup_o,
+  output logic pwrup_cause_toggle_o,
   output pwrup_cause_e pwrup_cause_o,
   input ack_pwrup_i,
   input req_pwrdn_i,
@@ -47,6 +48,7 @@
 
   state_e state_q, state_d;
   pwrup_cause_e cause_q, cause_d;
+  logic cause_toggle_q, cause_toggle_d;
 
   // All power signals and signals going to analog logic are flopped to avoid transitioanl glitches
   logic pdb_q, pdb_d;
@@ -54,6 +56,7 @@
   logic core_clk_en_q, core_clk_en_d;
   logic io_clk_en_q, io_clk_en_d;
 
+
   logic all_clks_valid;
   logic all_clks_invalid;
 
@@ -65,32 +68,35 @@
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
-      state_q       <= StReset;
-      cause_q       <= Por;
-      pdb_q         <= 1'b0;
-      pwr_clamp_q   <= 1'b1;
-      core_clk_en_q <= 1'b0;
-      io_clk_en_q   <= 1'b0;
+      state_q        <= StReset;
+      cause_q        <= Por;
+      cause_toggle_q <= 1'b0;
+      pdb_q          <= 1'b0;
+      pwr_clamp_q    <= 1'b1;
+      core_clk_en_q  <= 1'b0;
+      io_clk_en_q    <= 1'b0;
     end else begin
-      state_q       <= state_d;
-      cause_q       <= cause_d;
-      pdb_q         <= pdb_d;
-      pwr_clamp_q   <= pwr_clamp_d;
-      core_clk_en_q <= core_clk_en_d;
-      io_clk_en_q   <= io_clk_en_d;
+      state_q        <= state_d;
+      cause_q        <= cause_d;
+      cause_toggle_q <= cause_toggle_d;
+      pdb_q          <= pdb_d;
+      pwr_clamp_q    <= pwr_clamp_d;
+      core_clk_en_q  <= core_clk_en_d;
+      io_clk_en_q    <= io_clk_en_d;
     end
   end
 
   always_comb begin
-    state_d       = state_q;
-    cause_d       = cause_q;
-    pdb_d         = pdb_q;
-    pwr_clamp_d   = pwr_clamp_q;
-    core_clk_en_d = core_clk_en_q;
-    io_clk_en_d   = io_clk_en_q;
+    state_d        = state_q;
+    cause_d        = cause_q;
+    pdb_d          = pdb_q;
+    cause_toggle_d = cause_toggle_q;
+    pwr_clamp_d    = pwr_clamp_q;
+    core_clk_en_d  = core_clk_en_q;
+    io_clk_en_d    = io_clk_en_q;
 
-    req_pwrup_o   = 1'b0;
-    ack_pwrdn_o   = 1'b0;
+    req_pwrup_o    = 1'b0;
+    ack_pwrdn_o    = 1'b0;
 
     unique case(state_q)
 
@@ -104,6 +110,7 @@
         // different
         if (wakeup_i || reset_req_i) begin
           state_d = StMainPowerOn;
+          cause_toggle_d = ~cause_toggle_q;
           cause_d = reset_req_i ? Reset : Wake;
         end
       end
@@ -183,6 +190,7 @@
 
 
   assign pwrup_cause_o = cause_q;
+  assign pwrup_cause_toggle_o = cause_toggle_q;
 
   assign ast_o.core_clk_en = core_clk_en_q;
   assign ast_o.io_clk_en = io_clk_en_q;