rtl/verilog/timer.v

Sat, 06 Aug 2011 01:40:34 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:40:34 +0100
changeset 1
85c1144140c3
parent 0
396b0bd970d3
permissions
-rw-r--r--

Update comments per latest Lattice code dump (LM32 v3.8)

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