From 2d965da32376f5c5bf7378ae5e6e7707736fbf09 Mon Sep 17 00:00:00 2001 From: Robert Peip Date: Tue, 15 Dec 2020 15:24:33 +0100 Subject: [PATCH] add fastforward and OSD-Pause feature --- Gameboy.sv | 40 +++++++++++++++++------- files.qip | 1 + rtl/gb.v | 3 +- rtl/speedcontrol.vhd | 73 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 rtl/speedcontrol.vhd diff --git a/Gameboy.sv b/Gameboy.sv index fd8cb48..cf040fe 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -151,7 +151,7 @@ assign AUDIO_MIX = status[8:7]; // 0 1 2 3 // 01234567890123456789012345678901 // 0123456789ABCDEFGHIJKLMNOPQRSTUV -// XXXXXXXXXXXXXXXXXXXXX XX +// XXXXXXXXXXXXXXXXXXXXX XXXXX `include "build_id.v" localparam CONF_STR = { @@ -179,9 +179,12 @@ localparam CONF_STR = { "-;", "OB,Boot,Normal,Fast;", "O6,Link Port,Disabled,Enabled;", + "-;", + "OPQ,FastForward Sound,Normal,Hack,Off;", + "OR,Pause when OSD is open,Off,On;", "-;", "R0,Reset;", - "J1,A,B,Select,Start;", + "J1,A,B,Select,Start,FastForward;", "V,v",`BUILD_DATE }; @@ -555,6 +558,9 @@ always @(posedge clk_sys) if(reset) begin else if(cart_download) isGBC <= !filetype[7:4]; end +wire [15:0] GB_AUDIO_L; +wire [15:0] GB_AUDIO_R; + // the gameboy itself gb gb ( .reset ( reset ), @@ -562,6 +568,7 @@ gb gb ( .clk_sys ( clk_sys ), .ce ( ce_cpu ), // the whole gameboy runs on 4mhnz .ce_2x ( ce_cpu2x ), // ~8MHz in dualspeed mode (GBC) + .ce_sound ( ce_sound ), // ~8Mhz if not fastforward .fast_boot ( status[11] ), @@ -583,8 +590,8 @@ gb gb ( .gbc_bios_do ( bios_do ), // audio - .audio_l ( AUDIO_L ), - .audio_r ( AUDIO_R ), + .audio_l ( GB_AUDIO_L ), + .audio_r ( GB_AUDIO_R ), // interface to the lcd .lcd_clkena ( lcd_clkena ), @@ -609,6 +616,9 @@ gb gb ( .gg_available(gg_available) ); +assign AUDIO_L = (joystick_0[8] && status[26]) ? 16'd0 : GB_AUDIO_L; +assign AUDIO_R = (joystick_0[8] && status[26]) ? 16'd0 : GB_AUDIO_R; + // the lcd to vga converter wire [7:0] video_r, video_g, video_b; wire video_hs, video_vs; @@ -739,14 +749,22 @@ video_mixer #(.LINE_LENGTH(200), .GAMMA(1)) video_mixer //////////////////////////////// CE //////////////////////////////////// -reg ce_cpu, ce_cpu2x; -always @(negedge clk_sys) begin - reg [2:0] div = 0; - div <= div + 1'd1; - ce_cpu2x <= !div[1:0]; - ce_cpu <= !div[2:0]; -end +wire ce_cpu, ce_cpu2x, ce_sound, ce_soundhack; +wire cart_act = cart_wr | cart_rd; + +speedcontrol speedcontrol +( + .clk_sys (clk_sys), + .pause (status[27] && OSD_STATUS && !ioctl_download), + .speedup (joystick_0[8] && !ioctl_download && !OSD_STATUS), + .cart_act (cart_act), + .ce (ce_cpu), + .ce_2x (ce_cpu2x), + .ce_2xNormal (ce_soundhack) +); + +assign ce_sound = status[25] ? ce_soundhack : ce_cpu2x; ///////////////////////////// GBC BIOS ///////////////////////////////// diff --git a/files.qip b/files.qip index f215bd4..80a7915 100644 --- a/files.qip +++ b/files.qip @@ -9,6 +9,7 @@ set_global_assignment -name VERILOG_FILE rtl/timer.v set_global_assignment -name VERILOG_FILE rtl/sprites.v set_global_assignment -name VERILOG_FILE rtl/lcd.v set_global_assignment -name VHDL_FILE rtl/gbc_snd.vhd +set_global_assignment -name VHDL_FILE rtl/speedcontrol.vhd set_global_assignment -name VERILOG_FILE rtl/gb.v set_global_assignment -name VERILOG_FILE rtl/hdma.v set_global_assignment -name VERILOG_FILE rtl/link.v diff --git a/rtl/gb.v b/rtl/gb.v index 89fbdc3..688cbd0 100644 --- a/rtl/gb.v +++ b/rtl/gb.v @@ -25,6 +25,7 @@ module gb ( input clk_sys, input ce, input ce_2x, + input ce_sound, input fast_boot, input [7:0] joystick, @@ -267,7 +268,7 @@ wire audio_wr = !cpu_wr_n && sel_audio; gbc_snd audio ( .clk ( clk_sys ), - .ce ( ce_2x ), + .ce ( ce_sound ), .reset ( reset_r ), .is_gbc ( isGBC ), diff --git a/rtl/speedcontrol.vhd b/rtl/speedcontrol.vhd new file mode 100644 index 0000000..b51cd6a --- /dev/null +++ b/rtl/speedcontrol.vhd @@ -0,0 +1,73 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity speedcontrol is + port + ( + clk_sys : in std_logic; + pause : in std_logic; + speedup : in std_logic; + cart_act : in std_logic; + ce : out std_logic := '0'; + ce_2x : out std_logic := '0'; + ceNormal : out std_logic := '0'; + ce_2xNormal : out std_logic := '0' + ); +end entity; + +architecture arch of speedcontrol is + + signal clkdiv : unsigned(2 downto 0) := (others => '0'); + signal nextdiv : unsigned(2 downto 0) := (others => '0'); + + signal clkdivNormal : unsigned(2 downto 0) := (others => '0'); + + signal cart_act_1 : std_logic := '0'; + +begin + + process(clk_sys) + begin + if falling_edge(clk_sys) then + if (pause = '1') then + + ce <= '0'; + ce_2x <= '0'; + ceNormal <= '0'; + ce_2xNormal <= '0'; + + else + + clkdiv <= clkdiv + 1; + clkdivNormal <= clkdivNormal + 1; + + -- generation for speed depending on speedup + cart_act_1 <= cart_act; + + if (clkdiv = "000") then ce <= '1'; else ce <= '0'; end if; + if ((nextdiv = "111" and clkdiv(1 downto 0) = "00") or nextdiv = "001") then ce_2x <= '1'; else ce_2x <= '0'; end if; + + if (clkdiv = nextdiv and (clkdiv = "111" or cart_act = '0')) then + clkdiv <= "000"; + if (speedup = '1') then + nextdiv <= "001"; + else + nextdiv <= "111"; + end if; + end if; + + if (cart_act = '1' and cart_act_1 = '0') then + nextdiv <= "111"; + end if; + + -- generation for non speed up base, used e.g. for sound hack + if (clkdivNormal = "000") then ceNormal <= '1'; else ceNormal <= '0'; end if; + if (clkdivNormal(1 downto 0) = "00") then ce_2xNormal <= '1'; else ce_2xNormal <= '0'; end if; + + end if; + + end if; + end process; + +end architecture;