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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [rtc/] [rtc.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module rtc(
28
    input               clk,
29
    input               rst_n,
30
 
31
    output reg          irq,
32
 
33
    //io slave
34
    input               io_address,
35
    input               io_read,
36
    output reg  [7:0]   io_readdata,
37
    input               io_write,
38
    input       [7:0]   io_writedata,
39
 
40
    //mgmt slave
41
    /*
42
    128.[26:0]: cycles in second
43
    129.[12:0]: cycles in 122.07031 us
44
    */
45
    input       [7:0]   mgmt_address,
46
    input               mgmt_write,
47
    input       [31:0]  mgmt_writedata
48
);
49
 
50
//------------------------------------------------------------------------------
51
 
52
reg io_read_last;
53
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) io_read_last <= 1'b0; else if(io_read_last) io_read_last <= 1'b0; else io_read_last <= io_read; end
54
wire io_read_valid = io_read && io_read_last == 1'b0;
55
 
56
//------------------------------------------------------------------------------ cycle count from mgmt
57
 
58
reg [26:0] cycles_in_second;
59
always @(posedge clk or negedge rst_n) begin
60
    if(rst_n == 1'b0)                               cycles_in_second <= 27'd30303030;
61
    else if(mgmt_write && mgmt_address == 8'd128)   cycles_in_second <= mgmt_writedata[26:0];
62
end
63
 
64
reg [12:0] cycles_in_122us;
65
always @(posedge clk or negedge rst_n) begin
66
    if(rst_n == 1'b0)                               cycles_in_122us <= 13'd4069;
67
    else if(mgmt_write && mgmt_address == 8'd129)   cycles_in_122us <= mgmt_writedata[12:0];
68
end
69
 
70
//------------------------------------------------------------------------------ io read
71
 
72
wire [7:0] io_readdata_next =
73
    (io_address == 1'b0)?       8'hFF :
74
    (ram_address == 7'h00)?     rtc_second :
75
    (ram_address == 7'h01)?     alarm_second :
76
    (ram_address == 7'h02)?     rtc_minute :
77
    (ram_address == 7'h03)?     alarm_second :
78
    (ram_address == 7'h04)?     rtc_hour :
79
    (ram_address == 7'h05)?     alarm_hour :
80
    (ram_address == 7'h06)?     rtc_dayofweek :
81
    (ram_address == 7'h07)?     rtc_dayofmonth :
82
    (ram_address == 7'h08)?     rtc_month :
83
    (ram_address == 7'h09)?     rtc_year :
84
    (ram_address == 7'h0A)?     { sec_state == SEC_UPDATE_IN_PROGRESS || sec_state == SEC_SECOND_START, divider, periodic_rate } :
85
    (ram_address == 7'h0B)?     { crb_freeze, crb_int_periodic_ena, crb_int_alarm_ena, crb_int_update_ena,
86
                                  1'b0, crb_binarymode, crb_24hour, crb_daylightsaving } :
87
    (ram_address == 7'h0C)?     { irq, periodic_interrupt, alarm_interrupt, update_interrupt, 4'd0 } :
88
    (ram_address == 7'h0D)?     8'h80 :
89
    (ram_address == 7'h32)?     rtc_century :
90
    (ram_address == 7'h37)?     rtc_century :
91
                                ram_q;
92
 
93
always @(posedge clk or negedge rst_n) begin
94
    if(rst_n == 1'b0)   io_readdata <= 8'd0;
95
    else                io_readdata <= io_readdata_next;
96
end
97
 
98
//------------------------------------------------------------------------------ irq
99
 
100
wire interrupt_start = irq == 1'b0 && (
101
    (crb_int_periodic_ena && periodic_interrupt) ||
102
    (crb_int_alarm_ena    && alarm_interrupt) ||
103
    (crb_int_update_ena   && update_interrupt) );
104
 
105
always @(posedge clk or negedge rst_n) begin
106
    if(rst_n == 1'b0)                                                       irq <= 1'b0;
107
    else if(io_read_valid && io_address == 1'b1 && ram_address == 7'h0C)    irq <= 1'b0;
108
    else if(interrupt_start)                                                irq <= 1'b1;
109
end
110
 
111
//------------------------------------------------------------------------------ once per second state machine
112
 
113
localparam [2:0] SEC_UPDATE_START       = 3'd0;
114
localparam [2:0] SEC_UPDATE_IN_PROGRESS = 3'd1;
115
localparam [2:0] SEC_SECOND_START       = 3'd2;
116
localparam [2:0] SEC_SECOND_IN_PROGRESS = 3'd3;
117
localparam [2:0] SEC_STOPPED            = 3'd4;
118
 
119
reg [2:0] sec_state;
120
 
121
always @(posedge clk or negedge rst_n) begin
122
    if(rst_n == 1'b0)                                                                                   sec_state <= SEC_UPDATE_START;
123
 
124
    else if(crb_freeze || divider[2:1] == 2'b11)                                                        sec_state <= SEC_STOPPED;
125
    else if(sec_state == SEC_STOPPED)                                                                   sec_state <= SEC_UPDATE_START;
126
 
127
    else if(sec_state == SEC_UPDATE_START)                                                              sec_state <= SEC_UPDATE_IN_PROGRESS;
128
    else if(sec_state == SEC_UPDATE_IN_PROGRESS && sec_timeout == 27'd0)                                sec_state <= SEC_SECOND_START;
129
    else if(sec_state == SEC_SECOND_START)                                                              sec_state <= SEC_SECOND_IN_PROGRESS;
130
    else if(sec_state == SEC_SECOND_IN_PROGRESS && sec_timeout == { 13'd0, cycles_in_122us, 1'b0 })     sec_state <= SEC_UPDATE_START;
131
end
132
 
133
reg [26:0] sec_timeout;
134
always @(posedge clk or negedge rst_n) begin
135
    if(rst_n == 1'b0)                               sec_timeout <= 27'd8137; //4069*2 -1
136
    else if(crb_freeze || divider[2:1] == 2'b11)    sec_timeout <= 27'd8137; //4069*2 -1
137
    else if(sec_timeout == 27'd0)                   sec_timeout <= cycles_in_second;
138
    else                                            sec_timeout <= sec_timeout - 27'd1;
139
end
140
 
141
reg update_interrupt;
142
always @(posedge clk or negedge rst_n) begin
143
    if(rst_n == 1'b0)                                                       update_interrupt <= 1'b0;
144
    else if(io_read_valid && io_address == 1'b1 && ram_address == 7'h0C)    update_interrupt <= 1'b0;
145
    else if(sec_state == SEC_SECOND_START)                                  update_interrupt <= 1'b1;
146
end
147
 
148
//------------------------------------------------------------------------------
149
 
150
wire max_second =
151
    (crb_binarymode && rtc_second >= 8'd59) ||
152
    (~(crb_binarymode) && (rtc_second[7:4] >= 4'd6 || (rtc_second[7:4] == 4'd5 && rtc_second[3:0] >= 4'd9)));
153
 
154
wire [7:0] next_second =
155
    (max_second)?                                       8'd0 :
156
    (~(crb_binarymode) && rtc_second[3:0] >= 4'd9)?     { rtc_second[7:4] + 4'd1, 4'd0 } :
157
                                                        rtc_second + 8'd1;
158
 
159
wire max_minute =
160
    (crb_binarymode && rtc_minute >= 8'd59) ||
161
    (~(crb_binarymode) && (rtc_minute[7:4] >= 4'd6 || (rtc_minute[7:4] == 4'd5 && rtc_minute[3:0] >= 4'd9)));
162
 
163
wire [7:0] next_minute =
164
    (max_minute)?                                       8'd0 :
165
    (~(crb_binarymode) && rtc_minute[3:0] >= 4'd9)?     { rtc_minute[7:4] + 4'd1, 4'd0 } :
166
                                                        rtc_minute + 8'd1;
167
 
168
wire dst_april   = crb_daylightsaving && rtc_dayofweek == 8'd1 && rtc_month == 8'd4 &&
169
    ((crb_binarymode && rtc_dayofmonth >= 8'd24) || (~(crb_binarymode) && rtc_dayofmonth[7:4] >= 4'd2 && rtc_dayofmonth[3:0] >= 4'd4)) &&
170
    rtc_hour == 8'd1;
171
 
172
wire dst_october = crb_daylightsaving && rtc_dayofweek == 8'd1 &&
173
    ((crb_binarymode && rtc_month == 8'd10) || (~(crb_binarymode) && rtc_month[7:4] == 4'd1 && rtc_month[3:0] == 4'd0)) &&
174
    ((crb_binarymode && rtc_dayofmonth >= 8'd25) || (~(crb_binarymode) && rtc_dayofmonth[7:4] >= 4'd2 && rtc_dayofmonth[3:0] >= 4'd5)) &&
175
    rtc_hour == 8'd1;
176
 
177
wire max_hour =
178
    (~(crb_24hour) && crb_binarymode    && rtc_hour[7] && rtc_hour[6:0] >= 7'd12) ||
179
    (crb_24hour    && crb_binarymode    && rtc_hour >= 8'd23) ||
180
    (~(crb_24hour) && ~(crb_binarymode) && rtc_hour[7] && (rtc_hour[6:4] >= 3'd2 || (rtc_hour[6:4] == 3'd1 && rtc_hour[3:0] >= 4'd2))) ||
181
    (crb_24hour    && ~(crb_binarymode) && (rtc_hour[7:4] >= 4'd3 || (rtc_hour[7:4] == 4'd2 && rtc_hour[3:0] >= 4'd3)));
182
 
183
wire [7:0] next_hour =
184
    (dst_april)?                                                                                8'd3 :
185
    (dst_october)?                                                                              8'd1 :
186
    (~(crb_24hour) && max_hour)?                                                                8'd1 :
187
    (crb_24hour    && max_hour)?                                                                8'd0 :
188
    (~(crb_24hour) && crb_binarymode    && rtc_hour[6:0] >= 7'd12)?                             8'h81 :
189
    (~(crb_24hour) && ~(crb_binarymode) && rtc_hour[6:4] == 3'd1 && rtc_hour[3:0] >= 4'd2)?     8'h81 :
190
    (~(crb_24hour) && ~(crb_binarymode) && rtc_hour[6:4] == 3'd0 && rtc_hour[3:0] >= 4'd9)?     { rtc_hour[7], 3'b1, 4'd0 }  :
191
    (crb_24hour    && ~(crb_binarymode) && rtc_hour[3:0] >= 4'd9)?                              { rtc_hour[7:4] + 4'd1, 4'd0 } :
192
                                                                                                rtc_hour + 8'd1;
193
 
194
wire max_dayofweek = rtc_dayofweek >= 8'd7;
195
 
196
wire [7:0] next_dayofweek =
197
    (max_dayofweek)?    8'd1 :
198
                        rtc_dayofweek + 8'd1;
199
 
200
//simplified leap year condition
201
wire leap_year =
202
    (crb_binarymode    && rtc_year[1:0] == 2'b00) ||
203
    (~(crb_binarymode) && ((rtc_year[1:0] == 2'b00 && rtc_year[4] == 1'b0) || (rtc_year[1:0] == 2'b10 && rtc_year[4] == 1'b1)));
204
 
205
wire max_dayofmonth =
206
    (crb_binarymode && (
207
        (rtc_month <= 8'd1  && rtc_dayofmonth >= 8'd31) ||
208
        (rtc_month == 8'd2  && ((~(leap_year) && rtc_dayofmonth >= 8'd28) || (leap_year && rtc_dayofmonth >= 8'd29))) ||
209
        (rtc_month == 8'd3  && rtc_dayofmonth >= 8'd31) ||
210
        (rtc_month == 8'd4  && rtc_dayofmonth >= 8'd30) ||
211
        (rtc_month == 8'd5  && rtc_dayofmonth >= 8'd31) ||
212
        (rtc_month == 8'd6  && rtc_dayofmonth >= 8'd30) ||
213
        (rtc_month == 8'd7  && rtc_dayofmonth >= 8'd31) ||
214
        (rtc_month == 8'd8  && rtc_dayofmonth >= 8'd31) ||
215
        (rtc_month == 8'd9  && rtc_dayofmonth >= 8'd30) ||
216
        (rtc_month == 8'd10 && rtc_dayofmonth >= 8'd31) ||
217
        (rtc_month == 8'd11 && rtc_dayofmonth >= 8'd30) ||
218
        (rtc_month >= 8'd12 && rtc_dayofmonth >= 8'd31))
219
    ) ||
220
    (~(crb_binarymode) && (
221
        (rtc_month <= 8'h01 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
222
        (rtc_month == 8'h02 && ((~(leap_year) && (rtc_dayofmonth[7:4] >= 4'd3 || (rtc_dayofmonth[7:4] == 4'd2 && rtc_dayofmonth[3:0] >= 4'd8))) ||
223
                               (leap_year    && (rtc_dayofmonth[7:4] >= 4'd3 || (rtc_dayofmonth[7:4] == 4'd2 && rtc_dayofmonth[3:0] >= 4'd9))))) ||
224
        (rtc_month == 8'h03 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
225
        (rtc_month == 8'h04 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3))) ||
226
        (rtc_month == 8'h05 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
227
        (rtc_month == 8'h06 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3))) ||
228
        (rtc_month == 8'h07 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
229
        (rtc_month == 8'h08 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
230
        (rtc_month == 8'h09 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3))) ||
231
        (rtc_month == 8'h10 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))) ||
232
        (rtc_month == 8'h11 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3))) ||
233
        (rtc_month >= 8'h12 && (rtc_dayofmonth[7:4] >= 4'd4 || (rtc_dayofmonth[7:4] == 4'd3 && rtc_dayofmonth[3:0] >= 4'd1))))
234
    );
235
 
236
wire [7:0] next_dayofmonth =
237
    (max_dayofmonth)?                                       8'd1 :
238
    (~(crb_binarymode) && rtc_dayofmonth[3:0] >= 4'd9)?     { rtc_dayofmonth[7:4] + 4'd1, 4'd0 } :
239
                                                            rtc_dayofmonth + 8'd1;
240
 
241
wire max_month =
242
    (crb_binarymode && rtc_month >= 8'd12) || (~(crb_binarymode) && (rtc_month[7:4] >= 4'd2 || (rtc_month[7:4] == 4'd1 && rtc_month[3:0] >= 4'd2)));
243
 
244
wire [7:0] next_month =
245
    (max_month)?                                    8'd1 :
246
    (~(crb_binarymode) && rtc_month[3:0] >= 4'd9)?  { rtc_month[7:4] + 4'd1, 4'd0 } :
247
                                                    rtc_month + 8'd1;
248
 
249
wire max_year =
250
    (crb_binarymode && rtc_year >= 8'd99) || (~(crb_binarymode) && (rtc_year[7:4] >= 4'd10 || (rtc_year[7:4] == 4'd9 && rtc_year[3:0] >= 4'd9)));
251
 
252
wire [7:0] next_year =
253
    (max_year)?                                     8'd0 :
254
    (~(crb_binarymode) && rtc_year[3:0] >= 4'd9)?   { rtc_year[7:4] + 4'd1, 4'd0 } :
255
                                                    rtc_year + 8'd1;
256
 
257
wire max_century =
258
    (crb_binarymode && rtc_century >= 8'd99) || (~(crb_binarymode) && (rtc_century[7:4] >= 4'd10 || (rtc_century[7:4] == 4'd9 && rtc_century[3:0] >= 4'd9)));
259
 
260
wire [7:0] next_century =
261
    (max_century)?                                      8'd0 :
262
    (~(crb_binarymode) && rtc_century[3:0] >= 4'd9)?    { rtc_century[7:4] + 4'd1, 4'd0 } :
263
                                                        rtc_century + 8'd1;
264
 
265
//------------------------------------------------------------------------------
266
 
267
wire rtc_second_update = sec_state == SEC_SECOND_START;
268
wire rtc_minute_update = rtc_second_update && max_second;
269
wire rtc_hour_update   = rtc_minute_update && max_minute;
270
wire rtc_day_update    = rtc_hour_update   && max_hour;
271
wire rtc_month_update  = rtc_day_update    && max_dayofmonth;
272
wire rtc_year_update   = rtc_month_update  && max_month;
273
wire rtc_century_update= rtc_year_update   && max_year;
274
 
275
//------------------------------------------------------------------------------
276
 
277
reg [7:0] rtc_second;
278
always @(posedge clk or negedge rst_n) begin
279
    if(rst_n == 1'b0)                                                   rtc_second <= 8'd0;
280
    else if(mgmt_write && mgmt_address == 8'h00)                        rtc_second <= mgmt_writedata[7:0];
281
    else if(io_write && io_address == 1'b1 && ram_address == 7'h00)     rtc_second <= io_writedata;
282
    else if(rtc_second_update)                                          rtc_second <= next_second;
283
end
284
 
285
reg [7:0] rtc_minute;
286
always @(posedge clk or negedge rst_n) begin
287
    if(rst_n == 1'b0)                                                   rtc_minute <= 8'd0;
288
    else if(mgmt_write && mgmt_address == 8'h02)                        rtc_minute <= mgmt_writedata[7:0];
289
    else if(io_write && io_address == 1'b1 && ram_address == 7'h02)     rtc_minute <= io_writedata;
290
    else if(rtc_minute_update)                                          rtc_minute <= next_minute;
291
end
292
 
293
reg [7:0] rtc_hour;
294
always @(posedge clk or negedge rst_n) begin
295
    if(rst_n == 1'b0)                                                   rtc_hour <= 8'd0;
296
    else if(mgmt_write && mgmt_address == 8'h04)                        rtc_hour <= mgmt_writedata[7:0];
297
    else if(io_write && io_address == 1'b1 && ram_address == 7'h04)     rtc_hour <= io_writedata;
298
    else if(rtc_hour_update)                                            rtc_hour <= next_hour;
299
end
300
 
301
reg [7:0] rtc_dayofweek;
302
always @(posedge clk or negedge rst_n) begin
303
    if(rst_n == 1'b0)                                                   rtc_dayofweek <= 8'd0;
304
    else if(mgmt_write && mgmt_address == 8'h06)                        rtc_dayofweek <= mgmt_writedata[7:0];
305
    else if(io_write && io_address == 1'b1 && ram_address == 7'h06)     rtc_dayofweek <= io_writedata;
306
    else if(rtc_day_update)                                             rtc_dayofweek <= next_dayofweek;
307
end
308
 
309
reg [7:0] rtc_dayofmonth;
310
always @(posedge clk or negedge rst_n) begin
311
    if(rst_n == 1'b0)                                                   rtc_dayofmonth <= 8'd0;
312
    else if(mgmt_write && mgmt_address == 8'h07)                        rtc_dayofmonth <= mgmt_writedata[7:0];
313
    else if(io_write && io_address == 1'b1 && ram_address == 7'h07)     rtc_dayofmonth <= io_writedata;
314
    else if(rtc_day_update)                                             rtc_dayofmonth <= next_dayofmonth;
315
end
316
 
317
reg [7:0] rtc_month;
318
always @(posedge clk or negedge rst_n) begin
319
    if(rst_n == 1'b0)                                                   rtc_month <= 8'd0;
320
    else if(mgmt_write && mgmt_address == 8'h08)                        rtc_month <= mgmt_writedata[7:0];
321
    else if(io_write && io_address == 1'b1 && ram_address == 7'h08)     rtc_month <= io_writedata;
322
    else if(rtc_month_update)                                           rtc_month <= next_month;
323
end
324
 
325
reg [7:0] rtc_year;
326
always @(posedge clk or negedge rst_n) begin
327
    if(rst_n == 1'b0)                                                   rtc_year <= 8'd0;
328
    else if(mgmt_write && mgmt_address == 8'h09)                        rtc_year <= mgmt_writedata[7:0];
329
    else if(io_write && io_address == 1'b1 && ram_address == 7'h09)     rtc_year <= io_writedata;
330
    else if(rtc_year_update)                                            rtc_year <= next_year;
331
end
332
 
333
reg [7:0] rtc_century;
334
always @(posedge clk or negedge rst_n) begin
335
    if(rst_n == 1'b0)                                                   rtc_century <= 8'd0;
336
    else if(mgmt_write && mgmt_address == 8'h32)                        rtc_century <= mgmt_writedata[7:0];
337
    else if(io_write && io_address == 1'b1 && ram_address == 7'h32)     rtc_century <= io_writedata;
338
    else if(io_write && io_address == 1'b1 && ram_address == 7'h37)     rtc_century <= io_writedata;
339
    else if(rtc_century_update)                                         rtc_century <= next_century;
340
end
341
 
342
//------------------------------------------------------------------------------
343
 
344
reg [7:0] alarm_second;
345
always @(posedge clk or negedge rst_n) begin
346
    if(rst_n == 1'b0)                                                   alarm_second <= 8'd0;
347
    else if(mgmt_write && mgmt_address == 8'h01)                        alarm_second <= mgmt_writedata[7:0];
348
    else if(io_write && io_address == 1'b1 && ram_address == 7'h01)     alarm_second <= io_writedata;
349
end
350
 
351
reg [7:0] alarm_minute;
352
always @(posedge clk or negedge rst_n) begin
353
    if(rst_n == 1'b0)                                                   alarm_minute <= 8'd0;
354
    else if(mgmt_write && mgmt_address == 8'h03)                        alarm_minute <= mgmt_writedata[7:0];
355
    else if(io_write && io_address == 1'b1 && ram_address == 7'h03)     alarm_minute <= io_writedata;
356
end
357
 
358
reg [7:0] alarm_hour;
359
always @(posedge clk or negedge rst_n) begin
360
    if(rst_n == 1'b0)                                                   alarm_hour <= 8'd0;
361
    else if(mgmt_write && mgmt_address == 8'h05)                        alarm_hour <= mgmt_writedata[7:0];
362
    else if(io_write && io_address == 1'b1 && ram_address == 7'h05)     alarm_hour <= io_writedata;
363
end
364
 
365
wire alarm_interrupt_activate =
366
    (alarm_second[7:6] == 2'b11 || (rtc_second_update && next_second == alarm_second)) &&
367
    (alarm_minute[7:6] == 2'b11 || (rtc_minute_update && next_minute == alarm_minute) || (~(rtc_minute_update) && rtc_minute == alarm_minute)) &&
368
    (alarm_hour[7:6] == 2'b11   || (rtc_hour_update && next_hour == alarm_hour)       || (~(rtc_hour_update)   && rtc_hour == alarm_hour));
369
 
370
reg alarm_interrupt;
371
always @(posedge clk or negedge rst_n) begin
372
    if(rst_n == 1'b0)                                                       alarm_interrupt <= 1'b0;
373
    else if(io_read_valid && io_address == 1'b1 && ram_address == 7'h0C)    alarm_interrupt <= 1'b0;
374
    else if(sec_state == SEC_SECOND_START && alarm_interrupt_activate)      alarm_interrupt <= 1'b1;
375
end
376
 
377
//------------------------------------------------------------------------------
378
 
379
/*
380
crb_freeze 1: no update, no alarm
381
*/
382
 
383
reg crb_freeze;
384
always @(posedge clk or negedge rst_n) begin
385
    if(rst_n == 1'b0)                                                   crb_freeze <= 1'b0;
386
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_freeze <= mgmt_writedata[7];
387
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_freeze <= io_writedata[7];
388
end
389
 
390
reg crb_int_periodic_ena;
391
always @(posedge clk or negedge rst_n) begin
392
    if(rst_n == 1'b0)                                                   crb_int_periodic_ena <= 1'b0;
393
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_int_periodic_ena <= mgmt_writedata[6];
394
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_int_periodic_ena <= io_writedata[6];
395
end
396
 
397
reg crb_int_alarm_ena;
398
always @(posedge clk or negedge rst_n) begin
399
    if(rst_n == 1'b0)                                                   crb_int_alarm_ena <= 1'b0;
400
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_int_alarm_ena <= mgmt_writedata[5];
401
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_int_alarm_ena <= io_writedata[5];
402
end
403
 
404
reg crb_int_update_ena;
405
always @(posedge clk or negedge rst_n) begin
406
    if(rst_n == 1'b0)                                                   crb_int_update_ena <= 1'b0;
407
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_int_update_ena <= ~(mgmt_writedata[7]) & mgmt_writedata[4];
408
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_int_update_ena <= ~(io_writedata[7]) & io_writedata[4];
409
end
410
 
411
reg crb_binarymode;
412
always @(posedge clk or negedge rst_n) begin
413
    if(rst_n == 1'b0)                                                   crb_binarymode <= 1'b0;
414
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_binarymode <= mgmt_writedata[2];
415
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_binarymode <= io_writedata[2];
416
end
417
 
418
reg crb_24hour;
419
always @(posedge clk or negedge rst_n) begin
420
    if(rst_n == 1'b0)                                                   crb_24hour <= 1'b1;
421
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_24hour <= mgmt_writedata[1];
422
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_24hour <= io_writedata[1];
423
end
424
 
425
reg crb_daylightsaving;
426
always @(posedge clk or negedge rst_n) begin
427
    if(rst_n == 1'b0)                                                   crb_daylightsaving <= 1'b0;
428
    else if(mgmt_write && mgmt_address == 8'h0B)                        crb_daylightsaving <= mgmt_writedata[0];
429
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0B)     crb_daylightsaving <= io_writedata[0];
430
end
431
 
432
//------------------------------------------------------------------------------
433
 
434
/*
435
divider 00x : no periodic
436
divider 11x : no update, no alarm
437
*/
438
 
439
reg [2:0] divider;
440
always @(posedge clk or negedge rst_n) begin
441
    if(rst_n == 1'b0)                                                   divider <= 3'd2;
442
    else if(mgmt_write && mgmt_address == 8'h0A)                        divider <= mgmt_writedata[6:4];
443
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0A)     divider <= io_writedata[6:4];
444
end
445
 
446
reg [3:0] periodic_rate;
447
always @(posedge clk or negedge rst_n) begin
448
    if(rst_n == 1'b0)                                                   periodic_rate <= 4'd6;
449
    else if(mgmt_write && mgmt_address == 8'h0A)                        periodic_rate <= mgmt_writedata[3:0];
450
    else if(io_write && io_address == 1'b1 && ram_address == 7'h0A)     periodic_rate <= io_writedata[3:0];
451
end
452
 
453
wire periodic_enabled = divider[2:1] != 2'b00 && periodic_rate != 4'd0;
454
wire periodic_start   = periodic_enabled && (
455
                            (periodic_minor == 13'd0 && periodic_major == 13'd0) ||
456
                            (periodic_minor == 13'd0 && periodic_major == 13'd1));
457
wire periodic_count   = periodic_enabled && periodic_major >= 13'd1;
458
 
459
wire [12:0] periodic_major_initial = {
460
    periodic_rate == 4'd15, periodic_rate == 4'd14, periodic_rate == 4'd13, periodic_rate == 4'd12,
461
    periodic_rate == 4'd11, periodic_rate == 4'd10, periodic_rate == 4'd9 || periodic_rate == 4'd2,  periodic_rate == 4'd8 || periodic_rate == 4'd1,
462
    periodic_rate == 4'd7,  periodic_rate == 4'd6,  periodic_rate == 4'd5,  periodic_rate == 4'd4,
463
    periodic_rate == 4'd3 };
464
 
465
reg [12:0] periodic_minor;
466
always @(posedge clk or negedge rst_n) begin
467
    if(rst_n == 1'b0)                                   periodic_minor <= 13'd0;
468
    else if(~(periodic_enabled))                        periodic_minor <= 13'd0;
469
    else if(periodic_start)                             periodic_minor <= cycles_in_122us;
470
    else if(periodic_count && periodic_minor == 13'd0)  periodic_minor <= cycles_in_122us;
471
    else if(periodic_count)                             periodic_minor <= periodic_minor - 13'd1;
472
end
473
 
474
reg [12:0] periodic_major;
475
always @(posedge clk or negedge rst_n) begin
476
    if(rst_n == 1'b0)                                   periodic_major <= 13'd0;
477
    else if(~(periodic_enabled))                        periodic_major <= 13'd0;
478
    else if(periodic_start)                             periodic_major <= periodic_major_initial;
479
    else if(periodic_count && periodic_minor == 13'd0)  periodic_major <= periodic_major - 13'd1;
480
end
481
 
482
reg periodic_interrupt;
483
always @(posedge clk or negedge rst_n) begin
484
    if(rst_n == 1'b0)                                                               periodic_interrupt <= 1'b0;
485
    else if(io_read_valid && io_address == 1'b1 && ram_address == 7'h0C)            periodic_interrupt <= 1'b0;
486
    else if(periodic_enabled && periodic_minor == 13'd0 && periodic_major == 13'd1) periodic_interrupt <= 1'b1;
487
end
488
 
489
//------------------------------------------------------------------------------
490
 
491
reg [6:0] ram_address;
492
always @(posedge clk or negedge rst_n) begin
493
    if(rst_n == 1'b0)                       ram_address <= 7'd0;
494
    else if(io_write && io_address == 1'b0) ram_address <= io_writedata[6:0];
495
end
496
 
497
//------------------------------------------------------------------------------
498
 
499
wire [7:0] ram_q;
500
 
501
simple_ram #(
502
    .width      (8),
503
    .widthad    (7)
504
)
505
rtc_ram_inst(
506
    .clk                (clk),
507
 
508
    .wraddress          ((mgmt_write && mgmt_address[7] == 1'b0)?   mgmt_address[6:0] : ram_address),
509
    .wren               ((mgmt_write && mgmt_address[7] == 1'b0) || (io_write && io_address == 1'b1)),
510
    .data               ((mgmt_write && mgmt_address[7] == 1'b0)?   mgmt_writedata[7:0] : io_writedata),
511
 
512
    .rdaddress          ((io_write && io_address == 1'b0)?  io_writedata[6:0] : ram_address),
513
    .q                  (ram_q)
514
);
515
 
516
//------------------------------------------------------------------------------
517
 
518
// synthesis translate_off
519
wire _unused_ok = &{ 1'b0, mgmt_writedata[31:27], 1'b0 };
520
// synthesis translate_on
521
 
522
//------------------------------------------------------------------------------
523
 
524
endmodule

powered by: WebSVN 2.1.0

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