[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