agorararmard | 6c766a8 | 2020-12-10 18:13:12 +0200 | [diff] [blame] | 1 | // SPDX-FileCopyrightText: 2020 Efabless Corporation |
agorararmard | e5780bf | 2020-12-09 21:27:56 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
agorararmard | afa96ea | 2020-12-09 23:37:31 +0200 | [diff] [blame] | 14 | // SPDX-License-Identifier: Apache-2.0 |
agorararmard | e5780bf | 2020-12-09 21:27:56 +0000 | [diff] [blame] | 15 | |
Matt Venn | 08cd6eb | 2020-11-16 12:01:14 +0100 | [diff] [blame] | 16 | `default_nettype none |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 17 | /* |
| 18 | *--------------------------------------------------------------------- |
Tim Edwards | 251e0df | 2020-10-05 11:02:12 -0400 | [diff] [blame] | 19 | * See gpio_control_block for description. This module is like |
| 20 | * gpio_contro_block except that it has an additional two management- |
| 21 | * Soc-facing pins, which are the out_enb line and the output line. |
| 22 | * If the chip is configured for output with the oeb control |
| 23 | * register = 1, then the oeb line is controlled by the additional |
| 24 | * signal from the management SoC. If the oeb control register = 0, |
| 25 | * then the output is disabled completely. The "io" line is input |
| 26 | * only in this module. |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 27 | * |
| 28 | *--------------------------------------------------------------------- |
| 29 | */ |
| 30 | |
| 31 | /* |
| 32 | *--------------------------------------------------------------------- |
| 33 | * |
| 34 | * This module instantiates a shift register chain that passes through |
| 35 | * each gpio cell. These are connected end-to-end around the padframe |
| 36 | * periphery. The purpose is to avoid a massive number of control |
| 37 | * wires between the digital core and I/O, passing through the user area. |
| 38 | * |
| 39 | * See mprj_ctrl.v for the module that registers the data for each |
| 40 | * I/O and drives the input to the shift register. |
| 41 | * |
| 42 | *--------------------------------------------------------------------- |
| 43 | */ |
| 44 | |
| 45 | module gpio_control_block #( |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 46 | parameter PAD_CTRL_BITS = 13, |
| 47 | // Parameterized initial startup state of the pad. |
| 48 | // The default parameters if unspecified is for the pad to be |
| 49 | // an input with no pull-up or pull-down, so that it is disconnected |
| 50 | // from the outside world. |
| 51 | parameter HOLD_INIT = 1'b0, |
| 52 | parameter SLOW_INIT = 1'b0, |
| 53 | parameter TRIP_INIT = 1'b0, |
| 54 | parameter IB_INIT = 1'b0, |
| 55 | parameter IENB_INIT = 1'b0, |
manarabdelaty | 589a528 | 2020-12-05 01:06:48 +0200 | [diff] [blame] | 56 | parameter OENB_INIT = `OENB_INIT, |
| 57 | parameter DM_INIT = `DM_INIT, |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 58 | parameter AENA_INIT = 1'b0, |
| 59 | parameter ASEL_INIT = 1'b0, |
| 60 | parameter APOL_INIT = 1'b0 |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 61 | ) ( |
Manar | 61dce92 | 2020-11-10 19:26:28 +0200 | [diff] [blame] | 62 | `ifdef USE_POWER_PINS |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 63 | inout vccd, |
| 64 | inout vssd, |
| 65 | inout vccd1, |
| 66 | inout vssd1, |
| 67 | `endif |
| 68 | |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 69 | // Management Soc-facing signals |
| 70 | input resetn, // Global reset |
| 71 | input serial_clock, |
| 72 | |
Tim Edwards | 251e0df | 2020-10-05 11:02:12 -0400 | [diff] [blame] | 73 | output mgmt_gpio_in, // Management from pad (input only) |
| 74 | input mgmt_gpio_out, // Management to pad (output only) |
| 75 | input mgmt_gpio_oeb, // Management to pad (output only) |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 76 | |
| 77 | // Serial data chain for pad configuration |
| 78 | input serial_data_in, |
| 79 | output serial_data_out, |
| 80 | |
| 81 | // User-facing signals |
| 82 | input user_gpio_out, // User space to pad |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 83 | input user_gpio_oeb, // Output enable (user) |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 84 | output user_gpio_in, // Pad to user space |
| 85 | |
| 86 | // Pad-facing signals (Pad GPIOv2) |
| 87 | output pad_gpio_holdover, |
| 88 | output pad_gpio_slow_sel, |
| 89 | output pad_gpio_vtrip_sel, |
| 90 | output pad_gpio_inenb, |
| 91 | output pad_gpio_ib_mode_sel, |
| 92 | output pad_gpio_ana_en, |
| 93 | output pad_gpio_ana_sel, |
| 94 | output pad_gpio_ana_pol, |
| 95 | output [2:0] pad_gpio_dm, |
Tim Edwards | 251e0df | 2020-10-05 11:02:12 -0400 | [diff] [blame] | 96 | output pad_gpio_outenb, |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 97 | output pad_gpio_out, |
Ahmed Ghazy | d0dcdcf | 2020-12-15 22:00:25 +0200 | [diff] [blame] | 98 | input pad_gpio_in, |
| 99 | |
| 100 | // to provide a way to automatically disable/enable output |
| 101 | // from the outside with needing a conb cell |
| 102 | output one, |
| 103 | output zero |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 104 | ); |
| 105 | |
| 106 | /* Parameters defining the bit offset of each function in the chain */ |
| 107 | localparam MGMT_EN = 0; |
| 108 | localparam OEB = 1; |
| 109 | localparam HLDH = 2; |
Tim Edwards | 251e0df | 2020-10-05 11:02:12 -0400 | [diff] [blame] | 110 | localparam INP_DIS = 3; |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 111 | localparam MOD_SEL = 4; |
| 112 | localparam AN_EN = 5; |
| 113 | localparam AN_SEL = 6; |
| 114 | localparam AN_POL = 7; |
| 115 | localparam SLOW = 8; |
| 116 | localparam TRIP = 9; |
| 117 | localparam DM = 10; |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 118 | |
| 119 | /* Internally registered signals */ |
| 120 | reg mgmt_ena; // Enable management SoC to access pad |
| 121 | reg gpio_holdover; |
| 122 | reg gpio_slow_sel; |
| 123 | reg gpio_vtrip_sel; |
| 124 | reg gpio_inenb; |
| 125 | reg gpio_ib_mode_sel; |
| 126 | reg gpio_outenb; |
| 127 | reg [2:0] gpio_dm; |
| 128 | reg gpio_ana_en; |
| 129 | reg gpio_ana_sel; |
| 130 | reg gpio_ana_pol; |
| 131 | |
| 132 | /* Derived output values */ |
| 133 | wire pad_gpio_holdover; |
| 134 | wire pad_gpio_slow_sel; |
| 135 | wire pad_gpio_vtrip_sel; |
| 136 | wire pad_gpio_inenb; |
| 137 | wire pad_gpio_ib_mode_sel; |
| 138 | wire pad_gpio_ana_en; |
| 139 | wire pad_gpio_ana_sel; |
| 140 | wire pad_gpio_ana_pol; |
| 141 | wire [2:0] pad_gpio_dm; |
| 142 | wire pad_gpio_outenb; |
| 143 | wire pad_gpio_out; |
| 144 | wire pad_gpio_in; |
Ahmed Ghazy | d0dcdcf | 2020-12-15 22:00:25 +0200 | [diff] [blame] | 145 | wire one; |
| 146 | wire zero; |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 147 | |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 148 | wire user_gpio_in; |
| 149 | wire gpio_in_unbuf; |
Tim Edwards | 581068f | 2020-11-19 12:45:25 -0500 | [diff] [blame] | 150 | wire gpio_logic1; |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 151 | |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 152 | /* Serial shift for the above (latched) values */ |
| 153 | reg [PAD_CTRL_BITS-1:0] shift_register; |
| 154 | |
| 155 | /* Utilize reset and clock to encode a load operation */ |
| 156 | wire load_data; |
| 157 | wire int_reset; |
| 158 | |
| 159 | /* Create internal reset and load signals from input reset and clock */ |
| 160 | assign serial_data_out = shift_register[PAD_CTRL_BITS-1]; |
| 161 | assign int_reset = (~resetn) & (~serial_clock); |
| 162 | assign load_data = (~resetn) & serial_clock; |
| 163 | |
| 164 | always @(posedge serial_clock or posedge int_reset) begin |
| 165 | if (int_reset == 1'b1) begin |
| 166 | /* Clear shift register */ |
| 167 | shift_register <= 'd0; |
| 168 | end else begin |
| 169 | /* Shift data in */ |
| 170 | shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in}; |
| 171 | end |
| 172 | end |
| 173 | |
| 174 | always @(posedge load_data or posedge int_reset) begin |
| 175 | if (int_reset == 1'b1) begin |
| 176 | /* Initial state on reset: Pad set to management input */ |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 177 | mgmt_ena <= 1'b1; // Management SoC has control over all I/O |
| 178 | gpio_holdover <= HOLD_INIT; // All signals latched in hold mode |
| 179 | gpio_slow_sel <= SLOW_INIT; // Fast slew rate |
| 180 | gpio_vtrip_sel <= TRIP_INIT; // CMOS mode |
| 181 | gpio_ib_mode_sel <= IB_INIT; // CMOS mode |
| 182 | gpio_inenb <= IENB_INIT; // Input enabled |
Tim Edwards | 251e0df | 2020-10-05 11:02:12 -0400 | [diff] [blame] | 183 | gpio_outenb <= OENB_INIT; // (unused placeholder) |
Tim Edwards | 44bab47 | 2020-10-04 22:09:54 -0400 | [diff] [blame] | 184 | gpio_dm <= DM_INIT; // Configured as input only |
| 185 | gpio_ana_en <= AENA_INIT; // Digital enabled |
| 186 | gpio_ana_sel <= ASEL_INIT; // Don't-care when gpio_ana_en = 0 |
| 187 | gpio_ana_pol <= APOL_INIT; // Don't-care when gpio_ana_en = 0 |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 188 | end else begin |
| 189 | /* Load data */ |
| 190 | mgmt_ena <= shift_register[MGMT_EN]; |
| 191 | gpio_outenb <= shift_register[OEB]; |
| 192 | gpio_holdover <= shift_register[HLDH]; |
| 193 | gpio_inenb <= shift_register[INP_DIS]; |
| 194 | gpio_ib_mode_sel <= shift_register[MOD_SEL]; |
| 195 | gpio_ana_en <= shift_register[AN_EN]; |
| 196 | gpio_ana_sel <= shift_register[AN_SEL]; |
| 197 | gpio_ana_pol <= shift_register[AN_POL]; |
| 198 | gpio_slow_sel <= shift_register[SLOW]; |
| 199 | gpio_vtrip_sel <= shift_register[TRIP]; |
| 200 | gpio_dm <= shift_register[DM+2:DM]; |
| 201 | |
| 202 | end |
| 203 | end |
| 204 | |
| 205 | /* These pad configuration signals are static and do not change */ |
| 206 | /* after setup. */ |
| 207 | |
| 208 | assign pad_gpio_holdover = gpio_holdover; |
| 209 | assign pad_gpio_slow_sel = gpio_slow_sel; |
| 210 | assign pad_gpio_vtrip_sel = gpio_vtrip_sel; |
| 211 | assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel; |
| 212 | assign pad_gpio_ana_en = gpio_ana_en; |
| 213 | assign pad_gpio_ana_sel = gpio_ana_sel; |
| 214 | assign pad_gpio_ana_pol = gpio_ana_pol; |
| 215 | assign pad_gpio_dm = gpio_dm; |
| 216 | assign pad_gpio_inenb = gpio_inenb; |
| 217 | |
| 218 | /* Implement pad control behavior depending on state of mgmt_ena */ |
| 219 | |
Tim Edwards | 33f5f6f | 2020-12-15 11:38:13 -0500 | [diff] [blame] | 220 | // assign gpio_in_unbuf = (mgmt_ena) ? 1'b0 : pad_gpio_in; |
| 221 | // assign mgmt_gpio_in = (mgmt_ena) ? ((gpio_inenb == 1'b0) ? |
| 222 | // pad_gpio_in : 1'bz) : 1'b0; |
| 223 | |
| 224 | assign gpio_in_unbuf = pad_gpio_in; |
| 225 | assign mgmt_gpio_in = (gpio_inenb == 1'b0) ? pad_gpio_in : 1'bz; |
Tim Edwards | 89f0924 | 2020-10-05 15:17:34 -0400 | [diff] [blame] | 226 | |
| 227 | assign pad_gpio_outenb = (mgmt_ena) ? ((mgmt_gpio_oeb == 1'b1) ? gpio_outenb : |
| 228 | 1'b0) : user_gpio_oeb; |
| 229 | assign pad_gpio_out = (mgmt_ena) ? |
| 230 | ((mgmt_gpio_oeb == 1'b1) ? |
| 231 | ((gpio_dm[2:1] == 2'b01) ? ~gpio_dm[0] : mgmt_gpio_out) : |
| 232 | mgmt_gpio_out) : |
| 233 | user_gpio_out; |
| 234 | |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 235 | /* Buffer user_gpio_in with an enable that is set by the user domain vccd */ |
| 236 | |
| 237 | sky130_fd_sc_hd__conb_1 gpio_logic_high ( |
Ahmed Ghazy | 64c17e8 | 2020-11-18 20:17:26 +0200 | [diff] [blame] | 238 | `ifdef USE_POWER_PINS |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 239 | .VPWR(vccd1), |
| 240 | .VGND(vssd1), |
| 241 | .VPB(vccd1), |
| 242 | .VNB(vssd1), |
Ahmed Ghazy | 64c17e8 | 2020-11-18 20:17:26 +0200 | [diff] [blame] | 243 | `endif |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 244 | .HI(gpio_logic1), |
| 245 | .LO() |
| 246 | ); |
| 247 | |
| 248 | sky130_fd_sc_hd__einvp_8 gpio_in_buf ( |
Ahmed Ghazy | 64c17e8 | 2020-11-18 20:17:26 +0200 | [diff] [blame] | 249 | `ifdef USE_POWER_PINS |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 250 | .VPWR(vccd), |
| 251 | .VGND(vssd), |
| 252 | .VPB(vccd), |
| 253 | .VNB(vssd), |
Ahmed Ghazy | 64c17e8 | 2020-11-18 20:17:26 +0200 | [diff] [blame] | 254 | `endif |
Tim Edwards | 53d9218 | 2020-10-11 21:47:40 -0400 | [diff] [blame] | 255 | .Z(user_gpio_in), |
| 256 | .A(~gpio_in_unbuf), |
| 257 | .TE(gpio_logic1) |
| 258 | ); |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 259 | |
Ahmed Ghazy | d0dcdcf | 2020-12-15 22:00:25 +0200 | [diff] [blame] | 260 | sky130_fd_sc_hd__conb_1 const_source ( |
| 261 | `ifdef USE_POWER_PINS |
| 262 | .VPWR(vccd), |
| 263 | .VGND(vssd), |
| 264 | .VPB(vccd), |
| 265 | .VNB(vssd), |
| 266 | `endif |
| 267 | .HI(one), |
| 268 | .LO(zero) |
| 269 | ); |
| 270 | |
Tim Edwards | 04ba17f | 2020-10-02 22:27:50 -0400 | [diff] [blame] | 271 | endmodule |
Tim Edwards | 581068f | 2020-11-19 12:45:25 -0500 | [diff] [blame] | 272 | `default_nettype wire |