[clkmgr] Fix dft issues
Addresses #5452 and #5453
- force step_down_req to 0 when in test mode
- It is assumed the flops inside prim_clock_div are off the scan chain
- remove bypass mux functionality when in test mode. The mux itself is
still kept as a constraint anchor point.
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/clkmgr/data/clkmgr.sv.tpl b/hw/ip/clkmgr/data/clkmgr.sv.tpl
index 3b89175..aa05c43 100644
--- a/hw/ip/clkmgr/data/clkmgr.sv.tpl
+++ b/hw/ip/clkmgr/data/clkmgr.sv.tpl
@@ -112,7 +112,7 @@
prim_clock_div #(
.Divisor(${src['div']})
- ) u_${src['name']}_div (
+ ) u_no_scan_${src['name']}_div (
.clk_i(clk_${src['src']}_i),
.rst_ni(rst_${src['src']}_ni),
.step_down_req_i(step_down_req == lc_ctrl_pkg::On),
diff --git a/hw/ip/prim/rtl/prim_clock_div.sv b/hw/ip/prim/rtl/prim_clock_div.sv
index 838d146..4d057fe 100644
--- a/hw/ip/prim/rtl/prim_clock_div.sv
+++ b/hw/ip/prim/rtl/prim_clock_div.sv
@@ -21,6 +21,11 @@
// For odd divide we need to introduce more parameters to control duty cycle
`ASSERT_INIT(DivEven_A, (Divisor % 2) == 0)
+ // It is assumed the flops in this module are NOT on the scan-chain, as a result only
+ // the input values are guarded
+ logic step_down_req;
+ assign step_down_req = test_en_i ? '0 : step_down_req_i;
+
logic clk_int;
if (Divisor == 2) begin : gen_div2
@@ -49,7 +54,7 @@
if (!rst_ni) begin
step_down_nq <= 1'b0;
end else begin
- step_down_nq <= step_down_req_i;
+ step_down_nq <= step_down_req;
end
end
@@ -72,7 +77,7 @@
logic [CntWidth-1:0] cnt;
logic [CntWidth-1:0] limit;
- assign limit = !step_down_req_i ? ToggleCnt - 1 :
+ assign limit = !step_down_req ? ToggleCnt - 1 :
(ToggleCnt / 2) == 2 ? '0 : (ToggleCnt / 2) - 1;
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -91,25 +96,22 @@
if (!rst_ni) begin
step_down_ack_o <= 1'b0;
end else begin
- step_down_ack_o <= step_down_req_i;
+ step_down_ack_o <= step_down_req;
end
end
end
- // when in scanmode, bypass the dividers completely
- // also anchor point for constraints
+ // anchor points for constraints
logic clk_muxed;
-
prim_clock_mux2 #(
.NoFpgaBufG(1'b1)
) u_clk_mux (
.clk0_i(clk_int),
.clk1_i(clk_i),
- .sel_i(test_en_i),
+ .sel_i('0),
.clk_o(clk_muxed)
);
- // anchor point for constraints
prim_clock_buf u_clk_div_buf (
.clk_i(clk_muxed),
.clk_o
diff --git a/hw/top_earlgrey/data/clocks.xdc b/hw/top_earlgrey/data/clocks.xdc
index 4fe896e..2c6c90b 100644
--- a/hw/top_earlgrey/data/clocks.xdc
+++ b/hw/top_earlgrey/data/clocks.xdc
@@ -15,10 +15,10 @@
## destination flops few enough.
set u_pll clkgen/pll
-set u_div2 top_*/u_clkmgr_aon/u_io_div2_div
+set u_div2 top_*/u_clkmgr_aon/u_no_scan_io_div2_div
create_generated_clock -name clk_io_div2 -source [get_pin ${u_pll}/CLKOUT0] -divide_by 2 [get_pin ${u_div2}/u_clk_div_buf/gen_xilinx.u_impl_xilinx/bufg_i/O]
-set u_div4 top_*/u_clkmgr_aon/u_io_div4_div
+set u_div4 top_*/u_clkmgr_aon/u_no_scan_io_div4_div
create_generated_clock -name clk_io_div4 -source [get_pin ${u_pll}/CLKOUT0] -divide_by 4 [get_pin ${u_div4}/u_clk_div_buf/gen_xilinx.u_impl_xilinx/bufg_i/O]
## JTAG and SPI clocks
diff --git a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv
index 4f98a06..f29eabe 100644
--- a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv
+++ b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv
@@ -111,7 +111,7 @@
prim_clock_div #(
.Divisor(2)
- ) u_io_div2_div (
+ ) u_no_scan_io_div2_div (
.clk_i(clk_io_i),
.rst_ni(rst_io_ni),
.step_down_req_i(step_down_req == lc_ctrl_pkg::On),
@@ -133,7 +133,7 @@
prim_clock_div #(
.Divisor(4)
- ) u_io_div4_div (
+ ) u_no_scan_io_div4_div (
.clk_i(clk_io_i),
.rst_ni(rst_io_ni),
.step_down_req_i(step_down_req == lc_ctrl_pkg::On),
diff --git a/hw/top_earlgrey/syn/asic.constraints.sdc b/hw/top_earlgrey/syn/asic.constraints.sdc
index ddebff0..f6450bd 100644
--- a/hw/top_earlgrey/syn/asic.constraints.sdc
+++ b/hw/top_earlgrey/syn/asic.constraints.sdc
@@ -70,12 +70,12 @@
# generated clocks (div2/div4)
create_generated_clock -name IO_DIV2_CLK -divide_by 2 \
- -source [get_pins top_earlgrey/u_clkmgr_aon/u_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
- [get_pins top_earlgrey/u_clkmgr_aon/u_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
+ -source [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
+ [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div2_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
create_generated_clock -name IO_DIV4_CLK -divide_by 4 \
- -source [get_pins top_earlgrey/u_clkmgr_aon/u_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
- [get_pins top_earlgrey/u_clkmgr_aon/u_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
+ -source [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_mux2/D1] \
+ [get_pins top_earlgrey/u_clkmgr_aon/u_no_scan_io_div4_div/u_clk_mux/gen_*u_impl*/u_size_only_inv/${DRIVING_CELL_PIN}]
# TODO: these are dummy constraints and likely incorrect, need to properly constrain min/max
# note that due to the muxing, additional timing views with set_case_analysis may be needed.