rtl/verilog/gpio.v

Fri, 13 Aug 2010 10:41:29 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 13 Aug 2010 10:41:29 +0100
changeset 0
267b5a25932f
child 1
dfc32cad81ba
permissions
-rw-r--r--

Initial commit, GPIO v3.1

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