diff --git a/Gameboy.sv b/Gameboy.sv index df3c88f..52e95ab 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -457,6 +457,13 @@ wire [2:0] mapper_sel = status[41:39]; assign joy0_rumble = {8'd0, ((rumbling & ~status[38]) ? 8'd128 : 8'd0)}; +reg ce_32k; // 32768Hz clock for RTC +reg [9:0] ce_32k_div; +always @(posedge clk_sys) begin + ce_32k_div <= ce_32k_div + 1'b1; + ce_32k <= !ce_32k_div; +end + cart_top cart ( .reset ( reset ), @@ -511,6 +518,7 @@ cart_top cart ( .joystick_analog_0 ( joystick_analog_0 ), + .ce_32k ( ce_32k ), .RTC_time ( RTC_time ), .RTC_timestampOut ( RTC_timestampOut ), .RTC_savedtimeOut ( RTC_savedtimeOut ), diff --git a/rtl/cart.v b/rtl/cart.v index db52eb8..f209376 100644 --- a/rtl/cart.v +++ b/rtl/cart.v @@ -52,6 +52,7 @@ module cart_top ( input [15:0] joystick_analog_0, + input ce_32k, input [32:0] RTC_time, output [31:0] RTC_timestampOut, output [47:0] RTC_savedtimeOut, @@ -133,6 +134,7 @@ mappers mappers ( .joystick_analog_0 ( joystick_analog_0 ), + .ce_32k ( ce_32k ), .RTC_time ( RTC_time ), .RTC_timestampOut ( RTC_timestampOut ), .RTC_savedtimeOut ( RTC_savedtimeOut ), diff --git a/rtl/mappers/huc3.v b/rtl/mappers/huc3.v index 9cc3696..3f525ca 100644 --- a/rtl/mappers/huc3.v +++ b/rtl/mappers/huc3.v @@ -8,6 +8,7 @@ module huc3 ( input [63:0] savestate_data, inout [63:0] savestate_back_b, + input ce_32k, input [32:0] RTC_time, inout [31:0] RTC_timestampOut_b, inout [47:0] RTC_savedtimeOut_b, @@ -105,7 +106,7 @@ reg [ 7:0] rtc_index; reg [ 3:0] rtc_flags; reg [ 3:0] rtc_out; reg [ 5:0] rtc_seconds; -reg [24:0] rtc_subseconds; +reg [14:0] rtc_subseconds; reg [11:0] rtc_minutes; // Minutes of the day 0-1439 reg [15:0] rtc_days; @@ -119,15 +120,15 @@ reg [31:0] diffSeconds; wire diffSeconds_fast_count = (diffSeconds > 0); always @(posedge clk_sys) begin - rtc_subseconds <= rtc_subseconds + 1'b1; + if (ce_32k) rtc_subseconds <= rtc_subseconds + 1'b1; - if (rtc_subseconds_end) begin + if (ce_32k & rtc_subseconds_end) begin RTC_timestampOut <= RTC_timestampOut + 1'd1; end else if (diffSeconds_fast_count) begin // fast counting loaded seconds diffSeconds <= diffSeconds - 1'd1; end - if (rtc_subseconds_end | diffSeconds_fast_count) begin + if ((ce_32k & rtc_subseconds_end) | diffSeconds_fast_count) begin rtc_seconds <= rtc_seconds + 1'b1; if (rtc_seconds == 59) begin rtc_seconds <= 0; diff --git a/rtl/mappers/mappers.v b/rtl/mappers/mappers.v index 9703321..0fddb13 100644 --- a/rtl/mappers/mappers.v +++ b/rtl/mappers/mappers.v @@ -30,6 +30,7 @@ module mappers( input [15:0] joystick_analog_0, + input ce_32k, input [32:0] RTC_time, output [31:0] RTC_timestampOut, output [47:0] RTC_savedtimeOut, @@ -177,6 +178,7 @@ mbc3 map_mbc3 ( .savestate_data ( savestate_data ), .savestate_back_b ( savestate_back_b ), + .ce_32k ( ce_32k ), .RTC_time ( RTC_time ), .RTC_timestampOut_b( RTC_timestampOut_b ), .RTC_savedtimeOut_b( RTC_savedtimeOut_b ), @@ -394,6 +396,7 @@ huc3 map_huc3 ( .savestate_data ( savestate_data2 ), .savestate_back_b ( savestate_back2_b ), + .ce_32k ( ce_32k ), .RTC_time ( RTC_time ), .RTC_timestampOut_b( RTC_timestampOut_b ), .RTC_savedtimeOut_b( RTC_savedtimeOut_b ), @@ -468,7 +471,7 @@ tama map_tama ( .clk_sys ( clk_sys ), .ce_cpu ( ce ), - .ce_1x ( ce_cpu ), + .ce_32k ( ce_32k ), .savestate_load ( savestate_load ), .savestate_data ( savestate_data2 ), @@ -488,6 +491,8 @@ tama map_tama ( .cart_di ( cart_di ), .cart_oe_b ( cart_oe_b ), + .nCS ( nCS ), + .cram_rd ( cram_rd ), .cram_di ( cram_di ), .cram_do_b ( cram_do_b ), diff --git a/rtl/mappers/mbc3.v b/rtl/mappers/mbc3.v index 137afb9..65000c8 100644 --- a/rtl/mappers/mbc3.v +++ b/rtl/mappers/mbc3.v @@ -10,6 +10,7 @@ module mbc3 ( input [15:0] savestate_data, inout [15:0] savestate_back_b, + input ce_32k, input [32:0] RTC_time, inout [31:0] RTC_timestampOut_b, inout [47:0] RTC_savedtimeOut_b, @@ -147,7 +148,7 @@ assign ram_enabled = mbc_ram_enable & ~mbc3_mode & has_ram; ///////////////////////////// RTC /////////////////////////////// reg [2:0] rtc_index; -reg [25:0] rtc_subseconds; +reg [15:0] rtc_subseconds; reg [5:0] rtc_seconds, rtc_seconds_latch; reg [5:0] rtc_minutes, rtc_minutes_latch; reg [4:0] rtc_hours, rtc_hours_latch; @@ -156,7 +157,7 @@ reg rtc_overflow, rtc_overflow_latch; reg rtc_halt; wire [7:0] rtc_return; -wire rtc_subseconds_end = (rtc_subseconds >= 33554432); +wire rtc_subseconds_end = (rtc_subseconds >= 32768-1); wire RTC_timestampNew = RTC_time[32]; wire [31:0] RTC_timestampIn = RTC_time[31:0]; @@ -189,7 +190,7 @@ always @(posedge clk_sys) begin end rtc_change <= 1'b0; - rtc_subseconds <= rtc_subseconds + 1'd1; + if (ce_32k & ~rtc_halt) rtc_subseconds <= rtc_subseconds + 1'd1; if (mbc3_mode || (bk_wr && enable && img_size[9])) begin // RTC is either used by game or already used in savegame RTC_inuse <= 1'b1; @@ -226,7 +227,7 @@ always @(posedge clk_sys) begin case (rtc_index) 0: begin rtc_seconds <= cart_di[5:0]; - rtc_subseconds <= 26'd0; + rtc_subseconds <= 0; end 1: rtc_minutes <= cart_di[5:0]; 2: rtc_hours <= cart_di[4:0]; @@ -240,14 +241,14 @@ always @(posedge clk_sys) begin end else begin // normal counting - if (rtc_subseconds_end) begin - rtc_subseconds <= 26'd0; + if (ce_32k & rtc_subseconds_end) begin + rtc_subseconds <= 0; RTC_timestampOut <= RTC_timestampOut + 1'd1; end else if (diffSeconds_fast_count) begin // fast counting loaded seconds diffSeconds <= diffSeconds - 1'd1; end - if (rtc_subseconds_end | diffSeconds_fast_count) begin + if ((ce_32k & rtc_subseconds_end) | diffSeconds_fast_count) begin if (~rtc_halt) begin rtc_change <= 1'b1; rtc_seconds <= rtc_seconds + 1'd1; diff --git a/rtl/mappers/tama.v b/rtl/mappers/tama.v index e9cd823..4b655ea 100644 --- a/rtl/mappers/tama.v +++ b/rtl/mappers/tama.v @@ -3,7 +3,7 @@ module tama ( input clk_sys, input ce_cpu, - input ce_1x, + input ce_32k, input savestate_load, input [63:0] savestate_data, @@ -74,7 +74,7 @@ reg ram_io; reg prev_cram_rd; reg [6:0] rtc_seconds; -reg [21:0] rtc_subseconds; +reg [14:0] rtc_subseconds; reg [6:0] rtc_minutes; reg [5:0] rtc_hours; reg [5:0] rtc_days; @@ -84,7 +84,7 @@ reg rtc_24hours; reg [3:0] rtc_index; reg [1:0] rtc_leap_year; -wire sec_inc = &rtc_subseconds; // 4Mhz +wire sec_inc = &rtc_subseconds; reg [5:0] days_in_month; always @* begin @@ -136,9 +136,9 @@ always @(posedge clk_sys) begin cram_wr_r <= 1'd0; ram_io <= 1'd0; prev_cram_rd <= 1'd0; - end else if(ce_cpu) begin + end else begin - if (cart_wr & ~nCS & ~cart_addr[14]) begin // $A000-BFFF + if (ce_cpu & cart_wr & ~nCS & ~cart_addr[14]) begin // $A000-BFFF if (cart_addr[0]) begin reg_index <= cart_di[3:0]; // Register index if (cart_di[3:0] == 4'hA) begin @@ -163,7 +163,7 @@ always @(posedge clk_sys) begin // TODO: Get RTC working. How does the game use the RTC? // The in game timer runs at ~16x speed so 1 minute passes every 3.75 seconds. // Does the RTC also run 16x speed or only when the Game Boy is on? - if (ce_1x) begin + if (ce_32k) begin rtc_subseconds <= rtc_subseconds + 1'b1; if (sec_inc) begin rtc_seconds[3:0] <= rtc_seconds[3:0] + 1'b1; @@ -226,53 +226,55 @@ always @(posedge clk_sys) begin end end - cram_wr_r <= 0; - ram_io <= 0; - if (reg_start) begin - reg_start <= 0; + if (ce_cpu) begin + cram_wr_r <= 0; + ram_io <= 0; + if (reg_start) begin + reg_start <= 0; - if (|rtc_sel) begin // RTC - if (rtc_sel == 2'd1) begin - case (reg_addr) - 5'h04: begin - rtc_minutes <= reg_data_in[6:0]; - rtc_seconds <= 0; - rtc_subseconds <= 0; - end - 5'h05: rtc_hours <= reg_data_in[5:0]; - 5'h06: rtc_index <= 0; - default: ; - endcase + if (|rtc_sel) begin // RTC + if (rtc_sel == 2'd1) begin + case (reg_addr) + 5'h04: begin + rtc_minutes <= reg_data_in[6:0]; + rtc_seconds <= 0; + rtc_subseconds <= 0; + end + 5'h05: rtc_hours <= reg_data_in[5:0]; + 5'h06: rtc_index <= 0; + default: ; + endcase + end + + if (rtc_sel == 2'd2) begin + case ({reg_addr,reg_data_in[3:0]}) + {2'd0, 4'h7}: rtc_days[3:0] <= reg_data_in[7:4]; + {2'd0, 4'h8}: rtc_days[5:4] <= reg_data_in[5:4]; + {2'd0, 4'h9}: rtc_month[3:0] <= reg_data_in[7:4]; + {2'd0, 4'hA}: rtc_month[4] <= reg_data_in[4]; + {2'd0, 4'hB}: rtc_year[3:0] <= reg_data_in[7:4]; + {2'd0, 4'hC}: rtc_year[7:4] <= reg_data_in[7:4]; + + {2'd2, 4'hA}: rtc_24hours <= reg_data_in[4]; + {2'd2, 4'hB}: rtc_leap_year <= reg_data_in[5:4]; + default: ; + endcase + end + + end else begin // RAM + cram_wr_r <= ~ram_read; + ram_io <= 1; end - - if (rtc_sel == 2'd2) begin - case ({reg_addr,reg_data_in[3:0]}) - {2'd0, 4'h7}: rtc_days[3:0] <= reg_data_in[7:4]; - {2'd0, 4'h8}: rtc_days[5:4] <= reg_data_in[5:4]; - {2'd0, 4'h9}: rtc_month[3:0] <= reg_data_in[7:4]; - {2'd0, 4'hA}: rtc_month[4] <= reg_data_in[4]; - {2'd0, 4'hB}: rtc_year[3:0] <= reg_data_in[7:4]; - {2'd0, 4'hC}: rtc_year[7:4] <= reg_data_in[7:4]; - - {2'd2, 4'hA}: rtc_24hours <= reg_data_in[4]; - {2'd2, 4'hB}: rtc_leap_year <= reg_data_in[5:4]; - default: ; - endcase - end - - end else begin // RAM - cram_wr_r <= ~ram_read; - ram_io <= 1; end - end - if (ram_io & ram_read) begin - reg_data_out <= cram_di; - end + if (ram_io & ram_read) begin + reg_data_out <= cram_di; + end - prev_cram_rd <= cram_rd; - if (prev_cram_rd & ~cram_rd & ~cart_addr[0] & |rtc_sel & reg_index[3:1] == 3'b110) begin - rtc_index <= rtc_index + 1'b1; + prev_cram_rd <= cram_rd; + if (prev_cram_rd & ~cram_rd & ~cart_addr[0] & |rtc_sel & reg_index[3:1] == 3'b110) begin + rtc_index <= rtc_index + 1'b1; + end end end end