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

Subversion Repositories p16c5x

[/] [p16c5x/] [trunk/] [RTL/] [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
// Additional Comments:
100
//
101
////////////////////////////////////////////////////////////////////////////////
102
 
103
module P16C5x #(
104
    parameter pRstVector = 12'h7FF,         // Reset Vector Location (PIC16F59)
105
    parameter pWDT_Size  = 20,              // Use 20 for synth. and 10 for Sim.
106
    parameter pRAMA_Init = "Src/RAMA.coe",  // RAM A initial value file ( 8x8)
107
    parameter pRAMB_Init = "Src/RAMB.coe"   // RAM B initial value file (64x8)
108
)(
109
    input   POR,                // In  - System Power-On Reset
110
 
111
    input   Clk,                // In  - System Clock
112
    input   ClkEn,              // In  - Processor Clock Enable
113
 
114
    input   MCLR,               // In  - Master Clear Input
115
    input   T0CKI,              // In  - Timer 0 Clock Input
116
 
117
    input   WDTE,               // In  - Watchdog Timer Enable
118
 
119
    output  reg [11:0] PC,      // Out - Program Counter
120
    input   [11:0] ROM,         // In  - Instruction Data Input
121
 
122
    output  WE_TRISA, WE_TRISB, WE_TRISC,   // Out - Tristate Register X WE
123
    output  WE_PORTA, WE_PORTB, WE_PORTC,   // Out - Port X Output Register
124
    output  RE_PORTA, RE_PORTB, RE_PORTC,   // In  - Port X Input Register
125
 
126
    output  [7:0] IO_DO,        // Out - I/O Bus Data Output
127
    input   [7:0] IO_DI,        // In  - I/O Bus Data Input
128
 
129
//
130
//  Debug Outputs
131
//
132
 
133
    output  reg Rst,            // Out - Internal Core Reset
134
 
135
    output  reg [5:0] OPTION,   // Out - Processor Configuration Register Output
136
 
137
    output  reg [11:0] IR,      // Out - Internal Instruction Register
138
    output  [ 9:0] dIR,         // Out - Pipeline Register (Non-ALU Instruct.)
139
    output  [11:0] ALU_Op,      // Out - Pipeline Register (ALU Instructions)
140
    output  [ 8:0] KI,          // Out - Pipeline Register (Literal)
141
    output  Err,                // Out - Instruction Decode Error Output
142
 
143
    output  reg Skip,           // Out - Skip Next Instruction
144
 
145
    output  reg [11:0] TOS,     // Out - Top-Of-Stack Register Output
146
    output  reg [11:0] NOS,     // Out - Next-On-Stack Register Output
147
 
148
    output  [7:0] W,            // Out - Working Register Output
149
 
150
    output  [7:0] FA,           // Out - File Address Output
151
    output  [7:0] DO,           // Out - File Data Input/ALU Data Output
152
    output  [7:0] DI,           // Out - File Data Output/ALU Data Input
153
 
154
    output  reg [7:0] TMR0,     // Out - Timer 0 Timer/Counter Output
155
    output  reg [7:0] FSR,      // Out - File Select Register Output
156
    output  [7:0] STATUS,       // Out - Processor Status Register Output
157
 
158
    output  T0CKI_Pls,          // Out - Timer 0 Clock Edge Pulse Output
159
 
160
    output  reg WDTClr,         // Out - Watchdog Timer Clear Output
161
    output  reg [pWDT_Size-1:0] WDT, // Out - Watchdog Timer
162
    output  reg WDT_TC,
163
    output  WDT_TO,             // Out - Watchdog Timer Timeout Output
164
 
165
    output  reg [7:0] PSCntr,   // Out - Prescaler Counter Output
166
    output  PSC_Pls             // Out - Prescaler Count Pulse Output
167
);
168
 
169
////////////////////////////////////////////////////////////////////////////////
170
//
171
//  Local Parameter Declarations
172
//
173
 
174
//  Special Function Register Addresses
175
 
