MacPlus_MiSTer/rtl/rtc.v
2021-03-20 20:16:45 +08:00

126 lines
2.7 KiB
Verilog

/* PRAM - RTC implementation for plus_too */
module rtc (
input clk,
input reset,
input [32:0] timestamp, // unix timestamp
input _cs,
input ck,
input dat_i,
output reg dat_o
);
reg [2:0] bit_cnt;
reg ck_d;
reg [7:0] din;
reg [7:0] cmd;
reg [7:0] dout;
reg cmd_mode;
reg receiving;
reg [31:0] secs;
reg [31:0] secs2;
reg [7:0] ram[20];
reg [24:0] clocktoseconds;
initial begin
ram[5'h00] = 8'hA8;
ram[5'h01] = 8'h00;
ram[5'h02] = 8'h00;
ram[5'h03] = 8'h22;
ram[5'h04] = 8'hCC;
ram[5'h05] = 8'h0A;
ram[5'h06] = 8'hCC;
ram[5'h07] = 8'h0A;
ram[5'h08] = 8'h00;
ram[5'h09] = 8'h00;
ram[5'h0A] = 8'h00;
ram[5'h0B] = 8'h00;
ram[5'h0C] = 8'h00;
ram[5'h0D] = 8'h02;
ram[5'h0E] = 8'h63;
ram[5'h0F] = 8'h00;
ram[5'h10] = 8'h03;
ram[5'h11] = 8'h88;
ram[5'h12] = 8'h00;
ram[5'h13] = 8'h6C;
end
initial secs = 0;
always @(posedge clk) begin
if (reset) begin
bit_cnt <= 0;
receiving <= 1;
cmd_mode <= 1;
dat_o <= 1;
// sec_cnt <= 0;
end
else begin
// timestamp is only sent at core load
if (secs==0)
secs <= timestamp[31:0] + 2082844800; // difference between unix epoch and mac epoch
// we need to add one to the seconds
clocktoseconds<= clocktoseconds + 1'd1;
if (32499999==clocktoseconds) // every 32mhz we increment secs by one
begin
clocktoseconds<=0;
secs<=secs+1;
end
if (_cs) begin
bit_cnt <= 0;
receiving <= 1;
cmd_mode <= 1;
dat_o <= 1;
end
else begin
ck_d <= ck;
// transmit at the falling edge
if (ck_d & ~ck & !receiving)
dat_o <= dout[7-bit_cnt];
// receive at the rising edge of ck
if (~ck_d & ck) begin
bit_cnt <= bit_cnt + 1'd1;
if (receiving)
din <= {din[6:0], dat_i};
if (bit_cnt == 7) begin
if (receiving && cmd_mode) begin
// command byte received
cmd_mode <= 0;
receiving <= ~din[6];
cmd <= {din[6:0], dat_i};
casez ({din[5:0], dat_i})
7'b00?0001: dout <= secs[7:0];
7'b00?0101: dout <= secs[15:8];
7'b00?1001: dout <= secs[23:16];
7'b00?1101: dout <= secs[31:24];
7'b010??01: dout <= ram[{3'b100, din[2:1]}];
7'b1????01: dout <= ram[din[4:1]];
default: ;
endcase
end
if (receiving && !cmd_mode) begin
// data byte received
casez (cmd[6:0])
7'b0000001: secs[7:0] <= {din[6:0], dat_i};
7'b0000101: secs[15:8] <= {din[6:0], dat_i};
7'b0001001: secs[23:16] <= {din[6:0], dat_i};
7'b0001101: secs[31:24] <= {din[6:0], dat_i};
7'b010??01: ram[{3'b100, cmd[3:2]}] <= {din[6:0], dat_i};
7'b1????01: ram[cmd[5:2]] <= {din[6:0], dat_i};
default: ;
endcase
end
end
end
end
end
end
endmodule