diff --git a/Gameboy.sv b/Gameboy.sv index a726550..aa8fbaf 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -425,7 +425,8 @@ wire [9:0] mbc_bank; wire [7:0] ram_mask_file, cart_ram_size; wire isGBC_game, isSGB_game; wire cart_has_save; -wire [31:0] RTC_timestampOut, RTC_savedtimeOut; +wire [31:0] RTC_timestampOut; +wire [47:0] RTC_savedtimeOut; wire RTC_inuse; cart_top cart ( @@ -969,6 +970,7 @@ assign sd_buff_din = (sd_lba[7:0] <= ram_mask_file) ? bk_q : // normal saveram (sd_buff_addr == 8'd1) ? RTC_timestampOut[31:16] : (sd_buff_addr == 8'd2) ? RTC_savedtimeOut[15:0] : (sd_buff_addr == 8'd3) ? RTC_savedtimeOut[31:16] : + (sd_buff_addr == 8'd4) ? RTC_savedtimeOut[47:32] : 16'hFFFF; diff --git a/files.qip b/files.qip index d9e9298..7881b86 100644 --- a/files.qip +++ b/files.qip @@ -25,9 +25,11 @@ set_global_assignment -name VERILOG_FILE rtl/mappers/mbc1.v set_global_assignment -name VERILOG_FILE rtl/mappers/mbc2.v set_global_assignment -name VERILOG_FILE rtl/mappers/mbc3.v set_global_assignment -name VERILOG_FILE rtl/mappers/mbc5.v +set_global_assignment -name VERILOG_FILE rtl/mappers/mbc6.v set_global_assignment -name VERILOG_FILE rtl/mappers/mbc7.v set_global_assignment -name VERILOG_FILE rtl/mappers/mmm01.v set_global_assignment -name VERILOG_FILE rtl/mappers/huc1.v +set_global_assignment -name VERILOG_FILE rtl/mappers/huc3.v set_global_assignment -name VERILOG_FILE rtl/mappers/gb_camera.v set_global_assignment -name VERILOG_FILE rtl/mappers/tama.v set_global_assignment -name SDC_FILE Gameboy.sdc diff --git a/rtl/cart.v b/rtl/cart.v index 67fe0b6..349a4bd 100644 --- a/rtl/cart.v +++ b/rtl/cart.v @@ -47,7 +47,7 @@ module cart_top ( input [32:0] RTC_time, output [31:0] RTC_timestampOut, - output [31:0] RTC_savedtimeOut, + output [47:0] RTC_savedtimeOut, output RTC_inuse, input [63:0] SaveStateExt_Din, @@ -106,9 +106,11 @@ mappers mappers ( .mbc3 ( mbc3 ), .mbc30( mbc30 ), .mbc5 ( mbc5 ), + .mbc6 ( mbc6 ), .mbc7 ( mbc7 ), .mmm01 ( mmm01 ), .huc1 ( HuC1 ), + .huc3 ( HuC3 ), .gb_camera ( gb_camera ), .tama ( tama ), @@ -196,11 +198,12 @@ wire mbc3 = (cart_mbc_type == 15) || (cart_mbc_type == 16) || (cart_mbc_type == wire mbc30 = mbc3 && ( (cart_rom_size == 7) || (cart_ram_size == 5) ); //wire mbc4 = (cart_mbc_type == 21) || (cart_mbc_type == 22) || (cart_mbc_type == 23); wire mbc5 = (cart_mbc_type == 25) || (cart_mbc_type == 26) || (cart_mbc_type == 27) || (cart_mbc_type == 28) || (cart_mbc_type == 29) || (cart_mbc_type == 30); +wire mbc6 = (cart_mbc_type == 32); wire mbc7 = (cart_mbc_type == 34); wire gb_camera = (cart_mbc_type == 252); wire tama = (cart_mbc_type == 253); -//wire HuC3 = (cart_mbc_type == 254); +wire HuC3 = (cart_mbc_type == 254); wire HuC1 = (cart_mbc_type == 255); diff --git a/rtl/mappers/huc3.v b/rtl/mappers/huc3.v new file mode 100644 index 0000000..75d2bf9 --- /dev/null +++ b/rtl/mappers/huc3.v @@ -0,0 +1,239 @@ +module huc3 ( + input enable, + + input clk_sys, + input ce_cpu, + + input savestate_load, + input [63:0] savestate_data, + inout [63:0] savestate_back_b, + + input [32:0] RTC_time, + inout [31:0] RTC_timestampOut_b, + inout [47:0] RTC_savedtimeOut_b, + inout RTC_inuse_b, + + input bk_rtc_wr, + input [16:0] bk_addr, + input [15:0] bk_data, + + input has_ram, + input [3:0] ram_mask, + input [8:0] rom_mask, + + input [15:0] cart_addr, + input [7:0] cart_mbc_type, + + input cart_wr, + input [7:0] cart_di, + + input [7:0] cram_di, + inout [7:0] cram_do_b, + inout [16:0] cram_addr_b, + + inout [9:0] mbc_bank_b, + inout ram_enabled_b, + inout has_battery_b +); + +wire [9:0] mbc_bank; +wire ram_enabled; +wire [7:0] cram_do; +wire [16:0] cram_addr; +wire has_battery; +wire [63:0] savestate_back; + +reg [31:0] RTC_timestampOut; +reg [47:0] RTC_savedtimeOut; +wire RTC_inuse = 1; + +assign mbc_bank_b = enable ? mbc_bank : 10'hZ; +assign cram_do_b = enable ? cram_do : 8'hZ; +assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign ram_enabled_b = enable ? ram_enabled : 1'hZ; +assign has_battery_b = enable ? has_battery : 1'hZ; +assign savestate_back_b = enable ? savestate_back : 64'hZ; +assign RTC_timestampOut_b = enable ? RTC_timestampOut : 32'hZ; +assign RTC_savedtimeOut_b = enable ? RTC_savedtimeOut : 48'hZ; +assign RTC_inuse_b = enable ? RTC_inuse : 1'hZ; + +// --------------------- CPU register interface ------------------ + +reg [6:0] rom_bank_reg; +reg [1:0] ram_bank_reg; +reg [3:0] mode; + +assign savestate_back[ 6: 0] = rom_bank_reg; +assign savestate_back[ 8: 7] = ram_bank_reg; +assign savestate_back[12: 9] = mode; +assign savestate_back[63:13] = 0; + +always @(posedge clk_sys) begin + if(savestate_load & enable) begin + rom_bank_reg <= savestate_data[ 6: 0]; // 7'd0; + ram_bank_reg <= savestate_data[ 8: 7]; // 2'd0; + mode <= savestate_data[12: 9]; // 4'd0; + end else if(~enable) begin + rom_bank_reg <= 7'd0; + ram_bank_reg <= 2'd0; + mode <= 4'd0; + end else if(ce_cpu) begin + if (cart_wr) begin + if (~cart_addr[15]) begin + case(cart_addr[14:13]) + 2'b00: mode <= cart_di[3:0]; + 2'b01: rom_bank_reg <= cart_di[6:0]; // ROM bank register + 2'b10: ram_bank_reg <= cart_di[1:0]; // RAM bank register + default: ; + endcase + end + end + end +end + +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 [11:0] rtc_minutes; // Minutes of the day 0-1439 +reg [15:0] rtc_days; + +reg [31:0] RTC_timestampSaved; +reg [47:0] RTC_savedtimeIn; +reg RTC_timestampNew_1; +reg RTC_saveLoaded; + +wire rtc_subseconds_end = &rtc_subseconds; +reg [31:0] diffSeconds; +wire diffSeconds_fast_count = (diffSeconds > 0); + +always @(posedge clk_sys) begin + rtc_subseconds <= rtc_subseconds + 1'b1; + + if (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 + rtc_seconds <= rtc_seconds + 1'b1; + if (rtc_seconds == 59) begin + rtc_seconds <= 0; + rtc_minutes <= rtc_minutes + 1'b1; + if (rtc_minutes == 1439) begin + rtc_minutes <= 0; + rtc_days <= rtc_days + 1'b1; + end + end + end + + RTC_saveLoaded <= 1'b0; + if (bk_rtc_wr) begin // load data from savefile to intermediate register + case (bk_addr[7:0]) + 0: RTC_timestampSaved[15:0] <= bk_data; + 1: RTC_timestampSaved[31:16] <= bk_data; + 2: RTC_savedtimeIn[15:0] <= bk_data; + 3: RTC_savedtimeIn[31:16] <= bk_data; + 4: RTC_savedtimeIn[47:32] <= bk_data; + 5: RTC_saveLoaded <= 1'b1; + endcase + end + + if (RTC_saveLoaded) begin // load data from intermediate register to RTC registers + + if (RTC_timestampOut > RTC_timestampSaved) begin + diffSeconds <= RTC_timestampOut - RTC_timestampSaved; + end + + rtc_seconds <= RTC_savedtimeIn[ 5: 0]; + rtc_minutes <= RTC_savedtimeIn[17: 6]; + rtc_days <= RTC_savedtimeIn[33:18]; + end + + RTC_savedtimeOut[33: 0] <= { rtc_days, rtc_minutes, rtc_seconds }; + RTC_savedtimeOut[47:34] <= 0; + + if (~enable) begin + rtc_index <= 8'd0; + rtc_flags <= 4'd0; + rtc_out <= 4'd0; + end else if(ce_cpu & cart_wr & (cart_addr[15:13] == 3'b101)) begin // $A000-BFFF + if (mode == 4'hB) begin + if (cart_di[7:4] == 4'd1) begin + case(rtc_index) + 8'h00: rtc_out <= rtc_minutes[ 3: 0]; + 8'h01: rtc_out <= rtc_minutes[ 7: 4]; + 8'h02: rtc_out <= rtc_minutes[11: 8]; + 8'h03: rtc_out <= rtc_days[ 3: 0]; + 8'h04: rtc_out <= rtc_days[ 7: 4]; + 8'h05: rtc_out <= rtc_days[11: 8]; + 8'h06: rtc_out <= rtc_days[15:12]; + endcase + rtc_index <= rtc_index + 1'b1; + end + + if (cart_di[7:4] == 4'd2 || cart_di[7:4] == 4'd3) begin + case(rtc_index) + 8'h00: begin + rtc_minutes[ 3: 0] <= cart_di[3:0]; + rtc_seconds <= 0; + rtc_subseconds <= 0; + end + 8'h01: rtc_minutes[ 7: 4] <= cart_di[3:0]; + 8'h02: rtc_minutes[11: 8] <= cart_di[3:0]; + 8'h03: rtc_days[ 3: 0] <= cart_di[3:0]; + 8'h04: rtc_days[ 7: 4] <= cart_di[3:0]; + 8'h05: rtc_days[11: 8] <= cart_di[3:0]; + 8'h06: rtc_days[15:12] <= cart_di[3:0]; + endcase + if (cart_di[4]) rtc_index <= rtc_index + 1'b1; + end + + case(cart_di[7:4]) + 4'd4: rtc_index[3:0] <= cart_di[3:0]; + 4'd5: rtc_index[7:4] <= cart_di[3:0]; + 4'd6: rtc_flags <= cart_di[3:0]; + default: ; + endcase + end + end + + RTC_timestampNew_1 <= RTC_time[32]; // saving timestamp from HPS + if (RTC_timestampNew_1 != RTC_time[32]) begin + RTC_timestampOut <= RTC_time[31:0]; + end + +end + +wire [1:0] ram_bank = ram_bank_reg & ram_mask[1:0]; + +// 0x0000-0x3FFF = Bank 0 +wire [6:0] rom_bank = (cart_addr[15:14] == 2'b00) ? 7'd0 : rom_bank_reg; + +// mask address lines to enable proper mirroring +wire [6:0] rom_bank_m = rom_bank & rom_mask[6:0]; //64 + +reg [7:0] cram_do_r; +always @* begin + cram_do_r = 8'hFF; + case(mode) + // 0: RAM read, A: RAM read/write. Robopon reads from RAM with mode 0. + 4'h0, 4'hA: if (has_ram) cram_do_r = cram_di; // RAM + 4'hC: cram_do_r[3:0] = (rtc_flags == 4'd2) ? 4'h1 : rtc_out; // RTC + 4'hD: cram_do_r[3:0] = 4'h1; //RTC + 4'hE: cram_do_r[0] = 1'b0; // Light detected + default: ; + endcase +end + +assign mbc_bank = { 2'b00, rom_bank_m, cart_addr[13] }; // 16k ROM Bank 0-127 +assign ram_enabled = (mode == 4'hA) & has_ram; // RAM write enable + +assign cram_do = cram_do_r; +assign cram_addr = { 2'b00, ram_bank, cart_addr[12:0] }; +assign has_battery = has_ram; + + +endmodule \ No newline at end of file diff --git a/rtl/mappers/mappers.v b/rtl/mappers/mappers.v index da78590..2446ef0 100644 --- a/rtl/mappers/mappers.v +++ b/rtl/mappers/mappers.v @@ -12,9 +12,11 @@ module mappers( input mbc3, input mbc30, input mbc5, + input mbc6, input mbc7, input mmm01, input huc1, + input huc3, input gb_camera, input tama, @@ -22,7 +24,7 @@ module mappers( input [32:0] RTC_time, output [31:0] RTC_timestampOut, - output [31:0] RTC_savedtimeOut, + output [47:0] RTC_savedtimeOut, output RTC_inuse, input bk_wr, @@ -69,10 +71,13 @@ tri0 [15:0] savestate_back_b; tri0 [63:0] savestate_back2_b; tri0 [7:0] cram_wr_do_b; tri0 cram_wr_b; +tri0 [31:0] RTC_timestampOut_b; +tri0 [47:0] RTC_savedtimeOut_b; +tri0 RTC_inuse_b; wire ce = speed ? ce_cpu2x : ce_cpu; -wire no_mapper = ~(mbc1 | mbc2 | mbc3 | mbc5 | mbc7 | mmm01 | huc1 | gb_camera | tama); +wire no_mapper = ~(mbc1 | mbc2 | mbc3 | mbc5 | mbc6 | mbc7 | mmm01 | huc1 | huc3 | gb_camera | tama); mbc1 map_mbc1 ( .enable ( mbc1 ), @@ -145,9 +150,9 @@ mbc3 map_mbc3 ( .savestate_back_b ( savestate_back_b ), .RTC_time ( RTC_time ), - .RTC_timestampOut ( RTC_timestampOut ), - .RTC_savedtimeOut ( RTC_savedtimeOut ), - .RTC_inuse ( RTC_inuse ), + .RTC_timestampOut_b( RTC_timestampOut_b ), + .RTC_savedtimeOut_b( RTC_savedtimeOut_b ), + .RTC_inuse_b ( RTC_inuse_b ), .bk_wr ( bk_wr ), .bk_rtc_wr ( bk_rtc_wr ), @@ -203,6 +208,35 @@ mbc5 map_mbc5 ( .has_battery_b ( has_battery_b ) ); +mbc6 map_mbc6 ( + .enable ( mbc6 ), + + .clk_sys ( clk_sys ), + .ce_cpu ( ce ), + + .savestate_load ( savestate_load ), + .savestate_data ( savestate_data2 ), + .savestate_back_b ( savestate_back2_b ), + + .has_ram ( has_ram ), + .ram_mask ( ram_mask ), + .rom_mask ( rom_mask ), + + .cart_addr ( cart_addr ), + .cart_mbc_type ( cart_mbc_type ), + + .cart_wr ( cart_wr ), + .cart_di ( cart_di ), + + .cram_di ( cram_di ), + .cram_do_b ( cram_do_b ), + .cram_addr_b ( cram_addr_b ), + + .mbc_bank_b ( mbc_bank_b ), + .ram_enabled_b ( ram_enabled_b ), + .has_battery_b ( has_battery_b ) +); + mbc7 map_mbc7 ( .enable ( mbc7 ), @@ -299,6 +333,45 @@ huc1 map_huc1 ( .has_battery_b ( has_battery_b ) ); +huc3 map_huc3 ( + .enable ( huc3 ), + + .clk_sys ( clk_sys ), + .ce_cpu ( ce ), + + .savestate_load ( savestate_load ), + .savestate_data ( savestate_data2 ), + .savestate_back_b ( savestate_back2_b ), + + .RTC_time ( RTC_time ), + .RTC_timestampOut_b( RTC_timestampOut_b ), + .RTC_savedtimeOut_b( RTC_savedtimeOut_b ), + .RTC_inuse_b ( RTC_inuse_b ), + + .bk_rtc_wr ( bk_rtc_wr ), + .bk_addr ( bk_addr ), + .bk_data ( bk_data ), + + .has_ram ( has_ram ), + .ram_mask ( ram_mask ), + .rom_mask ( rom_mask ), + + .cart_addr ( cart_addr ), + .cart_mbc_type ( cart_mbc_type ), + + .cart_wr ( cart_wr ), + .cart_di ( cart_di ), + + .cram_di ( cram_di ), + .cram_do_b ( cram_do_b ), + .cram_addr_b ( cram_addr_b ), + + .mbc_bank_b ( mbc_bank_b ), + .ram_enabled_b ( ram_enabled_b ), + .has_battery_b ( has_battery_b ) +); + + gb_camera map_gb_camera ( .enable ( gb_camera ), @@ -362,8 +435,11 @@ tama map_tama ( .has_battery_b ( has_battery_b ) ); -assign { cram_do, ram_enabled, savestate_back, savestate_back2 } = { cram_do_b, ram_enabled_b, savestate_back_b, savestate_back2_b }; +assign { cram_do, ram_enabled } = { cram_do_b, ram_enabled_b }; +assign { savestate_back, savestate_back2 } = { savestate_back_b, savestate_back2_b }; +assign { RTC_timestampOut, RTC_savedtimeOut, RTC_inuse } = { RTC_timestampOut_b, RTC_savedtimeOut_b, RTC_inuse_b }; assign { cram_wr_do, cram_wr } = { cram_wr_do_b, cram_wr_b }; + assign mbc_bank = no_mapper ? {8'd0, cart_addr[14:13]} : mbc_bank_b; assign cram_addr = no_mapper ? {4'd0, cart_addr[12:0]} : cram_addr_b; assign has_battery = no_mapper ? (cart_mbc_type == 8'h09) : has_battery_b; diff --git a/rtl/mappers/mbc3.v b/rtl/mappers/mbc3.v index 1038f53..de29cd7 100644 --- a/rtl/mappers/mbc3.v +++ b/rtl/mappers/mbc3.v @@ -11,9 +11,9 @@ module mbc3 ( inout [15:0] savestate_back_b, input [32:0] RTC_time, - output reg [31:0] RTC_timestampOut, - output reg [31:0] RTC_savedtimeOut, - output reg RTC_inuse, + inout [31:0] RTC_timestampOut_b, + inout [47:0] RTC_savedtimeOut_b, + inout RTC_inuse_b, input bk_wr, input bk_rtc_wr, @@ -47,12 +47,19 @@ wire ram_enabled; wire has_battery; wire [15:0] savestate_back; -assign mbc_bank_b = enable ? mbc_bank : 10'hZ; -assign cram_do_b = enable ? cram_do : 8'hZ; -assign cram_addr_b = enable ? cram_addr : 17'hZ; -assign ram_enabled_b = enable ? ram_enabled : 1'hZ; -assign has_battery_b = enable ? has_battery : 1'hZ; -assign savestate_back_b = enable ? savestate_back : 16'hZ; +reg [31:0] RTC_timestampOut; +reg [47:0] RTC_savedtimeOut; +reg RTC_inuse; + +assign mbc_bank_b = enable ? mbc_bank : 10'hZ; +assign cram_do_b = enable ? cram_do : 8'hZ; +assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign ram_enabled_b = enable ? ram_enabled : 1'hZ; +assign has_battery_b = enable ? has_battery : 1'hZ; +assign savestate_back_b = enable ? savestate_back : 16'hZ; +assign RTC_timestampOut_b = enable ? RTC_timestampOut : 32'hZ; +assign RTC_savedtimeOut_b = enable ? RTC_savedtimeOut : 48'hZ; +assign RTC_inuse_b = enable ? RTC_inuse : 1'hZ; // --------------------- CPU register interface ------------------ @@ -165,9 +172,9 @@ always @(posedge clk_sys) begin RTC_inuse <= 1'b0; rtc_latch <= 1'b0; end else begin - + RTC_savedtimeOut[47:29] <= 0; if (rtc_change == 1'b0) begin // when RTC hasn't changed recently, update the register which will be written after savegame - RTC_savedtimeOut <= {3'd0, rtc_halt, rtc_overflow, rtc_days, rtc_hours, rtc_minutes, rtc_seconds}; + RTC_savedtimeOut[28:0] <= {rtc_halt, rtc_overflow, rtc_days, rtc_hours, rtc_minutes, rtc_seconds}; end rtc_change <= 1'b0; diff --git a/rtl/mappers/mbc6.v b/rtl/mappers/mbc6.v new file mode 100644 index 0000000..a8bdd5c --- /dev/null +++ b/rtl/mappers/mbc6.v @@ -0,0 +1,128 @@ +module mbc6 ( + input enable, + + input clk_sys, + input ce_cpu, + + input savestate_load, + input [63:0] savestate_data, + inout [63:0] savestate_back_b, + + input has_ram, + input [1:0] ram_mask, + input [5:0] rom_mask, + + input [15:0] cart_addr, + input [7:0] cart_mbc_type, + + input cart_wr, + input [7:0] cart_di, + + input [7:0] cram_di, + inout [7:0] cram_do_b, + inout [16:0] cram_addr_b, + + inout [9:0] mbc_bank_b, + inout ram_enabled_b, + inout has_battery_b +); + +wire [9:0] mbc_bank; +wire [7:0] cram_do; +wire [16:0] cram_addr; +wire ram_enabled; +wire has_battery; +wire [63:0] savestate_back; + +assign mbc_bank_b = enable ? mbc_bank : 10'hZ; +assign cram_do_b = enable ? cram_do : 8'hZ; +assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign ram_enabled_b = enable ? ram_enabled : 1'hZ; +assign has_battery_b = enable ? has_battery : 1'hZ; +assign savestate_back_b = enable ? savestate_back : 64'hZ; + +// --------------------- CPU register interface ------------------ + +reg [6:0] rom_bank_reg_a; +reg [6:0] rom_bank_reg_b; +reg [2:0] ram_bank_reg_a; +reg [2:0] ram_bank_reg_b; +reg ram_enable; + +assign savestate_back[ 6: 0] = rom_bank_reg_a; +assign savestate_back[13: 7] = rom_bank_reg_b; +assign savestate_back[16:14] = ram_bank_reg_a; +assign savestate_back[19:17] = ram_bank_reg_b; +assign savestate_back[ 20] = ram_enable; +assign savestate_back[63:21] = 0; + +always @(posedge clk_sys) begin + if(savestate_load & enable) begin + rom_bank_reg_a <= savestate_data[ 6: 0]; // 7'd0; + rom_bank_reg_b <= savestate_data[13: 7]; // 7'd0; + ram_bank_reg_a <= savestate_data[16:14]; // 3'd0; + ram_bank_reg_b <= savestate_data[19:17]; // 3'd0; + ram_enable <= savestate_data[ 20]; // 1'b0; + end else if(~enable) begin + rom_bank_reg_a <= 7'd0; + rom_bank_reg_b <= 7'd0; + ram_bank_reg_a <= 3'd0; + ram_bank_reg_b <= 3'd0; + ram_enable <= 1'b0; + end else if(ce_cpu) begin + if (cart_wr) begin + if (!cart_addr[15:13]) begin // $0000-1FFF + case(cart_addr[12:10]) + 3'd0: ram_enable <= (cart_di[3:0] == 4'hA); //RAM enable/disable + 3'd1: ram_bank_reg_a <= cart_di[2:0]; // 4KB RAM bank A ($A000-AFFF) + 3'd2: ram_bank_reg_b <= cart_di[2:0]; // 4KB RAM bank B ($B000-BFFF) + 3'd3: ; // Flash enable + 3'd4: ; // Flash write enable + default: ; + endcase + end + if (cart_addr[15:13] == 3'b001) begin // $2000-3FFF + case(cart_addr[12:11]) + 2'd0: rom_bank_reg_a <= cart_di[6:0]; // 8KB ROM bank A ($4000-5FFF) + 2'd1: ; //rom_flash_sel_a <= (cart_di[3:0] == 4'h8); // ROM/Flash A select + 2'd2: rom_bank_reg_b <= cart_di[6:0]; // 8KB ROM bank B ($6000-7FFF) + 2'd3: ; //rom_flash_sel_b <= (cart_di[3:0] == 4'h8); // ROM/Flash B select + endcase + end + end + end +end + +reg [6:0] rom_bank; +always @* begin + if (~cart_addr[14]) begin // $0000-3FFF + rom_bank = { 6'd0, cart_addr[13] }; + end else if (~cart_addr[13]) begin // $4000-5FFF + rom_bank = rom_bank_reg_a; + end else begin // $6000-7FFF + rom_bank = rom_bank_reg_b; + end +end + +reg [2:0] ram_bank; +always @* begin + if (~cart_addr[12]) begin // $A000-AFFF + ram_bank = ram_bank_reg_a; + end else begin // $B000-BFFF + ram_bank = ram_bank_reg_b; + end +end + +// mask address lines to enable proper mirroring +wire [6:0] rom_bank_m = rom_bank & { rom_mask[5:0], 1'b1 }; // 64x16KB Mask +wire [2:0] ram_bank_m = ram_bank & { ram_mask[1:0], 1'b1 }; // 4x8KB Mask + +assign mbc_bank = { 3'd0, rom_bank_m }; // 8KB ROM Bank 0-127 + +assign cram_do = ram_enabled ? cram_di : 8'hFF; +assign cram_addr = { 2'd0, ram_bank_m, cart_addr[11:0] }; // 4KB RAM Bank 0-7 + +assign has_battery = has_ram; +assign ram_enabled = ram_enable & has_ram; + +endmodule \ No newline at end of file