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