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

Subversion Repositories rtcclock

[/] [rtcclock/] [trunk/] [rtl/] [rtcdate.v] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 dgisselq
///////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    rtcdate.v
4
//              
5
// Project:     A Wishbone Controlled Real--time Clock Core
6
//
7
// Purpose:
8
//      This core provides a real-time date function that can be coupled with
9
//      a real-time clock.  The date provided is in Binary Coded Decimal (bcd)
10
//      form, and available for reading and writing over the Wishbone Bus.
11
//
12
// WARNING: Race conditions exist when updating the date across the Wishbone
13
//      bus at or near midnight.  (This should be obvious, but it bears
14
//      stating.)  Specifically, if the update command shows up at the same
15
//      clock as the ppd clock, then the ppd clock will be ignored and the 
16
//      new date will be the date of the day following midnight.  However,
17
//      if the update command shows up one clock before the ppd, then the date
18
//      may be updated, but may have problems dealing with the last day of the
19
//      month or year.  To avoid race conditions, update the date sometime
20
//      after the stroke of midnight and before 5 clocks before the next
21
//      midnight.  If you are concerned that you might hit a race condition, 
22
//      just read the clock again (5+ clocks later) to make certain you set 
23
//      it correctly.
24
//
25
//
26
// Creator:     Dan Gisselquist, Ph.D.
27
//              Gisselquist Tecnology, LLC
28
//
29
///////////////////////////////////////////////////////////////////////////
30
//
31
// Copyright (C) 2015, Gisselquist Technology, LLC
32
//
33
// This program is free software (firmware): you can redistribute it and/or
34
// modify it under the terms of  the GNU General Public License as published
35
// by the Free Software Foundation, either version 3 of the License, or (at
36
// your option) any later version.
37
//
38
// This program is distributed in the hope that it will be useful, but WITHOUT
39
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
40
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
41
// for more details.
42
//
43
// You should have received a copy of the GNU General Public License along
44
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
45
// target there if the PDF file isn't present.)  If not, see
46
// <http://www.gnu.org/licenses/> for a copy.
47
//
48
// License:     GPL, v3, as defined and found on www.gnu.org,
49
//              http://www.gnu.org/licenses/gpl.html
50
//
51
//
52
///////////////////////////////////////////////////////////////////////////
53
module rtcdate(i_clk, i_ppd, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_data,
54
                o_wb_ack, o_wb_stall, o_wb_data);
55
        input   i_clk;
56
        // A one part per day signal, i.e. basically a clock enable line that
57
        // controls when the beginning of the day happens.  This line should
58
        // be high on the very last second of any day in order for the rtcdate
59
        // module to always have the right date.
60
        input   i_ppd;
61
        // Wishbone inputs
62
        input   i_wb_cyc, i_wb_stb, i_wb_we;
63
        input   [31:0]   i_wb_data;
64
        // Wishbone outputs
65
        output  reg     o_wb_ack;
66
        output  wire    o_wb_stall;
67
        output  wire    [31:0]   o_wb_data;
68
 
69
 
70
        reg     [5:0]    r_day;
71
        reg     [4:0]    r_mon;
72
        reg     [13:0]   r_year;
73
 
74
        reg     last_day_of_month, last_day_of_year, is_leap_year;
75
        always @(posedge i_clk)
76
                last_day_of_year <= (last_day_of_month) && (r_mon == 5'h12);
77
        always @(posedge i_clk)
78
        begin
79
                case(r_mon)
80
                5'h01: last_day_of_month <= (r_day >= 6'h31); // Jan
81
                5'h02: last_day_of_month <= (r_day >= 6'h29)
82
                                ||((~is_leap_year)&&(r_day == 6'h28));
83
                5'h03: last_day_of_month <= (r_day >= 6'h31); // March
84
                5'h04: last_day_of_month <= (r_day >= 6'h30); // April
85
                5'h05: last_day_of_month <= (r_day >= 6'h31); // May
86
                5'h06: last_day_of_month <= (r_day >= 6'h30); // June
87
                5'h07: last_day_of_month <= (r_day >= 6'h31); // July
88
                5'h08: last_day_of_month <= (r_day >= 6'h31); // August
89
                5'h09: last_day_of_month <= (r_day >= 6'h30); // Sept
90
                5'h10: last_day_of_month <= (r_day >= 6'h31); // October
91
                5'h11: last_day_of_month <= (r_day >= 6'h30); // November