176
localparam pINDF   = 5'b0_0000;     // Indirect Rd/Wr -- Address in FSR (0x04)
177
localparam pTMR0   = 5'b0_0001;     // Timer 0
178
localparam pPCL    = 5'b0_0010;     // Lower 8-bits of PC
179
localparam pSTATUS = 5'b0_0011;     // Status Register
180
localparam pFSR    = 5'b0_0100;     // File Select Register - Extended RAM ptr
181
localparam pPORTA  = 5'b0_0101;     // Port A: Tristate, Output, Input Registers
182
localparam pPORTB  = 5'b0_0110;     // Port B: Tristate, Output, Input Registers
183
localparam pPORTC  = 5'b0_0111;     // Port C: Tristate, Output, Input Registers
184
 
185
////////////////////////////////////////////////////////////////////////////////
186
//
187
//  Module Level Declarations
188
//
189
 
190
wire    Rst_M16C5x;         // Internal Core Reset (asynchronous)
191
 
192
wire    CE;                 // Internal Clock Enable: CE <= ClkEn & ~PD;
193
 
194
reg     [2:0] PA;           // PC Load Register PC[11:9] = PA[2:0]
195
reg     [7:0] SFR;          // Special Function Registers Data Output
196
 
197
wire    Rst_TO;             // Rst TO FF signal
198
reg     TO;                 // Time Out FF (STATUS Register)
199
wire    Rst_PD;             // Rst Power Down FF signal
200
reg     PD;                 // Power Down FF (STATUS Register)
201
reg     PwrDn;              // Power Down FF
202
 
203
// RAM Address: FA[4] ? {2'b0, FA[3:0]} : {FSR[6:5], FA[3:0]}
204
 
205
wire    [5:0] Addrs;
206
reg     [7:0] RAMA[ 7:0];   // RAM Block 0    = 0x08 - 0x0F      (Non-Banked)
207
reg     [7:0] RAMB[63:0];   // RAM Block 1..8 = @{FSR[6:5],FSR[3:0]} (Banked)
208
 
209
wire    T0CS;               // Timer 0 Clock Source Select
210
wire    T0SE;               // Timer 0 Source Edge
211
wire    PSA;                // Prescaler Assignment
212
wire    [2:0] PS;           // Prescaler Counter Output Bit Select
213
 
214
reg     [2:0] dT0CKI;       // Ext T0CKI Synchronized RE/RE FF chain
215
reg     PSC_Out;            // Synchronous Prescaler TC register
216
reg     [1:0] dPSC_Out;     // Rising Edge Detector for Prescaler output
217
 
218
wire    GOTO, CALL, RETLW;  // Signals for Decoded Instruction Register
219
wire    WE_SLEEP, WE_WDTCLR;
220
wire    WE_OPTION;
221
 
222
wire    WE_TMR0;            // Write Enable Signals Decoded from FA[4:0]
223
wire    WE_PCL;
224
wire    WE_STATUS;
225
wire    WE_FSR;
226
 
227
wire    WE_PSW;             // Write Enable for STATUS[2:0]: {Z, DC, C}
228
 
229
////////////////////////////////////////////////////////////////////////////////
230
//
231
//  ALU Declarations
232
//
233
 
234
wire    C, DC, Z;       // ALU Status Outputs
235
wire    Z_Tst, g;       // Zero and Bit Test Condition Code 
236
 
237
//
238
////////////////////////////////////////////////////////////////////////////////
239
////////////////////////////////////////////////////////////////////////////////
240
//
241
//  Top Level Implementation
242
//
243
 
244
assign CE = ClkEn & ~PwrDn;         // Internal Clock Enable, refer to comments
245
 
246
assign Rst_M16C5x = (POR | MCLR | WDT_TO);      // Internal Processor Reset
247
 
248
always @(posedge Clk or posedge Rst_M16C5x)
249
begin
250
    if(Rst_M16C5x)
251
        Rst <= #1 ~0;
252
    else if(CE)
253
        Rst <= #1  0;
254
end
255
 
256
//  Capture Program ROM input into Instruction Register (IR)
257
 
258
always @(posedge Clk)
259
begin
260
    if(Rst)
261
        IR <= #1 0;
262
    else if(CE)
263
        IR <= #1 ROM;
264
end
265
 
266
//  Instantiate Optimized Instruction Decoder - ROMs used to speed decode
267
 
