rtl/verilog/timer.v

Fri, 13 Aug 2010 10:49:23 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 13 Aug 2010 10:49:23 +0100
changeset 0
396b0bd970d3
child 1
85c1144140c3
permissions
-rw-r--r--

Initial import, Timer v3.0

philpem@0 1 // =============================================================================
philpem@0 2 // COPYRIGHT NOTICE
philpem@0 3 // Copyright 2006 (c) Lattice Semiconductor Corporation
philpem@0 4 // ALL RIGHTS RESERVED
philpem@0 5 // This confidential and proprietary software may be used only as authorised by
philpem@0 6 // a licensing agreement from Lattice Semiconductor Corporation.
philpem@0 7 // The entire notice above must be reproduced on all authorized copies and
philpem@0 8 // copies may only be made to the extent permitted by a licensing agreement from
philpem@0 9 // Lattice Semiconductor Corporation.
philpem@0 10 //
philpem@0 11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
philpem@0 12 // 5555 NE Moore Court 408-826-6000 (other locations)
philpem@0 13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
philpem@0 14 // U.S.A email: techsupport@latticesemi.com
philpem@0 15 // =============================================================================/
philpem@0 16 // FILE DETAILS
philpem@0 17 // Project : LM32 Timer
philpem@0 18 // File : timer.v
philpem@0 19 // Title : Timer component core file
philpem@0 20 // Dependencies : None
philpem@0 21 // Version : 7.0
philpem@0 22 // : Initial Release
philpem@0 23 // Version : 7.0SP2, 3.0
philpem@0 24 // : No Change
philpem@0 25 // =============================================================================
philpem@0 26 `ifndef TIMER_FILE
philpem@0 27 `define TIMER_FILE
philpem@0 28 module timer #(
philpem@0 29 parameter PERIOD_NUM = 20,//decimal
philpem@0 30 parameter PERIOD_WIDTH = 16,//decimal
philpem@0 31 parameter WRITEABLE_PERIOD = 1,
philpem@0 32 parameter READABLE_SNAPSHOT = 1,
philpem@0 33 parameter START_STOP_CONTROL = 1,
philpem@0 34 parameter TIMEOUT_PULSE = 1,
philpem@0 35 parameter WATCHDOG = 0)
philpem@0 36 (
philpem@0 37 //slave port
philpem@0 38 S_ADR_I, //32bits
philpem@0 39 S_DAT_I, //32bits
philpem@0 40 S_WE_I,
philpem@0 41 S_STB_I,
philpem@0 42 S_CYC_I,
philpem@0 43 S_CTI_I,
philpem@0 44 S_BTE_I,
philpem@0 45 S_LOCK_I,
philpem@0 46 S_SEL_I,
philpem@0 47 S_DAT_O, //32bits
philpem@0 48 S_ACK_O,
philpem@0 49 S_RTY_O,
philpem@0 50 S_ERR_O,
philpem@0 51 S_INT_O,
philpem@0 52 RSTREQ_O, //resetrequest, only used when WatchDog enabled
philpem@0 53 TOPULSE_O, //timeoutpulse, only used when TimeOutPulse enabled
philpem@0 54 //system clock and reset
philpem@0 55 CLK_I,
philpem@0 56 RST_I
philpem@0 57 );
philpem@0 58
philpem@0 59 input [31:0] S_ADR_I;
philpem@0 60 input [31:0] S_DAT_I;
philpem@0 61 input S_WE_I;
philpem@0 62 input S_STB_I;
philpem@0 63 input S_CYC_I;
philpem@0 64 input [2:0] S_CTI_I;
philpem@0 65 input S_LOCK_I;
philpem@0 66 input [3:0] S_SEL_I;
philpem@0 67 input [1:0] S_BTE_I;
philpem@0 68 output [31:0] S_DAT_O;
philpem@0 69 output S_ACK_O;
philpem@0 70 output S_INT_O;
philpem@0 71 output S_RTY_O;
philpem@0 72 output S_ERR_O;
philpem@0 73 output RSTREQ_O;
philpem@0 74 output TOPULSE_O;
philpem@0 75
philpem@0 76 input CLK_I;
philpem@0 77 input RST_I;
philpem@0 78
philpem@0 79 parameter UDLY = 1;
philpem@0 80 parameter ST_IDLE = 2'b00;
philpem@0 81 parameter ST_CNT = 2'b01;
philpem@0 82 parameter ST_STOP = 2'b10;
philpem@0 83
philpem@0 84 reg dw00_cs;
philpem@0 85 reg dw04_cs;
philpem@0 86 reg dw08_cs;
philpem@0 87 reg dw0c_cs;
philpem@0 88 reg reg_wr;
philpem@0 89 reg reg_rd;
philpem@0 90 reg [31:0] latch_s_data;
philpem@0 91 reg [1:0] reg_04_data;
philpem@0 92 reg reg_run;
philpem@0 93 reg reg_stop;
philpem@0 94 reg reg_start;
philpem@0 95 reg [1:0] status;
philpem@0 96 reg [PERIOD_WIDTH-1:0] internal_counter;
philpem@0 97 reg [PERIOD_WIDTH-1:0] reg_08_data;
philpem@0 98 reg s_ack_dly;
philpem@0 99 reg s_ack_2dly;
philpem@0 100 reg s_ack_pre;
philpem@0 101 reg RSTREQ_O;
philpem@0 102 reg TOPULSE_O;
philpem@0 103 reg reg_to;
philpem@0 104
philpem@0 105 wire reg_cont;
philpem@0 106 wire reg_ito;
philpem@0 107 wire [1:0] read_00_data;
philpem@0 108 wire [1:0] read_04_data;
philpem@0 109 wire [PERIOD_WIDTH-1:0] read_08_data;
philpem@0 110 wire [PERIOD_WIDTH-1:0] read_0c_data;
philpem@0 111 wire [PERIOD_WIDTH-1:0] reg_period;
philpem@0 112 wire S_ACK_O;
philpem@0 113 wire [31:0] S_DAT_O;
philpem@0 114 wire S_INT_O;
philpem@0 115
philpem@0 116 assign S_RTY_O = 1'b0;
philpem@0 117 assign S_ERR_O = 1'b0;
philpem@0 118
philpem@0 119 always @(posedge CLK_I or posedge RST_I)
philpem@0 120 if(RST_I)
philpem@0 121 latch_s_data <= #UDLY 32'h0;
philpem@0 122 else
philpem@0 123 latch_s_data <= #UDLY S_DAT_I;
philpem@0 124
philpem@0 125 always @(posedge CLK_I or posedge RST_I)
philpem@0 126 if(RST_I)
philpem@0 127 begin
philpem@0 128 dw00_cs <= #UDLY 1'b0;
philpem@0 129 dw04_cs <= #UDLY 1'b0;
philpem@0 130 dw08_cs <= #UDLY 1'b0;
philpem@0 131 dw0c_cs <= #UDLY 1'b0;
philpem@0 132 end
philpem@0 133 else
philpem@0 134 begin
philpem@0 135 dw00_cs <= #UDLY (!(|S_ADR_I[5:2]));
philpem@0 136 dw04_cs <= #UDLY (S_ADR_I[5:2] == 4'h1);
philpem@0 137 dw08_cs <= #UDLY (S_ADR_I[5:2] == 4'h2);
philpem@0 138 dw0c_cs <= #UDLY (S_ADR_I[5:2] == 4'h3);
philpem@0 139 end
philpem@0 140
philpem@0 141 always @(posedge CLK_I or posedge RST_I)
philpem@0 142 if(RST_I)
philpem@0 143 begin
philpem@0 144 reg_wr <= #UDLY 1'b0;
philpem@0 145 reg_rd <= #UDLY 1'b0;
philpem@0 146 end
philpem@0 147 else
philpem@0 148 begin
philpem@0 149 reg_wr <= #UDLY S_WE_I && S_STB_I && S_CYC_I;
philpem@0 150 reg_rd <= #UDLY !S_WE_I && S_STB_I && S_CYC_I;
philpem@0 151 end
philpem@0 152
philpem@0 153 generate
philpem@0 154 if (START_STOP_CONTROL == 1)
philpem@0 155
philpem@0 156 always @(posedge CLK_I or posedge RST_I)
philpem@0 157 if(RST_I)
philpem@0 158 begin
philpem@0 159 status <= #UDLY ST_IDLE;
philpem@0 160 internal_counter <= #UDLY 'h0;
philpem@0 161 end
philpem@0 162 else
philpem@0 163 case(status)
philpem@0 164 ST_IDLE:
philpem@0 165 begin
philpem@0 166 if(reg_wr && dw08_cs)
philpem@0 167 begin
philpem@0 168 internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
philpem@0 169 end
philpem@0 170 else if(reg_start && !reg_stop)
philpem@0 171 begin
philpem@0 172 status <= #UDLY ST_CNT;
philpem@0 173 if(|reg_period)
philpem@0 174 internal_counter <= #UDLY reg_period - 1;
philpem@0 175 end
philpem@0 176 end
philpem@0 177 ST_CNT:
philpem@0 178 begin
philpem@0 179 if(reg_stop && (|internal_counter))
philpem@0 180 status <= #UDLY ST_STOP;
philpem@0 181 else if(reg_wr && dw08_cs)
philpem@0 182 begin
philpem@0 183 internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
philpem@0 184 if(!(|internal_counter) && !reg_cont)
philpem@0 185 status <= #UDLY ST_IDLE;
philpem@0 186 end
philpem@0 187 else if(!(|internal_counter))
philpem@0 188 begin
philpem@0 189 if(!reg_cont)
philpem@0 190 begin
philpem@0 191 status <= #UDLY ST_IDLE;
philpem@0 192 end
philpem@0 193 internal_counter <= #UDLY reg_period;
philpem@0 194 end
philpem@0 195 else
philpem@0 196 internal_counter <= #UDLY internal_counter - 1;
philpem@0 197 end
philpem@0 198 ST_STOP:
philpem@0 199 begin
philpem@0 200 if(reg_start && !reg_stop)
philpem@0 201 status <= #UDLY ST_CNT;
philpem@0 202 else if(reg_wr && dw08_cs)
philpem@0 203 begin
philpem@0 204 internal_counter <= #UDLY (WRITEABLE_PERIOD == 1) ? latch_s_data : reg_period;
philpem@0 205 end
philpem@0 206 end
philpem@0 207 default:
philpem@0 208 begin
philpem@0 209 status <= #UDLY ST_IDLE;
philpem@0 210 internal_counter <= #UDLY 'h0;
philpem@0 211 end
philpem@0 212 endcase
philpem@0 213 endgenerate
philpem@0 214
philpem@0 215
philpem@0 216 generate
philpem@0 217 if (START_STOP_CONTROL == 0)
philpem@0 218 always @(posedge CLK_I or posedge RST_I)
philpem@0 219 if(RST_I)
philpem@0 220 internal_counter <= #UDLY 'h0;
philpem@0 221 else if ((reg_wr && dw08_cs) && (WATCHDOG == 1) || !(|internal_counter))
philpem@0 222 internal_counter <= #UDLY reg_period;
philpem@0 223 else
philpem@0 224 internal_counter <= #UDLY internal_counter - 1;
philpem@0 225 endgenerate
philpem@0 226
philpem@0 227 always @(posedge CLK_I or posedge RST_I)
philpem@0 228 if(RST_I)
philpem@0 229 reg_to <= #UDLY 1'b0;
philpem@0 230 else if(reg_wr && dw00_cs && (!latch_s_data[0]))
philpem@0 231 reg_to <= #UDLY 1'b0;
philpem@0 232 else if(!(|internal_counter) && reg_ito && ((START_STOP_CONTROL == 0) || reg_run))
philpem@0 233 reg_to <= #UDLY 1'b1;
philpem@0 234
philpem@0 235 generate
philpem@0 236 if (START_STOP_CONTROL == 1)
philpem@0 237 always @(posedge CLK_I or posedge RST_I)
philpem@0 238 if(RST_I)
philpem@0 239 reg_run <= #UDLY 1'b0;
philpem@0 240 else if(reg_stop)
philpem@0 241 reg_run <= #UDLY 1'b0;
philpem@0 242 else if(reg_start)
philpem@0 243 reg_run <= #UDLY 1'b1;
philpem@0 244 else
philpem@0 245 reg_run <= #UDLY (status !== ST_IDLE);
philpem@0 246 endgenerate
philpem@0 247
philpem@0 248 assign read_00_data = (START_STOP_CONTROL == 1) ? {reg_run,reg_to} : {1'b1,reg_to};
philpem@0 249
philpem@0 250 //reg_04:control
philpem@0 251 assign {reg_cont,reg_ito} = reg_04_data;
philpem@0 252
philpem@0 253 generate
philpem@0 254 if (START_STOP_CONTROL == 1)
philpem@0 255 always @(posedge CLK_I or posedge RST_I)
philpem@0 256 if(RST_I)
philpem@0 257 reg_stop <= #UDLY 1'b0;
philpem@0 258 else if(reg_wr && dw04_cs)
philpem@0 259 begin
philpem@0 260 if(latch_s_data[3] && !latch_s_data[2] && !reg_stop)
philpem@0 261 reg_stop <= #UDLY 1'b1;
philpem@0 262 else if(!latch_s_data[3] && latch_s_data[2] && reg_stop)
philpem@0 263 reg_stop <= #UDLY 1'b0;
philpem@0 264 end
philpem@0 265
philpem@0 266 always @(posedge CLK_I or posedge RST_I)
philpem@0 267 if(RST_I)
philpem@0 268 reg_start <= #UDLY 1'b0;
philpem@0 269 else if(reg_wr && dw04_cs && !reg_run)
philpem@0 270 reg_start <= #UDLY latch_s_data[2];
philpem@0 271 else
philpem@0 272 reg_start <= #UDLY 1'b0;
philpem@0 273 endgenerate
philpem@0 274
philpem@0 275 always @(posedge CLK_I or posedge RST_I)
philpem@0 276 if(RST_I)
philpem@0 277 reg_04_data <= #UDLY 2'h0;
philpem@0 278 else if(reg_wr && dw04_cs)
philpem@0 279 reg_04_data <= #UDLY latch_s_data[1:0];
philpem@0 280
philpem@0 281 assign read_04_data = reg_04_data;
philpem@0 282
philpem@0 283 generate
philpem@0 284 if (WRITEABLE_PERIOD == 1) begin
philpem@0 285 assign reg_period = reg_08_data;
philpem@0 286 assign read_08_data = reg_08_data;
philpem@0 287 always @(posedge CLK_I or posedge RST_I) begin
philpem@0 288 if (RST_I)
philpem@0 289 reg_08_data <= #UDLY PERIOD_NUM;
philpem@0 290 else if ((reg_wr && dw08_cs) && (START_STOP_CONTROL == 1))
philpem@0 291 reg_08_data <= #UDLY latch_s_data;
philpem@0 292 end
philpem@0 293 end
philpem@0 294 else
philpem@0 295 assign reg_period = PERIOD_NUM;
philpem@0 296 endgenerate
philpem@0 297
philpem@0 298 generate
philpem@0 299 if (READABLE_SNAPSHOT == 1)
philpem@0 300 assign read_0c_data = internal_counter;
philpem@0 301 endgenerate
philpem@0 302
philpem@0 303 always @(posedge CLK_I or posedge RST_I)
philpem@0 304 if(RST_I)
philpem@0 305 begin
philpem@0 306 s_ack_pre <= #UDLY 1'b0;
philpem@0 307 s_ack_dly <= #UDLY 1'b0;
philpem@0 308 s_ack_2dly <= #UDLY 1'b0;
philpem@0 309 end
philpem@0 310 else
philpem@0 311 begin
philpem@0 312 s_ack_pre <= #UDLY S_STB_I && S_CYC_I;
philpem@0 313 s_ack_dly <= #UDLY s_ack_pre;
philpem@0 314 s_ack_2dly <= #UDLY s_ack_dly;
philpem@0 315 end
philpem@0 316
philpem@0 317 assign S_ACK_O = s_ack_dly & !s_ack_2dly;
philpem@0 318 assign S_DAT_O = (dw00_cs & !S_WE_I & S_STB_I) ? read_00_data :
philpem@0 319 (dw04_cs & !S_WE_I & S_STB_I) ? read_04_data :
philpem@0 320 (dw08_cs & !S_WE_I & S_STB_I & WRITEABLE_PERIOD) ? read_08_data :
philpem@0 321 (dw0c_cs & !S_WE_I & S_STB_I & READABLE_SNAPSHOT) ? read_0c_data :
philpem@0 322 32'h0;
philpem@0 323 assign S_INT_O = reg_to;
philpem@0 324
philpem@0 325 generate
philpem@0 326 if (WATCHDOG == 1)
philpem@0 327 always @(posedge CLK_I or posedge RST_I) begin
philpem@0 328 if(RST_I)
philpem@0 329 RSTREQ_O <= #UDLY 1'b0;
philpem@0 330 else if(!(|internal_counter) && !RSTREQ_O && ((START_STOP_CONTROL == 0) || reg_run))
philpem@0 331 RSTREQ_O <= #UDLY 1'b1;
philpem@0 332 else
philpem@0 333 RSTREQ_O <= #UDLY 1'b0;
philpem@0 334 end
philpem@0 335 endgenerate
philpem@0 336
philpem@0 337
philpem@0 338 generate
philpem@0 339 if (TIMEOUT_PULSE == 1)
philpem@0 340 //TOPULSE_O
philpem@0 341 always @(posedge CLK_I or posedge RST_I)
philpem@0 342 if(RST_I)
philpem@0 343 TOPULSE_O <= #UDLY 1'b0;
philpem@0 344 else if(!(|internal_counter) && !TOPULSE_O && ((START_STOP_CONTROL == 0) || reg_run))
philpem@0 345 TOPULSE_O <= #UDLY 1'b1;
philpem@0 346 else
philpem@0 347 TOPULSE_O <= #UDLY 1'b0;
philpem@0 348 endgenerate
philpem@0 349
philpem@0 350 endmodule
philpem@0 351 `endif