blob: 2325b39ea1cc942c6a8f48ddb4cc30ebd299627c [file] [log] [blame]
Tim Edwards04ba17f2020-10-02 22:27:50 -04001/*
2 *---------------------------------------------------------------------
3 * This block interfaces between the sky130_fd_io GPIOv2 pad, the
4 * caravel management area, and the user project area.
5 *
6 * The management area has ultimate control over the setting of the
7 * pad, and can modify all core-voltage inputs to the pad and monitor
8 * the output.
9 *
10 * The user project will rely on the management SoC startup program
11 * to configure each I/O pad to a fixed configuration except for
12 * the output enable which remains under user control.
13 *
14 * This module is bit-sliced. Instantiate once for each GPIO pad.
15 *
16 *---------------------------------------------------------------------
17 */
18
19/*
20 *---------------------------------------------------------------------
21 *
22 * This module instantiates a shift register chain that passes through
23 * each gpio cell. These are connected end-to-end around the padframe
24 * periphery. The purpose is to avoid a massive number of control
25 * wires between the digital core and I/O, passing through the user area.
26 *
27 * See mprj_ctrl.v for the module that registers the data for each
28 * I/O and drives the input to the shift register.
29 *
30 *---------------------------------------------------------------------
31 */
32
33module gpio_control_block #(
Tim Edwards44bab472020-10-04 22:09:54 -040034 parameter PAD_CTRL_BITS = 13,
35 // Parameterized initial startup state of the pad.
36 // The default parameters if unspecified is for the pad to be
37 // an input with no pull-up or pull-down, so that it is disconnected
38 // from the outside world.
39 parameter HOLD_INIT = 1'b0,
40 parameter SLOW_INIT = 1'b0,
41 parameter TRIP_INIT = 1'b0,
42 parameter IB_INIT = 1'b0,
43 parameter IENB_INIT = 1'b0,
44 parameter OENB_INIT = 1'b1,
45 parameter DM_INIT = 3'b001,
46 parameter AENA_INIT = 1'b0,
47 parameter ASEL_INIT = 1'b0,
48 parameter APOL_INIT = 1'b0
Tim Edwards04ba17f2020-10-02 22:27:50 -040049) (
50 // Management Soc-facing signals
51 input resetn, // Global reset
52 input serial_clock,
53
54 inout mgmt_gpio_io, // Management to/from pad
55
56 // Serial data chain for pad configuration
57 input serial_data_in,
58 output serial_data_out,
59
60 // User-facing signals
61 input user_gpio_out, // User space to pad
Tim Edwards44bab472020-10-04 22:09:54 -040062 input user_gpio_oeb, // Output enable (user)
Tim Edwards04ba17f2020-10-02 22:27:50 -040063 output user_gpio_in, // Pad to user space
64
65 // Pad-facing signals (Pad GPIOv2)
66 output pad_gpio_holdover,
67 output pad_gpio_slow_sel,
68 output pad_gpio_vtrip_sel,
69 output pad_gpio_inenb,
70 output pad_gpio_ib_mode_sel,
71 output pad_gpio_ana_en,
72 output pad_gpio_ana_sel,
73 output pad_gpio_ana_pol,
74 output [2:0] pad_gpio_dm,
Tim Edwards44bab472020-10-04 22:09:54 -040075 output pad_gpio_oeb,
Tim Edwards04ba17f2020-10-02 22:27:50 -040076 output pad_gpio_out,
77 input pad_gpio_in
78);
79
80 /* Parameters defining the bit offset of each function in the chain */
81 localparam MGMT_EN = 0;
82 localparam OEB = 1;
83 localparam HLDH = 2;
Tim Edwards44bab472020-10-04 22:09:54 -040084 localparam INP_DIS = 2;
85 localparam MOD_SEL = 4;
86 localparam AN_EN = 5;
87 localparam AN_SEL = 6;
88 localparam AN_POL = 7;
89 localparam SLOW = 8;
90 localparam TRIP = 9;
91 localparam DM = 10;
Tim Edwards04ba17f2020-10-02 22:27:50 -040092
93 /* Internally registered signals */
94 reg mgmt_ena; // Enable management SoC to access pad
95 reg gpio_holdover;
96 reg gpio_slow_sel;
97 reg gpio_vtrip_sel;
98 reg gpio_inenb;
99 reg gpio_ib_mode_sel;
100 reg gpio_outenb;
101 reg [2:0] gpio_dm;
102 reg gpio_ana_en;
103 reg gpio_ana_sel;
104 reg gpio_ana_pol;
105
106 /* Derived output values */
107 wire pad_gpio_holdover;
108 wire pad_gpio_slow_sel;
109 wire pad_gpio_vtrip_sel;
110 wire pad_gpio_inenb;
111 wire pad_gpio_ib_mode_sel;
112 wire pad_gpio_ana_en;
113 wire pad_gpio_ana_sel;
114 wire pad_gpio_ana_pol;
115 wire [2:0] pad_gpio_dm;
116 wire pad_gpio_outenb;
117 wire pad_gpio_out;
118 wire pad_gpio_in;
119
120 /* Serial shift for the above (latched) values */
121 reg [PAD_CTRL_BITS-1:0] shift_register;
122
123 /* Utilize reset and clock to encode a load operation */
124 wire load_data;
125 wire int_reset;
126
127 /* Create internal reset and load signals from input reset and clock */
128 assign serial_data_out = shift_register[PAD_CTRL_BITS-1];
129 assign int_reset = (~resetn) & (~serial_clock);
130 assign load_data = (~resetn) & serial_clock;
131
132 always @(posedge serial_clock or posedge int_reset) begin
133 if (int_reset == 1'b1) begin
134 /* Clear shift register */
135 shift_register <= 'd0;
136 end else begin
137 /* Shift data in */
138 shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in};
139 end
140 end
141
142 always @(posedge load_data or posedge int_reset) begin
143 if (int_reset == 1'b1) begin
144 /* Initial state on reset: Pad set to management input */
Tim Edwards44bab472020-10-04 22:09:54 -0400145 mgmt_ena <= 1'b1; // Management SoC has control over all I/O
146 gpio_holdover <= HOLD_INIT; // All signals latched in hold mode
147 gpio_slow_sel <= SLOW_INIT; // Fast slew rate
148 gpio_vtrip_sel <= TRIP_INIT; // CMOS mode
149 gpio_ib_mode_sel <= IB_INIT; // CMOS mode
150 gpio_inenb <= IENB_INIT; // Input enabled
151 gpio_outenb <= OENB_INIT; // Output disabled
152 gpio_dm <= DM_INIT; // Configured as input only
153 gpio_ana_en <= AENA_INIT; // Digital enabled
154 gpio_ana_sel <= ASEL_INIT; // Don't-care when gpio_ana_en = 0
155 gpio_ana_pol <= APOL_INIT; // Don't-care when gpio_ana_en = 0
Tim Edwards04ba17f2020-10-02 22:27:50 -0400156 end else begin
157 /* Load data */
158 mgmt_ena <= shift_register[MGMT_EN];
159 gpio_outenb <= shift_register[OEB];
160 gpio_holdover <= shift_register[HLDH];
161 gpio_inenb <= shift_register[INP_DIS];
162 gpio_ib_mode_sel <= shift_register[MOD_SEL];
163 gpio_ana_en <= shift_register[AN_EN];
164 gpio_ana_sel <= shift_register[AN_SEL];
165 gpio_ana_pol <= shift_register[AN_POL];
166 gpio_slow_sel <= shift_register[SLOW];
167 gpio_vtrip_sel <= shift_register[TRIP];
168 gpio_dm <= shift_register[DM+2:DM];
169
170 end
171 end
172
173 /* These pad configuration signals are static and do not change */
174 /* after setup. */
175
176 assign pad_gpio_holdover = gpio_holdover;
177 assign pad_gpio_slow_sel = gpio_slow_sel;
178 assign pad_gpio_vtrip_sel = gpio_vtrip_sel;
179 assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel;
180 assign pad_gpio_ana_en = gpio_ana_en;
181 assign pad_gpio_ana_sel = gpio_ana_sel;
182 assign pad_gpio_ana_pol = gpio_ana_pol;
183 assign pad_gpio_dm = gpio_dm;
184 assign pad_gpio_inenb = gpio_inenb;
185
186 /* Implement pad control behavior depending on state of mgmt_ena */
187
188 /* If pad is configured for input and dm[2:1] is 01, then pad is */
189 /* configured as pull-up or pull-down depending on dm[0], and to */
190 /* set the pullup or pulldown condition, the pad output bit must */
191 /* be set to the opposite state of dm[0]. */
192 /* dm[0] = 0 is pull-down; dm[0] = 1 is pull-up. */
Tim Edwards44bab472020-10-04 22:09:54 -0400193 /* */
194 /* This is done for management control only, since the management */
195 /* control has only 1 inout signal for both input and output, and */
196 /* cannot set the output and read the input simultaneously. The */
197 /* user has control over both lines and only needs to be told what */
198 /* to set the output line to, to enable a pullup or pulldown. */
Tim Edwards04ba17f2020-10-02 22:27:50 -0400199
Tim Edwards44bab472020-10-04 22:09:54 -0400200 assign pad_gpio_out = (mgmt_ena) ?
201 (((gpio_dm[2:1] == 2'b01) && (gpio_inenb == 1'b0)) ?
202 ~gpio_dm[0] : mgmt_gpio_io) : user_gpio_out;
Tim Edwards04ba17f2020-10-02 22:27:50 -0400203
204 /* When under user control, gpio_outenb = 1 means that the pad is */
205 /* configured as input, and the user outenb is unused. Otherwise, */
206 /* the pad outenb signal is controlled by the user. */
207
208 assign pad_gpio_outenb = (mgmt_ena) ? gpio_outenb :
Tim Edwards44bab472020-10-04 22:09:54 -0400209 ((gpio_outenb == 1) ? 1'b1 : user_gpio_oeb);
Tim Edwards04ba17f2020-10-02 22:27:50 -0400210
211 /* User gpio_in is grounded when the management controls the pad */
212 assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
213
214 /* Management I/O line is set from the pad when the pad is */
215 /* configured for input. */
216 assign mgmt_gpio_io = (gpio_inenb == 0) ? pad_gpio_in : 1'bz;
217
218endmodule