268
P16C5x_IDec IDEC (
269
                .Rst(Rst),
270
                .Clk(Clk),
271
                .CE(CE),
272
 
273
                .DI(ROM),
274
                .Skip(Skip),
275
 
276
                .dIR(dIR),
277
                .ALU_Op(ALU_Op),
278
                .KI(KI),
279
 
280
                .Err(Err)
281
            );
282
 
283
//  Instantiate ALU module
284
 
285
P16C5x_ALU  ALU (
286
                .Rst(Rst),
287
                .Clk(Clk),
288
                .CE(CE),
289
 
290
                .ALU_Op(ALU_Op),
291
 
292
                .DI(DI),
293
                .KI(KI[7:0]),
294
                .WE_PSW(WE_PSW),
295
 
296
                .DO(DO),
297
                .Z_Tst(Z_Tst),
298
                .g(g),
299
 
300
                .W(W),
301
 
302
                .Z(Z),
303
                .DC(DC),
304
                .C(C)
305
            );
306
 
307
////////////////////////////////////////////////////////////////////////////////
308
////////////////////////////////////////////////////////////////////////////////
309
//
310
//  Microprocessor Core Implementation
311
//
312
//  Pipeline Instruction Register Assignments
313
 
314
assign GOTO      = dIR[0];
315
assign CALL      = dIR[1];
316
assign RETLW     = dIR[2];
317
assign WE_SLEEP  = dIR[3];
318
assign WE_WDTCLR = dIR[4];
319
assign WE_TRISA  = dIR[5];
320
assign WE_TRISB  = dIR[6];
321
assign WE_TRISC  = dIR[7];
322
assign WE_OPTION = dIR[8];
323
assign LITERAL   = dIR[9];      // Added to support WE/RE PortX external I/F
324
 
325
//  Skip Logic
326
 
327
assign Tst = ALU_Op[8];
328
 
329
always @(*)
330
begin
331
    Skip <= WE_SLEEP | WE_PCL
332
            | ((Tst) ? ((ALU_Op[7] & ALU_Op[6]) ? g    : Z_Tst)
333
                     : ((GOTO | CALL | RETLW)   ? 1'b1 : 1'b0 ));
334
end
335
 
336
//  File Register Address Multiplexer
337
 
