Fri, 13 Aug 2010 10:41:29 +0100
Initial commit, GPIO v3.1
1 // =============================================================================
2 // COPYRIGHT NOTICE
3 // Copyright 2004 (c) Lattice Semiconductor Corporation
4 // ALL RIGHTS RESERVED
5 // This confidential and proprietary software may be used only as authorised by
6 // a licensing agreement from Lattice Semiconductor Corporation.
7 // The entire notice above must be reproduced on all authorized copies and
8 // copies may only be made to the extent permitted by a licensing agreement from
9 // Lattice Semiconductor Corporation.
10 //
11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
12 // 5555 NE Moore Court 408-826-6000 (other locations)
13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
14 // U.S.A email: techsupport@latticesemi.com
15 // =============================================================================/
16 // FILE DETAILS
17 // Project : GPIO for LM32
18 // File : gpio.v
19 // Title : General Purpose IO Component
20 // Dependencies : system_conf.v
21 // Description : Implements the logic to interface general purpuse IO with
22 // Wishbone bus.
23 // =============================================================================
24 // REVISION HISTORY
25 // Version : 7.0
26 // Mod. Date : Jun 27, 2005
27 // Changes Made : Initial Creation
28 //
29 // Version : 7.0SP2, 3.0
30 // Mod. Date : 20 Nov. 2007
31 // Changes Made : Code clean up.
32 //
33 // Version : 3.1
34 // Mod. Date : 11 Oct. 2008
35 // Changes Made : Update the Edge Capture Register clean method
36 // Make IRQ Mask register readable
37 // =============================================================================
38 `ifndef GPIO_V
39 `define GPIO_V
40 `timescale 1ns/100 ps
41 `include "system_conf.v"
42 module gpio #(parameter DATA_WIDTH = 16,
43 parameter INPUT_WIDTH = 16,
44 parameter OUTPUT_WIDTH = 16,
45 parameter IRQ_MODE = 0,
46 parameter LEVEL = 0,
47 parameter EDGE = 0,
48 parameter POSE_EDGE_IRQ = 0,
49 parameter NEGE_EDGE_IRQ = 0,
50 parameter EITHER_EDGE_IRQ = 0,
51 parameter INPUT_PORTS_ONLY = 1,
52 parameter OUTPUT_PORTS_ONLY = 0,
53 parameter BOTH_INPUT_AND_OUTPUT = 0,
54 parameter TRISTATE_PORTS = 0)
55 (
56 //system clock and reset
57 CLK_I,
58 RST_I,
59 //wishbone interface signals
60 GPIO_ADR_I,
61 GPIO_CYC_I,
62 GPIO_DAT_I,
63 GPIO_SEL_I,
64 GPIO_STB_I,
65 GPIO_WE_I,
66 GPIO_LOCK_I,
67 GPIO_CTI_I,
68 GPIO_BTE_I,
69 GPIO_ACK_O,
70 GPIO_RTY_O,
71 GPIO_DAT_O,
72 GPIO_ERR_O,
73 IRQ_O, //bit_or of all IRQs
74 //PIO side
75 PIO_IN,
76 PIO_OUT,
77 PIO_IO,
78 PIO_BOTH_IN,
79 PIO_BOTH_OUT
80 );
82 //---------------------------------------------------------------------
83 // inputs
84 //
85 input CLK_I;
86 input RST_I;
87 input [31:0] GPIO_ADR_I;
88 input GPIO_CYC_I;
89 input [31:0] GPIO_DAT_I;
90 input [3:0] GPIO_SEL_I;
91 input GPIO_STB_I;
92 input GPIO_WE_I;
93 input GPIO_LOCK_I;
94 input [2:0] GPIO_CTI_I;
95 input [1:0] GPIO_BTE_I;
96 input [DATA_WIDTH-1:0] PIO_IN;
97 input [INPUT_WIDTH-1:0] PIO_BOTH_IN;
98 //---------------------------------------------------------------------
99 // outputs
100 //
101 output GPIO_ACK_O;
102 output GPIO_RTY_O;
103 output [31:0] GPIO_DAT_O;
104 output GPIO_ERR_O;
105 output IRQ_O;
106 output [DATA_WIDTH-1:0] PIO_OUT;
107 output [OUTPUT_WIDTH-1:0] PIO_BOTH_OUT;
108 //----------------
109 //inout mode
110 inout [DATA_WIDTH-1:0] PIO_IO;
111 //----------------
112 //process
114 parameter UDLY = 1;
116 wire ADR_0;
117 wire ADR_4;
118 wire ADR_8;
119 wire ADR_C;
120 wire read_addr_0;
121 wire read_addr_4;
122 wire read_addr_8;
123 wire read_addr_C;
124 wire GPIO_RTY_O;
125 wire GPIO_ERR_O;
126 wire [31:0] GPIO_DAT_O;
127 wire IRQ_O;
128 wire [DATA_WIDTH-1:0] PIO_OUT;
129 wire [OUTPUT_WIDTH-1:0] PIO_BOTH_OUT;
130 wire [DATA_WIDTH-1:0] tpio_out;
131 wire PIO_DATA_WR_EN;
132 wire PIO_TRI_WR_EN;
133 wire IRQ_MASK_WR_EN;
134 wire EDGE_CAP_WR_EN;
135 wire PIO_DATA_RE_EN;
136 wire PIO_TRI_RE_EN;
137 wire IRQ_MASK_RE_EN;
138 wire [DATA_WIDTH-1:0] IRQ_TRI_TEMP;
139 reg [DATA_WIDTH-1:0] PIO_DATA;
140 reg [DATA_WIDTH-1:0] IRQ_MASK;
141 reg [INPUT_WIDTH-1:0] IRQ_MASK_BOTH;
142 reg [DATA_WIDTH-1:0] IRQ_TEMP;
143 reg [INPUT_WIDTH-1:0] IRQ_TEMP_BOTH;
144 reg [DATA_WIDTH-1:0] EDGE_CAPTURE;
145 reg [INPUT_WIDTH-1:0] EDGE_CAPTURE_BOTH;
146 reg [DATA_WIDTH-1:0] PIO_DATA_DLY;
147 reg [INPUT_WIDTH-1:0] PIO_DATA_DLY_BOTH;
148 reg [OUTPUT_WIDTH-1:0] PIO_DATAO;
149 reg [INPUT_WIDTH-1 :0] PIO_DATAI;
150 reg GPIO_ACK_O;
152 assign GPIO_RTY_O = 1'b0;
153 assign GPIO_ERR_O = 1'b0;
154 assign ADR_0 = (GPIO_ADR_I[3:0] == 4'b0000 ? 1'b1 : 0); // IO Data
155 assign ADR_4 = (GPIO_ADR_I[3:0] == 4'b0100 ? 1'b1 : 0); // Tri-state Control
156 assign ADR_8 = (GPIO_ADR_I[3:0] == 4'b1000 ? 1'b1 : 0); // IRQ Mask
157 assign ADR_C = (GPIO_ADR_I[3:0] == 4'b1100 ? 1'b1 : 0); // Edge Capture
158 assign read_addr_0 = (ADR_0 & GPIO_STB_I & ~GPIO_WE_I) ;
159 assign read_addr_4 = (ADR_4 & GPIO_STB_I & ~GPIO_WE_I) ;
160 assign read_addr_8 = (IRQ_MODE == 1 && (ADR_8 & GPIO_STB_I & ~GPIO_WE_I));
161 assign read_addr_C = (IRQ_MODE == 1 && (ADR_C & GPIO_STB_I & ~GPIO_WE_I));
163 always @(posedge CLK_I or posedge RST_I)
164 if(RST_I)
165 GPIO_ACK_O <= #UDLY 1'b0;
166 else if( GPIO_STB_I && !GPIO_ACK_O)
167 GPIO_ACK_O <= #UDLY 1'b1;
168 else
169 GPIO_ACK_O <= #UDLY 1'b0;
171 generate
172 if (INPUT_PORTS_ONLY == 1) begin
173 always @(posedge CLK_I or posedge RST_I)
174 if (RST_I)
175 PIO_DATA <= #UDLY 0;
176 else if (GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && ADR_0 == 1'b1 && GPIO_SEL_I == 4'b1111)
177 PIO_DATA <= #UDLY PIO_IN;
178 end
179 endgenerate
181 generate
182 if (OUTPUT_PORTS_ONLY == 1) begin
183 always @(posedge CLK_I or posedge RST_I)
184 if (RST_I)
185 PIO_DATA <= #UDLY 0;
186 else if (GPIO_STB_I && !GPIO_ACK_O && GPIO_WE_I && ADR_0 == 1'b1 && GPIO_SEL_I == 4'b1111)
187 PIO_DATA <= #UDLY GPIO_DAT_I[DATA_WIDTH-1:0];
189 assign PIO_OUT = PIO_DATA;
190 end
191 endgenerate
193 generate
194 if (BOTH_INPUT_AND_OUTPUT == 1) begin
195 always @(posedge CLK_I or posedge RST_I)
196 if (RST_I) begin
197 PIO_DATAI <= #UDLY 0;
198 PIO_DATAO <= #UDLY 0;
199 end else if (GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111)
200 PIO_DATAI <= #UDLY PIO_BOTH_IN;
201 else if (GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111)
202 PIO_DATAO <= #UDLY GPIO_DAT_I[OUTPUT_WIDTH-1:0];
204 assign PIO_BOTH_OUT = PIO_DATAO[OUTPUT_WIDTH-1:0];
205 end
206 endgenerate
208 assign PIO_DATA_RE_EN = GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111;
209 assign PIO_TRI_RE_EN = GPIO_STB_I && GPIO_ACK_O && !GPIO_WE_I && (ADR_4 == 1'b1) && GPIO_SEL_I == 4'b1111;
210 assign IRQ_MASK_RE_EN = GPIO_STB_I && GPIO_ACK_O && !GPIO_WE_I && (ADR_8 == 1'b1) && GPIO_SEL_I == 4'b1111;
211 assign PIO_DATA_WR_EN = GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111;
212 assign PIO_TRI_WR_EN = GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_4 == 1'b1) && GPIO_SEL_I == 4'b1111;
213 assign IRQ_MASK_WR_EN = GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_8 == 1'b1) && GPIO_SEL_I == 4'b1111;
214 assign EDGE_CAP_WR_EN = GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_C == 1'b1) && GPIO_SEL_I == 4'b1111;
216 generate
217 genvar ti;
218 for (ti = 0 ; ti < DATA_WIDTH; ti = ti + 1)
219 begin : tio_inst
220 TRI_PIO #(.DATA_WIDTH(DATA_WIDTH),
221 .IRQ_MODE(IRQ_MODE),
222 .LEVEL(LEVEL),
223 .EDGE(EDGE),
224 .POSE_EDGE_IRQ(POSE_EDGE_IRQ),
225 .NEGE_EDGE_IRQ(NEGE_EDGE_IRQ),
226 .EITHER_EDGE_IRQ(EITHER_EDGE_IRQ))
227 TP (.CLK_I(CLK_I),
228 .RST_I(RST_I),
229 .DAT_I(GPIO_DAT_I[ti]),
230 .DAT_O(tpio_out[ti]),
231 .PIO_IO(PIO_IO[ti]),
232 .IRQ_O(IRQ_TRI_TEMP[ti]),
233 .PIO_TRI_WR_EN(PIO_TRI_WR_EN),
234 .PIO_TRI_RE_EN(PIO_TRI_RE_EN),
235 .PIO_DATA_WR_EN(PIO_DATA_WR_EN),
236 .PIO_DATA_RE_EN(PIO_DATA_RE_EN),
237 .IRQ_MASK_WR_EN(IRQ_MASK_WR_EN),
238 .IRQ_MASK_RE_EN(IRQ_MASK_RE_EN),
239 .EDGE_CAP_WR_EN(EDGE_CAP_WR_EN));
240 end
241 endgenerate
243 generate
244 if (INPUT_PORTS_ONLY == 1)
245 assign GPIO_DAT_O = read_addr_0 ? PIO_DATA :
246 read_addr_8 ? IRQ_MASK :
247 read_addr_C ? EDGE_CAPTURE :
248 0;
249 else if (BOTH_INPUT_AND_OUTPUT == 1)
250 assign GPIO_DAT_O = read_addr_0 ? PIO_DATAI :
251 read_addr_8 ? IRQ_MASK_BOTH :
252 read_addr_C ? EDGE_CAPTURE_BOTH :
253 0;
254 else if (TRISTATE_PORTS == 1)
255 assign GPIO_DAT_O = read_addr_0 ? tpio_out :
256 read_addr_4 ? tpio_out :
257 read_addr_8 ? tpio_out :
258 read_addr_C ? IRQ_TRI_TEMP :
259 0;
260 else
261 assign GPIO_DAT_O = 0;
262 endgenerate
264 //-----------------------------------------------------------------------------
265 //-------------------------------IRQ Generation--------------------------------
266 //-----------------------------------------------------------------------------
267 generate
268 if (IRQ_MODE == 1) begin
269 always @(posedge CLK_I or posedge RST_I)
270 if (RST_I) begin
271 IRQ_MASK <= #UDLY 0;
272 IRQ_MASK_BOTH <= #UDLY 0;
273 end else if (IRQ_MASK_WR_EN) begin
274 IRQ_MASK <= #UDLY GPIO_DAT_I[DATA_WIDTH-1:0];
275 IRQ_MASK_BOTH <= #UDLY GPIO_DAT_I[INPUT_WIDTH-1:0];
276 end
277 end
278 endgenerate
280 generate
281 //--------------------------------
282 //--INPUT_PORTS_ONLY MODE IRQ
283 //--------------------------------
284 if (IRQ_MODE == 1 && INPUT_PORTS_ONLY == 1 && LEVEL == 1) begin
285 //level mode IRQ
286 always @(posedge CLK_I or posedge RST_I)
287 if (RST_I)
288 IRQ_TEMP <= #UDLY 0;
289 else if (IRQ_MASK_WR_EN)
290 IRQ_TEMP <= #UDLY IRQ_TEMP & GPIO_DAT_I[DATA_WIDTH-1:0];
291 else
292 IRQ_TEMP <= #UDLY PIO_IN & IRQ_MASK;//bit-and
293 assign IRQ_O = |IRQ_TEMP;
294 end else if (IRQ_MODE == 1 && INPUT_PORTS_ONLY == 1 && EDGE == 1) begin
295 always @(posedge CLK_I or posedge RST_I)
296 if (RST_I)
297 PIO_DATA_DLY <= #UDLY 0;
298 else
299 PIO_DATA_DLY <= PIO_IN;
301 // edge-capture register bits are treated as individual bits.
302 genvar i;
303 for( i = 0; i < DATA_WIDTH; i = i + 1)
304 begin
305 always @(posedge CLK_I or posedge RST_I)
306 if (RST_I)
307 EDGE_CAPTURE[i] <= #UDLY 0;
308 else if (|(PIO_IN[i] & ~PIO_DATA_DLY[i]) && (POSE_EDGE_IRQ == 1))
309 EDGE_CAPTURE[i] <= #UDLY PIO_IN[i] & ~PIO_DATA_DLY[i];
310 else if (|(~PIO_IN[i] & PIO_DATA_DLY[i]) && (NEGE_EDGE_IRQ == 1))
311 EDGE_CAPTURE[i] <= #UDLY ~PIO_IN[i] & PIO_DATA_DLY[i];
312 else if (|(PIO_IN[i] & ~PIO_DATA_DLY[i]) && (EITHER_EDGE_IRQ == 1))
313 EDGE_CAPTURE[i] <= #UDLY PIO_IN[i] & ~PIO_DATA_DLY[i];
314 else if (|(~PIO_IN[i] & PIO_DATA_DLY[i]) && (EITHER_EDGE_IRQ == 1))
315 EDGE_CAPTURE[i] <= #UDLY ~PIO_IN[i] & PIO_DATA_DLY[i];
316 else if ( (~IRQ_MASK[i]) & GPIO_DAT_I[i] & IRQ_MASK_WR_EN )
317 // interrupt mask is being set, so clear edge-capture
318 EDGE_CAPTURE[i] <= #UDLY 0;
319 else if (EDGE_CAP_WR_EN)
320 // user's writing to the edge register, so update edge capture
321 // register
322 EDGE_CAPTURE[i] <= #UDLY EDGE_CAPTURE[i] & GPIO_DAT_I[i];
323 end
324 assign IRQ_O = |(EDGE_CAPTURE & IRQ_MASK);
326 //----------------------------------
327 //--BOTH_INPUT_AND_OUTPUT MODE IRQ
328 //----------------------------------
329 end else if (IRQ_MODE == 1 && BOTH_INPUT_AND_OUTPUT == 1 && LEVEL == 1) begin
330 always @(posedge CLK_I or posedge RST_I)
331 if (RST_I)
332 IRQ_TEMP_BOTH <= #UDLY 0;
333 else if (IRQ_MASK_WR_EN)
334 IRQ_TEMP_BOTH <= #UDLY IRQ_TEMP_BOTH & GPIO_DAT_I[INPUT_WIDTH-1:0];
335 else
336 IRQ_TEMP_BOTH <= #UDLY PIO_BOTH_IN & IRQ_MASK_BOTH;
337 assign IRQ_O = |IRQ_TEMP_BOTH;
339 //edge mode IRQ
340 end else if (IRQ_MODE == 1 && BOTH_INPUT_AND_OUTPUT == 1 && EDGE == 1) begin
341 always @(posedge CLK_I or posedge RST_I)
342 if (RST_I)
343 PIO_DATA_DLY_BOTH <= #UDLY 0;
344 else
345 PIO_DATA_DLY_BOTH <= PIO_BOTH_IN;
347 // edge-capture register bits are treated as individual bits.
348 genvar i_both;
349 for( i_both = 0; i_both < INPUT_WIDTH; i_both = i_both + 1)
350 begin
351 always @(posedge CLK_I or posedge RST_I)
352 if (RST_I)
353 EDGE_CAPTURE_BOTH[i_both] <= #UDLY 0;
354 else if (|(PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both]) && POSE_EDGE_IRQ == 1)
355 EDGE_CAPTURE_BOTH[i_both] <= #UDLY PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both];
356 else if (|(~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both]) && NEGE_EDGE_IRQ == 1)
357 EDGE_CAPTURE_BOTH[i_both] <= #UDLY ~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both];
358 else if (|(PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both]) && EITHER_EDGE_IRQ == 1)
359 EDGE_CAPTURE_BOTH[i_both] <= #UDLY PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both];
360 else if (|(~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both]) && EITHER_EDGE_IRQ == 1)
361 EDGE_CAPTURE_BOTH[i_both] <= #UDLY ~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both];
362 else if ( (~IRQ_MASK_BOTH[i_both]) & GPIO_DAT_I[i_both] & IRQ_MASK_WR_EN )
363 // interrupt mask is being set, so clear edge-capture
364 EDGE_CAPTURE_BOTH[i_both] <= #UDLY 0;
365 else if (EDGE_CAP_WR_EN)
366 // user's writing to the edge register, so update edge capture
367 // register
368 EDGE_CAPTURE_BOTH[i_both] <= #UDLY EDGE_CAPTURE_BOTH[i_both] & GPIO_DAT_I[i_both];
369 end
370 assign IRQ_O = |(EDGE_CAPTURE_BOTH & IRQ_MASK_BOTH);
372 end else if (IRQ_MODE == 1 && TRISTATE_PORTS == 1) begin
373 assign IRQ_O = |IRQ_TRI_TEMP;
374 end else
375 assign IRQ_O = 1'b0;
376 endgenerate
378 endmodule
379 `endif // GPIO_V