From 235fdb6cb2ad05e5a40f53b287f1c1aeb917f9a9 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Wed, 29 Dec 2021 20:34:50 +0100 Subject: [PATCH] Arkanoid --- Arcade_MiST/Taito Arkanoid/Arkanoid.qpf | 31 + Arcade_MiST/Taito Arkanoid/Arkanoid.qsf | 251 ++++++ Arcade_MiST/Taito Arkanoid/Arkanoid.sdc | 135 +++ Arcade_MiST/Taito Arkanoid/README.txt | 12 + .../Taito Arkanoid/meta/Arkanoid (JP).mra | 81 ++ .../Taito Arkanoid/meta/Arkanoid (US).mra | 83 ++ .../Arkanoid (Unl. Lives, slower) [hb].mra | 87 ++ .../meta/Arkanoid (Unl. lives) [hb].mra | 82 ++ .../Taito Arkanoid/meta/Arkanoid (W).mra | 81 ++ Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv | 770 ++++++++++++++++++ .../Taito Arkanoid/rtl/Arkanoid_MiST.sv | 353 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v | 60 ++ .../Taito Arkanoid/rtl/audio_iir_filter.v | 173 ++++ Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl | 35 + Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd | 136 ++++ Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v | 62 ++ .../Taito Arkanoid/rtl/jtframe_frac_cen.v | 58 ++ Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv | 124 +++ Arcade_MiST/Taito Arkanoid/rtl/pll.qip | 4 + Arcade_MiST/Taito Arkanoid/rtl/pll.v | 348 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv | 261 ++++++ Arcade_MiST/Taito Arkanoid/rtl/sdram.sv | 350 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/spram.vhd | 46 ++ 23 files changed, 3623 insertions(+) create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.qpf create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.qsf create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.sdc create mode 100644 Arcade_MiST/Taito Arkanoid/README.txt create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/pll.qip create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/pll.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/sdram.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/spram.vhd diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf b/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf new file mode 100644 index 00000000..aa7b8519 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "14:21:03 December 29, 2021" + +# Revisions + +PROJECT_REVISION = "Arkanoid" + diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf b/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf new file mode 100644 index 00000000..3022ea8f --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf @@ -0,0 +1,251 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Arkanoid_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +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_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY Arkanoid_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/spin.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(Arkanoid_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Arkanoid_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON + +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 FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +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_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +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 AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Arkanoid_MiST.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Arkanoid.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/mb112s146.sv +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name VERILOG_FILE rtl/build_id.v +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name VERILOG_FILE rtl/arkanoid_lpf.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/pll.v +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip +set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/vol_table_array.vhd +set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/YM2149.vhd +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp +set_global_assignment -name SIGNALTAP_FILE output_files/gfx.stp +set_global_assignment -name SIGNALTAP_FILE output_files/spin.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc b/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc new file mode 100644 index 00000000..59bf935d --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc @@ -0,0 +1,135 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set aud_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Taito Arkanoid/README.txt b/Arcade_MiST/Taito Arkanoid/README.txt new file mode 100644 index 00000000..8316ec8f --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/README.txt @@ -0,0 +1,12 @@ +A MiST port of Arkanoid (https://github.com/MiSTer-devel/Arcade-Arkanoid_MISTer) + +An FPGA implementation of Arkanoid by Ace, ElectronAsh, Enforcer, Sorgelig, Kitrinx and JimmyStones + +Controls: keyboard, joystick, mouse + +Usage: +- Create .ROM and ARC files from MAME ROM zip files using the mra utility and the meta/mra files. +- Example: mra -A -z /path/to/mame/roms Arkanoid.mra +- Copy the resulting ROM and ARC files to the root of the SD Card, next to the Arkanoid.rbf. + +- MRA utilty: https://github.com/sebdel/mra-tools-c diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra new file mode 100644 index 00000000..004fbf12 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra @@ -0,0 +1,81 @@ + + Arkanoid (JP) + Japan + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoidj + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra new file mode 100644 index 00000000..342cafdb --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra @@ -0,0 +1,83 @@ + + Arkanoid (US, older) + US + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoiduo + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 1 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra new file mode 100644 index 00000000..f1c4d63a --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra @@ -0,0 +1,87 @@ + + Arkanoid (Homebrew, Unlimited Lives, Slower) + + yes + no + Unl. Lives, slower + + + + 1986 + Taito + Ball and Paddle + + arkanhb1 + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + 00 + FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF + + + 05 + 00 00 00 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra new file mode 100644 index 00000000..230c7f61 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra @@ -0,0 +1,82 @@ + + Arkanoid (Homebrew, Unlimited Lives) + + yes + no + Unl. lives + + + + 1986 + Taito + Ball and Paddle + + arkanhb2 + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + 00 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra new file mode 100644 index 00000000..feedfc8a --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra @@ -0,0 +1,81 @@ + + Arkanoid + World + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoid + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 1 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 33 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv new file mode 100644 index 00000000..5379e867 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv @@ -0,0 +1,770 @@ +//============================================================================ +// +// Arkanoid top-level module +// Copyright (C) 2018, 2020 Ace, Enforcer, Ash Evans (aka ElectronAsh/OzOnE) +// and Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Module declaration, I/O ports +module Arkanoid +( + input reset, + input clk_48m, + input [1:0] spinner, //1 = left, 0 = right + input coin1, coin2, + input btn_shot, btn_service, tilt, + input btn_1p_start, btn_2p_start, + + input [7:0] dip_sw, + + input ym2149_clk_div, + input vol_boost, + + //This input serves to select different methods of acheiving 3MHz for the YM2149 depending on whether Arkanoid runs with + //original or overclocked timings to normalize sync frequencies + input overclock, + + output signed [15:0] sound, + + //Screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] h_center, + input [2:0] v_center, + + output video_hsync, video_vsync, + output video_csync, + output video_vblank, video_hblank, + output [3:0] video_r, video_g, video_b, + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, + + input [15:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write, + + output [15:0] cpu_rom_addr, + input [7:0] cpu_rom_do, + + output [14:0] gfx_rom_addr, + input [31:0] gfx_rom_do +); + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i; +wire cp1_cs_i, cp2_cs_i, cp3_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .cp1_cs(cp1_cs_i), + .cp2_cs(cp2_cs_i), + .cp3_cs(cp3_cs_i) +); + +//-------------------------------------------------- MiSTer hiscore load/save --------------------------------------------------// + +// Setup multipex between CPU Work RAM and Video RAM for hiscore data +wire [7:0] hs_data_out_wram /* synthesis keep */; +wire [7:0] hs_data_out_vram_h /* synthesis keep */; +wire [7:0] hs_data_out_vram_l /* synthesis keep */; +wire hs_cs_wram /* synthesis keep */; +wire hs_cs_vram_h /* synthesis keep */; +wire hs_cs_vram_l /* synthesis keep */; +assign hs_cs_wram = hs_address[15:12] == 4'b1100; +assign hs_cs_vram_l = hs_address[15:12] == 4'b1110 && !hs_address[0]; +assign hs_cs_vram_h = hs_address[15:12] == 4'b1110 && hs_address[0]; +assign hs_data_out = hs_cs_wram ? hs_data_out_wram : hs_cs_vram_l ? hs_data_out_vram_l : hs_data_out_vram_h; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6MHz and 3MHz clock enables +//Also generate an extra clock enable for DC offset removal in the sound section +reg [8:0] div = 9'd0; +always_ff @(posedge clk_48m) begin + div <= div + 9'd1; +end +wire cen_6m = !div[2:0]; +wire n_cen_6m = div[2:0] == 3'b100; +wire n_cen_3m = div[3:0] == 4'b1000; +wire dcrm_cen = !div; + +//Generate 3MHz clock enable for YM2149 to maintain consistent sound pitch when overclocked to normalize video timings +//(uses Jotego's fractional clock divider from JTFRAME) +wire n_cen_3m_adjust; +jtframe_frac_cen sound_cen +( + .clk(clk_48m), + .n(10'd31), + .m(10'd503), + .cenb({1'bZ, n_cen_3m_adjust}) +); + +//Edge detection for signals other than clocks used to latch data +reg old_hcnt0, old_hcnt2, old_hcnt3, old_vcnt4, old_nvblank, old_spinner_clk; +always_ff @(posedge clk_48m) begin + old_hcnt0 <= h_cnt[0]; + old_hcnt2 <= h_cnt[2]; + old_hcnt3 <= h_cnt[3]; + old_vcnt4 <= v_cnt[4]; + old_nvblank <= n_vblank; + old_spinner_clk <= spin_cnt_clk; +end + +//------------------------------------------------------------ CPUs ------------------------------------------------------------// + +wire z80_n_m1, z80_n_mreq, z80_n_iorq, z80_n_rd, z80_n_wr; +wire [15:0] z80_A; +wire [7:0] z80_Dout, z80_ram_D; +//Main CPU - Zilog Z80 (uses T80s variant of the T80 soft core) +//NMI, BUSRQ unused, pull high +T80s IC12 +( + .RESET_n(z80_n_reset), + .CLK(clk_48m), + //.CEN_p(cen_6m & ~pause), + .CEN(n_cen_6m & ~pause), + .WAIT_n(z80_n_wait), + .INT_n(z80_n_int), + .NMI_n(1), + .BUSRQ_n(1), + .MREQ_n(z80_n_mreq), + .IORQ_n(z80_n_iorq), + .RD_n(z80_n_rd), + .WR_n(z80_n_wr), + .A(z80_A), + .DI(z80_Din), + .DO(z80_Dout) +); +//Address decoding for data inputs to Z80 +wire cs_rom1 = (~z80_A[15] & ~z80_n_rd); +wire cs_rom2 = (z80_A[15:14] == 2'b10 & ~z80_n_rd); +wire cs_z80_ram = z80_A[15:12] == 4'b1100; +wire cs_ym2149 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b00); +wire cs_buttons2 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b01 & ~z80_n_rd); +wire cs_buttons1 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b10 & ~z80_n_rd); +wire cs_spinner = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b11 & ~z80_n_rd); +wire cs_mainlatch = (~z80_n_wr & z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b01); +wire cs_vram_l = h_cnt[0] ? 1'b1 : (z80_A[15:12] == 4'b1110 & ~z80_A[0] & ~z80_n_mreq); +wire cs_vram_h = h_cnt[0] ? 1'b1 : (z80_A[15:12] == 4'b1110 & z80_A[0] & ~z80_n_mreq); +//Multiplex data inputs to Z80 +wire [7:0] z80_Din = cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + (cs_z80_ram & ~z80_n_rd) ? z80_ram_D: + (~ym2149_bdir & z80_A[0] & ym2149_bc1) ? ym2149_data: + (vram_oe & cs_vram_h & vram_rd) ? vram_D[7:0]: + (vram_oe & cs_vram_l & vram_rd) ? vram_D[15:8]: + cs_buttons2 ? buttons2: + cs_buttons1 ? buttons1: + cs_spinner ? spinner_D: + 8'hFF; + +//Game ROMs +assign cpu_rom_addr = z80_A[15] ? {1'b1, eprom2_A14, z80_A[13:0]} : {1'b0, z80_A[14:0]}; +`ifdef EXT_ROM +wire [7:0] eprom1_D = cpu_rom_do; +wire [7:0] eprom2_D = cpu_rom_do; +`else +//ROM 1/2 +wire [7:0] eprom1_D; +eprom_1 IC17 +( + .ADDR(z80_A[14:0]), + .CLK(clk_48m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +//ROM 2/2 +wire [7:0] eprom2_D; +eprom_2 IC16 +( + .ADDR({eprom2_A14, z80_A[13:0]}), + .CLK(clk_48m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +`endif + +//Z80 work RAM +dpram_dc #(.widthad_a(11)) IC15 +( + .clock_a(clk_48m), + .address_a(z80_A[10:0]), + .data_a(z80_Dout), + .q_a(z80_ram_D), + .wren_a(cs_z80_ram & ~z80_n_wr), + + .clock_b(clk_48m), + .address_b(hs_address[10:0]), + .data_b(hs_data_in), + .q_b(hs_data_out_wram), + .wren_b(hs_write & hs_cs_wram) +); + +//Watchdog - counts 128 VBlanks before triggering a reset if Arkanoid encounters a run-time issue +wire watchdog_clr = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b10 & ~z80_n_wr) | pause; +reg [7:0] watchdog_timer = 8'd0; +always_ff @(posedge clk_48m) begin + if(watchdog_clr) + watchdog_timer <= 8'd0; + else if(old_nvblank && !n_vblank) + watchdog_timer <= watchdog_timer + 8'd1; +end + +//AND the reset input to the Z80 with the watchdog output +wire z80_n_reset = reset & ~watchdog_timer[7]; + +//Generate Z80 IRQ on the rising edge of the active-low VBlank +reg z80_n_int = 1; +always_ff @(posedge clk_48m) begin + if(!z80_n_iorq) + z80_n_int <= 1; + else if(!old_nvblank && n_vblank) + z80_n_int <= 0; +end + +//Generate Z80 WAIT signal +wire wait_trigger = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b00); +reg n_wait = 1; +reg wait_clear; +always_ff @(posedge clk_48m) begin + if(wait_clear) + n_wait <= 1; + else if(cen_6m) begin + n_wait <= ~wait_trigger; + wait_clear <= ~n_wait; + end +end +wire z80_n_wait = (~(z80_A[15:12] == 4'b1110 & ~z80_n_mreq) | ~h_cnt[0]) & n_wait; + +//Main latch +reg vflip, hflip, spinner_sel, mcu_sel, prom_bank, gfxrom_bank, eprom2_bank; +always_ff @(posedge clk_48m) begin + if(!z80_n_reset) begin + mcu_sel <= 0; + prom_bank <= 0; + gfxrom_bank <= 0; + eprom2_bank <= 0; + spinner_sel <= 0; + vflip <= 0; + hflip <= 0; + end + else if(n_cen_6m && cs_mainlatch) begin + mcu_sel <= z80_Dout[7]; + prom_bank <= z80_Dout[6]; + gfxrom_bank <= z80_Dout[5]; + eprom2_bank <= z80_Dout[4]; + spinner_sel <= z80_Dout[2]; + vflip <= z80_Dout[1]; + hflip <= z80_Dout[0]; + end +end +assign gfxrom_A[14] = gfxrom_bank; +wire eprom2_A14 = eprom2_bank; + +//------------------------------------------------------------ MCUs ------------------------------------------------------------// + +//Arkanoid uses an MC68705 microcontroller at IC14 on the PCB for protection and for reading spinner inputs - this MCU is +//currently unimplemented +wire mcu_data_latch = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b11 & ~z80_n_wr); + +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Reverse DIP switch order +wire [7:0] dipsw = {dip_sw[0], dip_sw[1], dip_sw[2], dip_sw[3], dip_sw[4], dip_sw[5], dip_sw[6], dip_sw[7]}; + +//Group and multiplex button inputs +wire [7:0] buttons1 = {5'b11111, btn_shot, 1'b1, btn_shot}; +wire [7:0] buttons2 = z80_A[2] ? {2'b01, coin2, coin1, tilt, btn_service, btn_2p_start, btn_1p_start} : 8'hFF; + +//Invert spinner inputs +wire [1:0] n_spinner1 = {~spinner[1], ~spinner[0]}; +wire [1:0] n_spinner2 = {~spinner[1], ~spinner[0]}; + +//Select which spinner inputs to send to the spinner input counters +wire spin_cnt_u_d = spinner_sel ? n_spinner1[1] : n_spinner2[1]; +wire spin_cnt_clk = spinner_sel ? n_spinner2[0] : n_spinner1[0]; + +//Spinner input counters +wire spin_cnt_en = (z80_A[2] | ~cs_buttons2); +reg [7:0] spin_cnt = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_spinner_clk && spin_cnt_clk) + if(spin_cnt_en) + spin_cnt <= spin_cnt_u_d ? (spin_cnt + 8'd1) : (spin_cnt - 8'd1); +end + +//Latch spinner counter values to the Z80 on the rising edge of horizontal counter bit 0 - this is normally done through the MCU, +//though bootlegs without an MCU directly latch the spinner counters to the Z80 as a workaround +reg [7:0] spinner_D = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt0 && h_cnt[0]) + spinner_D <= spin_cnt; +end + +//-------------------------------------------------------- Video timing --------------------------------------------------------// + +//Arkanoid's horizontal and vertical counters are 9 bits wide - delcare them here +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Define the range of values the vertical counter will count between based on the additional vertical center signal +//Shift the screen up by 1 line when horizontal centering shifts the screen left +wire [8:0] vcnt_start = 9'd248 - v_center; +wire [8:0] vcnt_end = 9'd511 - v_center; + +//The horizontal and vertical counters behave as follows at every rising edge of the pixel clock: +//-Start at 0, then count to 511 +//-Horizontal counter resets to 128 for a total of 384 horizontal lines +//-Vertical counter resets to 248 for a total of 264 vertical lines (adjustable with added vertical center signal) +//-Vertical counter increments when the horizontal counter equals 128 +//Model this behavior here +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + case(h_cnt) + 128: begin + h_cnt <= h_cnt + 9'd1; + case(v_cnt) + vcnt_end: v_cnt <= vcnt_start; + default: v_cnt <= v_cnt + 9'd1; + endcase + end + 511: h_cnt <= 9'd128; + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Generate h256 by latching bit 8 of the horizontal counter on the rising edge of bit 3 of that same counter +reg h256; +always_ff @(posedge clk_48m) begin + if(!old_hcnt3 && h_cnt[3]) + h256 <= h_cnt[8]; +end + +//XOR horizontal counter bits [7:3] with horizontal flip bit +wire [7:3] hcnt_x = h_cnt[7:3] ^ {5{hflip}}; + +//XOR vertical counter bits with vertical flip bit +wire [8:0] vcnt_x = v_cnt ^ {9{vflip}}; + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//Multiplex VRAM address lines based on horizontal counter bits 8 and 0 +wire [10:0] vram_A = !h_cnt[0] ? z80_A[11:1]: + h_cnt[8] ? {1'b0, vcnt_x[7:3], hcnt_x[7:3]}: + {1'b1, 5'b00000, h_cnt[6:2]}; + +//Multiplex VRAM write, output and chip enable signals based on the state of horizontal counter bit 0 +wire vram_we = n_cen_6m & (h_cnt[0] ? 1'b0 : z80_n_rd); +wire vram_oe = h_cnt[0] ? 1'b1 : ~z80_n_rd; + +//Generate active-high VRAM read enable +wire vram_rd = ~z80_n_rd & (z80_A[15:12] == 4'b1110 & ~z80_n_mreq); + +//VRAM +//Upper 8 bits +wire [15:0] vram_D; +dpram_dc #(.widthad_a(11)) IC57 +( + .clock_a(clk_48m), + .address_a(vram_A), + .data_a(z80_Dout), + .q_a(vram_D[15:8]), + .wren_a(cs_vram_l & vram_we), + + .clock_b(clk_48m), + .address_b(hs_address[11:1]), + .data_b(hs_data_in), + .q_b(hs_data_out_vram_l), + .wren_b(hs_write & hs_cs_vram_l) +); +//Lower 8 bits +dpram_dc #(.widthad_a(11)) IC58 +( + .clock_a(clk_48m), + .address_a(vram_A), + .data_a(z80_Dout), + .q_a(vram_D[7:0]), + .wren_a(cs_vram_h & vram_we), + + .clock_b(clk_48m), + .address_b(hs_address[11:1]), + .data_b(hs_data_in), + .q_b(hs_data_out_vram_h), + .wren_b(hs_write & hs_cs_vram_h) +); + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//Latch tilemap data from VRAM on the rising edge of horizontal counter bit 2 +reg [7:0] tiles_D = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt2 && h_cnt[2]) + tiles_D <= {vram_D[6], vram_D[4:3], vram_D[1], vram_D[2], vram_D[0], vram_D[7], vram_D[5]}; +end + +//Sum tilemap data with vertical counter bits [7:0] +wire [7:0] sr = {tiles_D[1], tiles_D[7], tiles_D[0], tiles_D[6:5], tiles_D[3], tiles_D[4], tiles_D[2]} + vcnt_x[7:0]; + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//Latch horizontal position and tilemap data from VRAM on the rising edge of horizontal counter bit 2 +reg [7:0] h_pos = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt2 && h_cnt[2]) + h_pos <= {vram_D[8], vram_D[15], vram_D[10], vram_D[13], vram_D[14], vram_D[12:11], vram_D[9]}; +end + +//Latch sprite data on the falling edge of horizontal counter bit 2 +reg [4:0] sprites_D = 5'd0; +always_ff @(posedge clk_48m) begin + if(old_hcnt2 && !h_cnt[2]) + sprites_D <= {vram_D[11], vram_D[14:12], vram_D[15]}; +end + +//Multiplex sprite horizontal position based on bit 8 of the horizontal counter +wire [7:0] sprite_hpos = h_cnt[8] ? {8{hflip}} : {h_pos[3], h_pos[6], h_pos[4], h_pos[2], h_pos[5], h_pos[1], h_pos[0], h_pos[7]}; + +//Generate sprite RAM addresses +wire [8:0] spriteram_A; +reg [7:0] spriteram_cnt = 8'd0; +wire spriteram_u_d = ~(hflip & h256); +wire n_spriteram_cnt_load = shift_ld | (h_cnt[8] & h256); +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + if(!n_spriteram_cnt_load) + spriteram_cnt <= {sprite_hpos[6], sprite_hpos[7], sprite_hpos[5:4], sprite_hpos[2], sprite_hpos[3], sprite_hpos[1:0]}; + else + spriteram_cnt <= spriteram_u_d ? (spriteram_cnt + 4'd1) : (spriteram_cnt - 4'd1); + end +end +assign spriteram_A[8] = ~h256 & ~(sprite_pixel1 | sprite_pixel2 | sprite_pixel3); +assign spriteram_A[7:0] = spriteram_cnt; + +//Latch sprite pixel signal on the falling edge of horizontal counter bit 2 and generate individual sprite pixel signals for each +//shifted graphics ROM data +reg n_inre; +always_ff @(posedge clk_48m) begin + if(old_hcnt0 && !h_cnt[0]) begin + if(h_cnt[8]) + n_inre <= 1; + else + n_inre <= ~(&sr[7:4]); + end +end +reg sprite_pixel; +always_ff @(posedge clk_48m) begin + if(old_hcnt2 && !h_cnt[2]) + sprite_pixel <= ~n_inre; +end +wire sprite_pixel1 = sprite_pixel & eprom3_shift; +wire sprite_pixel2 = sprite_pixel & eprom5_shift; +wire sprite_pixel3 = sprite_pixel & eprom4_shift; + +//Assign sprite RAM data input +wire [7:0] spriteram_Din = {sprites_D[0], sprites_D[3:1], sprites_D[4], sprite_pixel2, sprite_pixel3, sprite_pixel1}; + +//Sprite RAM (the original PCB uses a 2KB RAM chip with 11 address lines, but only 9 are used, limiting its capacity to 512 bytes) +wire [7:0] spriteram_Dout; +spram #(8, 9) IC51 +( + .clk(clk_48m), + .we(n_cen_6m), + .addr(spriteram_A), + .data(spriteram_Din), + .q(spriteram_Dout) +); + +//-------------------------------------------------------- Graphics ROMs -------------------------------------------------------// + +//Latch data from VRAM to be used as addresses for the graphics ROMs on the falling edge of horizontal counter bit 0 and +//multiplex based on horizontal counter bit 8 +wire [14:0] gfxrom_A; +reg [13:0] gfx_address = 14'd0; +always_ff @(posedge clk_48m) begin + if(old_hcnt0 && !h_cnt[0]) begin + if(h_cnt[8]) + gfx_address <= {vram_D[10:0], vcnt_x[2:0]}; + else + gfx_address <= {vram_D[9:0], sr[3:0]}; + end +end +assign gfxrom_A[13:0] = gfx_address; + +assign gfx_rom_addr = gfxrom_A; + +//Graphics ROMs +`ifdef EXT_ROM +wire [7:0] eprom3_D = gfx_rom_do[7:0]; +wire [7:0] eprom4_D = gfx_rom_do[15:8]; +wire [7:0] eprom5_D = gfx_rom_do[23:16]; +`else +//ROM 1/3 +wire [7:0] eprom3_D; +eprom_3 IC64 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +//ROM 2/3 +wire [7:0] eprom4_D; +eprom_4 IC63 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom4_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); + +//ROM 3/3 +wire [7:0] eprom5_D; +eprom_5 IC62 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom5_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); +`endif + +//Fujitsu MB112S146 - Custom bit shifter used by Arkanoid to left/right shift graphics data from the graphics ROMs +//Instantiate two instances of this chip to shift graphics data from the 3 graphics ROMs +wire shift_ld = ~(&h_cnt[2:0]); +wire flip_sel = hflip & h256; +wire eprom5_shift; +mb112s146 IC77 +( + .clk(clk_48m), + .cen(n_cen_6m), + .n_clr(1), + .shift_ld(shift_ld), + .sel(flip_sel), + .s_in(2'b00), + .d2_in(8'h00), //This shift register is unused, pull inputs low + .d1_in(eprom5_D), + .shift_out({1'bZ, eprom5_shift}) //Shift register 1 unused +); +wire eprom3_shift, eprom4_shift; +mb112s146 IC78 +( + .clk(clk_48m), + .cen(n_cen_6m), + .n_clr(1), + .shift_ld(shift_ld), + .sel(flip_sel), + .s_in(2'b00), + .d2_in(eprom3_D), + .d1_in(eprom4_D), + .shift_out({eprom3_shift, eprom4_shift}) +); + +//Latch tilemap and sprite data for color PROMs +reg [7:0] tiles = 8'd0; +reg [7:0] sprites = 8'd0; +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + tiles <= {eprom3_shift, eprom5_shift, sprites_D[4], eprom4_shift, sprites_D[2], sprites_D[0], sprites_D[3], sprites_D[1]}; + sprites <= {spriteram_Dout[3], spriteram_Dout[0], spriteram_Dout[1], spriteram_Dout[6], spriteram_Dout[2], spriteram_Dout[5:4], spriteram_Dout[7]}; + end +end + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Generate BDIR and BCI inputs for YM2149 +wire ym2149_bdir = (~z80_n_wr & cs_ym2149); +wire ym2149_bc1 = (~z80_n_rd & cs_ym2149); + +//Select whether to use a fractional or integer clock divider for the YM2149 to maintain consistent sound pitch at both original +//and overclocked timings +wire cen_sound = overclock ? n_cen_3m_adjust : n_cen_3m; + +//Sound chip - Yamaha YM2149 (implementation by MikeJ) +//Implements volume table to simulate mixing of the three analog outputs directly at the chip as per the original Arkanoid PCB +wire [7:0] ym2149_data; +ym2149 #(.MIXER_VOLTABLE(1'b1)) IC2 +( + .I_DA(z80_Dout), + .O_DA(ym2149_data), + .I_A9_L(0), + .I_A8(1), + .I_BDIR(ym2149_bdir), + .I_BC2(z80_A[0]), + .I_BC1(ym2149_bc1), + .I_SEL_L(ym2149_clk_div), + .O_AUDIO_L(sound_raw), + .I_IOB(dipsw), + .ENA(cen_sound), + .RESET_L(z80_n_reset), + .CLK(clk_48m) +); + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Multiplex tilemaps and sprites to color PROM addresses +wire prom_A_sel = ~(sprites[6] | sprites[5] | sprites[3]); +reg [7:0] prom_A = 8'd0; +always_ff @(posedge clk_48m) begin + if(cen_6m) begin + if(prom_A_sel) + prom_A <= {tiles[2], tiles[1], tiles[3], tiles[0], tiles[5], tiles[6], tiles[4], tiles[7]}; + else + prom_A <= {sprites[0], sprites[4], sprites[2], sprites[1], sprites[7], sprites[3], sprites[5], sprites[6]}; + end +end + +//Arkanoid generates its final video output by latching data from 3 LUT PROMs, one per color, for 12-bit RGB with 4 bits per color +//Red color PROM +wire [3:0] prom1_data; +color_prom_1 IC24 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom1_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp1_cs_i), + .WR(ioctl_wr) +); +//Green color PROM +wire [3:0] prom2_data; +color_prom_2 IC23 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom2_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp2_cs_i), + .WR(ioctl_wr) +); +//Blue color PROM +wire [3:0] prom3_data; +color_prom_3 IC22 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom3_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp3_cs_i), + .WR(ioctl_wr) +); + +//Generate active-low VBlank (this VBlank is imperfect - use as part of the video output logic to recreate the 1-pixel upward +//vertical shift on the last 10 vertical lines on the right side of the screen) +reg n_vblank; +always_ff @(posedge clk_48m) begin + if(!old_vcnt4 && v_cnt[4]) + n_vblank <= ~(&v_cnt[7:5]); +end + +//Latch data from color PROMs for video output +reg [3:0] red, green, blue; +always_ff @(posedge clk_48m) begin + if(!n_vblank || video_hblank) begin + red <= 4'd0; + green <= 4'd0; + blue <= 4'd0; + end + else if(cen_6m) begin + red <= prom1_data; + green <= prom2_data; + blue <= prom3_data; + end +end +assign video_r = red; +assign video_g = green; +assign video_b = blue; + +//Video sync & blanking outputs (HSync and blanks active-high, VSync active-low) +assign video_hsync = h_center[3] ? (~h_cnt[8] && h_cnt[6:0] > (7'd54 - h_center[2:0]) && h_cnt[6:0] < (7'd87 - h_center[2:0])): + (~h_cnt[8] && h_cnt[6:0] > (7'd47 - h_center[2:0]) && h_cnt[6:0] < (7'd80 - h_center[2:0])); +assign video_vsync = ~(v_cnt >= vcnt_start && v_cnt <= vcnt_start + 9'd7); +assign video_csync = video_hsync ^ video_vsync; +assign video_vblank = (v_cnt < 271 || v_cnt > 495); +assign video_hblank = (h_cnt > 137 && h_cnt < 266); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Remove DC offset from audio output (uses jt49_dcrm2 from JT49 by Jotego) +wire [9:0] sound_raw; + +wire signed [15:0] sound_dcrm; +jt49_dcrm2 #(16) dcrm +( + .clk(clk_48m), + .cen(dcrm_cen), + .rst(~reset), + .din({5'd0, sound_raw}), + .dout(sound_dcrm) +); + +//Low-pass filter the audio output (cutoff frequency ~16.7KHz) +wire signed [15:0] sound_filtered; + +arkanoid_lpf lpf +( + .clk(clk_48m), + .reset(~reset), + .in(sound_dcrm), + .out(sound_filtered) +); + +//Apply gain to final audio output (mute when the game is paused) +assign sound = pause ? 16'd0 : vol_boost ? (sound_filtered <<< 16'd5) : (sound_filtered <<< 16'd4); + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv new file mode 100644 index 00000000..ec2669c7 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv @@ -0,0 +1,353 @@ +module Arkanoid_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "Arkanoid;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire [1:0] orientation = 2'b11; +wire [7:0] dip_sw = status[15:8]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_96; +assign SDRAM_CKE = 1; +assign AUDIO_R = AUDIO_L; + +wire clock_48, clock_96, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_96), + .c1(clock_48), + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; +wire mouse_strobe; +wire [8:0] mouse_x; +wire [7:0] mouse_flags; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_48 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .mouse_strobe (mouse_strobe ), + .mouse_flags (mouse_flags ), + .mouse_x (mouse_x ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + + +wire [15:0] cpu_rom_addr; +wire [15:0] cpu_rom_do; +wire [14:0] bg_addr; +wire [31:0] bg_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_48 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 17'h10000; + +reg port1_req, port2_req; + +sdram #(96) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_96 ), + + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'hffff : {1'b0, cpu_rom_addr[15:1]} ), + .cpu1_q ( cpu_rom_do ), + .cpu2_addr ( ), + .cpu2_q ( ), + + // port2 for sprite graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( {bg_ioctl_addr[24:17], bg_ioctl_addr[14:0], bg_ioctl_addr[16]} ), // merge sprite roms to 32-bit wide words + .port2_ds ( {bg_ioctl_addr[15], ~bg_ioctl_addr[15]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .sp_addr ( ioctl_downl ? 16'hffff : bg_addr ), + .sp_q ( bg_do ) +); + +// ROM download controller +always @(posedge clock_48) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_48) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +// quadrature encoder (spinner) +reg [1:0] spinner_encoder; +reg [11:0] position = 0; +wire [11:0] position_next = position + {{4{mouse_x[8]}}, mouse_x[7:0]}; + +always @(posedge clock_48) begin + reg [15:0] spin_counter; + reg [2:0] ce_6m; + reg [11:0] div_4k; + + ce_6m <= ce_6m + 3'd1; + if(!ce_6m) begin + + div_4k <= div_4k + 1'd1; + if(div_4k == 1499) div_4k <= 0; + + if(position != 0) begin //we need to drive position to 0 still; + if(!div_4k) begin + case({position[11] , spinner_encoder}) + {1'b1, 2'b00}: spinner_encoder <= 2'b01; + {1'b1, 2'b01}: spinner_encoder <= 2'b11; + {1'b1, 2'b11}: spinner_encoder <= 2'b10; + {1'b1, 2'b10}: spinner_encoder <= 2'b00; + {1'b0, 2'b00}: spinner_encoder <= 2'b10; + {1'b0, 2'b10}: spinner_encoder <= 2'b11; + {1'b0, 2'b11}: spinner_encoder <= 2'b01; + {1'b0, 2'b01}: spinner_encoder <= 2'b00; + endcase + + if(position[11]) position <= position + 1'b1; + else position <= position - 1'b1; + end + end + + if (m_left | m_right) begin // 0.167us per cycle + // DPAD left/right + if (spin_counter == 'd48000) begin// roughly 8ms to emulate 125hz standard mouse poll rate + position <= m_right ? (m_fireB ? 12'd9 : 12'd4) : (m_fireB ? -12'd9 : -12'd4); + spin_counter <= 0; + end else begin + spin_counter <= spin_counter + 1'b1; + end + end else begin + spin_counter <= 0; + end + end + if(mouse_strobe) begin + if (position[11] != mouse_x[8] || position[11] == position_next[11]) + position <= position_next; + else + position <= {position[11], {11{~position[11]}}}; + end +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +Arkanoid Arkanoid_inst +( + .reset(~reset), //input reset + + .clk_48m(clock_48), //input clk_48m + + .spinner(spinner_encoder), //input [1:0] spinner + + .coin1(m_coin1), //input coin1 + .coin2(m_coin2), //input coin2 + + .btn_shot(~(m_fireA | |mouse_flags[1:0])), //input btn_shot + .btn_service(~service), //input btn_service + + .tilt(1), //input tilt + + .btn_1p_start(~m_one_player), //input btn_1p_start + .btn_2p_start(~m_two_players), //input btn_2p_start + + .dip_sw(~dip_sw), //input [7:0] dip_sw + + .sound(audio), //output [15:0] sound + + .h_center(), //Screen centering + .v_center(), + + .video_hsync(hs), //output video_hsync + .video_vsync(vs), //output video_vsync + .video_vblank(vblank), //output video_vblank + .video_hblank(hblank), //output video_hblank + + .video_r(r), //output [3:0] video_r + .video_g(g), //output [3:0] video_g + .video_b(b), //output [3:0] video_b + + .ym2149_clk_div(1'b1), //Easter egg - controls the YM2149 clock divider for bootlegs with overclocked AY-3-8910s (default on) + .vol_boost(1'b0), //Audio volume boost option + .overclock(1'b0), //Flag to signal that Arkanoid has been overclocked to normalize video timings in order to maintain consistent sound pitch + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(1'b0), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write(hs_write_enable), + + .cpu_rom_addr(cpu_rom_addr), + .cpu_rom_do(cpu_rom_addr[0] ? cpu_rom_do[15:8] : cpu_rom_do[7:0]), + .gfx_rom_addr(bg_addr), + .gfx_rom_do(bg_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_48 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +dac #(.C_bits(16))dac_l( + .clk_i(clock_48), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(AUDIO_L) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_48 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v b/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v new file mode 100644 index 00000000..36a867b6 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to low-pass filter the YM2149 on Arkanoid. + +module arkanoid_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 48MHz/256 = 187500Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.22211491, 0.22211491 + //1.0000000, -0.55577018 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd18211; + B1 = 18'd7278; + B2 = 18'd7278; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v b/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl b/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd b/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + 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", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v b/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v b/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv b/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv new file mode 100644 index 00000000..5e18653d --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv @@ -0,0 +1,124 @@ +//============================================================================ +// +// SystemVerilog mplementation of the Fujitsu MB112S146 custom IC +// Contains two left/right shift registers and a multiplexer +// Copyright (C) 2019 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Chip pinout: +/* _____________ + _| |_ +shift_ld |_|1 28|_| VCC + _| |_ +latch |_|2 27|_| n_clr + _| |_ +s_in(0) |_|3 26|_| sel + _| |_ +s_in(1) |_|4 25|_| GND + _| |_ +clk |_|5 24|_| d2_in(0) + _| |_ +d1_in(0) |_|6 23|_| d2_in(1) + _| |_ +d1_in(1) |_|7 22|_| d2_in(2) + _| |_ +d1_in(2) |_|8 21|_| d2_in(3) + _| |_ +d1_in(3) |_|9 20|_| d2_in(4) + _| |_ +d1_in(4) |_|10 19|_| d2_in(5) + _| |_ +d1_in(5) |_|11 18|_| d2_in(6) + _| |_ +d1_in(6) |_|12 17|_| d2_in(7) + _| |_ +d1_in(7) |_|13 16|_| shift_out(0) + _| |_ +GND |_|14 15|_| shift_out(1) + |_____________| +*/ + +module mb112s146 +( + input clk, cen, + input n_clr, shift_ld, + input sel, + input [1:0] s_in, + input [7:0] d1_in, d2_in, + output [1:0] shift_out +); + +reg [7:0] shift_l_1, shift_l_2; +reg [7:0] shift_r_1, shift_r_2; + +always_ff @(posedge clk or negedge n_clr) begin + if(!n_clr) begin + //Reset internal registers + shift_l_1 <= 8'd0; + shift_l_2 <= 8'd0; + shift_r_1 <= 8'd0; + shift_r_2 <= 8'd0; + end + else if(cen) begin + //Left shift data 1 input + shift_l_1[0] <= (s_in[0] & shift_ld) | (~shift_ld & d1_in[0]); + shift_l_1[1] <= (shift_l_1[0] & shift_ld) | (~shift_ld & d1_in[1]); + shift_l_1[2] <= (shift_l_1[1] & shift_ld) | (~shift_ld & d1_in[2]); + shift_l_1[3] <= (shift_l_1[2] & shift_ld) | (~shift_ld & d1_in[3]); + shift_l_1[4] <= (shift_l_1[3] & shift_ld) | (~shift_ld & d1_in[4]); + shift_l_1[5] <= (shift_l_1[4] & shift_ld) | (~shift_ld & d1_in[5]); + shift_l_1[6] <= (shift_l_1[5] & shift_ld) | (~shift_ld & d1_in[6]); + shift_l_1[7] <= (shift_l_1[6] & shift_ld) | (~shift_ld & d1_in[7]); + //Left shift data 2 input + shift_l_2[0] <= (s_in[1] & shift_ld) | (~shift_ld & d2_in[0]); + shift_l_2[1] <= (shift_l_2[0] & shift_ld) | (~shift_ld & d2_in[1]); + shift_l_2[2] <= (shift_l_2[1] & shift_ld) | (~shift_ld & d2_in[2]); + shift_l_2[3] <= (shift_l_2[2] & shift_ld) | (~shift_ld & d2_in[3]); + shift_l_2[4] <= (shift_l_2[3] & shift_ld) | (~shift_ld & d2_in[4]); + shift_l_2[5] <= (shift_l_2[4] & shift_ld) | (~shift_ld & d2_in[5]); + shift_l_2[6] <= (shift_l_2[5] & shift_ld) | (~shift_ld & d2_in[6]); + shift_l_2[7] <= (shift_l_2[6] & shift_ld) | (~shift_ld & d2_in[7]); + //Right shift data 1 input + shift_r_1[0] <= (s_in[0] & shift_ld) | (~shift_ld & d1_in[7]); + shift_r_1[1] <= (shift_r_1[0] & shift_ld) | (~shift_ld & d1_in[6]); + shift_r_1[2] <= (shift_r_1[1] & shift_ld) | (~shift_ld & d1_in[5]); + shift_r_1[3] <= (shift_r_1[2] & shift_ld) | (~shift_ld & d1_in[4]); + shift_r_1[4] <= (shift_r_1[3] & shift_ld) | (~shift_ld & d1_in[3]); + shift_r_1[5] <= (shift_r_1[4] & shift_ld) | (~shift_ld & d1_in[2]); + shift_r_1[6] <= (shift_r_1[5] & shift_ld) | (~shift_ld & d1_in[1]); + shift_r_1[7] <= (shift_r_1[6] & shift_ld) | (~shift_ld & d1_in[0]); + //Right shift data 2 input + shift_r_2[0] <= (s_in[1] & shift_ld) | (~shift_ld & d2_in[7]); + shift_r_2[1] <= (shift_r_2[0] & shift_ld) | (~shift_ld & d2_in[6]); + shift_r_2[2] <= (shift_r_2[1] & shift_ld) | (~shift_ld & d2_in[5]); + shift_r_2[3] <= (shift_r_2[2] & shift_ld) | (~shift_ld & d2_in[4]); + shift_r_2[4] <= (shift_r_2[3] & shift_ld) | (~shift_ld & d2_in[3]); + shift_r_2[5] <= (shift_r_2[4] & shift_ld) | (~shift_ld & d2_in[2]); + shift_r_2[6] <= (shift_r_2[5] & shift_ld) | (~shift_ld & d2_in[1]); + shift_r_2[7] <= (shift_r_2[6] & shift_ld) | (~shift_ld & d2_in[0]); + end +end + +assign shift_out = sel ? {shift_r_2[7], shift_r_1[7]}: + {shift_l_2[7], shift_l_1[7]}; + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/pll.qip b/Arcade_MiST/Taito Arkanoid/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Taito Arkanoid/rtl/pll.v b/Arcade_MiST/Taito Arkanoid/rtl/pll.v new file mode 100644 index 00000000..18e1d7fd --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 9, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 32, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 9, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 16, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// 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 "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "360" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "96.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "48.000000" +// 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" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "191" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "96.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "48.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// 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 "9" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "32" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "16" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv b/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv new file mode 100644 index 00000000..bb888c11 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv @@ -0,0 +1,261 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Arkanoid: +// 0x0000 - 0x7FFF = eprom_1 +// 0x8000 - 0xFFFF = eprom_2 +// 0x10000 - 0x17FFF = eprom_3 +// 0x18000 - 0x1FFFF = eprom_4 +// 0x20000 - 0x27FFF = eprom_5 +// 0x28000 - 0x281FF = color_prom_1 +// 0x28200 - 0x283FF = color_prom_2 +// 0x28400 - 0x285FF = color_prom_3 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, cp1_cs, cp2_cs, cp3_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, cp1_cs, cp2_cs, cp3_cs} = 0; + if(ioctl_addr < 'h8000) + ep1_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h10000) + ep2_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h18000) + ep3_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h20000) + ep4_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28000) + ep5_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28200) + cp1_cs = 1; // 0x200 9 + else if(ioctl_addr < 'h28400) + cp2_cs = 1; // 0x200 9 + else + cp3_cs = 1; // 0x200 9 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_4 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_5 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module color_prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_1 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_2 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_3 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv b/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv new file mode 100644 index 00000000..9f5bc668 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv @@ -0,0 +1,350 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// 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 +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + 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, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [16:1] cpu1_addr, + output reg [15:0] cpu1_q, + input [16:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [31:0] port2_q, + + input [16:2] sp_addr, + output reg [31:0] sp_q +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b001; // 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 + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 - data0 read burst terminated + 1 ras0 + 2 data1 returned + 3 CAS0 data1 returned + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_DS1b = 3'd0; +localparam STATE_READ1b = 3'd4; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- 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; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// 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 +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [16:1] addr_last[2]; +reg [16:2] addr_last2[2]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CPU2 = 2'd2; +localparam PORT_SP = 2'd1; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 8'd0, cpu1_addr }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 8'd0, cpu2_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (sp_addr != addr_last2[PORT_SP]) begin + next_port[1] = PORT_SP; + addr_latch_next[1] = { 1'b1, 7'd0, sp_addr, 1'b0 }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][16:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][16:2]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: port2_q[15:0] <= sd_din; + PORT_SP : sp_q[15:0] <= sd_din; + default: ; + endcase; + end + + if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + + if(t == STATE_READ1b && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end + PORT_SP : begin sp_q[31:16] <= sd_din; end + default: ; + endcase; + end + end +end + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd b/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl;