Added additional protection for all the signals output to the user
space, to force them to be tristated whenever the user space 1.8V
supply is missing.
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v
index 463f127..f0708d2 100644
--- a/verilog/rtl/caravel.v
+++ b/verilog/rtl/caravel.v
@@ -37,6 +37,7 @@
`include "digital_pll.v"
`include "caravel_clocking.v"
`include "mgmt_core.v"
+`include "mgmt_protect.v"
`include "mprj_io.v"
`include "chip_io.v"
`include "user_id_programming.v"
@@ -372,11 +373,49 @@
.mask_rev(mask_rev)
);
- sky130_fd_sc_hd__ebufn_8 la_buf [127:0] (
- .Z(la_data_in_mprj),
- .A(la_output_core),
- .TE_B(la_oen)
+ /* Clock and reset to user space are passed through a tristate */
+ /* buffer like the above, but since they are intended to be */
+ /* always active, connect the enable to the logic-1 output from */
+ /* the vccd1 domain. */
+
+ wire mprj_clock;
+ wire mprj_resetn;
+ wire mprj_cyc_o_user;
+ wire mprj_stb_o_user;
+ wire mprj_we_o_user;
+ wire [3:0] mprj_sel_o_user;
+ wire [31:0] mprj_adr_o_user;
+ wire [31:0] mprj_dat_o_user;
+
+ mgmt_protect mgmt_buffers (
+ `ifdef LVS
+ .vccd(vccd),
+ .vssd(vssd),
+ .vccd1(vccd1),
+ .vssd1(vssd1),
+ `endif
+ .caravel_clk(caravel_clk),
+ .caravel_rstn(caravel_rstn),
+ .mprj_cyc_o_core(mprj_cyc_o_core),
+ .mprj_stb_o_core(mprj_stb_o_core),
+ .mprj_we_o_core(mprj_we_o_core),
+ .mprj_sel_o_core(mprj_sel_o_core),
+ .mprj_adr_o_core(mprj_adr_o_core),
+ .mprj_dat_o_core(mprj_dat_o_core),
+ .la_output_core(la_output_core),
+ .la_oen(la_oen),
+
+ .user_clock(mprj_clock),
+ .user_resetn(mprj_resetn),
+ .mprj_cyc_o_user(mprj_cyc_o_user),
+ .mprj_stb_o_user(mprj_stb_o_user),
+ .mprj_we_o_user(mprj_we_o_user),
+ .mprj_sel_o_user(mprj_sel_o_user),
+ .mprj_adr_o_user(mprj_adr_o_user),
+ .mprj_dat_o_user(mprj_dat_o_user),
+ .la_data_in_mprj(la_data_in_mprj)
);
+
/*--------------------------------------*/
/* User project is instantiated here */
@@ -396,15 +435,15 @@
vssa1, // User area 1 digital ground
vssa2, // User area 2 digital ground
`endif
- .wb_clk_i(caravel_clk),
- .wb_rst_i(!caravel_rstn),
+ .wb_clk_i(mprj_clock),
+ .wb_rst_i(!mprj_resetn),
// MGMT SoC Wishbone Slave
- .wbs_cyc_i(mprj_cyc_o_core),
- .wbs_stb_i(mprj_stb_o_core),
- .wbs_we_i(mprj_we_o_core),
- .wbs_sel_i(mprj_sel_o_core),
- .wbs_adr_i(mprj_adr_o_core),
- .wbs_dat_i(mprj_dat_o_core),
+ .wbs_cyc_i(mprj_cyc_o_user),
+ .wbs_stb_i(mprj_stb_o_user),
+ .wbs_we_i(mprj_we_o_user),
+ .wbs_sel_i(mprj_sel_o_user),
+ .wbs_adr_i(mprj_adr_o_user),
+ .wbs_dat_i(mprj_dat_o_user),
.wbs_ack_o(mprj_ack_i_core),
.wbs_dat_o(mprj_dat_i_core),
// Logic Analyzer
@@ -439,6 +478,12 @@
.DM_INIT(3'b110), // Mode = output, strong up/down
.OENB_INIT(1'b0) // Enable output signaling from wire
) gpio_control_bidir [1:0] (
+ `ifdef LVS
+ inout vccd,
+ inout vssd,
+ inout vccd1,
+ inout vssd1,
+ `endif
// Management Soc-facing signals
@@ -474,6 +519,12 @@
);
gpio_control_block gpio_control_in [`MPRJ_IO_PADS-1:2] (
+ `ifdef LVS
+ inout vccd,
+ inout vssd,
+ inout vccd1,
+ inout vssd1,
+ `endif
// Management Soc-facing signals
diff --git a/verilog/rtl/gpio_control_block.v b/verilog/rtl/gpio_control_block.v
index 823856b..ab08e46 100644
--- a/verilog/rtl/gpio_control_block.v
+++ b/verilog/rtl/gpio_control_block.v
@@ -43,6 +43,13 @@
parameter ASEL_INIT = 1'b0,
parameter APOL_INIT = 1'b0
) (
+ `ifdef LVS
+ inout vccd,
+ inout vssd,
+ inout vccd1,
+ inout vssd1,
+ `endif
+
// Management Soc-facing signals
input resetn, // Global reset
input serial_clock,
@@ -115,6 +122,9 @@
wire pad_gpio_out;
wire pad_gpio_in;
+ wire user_gpio_in;
+ wire gpio_in_unbuf;
+
/* Serial shift for the above (latched) values */
reg [PAD_CTRL_BITS-1:0] shift_register;
@@ -183,7 +193,7 @@
/* Implement pad control behavior depending on state of mgmt_ena */
- assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
+ assign gpio_in_unbuf = (mgmt_ena) ? 1'b0 : pad_gpio_in;
assign mgmt_gpio_in = (mgmt_ena) ? ((gpio_inenb == 1'b0) ?
pad_gpio_in : 1'bz) : 1'b0;
@@ -195,5 +205,29 @@
mgmt_gpio_out) :
user_gpio_out;
+ /* Buffer user_gpio_in with an enable that is set by the user domain vccd */
+
+ sky130_fd_sc_hd__conb_1 gpio_logic_high (
+ `ifdef LVS
+ .VPWR(vccd1),
+ .VGND(vssd1),
+ .VPB(vccd1),
+ .VNB(vssd1),
+ `endif
+ .HI(gpio_logic1),
+ .LO()
+ );
+
+ sky130_fd_sc_hd__einvp_8 gpio_in_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(user_gpio_in),
+ .A(~gpio_in_unbuf),
+ .TE(gpio_logic1)
+ );
endmodule
diff --git a/verilog/rtl/mgmt_protect.v b/verilog/rtl/mgmt_protect.v
new file mode 100644
index 0000000..24b9cbc
--- /dev/null
+++ b/verilog/rtl/mgmt_protect.v
@@ -0,0 +1,173 @@
+/*----------------------------------------------------------------------*/
+/* Buffers protecting the management region from the user region. */
+/* This mainly consists of tristate buffers that are enabled by a */
+/* "logic 1" output connected to the user's VCCD domain. This ensures */
+/* that the buffer is disabled and the output high-impedence when the */
+/* user 1.8V supply is absent. */
+/*----------------------------------------------------------------------*/
+/* Because there is no tristate buffer with a non-inverted enable, a */
+/* tristate inverter with non-inverted enable is used in series with */
+/* another (normal) inverter. */
+/*----------------------------------------------------------------------*/
+/* For the sake of placement/routing, one conb (logic 1) cell is used */
+/* for every buffer. */
+/*----------------------------------------------------------------------*/
+
+module mgmt_protect (
+`ifdef LVS
+ inout vccd,
+ inout vssd,
+ inout vccd1,
+ inout vssd1,
+`endif
+
+ input caravel_clk,
+ input caravel_rstn,
+ input mprj_cyc_o_core,
+ input mprj_stb_o_core,
+ input mprj_we_o_core,
+ input [3:0] mprj_sel_o_core,
+ input [31:0] mprj_adr_o_core,
+ input [31:0] mprj_dat_o_core,
+ input [127:0] la_output_core,
+ input [127:0] la_oen,
+
+ output user_clock,
+ output user_resetn,
+ output mprj_cyc_o_user,
+ output mprj_stb_o_user,
+ output mprj_we_o_user,
+ output [3:0] mprj_sel_o_user,
+ output [31:0] mprj_adr_o_user,
+ output [31:0] mprj_dat_o_user,
+ output [127:0] la_data_in_mprj
+);
+
+ wire [72:0] mprj_logic1;
+
+ sky130_fd_sc_hd__conb_1 mprj_logic_high [72:0] (
+ `ifdef LVS
+ .VPWR(vccd1),
+ .VGND(vssd1),
+ .VPB(vccd1),
+ .VNB(vssd1),
+ `endif
+ .HI(mprj_logic1),
+ .LO()
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_rstn_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(user_resetn),
+ .A(~caravel_rstn),
+ .TE(mprj_logic1[0])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_clk_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(user_clock),
+ .A(~caravel_clk),
+ .TE(mprj_logic1[1])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_cyc_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_cyc_o_user),
+ .A(~mprj_cyc_o_core),
+ .TE(mprj_logic1[2])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_stb_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_stb_o_user),
+ .A(~mprj_stb_o_core),
+ .TE(mprj_logic1[3])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_we_buf (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_we_o_user),
+ .A(~mprj_we_o_core),
+ .TE(mprj_logic1[4])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_sel_buf [3:0] (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_sel_o_user),
+ .A(~mprj_sel_o_core),
+ .TE(mprj_logic1[8:5])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_adr_buf [31:0] (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_adr_o_user),
+ .A(~mprj_adr_o_core),
+ .TE(mprj_logic1[40:9])
+ );
+
+ sky130_fd_sc_hd__einvp_8 mprj_dat_buf [31:0] (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(mprj_dat_o_user),
+ .A(~mprj_dat_o_core),
+ .TE(mprj_logic1[72:41])
+ );
+
+ /* The LA buffers are controlled from the user side, so */
+ /* it is only necessary to make sure that the function */
+ /* is inverting the OEB signal and using positive-sense */
+ /* enable, so that the buffer is disabled on user-side */
+ /* power-down of vccd1. */
+
+ sky130_fd_sc_hd__einvp_8 la_buf [127:0] (
+ `ifdef LVS
+ .VPWR(vccd),
+ .VGND(vssd),
+ .VPB(vccd),
+ .VNB(vssd),
+ `endif
+ .Z(la_data_in_mprj),
+ .A(~la_output_core),
+ .TE(~la_oen)
+ );
+
+endmodule