mirror of
https://github.com/MiSTer-devel/Gameboy_MiSTer.git
synced 2026-05-17 03:03:43 +00:00
3D LUT for color correction. Fix OAM in save state. (#282)
* Move Cart RAM to SDRAM Used the SDRAM controller from the NES core * 3D LUT for color correction. Load custom LUT * Add custom LUTs * Fix OAM saving to save state
This commit is contained in:
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.lut binary
|
||||
BIN
ColorLUT/dark.lut
Normal file
BIN
ColorLUT/dark.lut
Normal file
Binary file not shown.
BIN
ColorLUT/def_corrected.lut
Normal file
BIN
ColorLUT/def_corrected.lut
Normal file
Binary file not shown.
1
ColorLUT/low_contrast.lut
Normal file
1
ColorLUT/low_contrast.lut
Normal file
File diff suppressed because one or more lines are too long
204
Gameboy.sv
204
Gameboy.sv
@@ -239,6 +239,7 @@ localparam CONF_STR = {
|
||||
"h1P1FC3,GBP,Load Palette;",
|
||||
"P1OG,Frame blend,Off,On;",
|
||||
"d4P1OU,GBC Colors,Corrected,Raw;",
|
||||
"H9P1FC7,LUT,Load GBC Color LUT;",
|
||||
"P1O5,Stabilize video(buffer),Off,On;",
|
||||
"P1-;",
|
||||
"P1O34,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
|
||||
@@ -350,6 +351,8 @@ wire sys_auto = (status[15:14] == 0);
|
||||
wire sys_gbc = (status[15:14] == 2);
|
||||
wire sys_megaduck = (status[15:14] == 3);
|
||||
|
||||
wire gbc_raw_colors = status[30];
|
||||
|
||||
hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
|
||||
(
|
||||
.clk_sys(clk_sys),
|
||||
@@ -360,7 +363,7 @@ hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
|
||||
.ioctl_wr(ioctl_wr),
|
||||
.ioctl_addr(ioctl_addr),
|
||||
.ioctl_dout(ioctl_dout),
|
||||
.ioctl_wait(ioctl_wait),
|
||||
.ioctl_wait(ioctl_wait | save_wait),
|
||||
.ioctl_index(filetype),
|
||||
|
||||
.sd_lba('{sd_lba}),
|
||||
@@ -377,8 +380,8 @@ hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
|
||||
|
||||
.buttons(buttons),
|
||||
.status(status),
|
||||
.status_menumask({7'h0,
|
||||
fastboot_available,
|
||||
.status_menumask({6'h0,
|
||||
gbc_raw_colors, fastboot_available,
|
||||
sys_megaduck, boot_gba_available, sgb_border_en, isGBC,
|
||||
cart_ready, sav_supported, |tint, gg_available}),
|
||||
.status_in({status[63:34],ss_slot,status[31:0]}),
|
||||
@@ -417,6 +420,7 @@ wire cart_wr;
|
||||
wire cart_oe;
|
||||
wire [7:0] cart_di, cart_do;
|
||||
wire nCS; // WRAM or Cart RAM CS
|
||||
wire sdram_rd;
|
||||
|
||||
wire cart_download = ioctl_download && (filetype[5:0] == 6'h01 || filetype == 8'h80);
|
||||
wire md_download = ioctl_download && (filetype == 8'h81);
|
||||
@@ -425,6 +429,7 @@ wire sgb_border_download = ioctl_download && (filetype == 2);
|
||||
wire cgb_boot_download = ioctl_download && (filetype == 4);
|
||||
wire dmg_boot_download = ioctl_download && (filetype == 5);
|
||||
wire sgb_boot_download = ioctl_download && (filetype == 6);
|
||||
wire cgb_lut_download = ioctl_download && (filetype == 7);
|
||||
wire boot_download = cgb_boot_download | dmg_boot_download | sgb_boot_download;
|
||||
|
||||
///////////////////////////// Bootrom added features ///////////////////////////
|
||||
@@ -461,52 +466,82 @@ end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wire [1:0] sdram_ds = cart_download ? 2'b11 : {mbc_addr[0], ~mbc_addr[0]};
|
||||
localparam CARTRAM_BANK = 2'b01;
|
||||
|
||||
//wire [1:0] sdram_ds = cart_download ? 2'b11 : {mbc_addr[0], ~mbc_addr[0]};
|
||||
wire [15:0] sdram_do;
|
||||
wire [15:0] sdram_di = cart_download ? ioctl_dout : 16'd0;
|
||||
wire [23:0] sdram_addr = cart_download? ioctl_addr[24:1]: {2'b00, mbc_addr[22:1]};
|
||||
wire sdram_oe = ~cart_download & cart_rd & ~cram_rd;
|
||||
wire sdram_we = cart_download & dn_write;
|
||||
wire sdram_refresh_force;
|
||||
wire sdram_autorefresh = !ff_on;
|
||||
wire [15:0] sdram_di = cart_download ? ioctl_dout :
|
||||
savestate_ovr ? Savestate_CRAMWriteData :
|
||||
cart_di;
|
||||
|
||||
assign SDRAM_CKE = 1;
|
||||
wire [24:0] sdram_addr = cart_download ? ioctl_addr[24:0] :
|
||||
(savestate_ovr | is_cram_addr) ? { CARTRAM_BANK, 6'd0, cram_addr } :
|
||||
{2'b00, mbc_addr[22:0]};
|
||||
|
||||
sdram sdram (
|
||||
// interface to the MT48LC16M16 chip
|
||||
.sd_data ( SDRAM_DQ ),
|
||||
.sd_addr ( SDRAM_A ),
|
||||
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
|
||||
.sd_cs ( SDRAM_nCS ),
|
||||
.sd_ba ( SDRAM_BA ),
|
||||
.sd_we ( SDRAM_nWE ),
|
||||
.sd_ras ( SDRAM_nRAS ),
|
||||
.sd_cas ( SDRAM_nCAS ),
|
||||
.sd_clk ( SDRAM_CLK ),
|
||||
wire sdram_oe = ~cart_download & (savestate_ovr ? Savestate_CRAMRdEn : sdram_rd);
|
||||
wire sdram_we = (cart_download & dn_write) | cram_wr;
|
||||
wire sdram_pause_refresh;
|
||||
wire sdram_busy;
|
||||
|
||||
// system interface
|
||||
.clk ( clk_ram ),
|
||||
.sync ( ce_cpu2x ),
|
||||
.init ( ~pll_locked ),
|
||||
wire [15:0] save_dout;
|
||||
|
||||
// cpu interface
|
||||
.din ( sdram_di ),
|
||||
.addr ( sdram_addr ),
|
||||
.ds ( sdram_ds ),
|
||||
.we ( sdram_we ),
|
||||
.oe ( sdram_oe ),
|
||||
.autorefresh ( sdram_autorefresh ),
|
||||
.refresh ( sdram_refresh_force ),
|
||||
.dout ( sdram_do )
|
||||
assign Savestate_CRAMReadData = bram_save ? Savestate_CRAM_Q : sdram_do;
|
||||
|
||||
sdram sdram
|
||||
(
|
||||
.SDRAM_DQ(SDRAM_DQ),
|
||||
.SDRAM_A(SDRAM_A),
|
||||
.SDRAM_DQML(SDRAM_DQML),
|
||||
.SDRAM_DQMH(SDRAM_DQMH),
|
||||
.SDRAM_BA(SDRAM_BA),
|
||||
.SDRAM_nCS(SDRAM_nCS),
|
||||
.SDRAM_nWE(SDRAM_nWE),
|
||||
.SDRAM_nRAS(SDRAM_nRAS),
|
||||
.SDRAM_nCAS(SDRAM_nCAS),
|
||||
.SDRAM_CLK(SDRAM_CLK),
|
||||
.SDRAM_CKE(SDRAM_CKE),
|
||||
|
||||
// system interface
|
||||
.clk ( clk_ram ),
|
||||
.init (0), //~clock_locked),
|
||||
|
||||
// ROM + Cart RAM
|
||||
.ch0_addr ( sdram_addr ),
|
||||
.ch0_wr ( sdram_we ),
|
||||
.ch0_din ( sdram_di ),
|
||||
.ch0_rd ( sdram_oe ),
|
||||
.ch0_dout ( sdram_do ),
|
||||
.ch0_word ( cart_download | savestate_ovr),
|
||||
.ch0_busy ( sdram_busy),
|
||||
|
||||
// HPS Cart RAM Save/Load
|
||||
.ch1_addr ( { CARTRAM_BANK, 6'd0, save_addr, 1'b0 } ),
|
||||
.ch1_wr ( save_wr ),
|
||||
.ch1_din ( bk_data ),
|
||||
.ch1_rd ( save_rd ),
|
||||
.ch1_dout ( save_dout ),
|
||||
.ch1_word ( 1'b1 ),
|
||||
.ch1_busy ( save_busy ),
|
||||
|
||||
.ch2_addr ( 0 ),
|
||||
.ch2_wr ( 0 ),
|
||||
.ch2_din ( 0 ),
|
||||
.ch2_rd ( 0 ),
|
||||
.ch2_dout ( ),
|
||||
.ch2_busy ( ),
|
||||
|
||||
.refresh ( sdram_pause_refresh )
|
||||
);
|
||||
|
||||
wire dn_write;
|
||||
wire cart_ready;
|
||||
wire cram_rd, cram_wr;
|
||||
wire [7:0] rom_do = (mbc_addr[0]) ? sdram_do[15:8] : sdram_do[7:0];
|
||||
wire cram_rd, cram_wr, cram_bram_wr, is_cram_addr;
|
||||
wire [16:0] cram_addr;
|
||||
wire [15:0] Savestate_CRAM_Q;
|
||||
|
||||
wire [7:0] ram_mask_file, cart_ram_size;
|
||||
wire isGBC_game, isSGB_game;
|
||||
wire cart_has_save;
|
||||
wire cart_has_save, bram_save;
|
||||
wire [31:0] RTC_timestampOut;
|
||||
wire [47:0] RTC_savedtimeOut;
|
||||
wire RTC_inuse;
|
||||
@@ -552,14 +587,18 @@ cart_top cart (
|
||||
.dn_write ( dn_write ),
|
||||
.cart_ready ( cart_ready ),
|
||||
|
||||
.is_cram_addr( is_cram_addr),
|
||||
.cram_rd ( cram_rd ),
|
||||
.cram_wr ( cram_wr ),
|
||||
.cram_bram_wr( cram_bram_wr ),
|
||||
.cram_addr ( cram_addr ),
|
||||
|
||||
.cart_download ( cart_download ),
|
||||
|
||||
.ram_mask_file ( ram_mask_file ),
|
||||
.ram_size ( cart_ram_size ),
|
||||
.has_save ( cart_has_save ),
|
||||
.bram_save ( bram_save ),
|
||||
|
||||
.isGBC_game ( isGBC_game ),
|
||||
.isSGB_game ( isSGB_game ),
|
||||
@@ -577,7 +616,7 @@ cart_top cart (
|
||||
.bk_q ( bk_q ),
|
||||
.img_size ( img_size ),
|
||||
|
||||
.rom_di ( rom_do ),
|
||||
.rom_di ( sdram_do[7:0] ),
|
||||
|
||||
.joystick_analog_0 ( joystick_analog_0 ),
|
||||
|
||||
@@ -593,12 +632,12 @@ cart_top cart (
|
||||
.SaveStateExt_rst ( SaveStateBus_rst ),
|
||||
.SaveStateExt_Dout( SaveStateBus_Dout ),
|
||||
.savestate_load ( savestate_load ),
|
||||
.sleep_savestate ( sleep_savestate ),
|
||||
.savestate_ovr ( savestate_ovr ),
|
||||
|
||||
.Savestate_CRAMAddr ( Savestate_CRAMAddr ),
|
||||
.Savestate_CRAMRWrEn ( Savestate_CRAMRWrEn ),
|
||||
.Savestate_CRAMWriteData( Savestate_CRAMWriteData ),
|
||||
.Savestate_CRAMReadData ( Savestate_CRAMReadData ),
|
||||
.Savestate_CRAM_Q ( Savestate_CRAM_Q ),
|
||||
|
||||
.rumbling (rumbling)
|
||||
);
|
||||
@@ -672,6 +711,8 @@ gb gb (
|
||||
|
||||
.nCS ( nCS ),
|
||||
|
||||
.sdram_rd ( sdram_rd ),
|
||||
|
||||
.boot_gba_en ( boot_gba_available && status[37] ),
|
||||
.fast_boot_en ( fastboot_available && status[42] ),
|
||||
|
||||
@@ -719,6 +760,7 @@ gb gb (
|
||||
.load_state (ss_load),
|
||||
.savestate_number(ss_slot),
|
||||
.sleep_savestate (sleep_savestate),
|
||||
.savestate_ovr (savestate_ovr),
|
||||
|
||||
.SaveStateExt_Din (SaveStateBus_Din),
|
||||
.SaveStateExt_Adr (SaveStateBus_Adr),
|
||||
@@ -728,6 +770,7 @@ gb gb (
|
||||
.SaveStateExt_load(savestate_load),
|
||||
|
||||
.Savestate_CRAMAddr (Savestate_CRAMAddr),
|
||||
.Savestate_CRAMRdEn (Savestate_CRAMRdEn),
|
||||
.Savestate_CRAMRWrEn (Savestate_CRAMRWrEn),
|
||||
.Savestate_CRAMWriteData(Savestate_CRAMWriteData),
|
||||
.Savestate_CRAMReadData (Savestate_CRAMReadData),
|
||||
@@ -740,6 +783,8 @@ gb gb (
|
||||
.SAVE_out_be(ss_be),
|
||||
.SAVE_out_done(ss_ack), // should be one cycle high when write is done or read value is valid
|
||||
|
||||
.savestate_sdram_busy(sdram_busy),
|
||||
|
||||
.rewind_on(status[27]),
|
||||
.rewind_active(status[27] & joystick_0[10])
|
||||
);
|
||||
@@ -775,7 +820,7 @@ lcd lcd
|
||||
.inv ( status[12] ),
|
||||
.double_buffer( status[5]),
|
||||
.frame_blend( status[16] ),
|
||||
.originalcolors( status[30] ),
|
||||
.originalcolors( gbc_raw_colors ),
|
||||
.analog_wide ( status[34] ),
|
||||
|
||||
// Palettes
|
||||
@@ -784,6 +829,11 @@ lcd lcd
|
||||
.pal3 (palette[79:56]),
|
||||
.pal4 (palette[55:32]),
|
||||
|
||||
.lut_download (cgb_lut_download),
|
||||
.ioctl_wr (ioctl_wr),
|
||||
.ioctl_addr (ioctl_addr),
|
||||
.ioctl_dout (ioctl_dout),
|
||||
|
||||
.sgb_border_pix ( sgb_border_pix),
|
||||
.sgb_pal_en ( sgb_pal_en ),
|
||||
.sgb_en ( sgb_border_en ),
|
||||
@@ -901,9 +951,8 @@ wire ce_cpu, ce_cpu_n, ce_cpu2x;
|
||||
wire cart_act = cart_wr | cart_rd;
|
||||
|
||||
wire fastforward = joystick_0[8] && !ioctl_download && !OSD_STATUS;
|
||||
wire ff_on;
|
||||
|
||||
wire sleep_savestate;
|
||||
wire sleep_savestate, savestate_ovr;
|
||||
|
||||
reg paused;
|
||||
always_ff @(posedge clk_sys) begin
|
||||
@@ -916,12 +965,13 @@ speedcontrol speedcontrol
|
||||
.pause (paused),
|
||||
.speedup (fast_forward),
|
||||
.cart_act (cart_act),
|
||||
.save_act (bk_state),
|
||||
.DMA_on (DMA_on),
|
||||
.ce (ce_cpu),
|
||||
.ce_n (ce_cpu_n),
|
||||
.ce_2x (ce_cpu2x),
|
||||
.refresh (sdram_refresh_force),
|
||||
.ff_on (ff_on)
|
||||
.refresh (sdram_pause_refresh),
|
||||
.ff_on ()
|
||||
);
|
||||
|
||||
///////////////////////////// Fast Forward Latch /////////////////////////////////
|
||||
@@ -966,9 +1016,10 @@ wire [63:0] SaveStateBus_Dout;
|
||||
wire savestate_load;
|
||||
|
||||
wire [19:0] Savestate_CRAMAddr;
|
||||
wire Savestate_CRAMRdEn;
|
||||
wire Savestate_CRAMRWrEn;
|
||||
wire [7:0] Savestate_CRAMWriteData;
|
||||
wire [7:0] Savestate_CRAMReadData;
|
||||
wire [15:0] Savestate_CRAMWriteData;
|
||||
wire [15:0] Savestate_CRAMReadData;
|
||||
|
||||
wire [63:0] ss_dout, ss_din;
|
||||
wire [27:2] ss_addr;
|
||||
@@ -1121,18 +1172,7 @@ assign USER_OUT[0] = (serial_ena & sc_int_clock_out) ? ser_clk_out : 1'b1;
|
||||
|
||||
///////////////////////// BRAM SAVE/LOAD /////////////////////////////
|
||||
|
||||
wire [16:0] bk_addr = {sd_lba[7:0],sd_buff_addr};
|
||||
wire bk_wr = (sd_lba[7:0] > ram_mask_file) ? 1'b0 : sd_buff_wr & sd_ack; // only restore data amount of saveram, don't save on RTC data
|
||||
wire bk_rtc_wr = (sd_lba[7:0] > ram_mask_file) & sd_buff_wr & sd_ack;
|
||||
wire [15:0] bk_data = sd_buff_dout;
|
||||
wire [15:0] bk_q;
|
||||
assign sd_buff_din = (sd_lba[7:0] <= ram_mask_file) ? bk_q : // normal saveram data or RTC data
|
||||
(sd_buff_addr == 8'd0) ? RTC_timestampOut[15:0] :
|
||||
(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;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1156,7 +1196,7 @@ always @(posedge clk_sys) begin
|
||||
else if (bk_state)
|
||||
new_load <= 1'b0;
|
||||
|
||||
if (cram_wr & ~OSD_STATUS & sav_supported)
|
||||
if ((cram_wr | cram_bram_wr) & ~OSD_STATUS & sav_supported)
|
||||
sav_pending <= 1'b1;
|
||||
else if (bk_state)
|
||||
sav_pending <= 1'b0;
|
||||
@@ -1210,6 +1250,48 @@ always @(posedge clk_sys) begin
|
||||
end
|
||||
end
|
||||
|
||||
wire [15:0] bk_addr = {sd_lba[7:0],sd_buff_addr};
|
||||
wire bk_addr_end = (sd_lba[7:0] > ram_mask_file);
|
||||
wire bk_wr = bk_addr_end ? 1'b0 : sd_buff_wr & sd_ack; // only restore data amount of saveram, don't save on RTC data
|
||||
wire bk_rtc_wr = bk_addr_end & sd_buff_wr & sd_ack;
|
||||
wire [15:0] bk_data = sd_buff_dout;
|
||||
wire [15:0] bk_q;
|
||||
assign sd_buff_din = (sd_lba[7:0] <= ram_mask_file) ? ( bram_save ? bk_q : save_dout ) : // normal saveram data or RTC data
|
||||
(sd_buff_addr == 8'd0) ? RTC_timestampOut[15:0] :
|
||||
(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;
|
||||
|
||||
|
||||
wire save_busy;
|
||||
reg save_rd, save_wr;
|
||||
reg save_wait;
|
||||
reg [15:0] save_addr;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
|
||||
if(~save_busy & ~save_rd & ~save_wr) save_wait <= 0;
|
||||
|
||||
if(~bk_state) begin
|
||||
save_addr <= '1;
|
||||
save_wait <= 0;
|
||||
end else if(sd_ack & ~save_busy) begin
|
||||
if( ~bk_loading & ~bk_addr_end & (save_addr != bk_addr) ) begin
|
||||
save_rd <= 1;
|
||||
save_addr <= bk_addr;
|
||||
save_wait <= 1;
|
||||
end
|
||||
if( bk_loading & ~bk_addr_end & sd_buff_wr ) begin
|
||||
save_wr <= 1;
|
||||
save_addr <= bk_addr;
|
||||
save_wait <= 1;
|
||||
end
|
||||
end
|
||||
if(~bk_state | save_busy) {save_rd, save_wr} <= 0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -100,6 +100,7 @@ entity GBse is
|
||||
A : out std_logic_vector(15 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
phi_early : out std_logic; -- for SDRAM
|
||||
isGBC : in std_logic; -- Gameboy Color
|
||||
-- savestates
|
||||
SaveStateBus_Din : in std_logic_vector(BUS_buswidth-1 downto 0);
|
||||
@@ -147,6 +148,8 @@ begin
|
||||
SaveStateBus_Dout <= wired_or;
|
||||
end process;
|
||||
|
||||
phi_early <= not TState(1) and not TState(0);
|
||||
|
||||
u0 : T80
|
||||
generic map
|
||||
(
|
||||
|
||||
71
rtl/cart.v
71
rtl/cart.v
@@ -24,14 +24,18 @@ module cart_top (
|
||||
output reg dn_write,
|
||||
output cart_ready,
|
||||
|
||||
output is_cram_addr,
|
||||
output cram_rd,
|
||||
output cram_wr,
|
||||
output cram_bram_wr,
|
||||
output [16:0] cram_addr,
|
||||
|
||||
input cart_download,
|
||||
|
||||
output [7:0] ram_mask_file,
|
||||
output [7:0] ram_size,
|
||||
output has_save,
|
||||
output bram_save,
|
||||
|
||||
output isGBC_game,
|
||||
output isSGB_game,
|
||||
@@ -65,12 +69,12 @@ module cart_top (
|
||||
input SaveStateExt_rst,
|
||||
output [63:0] SaveStateExt_Dout,
|
||||
input savestate_load,
|
||||
input sleep_savestate,
|
||||
input savestate_ovr,
|
||||
|
||||
input [19:0] Savestate_CRAMAddr,
|
||||
input Savestate_CRAMRWrEn,
|
||||
input [7:0] Savestate_CRAMWriteData,
|
||||
output [7:0] Savestate_CRAMReadData,
|
||||
input [15:0] Savestate_CRAMWriteData,
|
||||
output [15:0] Savestate_CRAM_Q,
|
||||
output rumbling
|
||||
);
|
||||
///////////////////////////////////////////////////
|
||||
@@ -98,7 +102,7 @@ eReg_SavestateV #(0, 37, 63, 0, 64'h0000000000000000) iREG_SAVESTATE_Ext2 (clk_s
|
||||
assign SaveStateExt_Dout = SaveStateBus_Dout_or[0] | SaveStateBus_Dout_or[1];
|
||||
|
||||
wire [7:0] rom_do;
|
||||
wire [7:0] cram_do;
|
||||
wire [7:0] mbc_cram_do;
|
||||
wire [16:0] mbc_cram_addr;
|
||||
wire mbc_ram_enable, mbc_battery;
|
||||
wire mbc_cram_wr;
|
||||
@@ -174,8 +178,8 @@ mappers mappers (
|
||||
.nCS ( nCS ),
|
||||
|
||||
.cram_rd ( cram_rd ),
|
||||
.cram_di ( cram_q ),
|
||||
.cram_do ( cram_do ),
|
||||
.cram_di ( bram_save ? cram_q : rom_di ),
|
||||
.cram_do ( mbc_cram_do ),
|
||||
.cram_addr ( mbc_cram_addr ),
|
||||
|
||||
.cram_wr_do ( mbc_cram_wr_do ),
|
||||
@@ -388,32 +392,30 @@ reg [7:0] cart_do_r;
|
||||
always @* begin
|
||||
if (~cart_ready)
|
||||
cart_do_r = 8'h00;
|
||||
else if (cram_rd)
|
||||
cart_do_r = cram_do;
|
||||
else if (is_cram_addr)
|
||||
cart_do_r = mbc_cram_do;
|
||||
else
|
||||
cart_do_r = rom_do;
|
||||
end
|
||||
|
||||
assign cart_do = cart_do_r;
|
||||
|
||||
reg read_low = 0;
|
||||
always @(posedge clk_sys) begin
|
||||
read_low <= cram_addr[0];
|
||||
end
|
||||
|
||||
assign Savestate_CRAMReadData = read_low ? cram_q_h : cram_q_l;
|
||||
|
||||
wire [7:0] cram_q_h, cram_q_l;
|
||||
wire [7:0] cram_q = cram_addr[0] ? cram_q_h : cram_q_l;
|
||||
wire [7:0] cram_q_h;
|
||||
wire [7:0] cram_q_l;
|
||||
|
||||
wire is_cram_addr = ~nCS & ~cart_addr[14];
|
||||
|
||||
assign is_cram_addr = ~nCS & ~cart_addr[14];
|
||||
assign cram_rd = cart_rd & is_cram_addr;
|
||||
assign cram_wr = sleep_savestate ? Savestate_CRAMRWrEn : mbc_cram_wr || (cart_wr & is_cram_addr & mbc_ram_enable);
|
||||
assign cram_wr = savestate_ovr ? Savestate_CRAMRWrEn : (cart_wr & is_cram_addr & mbc_ram_enable);
|
||||
assign cram_bram_wr = savestate_ovr ? (Savestate_CRAMRWrEn & ~|Savestate_CRAMAddr[16:8]) : mbc_cram_wr;
|
||||
|
||||
wire [16:0] cram_addr = sleep_savestate ? Savestate_CRAMAddr[16:0] : mbc_cram_addr;
|
||||
wire [7:0] cram_di = sleep_savestate ? Savestate_CRAMWriteData : mbc_cram_wr ? mbc_cram_wr_do : cart_di;
|
||||
assign cram_addr = savestate_ovr ? Savestate_CRAMAddr[16:0] : mbc_cram_addr;
|
||||
|
||||
wire [7:0] cram_di_l = savestate_ovr ? Savestate_CRAMWriteData[ 7:0] : mbc_cram_wr_do;
|
||||
wire [7:0] cram_di_h = savestate_ovr ? Savestate_CRAMWriteData[15:8] : mbc_cram_wr_do;
|
||||
|
||||
assign Savestate_CRAM_Q = { cram_q_h, cram_q_l };
|
||||
|
||||
assign bram_save = mbc7 | tama;
|
||||
|
||||
// RAM size
|
||||
assign ram_mask_file = // 0 - no ram
|
||||
@@ -426,31 +428,30 @@ assign ram_mask_file = // 0 - no ram
|
||||
|
||||
assign has_save = mbc_battery && (|ram_size || mbc2 || mbc7 || tama);
|
||||
|
||||
// Up to 8kb * 16banks of Cart Ram (128kb)
|
||||
dpram #(16) cram_l (
|
||||
dpram #(7) cram_bram_l (
|
||||
.clock_a (clk_sys),
|
||||
.address_a (cram_addr[16:1]),
|
||||
.wren_a (cram_wr & ~cram_addr[0]),
|
||||
.data_a (cram_di),
|
||||
.address_a (cram_addr[7:1]),
|
||||
.wren_a (cram_bram_wr & (~cram_addr[0] | savestate_ovr)),
|
||||
.data_a (cram_di_l),
|
||||
.q_a (cram_q_l),
|
||||
|
||||
.clock_b (clk_sys),
|
||||
.address_b (bk_addr[15:0]),
|
||||
.wren_b (bk_wr),
|
||||
.address_b (bk_addr[6:0]),
|
||||
.wren_b (bk_wr & ~|bk_addr[16:7]),
|
||||
.data_b (bk_data[7:0]),
|
||||
.q_b (bk_q[7:0])
|
||||
);
|
||||
|
||||
dpram #(16) cram_h (
|
||||
dpram #(7) cram_bram_h (
|
||||
.clock_a (clk_sys),
|
||||
.address_a (cram_addr[16:1]),
|
||||
.wren_a (cram_wr & cram_addr[0]),
|
||||
.data_a (cram_di),
|
||||
.address_a (cram_addr[7:1]),
|
||||
.wren_a (cram_bram_wr & (cram_addr[0] | savestate_ovr)),
|
||||
.data_a (cram_di_h),
|
||||
.q_a (cram_q_h),
|
||||
|
||||
.clock_b (clk_sys),
|
||||
.address_b (bk_addr[15:0]),
|
||||
.wren_b (bk_wr),
|
||||
.address_b (bk_addr[6:0]),
|
||||
.wren_b (bk_wr & ~|bk_addr[16:7]),
|
||||
.data_b (bk_data[15:8]),
|
||||
.q_b (bk_q[15:8])
|
||||
);
|
||||
|
||||
@@ -7,7 +7,8 @@ USE altera_mf.altera_mf_components.all;
|
||||
ENTITY dpram IS
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8
|
||||
data_width : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
@@ -50,6 +51,7 @@ BEGIN
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width,
|
||||
widthad_b => addr_width,
|
||||
width_a => data_width,
|
||||
|
||||
42
rtl/gb.v
42
rtl/gb.v
@@ -46,6 +46,8 @@ module gb (
|
||||
// WRAM or Cart RAM CS
|
||||
output nCS,
|
||||
|
||||
output sdram_rd,
|
||||
|
||||
input cgb_boot_download,
|
||||
input dmg_boot_download,
|
||||
input sgb_boot_download,
|
||||
@@ -98,6 +100,7 @@ module gb (
|
||||
input load_state,
|
||||
input [1:0] savestate_number,
|
||||
output sleep_savestate,
|
||||
output savestate_ovr,
|
||||
|
||||
output [63:0] SaveStateExt_Din,
|
||||
output [9:0] SaveStateExt_Adr,
|
||||
@@ -107,9 +110,10 @@ module gb (
|
||||
output SaveStateExt_load,
|
||||
|
||||
output [19:0] Savestate_CRAMAddr,
|
||||
output Savestate_CRAMRdEn,
|
||||
output Savestate_CRAMRWrEn,
|
||||
output [7:0] Savestate_CRAMWriteData,
|
||||
input [7:0] Savestate_CRAMReadData,
|
||||
output [15:0] Savestate_CRAMWriteData,
|
||||
input [15:0] Savestate_CRAMReadData,
|
||||
|
||||
output [63:0] SAVE_out_Din, // data read from savestate
|
||||
input [63:0] SAVE_out_Dout, // data written to savestate
|
||||
@@ -119,6 +123,8 @@ module gb (
|
||||
output [7:0] SAVE_out_be,
|
||||
input SAVE_out_done, // should be one cycle high when write is done or read value is valid
|
||||
|
||||
input savestate_sdram_busy,
|
||||
|
||||
input rewind_on,
|
||||
input rewind_active
|
||||
);
|
||||
@@ -128,9 +134,10 @@ wire [63:0] SaveStateBus_Din;
|
||||
wire [9:0] SaveStateBus_Adr;
|
||||
wire SaveStateBus_wren, SaveStateBus_rst;
|
||||
|
||||
wire [7:0] Savestate_RAMWriteData;
|
||||
wire [15:0] Savestate_RAMWriteData;
|
||||
wire [7:0] Savestate_RAMReadData_WRAM, Savestate_RAMReadData_VRAM, Savestate_RAMReadData_ORAM, Savestate_RAMReadData_ZRAM;
|
||||
wire [19:0] Savestate_RAMAddr;
|
||||
wire [4:0] Savestate_RAMRdEn;
|
||||
wire [4:0] Savestate_RAMRWrEn;
|
||||
|
||||
localparam SAVESTATE_MODULES = 8;
|
||||
@@ -239,6 +246,7 @@ reg vram_bank; //0-1 FF4F - VBK
|
||||
|
||||
wire [7:0] hdma_do;
|
||||
wire hdma_active;
|
||||
wire hdma_rd_clk;
|
||||
|
||||
reg cpu_speed; // - 0 Normal mode (4MHz) - 1 Double Speed Mode (8MHz)
|
||||
reg prepare_switch; // set to 1 to toggle speed
|
||||
@@ -297,6 +305,7 @@ wire cpu_rd_n;
|
||||
wire cpu_iorq_n;
|
||||
wire cpu_m1_n;
|
||||
wire cpu_mreq_n;
|
||||
wire cpu_phi_early;
|
||||
|
||||
wire clk = clk_sys & ce;
|
||||
|
||||
@@ -307,6 +316,8 @@ wire clk_cpu = clk_sys & ce_cpu;
|
||||
wire hdma_cpu_stop = (isGBC & hdma_active & cpu_rd_n & cpu_wr_n);
|
||||
wire cpu_clken = ~hdma_cpu_stop & ce_cpu;
|
||||
|
||||
assign sdram_rd = ~cpu_phi_early | hdma_rd_clk; // For SDRAM read & refresh
|
||||
|
||||
reg reset_r = 1;
|
||||
wire reset_ss;
|
||||
|
||||
@@ -366,6 +377,7 @@ GBse cpu (
|
||||
.DI ( genie_ovr ? genie_data : cpu_di),
|
||||
.DO ( cpu_do ),
|
||||
.STOP ( cpu_stop ),
|
||||
.phi_early ( cpu_phi_early ),
|
||||
.isGBC ( isGBC ),
|
||||
// savestates
|
||||
.SaveStateBus_Din (SaveStateBus_Din ),
|
||||
@@ -733,7 +745,7 @@ video video (
|
||||
|
||||
.Savestate_OAMRAMAddr (Savestate_RAMAddr[7:0]),
|
||||
.Savestate_OAMRAMRWrEn (Savestate_RAMRWrEn[2]),
|
||||
.Savestate_OAMRAMWriteData (Savestate_RAMWriteData),
|
||||
.Savestate_OAMRAMWriteData (Savestate_RAMWriteData[7:0]),
|
||||
.Savestate_OAMRAMReadData (Savestate_RAMReadData_ORAM),
|
||||
|
||||
.SaveStateBus_Din (SaveStateBus_Din ),
|
||||
@@ -770,7 +782,7 @@ dpram #(13) vram0 (
|
||||
.clock_b (clk_sys),
|
||||
.address_b (Savestate_RAMAddr[12:0]),
|
||||
.wren_b (Savestate_RAMRWrEn[1] & !Savestate_RAMAddr[13]),
|
||||
.data_b (Savestate_RAMWriteData),
|
||||
.data_b (Savestate_RAMWriteData[7:0]),
|
||||
.q_b (Savestate_RAMReadData_VRAM0)
|
||||
);
|
||||
|
||||
@@ -785,7 +797,7 @@ dpram #(13) vram1 (
|
||||
.clock_b (clk_sys),
|
||||
.address_b (Savestate_RAMAddr[12:0]),
|
||||
.wren_b (Savestate_RAMRWrEn[1] & Savestate_RAMAddr[13]),
|
||||
.data_b (Savestate_RAMWriteData),
|
||||
.data_b (Savestate_RAMWriteData[7:0]),
|
||||
.q_b (Savestate_RAMReadData_VRAM1)
|
||||
);
|
||||
|
||||
@@ -826,6 +838,7 @@ hdma hdma(
|
||||
// dma connection
|
||||
.hdma_rd ( hdma_rd ),
|
||||
.hdma_active ( hdma_active ),
|
||||
.hdma_rd_clk ( hdma_rd_clk ),
|
||||
.hdma_source_addr ( hdma_source_addr ),
|
||||
.hdma_target_addr ( hdma_target_addr ),
|
||||
|
||||
@@ -853,7 +866,7 @@ dpram #(7) zpram (
|
||||
.clock_b (clk_sys),
|
||||
.address_b (Savestate_RAMAddr[6:0]),
|
||||
.wren_b (Savestate_RAMRWrEn[3]),
|
||||
.data_b (Savestate_RAMWriteData),
|
||||
.data_b (Savestate_RAMWriteData[7:0]),
|
||||
.q_b (Savestate_RAMReadData_ZRAM)
|
||||
);
|
||||
|
||||
@@ -888,7 +901,7 @@ dpram #(15) wram (
|
||||
.clock_b (clk_sys),
|
||||
.address_b (Savestate_RAMAddr[14:0]),
|
||||
.wren_b (Savestate_RAMRWrEn[0]),
|
||||
.data_b (Savestate_RAMWriteData),
|
||||
.data_b (Savestate_RAMWriteData[7:0]),
|
||||
.q_b (Savestate_RAMReadData_WRAM)
|
||||
);
|
||||
|
||||
@@ -1024,7 +1037,7 @@ assign ext_bus_a15 = ext_bus_i[15] | sel_boot_rom;
|
||||
assign ext_bus_addr = ext_bus_i[14:0];
|
||||
|
||||
assign ext_bus_rd = hdma_read_ext_bus | dma_read_ext_bus | (sel_ext_bus & ~cpu_rd_n);
|
||||
assign ext_bus_wr = (sel_ext_bus & ~cpu_wr_n_edge) & ~hdma_read_ext_bus & ~dma_read_ext_bus;
|
||||
assign ext_bus_wr = (sel_ext_bus & ~cpu_wr_n) & ~hdma_read_ext_bus & ~dma_read_ext_bus;
|
||||
|
||||
assign ext_bus_wram_sel = ~nCS & ext_bus_addr[14];
|
||||
assign ext_bus_cram_sel = ~nCS & ~ext_bus_addr[14];
|
||||
@@ -1056,6 +1069,7 @@ assign SaveStateExt_rst = SaveStateBus_rst;
|
||||
assign SaveStateExt_load = savestate_loaded;
|
||||
|
||||
assign Savestate_CRAMAddr = Savestate_RAMAddr;
|
||||
assign Savestate_CRAMRdEn = Savestate_RAMRdEn[4];
|
||||
assign Savestate_CRAMRWrEn = Savestate_RAMRWrEn[4];
|
||||
assign Savestate_CRAMWriteData = Savestate_RAMWriteData;
|
||||
|
||||
@@ -1064,6 +1078,7 @@ wire [63:0] SaveStateBus_Dout = SaveStateBus_wired_or[0] | SaveStateBus_wired_o
|
||||
SaveStateExt_Dout;
|
||||
|
||||
wire sleep_rewind, sleep_savestates;
|
||||
wire loading_savestate, saving_savestate;
|
||||
|
||||
gb_savestates gb_savestates (
|
||||
.clk (clk_sys),
|
||||
@@ -1088,12 +1103,15 @@ gb_savestates gb_savestates (
|
||||
.BUS_rst (SaveStateBus_rst),
|
||||
.BUS_Dout (SaveStateBus_Dout),
|
||||
|
||||
//.loading_savestate (loading_savestate),
|
||||
//.saving_savestate (saving_savestate),
|
||||
.loading_savestate (loading_savestate),
|
||||
.saving_savestate (saving_savestate),
|
||||
.sleep_savestate (sleep_savestates),
|
||||
.clock_ena_in (ce_2x),
|
||||
|
||||
.memory_busy (savestate_sdram_busy),
|
||||
|
||||
.Save_RAMAddr (Savestate_RAMAddr),
|
||||
.Save_RAMRdEn (Savestate_RAMRdEn),
|
||||
.Save_RAMWrEn (Savestate_RAMRWrEn),
|
||||
.Save_RAMWriteData (Savestate_RAMWriteData),
|
||||
.Save_RAMReadData_WRAM (Savestate_RAMReadData_WRAM),
|
||||
@@ -1132,6 +1150,6 @@ gb_statemanager #(58720256, 33554432) gb_statemanager (
|
||||
);
|
||||
|
||||
assign sleep_savestate = sleep_rewind | sleep_savestates;
|
||||
|
||||
assign savestate_ovr = loading_savestate | saving_savestate;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -33,15 +33,18 @@ entity gb_savestates is
|
||||
saving_savestate : out std_logic := '0';
|
||||
sleep_savestate : out std_logic := '0';
|
||||
clock_ena_in : in std_logic;
|
||||
|
||||
memory_busy : in std_logic;
|
||||
|
||||
Save_RAMAddr : buffer std_logic_vector(19 downto 0) := (others => '0');
|
||||
Save_RAMWrEn : out std_logic_vector(4 downto 0) := (others => '0');
|
||||
Save_RAMWriteData : out std_logic_vector(7 downto 0) := (others => '0');
|
||||
Save_RAMRdEn : buffer std_logic_vector(4 downto 0) := (others => '0');
|
||||
Save_RAMWrEn : buffer std_logic_vector(4 downto 0) := (others => '0');
|
||||
Save_RAMWriteData : out std_logic_vector(15 downto 0) := (others => '0');
|
||||
Save_RAMReadData_WRAM : in std_logic_vector(7 downto 0);
|
||||
Save_RAMReadData_VRAM : in std_logic_vector(7 downto 0);
|
||||
Save_RAMReadData_ORAM : in std_logic_vector(7 downto 0);
|
||||
Save_RAMReadData_ZRAM : in std_logic_vector(7 downto 0);
|
||||
Save_RAMReadData_CRAM : in std_logic_vector(7 downto 0);
|
||||
Save_RAMReadData_CRAM : in std_logic_vector(15 downto 0);
|
||||
|
||||
bus_out_Din : out std_logic_vector(63 downto 0) := (others => '0');
|
||||
bus_out_Dout : in std_logic_vector(63 downto 0);
|
||||
@@ -90,8 +93,10 @@ architecture arch of gb_savestates is
|
||||
LOADINTERNALS_READ,
|
||||
LOADINTERNALS_WRITE,
|
||||
LOADMEMORY_NEXT,
|
||||
LOADMEMORY_NEXT_WAIT,
|
||||
LOADMEMORY_READ,
|
||||
LOADMEMORY_WRITE
|
||||
LOADMEMORY_WRITE,
|
||||
LOAD_FINISH
|
||||
);
|
||||
signal state : tstate := IDLE;
|
||||
|
||||
@@ -101,11 +106,17 @@ architecture arch of gb_savestates is
|
||||
signal settle : integer range 0 to SETTLECOUNT := 0;
|
||||
|
||||
signal bytecounter : integer range 0 to 7 := 0;
|
||||
|
||||
signal Save_RAMReadData : std_logic_vector(7 downto 0);
|
||||
signal Save_RAMReadDataH : std_logic_vector(7 downto 0);
|
||||
signal RAMAddrNext : std_logic_vector(19 downto 0) := (others => '0');
|
||||
|
||||
signal header_amount : unsigned(31 downto 0) := (others => '0');
|
||||
|
||||
signal memory_is_slow : std_logic;
|
||||
signal memory_is_word : std_logic;
|
||||
signal memory_ready : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
savestate_busy <= '0' when state = IDLE else '1';
|
||||
@@ -114,13 +125,20 @@ begin
|
||||
Save_RAMReadData_VRAM when savetype_counter = 1 else
|
||||
Save_RAMReadData_ORAM when savetype_counter = 2 else
|
||||
Save_RAMReadData_ZRAM when savetype_counter = 3 else
|
||||
Save_RAMReadData_CRAM;
|
||||
Save_RAMReadData_CRAM(7 downto 0);
|
||||
|
||||
Save_RAMReadDataH <= Save_RAMReadData_CRAM(15 downto 8);
|
||||
|
||||
memory_is_slow <= '1' when savetype_counter = 4 else '0';
|
||||
memory_is_word <= '1' when savetype_counter = 4 else '0';
|
||||
memory_ready <= '1' when memory_is_slow = '0'
|
||||
or (memory_busy = '0' and Save_RAMRdEn = "00000" and Save_RAMWrEn = "00000")
|
||||
else '0';
|
||||
|
||||
process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
|
||||
Save_RAMWrEn <= (others => '0');
|
||||
bus_out_ena <= '0';
|
||||
BUS_wren <= '0';
|
||||
BUS_rst <= '0';
|
||||
@@ -136,6 +154,11 @@ begin
|
||||
when x"03" => savetypes(4) <= 32768; -- 32 KByte
|
||||
when others => savetypes(4) <= 131072; -- 128 KByte
|
||||
end case;
|
||||
|
||||
if (memory_is_slow = '0' or memory_busy = '1') then
|
||||
Save_RAMRdEn <= (others => '0');
|
||||
Save_RAMWrEn <= (others => '0');
|
||||
end if;
|
||||
|
||||
case state is
|
||||
|
||||
@@ -198,11 +221,16 @@ begin
|
||||
|
||||
when SAVEMEMORY_NEXT =>
|
||||
if (savetype_counter < SAVETYPESCOUNT) then
|
||||
state <= SAVEMEMORY_FIRST;
|
||||
if (memory_is_slow = '1') then
|
||||
state <= SAVEMEMORY_READ;
|
||||
else
|
||||
state <= SAVEMEMORY_FIRST;
|
||||
end if;
|
||||
bytecounter <= 0;
|
||||
count <= 8;
|
||||
maxcount <= savetypes(savetype_counter);
|
||||
Save_RAMAddr <= (others => '0');
|
||||
Save_RAMRdEn(savetype_counter) <= '1';
|
||||
else
|
||||
state <= SAVESIZEAMOUNT;
|
||||
bus_out_Adr <= std_logic_vector(to_unsigned(savestate_address, 26));
|
||||
@@ -215,18 +243,35 @@ begin
|
||||
|
||||
when SAVEMEMORY_FIRST =>
|
||||
state <= SAVEMEMORY_READ;
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 1);
|
||||
if (memory_is_word = '1') then
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 2);
|
||||
else
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 1);
|
||||
end if;
|
||||
Save_RAMRdEn(savetype_counter) <= '1';
|
||||
|
||||
when SAVEMEMORY_READ =>
|
||||
bus_out_Din(bytecounter * 8 + 7 downto bytecounter * 8) <= Save_RAMReadData;
|
||||
if (bytecounter < 7) then
|
||||
bytecounter <= bytecounter + 1;
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 1);
|
||||
else
|
||||
state <= SAVEMEMORY_WRITE;
|
||||
bus_out_ena <= '1';
|
||||
if (memory_ready = '1') then
|
||||
if (memory_is_word = '1') then
|
||||
bus_out_Din(bytecounter * 8 + 15 downto bytecounter * 8) <= Save_RAMReadDataH & Save_RAMReadData;
|
||||
else
|
||||
bus_out_Din(bytecounter * 8 + 7 downto bytecounter * 8) <= Save_RAMReadData;
|
||||
end if;
|
||||
|
||||
if (memory_is_word = '1' and bytecounter < 6) then
|
||||
bytecounter <= bytecounter + 2;
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 2);
|
||||
Save_RAMRdEn(savetype_counter) <= '1';
|
||||
elsif (memory_is_word = '0' and bytecounter < 7) then
|
||||
bytecounter <= bytecounter + 1;
|
||||
Save_RAMAddr <= std_logic_vector(unsigned(Save_RAMAddr) + 1);
|
||||
Save_RAMRdEn(savetype_counter) <= '1';
|
||||
else
|
||||
state <= SAVEMEMORY_WRITE;
|
||||
bus_out_ena <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
when SAVEMEMORY_WRITE =>
|
||||
if (bus_out_done = '1') then
|
||||
bus_out_Adr <= std_logic_vector(unsigned(bus_out_Adr) + 2);
|
||||
@@ -309,10 +354,8 @@ begin
|
||||
bytecounter <= 0;
|
||||
bus_out_ena <= '1';
|
||||
else
|
||||
state <= IDLE;
|
||||
state <= LOAD_FINISH;
|
||||
reset_out <= '1';
|
||||
loading_savestate <= '0';
|
||||
sleep_savestate <= '0';
|
||||
load_done <= '1';
|
||||
end if;
|
||||
|
||||
@@ -322,25 +365,45 @@ begin
|
||||
end if;
|
||||
|
||||
when LOADMEMORY_WRITE =>
|
||||
RAMAddrNext <= std_logic_vector(unsigned(RAMAddrNext) + 1);
|
||||
Save_RAMAddr <= RAMAddrNext;
|
||||
Save_RAMWrEn(savetype_counter) <= '1';
|
||||
Save_RAMWriteData <= bus_out_Dout(bytecounter * 8 + 7 downto bytecounter * 8);
|
||||
if (bytecounter < 7) then
|
||||
bytecounter <= bytecounter + 1;
|
||||
else
|
||||
bus_out_Adr <= std_logic_vector(unsigned(bus_out_Adr) + 2);
|
||||
if (count < maxcount) then
|
||||
state <= LOADMEMORY_READ;
|
||||
count <= count + 8;
|
||||
bytecounter <= 0;
|
||||
bus_out_ena <= '1';
|
||||
else
|
||||
savetype_counter <= savetype_counter + 1;
|
||||
state <= LOADMEMORY_NEXT;
|
||||
if (memory_ready = '1') then
|
||||
if (memory_is_word = '1') then
|
||||
RAMAddrNext <= std_logic_vector(unsigned(RAMAddrNext) + 2);
|
||||
else
|
||||
RAMAddrNext <= std_logic_vector(unsigned(RAMAddrNext) + 1);
|
||||
end if;
|
||||
Save_RAMAddr <= RAMAddrNext;
|
||||
Save_RAMWrEn(savetype_counter) <= '1';
|
||||
Save_RAMWriteData( 7 downto 0) <= bus_out_Dout(bytecounter * 8 + 7 downto bytecounter * 8);
|
||||
Save_RAMWriteData(15 downto 8) <= bus_out_Dout(bytecounter * 8 + 15 downto bytecounter * 8 + 8);
|
||||
|
||||
if (memory_is_word = '1' and bytecounter < 6) then
|
||||
bytecounter <= bytecounter + 2;
|
||||
elsif (memory_is_word = '0' and bytecounter < 7) then
|
||||
bytecounter <= bytecounter + 1;
|
||||
else
|
||||
bus_out_Adr <= std_logic_vector(unsigned(bus_out_Adr) + 2);
|
||||
if (count < maxcount) then
|
||||
state <= LOADMEMORY_READ;
|
||||
count <= count + 8;
|
||||
bytecounter <= 0;
|
||||
bus_out_ena <= '1';
|
||||
else
|
||||
state <= LOADMEMORY_NEXT_WAIT;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
when LOADMEMORY_NEXT_WAIT =>
|
||||
if (memory_ready = '1') then
|
||||
savetype_counter <= savetype_counter + 1;
|
||||
state <= LOADMEMORY_NEXT;
|
||||
end if;
|
||||
|
||||
when LOAD_FINISH =>
|
||||
state <= IDLE;
|
||||
loading_savestate <= '0';
|
||||
sleep_savestate <= '0';
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
|
||||
@@ -16,6 +16,7 @@ module hdma(
|
||||
// dma connection
|
||||
output reg hdma_rd,
|
||||
output reg hdma_active,
|
||||
output hdma_rd_clk,
|
||||
output [15:0] hdma_source_addr,
|
||||
output [15:0] hdma_target_addr,
|
||||
|
||||
@@ -53,6 +54,7 @@ wire [1:0] byte_cycles = speed ? 2'd3 : 2'd1;
|
||||
reg [1:0] hdma_cnt;
|
||||
|
||||
//assign hdma_rd = hdma_active;
|
||||
assign hdma_rd_clk = hdma_rd & (hdma_cnt != byte_cycles);
|
||||
assign hdma_source_addr = { hdma_source, byte_cnt };
|
||||
assign hdma_target_addr = { hdma_target, byte_cnt };
|
||||
|
||||
|
||||
83
rtl/lcd.v
83
rtl/lcd.v
@@ -23,6 +23,11 @@ module lcd
|
||||
input [23:0] pal3,
|
||||
input [23:0] pal4,
|
||||
|
||||
input lut_download,
|
||||
input ioctl_wr,
|
||||
input [15:0] ioctl_addr,
|
||||
input [15:0] ioctl_dout,
|
||||
|
||||
input [15:0] sgb_border_pix,
|
||||
input sgb_pal_en,
|
||||
input sgb_en,
|
||||
@@ -301,38 +306,68 @@ function [7:0] blend;
|
||||
end
|
||||
endfunction
|
||||
|
||||
reg [3:0] color_lut_sr;
|
||||
wire [7:0] color_lut_dout;
|
||||
// Color LUT 16bit to 24bit writes
|
||||
reg [23:0] color_lut_data;
|
||||
reg [7:0] color_lut_temp;
|
||||
reg [1:0] color_cnt;
|
||||
reg [14:0] color_lut_wr_addr;
|
||||
reg color_lut_wr, prev_color_lut_wr;
|
||||
reg prev_lut_download;
|
||||
always@(posedge clk_sys) begin
|
||||
prev_lut_download <= lut_download;
|
||||
|
||||
wire [9:0] color_lut_addr =
|
||||
color_lut_sr[0] ? { r5, r5 } : // red only
|
||||
color_lut_sr[1] ? { b5, g5 } : // mixed blue + green
|
||||
{ b5, b5 }; // blue only
|
||||
if (~prev_lut_download & lut_download) begin
|
||||
color_cnt <= 2'd0;
|
||||
color_lut_wr_addr <= 15'd0;
|
||||
end
|
||||
|
||||
// Color LUT for mix of 2 colors with 2 stage gamma
|
||||
dpram_dif #(10,8,10,8,"lcd_color_lut.mif") lcd_color_lut (
|
||||
.clock (clk_vid),
|
||||
prev_color_lut_wr <= color_lut_wr;
|
||||
if (prev_color_lut_wr & ~color_lut_wr) begin
|
||||
color_lut_wr_addr <= color_lut_wr_addr + 1'b1;
|
||||
end
|
||||
|
||||
.address_a (color_lut_addr),
|
||||
.q_a (color_lut_dout)
|
||||
);
|
||||
|
||||
|
||||
reg [7:0] r_lut, g_lut, b_lut;
|
||||
always@(posedge clk_vid) begin
|
||||
color_lut_sr <= { color_lut_sr[2:0], (ce_pix | ce_pix_n) };
|
||||
|
||||
if (color_lut_sr[1]) begin r_lut <= color_lut_dout; end
|
||||
if (color_lut_sr[2]) begin g_lut <= color_lut_dout; end
|
||||
if (color_lut_sr[3]) begin b_lut <= color_lut_dout; end
|
||||
color_lut_wr <= 0;
|
||||
if (lut_download & ioctl_wr) begin
|
||||
color_cnt <= color_cnt + 1'b1;
|
||||
case (color_cnt)
|
||||
2'd0: begin
|
||||
color_lut_data[15:0] <= ioctl_dout[15:0];
|
||||
end
|
||||
2'd1: begin
|
||||
color_lut_data[23:16] <= ioctl_dout[7:0];
|
||||
color_lut_temp <= ioctl_dout[15:8];
|
||||
color_lut_wr <= 1'b1;
|
||||
end
|
||||
2'd2: begin
|
||||
color_lut_data[23:0] <= { ioctl_dout[15:0], color_lut_temp };
|
||||
color_lut_wr <= 1'b1;
|
||||
color_cnt <= 2'd0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
wire [23:0] color_lut_dout;
|
||||
|
||||
// Color 3D LUT
|
||||
dpram #(15,24, "lcd_color_lut.mif") lcd_color_lut (
|
||||
.clock_a (clk_vid),
|
||||
.address_a ( { r5, g5, b5 } ),
|
||||
.q_a (color_lut_dout),
|
||||
|
||||
.clock_b (clk_sys),
|
||||
.address_b (color_lut_wr_addr),
|
||||
.data_b (color_lut_data),
|
||||
.wren_b (color_lut_wr),
|
||||
.q_b ()
|
||||
);
|
||||
|
||||
reg [7:0] r_tmp, g_tmp, b_tmp;
|
||||
always@(*) begin
|
||||
if (~sgb_pal_en & isGBC & !originalcolors) begin
|
||||
r_tmp = r_lut;
|
||||
g_tmp = g_lut;
|
||||
b_tmp = b_lut;
|
||||
r_tmp = color_lut_dout[7:0];
|
||||
g_tmp = color_lut_dout[15:8];
|
||||
b_tmp = color_lut_dout[23:16];
|
||||
end else if (sgb_pal_en | (isGBC & originalcolors)) begin
|
||||
r_tmp = {r5,r5[4:2]};
|
||||
g_tmp = {g5,g5[4:2]};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -72,6 +72,7 @@ reg reg_start;
|
||||
reg cram_wr_r;
|
||||
reg ram_io;
|
||||
reg prev_cram_rd;
|
||||
reg prev_cart_wr;
|
||||
|
||||
reg [6:0] rtc_seconds;
|
||||
reg [14:0] rtc_subseconds;
|
||||
@@ -107,7 +108,8 @@ assign savestate_back[ 34] = reg_start;
|
||||
assign savestate_back[ 35] = cram_wr_r;
|
||||
assign savestate_back[ 36] = ram_io;
|
||||
assign savestate_back[ 37] = prev_cram_rd;
|
||||
assign savestate_back[63:38] = 0;
|
||||
assign savestate_back[ 38] = prev_cart_wr;
|
||||
assign savestate_back[63:39] = 0;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if(savestate_load & enable) begin
|
||||
@@ -123,6 +125,7 @@ always @(posedge clk_sys) begin
|
||||
cram_wr_r <= savestate_data[ 35]; //1'd0;
|
||||
ram_io <= savestate_data[ 36]; //1'd0;
|
||||
prev_cram_rd <= savestate_data[ 37]; //1'd0;
|
||||
prev_cart_wr <= savestate_data[ 38]; //1'd0;
|
||||
end else if(~enable) begin
|
||||
rom_bank_reg <= 5'd0;
|
||||
unlocked <= 1'd0;
|
||||
@@ -136,27 +139,31 @@ always @(posedge clk_sys) begin
|
||||
cram_wr_r <= 1'd0;
|
||||
ram_io <= 1'd0;
|
||||
prev_cram_rd <= 1'd0;
|
||||
prev_cart_wr <= 1'd0;
|
||||
end else begin
|
||||
|
||||
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
|
||||
unlocked <= 1'b1;
|
||||
if (ce_cpu) begin
|
||||
prev_cart_wr <= cart_wr;
|
||||
if (prev_cart_wr & ~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
|
||||
unlocked <= 1'b1;
|
||||
end
|
||||
end else if (unlocked) begin
|
||||
case (reg_index)
|
||||
4'd0: rom_bank_reg[3:0] <= cart_di[3:0];
|
||||
4'd1: rom_bank_reg[4] <= cart_di[0];
|
||||
4'd4: reg_data_in[3:0] <= cart_di[3:0];
|
||||
4'd5: reg_data_in[7:4] <= cart_di[3:0];
|
||||
4'd6: { rtc_sel, ram_read, reg_addr[4] } <= cart_di[3:0];
|
||||
4'd7: begin
|
||||
reg_addr[3:0] <= cart_di[3:0];
|
||||
reg_start <= 1'b1;
|
||||
end
|
||||
default ;
|
||||
endcase
|
||||
end
|
||||
end else if (unlocked) begin
|
||||
case (reg_index)
|
||||
4'd0: rom_bank_reg[3:0] <= cart_di[3:0];
|
||||
4'd1: rom_bank_reg[4] <= cart_di[0];
|
||||
4'd4: reg_data_in[3:0] <= cart_di[3:0];
|
||||
4'd5: reg_data_in[7:4] <= cart_di[3:0];
|
||||
4'd6: { rtc_sel, ram_read, reg_addr[4] } <= cart_di[3:0];
|
||||
4'd7: begin
|
||||
reg_addr[3:0] <= cart_di[3:0];
|
||||
reg_start <= 1'b1;
|
||||
end
|
||||
default ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
386
rtl/sdram.sv
386
rtl/sdram.sv
@@ -1,9 +1,9 @@
|
||||
//
|
||||
// sdram.v
|
||||
// This version issues refresh only when 8bit channel reads the same 16bit word 2 times
|
||||
//
|
||||
// sdram controller implementation for the MiST/MiSTer boards
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
// Copyright (c) 2017 Sorgelig
|
||||
// sdram controller implementation
|
||||
// Copyright (c) 2018 Sorgelig
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
@@ -19,180 +19,260 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
//
|
||||
//
|
||||
// This SDRAM module provides/writes the data in 8 cycles of clock.
|
||||
// So, with 64MHz of system clock, it can emulate 8MHz asynchronous DRAM.
|
||||
//
|
||||
//
|
||||
|
||||
module sdram
|
||||
(
|
||||
|
||||
// interface to the MT48LC16M16 chip
|
||||
inout reg [15:0] sd_data, // 16 bit bidirectional data bus
|
||||
output reg [12:0] sd_addr, // 13 bit multiplexed address bus
|
||||
output [1:0] sd_dqm, // two byte masks
|
||||
output reg [1:0] sd_ba, // two banks
|
||||
output sd_cs, // a single chip select
|
||||
output sd_we, // write enable
|
||||
output sd_ras, // row address select
|
||||
output sd_cas, // columns address select
|
||||
output sd_clk,
|
||||
inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
|
||||
output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
|
||||
output reg SDRAM_DQML, // byte mask
|
||||
output reg SDRAM_DQMH, // byte mask
|
||||
output reg [1:0] SDRAM_BA, // two banks
|
||||
output reg SDRAM_nCS, // a single chip select
|
||||
output reg SDRAM_nWE, // write enable
|
||||
output reg SDRAM_nRAS, // row address select
|
||||
output reg SDRAM_nCAS, // columns address select
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE,
|
||||
|
||||
// cpu/chipset interface
|
||||
input init, // init signal after FPGA config to initialize RAM
|
||||
input clk, // sdram is accessed at 64MHz
|
||||
input sync,
|
||||
input init, // init signal after FPGA config to initialize RAM
|
||||
input clk, // sdram is accessed at up to 128MHz
|
||||
|
||||
input [15:0] din, // data input from chipset/cpu
|
||||
output reg [15:0] dout, // data output to chipset/cpu
|
||||
input [23:0] addr, // 24 bit word address
|
||||
input [1:0] ds, // upper/lower data strobe
|
||||
input oe, // cpu/chipset requests read
|
||||
input we, // cpu/chipset requests write
|
||||
input autorefresh,// autorefresh when no read or write required
|
||||
input refresh // force refresh when core is paused or fastforward
|
||||
input [24:0] ch0_addr,
|
||||
input ch0_rd,
|
||||
input ch0_wr,
|
||||
input ch0_word,
|
||||
input [15:0] ch0_din,
|
||||
output reg [15:0] ch0_dout,
|
||||
output reg ch0_busy,
|
||||
|
||||
input [24:0] ch1_addr,
|
||||
input ch1_rd,
|
||||
input ch1_wr,
|
||||
input ch1_word,
|
||||
input [15:0] ch1_din,
|
||||
output reg [15:0] ch1_dout,
|
||||
output reg ch1_busy,
|
||||
|
||||
input [24:0] ch2_addr,
|
||||
input ch2_rd,
|
||||
input ch2_wr,
|
||||
input [7:0] ch2_din,
|
||||
output reg [7:0] ch2_dout,
|
||||
output reg ch2_busy,
|
||||
|
||||
input refresh
|
||||
);
|
||||
|
||||
localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 3 cycles@128MHz
|
||||
localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8
|
||||
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
|
||||
assign SDRAM_nCS = 0;
|
||||
assign SDRAM_CKE = 1;
|
||||
assign {SDRAM_DQMH,SDRAM_DQML} = SDRAM_A[12:11];
|
||||
|
||||
localparam RASCAS_DELAY = 3'd1; // tRCD=20ns -> 2 cycles@85MHz
|
||||
localparam BURST_LENGTH = 3'd0; // 0=1, 1=2, 2=4, 3=8, 7=full page
|
||||
localparam ACCESS_TYPE = 1'd0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'd0; // only 0 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'd1; // 0=write burst enabled, 1=only single access write
|
||||
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
localparam STATE_IDLE = 3'd0; // state to check the requests
|
||||
localparam STATE_START = STATE_IDLE+1'd1; // state in which a new command is started
|
||||
localparam STATE_NEXT = STATE_START+1'd1; // state in which a new command is started
|
||||
localparam STATE_CONT = STATE_START+RASCAS_DELAY;
|
||||
localparam STATE_READY = STATE_CONT+CAS_LATENCY+2'd2;
|
||||
localparam STATE_LAST = STATE_READY; // last state in cycle
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------------ cycle state machine ------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
reg [2:0] state;
|
||||
reg [22:0] a;
|
||||
reg [1:0] bank;
|
||||
reg [15:0] data;
|
||||
reg we;
|
||||
reg ds;
|
||||
reg ram_req=0;
|
||||
|
||||
// The state machine runs at 128Mhz synchronous to the 8 Mhz chipset clock.
|
||||
// It wraps from T15 to T0 on the rising edge of clk_8
|
||||
wire [2:0] rd,wr;
|
||||
|
||||
localparam STATE_FIRST = 3'd0; // first state in cycle
|
||||
localparam STATE_CMD_START = 3'd1; // state in which a new command can be started
|
||||
localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY; // command can be continued
|
||||
localparam STATE_READ = STATE_CMD_CONT + CAS_LATENCY + 4'd1;
|
||||
localparam STATE_HIGHZ = STATE_READ - 4'd1; // disable output to prevent contention
|
||||
assign rd = {ch2_rd, ch1_rd, ch0_rd};
|
||||
assign wr = {ch2_wr, ch1_wr, ch0_wr};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// --------------------------- startup/reset ---------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// wait 1ms (32 8Mhz cycles) after FPGA config is done before going
|
||||
// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
|
||||
reg [4:0] reset;
|
||||
// access manager
|
||||
always @(posedge clk) begin
|
||||
if(init) reset <= 5'h1f;
|
||||
else if((stage == STATE_FIRST) && (reset != 0))
|
||||
reset <= reset - 5'd1;
|
||||
end
|
||||
reg old_ref;
|
||||
reg [2:0] old_rd,old_wr;//,rd,wr;
|
||||
reg [24:1] last_a[3] = '{'1,'1,'1};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------ generate ram control signals ---------------------
|
||||
// ---------------------------------------------------------------------
|
||||
old_rd <= old_rd & rd;
|
||||
old_wr <= old_wr & wr;
|
||||
|
||||
// all possible commands
|
||||
localparam CMD_INHIBIT = 4'b1111;
|
||||
localparam CMD_NOP = 4'b0111;
|
||||
localparam CMD_ACTIVE = 4'b0011;
|
||||
localparam CMD_READ = 4'b0101;
|
||||
localparam CMD_WRITE = 4'b0100;
|
||||
localparam CMD_BURST_TERMINATE = 4'b0110;
|
||||
localparam CMD_PRECHARGE = 4'b0010;
|
||||
localparam CMD_AUTO_REFRESH = 4'b0001;
|
||||
localparam CMD_LOAD_MODE = 4'b0000;
|
||||
|
||||
reg [3:0] sd_cmd; // current command sent to sd ram
|
||||
|
||||
// drive control signals according to current command
|
||||
assign sd_cs = sd_cmd[3];
|
||||
assign sd_ras = sd_cmd[2];
|
||||
assign sd_cas = sd_cmd[1];
|
||||
assign sd_we = sd_cmd[0];
|
||||
|
||||
assign sd_dqm = sd_addr[12:11];
|
||||
|
||||
reg [1:0] mode;
|
||||
reg [15:0] din_r;
|
||||
reg [2:0] stage;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [12:0] addr_r;
|
||||
reg old_sync;
|
||||
reg old_oe;
|
||||
|
||||
if(|stage) stage <= stage + 1'd1;
|
||||
|
||||
old_sync <= sync;
|
||||
old_oe <= oe;
|
||||
if(~old_sync && sync && autorefresh) stage <= 1; // normal operation with read/write and refresh
|
||||
if(refresh && stage == STATE_FIRST) stage <= 1; // forced refresh when paused or fastforward
|
||||
if(~old_oe && oe && ~autorefresh) stage <= 1; // react on request only with fastforward
|
||||
|
||||
sd_cmd <= CMD_INHIBIT; // default: idle
|
||||
sd_data <= 16'hZZZZ;
|
||||
|
||||
if(reset != 0) begin
|
||||
// initialization takes place at the end of the reset phase
|
||||
if(stage == STATE_CMD_START) begin
|
||||
|
||||
if(reset == 13) begin
|
||||
sd_cmd <= CMD_PRECHARGE;
|
||||
sd_addr[10] <= 1'b1; // precharge all banks
|
||||
end
|
||||
|
||||
if(reset == 2) begin
|
||||
sd_cmd <= CMD_LOAD_MODE;
|
||||
sd_addr <= MODE;
|
||||
end
|
||||
|
||||
if(state == STATE_IDLE && mode == MODE_NORMAL) begin
|
||||
ram_req <= 0;
|
||||
we <= 0;
|
||||
ch0_busy <= 0;
|
||||
ch1_busy <= 0;
|
||||
ch2_busy <= 0;
|
||||
if((~old_rd[0] & rd[0]) | (~old_wr[0] & wr[0])) begin
|
||||
old_rd[0] <= rd[0];
|
||||
old_wr[0] <= wr[0];
|
||||
we <= wr[0];
|
||||
ds <= ch0_word;
|
||||
{bank,a} <= ch0_addr;
|
||||
data <= ch0_word ? ch0_din : {ch0_din[7:0],ch0_din[7:0]};
|
||||
ram_req <= wr[0] || (last_a[0] != ch0_addr[24:1]);
|
||||
last_a[0] <= wr[0] ? '1 : ch0_addr[24:1];
|
||||
ch0_busy <= 1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
mode <= 0;
|
||||
end else begin
|
||||
|
||||
// normal operation
|
||||
if(stage == STATE_CMD_START) begin
|
||||
if(we || oe) begin
|
||||
|
||||
mode <= {we, oe};
|
||||
|
||||
// RAS phase
|
||||
sd_cmd <= CMD_ACTIVE;
|
||||
sd_addr <= { 1'b0, addr[19:8] };
|
||||
sd_ba <= addr[21:20];
|
||||
|
||||
din_r <= din;
|
||||
addr_r <= { we ? ~ds : 2'b00, 2'b10, addr[22], addr[7:0] }; // auto precharge
|
||||
end
|
||||
else if (autorefresh || refresh) begin
|
||||
sd_cmd <= CMD_AUTO_REFRESH;
|
||||
mode <= 0;
|
||||
end
|
||||
else if((~old_rd[1] & rd[1]) | (~old_wr[1] & wr[1])) begin
|
||||
old_rd[1] <= rd[1];
|
||||
old_wr[1] <= wr[1];
|
||||
we <= wr[1];
|
||||
ds <= ch1_word;
|
||||
{bank,a} <= ch1_addr;
|
||||
data <= ch1_word ? ch1_din : {ch1_din[7:0],ch1_din[7:0]};
|
||||
ram_req <= wr[1] || (last_a[1] != ch1_addr[24:1]);
|
||||
last_a[1] <= wr[1] ? '1 : ch1_addr[24:1];
|
||||
ch1_busy <= 1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
|
||||
// CAS phase
|
||||
if(stage == STATE_CMD_CONT && mode) begin
|
||||
sd_cmd <= mode[1] ? CMD_WRITE : CMD_READ;
|
||||
sd_addr <= addr_r;
|
||||
if(mode[1]) sd_data <= din_r;
|
||||
else if((~old_rd[2] & rd[2]) | (~old_wr[2] & wr[2])) begin
|
||||
old_rd[2] <= rd[2];
|
||||
old_wr[2] <= wr[2];
|
||||
we <= wr[2];
|
||||
ds <= 0;
|
||||
{bank,a} <= ch2_addr;
|
||||
data <= {ch2_din,ch2_din};
|
||||
ram_req <= wr[2] || (last_a[2] != ch2_addr[24:1]);
|
||||
last_a[2] <= wr[2] ? '1 : ch2_addr[24:1];
|
||||
ch2_busy <= 1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
|
||||
if(stage == STATE_HIGHZ) begin
|
||||
sd_addr[12:11] <= 2'b11; // disable chip output
|
||||
mode[1] <= 0; // disable data output
|
||||
end
|
||||
|
||||
if(stage == STATE_READ && mode) begin
|
||||
dout <= sd_data;
|
||||
else if (refresh) begin
|
||||
ram_req <= 1'b0;
|
||||
we <= 1'b0;
|
||||
state <= STATE_START;
|
||||
end
|
||||
end
|
||||
|
||||
if (state == STATE_READY) begin
|
||||
ch0_busy <= 0;
|
||||
ch1_busy <= 0;
|
||||
ch2_busy <= 0;
|
||||
end
|
||||
|
||||
if(mode != MODE_NORMAL || state != STATE_IDLE || reset) begin
|
||||
state <= state + 1'd1;
|
||||
if(state == STATE_LAST) state <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
localparam MODE_NORMAL = 2'b00;
|
||||
localparam MODE_RESET = 2'b01;
|
||||
localparam MODE_LDM = 2'b10;
|
||||
localparam MODE_PRE = 2'b11;
|
||||
|
||||
// initialization
|
||||
reg [1:0] mode;
|
||||
reg [4:0] reset=5'h1f;
|
||||
always @(posedge clk) begin
|
||||
reg init_old=0;
|
||||
init_old <= init;
|
||||
|
||||
if(init_old & ~init) reset <= 5'h1f;
|
||||
else if(state == STATE_LAST) begin
|
||||
if(reset != 0) begin
|
||||
reset <= reset - 5'd1;
|
||||
if(reset == 14) mode <= MODE_PRE;
|
||||
else if(reset == 3) mode <= MODE_LDM;
|
||||
else mode <= MODE_RESET;
|
||||
end
|
||||
else mode <= MODE_NORMAL;
|
||||
end
|
||||
end
|
||||
|
||||
localparam CMD_NOP = 3'b111;
|
||||
localparam CMD_ACTIVE = 3'b011;
|
||||
localparam CMD_READ = 3'b101;
|
||||
localparam CMD_WRITE = 3'b100;
|
||||
localparam CMD_BURST_TERMINATE = 3'b110;
|
||||
localparam CMD_PRECHARGE = 3'b010;
|
||||
localparam CMD_AUTO_REFRESH = 3'b001;
|
||||
localparam CMD_LOAD_MODE = 3'b000;
|
||||
|
||||
wire [1:0] dqm = {we & ~ds & ~a[0], we & ~ds & a[0]};
|
||||
|
||||
// SDRAM state machines
|
||||
always @(posedge clk) begin
|
||||
reg [15:0] last_data[3];
|
||||
reg [15:0] data_reg;
|
||||
|
||||
if(state == STATE_START) SDRAM_BA <= (mode == MODE_NORMAL) ? bank : 2'b00;
|
||||
|
||||
SDRAM_DQ <= 'Z;
|
||||
casex({ram_req,we,mode,state})
|
||||
{2'b1X, MODE_NORMAL, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_ACTIVE;
|
||||
{2'b11, MODE_NORMAL, STATE_CONT }: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE, SDRAM_DQ} <= {CMD_WRITE, data};
|
||||
{2'b10, MODE_NORMAL, STATE_CONT }: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_READ;
|
||||
{2'b0X, MODE_NORMAL, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_AUTO_REFRESH;
|
||||
|
||||
// init
|
||||
{2'bXX, MODE_LDM, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_LOAD_MODE;
|
||||
{2'bXX, MODE_PRE, STATE_START}: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_PRECHARGE;
|
||||
|
||||
default: {SDRAM_nRAS, SDRAM_nCAS, SDRAM_nWE} <= CMD_NOP;
|
||||
endcase
|
||||
|
||||
casex({ram_req,mode,state})
|
||||
{1'b1, MODE_NORMAL, STATE_START}: SDRAM_A <= a[13:1];
|
||||
{1'b1, MODE_NORMAL, STATE_CONT }: SDRAM_A <= {dqm, 2'b10, a[22:14]};
|
||||
|
||||
// init
|
||||
{1'bX, MODE_LDM, STATE_START}: SDRAM_A <= MODE;
|
||||
{1'bX, MODE_PRE, STATE_START}: SDRAM_A <= 13'b0010000000000;
|
||||
|
||||
default: SDRAM_A <= 13'b0000000000000;
|
||||
endcase
|
||||
|
||||
data_reg <= SDRAM_DQ;
|
||||
|
||||
if(state == STATE_READY) begin
|
||||
if(ch0_busy) begin
|
||||
if(ram_req) begin
|
||||
if(we) ch0_dout <= data;
|
||||
else begin
|
||||
ch0_dout <= (~ch0_word & a[0]) ? {data_reg[7:0], data_reg[15:8]} : data_reg;
|
||||
last_data[0] <= data_reg;
|
||||
end
|
||||
end
|
||||
else ch0_dout <= (~ch0_word & a[0]) ? {last_data[0][7:0], last_data[0][15:8]} : last_data[0];
|
||||
end
|
||||
if(ch1_busy) begin
|
||||
if(ram_req) begin
|
||||
if(we) ch1_dout <= data;
|
||||
else begin
|
||||
ch1_dout <= (~ch1_word & a[0]) ? {data_reg[7:0], data_reg[15:8]} : data_reg;
|
||||
last_data[1] <= data_reg;
|
||||
end
|
||||
end
|
||||
else ch1_dout <= (~ch1_word & a[0]) ? {last_data[1][7:0], last_data[1][15:8]} : last_data[1];
|
||||
end
|
||||
if(ch2_busy) begin
|
||||
if(ram_req) begin
|
||||
if(we) ch2_dout <= data[7:0];
|
||||
else begin
|
||||
ch2_dout <= a[0] ? data_reg[15:8] : data_reg[7:0];
|
||||
last_data[2] <= data_reg;
|
||||
end
|
||||
end
|
||||
else ch2_dout <= a[0] ? last_data[2][15:8] : last_data[2][7:0];
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
altddio_out
|
||||
#(
|
||||
.extend_oe_disable("OFF"),
|
||||
@@ -209,7 +289,7 @@ sdramclk_ddr
|
||||
.datain_h(1'b0),
|
||||
.datain_l(1'b1),
|
||||
.outclock(clk),
|
||||
.dataout(sd_clk),
|
||||
.dataout(SDRAM_CLK),
|
||||
.aclr(1'b0),
|
||||
.aset(1'b0),
|
||||
.oe(1'b1),
|
||||
|
||||
@@ -9,6 +9,7 @@ entity speedcontrol is
|
||||
pause : in std_logic;
|
||||
speedup : in std_logic;
|
||||
cart_act : in std_logic;
|
||||
save_act : in std_logic;
|
||||
DMA_on : in std_logic;
|
||||
ce : out std_logic := '0';
|
||||
ce_n : out std_logic := '0';
|
||||
@@ -64,7 +65,7 @@ begin
|
||||
if (pause = '1' and clkdiv = "111" and cart_act = '0') then
|
||||
state <= PAUSED;
|
||||
unpause_cnt <= 0;
|
||||
elsif (speedup = '1' and pause = '0' and DMA_on = '0' and clkdiv = "000") then
|
||||
elsif (speedup = '1' and pause = '0' and DMA_on = '0' and save_act = '0' and clkdiv = "000") then
|
||||
state <= FASTFORWARDSTART;
|
||||
fastforward_cnt <= 0;
|
||||
else
|
||||
@@ -82,7 +83,11 @@ begin
|
||||
|
||||
when PAUSED =>
|
||||
if (unpause_cnt = 0) then
|
||||
refresh <= '1';
|
||||
if (refreshcnt > 117) then
|
||||
refresh <= '1';
|
||||
elsif (refreshcnt = 0) then
|
||||
refreshcnt <= 127;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if (pause = '0') then
|
||||
@@ -102,7 +107,7 @@ begin
|
||||
end if;
|
||||
|
||||
when FASTFORWARD =>
|
||||
if (pause = '1' or speedup = '0' or DMA_on = '1') then
|
||||
if (pause = '1' or speedup = '0' or DMA_on = '1' or save_act = '1') then
|
||||
state <= FASTFORWARDEND;
|
||||
fastforward_cnt <= 0;
|
||||
if (clkdiv(0) = '1') then
|
||||
@@ -111,11 +116,12 @@ begin
|
||||
elsif (cart_act = '1' and cart_act_1 = '0') then
|
||||
state <= RAMACCESS;
|
||||
sdram_busy <= 1;
|
||||
elsif (cart_act = '0' and refreshcnt = 0) then
|
||||
refreshcnt <= 127;
|
||||
refresh <= '1';
|
||||
state <= RAMACCESS;
|
||||
sdram_busy <= 1;
|
||||
-- Refresh is already done in current SDRAM controller
|
||||
--elsif (cart_act = '0' and refreshcnt = 0) then
|
||||
-- refreshcnt <= 127;
|
||||
-- refresh <= '1';
|
||||
-- state <= RAMACCESS;
|
||||
-- sdram_busy <= 1;
|
||||
else
|
||||
clkdiv(0) <= not clkdiv(0);
|
||||
if (clkdiv(0) = '0') then
|
||||
|
||||
@@ -129,7 +129,12 @@ dpram #(7,8) oam_data_h (
|
||||
.q_b (Savestate_OAMRAMReadDataH)
|
||||
);
|
||||
|
||||
assign Savestate_OAMRAMReadData = Savestate_OAMRAMAddr[0] ? Savestate_OAMRAMReadDataH : Savestate_OAMRAMReadDataL;
|
||||
reg Savestate_OAMRAMAddr0_d;
|
||||
always @(posedge clk) begin
|
||||
Savestate_OAMRAMAddr0_d <= Savestate_OAMRAMAddr[0];
|
||||
end
|
||||
|
||||
assign Savestate_OAMRAMReadData = Savestate_OAMRAMAddr0_d ? Savestate_OAMRAMReadDataH : Savestate_OAMRAMReadDataL;
|
||||
|
||||
reg [7:0] sprite_x[0:SPRITES_PER_LINE-1];
|
||||
reg [3:0] sprite_y[0:SPRITES_PER_LINE-1];
|
||||
|
||||
Reference in New Issue
Block a user