]> git.ozlabs.org Git - minimigmac.git/blob - fpga/rtc.v
Initial commit
[minimigmac.git] / fpga / rtc.v
1 /* Mac Plus real time clock
2  *
3  * Doesn't do much yet ... eventually needs a backbus interface
4  * to save/restore PRAM to the PIC. Not much I can do about the
5  * actual RTC tho.
6  * 
7  *
8  * NOTE:
9  * 
10  * The HW ref manual seems to indicate that the RTC chip latches
11  * on raising clock but SW should latch on falling clock. However
12  * that isn't what the ROM does.
13  * 
14  * The actual transfer done by the ROM looks like:
15  * 
16  *  * Byte send:
17  *     - Direction set to output, value 111 (disabled, clock & data high)
18  *     - Set enabled and clock to 0
19  *     8 times: - Set value bit and clock to 0
20  *              - Set clock to 1
21  * 
22  * So the transfer "completes" with clock high after sending the last bit,
23  * the next transfer is then either a read or a write. In the later case,
24  * the ROM goes back to the same routine above, which means it continues
25  * clocking bits without a significant "hickup".
26  * 
27  * For a read however, what happens next is:
28  * 
29  *    - Set direction to input (at this point clock is still high)
30  *    - Clear data (no effect as direction is input) and clock
31  *    8 times: - Set clock to 0
32  *             - Set clock to 1
33  *             - Read bit
34  *    - Set direction to output
35  * 
36  * Finally disable chip.
37  * 
38  * You will notice that this is quite bogus since there's no way
39  * for the RTC chip to know after a read when to stop driving the
40  * data line before the Mac sets the direction back to output,
41  * so there -will- be some contention... oops. This isn't a problem
42  * for us though as we use separate signals.
43  */
44
45 module rtc(input                sysclk,
46            input                reset,
47            output reg           onesec, 
48            input                data_in,
49            output               data_out,
50            input                data_clock,
51            input                _data_enable);
52
53         parameter divider = 23'h7a1200;
54                            
55         /* Sysclk is 16Mhz, to generate a 1-sec pulse, we need
56          * a 23-bit counter
57          */
58         reg [22:0]              cnt;
59         reg                     oldclk;
60         wire                    dstrobe;
61         wire                    gotbyte;
62         reg [7:0]               rdata;  
63         reg [7:0]               shift;
64         reg [7:0]               addr;
65         reg                     dir;
66         reg                     ckaddr;
67         reg [2:0]               bitcnt;
68         
69         localparam rtc_state_cmd        = 0;
70         localparam rtc_state_read       = 1;
71         localparam rtc_state_write      = 2;
72         localparam rtc_state_cmd2       = 3;
73         reg [1:0]               state;
74
75         /* Generate one second tick */
76         always@(posedge sysclk or posedge reset) begin
77                 if (reset) begin
78                         cnt <= divider;
79                         onesec <= 0;
80                 end else begin
81                         if (cnt == 0) begin
82                                 onesec <= ~onesec;
83                                 cnt <= divider;
84                         end else
85                           cnt <= cnt - 1;
86                 end
87         end
88
89         /* Data clock edge detect buffer */
90         always@(posedge sysclk or posedge reset) begin
91                 if (reset)
92                   oldclk <= 1;
93                 else
94                   oldclk <= data_clock;
95         end
96
97         assign dstrobe = data_clock & ~oldclk & ~_data_enable;
98
99 `ifdef __foo__  
100         /* Shift bit counter */
101         always@(posedge sysclk or posedge reset) begin
102                 if (reset) begin
103                         bitcnt <= 7;
104                 end else begin
105                         if (_data_enable)
106                           bitcnt <= 7;
107                         else if (dstrobe)
108                           bitcnt <= bitcnt - 1;
109                 end
110         end
111         assign gotbyte = (bitcnt == 0) && dstrobe;      
112
113         /* Shift register */
114         always@(posedge sysclk or posedge reset) begin
115                 if (reset)
116                         shift <= 0;
117                 else begin
118                         if (_data_enable)
119                           shift <= 0;
120                         else if (dstrobe) begin
121                                 if (state == rtc_state_read && bitcnt == 3'b111)
122                                   shift <= rdata;
123                                 else
124                                   shift <= { shift[6:0], data_in };
125                         end                     
126                 end
127         end
128         assign data_out = shift[7];     
129
130         /* Latch/decode command byte into address, ckaddr and dir */
131         always@(posedge sysclk or posedge reset) begin
132                 if (reset) begin
133                         addr <= 0;
134                         dir <= 0;
135                         ckaddr <= 0;                    
136                 end else if (gotbyte) begin
137                         if (state == rtc_state_cmd) begin
138                                 dir <= shift[7];
139                                 addr <= shift;
140                         end else if (state == rtc_state_cmd2)
141                           addr <= { addr[2:0], shift[6:2] };                    
142                 end             
143         end
144
145         /* State machine */
146         always@(posedge sysclk or posedge reset) begin
147                 if (reset) begin
148                         state <= rtc_state_cmd;
149                 end else begin
150                         if (_data_enable)
151                           state <= rtc_state_cmd;
152                         else if (gotbyte) begin
153                                 if (state == rtc_state_cmd) begin
154                                         if (shift[6:3] == 4'b1111)
155                                           state <= rtc_state_cmd2;
156                                         else if (shift[7])
157                                           state <= rtc_state_read;
158                                         else
159                                           state <= rtc_state_write;
160                                 end else if (state == rtc_state_cmd2) begin
161                                         if (addr[7])
162                                           state <= rtc_state_read;
163                                         else
164                                           state <= rtc_state_write;
165                                 end else
166                                   state <= rtc_state_cmd;
167                         end
168                 end
169         end
170
171         /* Read machine */
172         always@(posedge sysclk or posedge reset) begin
173                 if (reset) begin
174                         rdata <= 0;
175                 end else begin
176                 end             
177         end
178 `endif
179         
180 endmodule