From b69abe752515d12b0a857a7d595b04cccbb27f5a Mon Sep 17 00:00:00 2001 From: mo-hosni Date: Wed, 13 Mar 2024 20:36:40 +0200 Subject: [PATCH] update the scan chain jtag ports to be non-configurable --- verilog/rtl/caravel_core.v | 163 ++++++++++++++- verilog/rtl/gpio_control_block_mgmt.v | 289 ++++++++++++++++++++++++++ 2 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 verilog/rtl/gpio_control_block_mgmt.v diff --git a/verilog/rtl/caravel_core.v b/verilog/rtl/caravel_core.v index dd42ac66..d1453e4e 100644 --- a/verilog/rtl/caravel_core.v +++ b/verilog/rtl/caravel_core.v @@ -1321,8 +1321,167 @@ module caravel_core ( .pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]) ); - /* Section 2 GPIOs (GPIO 19 to 34) */ + /* Section 2 GPIOs (GPIO 19 to 26) */ + + gpio_control_block gpio_control_in_2 [7:0] ( +`ifdef USE_POWER_PINS + .vccd(vccd), + .vssd(vssd), + .vccd1(vccd1), + .vssd1(vssd1), +`endif + .gpio_defaults(gpio_defaults[(27*13-1):(19*13)]), + + // Management Soc-facing signals + + .resetn(gpio_resetn_2_shifted[(7):0]), + .serial_clock(gpio_clock_2_shifted[(7):0]), + .serial_load(gpio_load_2_shifted[(7):0]), + + .resetn_out(gpio_resetn_2[(7):0]), + .serial_clock_out(gpio_clock_2[(7):0]), + .serial_load_out(gpio_load_2[(7):0]), + + .mgmt_gpio_in(mgmt_io_in[(26):(19)]), + .mgmt_gpio_out(mgmt_io_out[(26):(19)]), + .mgmt_gpio_oeb(mprj_io_one[(26):(19)]), + + + .one(mprj_io_one[(26):(19)]), + .zero(), + + // Serial data chain for pad configuration + .serial_data_in(gpio_serial_link_2_shifted[(7):0]), + .serial_data_out(gpio_serial_link_2[(7):0]), + + // User-facing signals + .user_gpio_out(user_io_out[(26):(19)]), + .user_gpio_oeb(user_io_oeb[(26):(19)]), + .user_gpio_in(user_io_in[(26):(19)]), + + // Pad-facing signals (Pad GPIOv2) + .pad_gpio_inenb(mprj_io_inp_dis[(26):(19)]), + .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(26):(19)]), + .pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(26):(19)]), + .pad_gpio_slow_sel(mprj_io_slow_sel[(26):(19)]), + .pad_gpio_holdover(mprj_io_holdover[(26):(19)]), + .pad_gpio_ana_en(mprj_io_analog_en[(26):(19)]), + .pad_gpio_ana_sel(mprj_io_analog_sel[(26):(19)]), + .pad_gpio_ana_pol(mprj_io_analog_pol[(26):(19)]), + .pad_gpio_dm(mprj_io_dm[(27*3-1):(19*3)]), + .pad_gpio_outenb(mprj_io_oeb[(26):(19)]), + .pad_gpio_out(mprj_io_out[(26):(19)]), + .pad_gpio_in(mprj_io_in[(26):(19)]) + ); + + /* Section 2 GPIOs (GPIO 27 to 31) DFT jtag */ + + gpio_control_block_mgmt gpio_control_in_2 [12:8] ( +`ifdef USE_POWER_PINS + .vccd(vccd), + .vssd(vssd), + .vccd1(vccd1), + .vssd1(vssd1), +`endif + .gpio_defaults(gpio_defaults[(32*13-1):(27*13)]), + + // Management Soc-facing signals + + .resetn(gpio_resetn_2_shifted[(12):(8)]), + .serial_clock(gpio_clock_2_shifted[(12):(8)]), + .serial_load(gpio_load_2_shifted[(12):(8)]), + + .resetn_out(gpio_resetn_2[(12):(8)]), + .serial_clock_out(gpio_clock_2[(12):(8)]), + .serial_load_out(gpio_load_2[(12):(8)]), + + .mgmt_gpio_in(mgmt_io_in[(31):(27)]), + .mgmt_gpio_out(mgmt_io_out[(31):(27)]), + .mgmt_gpio_oeb(mprj_io_one[(31):(27)]), + + + .one(mprj_io_one[(31):(27)]), + .zero(), + + // Serial data chain for pad configuration + .serial_data_in(gpio_serial_link_2_shifted[(12):(8)]), + .serial_data_out(gpio_serial_link_2[(12):(8)]), + + // User-facing signals + .user_gpio_out(user_io_out[(31):(27)]), + .user_gpio_oeb(user_io_oeb[(31):(27)]), + .user_gpio_in(user_io_in[(31):(27)]), + + // Pad-facing signals (Pad GPIOv2) + .pad_gpio_inenb(mprj_io_inp_dis[(31):(27)]), + .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(31):(27)]), + .pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(31):(27)]), + .pad_gpio_slow_sel(mprj_io_slow_sel[(31):(27)]), + .pad_gpio_holdover(mprj_io_holdover[(31):(27)]), + .pad_gpio_ana_en(mprj_io_analog_en[(31):(27)]), + .pad_gpio_ana_sel(mprj_io_analog_sel[(31):(27)]), + .pad_gpio_ana_pol(mprj_io_analog_pol[(31):(27)]), + .pad_gpio_dm(mprj_io_dm[(32*3-1):(27*3)]), + .pad_gpio_outenb(mprj_io_oeb[(31):(27)]), + .pad_gpio_out(mprj_io_out[(31):(27)]), + .pad_gpio_in(mprj_io_in[(31):(27)]) + ); + /* Section 2 GPIOs (GPIO 32 to 34) */ + + gpio_control_block_mgmt gpio_control_in_2 [15:13] ( +`ifdef USE_POWER_PINS + .vccd(vccd), + .vssd(vssd), + .vccd1(vccd1), + .vssd1(vssd1), +`endif + .gpio_defaults(gpio_defaults[(35*13-1):(32*13)]), + + // Management Soc-facing signals + + .resetn(gpio_resetn_2_shifted[(15):(13)]), + .serial_clock(gpio_clock_2_shifted[(15):(13)]), + .serial_load(gpio_load_2_shifted[(15):(13)]), + + .resetn_out(gpio_resetn_2[(15):(13)]), + .serial_clock_out(gpio_clock_2[(15):(13)]), + .serial_load_out(gpio_load_2[(15):(13)]), + + .mgmt_gpio_in(mgmt_io_in[(34):(32)]), + .mgmt_gpio_out(mgmt_io_out[(34):(32)]), + .mgmt_gpio_oeb(mprj_io_one[(34):(32)]), + + + .one(mprj_io_one[(34):(32)]), + .zero(), + + // Serial data chain for pad configuration + .serial_data_in(gpio_serial_link_2_shifted[(15):(13)]), + .serial_data_out(gpio_serial_link_2[(15):(13)]), + + // User-facing signals + .user_gpio_out(user_io_out[(34):(32)]), + .user_gpio_oeb(user_io_oeb[(34):(32)]), + .user_gpio_in(user_io_in[(34):(32)]), + + // Pad-facing signals (Pad GPIOv2) + .pad_gpio_inenb(mprj_io_inp_dis[(34):(32)]), + .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(34):(32)]), + .pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(34):(32)]), + .pad_gpio_slow_sel(mprj_io_slow_sel[(34):(32)]), + .pad_gpio_holdover(mprj_io_holdover[(34):(32)]), + .pad_gpio_ana_en(mprj_io_analog_en[(34):(32)]), + .pad_gpio_ana_sel(mprj_io_analog_sel[(34):(32)]), + .pad_gpio_ana_pol(mprj_io_analog_pol[(34):(32)]), + .pad_gpio_dm(mprj_io_dm[(35*3-1):(32*3)]), + .pad_gpio_outenb(mprj_io_oeb[(34):(32)]), + .pad_gpio_out(mprj_io_out[(34):(32)]), + .pad_gpio_in(mprj_io_in[(34):(32)]) + ); + + /* Section 2 GPIOs (GPIO 19 to 34) */ +/* gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-4:0] ( `ifdef USE_POWER_PINS .vccd(vccd), @@ -1374,7 +1533,7 @@ module caravel_core ( .pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]), .pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]) ); - +*/ user_id_programming #( .USER_PROJECT_ID(USER_PROJECT_ID) ) user_id_value ( diff --git a/verilog/rtl/gpio_control_block_mgmt.v b/verilog/rtl/gpio_control_block_mgmt.v new file mode 100644 index 00000000..5e710dd9 --- /dev/null +++ b/verilog/rtl/gpio_control_block_mgmt.v @@ -0,0 +1,289 @@ +// 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 +/* + *--------------------------------------------------------------------- + * See gpio_control_block for description. This module is like + * gpio_contro_block except that it has an additional two management- + * Soc-facing pins, which are the out_enb line and the output line. + * If the chip is configured for output with the oeb control + * register = 1, then the oeb line is controlled by the additional + * signal from the management SoC. If the oeb control register = 0, + * then the output is disabled completely. The "io" line is input + * only in this module. + * + *--------------------------------------------------------------------- + */ + +/* + *--------------------------------------------------------------------- + * + * This module instantiates a shift register chain that passes through + * each gpio cell. These are connected end-to-end around the padframe + * periphery. The purpose is to avoid a massive number of control + * wires between the digital core and I/O, passing through the user area. + * + * See mprj_ctrl.v for the module that registers the data for each + * I/O and drives the input to the shift register. + * + * Modified 7/24/2022 by Tim Edwards + * Replaced the data delay with a negative edge-triggered flop + * so that the serial data bit out from the module only changes on + * the clock half cycle. This avoids the need to fine-tune the clock + * skew between GPIO blocks. + * + * Modified 10/05/2022 by Tim Edwards + * + *--------------------------------------------------------------------- + */ + +module gpio_control_block_mgmt #( + parameter PAD_CTRL_BITS = 13 +) ( + `ifdef USE_POWER_PINS + inout vccd, + inout vssd, + inout vccd1, + inout vssd1, + `endif + + // Power-on defaults + input [PAD_CTRL_BITS-1:0] gpio_defaults, + + // Management Soc-facing signals + input resetn, // Global reset, locally propagated + output resetn_out, + input serial_clock, // Global clock, locally propatated + output serial_clock_out, + input serial_load, // Register load strobe + output serial_load_out, + + output mgmt_gpio_in, // Management from pad (input only) + input mgmt_gpio_out, // Management to pad (output only) + input mgmt_gpio_oeb, // Management to pad (output only) + + // Serial data chain for pad configuration + input serial_data_in, + output reg serial_data_out, + + // User-facing signals + input user_gpio_out, // User space to pad + input user_gpio_oeb, // Output enable (user) + output user_gpio_in, // Pad to user space + + // Pad-facing signals (Pad GPIOv2) + output pad_gpio_holdover, + output pad_gpio_slow_sel, + output pad_gpio_vtrip_sel, + output pad_gpio_inenb, + output pad_gpio_ib_mode_sel, + output pad_gpio_ana_en, + output pad_gpio_ana_sel, + output pad_gpio_ana_pol, + output [2:0] pad_gpio_dm, + output pad_gpio_outenb, + output pad_gpio_out, + input pad_gpio_in, + + // to provide a way to automatically disable/enable output + // from the outside with needing a conb cell + output one, + output zero +); + + /* Parameters defining the bit offset of each function in the chain */ + localparam MGMT_EN = 0; + localparam OEB = 1; + localparam HLDH = 2; + localparam INP_DIS = 3; + localparam MOD_SEL = 4; + localparam AN_EN = 5; + localparam AN_SEL = 6; + localparam AN_POL = 7; + localparam SLOW = 8; + localparam TRIP = 9; + localparam DM = 10; + + /* Internally registered signals */ + /* + reg mgmt_ena; // Enable management SoC to access pad + reg gpio_holdover; + reg gpio_slow_sel; + reg gpio_vtrip_sel; + reg gpio_inenb; + reg gpio_ib_mode_sel; + reg gpio_outenb; + reg [2:0] gpio_dm; + reg gpio_ana_en; + reg gpio_ana_sel; + reg gpio_ana_pol; +*/ + wire mgmt_ena = 1'b0; + wire gpio_holdover = gpio_defaults[HLDH]; + wire gpio_slow_sel = gpio_defaults[SLOW]; + wire gpio_vtrip_sel = gpio_defaults[TRIP]; + wire gpio_ib_mode_sel = gpio_defaults[MOD_SEL]; + wire gpio_inenb = gpio_defaults[INP_DIS]; + wire gpio_outenb = gpio_defaults[OEB]; + wire [2:0] gpio_dm = gpio_defaults[DM+2:DM]; + wire gpio_ana_en = gpio_defaults[AN_EN]; + wire gpio_ana_sel = gpio_defaults[AN_SEL]; + wire gpio_ana_pol = gpio_defaults[AN_POL]; + + wire gpio_logic1; + + /* Serial shift for the above (latched) values */ + reg [PAD_CTRL_BITS-1:0] shift_register; + + /* Latch the output on the clock negative edge */ + always @(negedge serial_clock or negedge resetn) begin + if (resetn == 1'b0) begin + /* Clear the shift register output */ + serial_data_out <= 1'b0; + end else begin + serial_data_out <= shift_register[PAD_CTRL_BITS-1]; + end + end + + /* Propagate the clock and reset signals so that they aren't wired */ + /* all over the chip, but are just wired between the blocks. */ + (* keep *) sky130_fd_sc_hd__clkbuf_8 BUF[2:0] ( + `ifdef USE_POWER_PINS + .VPWR(vccd), + .VGND(vssd), + .VPB(vccd), + .VNB(vssd), + `endif + .A({serial_clock, resetn, serial_load}), + .X({serial_clock_out, resetn_out, serial_load_out}) + ); + + always @(posedge serial_clock or negedge resetn) begin + if (resetn == 1'b0) begin + /* Clear shift register */ + shift_register <= 'd0; + end else begin + /* Shift data in */ + shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in}; + end + end + +/* + always @(posedge serial_load or negedge resetn) begin + if (resetn == 1'b0) begin + mgmt_ena <= gpio_defaults[MGMT_EN]; + gpio_holdover <= gpio_defaults[HLDH]; + gpio_slow_sel <= gpio_defaults[SLOW]; + gpio_vtrip_sel <= gpio_defaults[TRIP]; + gpio_ib_mode_sel <= gpio_defaults[MOD_SEL]; + gpio_inenb <= gpio_defaults[INP_DIS]; + gpio_outenb <= gpio_defaults[OEB]; + gpio_dm <= gpio_defaults[DM+2:DM]; + gpio_ana_en <= gpio_defaults[AN_EN]; + gpio_ana_sel <= gpio_defaults[AN_SEL]; + gpio_ana_pol <= gpio_defaults[AN_POL]; + + end else begin + mgmt_ena <= shift_register[MGMT_EN]; + gpio_outenb <= shift_register[OEB]; + gpio_holdover <= shift_register[HLDH]; + gpio_inenb <= shift_register[INP_DIS]; + gpio_ib_mode_sel <= shift_register[MOD_SEL]; + gpio_ana_en <= shift_register[AN_EN]; + gpio_ana_sel <= shift_register[AN_SEL]; + gpio_ana_pol <= shift_register[AN_POL]; + gpio_slow_sel <= shift_register[SLOW]; + gpio_vtrip_sel <= shift_register[TRIP]; + gpio_dm <= shift_register[DM+2:DM]; + + end + end +*/ + /* These pad configuration signals are static and do not change */ + /* after setup. */ + + assign pad_gpio_holdover = gpio_holdover; + assign pad_gpio_slow_sel = gpio_slow_sel; + assign pad_gpio_vtrip_sel = gpio_vtrip_sel; + assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel; + assign pad_gpio_ana_en = gpio_ana_en; + assign pad_gpio_ana_sel = gpio_ana_sel; + assign pad_gpio_ana_pol = gpio_ana_pol; + assign pad_gpio_dm = gpio_dm; + assign pad_gpio_inenb = gpio_inenb; + + /* Implement pad control behavior depending on state of mgmt_ena */ + + /* The pad value always goes back to the housekeeping module */ + + assign mgmt_gpio_in = pad_gpio_in; + //(gpio_inenb == 1'b0 && gpio_outenb == 1'b1) ? + //pad_gpio_in : 1'bz; + + assign pad_gpio_outenb = mgmt_gpio_oeb; //(mgmt_ena) ? mgmt_gpio_oeb : + // ((mgmt_gpio_oeb == 1'b1) ? gpio_outenb : 1'b0) : + //user_gpio_oeb; + assign pad_gpio_out = mgmt_gpio_out; + //(mgmt_ena) ? mgmt_gpio_out : + //((mgmt_gpio_oeb == 1'b1) ? + //((gpio_dm[2:1] == 2'b01) ? ~gpio_dm[0] : mgmt_gpio_out) : + //mgmt_gpio_out) : + //user_gpio_out; + + /* Buffer user_gpio_in with an enable that is set by the user domain vccd */ + + gpio_logic_high gpio_logic_high ( +`ifdef USE_POWER_PINS + .vccd1(vccd1), + .vssd1(vssd1), +`endif + .gpio_logic1(gpio_logic1) + ); + + /* If user project area is powered down, zero the pad input value */ + /* going to the user project. */ + assign user_gpio_in = pad_gpio_in & gpio_logic1; + + (* keep *) + sky130_fd_sc_hd__macro_sparecell spare_cell ( +`ifdef USE_POWER_PINS + .VPWR(vccd), + .VGND(vssd), + .VPB(vccd), + .VNB(vssd) +`endif + ); + + // buffering const one and zero outputs + wire one_unbuf; + wire zero_unbuf; + + sky130_fd_sc_hd__conb_1 const_source ( +`ifdef USE_POWER_PINS + .VPWR(vccd), + .VGND(vssd), + .VPB(vccd), + .VNB(vssd), +`endif + .HI(one_unbuf), + .LO(zero_unbuf) + ); + + assign zero = zero_unbuf; + assign one = one_unbuf; + +endmodule +`default_nettype wire