338
assign INDF = ALU_Op[10];
339
assign FA   = ((INDF) ? FSR
340
                      : ((KI[4]) ? {FSR[6:5], KI[4:0]}
341
                                 : {    2'b0, KI[4:0]}));
342
 
343
//  File Register Write Enable
344
 
345
assign WE_F = ALU_Op[11];
346
 
347
//  Special Function Register Write Enables
348
 
349
assign WE_TMR0   =  WE_F & (FA[4:0] == pTMR0);
350
assign WE_PCL    =  WE_F & (FA[4:0] == pPCL);
351
assign WE_STATUS =  WE_F & (FA[4:0] == pSTATUS);
352
assign WE_FSR    =  WE_F & (FA[4:0] == pFSR);
353
//
354
//  I/O Ports moved to an external implementation
355
//      WE_PortX asserts for an FA address match when LITERAL not asserted and a
356
//          WE_F is asserted.
357
//      RE_PortX asserts for an FA address match whn LITERAL not asserted, WE_F
358
//          is not asserted, and WE_TrisX not asserted. Tris X has the same FA
359
//          field. Tristate control for port A is instruction 0x005, and FA is
360
//          the least significant 5 bits of the instruction. FA of 0x05 is the
361
//          file address of Port A. (The same applies for Tris B and Tris C.)
362
//
363
assign WE_PORTA  =  WE_F & (FA[4:0] == pPORTA) & ~LITERAL;
364
assign WE_PORTB  =  WE_F & (FA[4:0] == pPORTB) & ~LITERAL;
365
assign WE_PORTC  =  WE_F & (FA[4:0] == pPORTC) & ~LITERAL;
366
//
367
assign RE_PORTA  = ~WE_F & (FA[4:0] == pPORTA) & ~LITERAL & ~WE_TRISA;
368
assign RE_PORTB  = ~WE_F & (FA[4:0] == pPORTB) & ~LITERAL & ~WE_TRISB;
369
assign RE_PORTC  = ~WE_F & (FA[4:0] == pPORTC) & ~LITERAL & ~WE_TRISC;
370
 
371
//  Assign Write Enable for STATUS register Processor Status Word (PSW) bits
372
//      Allow write to the STATUS[2:0] bits, {Z, DC, C}, only for instructions
373
//      MOVWF, BCF, BSF, and SWAPF. Exclude instructions DECFSZ and INCFSZ.
374
 
375
assign WE_PSW = WE_STATUS & (ALU_Op[5:4] == 2'b00) & (ALU_Op[8] == 1'b0);
376
 
377
////////////////////////////////////////////////////////////////////////////////
378
//
379
// Program Counter Implementation
380
//
381
//  On CALL or MOVWF PCL (direct or indirect), load PCL from the ALU output
382
//  and the upper bits with {PA, 0}, i.e. PC[8] = 0.
383
//
384
 
385
assign Ld_PCL = CALL | WE_PCL;
386
 
387
always @(posedge Clk)
388
begin
389
    if(Rst)
390
        PC <= #1 pRstVector;    // Set PC to Reset Vector on Rst or WDT Timeout
391
    else if(CE)
392
        PC <= #1 (GOTO ? {PA, KI}
393
                       : (Ld_PCL ? {PA, 1'b0, DO}
394
                                 : (RETLW ? TOS : PC + 1)));
395
end
396
 
397
//  Stack Implementation (2 Level Stack)
398
 
399
always @(posedge Clk)
400
begin
401
    if(POR)
402
        TOS <= #1 pRstVector;       // Set TOS on Rst or WDT Timeout
403
    else if(CE)
404
        TOS <= #1 (CALL ? PC : (RETLW ? NOS : TOS));
405
end
406
 
407
always @(posedge Clk)
408
begin
409
    if(POR)
410
        NOS <= #1 pRstVector;       // Set NOS on Rst or WDT Timeout
411
    else if(CE)
412
        NOS <= #1 (CALL ? TOS : NOS);
413
end
414
 
415
////////////////////////////////////////////////////////////////////////////////
416
//
417
//  Port Configuration and Option Registers
418
 
419
always @(posedge Clk)
420
begin
421
    if(POR)
422
        OPTION <= #1 8'b0011_1111;
423
    else if(CE)
424
        OPTION <= #1 ((WE_OPTION) ? W : OPTION);
425
end
426
 
427
////////////////////////////////////////////////////////////////////////////////
428
//
429
//  CLRWDT Strobe Pulse Generator
430
 
431
always @(posedge Clk)
432
begin
433
    if(Rst)
434
        WDTClr <= #1 0;
435
    else
436
        WDTClr <= #1 (WE_WDTCLR | WE_SLEEP) & ~PwrDn;
437
end
438
 
439
////////////////////////////////////////////////////////////////////////////////
440
//
441
//  TO (Time Out) STATUS Register Bit
442
 
443
assign Rst_TO = (POR | (MCLR & PD) | WE_WDTCLR);
444
 
445
always @(posedge Clk)
446
begin
447
    if(Rst_TO)
448
        TO <= #1  0;
449
    else if(WDT_TO)
450
        TO <= #1 ~0;
451
end
452
 
453
////////////////////////////////////////////////////////////////////////////////
454
//
455
//  PD (Power Down) STATUS Register Bit - Sleep Mode
456
 
457
assign Rst_PD = POR | (WE_WDTCLR & ~PwrDn);
458
 
459
always @(posedge Clk)
460
begin
461
    if(Rst_PD)
462
        PD <= #1 0;
463
    else if(CE)
464
        PD <= #1 ((WE_SLEEP) ? 1'b1 : PD);
465
end
466
 
467
//  PwrDn - Sleep Mode Control FF: Set by SLEEP instruction, cleared by Rst
468
//          Differs from PD in that it is not readable and does not maintain
469
//          its state through Reset. Gates CE to rest of the processor.
470
 
471
always @(posedge Clk)
472
begin
473
    if(Rst)
474
        PwrDn <= #1 0;
475
    else if(ClkEn)
476
        PwrDn <= #1 ((WE_SLEEP) ? 1'b1 : PwrDn);
477
end
478
 
479
////////////////////////////////////////////////////////////////////////////////
480
//
481
//  File Register RAM
482
 
483
assign Addrs = {FA[6:5], FA[3:0]};
484
 
485
//  RAM A - 16 Word Distributed RAM
486
 
487
assign WE_RAMA = WE_F & ~FA[4] & FA[3];
488
 
489
initial
490
  $readmemh(pRAMA_Init, RAMA, 0, 7);
491
 
492
always @(posedge Clk)
493
begin
494
    if(CE)
495
        if(WE_RAMA)
496
            RAMA[Addrs[2:0]] <= #1 DO;
497
end
498
 
499
//  RAM B - 64 Word Distributed RAM
500
 
501
assign WE_RAMB = WE_F & FA[4];
502
 
503
initial
504
  $readmemh(pRAMB_Init, RAMB, 0, 63);
505
 
506
always @(posedge Clk)
507
begin
508
    if(CE)
509
        if(WE_RAMB)
510
            RAMB[Addrs] <= #1 DO;
511
end
512
 
513
////////////////////////////////////////////////////////////////////////////////
514
//
515
// Special Function Registers
516
 
517
always @(posedge Clk)
518
begin
519
    if(POR)
520
        PA  <= #1 0;
521
    else if(CE)
522
        PA  <= #1 ((WE_STATUS) ? DO[7:5] : PA);
523
end
524
 
525
always @(posedge Clk)
526
begin
527
    if(POR)
528
        FSR <= #1 0;
529
    else if(CE)
530
        FSR <= #1 ((WE_FSR) ? DO : FSR);
531
end
532
 
533
//  Generate STATUS Register
534
 
535
assign STATUS = {PA, ~TO, ~PD, Z, DC, C};
536
 
537
//  Special Function Register (SFR) Multiplexers
538
 
539
always @(*)
540
begin
541
    case(FA[2:0])
542
        3'b000 :  SFR <= 0;
543
        3'b001 :  SFR <= TMR0;
544
        3'b010 :  SFR <= PC[7:0];
545
        3'b011 :  SFR <= STATUS;
546
        3'b100 :  SFR <= FSR;
547
        3'b101 :  SFR <= IO_DI;
548
        3'b110 :  SFR <= IO_DI;
549
        3'b111 :  SFR <= IO_DI;
550
    endcase
551
end
552
 
553
//  File Data Output Multiplexer
554
 
555
assign DI = (FA[4] ? RAMB[Addrs] : (FA[3] ? RAMA[Addrs[2:0]] : SFR));
556
 
557
//  IO Data Output Multiplexer
558
 
559
assign IO_DO = ((|{WE_TRISA, WE_TRISB, WE_TRISC}) ? W : DO);
560
 
561
////////////////////////////////////////////////////////////////////////////////
562
////////////////////////////////////////////////////////////////////////////////
563
//
564
//  Watchdog Timer and Timer0 Implementation- see Figure 8-6
565
//
566
//  OPTION Register Assignments
567
 
568
assign T0CS = OPTION[5];     // Timer0 Clock Source:   1 - T0CKI,  0 - Clk
569
assign T0SE = OPTION[4];     // Timer0 Source Edge:    1 - FE,     0 - RE
570
assign PSA  = OPTION[3];     // Pre-Scaler Assignment: 1 - WDT,    0 - Timer0
571
assign PS   = OPTION[2:0];   // Pre-Scaler Count: Timer0 - 2^(PS+1), WDT - 2^PS
572
 
573
// WDT - Watchdog Timer
574
 
575
assign WDT_Rst = Rst | WDTClr;
576
 
577
always @(posedge Clk)
578
begin
579
    if(WDT_Rst)
580
        WDT <= #1 0;
581
    else if(WDTE)
582
        WDT <= #1 WDT + 1;
583
end
584
 
585
//  WDT synchronous TC FF
586
 
587
always @(posedge Clk)
588
begin
589
    if(WDT_Rst)
590
        WDT_TC <= #1 0;
591
    else
592
        WDT_TC <= #1 &WDT;
593
end
594
 
595
// WDT Timeout multiplexer
596
 
597
assign WDT_TO = (PSA ? PSC_Pls : WDT_TC);
598
 
599
////////////////////////////////////////////////////////////////////////////////
600
//
601
//  T0CKI RE/FE Pulse Generator (on Input rather than after PSCntr)
602
//
603
//      Device implements an XOR on T0CKI and a clock multiplexer for the
604
//      Prescaler since it has two clock asynchronous clock sources: the WDT
605
//      or the external T0CKI (Timer0 Clock Input). Instead of this type of
606
//      gated clock ripple counter implementation of the Prescaler, a fully
607
//      synchronous implementation has been selected. Thus, the T0CKI must be
608
//      synchronized and the falling or rising edge detected as determined by
609
//      the T0CS bit in the OPTION register. Similarly, the WDT is implemented
610
//      using the processor clock, which means that the WDT TC pulse is in the
611
//      same clock domain as the rest of the logic.
612
//
613
 
614
always @(posedge Clk)
615
begin
616
    if(Rst)
617
        dT0CKI <= #1 0;
618
    else begin
619
        dT0CKI[0] <= #1 T0CKI;                              // Synch FF #1
620
        dT0CKI[1] <= #1 dT0CKI[0];                          // Synch FF #2
621
        dT0CKI[2] <= #1 (T0SE ? (dT0CKI[1] & ~dT0CKI[0])    // Falling Edge
622
                              : (dT0CKI[0] & ~dT0CKI[1]));  // Rising Edge
623
    end
624
end
625
 
626
assign T0CKI_Pls = dT0CKI[2]; // T0CKI Pulse out, either FE/RE
627
 
628
//  Tmr0 Clock Source Multiplexer
629
 
630
assign Tmr0_CS = (T0CS ? T0CKI_Pls : CE);
631
 
632
////////////////////////////////////////////////////////////////////////////////
633
//
634
// Pre-Scaler Counter
635
 
636
assign Rst_PSC   = (PSA ? WDTClr : WE_TMR0) | Rst;
637
assign CE_PSCntr = (PSA ? WDT_TC : Tmr0_CS);
638
 
639
always @(posedge Clk)
640
begin
641
    if(Rst_PSC)
642
        PSCntr <= #1 0;
643
    else if(CE_PSCntr)
644
        PSCntr <= #1 PSCntr + 1;
645
end
646
 
647
//  Prescaler Counter Output Multiplexer
648
 
649
always @(*)
650
begin
651
    case (PS)
652
        3'b000 : PSC_Out <= PSCntr[0];
653
        3'b001 : PSC_Out <= PSCntr[1];
654
        3'b010 : PSC_Out <= PSCntr[2];
655
        3'b011 : PSC_Out <= PSCntr[3];
656
        3'b100 : PSC_Out <= PSCntr[4];
657
        3'b101 : PSC_Out <= PSCntr[5];
658
        3'b110 : PSC_Out <= PSCntr[6];
659
        3'b111 : PSC_Out <= PSCntr[7];
660
    endcase
661
end
662
 
663
// Prescaler Counter Rising Edge Detector
664
 
665
always @(posedge Clk)
666
begin
667
    if(POR)
668
        dPSC_Out <= #1 0;
669
    else begin
670
        dPSC_Out[0] <= #1 PSC_Out;
671
        dPSC_Out[1] <= #1 PSC_Out & ~dPSC_Out[0];
672
    end
673
end
674
 
675
assign PSC_Pls = dPSC_Out[1];
676
 
677
////////////////////////////////////////////////////////////////////////////////
678
//
679
// Tmr0 Counter/Timer
680
 
681
assign CE_Tmr0 = (PSA ? Tmr0_CS : PSC_Pls);
682
 
683
always @(posedge Clk)
684
begin
685
    if(POR)
686
        TMR0 <= #1 0;
687
    else if(WE_TMR0)
688
        TMR0 <= #1 DO;
689
    else if(CE_Tmr0)
690
        TMR0 <= #1 TMR0 + 1;
691
end
692
 
693
endmodule

powered by: WebSVN 2.1.0

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