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

     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