92
                5'h12: last_day_of_month <= (r_day >= 6'h31); // December
93
                default: last_day_of_month <= 1'b0;
94
                endcase
95
        end
96
 
97
        reg     year_divisible_by_four, century_year, four_century_year;
98
        always @(posedge i_clk)
99
                year_divisible_by_four<= ((~r_year[0])&&(r_year[4]==r_year[1]));
100
        always @(posedge i_clk)
101
                century_year <= (r_year[7:0] == 8'h00);
102
        always @(posedge i_clk)
103
                four_century_year <= ((~r_year[8])&&((r_year[12]==r_year[9])));
104
        always @(posedge i_clk)
105
                is_leap_year <= (year_divisible_by_four)&&((~century_year)
106
                        ||((century_year)&&(four_century_year)));
107
 
108
 
109
        // Adjust the day of month
110
        initial r_day = 6'h01;
111
        always @(posedge i_clk)
112
        begin
113
                if ((r_day == 0)||(r_day > 6'h31)||(r_day[3:0] > 4'h9))
114
                        r_day <= 6'h01;
115
                else if ((i_ppd)&&(last_day_of_month))
116
                        r_day <= 6'h01;
117
                else if ((i_ppd)&&(r_day[3:0] != 4'h9))
118
                        r_day[3:0] <= r_day[3:0] + 4'h1;
119
                else if (i_ppd)
120
                begin
121
                        r_day[3:0] <= 4'h0;
122
                        r_day[5:4] <= r_day[5:4] + 2'h1;
123
                end
124
 
125
                if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)&&(i_wb_data[7:0]!=8'hff))
126
                        r_day <= i_wb_data[5:0];
127
        end
128
 
129
        // Adjust the month of the year
130
        initial r_mon = 5'h01;
131
        always @(posedge i_clk)
132
        begin
133
                if ((r_mon == 0)||(r_mon > 5'h12)||(r_mon[3:0] > 4'h9))
134
                        r_mon <= 5'h01;
135
                else if ((i_ppd)&&(last_day_of_year))
136
                        r_mon <= 5'h01;
137
                else if ((i_ppd)&&(last_day_of_month)&&(r_mon[3:0] != 4'h9))
138
                        r_mon[3:0] <= r_mon[3:0] + 4'h1;
139
                else if ((i_ppd)&&(last_day_of_month))
140
                begin
141
                        r_mon[3:0] <= 4'h0;
142
                        r_mon[4] <= 1;
143
                end
144
 
145
                if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)&&(i_wb_data[15:8]!=8'hff))
146
                        r_mon <= i_wb_data[12:8];
147
        end
148
 
149
        // Adjust the year
150
        initial r_year = 14'h2000;
151
        always @(posedge i_clk)
152
        begin
153
                // Deal with any out of bounds conditions
154
                if (r_year[3:0] > 4'h9)
155
                        r_year[3:0] <= 4'h0;
156
                if (r_year[7:4] > 4'h9)
157
                        r_year[7:4] <= 4'h0;
158
                if (r_year[11:8] > 4'h9)
159
                        r_year[11:8] <= 4'h0;
160
                if ((i_ppd)&&(last_day_of_year))
161
                begin
162
                        if (r_year[3:0] != 4'h9)
163
                                r_year[3:0] <= r_year[3:0] + 4'h1;
164
                        else begin
165
                                r_year[3:0] <= 4'h0;
166
                                if (r_year[7:4] != 4'h9)
167
                                        r_year[7:4] <= r_year[7:4] + 4'h1;
168
                                else begin
169
                                        r_year[7:4] <= 4'h0;
170
                                        if (r_year[11:8] != 4'h9)
171
                                                r_year[11:8] <= r_year[11:8]+4'h1;
172
                                        else begin
173
                                                r_year[11:8] <= 4'h0;
174
                                                r_year[13:12] <= r_year[13:12]+2'h1;
175
                                        end
176
                                end
177
                        end
178
                end
179
 
180
                if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)&&(i_wb_data[31:16]!=16'hffff))
181
                        r_year <= i_wb_data[29:16];
182
        end
183
 
184
        always @(posedge i_clk)
185
                o_wb_ack <= ((i_wb_cyc)&&(i_wb_stb));
186
        assign  o_wb_stall = 1'b0;
187
        assign  o_wb_data = { 2'h0, r_year, 3'h0, r_mon, 2'h0, r_day };
188
endmodule

powered by: WebSVN 2.1.0

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