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