diff --git a/cores/c64/C64_mist.qsf b/cores/c64/C64_mist.qsf index ad96e0b..17b86e7 100644 --- a/cores/c64/C64_mist.qsf +++ b/cores/c64/C64_mist.qsf @@ -238,68 +238,84 @@ set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[12] set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[13] set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[14] set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[15] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[0] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[1] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[2] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[3] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[4] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[5] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[6] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[7] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[8] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[9] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[10] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[11] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[12] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[13] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[14] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[15] # Fitter Assignments # ================== -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[2] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[3] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[4] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[5] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[6] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[7] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[8] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[9] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[10] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[11] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_A[12] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[2] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[3] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[4] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[5] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[6] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[7] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[8] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[9] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[10] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[11] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[12] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[13] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[14] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQ[15] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_BA[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_BA[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQML -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_DQMH -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_nRAS -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_nCAS -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_nWE -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_nCS -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[13] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[14] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[15] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[5] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[4] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[3] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[2] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_R[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[5] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[4] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[3] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[2] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_G[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[5] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[4] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[3] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[2] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[1] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_B[0] -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_HS -set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to LED set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R @@ -385,4 +401,7 @@ set_global_assignment -name QIP_FILE rtl/mist/rom_reconfig_ntsc.qip set_global_assignment -name SIGNALTAP_FILE output_files/pll.stp set_location_assignment PIN_46 -to UART_TX set_location_assignment PIN_31 -to UART_RX +set_location_assignment PLL_1 -to pll|altpll_component|auto_generated|pll1 +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to UART_TX + set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/cores/c64/C64_mist.sdc b/cores/c64/C64_mist.sdc index 7e94cbb..04042f8 100644 --- a/cores/c64/C64_mist.sdc +++ b/cores/c64/C64_mist.sdc @@ -43,11 +43,14 @@ set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|cl set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -min -5 [get_ports {VGA_*}] # SDRAM delays -set_input_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -max 6.4 [get_ports SDRAM_DQ[*]] -set_input_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -min 3.2 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -max 6.4 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -min 3.2 [get_ports SDRAM_DQ[*]] -set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] -set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -max 1.5 [get_ports {SDRAM_CLK}] +set_output_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -min -0.8 [get_ports {SDRAM_CLK}] set_multicycle_path -from {video_mixer:vmixer|scandoubler:scandoubler|Hq2x:Hq2x|*} -to {VGA_*[*]} -setup 4 set_multicycle_path -from {video_mixer:vmixer|scandoubler:scandoubler|Hq2x:Hq2x|*} -to {VGA_*[*]} -hold 3 diff --git a/cores/c64/rtl/fpga64_sid_iec.vhd b/cores/c64/rtl/fpga64_sid_iec.vhd index f651b20..61a1edf 100644 --- a/cores/c64/rtl/fpga64_sid_iec.vhd +++ b/cores/c64/rtl/fpga64_sid_iec.vhd @@ -86,6 +86,10 @@ entity fpga64_sid_iec is -- joystick interface joyA : in unsigned(6 downto 0); joyB : in unsigned(6 downto 0); + potA_x : in std_logic_vector(7 downto 0); + potA_y : in std_logic_vector(7 downto 0); + potB_x : in std_logic_vector(7 downto 0); + potB_y : in std_logic_vector(7 downto 0); -- serial port, for connection to pheripherals serioclk : out std_logic; @@ -125,6 +129,7 @@ entity fpga64_sid_iec is -- CIA cia_mode : in std_logic; + todclk : in std_logic; disk_num : out std_logic_vector(7 downto 0); @@ -599,8 +604,14 @@ div1m: process(clk32) -- this process devides 32 MHz to 1MHz (for the SID) sid_do8580_l when second_sid_en='0' else sid_do8580_r; - pot_x <= X"FF" when ((cia1_pao(7) and JoyA(5)) or (cia1_pao(6) and JoyB(5))) = '0' else X"00"; - pot_y <= X"FF" when ((cia1_pao(7) and JoyA(6)) or (cia1_pao(6) and JoyB(6))) = '0' else X"00"; + -- CD4066 analogue switch + pot_x <= potA_x when cia1_pao(6) = '1' else + potB_x when cia1_pao(7) = '1' else + x"FF"; + pot_y <= potA_y when cia1_pao(6) = '1' else + potB_y when cia1_pao(7) = '1' else + x"FF"; + second_sid_en <= '0' when sid_mode(0) = '0' else '1' when cpuAddr(11 downto 8) = x"4" and cpuAddr(5) = '1' else -- D420 '1' when cpuAddr(11 downto 8) = x"5" else -- D500 @@ -693,7 +704,7 @@ div1m: process(clk32) -- this process devides 32 MHz to 1MHz (for the SID) cnt_out => cnt1_out, pc_n => open, - tod => vicVSync, + tod => todclk, irq_n => irq_cia1 ); @@ -723,7 +734,7 @@ div1m: process(clk32) -- this process devides 32 MHz to 1MHz (for the SID) cnt_out => cnt2_out, pc_n => pc2_n, - tod => vicVSync, + tod => todclk, irq_n => irq_cia2 ); diff --git a/cores/c64/rtl/mist/c64_mist.vhd b/cores/c64/rtl/mist/c64_mist.vhd index 2d426c1..b2fff5d 100644 --- a/cores/c64/rtl/mist/c64_mist.vhd +++ b/cores/c64/rtl/mist/c64_mist.vhd @@ -81,6 +81,7 @@ component sdram is port ( -- interface to the MT48LC16M16 chip sd_addr : out std_logic_vector(12 downto 0); + sd_data : inout std_logic_vector(15 downto 0); sd_cs : out std_logic; sd_ba : out std_logic_vector(1 downto 0); sd_we : out std_logic; @@ -93,6 +94,8 @@ component sdram is port -- cpu/chipset interface addr : in std_logic_vector(24 downto 0); + din : in std_logic_vector( 7 downto 0); + dout : out std_logic_vector( 7 downto 0); refresh : in std_logic; we : in std_logic; ce : in std_logic @@ -196,7 +199,11 @@ component user_io generic(STRLEN : integer := 0 ); port ps2_kbd_data : out std_logic; ps2_mouse_clk : out std_logic; - ps2_mouse_data : out std_logic + ps2_mouse_data : out std_logic; + mouse_x : out signed(8 downto 0); + mouse_y : out signed(8 downto 0); + mouse_flags : out std_logic_vector(8 downto 0); -- YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn + mouse_strobe : out std_logic ); end component user_io; @@ -385,6 +392,10 @@ end component cartridge; signal joyB_c64 : std_logic_vector(6 downto 0); signal joyC_c64 : std_logic_vector(6 downto 0); signal joyD_c64 : std_logic_vector(6 downto 0); + signal potA_x : std_logic_vector(7 downto 0); + signal potA_y : std_logic_vector(7 downto 0); + signal potB_x : std_logic_vector(7 downto 0); + signal potB_y : std_logic_vector(7 downto 0); signal reset_key : std_logic; signal cart_detach_key :std_logic; -- cartridge detach key CTRL-D - LCA @@ -415,7 +426,15 @@ end component cartridge; signal ps2_clk : std_logic; signal ps2_dat : std_logic; - + signal mouse_en : std_logic; + signal mouse_x : signed( 8 downto 0); + signal mouse_x_pos : signed(10 downto 0); + signal mouse_y : signed( 8 downto 0); + signal mouse_y_pos : signed(10 downto 0); + signal mouse_flags : std_logic_vector(8 downto 0); + signal mouse_btns : std_logic_vector(1 downto 0); + signal mouse_strobe : std_logic; + signal c64_iec_atn_i : std_logic; signal c64_iec_clk_o : std_logic; signal c64_iec_data_o : std_logic; @@ -448,14 +467,17 @@ end component cartridge; signal c64_data_in16: std_logic_vector(15 downto 0); alias c64_data_out_int : unsigned is unsigned(c64_data_out); - signal c64_clk : std_logic; -- 31.527mhz (PAL), 32.727mhz(NTSC) clock source - signal clk_ram : std_logic; -- 2 x c64_clk + signal clk_c64 : std_logic; -- 31.527mhz (PAL), 32.727mhz(NTSC) clock source + signal clk_ram : std_logic; -- 2 x clk_c64 signal clk32 : std_logic; -- 32mhz signal ce_8 : std_logic; signal ce_4 : std_logic; signal hq2x160 : std_logic; signal osdclk : std_logic; signal clkdiv : std_logic_vector(9 downto 0); + signal todclk : std_logic; + signal toddiv : std_logic_vector(19 downto 0); + signal toddiv3 : std_logic_vector(1 downto 0); signal ram_ce : std_logic; signal ram_we : std_logic; @@ -499,7 +521,7 @@ begin user_io_d : user_io generic map (STRLEN => CONF_STR'length) port map ( - clk_sys => c64_clk, + clk_sys => clk_c64, clk_sd => clk32, SPI_CLK => SPI_SCK, @@ -532,12 +554,16 @@ begin sd_dout_strobe => sd_buff_wr, img_mounted => sd_change, ps2_kbd_clk => ps2_clk, - ps2_kbd_data => ps2_dat + ps2_kbd_data => ps2_dat, + mouse_x => mouse_x, + mouse_y => mouse_y, + mouse_flags => mouse_flags, + mouse_strobe => mouse_strobe ); data_io_d: data_io port map ( - clk_sys => c64_clk, + clk_sys => clk_c64, SPI_SCK => SPI_SCK, SPI_SS2 => SPI_SS2, SPI_DI => SPI_DI, @@ -564,7 +590,7 @@ begin mem_ce => not ram_ce, mem_ce_out => mem_ce, - clk32 => c64_clk, + clk32 => clk_c64, reset => reset_n, reset_out => reset_crt, @@ -597,8 +623,8 @@ begin ); -- rearrange joystick contacta for c64 - joyA_int <= joyA(6 downto 4) & joyA(0) & joyA(1) & joyA(2) & joyA(3); - joyB_int <= joyB(6 downto 4) & joyB(0) & joyB(1) & joyB(2) & joyB(3); + joyA_int <= joyA(6 downto 5) & (joyA(4) or (mouse_en and mouse_btns(0))) & joyA(0) & joyA(1) & joyA(2) & (joyA(3) or (mouse_en and mouse_btns(1))); + joyB_int <= joyB(6 downto 5) & (joyB(4) or (mouse_en and mouse_btns(0))) & joyB(0) & joyB(1) & joyB(2) & (joyB(3) or (mouse_en and mouse_btns(1))); joyC_c64 <= joyC(6 downto 4) & joyC(0) & joyC(1) & joyC(2) & joyC(3); joyD_c64 <= joyD(6 downto 4) & joyD(0) & joyD(1) & joyD(2) & joyD(3); @@ -613,9 +639,9 @@ begin sdram_ce <= mem_ce when iec_cycle='0' else ioctl_iec_cycle_used; sdram_we <= not ram_we when iec_cycle='0' else ioctl_iec_cycle_used; - process(c64_clk) + process(clk_c64) begin - if falling_edge(c64_clk) then + if falling_edge(clk_c64) then old_download <= ioctl_download; iec_cycleD <= iec_cycle; @@ -732,9 +758,9 @@ begin c64rom_addr <= ioctl_addr(13 downto 0) when ioctl_index = 0 else '1' & ioctl_addr(12 downto 0); c1541rom_wr <= ioctl_wr when (ioctl_index = 0) and (ioctl_addr(14) = '1') and (ioctl_download = '1') else '0'; - process(c64_clk) + process(clk_c64) begin - if rising_edge(c64_clk) then + if rising_edge(clk_c64) then clkdiv <= std_logic_vector(unsigned(clkdiv)+1); if(clkdiv(1 downto 0) = "00") then ce_8 <= '1'; @@ -836,8 +862,8 @@ begin pll : entity work.pll_c64 port map( inclk0 => CLOCK_27, - c0 => c64_clk, - c1 => clk_ram, + c0 => clk_ram, + c1 => clk_c64, areset => pll_areset, scanclk => pll_scanclk, scandata => pll_scandata, @@ -846,7 +872,7 @@ begin scandataout => pll_scandataout, scandone => pll_scandone ); - SDRAM_CLK <= not clk_ram; + SDRAM_CLK <= clk_ram; -- clock for 1541 pll_2 : entity work.pll @@ -856,9 +882,9 @@ begin locked => pll_locked ); - process(c64_clk) + process(clk_c64) begin - if rising_edge(c64_clk) then + if rising_edge(clk_c64) then -- Reset by: -- Button at device, IO controller reboot, OSD or FPGA startup if status(0)='1' or pll_locked = '0' then @@ -884,11 +910,6 @@ begin end if; end process; - SDRAM_DQ(15 downto 8) <= (others => 'Z') when sdram_we='0' else (others => '0'); - SDRAM_DQ(7 downto 0) <= (others => 'Z') when sdram_we='0' else sdram_data_out; - - -- read from sdram - c64_data_in <= SDRAM_DQ(7 downto 0); -- clock is always enabled and memory is never masked as we only -- use one byte SDRAM_CKE <= '1'; @@ -897,6 +918,7 @@ begin sdr: sdram port map( sd_addr => SDRAM_A, + sd_data => SDRAM_DQ, sd_ba => SDRAM_BA, sd_cs => SDRAM_nCS, sd_we => SDRAM_nWE, @@ -905,6 +927,8 @@ begin clk => clk_ram, addr => sdram_addr, + din => sdram_data_out, + dout => c64_data_in, init => not pll_locked, we => sdram_we, refresh => idle, @@ -913,7 +937,7 @@ begin dac : sigma_delta_dac port map ( - clk => c64_clk, + clk => clk_c64, ldatasum => audio_data_l(17 downto 3), rdatasum => audio_data_r(17 downto 3), aleft => AUDIO_L, @@ -923,7 +947,7 @@ begin fpga64 : entity work.fpga64_sid_iec port map( - clk32 => c64_clk, + clk32 => clk_c64, reset_n => reset_n, c64gs => status(11),-- not enough BRAM kbd_clk => not ps2_clk, @@ -958,6 +982,10 @@ begin ba => open, joyA => unsigned(joyA_c64), joyB => unsigned(joyB_c64), + potA_x => potA_x, + potA_y => potA_y, + potB_x => potB_x, + potB_y => potB_y, serioclk => open, ces => ces, SIDclk => open, @@ -978,6 +1006,7 @@ begin pb_in => pb_in, pb_out => pb_out, flag2_n => flag2_n, + todclk => todclk, cia_mode => status(4), disk_num => open, c64rom_addr => c64rom_addr, @@ -987,6 +1016,39 @@ begin reset_key => reset_key ); + -- paddle pins - mouse or GS controller + potA_x <= '0' & std_logic_vector(mouse_x_pos)(6 downto 1) & '0' when mouse_en = '1' + else x"00" when joyA_c64(5) = '1' else x"FF"; + potA_y <= '0' & std_logic_vector(mouse_y_pos)(6 downto 1) & '0' when mouse_en = '1' + else x"00" when joyA_c64(6) = '1' else x"FF"; + potB_x <= '0' & std_logic_vector(mouse_x_pos)(6 downto 1) & '0' when mouse_en = '1' + else x"00" when joyB_c64(5) = '1' else x"FF"; + potB_y <= '0' & std_logic_vector(mouse_y_pos)(6 downto 1) & '0' when mouse_en = '1' + else x"00" when joyB_c64(6) = '1' else x"FF"; + + process(clk_c64, reset_n) + variable mov_x: signed(6 downto 0); + variable mov_y: signed(6 downto 0); + begin + if reset_n = '0' then + mouse_x_pos <= (others => '0'); + mouse_y_pos <= (others => '0'); + mouse_en <= '0'; + elsif rising_edge(clk_c64) then + if mouse_strobe = '1' then + mouse_en <= '1'; + -- due to limited resolution on the c64 side, limit the mouse movement speed + if mouse_x > 40 then mov_x:="0101000"; elsif mouse_x < -40 then mov_x:= "1011000"; else mov_x := mouse_x(6 downto 0); end if; + if mouse_y > 40 then mov_y:="0101000"; elsif mouse_y < -40 then mov_y:= "1011000"; else mov_y := mouse_y(6 downto 0); end if; + mouse_x_pos <= mouse_x_pos + mov_x; + mouse_y_pos <= mouse_y_pos + mov_y; + mouse_btns <= mouse_flags(1 downto 0); + elsif joya(7 downto 0) /= 0 or joyb(7 downto 0) /= 0 then + mouse_en <= '0'; + end if; + end if; + end process; + -- connect user port process (pa2_out, pb_out, joyC_c64, joyD_c64, UART_RX, status) begin @@ -1010,6 +1072,25 @@ begin end if; end process; + -- generate TOD clock from stable 32 MHz + process(clk32, reset_n) + begin + if reset_n = '0' then + todclk <= '0'; + toddiv <= (others => '0'); + elsif rising_edge(clk32) then + toddiv <= toddiv + 1; + if (ntsc_init_mode_d2 = '1' and toddiv = 266665 and toddiv3 = "00") or + (ntsc_init_mode_d2 = '1' and toddiv = 266666 and toddiv3 /= "00") or + toddiv = 319999 then + toddiv <= (others => '0'); + todclk <= not todclk; + toddiv3 <= toddiv3 + 1; + if toddiv3 = "10" then toddiv3 <= "00"; end if; + end if; + end if; + end process; + disk_readonly <= status(16); c64_iec_data_i <= c1541_iec_data_o; @@ -1019,12 +1100,12 @@ begin c1541_iec_data_i <= c64_iec_data_o; c1541_iec_clk_i <= c64_iec_clk_o; - process(c64_clk, reset_n) + process(clk_c64, reset_n) variable reset_cnt : integer range 0 to 32000000; begin if reset_n = '0' then reset_cnt := 100000; - elsif rising_edge(c64_clk) then + elsif rising_edge(clk_c64) then if reset_cnt /= 0 then reset_cnt := reset_cnt - 1; end if; @@ -1043,7 +1124,7 @@ begin clk32 => clk32, reset => c1541_reset, - c1541rom_clk => c64_clk, + c1541rom_clk => clk_c64, c1541rom_addr => ioctl_addr(13 downto 0), c1541rom_data => ioctl_data, c1541rom_wr => c1541rom_wr, @@ -1074,7 +1155,7 @@ begin comp_sync : entity work.composite_sync port map( - clk32 => c64_clk, + clk32 => clk_c64, hsync => hsync, vsync => vsync, ntsc => ntsc_init_mode, @@ -1091,9 +1172,9 @@ begin hq2x <= status(9) xor status(8); ce_pix_actual <= ce_4 when hq2x160='1' else ce_8; - process(c64_clk) + process(clk_c64) begin - if rising_edge(c64_clk) then + if rising_edge(clk_c64) then if((old_vsync = '0') and (vsync_out = '1')) then if(status(10 downto 8)="010") then hq2x160 <= '1'; diff --git a/cores/c64/rtl/mist/pll_c64.vhd b/cores/c64/rtl/mist/pll_c64.vhd index 509f190..2a1dd93 100644 --- a/cores/c64/rtl/mist/pll_c64.vhd +++ b/cores/c64/rtl/mist/pll_c64.vhd @@ -165,11 +165,11 @@ BEGIN altpll_component : altpll GENERIC MAP ( bandwidth_type => "AUTO", - clk0_divide_by => 6, + clk0_divide_by => 3, clk0_duty_cycle => 50, clk0_multiply_by => 7, clk0_phase_shift => "0", - clk1_divide_by => 3, + clk1_divide_by => 6, clk1_duty_cycle => 50, clk1_multiply_by => 7, clk1_phase_shift => "0", @@ -261,12 +261,12 @@ END SYN; -- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" -- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" -- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" --- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "6" --- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "3" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "3" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "6" -- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" -- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" --- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "31.500000" --- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "63.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "63.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "31.500000" -- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" -- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" -- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" @@ -294,8 +294,8 @@ END SYN; -- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "7" -- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "7" -- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" --- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "31.52000000" --- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "63.04000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "63.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "32.72700000" -- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" -- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" -- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" @@ -341,11 +341,11 @@ END SYN; -- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" -- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all -- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" --- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "6" +-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3" -- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" -- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "7" -- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" --- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "3" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "6" -- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" -- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "7" -- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" diff --git a/cores/c64/rtl/mist/pll_c64_ntsc.mif b/cores/c64/rtl/mist/pll_c64_ntsc.mif index b335402..fa6c77f 100644 --- a/cores/c64/rtl/mist/pll_c64_ntsc.mif +++ b/cores/c64/rtl/mist/pll_c64_ntsc.mif @@ -17,8 +17,8 @@ -- Device Part: - -- Device Speed Grade: 8 -- PLL Scan Chain: Fast PLL (144 bits) --- File Name: /home/gyuri/git/mist-board/cores/c64/rtl/mist/pll_c64_ntsc.mif --- Generated: Sun Feb 10 18:12:08 2019 +-- File Name: /home/gyurco/git/mist-board/cores/c64/rtl/mist/pll_c64_ntsc.mif +-- Generated: Mon Mar 18 13:52:51 2019 WIDTH=1; DEPTH=144; @@ -82,39 +82,39 @@ CONTENT BEGIN 52 : 0; 53 : 0; 54 : 0; -- clk0 counter: Bypass = 0 (1 bit(s)) - 55 : 0; -- clk0 counter: High Count = 8 (8 bit(s)) + 55 : 0; -- clk0 counter: High Count = 4 (8 bit(s)) 56 : 0; 57 : 0; 58 : 0; - 59 : 1; - 60 : 0; + 59 : 0; + 60 : 1; 61 : 0; 62 : 0; 63 : 0; -- clk0 counter: Odd Division = 0 (1 bit(s)) - 64 : 0; -- clk0 counter: Low Count = 8 (8 bit(s)) + 64 : 0; -- clk0 counter: Low Count = 4 (8 bit(s)) 65 : 0; 66 : 0; 67 : 0; - 68 : 1; - 69 : 0; + 68 : 0; + 69 : 1; 70 : 0; 71 : 0; 72 : 0; -- clk1 counter: Bypass = 0 (1 bit(s)) - 73 : 0; -- clk1 counter: High Count = 4 (8 bit(s)) + 73 : 0; -- clk1 counter: High Count = 8 (8 bit(s)) 74 : 0; 75 : 0; 76 : 0; - 77 : 0; - 78 : 1; + 77 : 1; + 78 : 0; 79 : 0; 80 : 0; 81 : 0; -- clk1 counter: Odd Division = 0 (1 bit(s)) - 82 : 0; -- clk1 counter: Low Count = 4 (8 bit(s)) + 82 : 0; -- clk1 counter: Low Count = 8 (8 bit(s)) 83 : 0; 84 : 0; 85 : 0; - 86 : 0; - 87 : 1; + 86 : 1; + 87 : 0; 88 : 0; 89 : 0; 90 : 1; -- clk2 counter: Bypass = 1 (1 bit(s)) diff --git a/cores/c64/rtl/mist/pll_c64_pal.mif b/cores/c64/rtl/mist/pll_c64_pal.mif index d0bc170..30c2edc 100644 --- a/cores/c64/rtl/mist/pll_c64_pal.mif +++ b/cores/c64/rtl/mist/pll_c64_pal.mif @@ -17,8 +17,8 @@ -- Device Part: - -- Device Speed Grade: 8 -- PLL Scan Chain: Fast PLL (144 bits) --- File Name: /home/gyuri/git/mist-board/cores/c64/rtl/mist/pll_c64_pal.mif --- Generated: Sun Feb 10 22:52:34 2019 +-- File Name: /home/gyurco/git/mist-board/cores/c64/rtl/mist/pll_c64_pal.mif +-- Generated: Mon Mar 18 13:55:59 2019 WIDTH=1; DEPTH=144; @@ -82,41 +82,41 @@ CONTENT BEGIN 52 : 1; 53 : 0; 54 : 0; -- clk0 counter: Bypass = 0 (1 bit(s)) - 55 : 0; -- clk0 counter: High Count = 9 (8 bit(s)) + 55 : 0; -- clk0 counter: High Count = 5 (8 bit(s)) 56 : 0; 57 : 0; 58 : 0; - 59 : 1; - 60 : 0; + 59 : 0; + 60 : 1; 61 : 0; 62 : 1; - 63 : 0; -- clk0 counter: Odd Division = 0 (1 bit(s)) - 64 : 0; -- clk0 counter: Low Count = 9 (8 bit(s)) + 63 : 1; -- clk0 counter: Odd Division = 1 (1 bit(s)) + 64 : 0; -- clk0 counter: Low Count = 4 (8 bit(s)) 65 : 0; 66 : 0; 67 : 0; - 68 : 1; - 69 : 0; + 68 : 0; + 69 : 1; 70 : 0; - 71 : 1; + 71 : 0; 72 : 0; -- clk1 counter: Bypass = 0 (1 bit(s)) - 73 : 0; -- clk1 counter: High Count = 5 (8 bit(s)) + 73 : 0; -- clk1 counter: High Count = 9 (8 bit(s)) 74 : 0; 75 : 0; 76 : 0; - 77 : 0; - 78 : 1; + 77 : 1; + 78 : 0; 79 : 0; 80 : 1; - 81 : 1; -- clk1 counter: Odd Division = 1 (1 bit(s)) - 82 : 0; -- clk1 counter: Low Count = 4 (8 bit(s)) + 81 : 0; -- clk1 counter: Odd Division = 0 (1 bit(s)) + 82 : 0; -- clk1 counter: Low Count = 9 (8 bit(s)) 83 : 0; 84 : 0; 85 : 0; - 86 : 0; - 87 : 1; + 86 : 1; + 87 : 0; 88 : 0; - 89 : 0; + 89 : 1; 90 : 1; -- clk2 counter: Bypass = 1 (1 bit(s)) 91 : 0; -- clk2 counter: High Count = 0 (8 bit(s)) 92 : 0; diff --git a/cores/c64/rtl/mist/sdram.v b/cores/c64/rtl/mist/sdram.v index f8497d5..321986e 100644 --- a/cores/c64/rtl/mist/sdram.v +++ b/cores/c64/rtl/mist/sdram.v @@ -23,8 +23,9 @@ module sdram ( // interface to the MT48LC16M16 chip - output [12:0] sd_addr, // 13 bit multiplexed address bus - output [1:0] sd_ba, // two banks + output reg [12:0] sd_addr, // 13 bit multiplexed address bus + inout reg [15:0] sd_data, + 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 @@ -34,8 +35,10 @@ module sdram ( input init, // init signal after FPGA config to initialize RAM input clk, // sdram is accessed at up to 128MHz -// input [15:0] addr, // 25 bit byte address - input [24:0] addr, // 25 bit byte address + input [24:0] addr, // 25 bit byte address + input [ 7:0] din, + output [ 7:0] dout, + input refresh, // refresh cycle input ce, // cpu/chipset access input we // cpu/chipset requests write @@ -56,8 +59,8 @@ localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, B // --------------------------------------------------------------------- localparam STATE_IDLE = 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 - 3'd1; // 4 command can be continued +localparam STATE_CMD_START = 3'd0; // state in which a new command can be started +localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY; // 2 command can be continued localparam STATE_LAST = 3'd7; // last state in cycle reg [2:0] q /* synthesis noprune */; @@ -104,17 +107,21 @@ localparam CMD_LOAD_MODE = 4'b0000; reg [3:0] sd_cmd; // current command sent to sd ram +assign dout = sd_data[7:0]; + // 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_data = we?{din, din}:16'bZZZZZZZZZZZZZZZZ; -// assign dout = sd_data[7:0]; +wire [12:0] reset_addr = (reset == 13)?13'b0010000000000:MODE; +wire [12:0] run_addr = (q == STATE_CMD_START)?addr[20:8]:{ 4'b0010, addr[23], addr[7:0]}; always @(posedge clk) begin - sd_cmd <= CMD_INHIBIT; + sd_cmd <= CMD_INHIBIT; + sd_addr <= (reset != 0)?reset_addr:run_addr; + sd_ba <= addr[22:21]; + sd_data <= 16'bZZZZZZZZZZZZZZZZ; if(reset != 0) begin if(q == STATE_IDLE) begin @@ -128,20 +135,9 @@ always @(posedge clk) begin end else if((q == STATE_CMD_CONT)&&(!refresh)) begin if(we) sd_cmd <= CMD_WRITE; else if(ce) sd_cmd <= CMD_READ; + if(we) sd_data <= {din, din}; end end end - -wire [12:0] reset_addr = (reset == 13)?13'b0010000000000:MODE; - -wire [12:0] run_addr = -// (q == STATE_CMD_START)?{ 5'b00000, addr[15:8]}:{ 5'b00100, addr[7:0]}; -//(q == STATE_CMD_START)?addr[21:9]:{ 4'b0010, addr[8:0]}; //possibly try this LCA 6mar17 - (q == STATE_CMD_START)?addr[20:8]:{ 4'b0010, addr[23], addr[7:0]}; - -assign sd_addr = (reset != 0)?reset_addr:run_addr; - -//assign sd_ba = 2'b00; -assign sd_ba = addr[22:21]; endmodule diff --git a/cores/c64/rtl/mist/user_io.v b/cores/c64/rtl/mist/user_io.v index 999c474..5b03cd1 100644 --- a/cores/c64/rtl/mist/user_io.v +++ b/cores/c64/rtl/mist/user_io.v @@ -63,12 +63,18 @@ module user_io #(parameter STRLEN=0, parameter PS2DIV=100) ( output reg img_mounted, //rising edge if a new image is mounted output reg [31:0] img_size, // size of image in bytes - // ps2 keyboard emulation + // ps2 keyboard/mouse emulation output ps2_kbd_clk, output reg ps2_kbd_data, output ps2_mouse_clk, output reg ps2_mouse_data, + // mouse data + output reg [8:0] mouse_x, + output reg [8:0] mouse_y, + output reg [7:0] mouse_flags, // YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn + output reg mouse_strobe, // mouse data is valid on mouse_strobe + // serial com port input [7:0] serial_data, input serial_strobe @@ -374,12 +380,17 @@ always @(posedge clk_sys) begin reg [7:0] acmd; reg [7:0] abyte_cnt; // counts bytes + reg [7:0] mouse_flags_r; + reg [7:0] mouse_x_r; + //synchronize between SPI and sys clock domains spi_receiver_strobeD <= spi_receiver_strobe_r; spi_receiver_strobe <= spi_receiver_strobeD; spi_transfer_endD <= spi_transfer_end_r; spi_transfer_end <= spi_transfer_endD; + mouse_strobe <= 0; + if (~spi_transfer_endD & spi_transfer_end) begin abyte_cnt <= 8'd0; end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin @@ -402,6 +413,15 @@ always @(posedge clk_sys) begin // store incoming ps2 mouse bytes ps2_mouse_fifo[ps2_mouse_wptr] <= spi_byte_in; ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + if (abyte_cnt == 1) mouse_flags_r <= spi_byte_in; + else if (abyte_cnt == 2) mouse_x_r <= spi_byte_in; + else if (abyte_cnt == 3) begin + // flags: YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn + mouse_flags <= mouse_flags_r; + mouse_x <= { mouse_flags_r[4], mouse_x_r }; + mouse_y <= { mouse_flags_r[5], spi_byte_in }; + mouse_strobe <= 1; + end end 8'h05: begin // store incoming ps2 keyboard bytes @@ -446,6 +466,7 @@ always @(posedge clk_sd) begin reg spi_transfer_end; reg spi_receiver_strobeD; reg spi_transfer_endD; + reg sd_wrD; reg [7:0] acmd; reg [7:0] abyte_cnt; // counts bytes @@ -460,9 +481,12 @@ always @(posedge clk_sd) begin if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; end - if(sd_din_strobe) begin - sd_din_strobe<= 0; - if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + sd_din_strobe<= 0; + sd_wrD <= sd_wr; + // fetch the first byte immediately after the write command seen + if (~sd_wrD & sd_wr) begin + sd_buff_addr <= 0; + sd_din_strobe <= 1; end img_mounted <= 0; @@ -473,7 +497,7 @@ always @(posedge clk_sd) begin sd_ack_conf <= 1'b0; sd_dout_strobe <= 1'b0; sd_din_strobe <= 1'b0; - sd_buff_addr<= 0; + sd_buff_addr <= 0; end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin if(~&abyte_cnt) @@ -482,9 +506,10 @@ always @(posedge clk_sd) begin if(abyte_cnt == 0) begin acmd <= spi_byte_in; - // fetch first byte when sectore FPGA->IO command has been seen - if(spi_byte_in == 8'h18) + if(spi_byte_in == 8'h18) begin sd_din_strobe <= 1'b1; + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + end if((spi_byte_in == 8'h17) || (spi_byte_in == 8'h18)) sd_ack <= 1'b1; @@ -500,7 +525,10 @@ always @(posedge clk_sd) begin end // send sector FPGA -> IO - 8'h18: sd_din_strobe <= 1'b1; + 8'h18: begin + sd_din_strobe <= 1'b1; + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + end // send SD config IO -> FPGA 8'h19: begin diff --git a/cores/c64/rtl/mos6526.v b/cores/c64/rtl/mos6526.v index a51dc63..3543490 100644 --- a/cores/c64/rtl/mos6526.v +++ b/cores/c64/rtl/mos6526.v @@ -2,6 +2,7 @@ // by Rayne // Timers & Interrupts are rewritten by slingshot // Passes all Lorenz CIA Timer tests +// Passes all "new" CIA tests from VICE, except dd0dtest module mos6526 ( input wire mode, // 0 - 6526 "old", 1 - 8521 "new" @@ -215,7 +216,11 @@ always @(posedge clk) begin if (wr) case (rs) - 4'h4: ta_lo <= db_in; + 4'h4: + begin + ta_lo <= db_in; + if (timerAoverflow) timer_a <= {ta_hi, db_in}; + end 4'h5: begin ta_hi <= db_in; @@ -281,7 +286,11 @@ always @(posedge clk) begin if (wr) case (rs) - 4'h6: tb_lo <= db_in; + 4'h6: + begin + tb_lo <= db_in; + if (timerBoverflow) timer_b <= {tb_hi, db_in}; + end 4'h7: begin tb_hi <= db_in; diff --git a/cores/gameboy/gb.qsf b/cores/gameboy/gb.qsf index 1251020..de2abac 100644 --- a/cores/gameboy/gb.qsf +++ b/cores/gameboy/gb.qsf @@ -138,6 +138,123 @@ set_location_assignment PIN_59 -to SDRAM_nCS set_location_assignment PIN_33 -to SDRAM_CKE set_location_assignment PIN_43 -to SDRAM_CLK +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[12] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[11] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[10] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[9] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[8] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[7] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[6] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[5] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[4] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[3] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[2] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[15] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[14] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[13] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[12] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[11] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[10] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[9] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[8] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[7] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[6] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[5] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[4] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[3] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[2] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[15] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[14] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[13] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[12] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[11] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[10] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[9] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[8] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[7] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[6] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[5] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[4] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[3] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[2] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[1] +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[0] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[15] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[14] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[13] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[12] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[11] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[10] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[9] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[8] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[7] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[6] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[5] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[4] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[3] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[2] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[1] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[0] + +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[2] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[3] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[4] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[5] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[6] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[7] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[8] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[9] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[10] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[11] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[12] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[13] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[14] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[15] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[0] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[1] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to LED +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R set_global_assignment -name ENABLE_SIGNALTAP OFF set_global_assignment -name USE_SIGNALTAP_FILE output_files/clk.stp @@ -154,7 +271,6 @@ set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top -set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_* set_global_assignment -name VERILOG_INPUT_VERSION VERILOG_2001 set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON diff --git a/cores/gameboy/gb.v b/cores/gameboy/gb.v index 91fa300..aa3d3e7 100644 --- a/cores/gameboy/gb.v +++ b/cores/gameboy/gb.v @@ -115,11 +115,11 @@ wire [7:0] cpu_di = sel_sc?sc_r: // serial transfer control register sel_timer?timer_do: // timer registers sel_video_reg?video_do: // video registers - sel_video_oam?video_do: // video object attribute memory + (sel_video_oam&&!(lcd_mode==3 || lcd_mode==2))?video_do: // video object attribute memory sel_audio?audio_do: // audio registers sel_rom?rom_do: // boot rom + cartridge rom sel_cram?rom_do: // cartridge ram - sel_vram?(isGBC&&vram_bank)?vram1_do:vram_do: // vram (GBC bank 0+1) + (sel_vram&&lcd_mode!=3)?(isGBC&&vram_bank)?vram1_do:vram_do: // vram (GBC bank 0+1) sel_zpram?zpram_do: // zero page ram sel_iram?iram_do: // internal ram sel_ie?{3'b000, ie_r}: // interrupt enable register @@ -131,7 +131,7 @@ wire cpu_iorq_n; wire cpu_m1_n; wire cpu_mreq_n; -wire cpu_clken = isGBC ? !hdma_rd:1'b1; //when hdma is enabled stop CPU (GBC) +wire cpu_clken = isGBC ? !hdma_active:1'b1; //when hdma is enabled stop CPU (GBC) wire cpu_stop; GBse cpu ( @@ -278,8 +278,8 @@ wire [7:0] irq_vec = if_r[4]&&ie_r[4]?8'h60: // input 8'h55; -wire vs = (lcd_mode == 2'b01); -reg vsD, vsD2; +//wire vs = (lcd_mode == 2'b01); +//reg vsD, vsD2; reg [7:0] inputD, inputD2; // irq is low when an enable irq is active @@ -296,9 +296,9 @@ always @(negedge clk_cpu) begin //negedge to trigger interrupt earlier end // rising edge on vs - vsD <= vs; - vsD2 <= vsD; - if(vsD && !vsD2) if_r[0] <= 1'b1; +// vsD <= vs; +// vsD2 <= vsD; + if(vblank_irq) if_r[0] <= 1'b1; // video irq already is a 1 clock event if(video_irq) if_r[1] <= 1'b1; @@ -359,7 +359,7 @@ timer timer ( // -------------------------------------------------------------------- // cpu tries to read or write the lcd controller registers -wire video_irq; +wire video_irq,vblank_irq; wire [7:0] video_do; wire [12:0] video_addr; wire [15:0] dma_addr; @@ -375,6 +375,8 @@ video video ( .irq ( video_irq ), + .vblank_irq ( vblank_irq ), + .cpu_sel_reg ( sel_video_reg ), .cpu_sel_oam ( sel_video_oam ), @@ -402,7 +404,7 @@ video video ( ); // total 8k/16k (CGB) vram from $8000 to $9fff -wire cpu_wr_vram = sel_vram && !cpu_wr_n; +wire cpu_wr_vram = sel_vram && !cpu_wr_n && lcd_mode!=3; reg vram_bank; //0-1 FF4F - VBK @@ -453,10 +455,12 @@ wire [15:0] hdma_source_addr; wire [15:0] hdma_target_addr; wire [7:0] hdma_do; wire hdma_rd; +wire hdma_active; hdma hdma( .reset ( reset ), .clk ( clk2x ), + .speed ( cpu_speed ), // cpu register interface .sel_reg ( sel_hdma ), @@ -469,6 +473,7 @@ hdma hdma( // dma connection .hdma_rd ( hdma_rd ), + .hdma_active ( hdma_active ), .hdma_source_addr ( hdma_source_addr ), .hdma_target_addr ( hdma_target_addr ) diff --git a/cores/gameboy/hdma.v b/cores/gameboy/hdma.v index aaac02d..8a86755 100644 --- a/cores/gameboy/hdma.v +++ b/cores/gameboy/hdma.v @@ -1,331 +1,360 @@ -module hdma( - input reset, - input clk, // 8 Mhz cpu clock - - // cpu register interface - input sel_reg, - input [3:0] addr, - input wr, - output [7:0] dout, - input [7:0] din, - - input [1:0] lcd_mode, - - // dma connection - output hdma_rd, - output [15:0] hdma_source_addr, - output [15:0] hdma_target_addr - +module hdma( + input reset, + input clk, // 8 Mhz cpu clock + input speed, // cpu speed mode use for initial delay + + // cpu register interface + input sel_reg, + input [3:0] addr, + input wr, + output [7:0] dout, + input [7:0] din, + + input [1:0] lcd_mode, + + // dma connection + output reg hdma_rd, + output reg hdma_active, + output [15:0] hdma_source_addr, + output [15:0] hdma_target_addr + ); -//ff51-ff55 HDMA1-5 (GBC) -reg [7:0] hdma_source_h; // ff51 -reg [3:0] hdma_source_l; // ff52 only top 4 bits used -reg [4:0] hdma_target_h; // ff53 only lowest 5 bits used -reg [3:0] hdma_target_l; // ff54 only top 4 bits used -reg hdma_mode; // ff55 bit 7 - 1=General Purpose DMA 0=H-Blank DMA -reg hdma_enabled; // ff55 !bit 7 when read -reg [7:0] hdma_length; // ff55 bit 6:0 - dma transfer length (hdma_length+1)*16 bytes -reg hdma_active; - -// it takes about 8us to transfer a block of 16 bytes. -> 500ns per byte -> 2Mhz -// 32 cycles in Normal Speed Mode, and 64 'fast' cycles in Double Speed Mode -reg [13:0] hdma_cnt; -reg [5:0] hdma_16byte_cnt; //16bytes*4 - -assign hdma_rd = hdma_active; -assign hdma_source_addr = { hdma_source_h,hdma_source_l,4'd0} + hdma_cnt[13:2]; -assign hdma_target_addr = { 3'b100,hdma_target_h,hdma_target_l,4'd0} + hdma_cnt[13:2]; - -reg [1:0] hdma_state; -parameter active=2'd0,blocksent=2'd1,wait_h=2'd2; - -always @(posedge clk) begin - if(reset) begin - hdma_active <= 1'b0; - hdma_state <= wait_h; - hdma_enabled <= 1'b0; - hdma_source_h <= 8'hFF; - hdma_source_l <= 4'hF; - hdma_target_h <= 5'h1F; - hdma_target_l <= 4'hF; - end else begin - if(sel_reg && wr) begin - - case (addr) - 4'd1: hdma_source_h <= din; - 4'd2: hdma_source_l <= din[7:4]; - 4'd3: hdma_target_h <= din[4:0]; - 4'd4: hdma_target_l <= din[7:4]; - - - // writing the hdma register engages the dma engine - 4'h5: begin - if (hdma_mode == 1 && hdma_enabled && !din[7]) begin //terminate an active H-Blank transfer by writing zero to Bit 7 of FF55 - hdma_state <= wait_h; - hdma_active <= 1'b0; - hdma_enabled <= 1'b0; - end else begin //normal trigger - hdma_enabled <= 1'b1; - hdma_mode <= din[7]; - hdma_length <= {1'b0,din[6:0]} + 8'd1; - hdma_cnt <= 14'd0; - hdma_16byte_cnt <= 6'h3f; - if (din[7] == 1) hdma_state <= wait_h; - end - end - endcase - end - - if (hdma_enabled) begin - if(hdma_mode==0) begin //mode 0 GDMA do the transfer in one go - if(hdma_length != 0) begin - hdma_active <= 1'b1; - hdma_cnt <= hdma_cnt + 1'd1; - hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1; - if (!hdma_16byte_cnt) begin - hdma_length <= hdma_length - 1'd1; - if (hdma_length == 1) begin - hdma_active <= 1'b0; - hdma_enabled <= 1'b0; - hdma_length <= 8'h80; //7f+1 - end - end - end - - end else begin //mode 1 HDMA transfer 1 block (16bytes) in each H-Blank only - case (hdma_state) - - wait_h: begin - if (lcd_mode == 2'b00 ) // Mode 00: h-blank +localparam DELAY_SINGLE = 5'd10; +localparam DELAY_DOUBLE = DELAY_SINGLE/5'd2; + +//ff51-ff55 HDMA1-5 (GBC) +reg [7:0] hdma_source_h; // ff51 +reg [3:0] hdma_source_l; // ff52 only top 4 bits used +reg [4:0] hdma_target_h; // ff53 only lowest 5 bits used +reg [3:0] hdma_target_l; // ff54 only top 4 bits used +reg hdma_mode; // ff55 bit 7 - 1=General Purpose DMA 0=H-Blank DMA +reg hdma_enabled; // ff55 !bit 7 when read +reg [7:0] hdma_length; // ff55 bit 6:0 - dma transfer length (hdma_length+1)*16 bytes + +// it takes about 8us to transfer a block of 16 bytes. -> 500ns per byte -> 2Mhz +// 32 cycles in Normal Speed Mode, and 64 'fast' cycles in Double Speed Mode +reg [13:0] hdma_cnt; +reg [5:0] hdma_16byte_cnt; //16bytes*4 + +//assign hdma_rd = hdma_active; +assign hdma_source_addr = { hdma_source_h,hdma_source_l,4'd0} + hdma_cnt[13:2]; +assign hdma_target_addr = { 3'b100,hdma_target_h,hdma_target_l,4'd0} + hdma_cnt[13:2]; + +reg [4:0] dma_delay; + +reg [1:0] hdma_state; +parameter active=2'd0,blocksent=2'd1,wait_h=2'd2; + +always @(posedge clk) begin + if(reset) begin + hdma_active <= 1'b0; + hdma_state <= wait_h; + hdma_enabled <= 1'b0; + hdma_source_h <= 8'hFF; + hdma_source_l <= 4'hF; + hdma_target_h <= 5'h1F; + hdma_target_l <= 4'hF; + dma_delay <= 5'd0; + end else begin + if(sel_reg && wr) begin + + case (addr) + 4'd1: hdma_source_h <= din; + 4'd2: hdma_source_l <= din[7:4]; + 4'd3: hdma_target_h <= din[4:0]; + 4'd4: hdma_target_l <= din[7:4]; + + + // writing the hdma register engages the dma engine + 4'h5: begin + if (hdma_mode == 1 && hdma_enabled && !din[7]) begin //terminate an active H-Blank transfer by writing zero to Bit 7 of FF55 + hdma_state <= wait_h; + hdma_active <= 1'b0; + hdma_rd <= 1'b0; + hdma_enabled <= 1'b0; + end else begin //normal trigger + hdma_enabled <= 1'b1; + hdma_mode <= din[7]; + dma_delay <= speed?DELAY_DOUBLE:DELAY_SINGLE; + hdma_length <= {1'b0,din[6:0]} + 8'd1; + hdma_cnt <= 14'd0; + hdma_16byte_cnt <= 6'h3f; + if (din[7] == 1) hdma_state <= wait_h; + end + end + endcase + end + + if (hdma_enabled) begin + if(hdma_mode==0) begin //mode 0 GDMA do the transfer in one go after inital delay + hdma_active <= 1'b1; + if (dma_delay>0) begin + dma_delay <= dma_delay - 5'd1; + end else begin + if(hdma_length != 0) begin + hdma_rd <= 1'b1; + hdma_cnt <= hdma_cnt + 1'd1; + hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1; + if (!hdma_16byte_cnt) begin + hdma_length <= hdma_length - 1'd1; + if (hdma_length == 1) begin + hdma_active <= 1'b0; + hdma_rd <= 1'b0; + hdma_enabled <= 1'b0; + hdma_length <= 8'h80; //7f+1 + end + end + end + end + + end else begin //mode 1 HDMA transfer 1 block (16bytes) in each H-Blank only + case (hdma_state) + + wait_h: begin + if (lcd_mode == 2'b00 ) begin // Mode 00: h-blank + dma_delay <= speed?DELAY_DOUBLE:DELAY_SINGLE; hdma_state <= active; - hdma_16byte_cnt <= 6'h3f; - hdma_active <= 1'b0; - end - - blocksent: begin - if (hdma_length == 0) begin //check if finished - hdma_enabled <= 1'b0; - hdma_length <= 8'h80; //7f+1 - end - if (lcd_mode == 2'b11) // wait for mode 3, mode before h-blank - hdma_state <= wait_h; - end - - active: begin + end + hdma_16byte_cnt <= 6'h3f; + hdma_active <= 1'b0; + hdma_rd <= 1'b0; + end + + blocksent: begin + if (hdma_length == 0) begin //check if finished + hdma_enabled <= 1'b0; + hdma_length <= 8'h80; //7f+1 + end + if (lcd_mode == 2'b11) // wait for mode 3, mode before h-blank + hdma_state <= wait_h; + end + + active: begin if(hdma_length != 0) begin - hdma_active <= 1'b1; - hdma_cnt <= hdma_cnt + 1'd1; - hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1; - if (!hdma_16byte_cnt) begin - hdma_length <= hdma_length - 1'd1; - hdma_state <= blocksent; - hdma_active <= 1'b0; - end - end else begin - hdma_active <= 1'b0; - hdma_enabled <= 1'b0; - hdma_length <= 8'h80; //7f+1 - end - end - endcase - end - end - end -end - - -wire [7:0] length_m1 = hdma_length - 8'd1; - -assign dout = sel_reg? - (addr==4'd5)?hdma_enabled?{1'b0,length_m1[6:0]}: - {1'b1,length_m1[6:0]}: - 8'hFF: - 8'hFF; - -endmodule - -`timescale 1 ns/100 ps // time-unit = 1 ns, precision = 100 ps - -module hdma_tb; - - // duration for each bit = 125 * timescale = 125 * 1 ns = 125ns // 8MHz - localparam period = 125; - - reg reset = 1'd1; - reg clk = 1'd0; - - // cpu register interface - reg sel_reg = 1'd0; - reg [3:0] addr = 4'd0; - reg wr = 1'd0; - wire [7:0] dout; - reg [7:0] din = 8'd0; - - reg [1:0] lcd_mode = 2'd0; - - // dma connection - wire hdma_rd; - wire [15:0] hdma_source_addr; - wire [15:0] hdma_target_addr; - - - - hdma hdma( - .reset ( reset ), - .clk ( clk ), - - // cpu register interface - .sel_reg ( sel_reg ), - .addr ( addr ), - .wr ( wr ), - .dout ( dout ), - .din ( din ), - - .lcd_mode ( lcd_mode ), - - // dma connection - .hdma_rd ( hdma_rd ), - .hdma_source_addr ( hdma_source_addr ), - .hdma_target_addr ( hdma_target_addr ) - - ); - - always #62 clk <= !clk; - initial begin - reset <= 1'b0; - sel_reg <= 1'b1; - addr <= 4'd4; - - #1000 - - sel_reg <= 1'b1; - addr <= 4'd1; // source h - din <= 8'h20; - wr <= 1'd1; - - #period - wr <= 1'd0; - - #period - - sel_reg <= 1'b1; - addr <= 4'd2; // source l - din <= 8'h40; - wr <= 1'd1; - - #period - wr <= 1'd0; - - #period - - sel_reg <= 1'b1; - addr <= 4'd3; // target h - din <= 8'h82; - wr <= 1'd1; - #period - wr <= 1'd0; - - #period - - sel_reg <= 1'b1; - addr <= 4'd4; // target l - din <= 8'h00; - wr <= 1'd1; - - #period - wr <= 1'd0; - - #period - $display("GDMA"); - sel_reg <= 1'b1; - addr <= 4'd5; // trigger GDMA with length - din <= 8'h01; // 20h bytes - wr <= 1'd1; - #period - wr <= 1'd0; - - #8000 - - lcd_mode <= 2'd1; - #2000 - - lcd_mode <= 2'd0; - #8000 - - $display("HDMA"); - sel_reg <= 1'b1; - addr <= 4'd5; // trigger HDMA with length - din <= 8'h82; // 30h bytes - wr <= 1'd1; - - #period - wr <= 1'd0; - - #16000 - - lcd_mode <= 2'd2; - #2000 - - lcd_mode <= 2'd3; - #2000 - - lcd_mode <= 2'd0; - #16000 - - lcd_mode <= 2'd2; - #2000 - - lcd_mode <= 2'd3; - #2000 - - lcd_mode <= 2'd0; - #16000 - - sel_reg <= 1'b1; - addr <= 4'd5; - $display("Check FF55"); - - #1000 - - $display("HDMA with cancel"); - sel_reg <= 1'b1; - addr <= 4'd5; // trigger HDMA with length - din <= 8'h82; // 30h bytes - wr <= 1'd1; - - #period - wr <= 1'd0; - - #16000 - - lcd_mode <= 2'd2; - #2000 - - lcd_mode <= 2'd3; - #2000 - - $display("canceling"); - sel_reg <= 1'b1; - addr <= 4'd5; // trigger HDMA with length - din <= 8'h00; // stop - wr <= 1'd1; - - #period - wr <= 1'd0; - - #16000 - - sel_reg <= 1'b1; - addr <= 4'd5; - $display("Check FF55"); - - lcd_mode <= 2'd2; - #2000 - - lcd_mode <= 2'd3; - #2000 - $display("Test Complete"); - end - + hdma_active <= 1'b1; + if (dma_delay>0) begin + dma_delay <= dma_delay - 5'd1; + end else begin + hdma_rd <= 1'b1; + hdma_cnt <= hdma_cnt + 1'd1; + hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1; + if (!hdma_16byte_cnt) begin + hdma_length <= hdma_length - 1'd1; + hdma_state <= blocksent; + hdma_active <= 1'b0; + hdma_rd <= 1'b0; + end + end + end else begin + hdma_active <= 1'b0; + hdma_rd <= 1'b0; + hdma_enabled <= 1'b0; + hdma_length <= 8'h80; //7f+1 + end + end + endcase + end + end + end +end + + +wire [7:0] length_m1 = hdma_length - 8'd1; + +assign dout = sel_reg? + (addr==4'd5)?hdma_enabled?{1'b0,length_m1[6:0]}: + {1'b1,length_m1[6:0]}: + 8'hFF: + 8'hFF; + +endmodule + +`timescale 1 ns/100 ps // time-unit = 1 ns, precision = 100 ps + +module hdma_tb; + + // duration for each bit = 125 * timescale = 125 * 1 ns = 125ns // 8MHz + localparam period = 125; + + reg reset = 1'd1; + reg clk = 1'd0; + reg speed = 1'b0; + + // cpu register interface + reg sel_reg = 1'd0; + reg [3:0] addr = 4'd0; + reg wr = 1'd0; + wire [7:0] dout; + reg [7:0] din = 8'd0; + + reg [1:0] lcd_mode = 2'd0; + + // dma connection + wire hdma_rd; + wire hdma_active; + wire [15:0] hdma_source_addr; + wire [15:0] hdma_target_addr; + + + + hdma hdma( + .reset ( reset ), + .clk ( clk ), + .speed ( speed ), + + // cpu register interface + .sel_reg ( sel_reg ), + .addr ( addr ), + .wr ( wr ), + .dout ( dout ), + .din ( din ), + + .lcd_mode ( lcd_mode ), + + // dma connection + .hdma_rd ( hdma_rd ), + .hdma_active ( hdma_active ), + .hdma_source_addr ( hdma_source_addr ), + .hdma_target_addr ( hdma_target_addr ) + + ); + + always #62 clk <= !clk; + initial begin + reset <= 1'b0; + sel_reg <= 1'b1; + addr <= 4'd4; + + #1000 + + sel_reg <= 1'b1; + addr <= 4'd1; // source h + din <= 8'h20; + wr <= 1'd1; + + #period + wr <= 1'd0; + + #period + + sel_reg <= 1'b1; + addr <= 4'd2; // source l + din <= 8'h40; + wr <= 1'd1; + + #period + wr <= 1'd0; + + #period + + sel_reg <= 1'b1; + addr <= 4'd3; // target h + din <= 8'h82; + wr <= 1'd1; + #period + wr <= 1'd0; + + #period + + sel_reg <= 1'b1; + addr <= 4'd4; // target l + din <= 8'h00; + wr <= 1'd1; + + #period + wr <= 1'd0; + + #period + $display("GDMA"); + sel_reg <= 1'b1; + addr <= 4'd5; // trigger GDMA with length + din <= 8'h01; // 20h bytes + wr <= 1'd1; + #period + wr <= 1'd0; + + #8000 + + lcd_mode <= 2'd1; + #2000 + + lcd_mode <= 2'd0; + #8000 + + $display("HDMA"); + sel_reg <= 1'b1; + addr <= 4'd5; // trigger HDMA with length + din <= 8'h82; // 30h bytes + wr <= 1'd1; + + #period + wr <= 1'd0; + + #16000 + + lcd_mode <= 2'd2; + #2000 + + lcd_mode <= 2'd3; + #2000 + + lcd_mode <= 2'd0; + #16000 + + lcd_mode <= 2'd2; + #2000 + + lcd_mode <= 2'd3; + #2000 + + lcd_mode <= 2'd0; + #16000 + + sel_reg <= 1'b1; + addr <= 4'd5; + $display("Check FF55"); + + #1000 + + $display("HDMA with cancel"); + sel_reg <= 1'b1; + addr <= 4'd5; // trigger HDMA with length + din <= 8'h82; // 30h bytes + wr <= 1'd1; + + #period + wr <= 1'd0; + + #16000 + + lcd_mode <= 2'd2; + #2000 + + lcd_mode <= 2'd3; + #2000 + + $display("canceling"); + sel_reg <= 1'b1; + addr <= 4'd5; // trigger HDMA with length + din <= 8'h00; // stop + wr <= 1'd1; + + #period + wr <= 1'd0; + + #16000 + + sel_reg <= 1'b1; + addr <= 4'd5; + $display("Check FF55"); + + lcd_mode <= 2'd2; + #2000 + + lcd_mode <= 2'd3; + #2000 + $display("Test Complete"); + end + endmodule \ No newline at end of file diff --git a/cores/gameboy/t80/GBse.vhd b/cores/gameboy/t80/GBse.vhd index 2b6fa6b..4aaab04 100644 --- a/cores/gameboy/t80/GBse.vhd +++ b/cores/gameboy/t80/GBse.vhd @@ -74,7 +74,7 @@ use work.T80_Pack.all; entity GBse is generic( - T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle ); port( diff --git a/cores/gameboy/t80/T80_ALU.vhd b/cores/gameboy/t80/T80_ALU.vhd index 811a944..8d5685c 100644 --- a/cores/gameboy/t80/T80_ALU.vhd +++ b/cores/gameboy/t80/T80_ALU.vhd @@ -155,7 +155,7 @@ begin end if; end process; - process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, Rot_Akku) variable Q_t : std_logic_vector(7 downto 0); variable DAA_Q : unsigned(8 downto 0); begin diff --git a/cores/gameboy/t80/T80_MCode.vhd b/cores/gameboy/t80/T80_MCode.vhd index 60bfa01..8e85dbd 100644 --- a/cores/gameboy/t80/T80_MCode.vhd +++ b/cores/gameboy/t80/T80_MCode.vhd @@ -517,8 +517,10 @@ begin end if; when "11111001" => -- LD SP,HL - TStates <= "110"; - LDSPHL <= '1'; + MCycles <= "010"; + if MCycle = "010" then + LDSPHL <= '1'; + end if; when "11000101"|"11010101"|"11100101"|"11110101" => -- PUSH qq if Mode = 3 then @@ -845,34 +847,50 @@ begin end case; elsif IntCycle = '1' then -- INT (IM 2) - if mode = 3 then - MCycles <= "011"; - else - MCycles <= "101"; - end if; - case to_integer(unsigned(MCycle)) is - when 1 => - LDZ <= '1'; - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - TStates <= "100"; - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - TStates <= "100"; - Write <= '1'; - when 4 => - Inc_PC <= '1'; - LDZ <= '1'; - when 5 => - Jump <= '1'; - when others => null; - end case; + if mode = 3 then + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "110"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + when others => null; + end case; + else + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + end if; else -- NOP end if; @@ -1048,7 +1066,11 @@ begin end case; else -- JP cc,nn - MCycles <= "011"; + if Mode = 3 then + MCycles <= "100"; + else + MCycles <= "011"; + end if; case to_integer(unsigned(MCycle)) is when 2 => Inc_PC <= '1'; @@ -1057,6 +1079,8 @@ begin Inc_PC <= '1'; if is_cc_true(F, to_bitvector(IR(5 downto 3))) then Jump <= '1'; + else + MCycles <= "011"; end if; when others => null; end case; @@ -1364,25 +1388,41 @@ begin -- RST p if Mode = 3 then MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 3 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 4 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; else MCycles <= "011"; - end if; - case to_integer(unsigned(MCycle)) is - when 1 => - TStates <= "101"; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1101"; - when 2 => - Write <= '1'; - IncDec_16 <= "1111"; - Set_Addr_To <= aSP; - Set_BusB_To <= "1100"; - when 3 => - Write <= '1'; - RstP <= '1'; - when others => null; - end case; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + end if; -- INPUT AND OUTPUT GROUP when "11011011" => diff --git a/cores/gameboy/timer.v b/cores/gameboy/timer.v index 65d5510..eab0ac3 100644 --- a/cores/gameboy/timer.v +++ b/cores/gameboy/timer.v @@ -49,10 +49,10 @@ wire resetdiv = cpu_sel && cpu_wr && (cpu_addr == 2'b00); //resetdiv also resets reg [9:0] clk_div; always @(posedge clk or posedge resetdiv) if(resetdiv) - clk_div <= 10'd6; + clk_div <= 10'd2; else if (reset) - clk_div <= 10'd6; + clk_div <= 10'd8; else clk_div <= clk_div + 10'd1; diff --git a/cores/gameboy/video.v b/cores/gameboy/video.v index 76e2ff5..5ec2852 100644 --- a/cores/gameboy/video.v +++ b/cores/gameboy/video.v @@ -38,6 +38,7 @@ module video ( output lcd_clkena, output [14:0] lcd_data, output reg irq, + output reg vblank_irq, // vram connection output [1:0] mode, @@ -57,6 +58,7 @@ module video ( localparam STAGE2 = 9'd250; // oam + disp + pause localparam OAM_LEN = 80; localparam OAM_LEN16 = OAM_LEN/16; +localparam MODE3_OFFSET = 8'd16; wire sprite_pixel_active; wire [1:0] sprite_pixel_data; @@ -108,7 +110,7 @@ sprites sprites ( // give dma access to oam wire [7:0] oam_addr = dma_active?dma_addr[7:0]:cpu_addr; -wire oam_wr = dma_active?(dma_cnt[1:0] == 2):(cpu_wr && cpu_sel_oam); +wire oam_wr = dma_active?(dma_cnt[1:0] == 2):(cpu_wr && cpu_sel_oam && !(mode==3 || mode==2)); wire [7:0] oam_di = dma_active?dma_data:cpu_di; @@ -140,6 +142,7 @@ wire [7:0] ly = v_cnt; // ff45 line counter compare wire lyc_match = (ly == lyc); reg [7:0] lyc; +reg lyc_changed=0; reg [7:0] bgp; reg [7:0] obp0; @@ -195,12 +198,14 @@ end // ------------------------------- IRQs ------------------------------- // -------------------------------------------------------------------- -always @(posedge clk_reg) begin //TODO: have to check if this is correct +always @(posedge clk_reg) begin irq <= 1'b0; + vblank_irq <= 1'b0; - //TODO: investigate and fix timing of lyc=ly - // lyc=ly coincidence - if(stat[6] && (h_cnt == 1) && lyc_match) + if(stat[6] && h_cnt == 0 && lyc_match) + irq <= 1'b1; + + if(stat[6] && lyc_changed == 1 && h_cnt > 0 && lyc_match) irq <= 1'b1; // begin of oam phase @@ -208,8 +213,11 @@ always @(posedge clk_reg) begin //TODO: have to check if this is correct irq <= 1'b1; // begin of vblank - if(stat[4] && (h_cnt == 455) && (v_cnt == 143)) - irq <= 1'b1; + if((h_cnt == 455) && (v_cnt == 143)) begin + if (stat[4]) + irq <= 1'b1; + vblank_irq <= 1'b1; + end // begin of hblank if(stat[3] && (h_cnt == OAM_LEN + 160 + hextra)) @@ -243,6 +251,7 @@ always @(posedge clk_reg) begin end end else begin + lyc_changed<=0; if(cpu_sel_reg && cpu_wr) begin case(cpu_addr) 8'h40: lcdc <= cpu_di; @@ -250,7 +259,10 @@ always @(posedge clk_reg) begin 8'h42: scy <= cpu_di; 8'h43: scx <= cpu_di; // a write to 4 is supposed to reset the v_cnt - 8'h45: lyc <= cpu_di; + 8'h45: begin + lyc <= cpu_di; + lyc_changed<=1; + end 8'h46: dma <= cpu_di; 8'h47: bgp <= cpu_di; 8'h48: obp0 <= cpu_di; @@ -264,20 +276,23 @@ always @(posedge clk_reg) begin bgpi_ai <= cpu_di[7]; end 8'h69: begin - bgpd[bgpi] <= cpu_di; - if (bgpi_ai) - bgpi <= bgpi + 6'h1; + if (mode != 3) begin + bgpd[bgpi] <= cpu_di; + if (bgpi_ai) + bgpi <= bgpi + 6'h1; + end end 8'h6A: begin obpi <= cpu_di[5:0]; obpi_ai <= cpu_di[7]; end 8'h6B: begin - obpd[obpi] <= cpu_di; - if (obpi_ai) - obpi <= obpi + 6'h1; + if (mode != 3) begin + obpd[obpi] <= cpu_di; + if (obpi_ai) + obpi <= obpi + 6'h1; + end end - endcase end end @@ -299,9 +314,9 @@ assign cpu_do = (cpu_addr == 8'h4b)?wx: isGBC? (cpu_addr == 8'h68)?{bgpi_ai,1'd0,bgpi}: - (cpu_addr == 8'h69)?bgpd[bgpi]: + (cpu_addr == 8'h69 && mode != 3)?bgpd[bgpi]: (cpu_addr == 8'h6a)?{obpi_ai,1'd0,obpi}: - (cpu_addr == 8'h6b)?obpd[obpi]: + (cpu_addr == 8'h6b && mode != 3)?obpd[obpi]: 8'hff: 8'hff; @@ -351,14 +366,25 @@ wire [14:0] sprite_pix = isGBC?{obpd[sprite_palette_index+1][6:0],obpd[sprite_pa // - there's a sprite at the current position // - the sprites prioroty bit is 0, or // - the sprites priority is 1 and the backrgound color is 00 -// - GBC : BG priority is 0 +// - GBC : BG priority is 0 +// - GBC : BG priority is 1 and the backrgound color is 00 wire bg_piority = isGBC&&stage2_bgp_buffer_pix[stage2_rptr][3]; - -wire sprite_pixel_visible = - sprite_pixel_active && lcdc_spr_ena && (~bg_piority) && - ((!sprite_pixel_prio) || (stage2_buffer[stage2_rptr] == 2'b00)); - +wire [1:0] bg_color = stage2_buffer[stage2_rptr]; +reg sprite_pixel_visible; + +always @(*) begin + sprite_pixel_visible = 1'b0; + + if (sprite_pixel_active && lcdc_spr_ena) begin // pixel active and sprites enabled + if (bg_color == 2'b00) // background color = 0 + sprite_pixel_visible = 1'b1; + else if (!bg_piority && !sprite_pixel_prio) // sprite has priority enabled and background priority disabled + sprite_pixel_visible = 1'b1; + + end +end + always @(posedge clk) begin if(h_cnt == 455) begin stage2_wptr <= 8'h00; @@ -462,9 +488,9 @@ wire vblank = (v_cnt >= 144); // x scroll & 7 needs one more memory read per line reg [1:0] hextra_tiles; -wire [7:0] hextra = { 3'b000, hextra_tiles, 3'b000 }; +wire [7:0] hextra = { 3'b000, hextra_tiles, 3'b000 }+MODE3_OFFSET; wire hblank = ((h_cnt < OAM_LEN) || (h_cnt >= 160+OAM_LEN+hextra)); -wire oam = (h_cnt < OAM_LEN); // 80 clocks oam +wire oam = (h_cnt <= OAM_LEN); // 80 clocks oam wire stage2 = ((h_cnt >= STAGE2) && (h_cnt < STAGE2+160)); // output out of stage2 // first valid pixels are delivered 8 clocks after end of hblank @@ -546,6 +572,7 @@ wire bg_tile_obj_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b11); // Mode 10: oam // Mode 11: oam and vram assign mode = + (ly <= 144 && h_cnt<4)?2'b00: //AntonioND https://github.com/AntonioND/giibiiadvance/blob/master/docs/TCAGBD.pdf !lcdc_on?2'b00: vblank?2'b01: oam?2'b10: @@ -565,11 +592,11 @@ wire win_start = lcdc_win_ena && (v_cnt >= wy_r) && de && (wx_r >= 7) && (pcnt = // each memory access takes two cycles -always @(negedge clk or negedge lcdc_on) begin +always @(negedge clk) begin if (!lcdc_on) begin // don't increase counters if lcdoff //reset counters - h_cnt <= 9'd0; + h_cnt <= 9'd6; v_cnt <= 8'd0; end else begin