rtl/verilog/gpio.v

changeset 0
267b5a25932f
child 1
dfc32cad81ba
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rtl/verilog/gpio.v	Fri Aug 13 10:41:29 2010 +0100
     1.3 @@ -0,0 +1,379 @@
     1.4 +// =============================================================================
     1.5 +//                           COPYRIGHT NOTICE
     1.6 +// Copyright 2004 (c) Lattice Semiconductor Corporation
     1.7 +// ALL RIGHTS RESERVED
     1.8 +// This confidential and proprietary software may be used only as authorised by
     1.9 +// a licensing agreement from Lattice Semiconductor Corporation.
    1.10 +// The entire notice above must be reproduced on all authorized copies and
    1.11 +// copies may only be made to the extent permitted by a licensing agreement from
    1.12 +// Lattice Semiconductor Corporation.
    1.13 +//
    1.14 +// Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
    1.15 +// 5555 NE Moore Court                            408-826-6000 (other locations)
    1.16 +// Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
    1.17 +// U.S.A                                   email: techsupport@latticesemi.com
    1.18 +// =============================================================================/
    1.19 +//                         FILE DETAILS
    1.20 +// Project          : GPIO for LM32
    1.21 +// File             : gpio.v
    1.22 +// Title            : General Purpose IO Component 
    1.23 +// Dependencies     : system_conf.v
    1.24 +// Description      : Implements the logic to interface general purpuse IO with 
    1.25 +//                    Wishbone bus.
    1.26 +// =============================================================================
    1.27 +//                        REVISION HISTORY
    1.28 +// Version          : 7.0
    1.29 +// Mod. Date        : Jun 27, 2005
    1.30 +// Changes Made     : Initial Creation
    1.31 +//
    1.32 +// Version          : 7.0SP2, 3.0
    1.33 +// Mod. Date        : 20 Nov. 2007
    1.34 +// Changes Made     : Code clean up.
    1.35 +//
    1.36 +// Version          : 3.1
    1.37 +// Mod. Date        : 11 Oct. 2008
    1.38 +// Changes Made     : Update the Edge Capture Register clean method
    1.39 +//                    Make IRQ Mask register readable
    1.40 +// =============================================================================
    1.41 +`ifndef GPIO_V
    1.42 +`define GPIO_V
    1.43 +`timescale 1ns/100 ps
    1.44 +`include "system_conf.v"
    1.45 +module gpio #(parameter DATA_WIDTH = 16,
    1.46 +              parameter INPUT_WIDTH = 16,
    1.47 +              parameter OUTPUT_WIDTH = 16,
    1.48 +              parameter IRQ_MODE = 0,
    1.49 +              parameter LEVEL = 0,
    1.50 +              parameter EDGE = 0,
    1.51 +              parameter POSE_EDGE_IRQ = 0,
    1.52 +              parameter NEGE_EDGE_IRQ = 0,
    1.53 +              parameter EITHER_EDGE_IRQ = 0,
    1.54 +              parameter INPUT_PORTS_ONLY = 1,
    1.55 +              parameter OUTPUT_PORTS_ONLY = 0,
    1.56 +              parameter BOTH_INPUT_AND_OUTPUT = 0,
    1.57 +              parameter TRISTATE_PORTS = 0)
    1.58 +     (
    1.59 +     //system clock and reset
    1.60 +     CLK_I,
    1.61 +     RST_I,
    1.62 +     //wishbone interface signals
    1.63 +     GPIO_ADR_I,
    1.64 +     GPIO_CYC_I,
    1.65 +     GPIO_DAT_I,
    1.66 +     GPIO_SEL_I,
    1.67 +     GPIO_STB_I,
    1.68 +     GPIO_WE_I,
    1.69 +     GPIO_LOCK_I,
    1.70 +     GPIO_CTI_I,
    1.71 +     GPIO_BTE_I,
    1.72 +     GPIO_ACK_O,
    1.73 +     GPIO_RTY_O,
    1.74 +     GPIO_DAT_O,
    1.75 +     GPIO_ERR_O,
    1.76 +     IRQ_O, //bit_or of all IRQs
    1.77 +     //PIO side
    1.78 +     PIO_IN,
    1.79 +     PIO_OUT,
    1.80 +     PIO_IO,
    1.81 +     PIO_BOTH_IN,
    1.82 +     PIO_BOTH_OUT
    1.83 +     );
    1.84 +
    1.85 +//---------------------------------------------------------------------
    1.86 +// inputs
    1.87 +   //
    1.88 +   input                   CLK_I;
    1.89 +   input                   RST_I;
    1.90 +   input [31:0]            GPIO_ADR_I;
    1.91 +   input                   GPIO_CYC_I;
    1.92 +   input [31:0]            GPIO_DAT_I;
    1.93 +   input [3:0]             GPIO_SEL_I;
    1.94 +   input                   GPIO_STB_I;
    1.95 +   input                   GPIO_WE_I;
    1.96 +   input                   GPIO_LOCK_I;
    1.97 +   input [2:0]             GPIO_CTI_I;
    1.98 +   input [1:0]             GPIO_BTE_I;   
    1.99 +   input [DATA_WIDTH-1:0]  PIO_IN;
   1.100 +   input [INPUT_WIDTH-1:0] PIO_BOTH_IN;
   1.101 +//---------------------------------------------------------------------
   1.102 +// outputs
   1.103 +//
   1.104 +   output                    GPIO_ACK_O;
   1.105 +   output                    GPIO_RTY_O;
   1.106 +   output [31:0]             GPIO_DAT_O;
   1.107 +   output                    GPIO_ERR_O;
   1.108 +   output                    IRQ_O;
   1.109 +   output [DATA_WIDTH-1:0]   PIO_OUT;
   1.110 +   output [OUTPUT_WIDTH-1:0] PIO_BOTH_OUT;
   1.111 +//----------------
   1.112 +//inout mode
   1.113 +   inout [DATA_WIDTH-1:0]    PIO_IO;
   1.114 +//----------------
   1.115 +//process
   1.116 +   
   1.117 +   parameter    UDLY     = 1;
   1.118 +   
   1.119 +   wire         ADR_0;
   1.120 +   wire         ADR_4;
   1.121 +   wire         ADR_8;
   1.122 +   wire         ADR_C;
   1.123 +   wire         read_addr_0;   
   1.124 +   wire         read_addr_4;   
   1.125 +   wire         read_addr_8;   
   1.126 +   wire         read_addr_C;   
   1.127 +   wire         GPIO_RTY_O;
   1.128 +   wire         GPIO_ERR_O;
   1.129 +   wire [31:0]  GPIO_DAT_O;
   1.130 +   wire         IRQ_O;
   1.131 +   wire [DATA_WIDTH-1:0]   PIO_OUT;
   1.132 +   wire [OUTPUT_WIDTH-1:0] PIO_BOTH_OUT;
   1.133 +   wire [DATA_WIDTH-1:0]   tpio_out;
   1.134 +   wire                    PIO_DATA_WR_EN;
   1.135 +   wire                    PIO_TRI_WR_EN;
   1.136 +   wire                    IRQ_MASK_WR_EN;
   1.137 +   wire                    EDGE_CAP_WR_EN;
   1.138 +   wire                    PIO_DATA_RE_EN;
   1.139 +   wire                    PIO_TRI_RE_EN;
   1.140 +   wire                    IRQ_MASK_RE_EN;
   1.141 +   wire [DATA_WIDTH-1:0]   IRQ_TRI_TEMP;
   1.142 +   reg [DATA_WIDTH-1:0]    PIO_DATA;
   1.143 +   reg [DATA_WIDTH-1:0]    IRQ_MASK;
   1.144 +   reg [INPUT_WIDTH-1:0]   IRQ_MASK_BOTH;
   1.145 +   reg [DATA_WIDTH-1:0]    IRQ_TEMP;
   1.146 +   reg [INPUT_WIDTH-1:0]   IRQ_TEMP_BOTH;
   1.147 +   reg [DATA_WIDTH-1:0]    EDGE_CAPTURE;
   1.148 +   reg [INPUT_WIDTH-1:0]   EDGE_CAPTURE_BOTH;
   1.149 +   reg [DATA_WIDTH-1:0]    PIO_DATA_DLY;
   1.150 +   reg [INPUT_WIDTH-1:0]   PIO_DATA_DLY_BOTH;
   1.151 +   reg [OUTPUT_WIDTH-1:0]  PIO_DATAO; 
   1.152 +   reg [INPUT_WIDTH-1 :0]  PIO_DATAI;
   1.153 +   reg                     GPIO_ACK_O;
   1.154 +
   1.155 +   assign GPIO_RTY_O = 1'b0;
   1.156 +   assign GPIO_ERR_O = 1'b0;
   1.157 +   assign ADR_0 = (GPIO_ADR_I[3:0] == 4'b0000 ? 1'b1 : 0); // IO Data           
   1.158 +   assign ADR_4 = (GPIO_ADR_I[3:0] == 4'b0100 ? 1'b1 : 0); // Tri-state Control 
   1.159 +   assign ADR_8 = (GPIO_ADR_I[3:0] == 4'b1000 ? 1'b1 : 0); // IRQ Mask          
   1.160 +   assign ADR_C = (GPIO_ADR_I[3:0] == 4'b1100 ? 1'b1 : 0); // Edge Capture      
   1.161 +   assign read_addr_0 =                   (ADR_0 & GPIO_STB_I & ~GPIO_WE_I) ;   
   1.162 +   assign read_addr_4 =                   (ADR_4 & GPIO_STB_I & ~GPIO_WE_I) ;   
   1.163 +   assign read_addr_8 = (IRQ_MODE == 1 && (ADR_8 & GPIO_STB_I & ~GPIO_WE_I));   
   1.164 +   assign read_addr_C = (IRQ_MODE == 1 && (ADR_C & GPIO_STB_I & ~GPIO_WE_I));   
   1.165 +
   1.166 +   always @(posedge CLK_I or posedge RST_I)
   1.167 +     if(RST_I)
   1.168 +       GPIO_ACK_O       <= #UDLY 1'b0;
   1.169 +     else if( GPIO_STB_I && !GPIO_ACK_O)
   1.170 +       GPIO_ACK_O       <= #UDLY 1'b1;
   1.171 +     else
   1.172 +       GPIO_ACK_O       <= #UDLY 1'b0;   
   1.173 +
   1.174 +   generate
   1.175 +      if (INPUT_PORTS_ONLY == 1) begin   
   1.176 +         always @(posedge CLK_I or posedge RST_I)
   1.177 +           if (RST_I)
   1.178 +             PIO_DATA <= #UDLY 0;
   1.179 +           else if (GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && ADR_0 == 1'b1 && GPIO_SEL_I == 4'b1111)       
   1.180 +             PIO_DATA <= #UDLY PIO_IN;
   1.181 +         end
   1.182 +   endgenerate
   1.183 + 
   1.184 +   generate   
   1.185 +      if (OUTPUT_PORTS_ONLY == 1) begin
   1.186 +        always @(posedge CLK_I or posedge RST_I)
   1.187 +          if (RST_I)
   1.188 +            PIO_DATA <= #UDLY 0;
   1.189 +          else if (GPIO_STB_I && !GPIO_ACK_O && GPIO_WE_I && ADR_0 == 1'b1 && GPIO_SEL_I == 4'b1111)
   1.190 +            PIO_DATA <= #UDLY GPIO_DAT_I[DATA_WIDTH-1:0];   
   1.191 +            
   1.192 +        assign  PIO_OUT = PIO_DATA;
   1.193 +        end
   1.194 +   endgenerate
   1.195 +   
   1.196 +   generate
   1.197 +      if (BOTH_INPUT_AND_OUTPUT == 1) begin   
   1.198 +        always @(posedge CLK_I or posedge RST_I)
   1.199 +          if (RST_I) begin
   1.200 +            PIO_DATAI <= #UDLY 0;
   1.201 +            PIO_DATAO <= #UDLY 0;
   1.202 +          end else if (GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111)
   1.203 +            PIO_DATAI <= #UDLY PIO_BOTH_IN;
   1.204 +          else if (GPIO_STB_I && GPIO_ACK_O && GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111)
   1.205 +            PIO_DATAO <= #UDLY GPIO_DAT_I[OUTPUT_WIDTH-1:0];
   1.206 +               
   1.207 +        assign  PIO_BOTH_OUT = PIO_DATAO[OUTPUT_WIDTH-1:0];
   1.208 +        end
   1.209 +   endgenerate
   1.210 +   
   1.211 +   assign  PIO_DATA_RE_EN = GPIO_STB_I && !GPIO_ACK_O && !GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.212 +   assign  PIO_TRI_RE_EN  = GPIO_STB_I &&  GPIO_ACK_O && !GPIO_WE_I && (ADR_4 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.213 +   assign  IRQ_MASK_RE_EN = GPIO_STB_I &&  GPIO_ACK_O && !GPIO_WE_I && (ADR_8 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.214 +   assign  PIO_DATA_WR_EN = GPIO_STB_I &&  GPIO_ACK_O &&  GPIO_WE_I && (ADR_0 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.215 +   assign  PIO_TRI_WR_EN  = GPIO_STB_I &&  GPIO_ACK_O &&  GPIO_WE_I && (ADR_4 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.216 +   assign  IRQ_MASK_WR_EN = GPIO_STB_I &&  GPIO_ACK_O &&  GPIO_WE_I && (ADR_8 == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.217 +   assign  EDGE_CAP_WR_EN = GPIO_STB_I &&  GPIO_ACK_O &&  GPIO_WE_I && (ADR_C == 1'b1) && GPIO_SEL_I == 4'b1111;
   1.218 +   
   1.219 +   generate
   1.220 +      genvar     ti;
   1.221 +      for (ti = 0 ; ti < DATA_WIDTH; ti = ti + 1)
   1.222 +         begin : tio_inst
   1.223 +            TRI_PIO #(.DATA_WIDTH(DATA_WIDTH),
   1.224 +               .IRQ_MODE(IRQ_MODE),
   1.225 +               .LEVEL(LEVEL),
   1.226 +               .EDGE(EDGE),
   1.227 +               .POSE_EDGE_IRQ(POSE_EDGE_IRQ),
   1.228 +               .NEGE_EDGE_IRQ(NEGE_EDGE_IRQ),
   1.229 +               .EITHER_EDGE_IRQ(EITHER_EDGE_IRQ))
   1.230 +            TP (.CLK_I(CLK_I),
   1.231 +           .RST_I(RST_I),
   1.232 +           .DAT_I(GPIO_DAT_I[ti]),
   1.233 +           .DAT_O(tpio_out[ti]),
   1.234 +           .PIO_IO(PIO_IO[ti]),
   1.235 +           .IRQ_O(IRQ_TRI_TEMP[ti]),
   1.236 +           .PIO_TRI_WR_EN(PIO_TRI_WR_EN),
   1.237 +           .PIO_TRI_RE_EN(PIO_TRI_RE_EN),
   1.238 +           .PIO_DATA_WR_EN(PIO_DATA_WR_EN),
   1.239 +           .PIO_DATA_RE_EN(PIO_DATA_RE_EN),
   1.240 +           .IRQ_MASK_WR_EN(IRQ_MASK_WR_EN),
   1.241 +           .IRQ_MASK_RE_EN(IRQ_MASK_RE_EN),
   1.242 +           .EDGE_CAP_WR_EN(EDGE_CAP_WR_EN));
   1.243 +         end
   1.244 +   endgenerate
   1.245 +
   1.246 +   generate      
   1.247 +     if (INPUT_PORTS_ONLY == 1)
   1.248 +       assign GPIO_DAT_O = read_addr_0 ? PIO_DATA : 
   1.249 +                           read_addr_8 ? IRQ_MASK :
   1.250 +                           read_addr_C ? EDGE_CAPTURE :
   1.251 +                           0;
   1.252 +     else if (BOTH_INPUT_AND_OUTPUT == 1)
   1.253 +       assign GPIO_DAT_O = read_addr_0 ? PIO_DATAI : 
   1.254 +                           read_addr_8 ? IRQ_MASK_BOTH :
   1.255 +                           read_addr_C ? EDGE_CAPTURE_BOTH :
   1.256 +                           0;
   1.257 +     else if (TRISTATE_PORTS == 1)
   1.258 +       assign GPIO_DAT_O = read_addr_0 ? tpio_out : 
   1.259 +                           read_addr_4 ? tpio_out : 
   1.260 +                           read_addr_8 ? tpio_out :
   1.261 +                           read_addr_C ? IRQ_TRI_TEMP :
   1.262 +                           0;
   1.263 +     else
   1.264 +       assign GPIO_DAT_O = 0;
   1.265 +   endgenerate
   1.266 +   
   1.267 +//-----------------------------------------------------------------------------
   1.268 +//-------------------------------IRQ Generation--------------------------------
   1.269 +//-----------------------------------------------------------------------------
   1.270 +   generate
   1.271 +      if (IRQ_MODE == 1) begin
   1.272 +        always @(posedge CLK_I or posedge RST_I)
   1.273 +          if (RST_I) begin
   1.274 +            IRQ_MASK      <= #UDLY 0;
   1.275 +            IRQ_MASK_BOTH <= #UDLY 0;
   1.276 +          end else if (IRQ_MASK_WR_EN) begin
   1.277 +            IRQ_MASK      <= #UDLY GPIO_DAT_I[DATA_WIDTH-1:0];   
   1.278 +            IRQ_MASK_BOTH <= #UDLY GPIO_DAT_I[INPUT_WIDTH-1:0];   
   1.279 +          end
   1.280 +        end
   1.281 +   endgenerate
   1.282 +
   1.283 +   generate 
   1.284 +      //--------------------------------
   1.285 +      //--INPUT_PORTS_ONLY MODE IRQ
   1.286 +      //--------------------------------
   1.287 +      if (IRQ_MODE == 1 && INPUT_PORTS_ONLY == 1 && LEVEL == 1) begin   
   1.288 +         //level mode IRQ
   1.289 +         always @(posedge CLK_I or posedge RST_I)
   1.290 +           if (RST_I)
   1.291 +             IRQ_TEMP <= #UDLY 0;
   1.292 +           else if (IRQ_MASK_WR_EN)
   1.293 +             IRQ_TEMP <= #UDLY IRQ_TEMP & GPIO_DAT_I[DATA_WIDTH-1:0];
   1.294 +              else
   1.295 +             IRQ_TEMP <= #UDLY PIO_IN & IRQ_MASK;//bit-and   
   1.296 +         assign   IRQ_O = |IRQ_TEMP;
   1.297 +      end else if (IRQ_MODE == 1 && INPUT_PORTS_ONLY == 1 && EDGE == 1) begin   
   1.298 +         always @(posedge CLK_I or posedge RST_I)
   1.299 +           if (RST_I)
   1.300 +             PIO_DATA_DLY <= #UDLY 0;
   1.301 +           else
   1.302 +             PIO_DATA_DLY <= PIO_IN;
   1.303 +
   1.304 +         // edge-capture register bits are treated as individual bits.
   1.305 +         genvar i;
   1.306 +         for( i = 0; i < DATA_WIDTH; i = i + 1)
   1.307 +         begin
   1.308 +             always @(posedge CLK_I or posedge RST_I)
   1.309 +                 if (RST_I)
   1.310 +                   EDGE_CAPTURE[i] <= #UDLY 0;
   1.311 +                 else if (|(PIO_IN[i] & ~PIO_DATA_DLY[i]) && (POSE_EDGE_IRQ == 1))
   1.312 +                   EDGE_CAPTURE[i] <= #UDLY PIO_IN[i] & ~PIO_DATA_DLY[i];
   1.313 +                 else if (|(~PIO_IN[i] & PIO_DATA_DLY[i]) && (NEGE_EDGE_IRQ == 1))
   1.314 +                   EDGE_CAPTURE[i] <= #UDLY ~PIO_IN[i] & PIO_DATA_DLY[i];
   1.315 +                 else if (|(PIO_IN[i] & ~PIO_DATA_DLY[i]) && (EITHER_EDGE_IRQ == 1))
   1.316 +                   EDGE_CAPTURE[i] <= #UDLY PIO_IN[i] & ~PIO_DATA_DLY[i];
   1.317 +                 else if (|(~PIO_IN[i] & PIO_DATA_DLY[i]) && (EITHER_EDGE_IRQ == 1))
   1.318 +                   EDGE_CAPTURE[i] <= #UDLY ~PIO_IN[i] & PIO_DATA_DLY[i];
   1.319 +                 else if ( (~IRQ_MASK[i]) & GPIO_DAT_I[i] & IRQ_MASK_WR_EN )
   1.320 +                   // interrupt mask is being set, so clear edge-capture
   1.321 +                   EDGE_CAPTURE[i] <= #UDLY 0;
   1.322 +                 else if (EDGE_CAP_WR_EN)
   1.323 +                   // user's writing to the edge register, so update edge capture
   1.324 +                   // register
   1.325 +                   EDGE_CAPTURE[i] <= #UDLY EDGE_CAPTURE[i] & GPIO_DAT_I[i];
   1.326 +         end
   1.327 +         assign  IRQ_O = |(EDGE_CAPTURE & IRQ_MASK);
   1.328 +
   1.329 +     //----------------------------------
   1.330 +     //--BOTH_INPUT_AND_OUTPUT MODE IRQ
   1.331 +     //----------------------------------
   1.332 +     end else if  (IRQ_MODE == 1 && BOTH_INPUT_AND_OUTPUT == 1 && LEVEL == 1) begin
   1.333 +         always @(posedge CLK_I or posedge RST_I)
   1.334 +            if (RST_I)
   1.335 +              IRQ_TEMP_BOTH <= #UDLY 0;
   1.336 +            else if (IRQ_MASK_WR_EN)
   1.337 +              IRQ_TEMP_BOTH <= #UDLY IRQ_TEMP_BOTH & GPIO_DAT_I[INPUT_WIDTH-1:0];   
   1.338 +            else 
   1.339 +              IRQ_TEMP_BOTH <= #UDLY PIO_BOTH_IN & IRQ_MASK_BOTH;   
   1.340 +         assign   IRQ_O = |IRQ_TEMP_BOTH;
   1.341 +
   1.342 +     //edge mode IRQ
   1.343 +     end else if  (IRQ_MODE == 1 && BOTH_INPUT_AND_OUTPUT == 1 && EDGE == 1) begin   
   1.344 +         always @(posedge CLK_I or posedge RST_I)
   1.345 +           if (RST_I)
   1.346 +             PIO_DATA_DLY_BOTH <= #UDLY 0;
   1.347 +           else
   1.348 +             PIO_DATA_DLY_BOTH <= PIO_BOTH_IN;
   1.349 +
   1.350 +         // edge-capture register bits are treated as individual bits.
   1.351 +         genvar i_both;
   1.352 +         for( i_both = 0; i_both < INPUT_WIDTH; i_both = i_both + 1)
   1.353 +         begin
   1.354 +         always @(posedge CLK_I or posedge RST_I)
   1.355 +           if (RST_I)
   1.356 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY 0;
   1.357 +           else if (|(PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both]) && POSE_EDGE_IRQ == 1)
   1.358 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both];
   1.359 +           else if (|(~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both]) &&  NEGE_EDGE_IRQ == 1)
   1.360 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY ~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both];
   1.361 +           else if (|(PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both]) && EITHER_EDGE_IRQ == 1)
   1.362 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY PIO_BOTH_IN[i_both] & ~PIO_DATA_DLY_BOTH[i_both];
   1.363 +           else if (|(~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both]) && EITHER_EDGE_IRQ == 1)
   1.364 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY ~PIO_BOTH_IN[i_both] & PIO_DATA_DLY_BOTH[i_both];
   1.365 +           else if ( (~IRQ_MASK_BOTH[i_both]) & GPIO_DAT_I[i_both] & IRQ_MASK_WR_EN )
   1.366 +             // interrupt mask is being set, so clear edge-capture
   1.367 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY 0;
   1.368 +           else if (EDGE_CAP_WR_EN)
   1.369 +             // user's writing to the edge register, so update edge capture
   1.370 +             // register
   1.371 +             EDGE_CAPTURE_BOTH[i_both] <= #UDLY EDGE_CAPTURE_BOTH[i_both] & GPIO_DAT_I[i_both];
   1.372 +         end
   1.373 +         assign   IRQ_O = |(EDGE_CAPTURE_BOTH & IRQ_MASK_BOTH);
   1.374 +
   1.375 +     end else if (IRQ_MODE == 1 && TRISTATE_PORTS == 1) begin
   1.376 +         assign  IRQ_O = |IRQ_TRI_TEMP; 
   1.377 +     end else
   1.378 +         assign  IRQ_O = 1'b0;
   1.379 +   endgenerate   
   1.380 +
   1.381 +endmodule
   1.382 +`endif // GPIO_V