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

Subversion Repositories mpeg2fpga

[/] [mpeg2fpga/] [trunk/] [rtl/] [mpeg2/] [watchdog.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kdv
/*
2
 * watchdog.v
3
 *
4
 * Copyright (c) 2009 Koen De Vleeschauwer.
5
 *
6
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
7
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
10
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16
 * SUCH DAMAGE.
17
 */
18
 
19
/*
20
 * watchdog.v - watchdog timer. Generate reset if decoder not active during x seconds.
21
 *
22
 * The decoder is reset if the variable length decoding is inactive for
23
 * 256*256*16*(repeat_frame+1)*(watchdog_interval+1) clock cycles.
24
 *
25
 * The watchdog timer begins to run if the decoder asserts busy.
26
 *
27
 * The watchdog timer is reset if
28
 * - the 'busy' signal is low OR
29
 * - the source_select is non-zero (software output frame override) OR
30
 * - repeat_frame is 31 ("freeze frame") OR
31
 * - watchdog_interval is 255 (watchdog timer manually switched off).
32
 *
33
 * multiplying the watchdog timeout by (repeat_frame+1) causes the watchdog
34
 * timeout to increase if the video is slowed down.
35
 *
36
 * The watchdog can't use the "sync_rst" global reset, because the "sync_rst" signal
37
 * goes low when the watchdog timer expires.
38
 * If the watchdog were to use the "sync_rst" global reset, feedback might occur.
39
 * The watchdog uses the "hard_rst" global reset, which depends only on the
40
 * rst input pin.
41
 */
42
 
43
`include "timescale.v"
44
 
45
`undef DEBUG
46
//`define DEBUG 1
47
 
48
`undef CHECK
49
`ifdef __IVERILOG__
50
`define CHECK 1
51
`endif
52
 
53
module watchdog(
54
  clk,
55
  hard_rst,
56
  source_select,
57
  repeat_frame,
58
  busy,
59
  watchdog_rst,
60
  watchdog_interval,
61
  watchdog_interval_wr,
62
  watchdog_status_rd,
63
  watchdog_status
64
  );
65
 
66
  input              clk;                          // clock
67
  input              hard_rst;                     // "hard reset" input
68
 
69
  input         [2:0]source_select;                // select video out source
70
  input         [4:0]repeat_frame;
71
  input              busy;                         // high if decoder does not accept input
72
 
73
  output reg         watchdog_rst;                 // watchdog-generated reset signal. normally high; low during one clock cycle when watchdog timer expires.
74
  output reg         watchdog_status;              // asserted if watchdog expired
75
 
76
  input              watchdog_interval_wr;         // register file: asserted when the watchdog interval is written.
77
  input         [7:0]watchdog_interval;            // register file: value of the watchdog interval. 255 = never expire; 0 = expire immediate.
78
  input              watchdog_status_rd;           // register file: asserted if watchdog_status is read.
79
  wire               watchdog_expire_immediate = watchdog_interval_wr && (watchdog_interval == 8'd0);   // asserted if 8'd0 is written to watchdog_interval
80
 
81
  reg           [4:0]repeat_cnt;
82
  reg                decoder_active;
83
  reg           [7:0]watchdog_cnt;
84
 
85
  reg          [15:0]timer_lsb;                   // watchdog timer, lower 16 bits
86
  reg          [15:0]timer_msb;                   // watchdog timer, upper 16 bits
87
 
88
  reg          [15:0]holdoff_lsb;                 // holdoff timer, lower 16 bits
89
  reg          [15:0]holdoff_msb;                 // holdoff timer, upper 16 bits
90
 
91
  /*
92
   * FSM states
93
   */
94
 
95
  parameter [2:0]
96
    STATE_INIT     = 3'h0,
97
    STATE_HOLDOFF  = 3'h1,
98
    STATE_CLEAR    = 3'h2,
99
    STATE_TIMER    = 3'h3,
100
    STATE_EXPIRE   = 3'h4;
101
 
102
  reg          [2:0]state;
103
  reg          [2:0]next;
104
 
105
  /* next state logic */
106
  always @*
107
    case (state)
108
      STATE_INIT:              next = STATE_HOLDOFF;
109
 
110
      STATE_HOLDOFF:           if (watchdog_expire_immediate) next = STATE_EXPIRE;
111
                               else if (holdoff_msb[10]) next = STATE_CLEAR;
112
                               else next = STATE_HOLDOFF;
113
 
114
      STATE_CLEAR:             if (watchdog_expire_immediate) next = STATE_EXPIRE;
115
                               else if (decoder_active) next = STATE_CLEAR;
116
                               else next = STATE_TIMER;
117
 
118
      STATE_TIMER:             if (watchdog_expire_immediate) next = STATE_EXPIRE;
119
                               else if (decoder_active) next = STATE_CLEAR;
120
                               else if (watchdog_interval_wr) next = STATE_CLEAR; // reset watchdog timer if new watchdog_interval is written
121
                               else if (timer_msb[2]) next = STATE_EXPIRE;
122
                               else next = STATE_TIMER;
123
 
124
      STATE_EXPIRE:            next = STATE_INIT;
125
 
126
      default                  next = STATE_INIT;
127
    endcase
128
 
129
  /* state */
130
  always @(posedge clk)
131
    if(~hard_rst) state <= STATE_INIT;
132
    else state <= next;
133
 
134
  /*
135
   * Definition of decoder active:
136
   * - ~busy: decoder accepts data
137
   * - source_select != 3'd0: output frame override OR
138
   * - repeat_frame == 4'd31: output frame picture freeze OR
139
   * - watchdog_interval == 8'd0: watchdog timer expires and is switched off. (one-shot mode)
140
   * - watchdog_interval == 8'd255: watchdog timer switched off.
141
   *
142
   */
143
 
144
  always @(posedge clk)
145
    if (~hard_rst) decoder_active <= 1'b0;
146
    else decoder_active <= ~busy || (source_select != 3'd0) || (repeat_frame == 5'd31) || (watchdog_interval == 8'd0) || (watchdog_interval == 8'd255);
147
 
148
  /*
149
   * Watchdog reset and status outputs.
150
   * Note the scaling factor of the watchdog timer can be changed.
151
   * E.g. using timer_msb[3] instead of timer_msb[2] in will double the watchdog timeout,
152
   * while using timer_msb[1] will halve the watchdog timeout.
153
   * The current tap (timer_msb[2]) ought to be OK for clocks in the 25MHz .. 100Mhz range.
154
   * If watchdog_interval is 127 (default value) and repeat_frame is 0 (default value),
155
   * a tap at bit 2  corresponds to a watchdog timer interval of 2**25,
156
   * or 447 ms @ 75 MHz clock.
157
   */
158
 
159
  initial                 // Power-on value
160
    watchdog_rst <= 1'b1; // This synthesizes; see Xilinx AR# 29112
161
 
162
  always @(posedge clk)
163
    if (~hard_rst) watchdog_rst <= 1'b1;
164
    else if (state == STATE_EXPIRE) watchdog_rst <= 1'b0;
165
    else watchdog_rst <= 1'b1;
166
 
167
  always @(posedge clk)
168
    if (~hard_rst) watchdog_status <= 1'b0;
169
    else if (state == STATE_EXPIRE) watchdog_status <= 1'b1;  // set when watchdog timer expires
170
    else if (watchdog_status_rd) watchdog_status <= 1'b0; // clear when status register read access
171
    else watchdog_status <= watchdog_status;
172
 
173
  /*
174
   * Watchdog timer.
175
   */
176
 
177
  always @(posedge clk)
178
    if (~hard_rst) timer_lsb <= 16'b0;
179
    else if (state == STATE_CLEAR) timer_lsb <= 16'b0;
180
    else if ((state == STATE_TIMER) && (repeat_cnt == 5'b0) && (watchdog_cnt == 8'b0)) timer_lsb <= timer_lsb + 16'd1;
181
    else timer_lsb <= timer_lsb;
182
 
183
  always @(posedge clk)
184
    if (~hard_rst) timer_msb <= 16'b0;
185
    else if (state == STATE_CLEAR) timer_msb <= 16'b0;
186
    else if ((state == STATE_TIMER) && (repeat_cnt == 5'b0) && (watchdog_cnt == 8'b0) && (timer_lsb == 16'hffff)) timer_msb <= timer_msb + 16'd1;
187
    else timer_msb <= timer_msb;
188
 
189
  /*
190
   * Holdoff timer
191
   * Timer uses two 16-bit words. Tap at bit 10 of the second word (holdoff_msb[10]).
192
   * This corresponds to a holdoff timer of 2**(10+16) = 2**26 clk cycles,
193
   * or 894 ms @ 75 MHz clock.
194
   */
195
 
196
  always @(posedge clk)
197
    if (~hard_rst) holdoff_lsb <= 16'b0;
198
    else if (state == STATE_INIT) holdoff_lsb <= 16'b0;
199
    else if (state == STATE_HOLDOFF) holdoff_lsb <= holdoff_lsb + 16'b1;
200
    else holdoff_lsb <= holdoff_lsb;
201
 
202
  always @(posedge clk)
203
    if (~hard_rst) holdoff_msb <= 16'b0;
204
    else if (state == STATE_INIT) holdoff_msb <= 16'b0;
205
    else if ((state == STATE_HOLDOFF) && (holdoff_lsb == 16'hffff)) holdoff_msb <= holdoff_msb + 16'b1;
206
    else holdoff_msb <= holdoff_msb;
207
 
208
  /*
209
   * Counters. Divide clock by (repeat_frame + 1).(watchdog_interval + 1)
210
   * This results in the watchdog timeout being multiplied by (repeat_frame + 1)
211
   * if the video images are shown (repeat_frame + 1) times.
212
   */
213
 
214
  always @(posedge clk)
215
    if (~hard_rst) repeat_cnt <= 5'b0;
216
    else if (repeat_cnt == 5'b0) repeat_cnt <= repeat_frame;
217
    else repeat_cnt <= repeat_cnt - 5'b1;
218
 
219
  always @(posedge clk)
220
    if (~hard_rst) watchdog_cnt <= 8'b0;
221
    else if ((repeat_cnt == 5'b0) && (watchdog_cnt == 8'b0)) watchdog_cnt <= watchdog_interval;
222
    else if (repeat_cnt == 5'b0) watchdog_cnt <= watchdog_cnt - 8'b1;
223
    else watchdog_cnt <= watchdog_cnt;
224
 
225
`ifdef DEBUG
226
 
227
  always @(posedge clk)
228
    case (state)
229
      STATE_INIT:                               #0 $display("%m         STATE_INIT");
230
      STATE_HOLDOFF:                            #0 $display("%m         STATE_HOLDOFF");
231
      STATE_CLEAR:                              #0 $display("%m         STATE_CLEAR");
232
      STATE_TIMER:                              #0 $display("%m         STATE_TIMER");
233
      STATE_EXPIRE:                             #0 $display("%m         STATE_EXPIRE");
234
      default                                   #0 $display("%m         *** Error: unknown state %d", state);
235
    endcase
236
 
237
  always @(posedge clk)
238
    begin
239
      $strobe("%m\tdecoder_active: %d repeat_cnt: %3d watchdog_cnt: %3d timer: %3d watchdog_rst: %d watchdog_status: %d",
240
                   decoder_active, repeat_cnt, watchdog_cnt, timer, watchdog_rst, watchdog_status);
241
    end
242
 
243
`endif
244
 
245
endmodule
246
/* not truncated */

powered by: WebSVN 2.1.0

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