mirror of https://github.com/efabless/caravel.git
495 lines
13 KiB
Verilog
495 lines
13 KiB
Verilog
// SPDX-FileCopyrightText: 2020 Efabless Corporation
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
`default_nettype none
|
|
/*----------------------------------------------------------------------*/
|
|
/* 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 USE_POWER_PINS
|
|
inout vccd,
|
|
inout vssd,
|
|
inout vccd1,
|
|
inout vssd1,
|
|
inout vccd2,
|
|
inout vssd2,
|
|
inout vdda1,
|
|
inout vssa1,
|
|
inout vdda2,
|
|
inout vssa2,
|
|
`endif
|
|
|
|
input caravel_clk,
|
|
input caravel_clk2,
|
|
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 [2:0] user_irq_core,
|
|
|
|
output [31:0] mprj_dat_i_core,
|
|
output mprj_ack_i_core,
|
|
|
|
input mprj_iena_wb, // Enable wishbone from user project
|
|
|
|
// All signal in/out directions are the reverse of the signal
|
|
// names at the buffer intrface.
|
|
|
|
output [127:0] la_data_in_mprj,
|
|
input [127:0] la_data_out_mprj,
|
|
input [127:0] la_oenb_mprj,
|
|
input [127:0] la_iena_mprj,
|
|
|
|
input [127:0] la_data_out_core,
|
|
output [127:0] la_data_in_core,
|
|
output [127:0] la_oenb_core,
|
|
|
|
input [2:0] user_irq_ena,
|
|
|
|
output user_clock,
|
|
output user_clock2,
|
|
output user_reset,
|
|
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,
|
|
input [31:0] mprj_dat_i_user,
|
|
input mprj_ack_i_user,
|
|
output [2:0] user_irq,
|
|
output user1_vcc_powergood,
|
|
output user2_vcc_powergood,
|
|
output user1_vdd_powergood,
|
|
output user2_vdd_powergood
|
|
);
|
|
|
|
wire [462:0] mprj_logic1;
|
|
wire mprj2_logic1;
|
|
|
|
wire mprj_vdd_logic1_h;
|
|
wire mprj2_vdd_logic1_h;
|
|
wire mprj_vdd_logic1;
|
|
wire mprj2_vdd_logic1;
|
|
|
|
wire user1_vcc_powergood;
|
|
wire user2_vcc_powergood;
|
|
wire user1_vdd_powergood;
|
|
wire user2_vdd_powergood;
|
|
|
|
wire [127:0] la_data_in_mprj_bar;
|
|
wire [2:0] user_irq_bar;
|
|
|
|
wire [127:0] la_data_in_enable;
|
|
wire [127:0] la_data_out_enable;
|
|
wire [2:0] user_irq_enable;
|
|
wire wb_in_enable;
|
|
|
|
wire [31:0] mprj_dat_i_core_bar;
|
|
wire mprj_ack_i_core_bar;
|
|
|
|
mprj_logic_high mprj_logic_high_inst (
|
|
`ifdef USE_POWER_PINS
|
|
.vccd1(vccd1),
|
|
.vssd1(vssd1),
|
|
`endif
|
|
.HI(mprj_logic1)
|
|
);
|
|
|
|
mprj2_logic_high mprj2_logic_high_inst (
|
|
`ifdef USE_POWER_PINS
|
|
.vccd2(vccd2),
|
|
.vssd2(vssd2),
|
|
`endif
|
|
.HI(mprj2_logic1)
|
|
);
|
|
|
|
// Logic high in the VDDA (3.3V) domains
|
|
|
|
mgmt_protect_hv powergood_check (
|
|
`ifdef USE_POWER_PINS
|
|
.vccd(vccd),
|
|
.vssd(vssd),
|
|
.vdda1(vdda1),
|
|
.vssa1(vssa1),
|
|
.vdda2(vdda2),
|
|
.vssa2(vssa2),
|
|
`endif
|
|
.mprj_vdd_logic1(mprj_vdd_logic1),
|
|
.mprj2_vdd_logic1(mprj2_vdd_logic1)
|
|
);
|
|
|
|
// Buffering from the user side to the management side.
|
|
// NOTE: This is intended to be better protected, by a full
|
|
// chain of an lv-to-hv buffer followed by an hv-to-lv buffer.
|
|
// This serves as a placeholder until that configuration is
|
|
// checked and characterized. The function below forces the
|
|
// data input to the management core to be a solid logic 0 when
|
|
// the user project is powered down.
|
|
|
|
sky130_fd_sc_hd__and2_1 user_to_mprj_in_ena_buf [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.X(la_data_in_enable),
|
|
.A(la_iena_mprj),
|
|
.B(mprj_logic1[457:330])
|
|
);
|
|
|
|
sky130_fd_sc_hd__nand2_4 user_to_mprj_in_gates [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(la_data_in_mprj_bar),
|
|
.A(la_data_out_core),
|
|
.B(la_data_in_enable)
|
|
);
|
|
|
|
sky130_fd_sc_hd__inv_8 user_to_mprj_in_buffers [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(la_data_in_mprj),
|
|
.A(la_data_in_mprj_bar)
|
|
);
|
|
|
|
// Protection, similar to the above, for the three user IRQ lines
|
|
|
|
sky130_fd_sc_hd__and2_1 user_irq_ena_buf [2:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.X(user_irq_enable),
|
|
.A(user_irq_ena),
|
|
.B(mprj_logic1[460:458])
|
|
);
|
|
|
|
sky130_fd_sc_hd__nand2_4 user_irq_gates [2:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(user_irq_bar),
|
|
.A(user_irq_core),
|
|
.B(user_irq_enable)
|
|
);
|
|
|
|
sky130_fd_sc_hd__inv_8 user_irq_buffers [2:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(user_irq),
|
|
.A(user_irq_bar)
|
|
);
|
|
|
|
// Protection, similar to the above, for the return
|
|
// signals from user area to managment on the wishbone bus
|
|
|
|
sky130_fd_sc_hd__and2_1 user_to_mprj_wb_ena_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.X(wb_in_enable),
|
|
.A(mprj_iena_wb),
|
|
.B(mprj_logic1[462])
|
|
);
|
|
|
|
sky130_fd_sc_hd__nand2_4 user_wb_dat_gates [31:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(mprj_dat_i_core_bar),
|
|
.A(mprj_dat_i_user),
|
|
.B(wb_in_enable)
|
|
);
|
|
|
|
sky130_fd_sc_hd__inv_8 user_wb_dat_buffers [31:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(mprj_dat_i_core),
|
|
.A(mprj_dat_i_core_bar)
|
|
);
|
|
|
|
sky130_fd_sc_hd__nand2_4 user_wb_ack_gate (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(mprj_ack_i_core_bar),
|
|
.A(mprj_ack_i_user),
|
|
.B(wb_in_enable)
|
|
);
|
|
|
|
sky130_fd_sc_hd__inv_8 user_wb_ack_buffer (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Y(mprj_ack_i_core),
|
|
.A(mprj_ack_i_core_bar)
|
|
);
|
|
|
|
// The remaining circuitry guards against the management
|
|
// SoC dumping current into the user project area when
|
|
// the user project area is powered down.
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_rstn_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(user_reset),
|
|
.A(caravel_rstn),
|
|
.TE(mprj_logic1[0])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_clk_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.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_clk2_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(user_clock2),
|
|
.A(~caravel_clk2),
|
|
.TE(mprj_logic1[2])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_cyc_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_cyc_o_user),
|
|
.A(~mprj_cyc_o_core),
|
|
.TE(mprj_logic1[3])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_stb_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_stb_o_user),
|
|
.A(~mprj_stb_o_core),
|
|
.TE(mprj_logic1[4])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_we_buf (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_we_o_user),
|
|
.A(~mprj_we_o_core),
|
|
.TE(mprj_logic1[5])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_sel_buf [3:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_sel_o_user),
|
|
.A(~mprj_sel_o_core),
|
|
.TE(mprj_logic1[9:6])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_adr_buf [31:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_adr_o_user),
|
|
.A(~mprj_adr_o_core),
|
|
.TE(mprj_logic1[41:10])
|
|
);
|
|
|
|
sky130_fd_sc_hd__einvp_8 mprj_dat_buf [31:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(mprj_dat_o_user),
|
|
.A(~mprj_dat_o_core),
|
|
.TE(mprj_logic1[73:42])
|
|
);
|
|
|
|
/* Create signal to tristate the outputs to the user project */
|
|
|
|
sky130_fd_sc_hd__and2b_1 la_buf_enable [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.X(la_data_out_enable),
|
|
.A_N(la_oenb_mprj),
|
|
.B(mprj_logic1[201:74])
|
|
);
|
|
|
|
/* Project data out from the managment side to the user project */
|
|
/* area when the user project is powered down. */
|
|
|
|
sky130_fd_sc_hd__einvp_8 la_buf [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(la_data_in_core),
|
|
.A(~la_data_out_mprj),
|
|
.TE(la_data_out_enable)
|
|
);
|
|
|
|
/* Project data out enable (bar) from the managment side to the */
|
|
/* user project area when the user project is powered down. */
|
|
|
|
sky130_fd_sc_hd__einvp_8 user_to_mprj_oen_buffers [127:0] (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.Z(la_oenb_core),
|
|
.A(~la_oenb_mprj),
|
|
.TE(mprj_logic1[329:202])
|
|
);
|
|
|
|
/* The conb cell output is a resistive connection directly to */
|
|
/* the power supply, so when returning the user1_powergood */
|
|
/* signal, make sure that it is buffered properly. */
|
|
|
|
sky130_fd_sc_hd__buf_8 mprj_pwrgood (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.A(mprj_logic1[461]),
|
|
.X(user1_vcc_powergood)
|
|
);
|
|
|
|
sky130_fd_sc_hd__buf_8 mprj2_pwrgood (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.A(mprj2_logic1),
|
|
.X(user2_vcc_powergood)
|
|
);
|
|
|
|
sky130_fd_sc_hd__buf_8 mprj_vdd_pwrgood (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.A(mprj_vdd_logic1),
|
|
.X(user1_vdd_powergood)
|
|
);
|
|
|
|
sky130_fd_sc_hd__buf_8 mprj2_vdd_pwrgood (
|
|
`ifdef USE_POWER_PINS
|
|
.VPWR(vccd),
|
|
.VGND(vssd),
|
|
.VPB(vccd),
|
|
.VNB(vssd),
|
|
`endif
|
|
.A(mprj2_vdd_logic1),
|
|
.X(user2_vdd_powergood)
|
|
);
|
|
endmodule
|
|
`default_nettype wire
|