1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
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
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.
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.
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
23 //----------------------------------------------------------------------------
25 // *File Name: omsp_watchdog.v
27 // *Module Description:
31 // - Olivier Girard, olgirard@gmail.com
33 //----------------------------------------------------------------------------
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"
41 module omsp_watchdog (
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
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
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
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
89 //=============================================================================
90 // 1) PARAMETER DECLARATION
91 //=============================================================================
94 parameter WDTCTL = 9'h120;
97 // Register one-hot decoder
98 parameter WDTCTL_D = (512'h1 << WDTCTL);
101 //============================================================================
102 // 2) REGISTER DECODER
103 //============================================================================
105 // Register address decode
108 case ({per_addr,1'b0})
109 WDTCTL : reg_dec = WDTCTL_D;
110 default: reg_dec = {512{1'b0}};
114 wire reg_write = |per_wen & per_en;
115 wire reg_read = ~|per_wen & per_en;
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}};
122 //============================================================================
124 //============================================================================
128 // WDTNMI & WDTSSEL are not implemented and therefore masked
132 wire wdtctl_wr = reg_wr[WDTCTL];
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;
138 wire wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a);
139 wire wdttmsel = wdtctl[4];
142 //============================================================================
144 //============================================================================
147 wire [15:0] wdtctl_rd = {8'h69, wdtctl} & {16{reg_rd[WDTCTL]}};
149 wire [15:0] per_dout = wdtctl_rd;
152 //=============================================================================
154 //=============================================================================
156 // Synchronization state
158 always @ (posedge mclk or posedge puc)
159 if (puc) nmi_sync <= 3'h0;
160 else nmi_sync <= {nmi_sync[1:0], nmi};
163 wire nmi_re = ~nmi_sync[2] & nmi_sync[0] & nmie;
164 wire nmi_fe = nmi_sync[2] & ~nmi_sync[0] & nmie;
167 wire nmi_evt = wdtctl[6] ? nmi_fe : nmi_re;
170 //=============================================================================
172 //=============================================================================
174 // Watchdog clock source selection
175 //---------------------------------
176 wire clk_src_en = wdtctl[2] ? aclk_en : smclk_en;
179 // Watchdog 16 bit counter
180 //--------------------------
183 wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set;
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;
191 // Interval selection mux
192 //--------------------------
195 always @(wdtctl or wdtcnt)
197 2'b00 : wdtqn = wdtcnt[15];
198 2'b01 : wdtqn = wdtcnt[13];
199 2'b10 : wdtqn = wdtcnt[9];
200 default: wdtqn = wdtcnt[6];
204 // Watchdog event detection
205 //-----------------------------
208 always @ (posedge mclk or posedge puc)
209 if (puc) wdtqn_dly <= 1'b0;
210 else wdtqn_dly <= wdtqn;
212 wire wdtifg_set = (~wdtqn_dly & wdtqn) | wdtpw_error;
215 endmodule // omsp_watchdog
217 `include "openMSP430_undefines.v"