blob: 157584106725552d3154e13028fe21a04a190633 [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 #(
34 parameter PAD_CTRL_BITS = 13
35) (
36 // Management Soc-facing signals
37 input resetn, // Global reset
38 input serial_clock,
39
40 inout mgmt_gpio_io, // Management to/from pad
41
42 // Serial data chain for pad configuration
43 input serial_data_in,
44 output serial_data_out,
45
46 // User-facing signals
47 input user_gpio_out, // User space to pad
48 input user_gpio_outenb, // Output enable (user)
49 output user_gpio_in, // Pad to user space
50
51 // Pad-facing signals (Pad GPIOv2)
52 output pad_gpio_holdover,
53 output pad_gpio_slow_sel,
54 output pad_gpio_vtrip_sel,
55 output pad_gpio_inenb,
56 output pad_gpio_ib_mode_sel,
57 output pad_gpio_ana_en,
58 output pad_gpio_ana_sel,
59 output pad_gpio_ana_pol,
60 output [2:0] pad_gpio_dm,
61 output pad_gpio_outenb,
62 output pad_gpio_out,
63 input pad_gpio_in
64);
65
66 /* Parameters defining the bit offset of each function in the chain */
67 localparam MGMT_EN = 0;
68 localparam OEB = 1;
69 localparam HLDH = 2;
70 localparam ENH = 3;
71 localparam INP_DIS = 4;
72 localparam MOD_SEL = 5;
73 localparam AN_EN = 6;
74 localparam AN_SEL = 7;
75 localparam AN_POL = 8;
76 localparam SLOW = 9;
77 localparam TRIP = 10;
78 localparam DM = 11;
79
80 /* Internally registered signals */
81 reg mgmt_ena; // Enable management SoC to access pad
82 reg gpio_holdover;
83 reg gpio_slow_sel;
84 reg gpio_vtrip_sel;
85 reg gpio_inenb;
86 reg gpio_ib_mode_sel;
87 reg gpio_outenb;
88 reg [2:0] gpio_dm;
89 reg gpio_ana_en;
90 reg gpio_ana_sel;
91 reg gpio_ana_pol;
92
93 /* Derived output values */
94 wire pad_gpio_holdover;
95 wire pad_gpio_slow_sel;
96 wire pad_gpio_vtrip_sel;
97 wire pad_gpio_inenb;
98 wire pad_gpio_ib_mode_sel;
99 wire pad_gpio_ana_en;
100 wire pad_gpio_ana_sel;
101 wire pad_gpio_ana_pol;
102 wire [2:0] pad_gpio_dm;
103 wire pad_gpio_outenb;
104 wire pad_gpio_out;
105 wire pad_gpio_in;
106
107 /* Serial shift for the above (latched) values */
108 reg [PAD_CTRL_BITS-1:0] shift_register;
109
110 /* Utilize reset and clock to encode a load operation */
111 wire load_data;
112 wire int_reset;
113
114 /* Create internal reset and load signals from input reset and clock */
115 assign serial_data_out = shift_register[PAD_CTRL_BITS-1];
116 assign int_reset = (~resetn) & (~serial_clock);
117 assign load_data = (~resetn) & serial_clock;
118
119 always @(posedge serial_clock or posedge int_reset) begin
120 if (int_reset == 1'b1) begin
121 /* Clear shift register */
122 shift_register <= 'd0;
123 end else begin
124 /* Shift data in */
125 shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in};
126 end
127 end
128
129 always @(posedge load_data or posedge int_reset) begin
130 if (int_reset == 1'b1) begin
131 /* Initial state on reset: Pad set to management input */
132 mgmt_ena <= 1'b0;
133 gpio_holdover <= 1'b0; // All signals latched in hold mode
134 gpio_slow_sel <= 1'b0; // Fast slew rate
135 gpio_vtrip_sel <= 1'b0; // CMOS mode
136 gpio_ib_mode_sel <= 1'b0; // CMOS mode
137 gpio_inenb <= 1'b0; // Input enabled
138 gpio_outenb <= 1'b1; // Output disabled
139 gpio_dm <= 3'b001; // Configured as input only
140 gpio_ana_en <= 1'b0; // Digital enabled
141 gpio_ana_sel <= 1'b0; // Don't-care when gpio_ana_en = 0
142 gpio_ana_pol <= 1'b0; // Don't-care when gpio_ana_en = 0
143 end else begin
144 /* Load data */
145 mgmt_ena <= shift_register[MGMT_EN];
146 gpio_outenb <= shift_register[OEB];
147 gpio_holdover <= shift_register[HLDH];
148 gpio_inenb <= shift_register[INP_DIS];
149 gpio_ib_mode_sel <= shift_register[MOD_SEL];
150 gpio_ana_en <= shift_register[AN_EN];
151 gpio_ana_sel <= shift_register[AN_SEL];
152 gpio_ana_pol <= shift_register[AN_POL];
153 gpio_slow_sel <= shift_register[SLOW];
154 gpio_vtrip_sel <= shift_register[TRIP];
155 gpio_dm <= shift_register[DM+2:DM];
156
157 end
158 end
159
160 /* These pad configuration signals are static and do not change */
161 /* after setup. */
162
163 assign pad_gpio_holdover = gpio_holdover;
164 assign pad_gpio_slow_sel = gpio_slow_sel;
165 assign pad_gpio_vtrip_sel = gpio_vtrip_sel;
166 assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel;
167 assign pad_gpio_ana_en = gpio_ana_en;
168 assign pad_gpio_ana_sel = gpio_ana_sel;
169 assign pad_gpio_ana_pol = gpio_ana_pol;
170 assign pad_gpio_dm = gpio_dm;
171 assign pad_gpio_inenb = gpio_inenb;
172
173 /* Implement pad control behavior depending on state of mgmt_ena */
174
175 /* If pad is configured for input and dm[2:1] is 01, then pad is */
176 /* configured as pull-up or pull-down depending on dm[0], and to */
177 /* set the pullup or pulldown condition, the pad output bit must */
178 /* be set to the opposite state of dm[0]. */
179 /* dm[0] = 0 is pull-down; dm[0] = 1 is pull-up. */
180 /* Otherwise, the output
181
182 assign pad_gpio_out = (mgmt_ena) ? mgmt_gpio_io :
183 (((gpio_dm[2:1] == 2'b01) && (gpio_inenb == 1'b0)) ?
184 ~gpio_dm[0] : user_gpio_out);
185
186 /* When under user control, gpio_outenb = 1 means that the pad is */
187 /* configured as input, and the user outenb is unused. Otherwise, */
188 /* the pad outenb signal is controlled by the user. */
189
190 assign pad_gpio_outenb = (mgmt_ena) ? gpio_outenb :
191 ((gpio_outenb == 1) ? 1'b1 : user_gpio_outenb);
192
193 /* User gpio_in is grounded when the management controls the pad */
194 assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
195
196 /* Management I/O line is set from the pad when the pad is */
197 /* configured for input. */
198 assign mgmt_gpio_io = (gpio_inenb == 0) ? pad_gpio_in : 1'bz;
199
200endmodule