[top] Ast updates

- connect jitter enable
- connect differential scanmode signal

Signed-off-by: Timothy Chen <timothytim@google.com>

fixup! [top] Ast updates
diff --git a/hw/ip/clkmgr/data/clkmgr.hjson.tpl b/hw/ip/clkmgr/data/clkmgr.hjson.tpl
index cddbb91..2e83927 100644
--- a/hw/ip/clkmgr/data/clkmgr.hjson.tpl
+++ b/hw/ip/clkmgr/data/clkmgr.hjson.tpl
@@ -62,6 +62,13 @@
       package: "lc_ctrl_pkg",
     },
 
+    { struct:  "logic",
+      type:    "uni",
+      name:    "jitter_en",
+      act:     "req",
+      package: ""
+    },
+
   // All clock inputs
 % for src in srcs:
     { struct:  "logic",
@@ -99,6 +106,22 @@
 
 
   registers: [
+    { name: "JITTER_ENABLE",
+      desc: '''
+        Enable jittery clock
+      ''',
+      swaccess: "rw",
+      hwaccess: "hro",
+      fields: [
+        {
+          bits: "0",
+          name: "VAL",
+          desc: "Enable jittery clock"
+          resval: "0"
+        }
+      ]
+    },
+
     { name: "CLK_ENABLES",
       desc: '''
         Clock enable for software gateable clocks.
diff --git a/hw/ip/clkmgr/data/clkmgr.sv.tpl b/hw/ip/clkmgr/data/clkmgr.sv.tpl
index 03c708f..84e03df 100644
--- a/hw/ip/clkmgr/data/clkmgr.sv.tpl
+++ b/hw/ip/clkmgr/data/clkmgr.sv.tpl
@@ -41,7 +41,7 @@
   output pwrmgr_pkg::pwr_clk_rsp_t pwr_o,
 
   // dft interface
-  input scanmode_i,
+  input lc_ctrl_pkg::lc_tx_t scanmode_i,
 
   // idle hints
   input [${len(hint_clks)-1}:0] idle_i,
@@ -50,6 +50,9 @@
   input lc_ctrl_pkg::lc_tx_t ast_clk_bypass_ack_i,
   output lc_ctrl_pkg::lc_tx_t lc_clk_bypass_ack_o,
 
+  // jittery enable
+  output logic jitter_en_o,
+
   // clock output interface
 % for intf in export_clks:
   output clkmgr_${intf}_out_t clocks_${intf}_o,
@@ -94,6 +97,18 @@
 % endfor
 
 % for src in div_srcs:
+
+  lc_ctrl_pkg::lc_tx_t ${src['name']}_div_scanmode;
+  prim_lc_sync #(
+    .NumCopies(1),
+    .AsyncOn(0)
+  ) u_${src['name']}_div_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(${src['name']}_div_scanmode)
+  );
+
   prim_clock_div #(
     .Divisor(${src['div']})
   ) u_${src['name']}_div (
@@ -101,7 +116,7 @@
     .rst_ni(rst_${src['src']}_ni),
     .step_down_req_i(step_down_req == lc_ctrl_pkg::On),
     .step_down_ack_o(step_down_acks[${loop.index}]),
-    .test_en_i(scanmode_i),
+    .test_en_i(${src['name']}_div_scanmode == lc_ctrl_pkg::On),
     .clk_o(clk_${src['name']}_i)
   );
 % endfor
@@ -143,10 +158,21 @@
 % endfor
 
 % for src in rg_srcs:
+  lc_ctrl_pkg::lc_tx_t ${src}_scanmode;
+  prim_lc_sync #(
+    .NumCopies(1),
+    .AsyncOn(0)
+  ) u_${src}_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(${src}_scanmode)
+  );
+
   prim_clock_gating_sync u_${src}_cg (
     .clk_i(clk_${src}_i),
     .rst_ni(rst_${src}_ni),
-    .test_en_i(scanmode_i),
+    .test_en_i(${src}_scanmode == lc_ctrl_pkg::On),
     .async_en_i(pwr_i.ip_clk_en),
     .en_o(clk_${src}_en),
     .clk_o(clk_${src}_root)
@@ -240,12 +266,23 @@
     .q_o(${k}_sw_en)
   );
 
+  lc_ctrl_pkg::lc_tx_t ${k}_scanmode;
+  prim_lc_sync #(
+    .NumCopies(1),
+    .AsyncOn(0)
+  ) u_${k}_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(${k}_scanmode)
+  );
+
   prim_clock_gating #(
     .NoFpgaGate(1'b1)
   ) u_${k}_cg (
     .clk_i(clk_${v}_root),
     .en_i(${k}_sw_en & clk_${v}_en),
-    .test_en_i(scanmode_i),
+    .test_en_i(${k}_scanmode == lc_ctrl_pkg::On),
     .clk_o(clocks_o.${k})
   );
 
@@ -274,12 +311,23 @@
     .q_o(${k}_hint)
   );
 
+  lc_ctrl_pkg::lc_tx_t ${k}_scanmode;
+  prim_lc_sync #(
+    .NumCopies(1),
+    .AsyncOn(0)
+  ) u_${k}_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(${k}_scanmode)
+  );
+
   prim_clock_gating #(
     .NoFpgaGate(1'b1)
   ) u_${k}_cg (
     .clk_i(clk_${v["src"]}_root),
     .en_i(${k}_en & clk_${v["src"]}_en),
-    .test_en_i(scanmode_i),
+    .test_en_i(${k}_scanmode == lc_ctrl_pkg::On),
     .clk_o(clocks_o.${k})
   );
 
@@ -291,6 +339,8 @@
   assign hw2reg.clk_hints_status.${k}_val.d = ${k}_en;
 % endfor
 
+  assign jitter_en_o = reg2hw.jitter_enable.q;
+
   ////////////////////////////////////////////////////
   // Exported clocks
   ////////////////////////////////////////////////////
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index 3c78579..2fa2f2c 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -21,7 +21,7 @@
   output logic host_rderr_o,
   input flash_req_t flash_ctrl_i,
   output flash_rsp_t flash_ctrl_o,
-  input scanmode_i,
+  input lc_ctrl_pkg::lc_tx_t scanmode_i,
   input scan_en_i,
   input scan_rst_ni,
   input flash_power_ready_h_i,
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
index f22d83a..a79a91b 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
@@ -30,7 +30,7 @@
   input  jtag_pkg::jtag_req_t                        jtag_i,
   output jtag_pkg::jtag_rsp_t                        jtag_o,
   // This bypasses the clock inverter inside the JTAG TAP for scanmmode.
-  input                                              scanmode_i,
+  input  lc_tx_t                                     scanmode_i,
   // Alert outputs.
   input  prim_alert_pkg::alert_rx_t [NumAlerts-1:0]  alert_rx_i,
   output prim_alert_pkg::alert_tx_t [NumAlerts-1:0]  alert_tx_o,
@@ -147,7 +147,7 @@
   ) u_dmi_jtag (
     .clk_i,
     .rst_ni,
-    .testmode_i       ( scanmode_i        ),
+    .testmode_i       ( scanmode_i == On  ),
     .dmi_rst_no       (                   ), // unused
     .dmi_req_o        ( dmi_req           ),
     .dmi_req_valid_o  ( dmi_req_valid     ),
diff --git a/hw/ip/prim_generic/rtl/prim_generic_flash.sv b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
index 0529b10..2a744ec 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_flash.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
@@ -27,7 +27,7 @@
   input tms_i,
   output logic tdo_o,
   input lc_ctrl_pkg::lc_tx_t bist_enable_i,
-  input scanmode_i,
+  input lc_ctrl_pkg::lc_tx_t scanmode_i,
   input scan_en_i,
   input scan_rst_ni,
   input flash_power_ready_h_i,
@@ -99,7 +99,7 @@
     );
   end
 
-  logic unused_scanmode;
+  lc_ctrl_pkg::lc_tx_t unused_scanmode;
   logic unused_scan_en;
   logic unused_scan_rst_n;
   logic [TestModeWidth-1:0] unused_flash_test_mode;
diff --git a/hw/ip/rstmgr/data/rstmgr.sv.tpl b/hw/ip/rstmgr/data/rstmgr.sv.tpl
index 7419582..1825d9d 100644
--- a/hw/ip/rstmgr/data/rstmgr.sv.tpl
+++ b/hw/ip/rstmgr/data/rstmgr.sv.tpl
@@ -37,7 +37,7 @@
 
   // dft bypass
   input scan_rst_ni,
-  input scanmode_i,
+  input lc_ctrl_pkg::lc_tx_t scanmode_i,
 
   // reset outputs
 % for intf in export_rsts:
@@ -53,14 +53,26 @@
   // The por is at first stretched and synced on clk_aon
   // The rst_ni and pok_i input will be changed once AST is integrated
   logic [PowerDomains-1:0] rst_por_aon_n;
+  lc_ctrl_pkg::lc_tx_t [1:0] por_aon_scanmode;
 
   for (genvar i = 0; i < PowerDomains; i++) begin : gen_rst_por_aon
     if (i == DomainAonSel) begin : gen_rst_por_aon_normal
+
+      prim_lc_sync #(
+        .NumCopies(2),
+        .AsyncOn(0)
+      ) u_por_scanmode_sync  (
+        .clk_i,
+        .rst_ni,
+        .lc_en_i(scanmode_i),
+        .lc_en_o(por_aon_scanmode)
+      );
+
       rstmgr_por u_rst_por_aon (
         .clk_i(clk_aon_i),
         .rst_ni(ast_i.aon_pok),
         .scan_rst_ni,
-        .scanmode_i,
+        .scanmode_i(por_aon_scanmode[0] == lc_ctrl_pkg::On),
         .rst_no(rst_por_aon_n[i])
       );
 
@@ -69,7 +81,7 @@
       ) u_rst_por_aon_n_mux (
         .clk0_i(rst_por_aon_n[i]),
         .clk1_i(scan_rst_ni),
-        .sel_i(scanmode_i),
+        .sel_i(por_aon_scanmode[1] == lc_ctrl_pkg::On),
         .clk_o(resets_o.rst_por_aon_n[i])
       );
     end else begin : gen_rst_por_aon_tieoff
@@ -189,7 +201,18 @@
   // To simplify generation, each reset generates all associated power domain outputs.
   // If a reset does not support a particular power domain, that reset is always hard-wired to 0.
 
-% for rst in leaf_rsts:
+  lc_ctrl_pkg::lc_tx_t [${len(leaf_rsts)-1}:0] leaf_rst_scanmode;
+  prim_lc_sync #(
+    .NumCopies(${len(leaf_rsts)}),
+    .AsyncOn(0)
+    ) u_leaf_rst_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(leaf_rst_scanmode)
+ );
+
+% for i, rst in enumerate(leaf_rsts):
   logic [PowerDomains-1:0] rst_${rst['name']}_n;
   % for domain in power_domains:
     % if domain in rst['domains']:
@@ -212,7 +235,7 @@
   ) u_${domain.lower()}_${rst['name']}_mux (
     .clk0_i(rst_${rst['name']}_n[Domain${domain}Sel]),
     .clk1_i(scan_rst_ni),
-    .sel_i(scanmode_i),
+    .sel_i(leaf_rst_scanmode[${i}] == lc_ctrl_pkg::On),
     .clk_o(resets_o.rst_${rst['name']}_n[Domain${domain}Sel])
   );
 
diff --git a/hw/ip/spi_device/data/spi_device.hjson b/hw/ip/spi_device/data/spi_device.hjson
index 383c29f..50ee822 100644
--- a/hw/ip/spi_device/data/spi_device.hjson
+++ b/hw/ip/spi_device/data/spi_device.hjson
@@ -20,7 +20,8 @@
     { name: "rxoverflow",  desc: "RX Async FIFO overflow" },
     { name: "txunderflow", desc: "TX Async FIFO underflow" },
   ],
-  scan: "true", // Enable `scanmode_i` port
+  scan: "true",       // Enable `scanmode_i` port
+  scan_reset: "true", // Enable `scan_rst_ni` port
   regwidth: "32",
   registers: [
     { name: "CONTROL",
diff --git a/hw/ip/spi_device/dv/tb/tb.sv b/hw/ip/spi_device/dv/tb/tb.sv
index 8d0cbea..6e5338d 100644
--- a/hw/ip/spi_device/dv/tb/tb.sv
+++ b/hw/ip/spi_device/dv/tb/tb.sv
@@ -58,7 +58,7 @@
     .intr_rxerr_o   (intr_rxerr),
     .intr_rxoverflow_o (intr_rxoverflow),
     .intr_txunderflow_o(intr_txunderflow),
-    .scanmode_i     (1'b0      )
+    .scanmode_i     (lc_ctrl_pkg::Off)
   );
 
   assign sck          = spi_if.sck;
diff --git a/hw/ip/spi_device/rtl/spi_device.sv b/hw/ip/spi_device/rtl/spi_device.sv
index 0be22c4..b4fcb4a 100644
--- a/hw/ip/spi_device/rtl/spi_device.sv
+++ b/hw/ip/spi_device/rtl/spi_device.sv
@@ -30,7 +30,8 @@
   output logic intr_rxoverflow_o,  // RX Async FIFO Overflow
   output logic intr_txunderflow_o, // TX Async FIFO Underflow
 
-  input scanmode_i
+  input scan_rst_ni,
+  input lc_ctrl_pkg::lc_tx_t scanmode_i
 );
 
   import spi_device_pkg::*;
@@ -320,8 +321,24 @@
   //  doesn't exist until it transmits data through SDI
   logic sck_n;
   logic rst_spi_n;
+  lc_ctrl_pkg::lc_tx_t [ScanModeUseLast-1:0] scanmode;
 
-  prim_clock_inv u_clk_spi (.clk_i(cio_sck_i), .clk_no(sck_n), .scanmode_i);
+  prim_lc_sync #(
+    .NumCopies(int'(ScanModeUseLast)),
+    .AsyncOn(0)
+  ) u_scanmode_sync  (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i(scanmode_i),
+    .lc_en_o(scanmode)
+  );
+
+  prim_clock_inv u_clk_spi (
+    .clk_i(cio_sck_i),
+    .clk_no(sck_n),
+    .scanmode_i(scanmode[ClkInvSel] == lc_ctrl_pkg::On)
+  );
+
   assign clk_spi_in  = (cpha ^ cpol) ? sck_n    : cio_sck_i   ;
   assign clk_spi_out = (cpha ^ cpol) ? cio_sck_i    : sck_n   ;
 
@@ -334,11 +351,32 @@
     .clk_o (clk_spi_out_buf)
   );
 
-  assign rst_spi_n = (scanmode_i) ? rst_ni : rst_ni & ~cio_csb_i;
+  prim_clock_mux2 #(
+    .NoFpgaBufG(1'b1)
+  ) u_csb_rst_scan_mux (
+    .clk0_i(rst_ni & ~cio_csb_i),
+    .clk1_i(scan_rst_ni),
+    .sel_i(scanmode[CsbRstMuxSel] == lc_ctrl_pkg::On),
+    .clk_o(rst_spi_n)
+  );
 
-  assign rst_txfifo_n = (scanmode_i) ? rst_ni : rst_ni & ~rst_txfifo_reg;
-  assign rst_rxfifo_n = (scanmode_i) ? rst_ni : rst_ni & ~rst_rxfifo_reg;
+  prim_clock_mux2 #(
+    .NoFpgaBufG(1'b1)
+  ) u_tx_rst_scan_mux (
+    .clk0_i(rst_ni & ~rst_txfifo_reg),
+    .clk1_i(scan_rst_ni),
+    .sel_i(scanmode[TxRstMuxSel] == lc_ctrl_pkg::On),
+    .clk_o(rst_txfifo_n)
+  );
 
+  prim_clock_mux2 #(
+    .NoFpgaBufG(1'b1)
+  ) u_rx_rst_scan_mux (
+    .clk0_i(rst_ni & ~rst_rxfifo_reg),
+    .clk1_i(scan_rst_ni),
+    .sel_i(scanmode[RxRstMuxSel] == lc_ctrl_pkg::On),
+    .clk_o(rst_rxfifo_n)
+  );
 
   //////////////////////////////
   // SPI_DEVICE mode selector //
diff --git a/hw/ip/spi_device/rtl/spi_device_pkg.sv b/hw/ip/spi_device/rtl/spi_device_pkg.sv
index a2932f8..63abd6d 100644
--- a/hw/ip/spi_device/rtl/spi_device_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_pkg.sv
@@ -68,7 +68,6 @@
     QdRd   = 8'h6B    // Quad Read
   } spi_rom_cmd_e;
 
-
   // Sram parameters
   parameter int unsigned SramDw = 32;
 
@@ -94,4 +93,13 @@
 
   parameter int unsigned SramAw = $clog2(SramDepth);
 
+  // spi device scanmode usage
+  typedef enum logic [2:0] {
+    ClkInvSel,
+    CsbRstMuxSel,
+    TxRstMuxSel,
+    RxRstMuxSel,
+    ScanModeUseLast
+  } scan_mode_e;
+
 endpackage : spi_device_pkg
diff --git a/hw/ip/spi_device/spi_device.core b/hw/ip/spi_device/spi_device.core
index b2c3a58..3e24d3b 100644
--- a/hw/ip/spi_device/spi_device.core
+++ b/hw/ip/spi_device/spi_device.core
@@ -14,6 +14,8 @@
       - lowrisc:prim:clock_gating
       - lowrisc:prim:clock_inv
       - lowrisc:prim:ram_2p_adv
+      - lowrisc:ip:lc_ctrl_pkg
+      - lowrisc:prim:lc_sync
     files:
       - rtl/spi_device_reg_pkg.sv
       - rtl/spi_device_reg_top.sv