1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/rtl/verilog/timer.v Fri Aug 13 10:49:23 2010 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 +// ============================================================================= 1.5 +// COPYRIGHT NOTICE 1.6 +// Copyright 2006 (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 : LM32 Timer 1.21 +// File : timer.v 1.22 +// Title : Timer component core file 1.23 +// Dependencies : None 1.24 +// Version : 7.0 1.25 +// : Initial Release 1.26 +// Version : 7.0SP2, 3.0 1.27 +// : No Change 1.28 +// ============================================================================= 1.29 +`ifndef TIMER_FILE 1.30 +`define TIMER_FILE 1.31 +module timer #( 1.32 + parameter PERIOD_NUM = 20,//decimal 1.33 + parameter PERIOD_WIDTH = 16,//decimal 1.34 + parameter WRITEABLE_PERIOD = 1, 1.35 + parameter READABLE_SNAPSHOT = 1, 1.36 + parameter START_STOP_CONTROL = 1, 1.37 + parameter TIMEOUT_PULSE = 1, 1.38 + parameter WATCHDOG = 0) 1.39 + ( 1.40 + //slave port 1.41 + S_ADR_I, //32bits 1.42 + S_DAT_I, //32bits 1.43 + S_WE_I, 1.44 + S_STB_I, 1.45 + S_CYC_I, 1.46 + S_CTI_I, 1.47 + S_BTE_I, 1.48 + S_LOCK_I, 1.49 + S_SEL_I, 1.50 + S_DAT_O, //32bits 1.51 + S_ACK_O, 1.52 + S_RTY_O, 1.53 + S_ERR_O, 1.54 + S_INT_O, 1.55 + RSTREQ_O, //resetrequest, only used when WatchDog enabled 1.56 + TOPULSE_O, //timeoutpulse, only used when TimeOutPulse enabled 1.57 + //system clock and reset 1.58 + CLK_I, 1.59 + RST_I 1.60 + ); 1.61 + 1.62 + input [31:0] S_ADR_I; 1.63 + input [31:0] S_DAT_I; 1.64 + input S_WE_I; 1.65 + input S_STB_I; 1.66 + input S_CYC_I; 1.67 + input [2:0] S_CTI_I; 1.68 + input S_LOCK_I; 1.69 + input [3:0] S_SEL_I; 1.70 + input [1:0] S_BTE_I; 1.71 + output [31:0] S_DAT_O; 1.72 + output S_ACK_O; 1.73 + output S_INT_O; 1.74 + output S_RTY_O; 1.75 + output S_ERR_O; 1.76 + output RSTREQ_O; 1.77 + output TOPULSE_O; 1.78 + 1.79 + input CLK_I; 1.80 + input RST_I; 1.81 + 1.82 + parameter UDLY = 1; 1.83 + parameter ST_IDLE = 2'b00; 1.84 + parameter ST_CNT = 2'b01; 1.85 + parameter ST_STOP = 2'b10; 1.86 + 1.87 + reg dw00_cs; 1.88 + reg dw04_cs; 1.89 + reg dw08_cs; 1.90 + reg dw0c_cs; 1.91 + reg reg_wr; 1.92 + reg reg_rd; 1.93 + reg [31:0] latch_s_data; 1.94 + reg [1:0] reg_04_data; 1.95 + reg reg_run; 1.96 + reg reg_stop; 1.97 + reg reg_start; 1.98 + reg [1:0] status; 1.99 + reg [PERIOD_WIDTH-1:0] internal_counter; 1.100 + reg [PERIOD_WIDTH-1:0] reg_08_data; 1.101 + reg s_ack_dly; 1.102 + reg s_ack_2dly; 1.103 + reg s_ack_pre; 1.104 + reg RSTREQ_O; 1.105 + reg TOPULSE_O; 1.106 + reg reg_to; 1.107 + 1.108 + wire reg_cont; 1.109 + wire reg_ito; 1.110 + wire [1:0] read_00_data; 1.111 + wire [1:0] read_04_data; 1.112 + wire [PERIOD_WIDTH-1:0] read_08_data; 1.113 + wire [PERIOD_WIDTH-1:0] read_0c_data; 1.114 + wire [PERIOD_WIDTH-1:0] reg_period; 1.115 + wire S_ACK_O; 1.116 + wire [31:0] S_DAT_O; 1.117 + wire S_INT_O; 1.118 + 1.119 + assign S_RTY_O = 1'b0; 1.120 + assign S_ERR_O = 1'b0; 1.121 + 1.122 + always @(posedge CLK_I or posedge RST_I) 1.123 + if(RST_I) 1.124 + latch_s_data <= #UDLY 32'h0; 1.125 + else 1.126 + latch_s_data <= #UDLY S_DAT_I; 1.127 + 1.128 + always @(posedge CLK_I or posedge RST_I) 1.129 + if(RST_I) 1.130 + begin 1.131 + dw00_cs <= #UDLY 1'b0; 1.132 + dw04_cs <= #UDLY 1'b0; 1.133 + dw08_cs <= #UDLY 1'b0; 1.134 + dw0c_cs <= #UDLY 1'b0; 1.135 + end 1.136 + else 1.137 + begin 1.138 + dw00_cs <= #UDLY (!(|S_ADR_I[5:2])); 1.139 + dw04_cs <= #UDLY (S_ADR_I[5:2] == 4'h1); 1.140 + dw08_cs <= #UDLY (S_ADR_I[5:2] == 4'h2); 1.141 + dw0c_cs <= #UDLY (S_ADR_I[5:2] == 4'h3); 1.142 + end 1.143 + 1.144 + always @(posedge CLK_I or posedge RST_I) 1.145 + if(RST_I) 1.146 + begin 1.147 + reg_wr <= #UDLY 1'b0; 1.148 + reg_rd <= #UDLY 1'b0; 1.149 + end 1.150 + else 1.151 + begin 1.152 + reg_wr <= #UDLY S_WE_I && S_STB_I && S_CYC_I; 1.153 + reg_rd <= #UDLY !S_WE_I && S_STB_I && S_CYC_I; 1.154 + end 1.155 + 1.156 + generate 1.157 + if (START_STOP_CONTROL == 1) 1.158 + 1.159 + always @(posedge CLK_I or posedge RST_I) 1.160 + if(RST_I) 1.161 + begin 1.162 + status <= #UDLY ST_IDLE; 1.163 + internal_counter <= #UDLY 'h0; 1.164 + end 1.165 + else 1.166 + case(status) 1.167 + ST_IDLE: 1.168 + begin 1.169 + if(reg_wr && dw08_cs) 1.170 + begin 1.171 + internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period; 1.172 + end 1.173 + else if(reg_start && !reg_stop) 1.174 + begin 1.175 + status <= #UDLY ST_CNT; 1.176 + if(|reg_period) 1.177 + internal_counter <= #UDLY reg_period - 1; 1.178 + end 1.179 + end 1.180 + ST_CNT: 1.181 + begin 1.182 + if(reg_stop && (|internal_counter)) 1.183 + status <= #UDLY ST_STOP; 1.184 + else if(reg_wr && dw08_cs) 1.185 + begin 1.186 + internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period; 1.187 + if(!(|internal_counter) && !reg_cont) 1.188 + status <= #UDLY ST_IDLE; 1.189 + end 1.190 + else if(!(|internal_counter)) 1.191 + begin 1.192 + if(!reg_cont) 1.193 + begin 1.194 + status <= #UDLY ST_IDLE; 1.195 + end 1.196 + internal_counter <= #UDLY reg_period; 1.197 + end 1.198 + else 1.199 + internal_counter <= #UDLY internal_counter - 1; 1.200 + end 1.201 + ST_STOP: 1.202 + begin 1.203 + if(reg_start && !reg_stop) 1.204 + status <= #UDLY ST_CNT; 1.205 + else if(reg_wr && dw08_cs) 1.206 + begin 1.207 + internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period; 1.208 + end 1.209 + end 1.210 + default: 1.211 + begin 1.212 + status <= #UDLY ST_IDLE; 1.213 + internal_counter <= #UDLY 'h0; 1.214 + end 1.215 + endcase 1.216 + endgenerate 1.217 + 1.218 + 1.219 + generate 1.220 + if (START_STOP_CONTROL == 0) 1.221 + always @(posedge CLK_I or posedge RST_I) 1.222 + if(RST_I) 1.223 + internal_counter <= #UDLY 'h0; 1.224 + else if ((reg_wr && dw08_cs) && (WATCHDOG == 1) || !(|internal_counter)) 1.225 + internal_counter <= #UDLY reg_period; 1.226 + else 1.227 + internal_counter <= #UDLY internal_counter - 1; 1.228 + endgenerate 1.229 + 1.230 + always @(posedge CLK_I or posedge RST_I) 1.231 + if(RST_I) 1.232 + reg_to <= #UDLY 1'b0; 1.233 + else if(reg_wr && dw00_cs && (!latch_s_data[0])) 1.234 + reg_to <= #UDLY 1'b0; 1.235 + else if(!(|internal_counter) && reg_ito && ((START_STOP_CONTROL == 0) || reg_run)) 1.236 + reg_to <= #UDLY 1'b1; 1.237 + 1.238 + generate 1.239 + if (START_STOP_CONTROL == 1) 1.240 + always @(posedge CLK_I or posedge RST_I) 1.241 + if(RST_I) 1.242 + reg_run <= #UDLY 1'b0; 1.243 + else if(reg_stop) 1.244 + reg_run <= #UDLY 1'b0; 1.245 + else if(reg_start) 1.246 + reg_run <= #UDLY 1'b1; 1.247 + else 1.248 + reg_run <= #UDLY (status !== ST_IDLE); 1.249 + endgenerate 1.250 + 1.251 + assign read_00_data = (START_STOP_CONTROL == 1) ? {reg_run,reg_to} : {1'b1,reg_to}; 1.252 + 1.253 + //reg_04:control 1.254 + assign {reg_cont,reg_ito} = reg_04_data; 1.255 + 1.256 + generate 1.257 + if (START_STOP_CONTROL == 1) 1.258 + always @(posedge CLK_I or posedge RST_I) 1.259 + if(RST_I) 1.260 + reg_stop <= #UDLY 1'b0; 1.261 + else if(reg_wr && dw04_cs) 1.262 + begin 1.263 + if(latch_s_data[3] && !latch_s_data[2] && !reg_stop) 1.264 + reg_stop <= #UDLY 1'b1; 1.265 + else if(!latch_s_data[3] && latch_s_data[2] && reg_stop) 1.266 + reg_stop <= #UDLY 1'b0; 1.267 + end 1.268 + 1.269 + always @(posedge CLK_I or posedge RST_I) 1.270 + if(RST_I) 1.271 + reg_start <= #UDLY 1'b0; 1.272 + else if(reg_wr && dw04_cs && !reg_run) 1.273 + reg_start <= #UDLY latch_s_data[2]; 1.274 + else 1.275 + reg_start <= #UDLY 1'b0; 1.276 + endgenerate 1.277 + 1.278 + always @(posedge CLK_I or posedge RST_I) 1.279 + if(RST_I) 1.280 + reg_04_data <= #UDLY 2'h0; 1.281 + else if(reg_wr && dw04_cs) 1.282 + reg_04_data <= #UDLY latch_s_data[1:0]; 1.283 + 1.284 + assign read_04_data = reg_04_data; 1.285 + 1.286 + generate 1.287 + if (WRITEABLE_PERIOD == 1) begin 1.288 + assign reg_period = reg_08_data; 1.289 + assign read_08_data = reg_08_data; 1.290 + always @(posedge CLK_I or posedge RST_I) begin 1.291 + if (RST_I) 1.292 + reg_08_data <= #UDLY PERIOD_NUM; 1.293 + else if ((reg_wr && dw08_cs) && (START_STOP_CONTROL == 1)) 1.294 + reg_08_data <= #UDLY latch_s_data; 1.295 + end 1.296 + end 1.297 + else 1.298 + assign reg_period = PERIOD_NUM; 1.299 + endgenerate 1.300 + 1.301 + generate 1.302 + if (READABLE_SNAPSHOT == 1) 1.303 + assign read_0c_data = internal_counter; 1.304 + endgenerate 1.305 + 1.306 + always @(posedge CLK_I or posedge RST_I) 1.307 + if(RST_I) 1.308 + begin 1.309 + s_ack_pre <= #UDLY 1'b0; 1.310 + s_ack_dly <= #UDLY 1'b0; 1.311 + s_ack_2dly <= #UDLY 1'b0; 1.312 + end 1.313 + else 1.314 + begin 1.315 + s_ack_pre <= #UDLY S_STB_I && S_CYC_I; 1.316 + s_ack_dly <= #UDLY s_ack_pre; 1.317 + s_ack_2dly <= #UDLY s_ack_dly; 1.318 + end 1.319 + 1.320 + assign S_ACK_O = s_ack_dly & !s_ack_2dly; 1.321 + assign S_DAT_O = (dw00_cs & !S_WE_I & S_STB_I) ? read_00_data : 1.322 + (dw04_cs & !S_WE_I & S_STB_I) ? read_04_data : 1.323 + (dw08_cs & !S_WE_I & S_STB_I & WRITEABLE_PERIOD) ? read_08_data : 1.324 + (dw0c_cs & !S_WE_I & S_STB_I & READABLE_SNAPSHOT) ? read_0c_data : 1.325 + 32'h0; 1.326 + assign S_INT_O = reg_to; 1.327 + 1.328 + generate 1.329 + if (WATCHDOG == 1) 1.330 + always @(posedge CLK_I or posedge RST_I) begin 1.331 + if(RST_I) 1.332 + RSTREQ_O <= #UDLY 1'b0; 1.333 + else if(!(|internal_counter) && !RSTREQ_O && ((START_STOP_CONTROL == 0) || reg_run)) 1.334 + RSTREQ_O <= #UDLY 1'b1; 1.335 + else 1.336 + RSTREQ_O <= #UDLY 1'b0; 1.337 + end 1.338 + endgenerate 1.339 + 1.340 + 1.341 + generate 1.342 + if (TIMEOUT_PULSE == 1) 1.343 + //TOPULSE_O 1.344 + always @(posedge CLK_I or posedge RST_I) 1.345 + if(RST_I) 1.346 + TOPULSE_O <= #UDLY 1'b0; 1.347 + else if(!(|internal_counter) && !TOPULSE_O && ((START_STOP_CONTROL == 0) || reg_run)) 1.348 + TOPULSE_O <= #UDLY 1'b1; 1.349 + else 1.350 + TOPULSE_O <= #UDLY 1'b0; 1.351 + endgenerate 1.352 + 1.353 +endmodule 1.354 +`endif