OpenCores
URL https://opencores.org/ocsvn/m16c5x/m16c5x/trunk

Subversion Repositories m16c5x

[/] [m16c5x/] [trunk/] [RTL/] [Src/] [P16C5x.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 MichaelA
////////////////////////////////////////////////////////////////////////////////
2
//
3
//  Copyright 2008-2013 by Michael A. Morris, dba M. A. Morris & Associates
4
//
5
//  All rights reserved. The source code contained herein is publicly released
6
//  under the terms and conditions of the GNU Lesser Public License. No part of
7
//  this source code may be reproduced or transmitted in any form or by any
8
//  means, electronic or mechanical, including photocopying, recording, or any
9
//  information storage and retrieval system in violation of the license under
10
//  which the source code is released.
11
//
12
//  The source code contained herein is free; it may be redistributed and/or
13
//  modified in accordance with the terms of the GNU Lesser General Public
14
//  License as published by the Free Software Foundation; either version 2.1 of
15
//  the GNU Lesser General Public License, or any later version.
16
//
17
//  The source code contained herein is freely released WITHOUT ANY WARRANTY;
18
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19
//  PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for
20
//  more details.)
21
//
22
//  A copy of the GNU Lesser General Public License should have been received
23
//  along with the source code contained herein; if not, a copy can be obtained
24
//  by writing to:
25
//
26
//  Free Software Foundation, Inc.
27
//  51 Franklin Street, Fifth Floor
28
//  Boston, MA  02110-1301 USA
29
//
30
//  Further, no use of this source code is permitted in any form or means
31
//  without inclusion of this banner prominently in any derived works.
32
//
33
//  Michael A. Morris
34
//  Huntsville, AL
35
//
36
////////////////////////////////////////////////////////////////////////////////
37
 
38
`timescale 1ns / 1ps
39
 
40
////////////////////////////////////////////////////////////////////////////////
41
// Company:         M. A. Morris & Associates
42
// Engineer:        Michael A. Morris
43
//
44
// Create Date:     11:30:15 01/13/2008
45
// Design Name:     PIC16C5x
46
// Module Name:     C:/ISEProjects/ISE10.1i/P16C5x/PIC16C5x_Top.v
47
// Project Name:    PIC16C5x
48
// Target Devices:  N/A
49
// Tool versions:   ISEWebPACK 10.1i SP3
50
//
51
// Description:
52
//
53
//  Module implements a pipelined PIC16C5x processor. The processor implements
54
//  all PIC16C5x instructions. The module is derived from the PIC16C5x.v module
55
//  and removes the tristate control, output, and input registers associated
56
//  with Ports A...C. These ports are replaced by decoded 6 WE and 3 RE and an
57
//  I/O data bus. Three WEs assert when the TRIS A, TRIS B, or TRIS C instruc-
58
//  tions are exectued. The remaining three WEs assert when a register file
59
//  operation writes to addresses 0x05-0x07, which represent writes to the out-
60
//  put registers of Ports A...C, respectively. The three REs assert when regis-
61
//  ter file operations read addresses 0x05-0x07, which represent reads from the
62
//  input registers of Ports A...C, respectively.
63
//
64
//  Note:   Read-Modify-Write operations to register file addresses 0x05-0x07
65
//          only assert the corresponding WEs. The external logic is expected to
66
//          multiplex the input registers onto the I/O Data Input (IO_DI) bus on
67
//          the basis of the addresses. The core reads IO_DI and writes out the
68
//          modified data on the I/O Data Output (IO_DO) bus. In the event that
69
//          the input registers are implemented as FIFOs, this approach prevents
70
//          the assertion of a read strobe to the FIFO, which would advance the
71
//          pointers and cause the loss of the data at the head of the FIFO.
72
//
73
// Dependencies:    None
74
//
75
// Revision:
76
//
77
//  1.00    13F15   MAM     Converted PIC16C5x.v. The conversion entails remov-
78
//                          ing I/O ports and adding external DI/DO data bus, 
79
//                          write and read enables for I/O port registers and
80
//                          input buffers. This will demonstrate how PIC16C5x
81
//                          can be modified to support more sophisticated I/O.
82
//
83
//  1.10    13F15   MAM     Pulled in the optimized instruction decoder from
84
//                          F16C5x.v. Also converted the ALU section into a
85
//                          separate module.
86
//
87
//  1.30    13F20   MAM     Added parameter to determine reset vector. Although
88
//                          a full 4k x 12 program memory is available, no stan-
89
//                          dard 12-bit instruction length PIC supports that
90
//                          amount of program memory. To use free PIC-compatible
91
//                          tools, the parameter can be set to a value in the
92
//                          range of the supported devices.
93
//
94
//  1.40    13G07   MAM     Corrected error with the test conditional pertaining
95
//                          to BTFSC/BTFSS instructions. Qualifier was using
96
//                          ALU_Op[1:0] instead of ALU_Op[7:6]. Under certain
97
//                          combinations, results were correct.
98
//
99
//  1.50    13J19   MAM     Modified various register Write Enable/Clock Enable
100
//                          implementation to minimize logic/multiplexers and
101
//                          make better use of built-in FF CE functionality.
102
//
103
//  1.51    13J20   MAM     Added Msk port to CPU, made minor updates to
104
//                          comments, and removed all unused code.
105
//
106
// Additional Comments:
107
//
108
////////////////////////////////////////////////////////////////////////////////
109
 
110
module P16C5x #(
111
    parameter pRstVector = 12'h7FF,         // Reset Vector Location (PIC16F59)
112
    parameter pWDT_Size  = 20,              // Use 20 for synth. and 10 for Sim.
113
    parameter pRAMA_Init = "Src/RAMA.coe",  // RAM A initial value file ( 8x8)
114
    parameter pRAMB_Init = "Src/RAMB.coe"   // RAM B initial value file (64x8)
115
)(
116
    input   POR,                // In  - System Power-On Reset
117
 
118
    input   Clk,                // In  - System Clock
119
    input   ClkEn,              // In  - Processor Clock Enable
120
 
121
    input   MCLR,               // In  - Master Clear Input
122
    input   T0CKI,              // In  - Timer 0 Clock Input
123
 
124
    input   WDTE,               // In  - Watchdog Timer Enable
125
 
126
    output  reg [11:0] PC,      // Out - Program Counter
127
    input   [11:0] ROM,         // In  - Instruction Data Input
128
 
129
    output  WE_TRISA, WE_TRISB, WE_TRISC,   // Out - Tristate Register X WE
130
    output  WE_PORTA, WE_PORTB, WE_PORTC,   // Out - Port X Output Register
131
    output  RE_PORTA, RE_PORTB, RE_PORTC,   // In  - Port X Input Register
132
 
133
    output  [7:0] IO_DO,        // Out - I/O Bus Data Output
134
    input   [7:0] IO_DI,        // In  - I/O Bus Data Input
135
 
136
//
137
//  Debug Outputs
138
//
139
 
140
    output  reg Rst,            // Out - Internal Core Reset
141
 
142
    output  reg [5:0] OPTION,   // Out - Processor Configuration Register Output
143
 
144
    output  reg [11:0] IR,      // Out - Internal Instruction Register
145
    output  [ 9:0] dIR,         // Out - Pipeline Register (Non-ALU Instruct.)
146
    output  [11:0] ALU_Op,      // Out - Pipeline Register (ALU Instructions)
147
    output  [ 8:0] KI,          // Out - Pipeline Register (Literal)
148
    output  [ 7:0] Msk,         // Out - Pipeline Register Bit Mask
149
    output  Err,                // Out - Instruction Decode Error Output
150
 
151
    output  reg Skip,           // Out - Skip Next Instruction
152
 
153
    output  reg [11:0] TOS,     // Out - Top-Of-Stack Register Output
154
    output  reg [11:0] NOS,     // Out - Next-On-Stack Register Output
155
 
156
    output  [7:0] W,            // Out - Working Register Output
157
 
158
    output  [7:0] FA,           // Out - File Address Output
159
    output  [7:0] DO,           // Out - File Data Input/ALU Data Output
160
    output  [7:0] DI,           // Out - File Data Output/ALU Data Input
161
 
162
    output  reg [7:0] TMR0,     // Out - Timer 0 Timer/Counter Output
163
    output  reg [7:0] FSR,      // Out - File Select Register Output
164
    output  [7:0] STATUS,       // Out - Processor Status Register Output
165
 
166
    output  T0CKI_Pls,          // Out - Timer 0 Clock Edge Pulse Output
167
 
168
    output  reg WDTClr,         // Out - Watchdog Timer Clear Output
169
    output  reg [pWDT_Size-1:0] WDT, // Out - Watchdog Timer
170
    output  reg WDT_TC,
171
    output  WDT_TO,             // Out - Watchdog Timer Timeout Output
172
 
173
    output  reg [7:0] PSCntr,   // Out - Prescaler Counter Output
174
    output  PSC_Pls             // Out - Prescaler Count Pulse Output
175
);
176
 
177
////////////////////////////////////////////////////////////////////////////////
178
//
179
//  Local Parameter Declarations
180
//
181
 
182
//  Special Function Register Addresses
183
 
184
localparam pINDF   = 5'b0_0000;     // Indirect Rd/Wr -- Address in FSR (0x04)
185
localparam pTMR0   = 5'b0_0001;     // Timer 0
186
localparam pPCL    = 5'b0_0010;     // Lower 8-bits of PC
187
localparam pSTATUS = 5'b0_0011;     // Status Register
188
localparam pFSR    = 5'b0_0100;     // File Select Register - Extended RAM ptr
189
localparam pPORTA  = 5'b0_0101;     // Port A: Tristate, Output, Input Registers
190
localparam pPORTB  = 5'b0_0110;     // Port B: Tristate, Output, Input Registers
191
localparam pPORTC  = 5'b0_0111;     // Port C: Tristate, Output, Input Registers
192
 
193
////////////////////////////////////////////////////////////////////////////////
194
//
195
//  Module Level Declarations
196
//
197
 
198
wire    Rst_M16C5x;         // Internal Core Reset (asynchronous)
199
 
200
wire    CE;                 // Internal Clock Enable: CE <= ClkEn & ~PD;
201
 
202
reg     [2:0] PA;           // PC Load Register PC[11:9] = PA[2:0]
203
wor     [7:0] SFR;          // Special Function Registers Data Output
204
 
205
wire    Rst_TO;             // Rst TO FF signal
206
reg     TO;                 // Time Out FF (STATUS Register)
207
wire    Rst_PD;             // Rst Power Down FF signal
208
reg     PD;                 // Power Down FF (STATUS Register)
209
reg     PwrDn;              // Power Down FF
210
 
211
// RAM Address: FA[4] ? {2'b0, FA[3:0]} : {FSR[6:5], FA[3:0]}
212
 
213
wire    [5:0] Addrs;
214
reg     [7:0] RAMA[ 7:0];   // RAM Block 0    = 0x08 - 0x0F      (Non-Banked)
215
reg     [7:0] RAMB[63:0];   // RAM Block 1..8 = @{FSR[6:5],FSR[3:0]} (Banked)
216
 
217
wire    T0CS;               // Timer 0 Clock Source Select
218
wire    T0SE;               // Timer 0 Source Edge
219
wire    PSA;                // Prescaler Assignment
220
wire    [2:0] PS;           // Prescaler Counter Output Bit Select
221
 
222
reg     [2:0] dT0CKI;       // Ext T0CKI Synchronized RE/RE FF chain
223
reg     PSC_Out;            // Synchronous Prescaler TC register
224
reg     [1:0] dPSC_Out;     // Rising Edge Detector for Prescaler output
225
 
226
wire    GOTO, CALL, RETLW;  // Signals for Decoded Instruction Register
227
wire    WE_SLEEP, WE_WDTCLR;
228
wire    WE_OPTION;
229
 
230
wire    WE_TMR0;            // Write Enable Signals Decoded from FA[4:0]
231
wire    WE_PCL;
232
wire    WE_STATUS;
233
wire    WE_FSR;
234
 
235
wire    WE_PSW;             // Write Enable for STATUS[2:0]: {Z, DC, C}
236
 
237
////////////////////////////////////////////////////////////////////////////////
238
//
239
//  ALU Declarations
240
//
241
 
242
wire    C, DC, Z;       // ALU Status Outputs
243
wire    Z_Tst, g;       // Zero and Bit Test Condition Code 
244
 
245
////////////////////////////////////////////////////////////////////////////////
246
////////////////////////////////////////////////////////////////////////////////
247
//
248
//  Top Level Implementation
249
//
250
 
251
assign CE = ClkEn & ~PwrDn;         // Internal Clock Enable, refer to comments
252
 
253
assign Rst_M16C5x = (POR | MCLR | WDT_TO);      // Internal Processor Reset
254
 
255
always @(posedge Clk or posedge Rst_M16C5x)
256
begin
257
    if(Rst_M16C5x)
258
        Rst <= #1 ~0;
259
    else if(CE)
260
        Rst <= #1  0;
261
end
262
 
263
//  Capture Program ROM input into Instruction Register (IR)
264
 
265
always @(posedge Clk)
266
begin
267
    if(Rst)
268
        IR <= #1 0;
269
    else if(CE)
270
        IR <= #1 ROM;
271
end
272
 
273
//  Instantiate Optimized Instruction Decoder - ROMs used to speed decode
274
 
275
P16C5x_IDec IDEC (
276
                .Rst(Rst),
277
                .Clk(Clk),
278
                .CE(CE),
279
 
280
                .DI(ROM),
281
                .Skip(Skip),
282
 
283
                .dIR(dIR),
284
                .ALU_Op(ALU_Op),
285
                .KI(KI),
286
                .Msk(Msk),
287
 
288
                .Err(Err)
289
            );
290
 
291
//  Instantiate ALU module
292
 
293
P16C5x_ALU  ALU (
294
                .Rst(Rst),
295
                .Clk(Clk),
296
                .CE(CE),
297
 
298
                .ALU_Op(ALU_Op[9:0]),
299
 
300
                .DI(DI),
301
                .KI(KI[7:0]),
302
                .Msk(Msk),
303
 
304
                .WE_PSW(WE_PSW),
305
 
306
                .DO(DO),
307
                .Z_Tst(Z_Tst),
308
                .g(g),
309
 
310
                .W(W),
311
 
312
                .Z(Z),
313
                .DC(DC),
314
                .C(C)
315
            );
316
 
317
////////////////////////////////////////////////////////////////////////////////
318
////////////////////////////////////////////////////////////////////////////////
319
//
320
//  Microprocessor Core Implementation
321
//
322
//  Pipeline Instruction Register Assignments
323
 
324
assign GOTO      = dIR[0];
325
assign CALL      = dIR[1];
326
assign RETLW     = dIR[2];
327
assign WE_SLEEP  = dIR[3];
328
assign WE_WDTCLR = dIR[4];
329
assign WE_TRISA  = dIR[5];
330
assign WE_TRISB  = dIR[6];
331
assign WE_TRISC  = dIR[7];
332
assign WE_OPTION = dIR[8];
333
assign LITERAL   = dIR[9];      // Added to support WE/RE PortX external I/F
334
 
335
//  Skip Logic
336
 
337
assign Tst = ALU_Op[8];
338
 
339
always @(*)
340
begin
341
    Skip <= WE_SLEEP | WE_PCL
342
            | ((Tst) ? ((ALU_Op[7] & ALU_Op[6]) ? g    : Z_Tst)
343
                     : ((GOTO | CALL | RETLW)   ? 1'b1 : 1'b0 ));
344
end
345
 
346
//  File Register Address Multiplexer
347
 
348
assign INDF = ALU_Op[10];
349
assign FA   = ((INDF) ? FSR
350
                      : ((KI[4]) ? {FSR[6:5], KI[4:0]}
351
                                 : {    2'b0, KI[4:0]}));
352
 
353
//  File Register Write Enable
354
 
355
assign WE_F = ALU_Op[11];
356
 
357
//  Special Function Register Write Enables
358
 
359
assign WE_TMR0   =  WE_F & (FA[4:0] == pTMR0);
360
assign WE_PCL    =  WE_F & (FA[4:0] == pPCL);
361
assign WE_STATUS =  WE_F & (FA[4:0] == pSTATUS);
362
assign WE_FSR    =  WE_F & (FA[4:0] == pFSR);
363
 
364
//  I/O Ports moved to an external implementation
365
//      WE_PortX asserts for an FA address match when LITERAL not asserted and a
366
//          WE_F is asserted.
367
//      RE_PortX asserts for an FA address match whn LITERAL not asserted, WE_F
368
//          is not asserted, and WE_TrisX not asserted. Tris X has the same FA
369
//          field. Tristate control for port A is instruction 0x005, and FA is
370
//          the least significant 5 bits of the instruction. FA of 0x05 is the
371
//          file address of Port A. (The same applies for Tris B and Tris C.)
372
 
373
assign WE_PORTA  =  WE_F & (FA[4:0] == pPORTA) & ~LITERAL;
374
assign WE_PORTB  =  WE_F & (FA[4:0] == pPORTB) & ~LITERAL;
375
assign WE_PORTC  =  WE_F & (FA[4:0] == pPORTC) & ~LITERAL;
376
//
377
assign RE_PORTA  = ~WE_F & (FA[4:0] == pPORTA) & ~LITERAL & ~WE_TRISA;
378
assign RE_PORTB  = ~WE_F & (FA[4:0] == pPORTB) & ~LITERAL & ~WE_TRISB;
379
assign RE_PORTC  = ~WE_F & (FA[4:0] == pPORTC) & ~LITERAL & ~WE_TRISC;
380
 
381
//  Assign Write Enable for STATUS register Processor Status Word (PSW) bits
382
//      Allow write to the STATUS[2:0] bits, {Z, DC, C}, only for instructions
383
//      MOVWF, BCF, BSF, and SWAPF. Exclude instructions DECFSZ and INCFSZ.
384
 
385
assign WE_PSW = WE_STATUS & (ALU_Op[5:4] == 2'b00) & (ALU_Op[8] == 1'b0);
386
 
387
////////////////////////////////////////////////////////////////////////////////
388
//
389
// Program Counter Implementation
390
//
391
//  On CALL or MOVWF PCL (direct or indirect), load PCL from the ALU output
392
//  and the upper bits with {PA, 0}, i.e. PC[8] = 0.
393
//
394
 
395
assign Ld_PCL = CALL | WE_PCL;
396
 
397
always @(posedge Clk)
398
begin
399
    if(Rst)
400
        PC <= #1 pRstVector;    // Set PC to Reset Vector on Rst or WDT Timeout
401
    else if(CE)
402
        PC <= #1 (GOTO ? {PA, KI}
403
                       : (Ld_PCL ? {PA, 1'b0, DO}
404
                                 : (RETLW ? TOS : PC + 1)));
405
end
406
 
407
//  Stack Implementation (2 Level Stack)
408
 
409
assign CE_TOS = CE & (CALL | RETLW);
410
 
411
always @(posedge Clk)
412
begin
413
    if(POR)
414
        TOS <= #1 pRstVector;       // Set TOS on Rst or WDT Timeout
415
    else if(CE_TOS)
416
        TOS <= #1 ((CALL) ? PC : NOS);
417
end
418
 
419
assign CE_NOS = CE & CALL;
420
 
421
always @(posedge Clk)
422
begin
423
    if(POR)
424
        NOS <= #1 pRstVector;       // Set NOS on Rst or WDT Timeout
425
    else if(CE_NOS)
426
        NOS <= #1 TOS;
427
end
428
 
429
////////////////////////////////////////////////////////////////////////////////
430
//
431
//  Port Configuration and Option Registers
432
 
433
assign CE_OPTION = CE & WE_OPTION;
434
 
435
always @(posedge Clk)
436
begin
437
    if(POR)
438
        OPTION <= #1 8'b0011_1111;
439
    else if(CE_OPTION)
440
        OPTION <= #1 W;
441
end
442
 
443
////////////////////////////////////////////////////////////////////////////////
444
//
445
//  CLRWDT Strobe Pulse Generator
446
 
447
always @(posedge Clk)
448
begin
449
    if(Rst)
450
        WDTClr <= #1 0;
451
    else
452
        WDTClr <= #1 (WE_WDTCLR | WE_SLEEP) & ~PwrDn;
453
end
454
 
455
////////////////////////////////////////////////////////////////////////////////
456
//
457
//  TO (Time Out) STATUS Register Bit
458
 
459
assign Rst_TO = (POR | (MCLR & PD) | WE_WDTCLR);
460
 
461
always @(posedge Clk)
462
begin
463
    if(Rst_TO)
464
        TO <= #1  0;
465
    else if(WDT_TO)
466
        TO <= #1 ~0;
467
end
468
 
469
////////////////////////////////////////////////////////////////////////////////
470
//
471
//  PD (Power Down) STATUS Register Bit - Sleep Mode
472
 
473
assign Rst_PD = POR | (WE_WDTCLR & ~PwrDn);
474
 
475
assign CE_PD = CE & WE_SLEEP;
476
 
477
always @(posedge Clk)
478
begin
479
    if(Rst_PD)
480
        PD <= #1 0;
481
    else if(CE_PD)
482
        PD <= #1 1;
483
end
484
 
485
//  PwrDn - Sleep Mode Control FF: Set by SLEEP instruction, cleared by Rst
486
//          Differs from PD in that it is not readable and does not maintain
487
//          its state through Reset. Gates CE to rest of the processor.
488
 
489
assign CE_PwrDn = ClkEn & WE_SLEEP;
490
 
491
always @(posedge Clk)
492
begin
493
    if(Rst)
494
        PwrDn <= #1 0;
495
    else if(CE_PwrDn)
496
        PwrDn <= #1 1;
497
end
498
 
499
////////////////////////////////////////////////////////////////////////////////
500
//
501
//  File Register RAM
502
 
503
assign Addrs = {FA[6:5], FA[3:0]};
504
 
505
//  RAM A - 16 Word Distributed RAM
506
 
507
assign WE_RAMA = WE_F & ~FA[4] & FA[3];
508
 
509
initial
510
  $readmemh(pRAMA_Init, RAMA, 0, 7);
511
 
512
always @(posedge Clk)
513
begin
514
    if(CE)
515
        if(WE_RAMA)
516
            RAMA[Addrs[2:0]] <= #1 DO;
517
end
518
 
519
//  RAM B - 64 Word Distributed RAM
520
 
521
assign WE_RAMB = WE_F & FA[4];
522
 
523
initial
524
  $readmemh(pRAMB_Init, RAMB, 0, 63);
525
 
526
always @(posedge Clk)
527
begin
528
    if(CE)
529
        if(WE_RAMB)
530
            RAMB[Addrs] <= #1 DO;
531
end
532
 
533
////////////////////////////////////////////////////////////////////////////////
534
//
535
// Special Function Registers
536
//
537
 
538
assign CE_PA = CE & WE_STATUS;
539
 
540
always @(posedge Clk)
541
begin
542
    if(POR)
543
        PA  <= #1 0;
544
    else if(CE_PA)
545
        PA  <= #1 DO[7:5];
546
end
547
 
548
assign CE_FSR = CE & WE_FSR;
549
 
550
always @(posedge Clk)
551
begin
552
    if(POR)
553
        FSR <= #1 0;
554
    else if(CE_FSR)
555
        FSR <= #1 DO;
556
end
557
 
558
//  Generate STATUS Register
559
 
560
assign STATUS = {PA, ~TO, ~PD, Z, DC, C};
561
 
562
//  Special Function Register (SFR) Multiplexers
563
 
564
assign SFR = ((FA[2:0] == 3'b001) ? TMR0    : 0);
565
assign SFR = ((FA[2:0] == 3'b010) ? PC[7:0] : 0);
566
assign SFR = ((FA[2:0] == 3'b011) ? STATUS  : 0);
567
assign SFR = ((FA[2:0] == 3'b100) ? FSR     : 0);
568
assign SFR = ((FA[2:0] == 3'b101) ? IO_DI   : 0);
569
assign SFR = ((FA[2:0] == 3'b110) ? IO_DI   : 0);
570
assign SFR = ((FA[2:0] == 3'b111) ? IO_DI   : 0);
571
 
572
//  File Data Output Multiplexer
573
 
574
assign DI = (FA[4] ? RAMB[Addrs] : (FA[3] ? RAMA[Addrs[2:0]] : SFR));
575
 
576
//  IO Data Output Multiplexer
577
 
578
assign IO_DO = ((|{WE_TRISA, WE_TRISB, WE_TRISC}) ? W : DO);
579
 
580
////////////////////////////////////////////////////////////////////////////////
581
////////////////////////////////////////////////////////////////////////////////
582
//
583
//  Watchdog Timer and Timer0 Implementation- see Figure 8-6
584
//
585
//  OPTION Register Assignments
586
//
587
 
588
assign T0CS = OPTION[5];     // Timer0 Clock Source:   1 - T0CKI,  0 - Clk
589
assign T0SE = OPTION[4];     // Timer0 Source Edge:    1 - FE,     0 - RE
590
assign PSA  = OPTION[3];     // Pre-Scaler Assignment: 1 - WDT,    0 - Timer0
591
assign PS   = OPTION[2:0];   // Pre-Scaler Count: Timer0 - 2^(PS+1), WDT - 2^PS
592
 
593
// WDT - Watchdog Timer
594
 
595
assign WDT_Rst = Rst | WDTClr;
596
 
597
always @(posedge Clk)
598
begin
599
    if(WDT_Rst)
600
        WDT <= #1 0;
601
    else if(WDTE)
602
        WDT <= #1 WDT + 1;
603
end
604
 
605
//  WDT synchronous TC FF
606
 
607
always @(posedge Clk)
608
begin
609
    if(WDT_Rst)
610
        WDT_TC <= #1 0;
611
    else
612
        WDT_TC <= #1 &WDT;
613
end
614
 
615
// WDT Timeout multiplexer
616
 
617
assign WDT_TO = (PSA ? PSC_Pls : WDT_TC);
618
 
619
////////////////////////////////////////////////////////////////////////////////
620
//
621
//  T0CKI RE/FE Pulse Generator (on Input rather than after PSCntr)
622
//
623
//      Device implements an XOR on T0CKI and a clock multiplexer for the
624
//      Prescaler since it has two clock asynchronous clock sources: the WDT
625
//      or the external T0CKI (Timer0 Clock Input). Instead of this type of
626
//      gated clock ripple counter implementation of the Prescaler, a fully
627
//      synchronous implementation has been selected. Thus, the T0CKI must be
628
//      synchronized and the falling or rising edge detected as determined by
629
//      the T0CS bit in the OPTION register. Similarly, the WDT is implemented
630
//      using the processor clock, which means that the WDT TC pulse is in the
631
//      same clock domain as the rest of the logic.
632
//
633
 
634
always @(posedge Clk)
635
begin
636
    if(Rst)
637
        dT0CKI <= #1 0;
638
    else begin
639
        dT0CKI[0] <= #1 T0CKI;                              // Synch FF #1
640
        dT0CKI[1] <= #1 dT0CKI[0];                          // Synch FF #2
641
        dT0CKI[2] <= #1 (T0SE ? (dT0CKI[1] & ~dT0CKI[0])    // Falling Edge
642
                              : (dT0CKI[0] & ~dT0CKI[1]));  // Rising Edge
643
    end
644
end
645
 
646
assign T0CKI_Pls = dT0CKI[2]; // T0CKI Pulse out, either FE/RE
647
 
648
//  Tmr0 Clock Source Multiplexer
649
 
650
assign Tmr0_CS = (T0CS ? T0CKI_Pls : CE);
651
 
652
////////////////////////////////////////////////////////////////////////////////
653
//
654
// Pre-Scaler Counter
655
 
656
assign Rst_PSC   = (PSA ? WDTClr : WE_TMR0) | Rst;
657
assign CE_PSCntr = (PSA ? WDT_TC : Tmr0_CS);
658
 
659
always @(posedge Clk)
660
begin
661
    if(Rst_PSC)
662
        PSCntr <= #1 0;
663
    else if(CE_PSCntr)
664
        PSCntr <= #1 PSCntr + 1;
665
end
666
 
667
//  Prescaler Counter Output Multiplexer
668
 
669
always @(*)
670
begin
671
    case (PS)
672
        3'b000 : PSC_Out <= PSCntr[0];
673
        3'b001 : PSC_Out <= PSCntr[1];
674
        3'b010 : PSC_Out <= PSCntr[2];
675
        3'b011 : PSC_Out <= PSCntr[3];
676
        3'b100 : PSC_Out <= PSCntr[4];
677
        3'b101 : PSC_Out <= PSCntr[5];
678
        3'b110 : PSC_Out <= PSCntr[6];
679
        3'b111 : PSC_Out <= PSCntr[7];
680
    endcase
681
end
682
 
683
// Prescaler Counter Rising Edge Detector
684
 
685
always @(posedge Clk)
686
begin
687
    if(POR)
688
        dPSC_Out <= #1 0;
689
    else begin
690
        dPSC_Out[0] <= #1 PSC_Out;
691
        dPSC_Out[1] <= #1 PSC_Out & ~dPSC_Out[0];
692
    end
693
end
694
 
695
assign PSC_Pls = dPSC_Out[1];
696
 
697
////////////////////////////////////////////////////////////////////////////////
698
//
699
// Tmr0 Counter/Timer
700
 
701
assign CE_Tmr0 = (PSA ? Tmr0_CS : PSC_Pls);
702
 
703
always @(posedge Clk)
704
begin
705
    if(POR)
706
        TMR0 <= #1 0;
707
    else if(WE_TMR0)
708
        TMR0 <= #1 DO;
709
    else if(CE_Tmr0)
710
        TMR0 <= #1 TMR0 + 1;
711
end
712
 
713
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.