]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/blob - core/omsp_watchdog.v
OpenMSP430 core verilog source files moved to "core" subdirectory.
[fpga/openmsp430.git] / core / omsp_watchdog.v
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
3 //
4 // This source file may be used and distributed without restriction provided
5 // that this copyright statement is not removed from the file and that any
6 // derivative work contains the original copyright notice and the associated
7 // disclaimer.
8 //
9 // This source file is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published
11 // by the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This source is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this source; if not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 //----------------------------------------------------------------------------
24 //
25 // *File Name: omsp_watchdog.v
26 // 
27 // *Module Description:
28 //                       Watchdog Timer
29 //
30 // *Author(s):
31 //              - Olivier Girard,    olgirard@gmail.com
32 //
33 //----------------------------------------------------------------------------
34 // $Rev: 34 $
35 // $LastChangedBy: olivier.girard $
36 // $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
37 //----------------------------------------------------------------------------
38 `include "timescale.v"
39 `include "openMSP430_defines.v"
40
41 module  omsp_watchdog (
42
43 // OUTPUTs
44     nmi_evt,                        // NMI Event
45     per_dout,                       // Peripheral data output
46     wdtifg_set,                     // Set Watchdog-timer interrupt flag
47     wdtpw_error,                    // Watchdog-timer password error
48     wdttmsel,                       // Watchdog-timer mode select
49
50 // INPUTs
51     aclk_en,                        // ACLK enable
52     dbg_freeze,                     // Freeze Watchdog counter
53     mclk,                           // Main system clock
54     nmi,                            // Non-maskable interrupt (asynchronous)
55     nmie,                           // Non-maskable interrupt enable
56     per_addr,                       // Peripheral address
57     per_din,                        // Peripheral data input
58     per_en,                         // Peripheral enable (high active)
59     per_wen,                        // Peripheral write enable (high active)
60     puc,                            // Main system reset
61     smclk_en,                       // SMCLK enable
62     wdtie                           // Watchdog timer interrupt enable
63 );
64
65 // OUTPUTs
66 //=========
67 output              nmi_evt;        // NMI Event
68 output       [15:0] per_dout;       // Peripheral data output
69 output              wdtifg_set;     // Set Watchdog-timer interrupt flag
70 output              wdtpw_error;    // Watchdog-timer password error
71 output              wdttmsel;       // Watchdog-timer mode select
72
73 // INPUTs
74 //=========
75 input               aclk_en;        // ACLK enable
76 input               dbg_freeze;     // Freeze Watchdog counter
77 input               mclk;           // Main system clock
78 input               nmi;            // Non-maskable interrupt (asynchronous)
79 input               nmie;           // Non-maskable interrupt enable
80 input         [7:0] per_addr;       // Peripheral address
81 input        [15:0] per_din;        // Peripheral data input
82 input               per_en;         // Peripheral enable (high active)
83 input         [1:0] per_wen;        // Peripheral write enable (high active)
84 input               puc;            // Main system reset
85 input               smclk_en;       // SMCLK enable
86 input               wdtie;          // Watchdog timer interrupt enable
87
88
89 //=============================================================================
90 // 1)  PARAMETER DECLARATION
91 //=============================================================================
92
93 // Register addresses
94 parameter           WDTCTL     = 9'h120;
95
96
97 // Register one-hot decoder
98 parameter           WDTCTL_D   = (512'h1 << WDTCTL);
99
100
101 //============================================================================
102 // 2)  REGISTER DECODER
103 //============================================================================
104
105 // Register address decode
106 reg  [511:0]  reg_dec; 
107 always @(per_addr)
108   case ({per_addr,1'b0})
109     WDTCTL :     reg_dec  =  WDTCTL_D;
110     default:     reg_dec  =  {512{1'b0}};
111   endcase
112
113 // Read/Write probes
114 wire reg_write =  |per_wen   & per_en;
115 wire reg_read  = ~|per_wen   & per_en;
116
117 // Read/Write vectors
118 wire [511:0] reg_wr    = reg_dec & {512{reg_write}};
119 wire [511:0] reg_rd    = reg_dec & {512{reg_read}};
120
121
122 //============================================================================
123 // 3) REGISTERS
124 //============================================================================
125
126 // WDTCTL Register
127 //-----------------
128 // WDTNMI & WDTSSEL are not implemented and therefore masked
129    
130 reg  [7:0] wdtctl;
131
132 wire       wdtctl_wr = reg_wr[WDTCTL];
133
134 always @ (posedge mclk or posedge puc)
135   if (puc)            wdtctl <=  8'h00;
136   else if (wdtctl_wr) wdtctl <=  per_din[7:0] & 8'hd7;
137
138 wire       wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a);
139 wire       wdttmsel    = wdtctl[4];
140
141
142 //============================================================================
143 // 3) REGISTERS
144 //============================================================================
145
146 // Data output mux
147 wire [15:0] wdtctl_rd  = {8'h69, wdtctl}  & {16{reg_rd[WDTCTL]}};
148
149 wire [15:0] per_dout   =  wdtctl_rd;
150
151
152 //=============================================================================
153 // 4)  NMI GENERATION
154 //=============================================================================
155
156 // Synchronization state
157 reg [2:0] nmi_sync;
158 always @ (posedge mclk or posedge puc)
159   if (puc)  nmi_sync <= 3'h0;
160   else      nmi_sync <= {nmi_sync[1:0], nmi};
161
162 // Edge detection
163 wire        nmi_re    = ~nmi_sync[2] &  nmi_sync[0] & nmie;
164 wire        nmi_fe    =  nmi_sync[2] & ~nmi_sync[0] & nmie;
165
166 // NMI event
167 wire        nmi_evt   = wdtctl[6] ? nmi_fe : nmi_re;
168
169
170 //=============================================================================
171 // 5)  WATCHDOG TIMER
172 //=============================================================================
173
174 // Watchdog clock source selection
175 //---------------------------------
176 wire  clk_src_en = wdtctl[2] ? aclk_en : smclk_en;
177
178
179 // Watchdog 16 bit counter
180 //--------------------------
181 reg [15:0] wdtcnt;
182
183 wire       wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set;
184
185 always @ (posedge mclk or posedge puc)
186   if (puc)                                        wdtcnt <= 16'h0000;
187   else if (wdtcnt_clr)                            wdtcnt <= 16'h0000;
188   else if (~wdtctl[7] & clk_src_en & ~dbg_freeze) wdtcnt <= wdtcnt+16'h0001;
189
190    
191 // Interval selection mux
192 //--------------------------
193 reg        wdtqn;
194
195 always @(wdtctl or wdtcnt)
196     case(wdtctl[1:0])
197       2'b00  : wdtqn =  wdtcnt[15];
198       2'b01  : wdtqn =  wdtcnt[13];
199       2'b10  : wdtqn =  wdtcnt[9];
200       default: wdtqn =  wdtcnt[6];
201     endcase
202
203
204 // Watchdog event detection
205 //-----------------------------
206 reg        wdtqn_dly;
207
208 always @ (posedge mclk or posedge puc)
209   if (puc) wdtqn_dly <= 1'b0;
210   else     wdtqn_dly <= wdtqn;
211
212 wire       wdtifg_set =  (~wdtqn_dly & wdtqn) | wdtpw_error;
213
214
215 endmodule // omsp_watchdog
216
217 `include "openMSP430_undefines.v"