diff --git a/Arcade_MiST/Konami Gyruss/Gyruss.qpf b/Arcade_MiST/Konami Gyruss/Gyruss.qpf
new file mode 100644
index 00000000..12667bc5
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/Gyruss.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 = "00:21:03 December 03, 2019"
+
+# Revisions
+
+PROJECT_REVISION = "Gyruss"
+
diff --git a/Arcade_MiST/Konami Gyruss/Gyruss.qsf b/Arcade_MiST/Konami Gyruss/Gyruss.qsf
new file mode 100644
index 00000000..88e7856c
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/Gyruss.qsf
@@ -0,0 +1,253 @@
+# -------------------------------------------------------------------------- #
+#
+# 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:
+# Gyruss_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 SP4.26"
+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 Gyruss_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/sndcpu.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(Gyruss_MiST)
+
+ # Pin & Location Assignments
+ # ==========================
+
+ # Fitter Assignments
+ # ==================
+
+ # start DESIGN_PARTITION(Top)
+ # ---------------------------
+
+ # Incremental Compilation Assignments
+ # ===================================
+
+ # end DESIGN_PARTITION(Top)
+ # -------------------------
+
+# end ENTITY(Gyruss_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/Gyruss_MiST.sv
+set_global_assignment -name QIP_FILE rtl/pll.qip
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.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 VERILOG_FILE rtl/hiscore.v
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss_SND.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss_CPU.sv
+set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf.v
+set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf_medium.v
+set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf_light.v
+set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf_heavy.v
+set_global_assignment -name VERILOG_FILE rtl/Filters/audio_iir_filter.v
+set_global_assignment -name QIP_FILE rtl/custom/gyruss_custom.qip
+set_global_assignment -name VHDL_FILE rtl/ram_rom/spram.vhd
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/ram_rom/rom_loader.sv
+set_global_assignment -name QIP_FILE rtl/ram_rom/gyruss_ram_rom.qip
+set_global_assignment -name VHDL_FILE rtl/ram_rom/dpram_dc.vhd
+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 QIP_FILE ../../common/CPU/t48/i8039.qip
+set_global_assignment -name QIP_FILE ../../common/Sound/JT49/jt49.qip
+set_global_assignment -name SIGNALTAP_FILE output_files/sndcpu.stp
+set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Gyruss/Gyruss.sdc b/Arcade_MiST/Konami Gyruss/Gyruss.sdc
new file mode 100644
index 00000000..a28c4467
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/Gyruss.sdc
@@ -0,0 +1,136 @@
+## 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[0]"
+set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]"
+set aud_clk "pll|altpll_component|auto_generated|pll1|clk[0]"
+#**************************************************************
+# 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_clock_groups -asynchronous -group [get_clocks $sys_clk] -group [get_clocks $aud_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/Konami Gyruss/README.md b/Arcade_MiST/Konami Gyruss/README.md
new file mode 100644
index 00000000..16c55805
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/README.md
@@ -0,0 +1,11 @@
+# MiST port of Konami Gyruss by ACE
+
+https://github.com/MiSTer-devel/Arcade-Gyruss_MiSTer
+
+## Usage
+
+- Create ROM and ARC files from the MRA files using the MRA utility.
+ Example: mra -A -z /path/to/mame/roms "Gyruss.mra"
+- Copy the ROM files to the root of the SD Card
+- Copy the RBF and ARC files to the same folder on the SD Card
+- MRA utility: https://github.com/sebdel/mra-tools-c/
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Gyruss/meta/Gyruss.mra b/Arcade_MiST/Konami Gyruss/meta/Gyruss.mra
new file mode 100644
index 00000000..2eef1d3e
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/meta/Gyruss.mra
@@ -0,0 +1,75 @@
+
+ Gyruss
+
+ no
+ no
+
+
+
+
+ 1983
+ Konami
+ Shooter - Tube
+
+ gyruss
+ gyruss
+ 0218
+ Gyruss
+
+
+
+ 15kHz
+ vertical (cw)
+ no
+
+ 2 (alternating)
+ 4-way
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 01 00 00 00 00 FF 00 02 00 02 00 01 00 FF 00 00
+ 00 00 94 88 00 28 00 83
+ 00 00 94 0B 00 03 00 01
+
+
+
+
+
+
+
+
+ 20210430005030
+
diff --git a/Arcade_MiST/Konami Gyruss/rtl/Filters/audio_iir_filter.v b/Arcade_MiST/Konami Gyruss/rtl/Filters/audio_iir_filter.v
new file mode 100644
index 00000000..ad324f04
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Filters/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/Konami Gyruss/rtl/Filters/gyruss_lpf.v b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf.v
new file mode 100644
index 00000000..cb4ef070
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_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 remove aliasing on Gyruss.
+
+module gyruss_lpf(
+ input clk,
+ input reset,
+ input signed [15:0] in,
+ output signed [15:0] out);
+
+ localparam div = 10'd220; //Sample at 49.152/220 = 223418Hz
+
+ //Coefficients computed with Octave/Matlab/Online filter calculators.
+ //or with scipy.signal.bessel or similar tools
+
+ //0.045425748, 0.045425748
+ //1.0000000, -0.90914850
+ 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/Konami Gyruss/rtl/Filters/gyruss_lpf_heavy.v b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_heavy.v
new file mode 100644
index 00000000..e90bd881
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_heavy.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 match the heaviest low-pass filter on Gyruss.
+
+module gyruss_lpf_heavy(
+ input clk,
+ input reset,
+ input signed [15:0] in,
+ output signed [15:0] out);
+
+ localparam div = 10'd220; //Sample at 49.152/220 = 223418Hz
+
+ //Coefficients computed with Octave/Matlab/Online filter calculators.
+ //or with scipy.signal.bessel or similar tools
+
+ //0.0041276697, 0.0041276697
+ //1.0000000, -0.99174466
+ 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'd32498;
+ B1 = 18'd135;
+ B2 = 18'd135;
+ 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/Konami Gyruss/rtl/Filters/gyruss_lpf_light.v b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_light.v
new file mode 100644
index 00000000..1129e712
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_light.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 match the lightest low-pass filter on Gyruss.
+
+module gyruss_lpf_light(
+ input clk,
+ input reset,
+ input signed [15:0] in,
+ output signed [15:0] out);
+
+ localparam div = 10'd220; //Sample at 49.152/220 = 223418Hz
+
+ //Coefficients computed with Octave/Matlab/Online filter calculators.
+ //or with scipy.signal.bessel or similar tools
+
+ //0.017174022, 0.017174022
+ //1.0000000, -0.96565196
+ 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'd31642;
+ B1 = 18'd563;
+ B2 = 18'd563;
+ 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/Konami Gyruss/rtl/Filters/gyruss_lpf_medium.v b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_medium.v
new file mode 100644
index 00000000..603eba2b
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Filters/gyruss_lpf_medium.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 match the middle low-pass filter on Gyruss.
+
+module gyruss_lpf_medium(
+ input clk,
+ input reset,
+ input signed [15:0] in,
+ output signed [15:0] out);
+
+ localparam div = 10'd220; //Sample at 49.152/220 = 223418Hz
+
+ //Coefficients computed with Octave/Matlab/Online filter calculators.
+ //or with scipy.signal.bessel or similar tools
+
+ //0.0053024160, 0.0053024160
+ //1.0000000, -0.98939517
+ 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'd32420;
+ B1 = 18'd174;
+ B2 = 18'd174;
+ 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/Konami Gyruss/rtl/Gyruss.sv b/Arcade_MiST/Konami Gyruss/rtl/Gyruss.sv
new file mode 100644
index 00000000..038c637c
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Gyruss.sv
@@ -0,0 +1,192 @@
+//============================================================================
+//
+// Gyruss top-level module
+// Copyright (C) 2021 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.
+//
+//============================================================================
+
+//Module declaration, I/O ports
+module Gyruss
+(
+ input reset,
+ input clk_49m, //Actual frequency: 49.152MHz
+ input [1:0] coin, //0 = coin 1, 1 = coin 2
+ input [1:0] start_buttons, //0 = Player 1, 1 = Player 2
+ input [3:0] p1_joystick, p2_joystick, //0 = up, 1 = down, 2 = left, 3 = right
+ input p1_fire,
+ input p2_fire,
+ input btn_service,
+ input [23:0] dip_sw,
+ output video_hsync, video_vsync, video_csync,
+ output video_hblank, video_vblank,
+ output ce_pix,
+ output [2:0] video_r, video_g,
+ output [1:0] video_b,
+ output signed [15:0] sound_l, sound_r,
+
+ //Screen centering (alters HSync, VSync and VBlank timing in the Konami 082 to reposition the video output)
+ input [3:0] h_center, v_center,
+
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_data,
+ input ioctl_wr,
+
+ input pause,
+
+ input [10:0] hs_address,
+ input [7:0] hs_data_in,
+ output [7:0] hs_data_out,
+ input hs_write,
+ input hs_access,
+
+ output [15:0] main_cpu_rom_addr,
+ input [7:0] main_cpu_rom_do,
+ output [12:0] sub_cpu_rom_addr,
+ input [7:0] sub_cpu_rom_do,
+ output [12:0] sp_rom_addr,
+ input [31:0] sp_rom_do
+);
+
+//Linking signals between PCBs
+wire A5, A6, irq_trigger, cs_sounddata, cs_controls_dip1, cs_dip2, cs_dip3;
+wire [7:0] controls_dip, cpubrd_D;
+
+//ROM loader signals for MISTer (loads ROMs from SD card)
+wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i, ep6_cs_i, ep7_cs_i, ep8_cs_i, ep9_cs_i,
+ ep10_cs_i, ep11_cs_i, ep12_cs_i;
+wire cp_cs_i, tl_cs_i, sl_cs_i;
+
+//MiSTer data write selector
+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),
+ .ep6_cs(ep6_cs_i),
+ .ep7_cs(ep7_cs_i),
+ .ep8_cs(ep8_cs_i),
+ .ep9_cs(ep9_cs_i),
+ .ep10_cs(ep10_cs_i),
+ .ep11_cs(ep11_cs_i),
+ .ep12_cs(ep12_cs_i),
+ .cp_cs(cp_cs_i),
+ .tl_cs(tl_cs_i),
+ .sl_cs(sl_cs_i)
+);
+
+//Instantiate main PCB
+Gyruss_CPU main_pcb
+(
+ .reset(reset),
+ .clk_49m(clk_49m),
+ .red(video_r),
+ .green(video_g),
+ .blue(video_b),
+ .video_hsync(video_hsync),
+ .video_vsync(video_vsync),
+ .video_csync(video_csync),
+ .video_hblank(video_hblank),
+ .video_vblank(video_vblank),
+ .ce_pix(ce_pix),
+
+ .h_center(h_center),
+ .v_center(v_center),
+
+ .controls_dip(controls_dip),
+ .cpubrd_Dout(cpubrd_D),
+ .cpubrd_A5(A5),
+ .cpubrd_A6(A6),
+ .cs_sounddata(cs_sounddata),
+ .irq_trigger(irq_trigger),
+ .cs_dip2(cs_dip2),
+ .cs_dip3(cs_dip3),
+ .cs_controls_dip1(cs_controls_dip1),
+
+ .ep1_cs_i(ep1_cs_i),
+ .ep2_cs_i(ep2_cs_i),
+ .ep3_cs_i(ep3_cs_i),
+ .ep4_cs_i(ep4_cs_i),
+ .ep5_cs_i(ep5_cs_i),
+ .ep6_cs_i(ep6_cs_i),
+ .ep7_cs_i(ep7_cs_i),
+ .ep8_cs_i(ep8_cs_i),
+ .ep9_cs_i(ep9_cs_i),
+ .cp_cs_i(cp_cs_i),
+ .tl_cs_i(tl_cs_i),
+ .sl_cs_i(sl_cs_i),
+ .ioctl_addr(ioctl_addr),
+ .ioctl_wr(ioctl_wr),
+ .ioctl_data(ioctl_data),
+
+ .pause(pause),
+
+ .hs_address(hs_address),
+ .hs_data_in(hs_data_in),
+ .hs_data_out(hs_data_out),
+ .hs_write(hs_write),
+ .hs_access(hs_access),
+
+ .main_cpu_rom_addr(main_cpu_rom_addr),
+ .main_cpu_rom_do(main_cpu_rom_do),
+ .sub_cpu_rom_addr(sub_cpu_rom_addr),
+ .sub_cpu_rom_do(sub_cpu_rom_do),
+ .sp_rom_addr(sp_rom_addr),
+ .sp_rom_do(sp_rom_do)
+);
+
+//Instantiate sound PCB
+Gyruss_SND sound_pcb
+(
+ .reset(reset),
+ .clk_49m(clk_49m),
+ .irq_trigger(irq_trigger),
+ .cs_sounddata(cs_sounddata),
+ .dip_sw(dip_sw),
+ .coin(coin),
+ .start_buttons(start_buttons),
+ .p1_joystick(p1_joystick),
+ .p2_joystick(p2_joystick),
+ .p1_fire(p1_fire),
+ .p2_fire(p2_fire),
+ .btn_service(btn_service),
+
+ .cs_controls_dip1(cs_controls_dip1),
+ .cs_dip2(cs_dip2),
+ .cs_dip3(cs_dip3),
+ .cpubrd_A5(A5),
+ .cpubrd_A6(A6),
+ .cpubrd_Din(cpubrd_D),
+ .controls_dip(controls_dip),
+ .sound_l(sound_l),
+ .sound_r(sound_r),
+
+ .ep10_cs_i(ep10_cs_i),
+ .ep11_cs_i(ep11_cs_i),
+ .ep12_cs_i(ep12_cs_i),
+ .ioctl_addr(ioctl_addr),
+ .ioctl_wr(ioctl_wr),
+ .ioctl_data(ioctl_data)
+);
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv
new file mode 100644
index 00000000..3fc12647
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv
@@ -0,0 +1,996 @@
+//============================================================================
+//
+// Gyruss main PCB model
+// Copyright (C) 2021 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.
+//
+//============================================================================
+
+//Module declaration, I/O ports
+module Gyruss_CPU
+(
+ input reset,
+ input clk_49m, //Actual frequency: 49.152MHz
+ output [2:0] red, green, //8-bit RGB, 3 bits per color for red and green,
+ output [1:0] blue, //2 bits for blue
+ output video_hsync, video_vsync, video_csync, //CSync not needed for MISTer
+ output video_hblank, video_vblank,
+ output ce_pix,
+
+ input [7:0] controls_dip,
+ output [7:0] cpubrd_Dout,
+ output cpubrd_A5, cpubrd_A6,
+ output cs_sounddata, irq_trigger,
+ output cs_dip3, cs_dip2, cs_controls_dip1,
+
+ //Screen centering (alters HSync, VSync and VBlank timing in the Konami 082 to reposition the video output)
+ input [3:0] h_center, v_center,
+
+ input ep1_cs_i,
+ input ep2_cs_i,
+ input ep3_cs_i,
+ input ep4_cs_i,
+ input ep5_cs_i,
+ input ep6_cs_i,
+ input ep7_cs_i,
+ input ep8_cs_i,
+ input ep9_cs_i,
+ input cp_cs_i,
+ input tl_cs_i,
+ input sl_cs_i,
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_data,
+ input ioctl_wr,
+
+ input pause,
+
+ input [12:0] hs_address,
+ input [7:0] hs_data_in,
+ output [7:0] hs_data_out,
+ input hs_write,
+ input hs_access,
+
+ output [15:0] main_cpu_rom_addr,
+ input [7:0] main_cpu_rom_do,
+ output [12:0] sub_cpu_rom_addr,
+ input [7:0] sub_cpu_rom_do,
+ output [12:0] sp_rom_addr,
+ input [31:0] sp_rom_do
+);
+
+//------------------------------------------------------- Signal outputs -------------------------------------------------------//
+
+//Assign active high HBlank and VBlank outputs
+assign video_hblank = hblk;
+assign video_vblank = vblk;
+
+//Output pixel clock enable
+assign ce_pix = cen_6m;
+
+//Output select lines for player inputs and DIP switches to sound board
+assign cs_controls_dip1 = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b01) & n_ram_write;
+assign cs_dip2 = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b00) & n_ram_write;
+assign cs_dip3 = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b10) & n_ram_write;
+
+//Output primary MC6809E address lines A5 and A6 to sound board
+assign cpubrd_A5 = z80_A[5];
+assign cpubrd_A6 = z80_A[6];
+
+//Assign CPU board data output to sound board
+assign cpubrd_Dout = z80_Dout;
+
+//Generate and output chip select for latching sound data to sound CPU
+assign cs_sounddata = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b10) & ~n_ram_write;
+
+//Generate sound IRQ trigger
+wire cs_soundirq = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b01) & ~n_ram_write;
+reg sound_irq = 1;
+always_ff @(posedge clk_49m) begin
+ if(n_cen_3m) begin
+ if(cs_soundirq)
+ sound_irq <= 1;
+ else
+ sound_irq <= 0;
+ end
+end
+assign irq_trigger = sound_irq;
+
+//------------------------------------------------------- Clock division -------------------------------------------------------//
+
+//Generate 12.288MHz, 6.144MHz, 3.072MHz and 1.576MHz clock enables
+reg [4:0] div = 5'd0;
+always_ff @(posedge clk_49m) begin
+ div <= div + 5'd1;
+end
+reg [3:0] n_div = 4'd0;
+always_ff @(negedge clk_49m) begin
+ n_div <= n_div + 4'd1;
+end
+wire cen_12m = !div[1:0];
+wire cen_6m = !div[2:0];
+wire cen_3m = !div[3:0];
+wire n_cen_3m = !n_div;
+wire cen_1m5 = !div;
+
+//Generate E and Q clock enables for KONAMI-1 (code adapted from Sorgelig's phase generator used in the MiSTer Vectrex core)
+reg k1_E, k1_Q;
+always_ff @(posedge clk_49m) begin
+ reg [1:0] clk_phase = 0;
+ k1_E <= 0;
+ k1_Q <= 0;
+ if(cen_6m) begin
+ clk_phase <= clk_phase + 1'd1;
+ case(clk_phase)
+ 2'b01: k1_Q <= 1;
+ 2'b10: k1_E <= 1;
+ endcase
+ end
+end
+
+//------------------------------------------------------------ CPUs ------------------------------------------------------------//
+
+//Primary CPU - Zilog Z80 (uses T80s version of the T80 soft core)
+wire [15:0] z80_A;
+wire [7:0] z80_Dout;
+wire n_mreq, n_rd, n_rfsh;
+T80s u13G
+(
+ .RESET_n(reset),
+ .CLK(clk_49m),
+ .CEN(n_cen_3m & ~pause),
+ .NMI_n(z80_nmi),
+ .WAIT_n(n_wait),
+ .MREQ_n(n_mreq),
+ .RD_n(n_rd),
+ .RFSH_n(n_rfsh),
+ .A(z80_A),
+ .DI(z80_Din),
+ .DO(z80_Dout)
+);
+//Address decoding for Z80
+wire cs_rom1 = ~n_mreq & n_rfsh & (z80_A[15:13] == 3'b000);
+wire cs_rom2 = ~n_mreq & n_rfsh & (z80_A[15:13] == 3'b001);
+wire cs_rom3 = ~n_mreq & n_rfsh & (z80_A[15:13] == 3'b010);
+wire n_cs_k501 = ~(~n_mreq & n_rfsh & z80_A[15]);
+wire cs_mainlatch = (~n_k501_enable & z80_A[14]) & (z80_A[8:7] == 2'b11) & ~n_ram_write;
+wire cs_z80sharedram = (z80_A[14:13] == 2'b01) & ~n_k501_enable;
+wire n_cs_vram_wram = ~((z80_A[14:13] == 2'b00) & ~n_k501_enable);
+//Part of the RAM decoding is handled by the Konami 501 custom chip - instantiate an instance of this IC here
+wire n_wait, n_ram_write, n_k501_enable;
+wire [7:0] k501_D, k501_Dout;
+k501 u11E
+(
+ .CLK(clk_49m),
+ .CEN(cen_12m),
+ .H1(h_cnt[0]),
+ .H2(h_cnt[1]),
+ .RAM(n_cs_k501),
+ .RD(n_rd),
+ .WAIT(n_wait),
+ .WRITE(n_ram_write),
+ .ENABLE(n_k501_enable),
+ .Di(z80_Dout),
+ .XDi(k501_Din),
+ .Do(k501_Dout),
+ .XDo(k501_D)
+);
+//Multiplex data inputs to Z80
+wire [7:0] z80_Din = cs_rom1 ? eprom1_D:
+ cs_rom2 ? eprom2_D:
+ cs_rom3 ? eprom3_D:
+ ~n_cs_k501 ? k501_Dout:
+ 8'hFF;
+
+assign main_cpu_rom_addr = z80_A[14:0];
+//Z80 ROMs
+//ROM 1/3
+wire [7:0] eprom1_D = main_cpu_rom_do;
+/*
+eprom_1 u11J
+(
+ .ADDR(z80_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom1_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep1_cs_i),
+ .WR(ioctl_wr)
+);*/
+//ROM 2/3
+wire [7:0] eprom2_D = main_cpu_rom_do;
+/*
+eprom_2 u12J
+(
+ .ADDR(z80_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom2_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep2_cs_i),
+ .WR(ioctl_wr)
+);*/
+//ROM 3/3
+wire [7:0] eprom3_D = main_cpu_rom_do;
+/*
+eprom_3 u13J
+(
+ .ADDR(z80_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom3_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep3_cs_i),
+ .WR(ioctl_wr)
+);*/
+
+//Multiplex data input to Konami 501 data bus passthrough
+wire [7:0] k501_Din = (~n_cs_vram_wram & cs_wram0 & n_vram_wram_wr) ? wram0_D:
+ (~n_cs_vram_wram & cs_wram1 & n_vram_wram_wr) ? wram1_D:
+ (~n_cs_vram_wram & ~n_cs_vram & n_vram_wram_wr) ? vram_D:
+ (cs_z80sharedram & n_z80_sharedram_wr) ? z80_sharedram_D:
+ (cs_controls_dip1 | cs_dip2 | cs_dip3) ? controls_dip:
+ 8'hFF;
+
+//Main latch
+reg z80_nmi_mask = 0;
+reg flip = 0;
+always_ff @(posedge clk_49m) begin
+ if(!reset) begin
+ z80_nmi_mask <= 0;
+ flip <= 0;
+ end
+ else if(n_cen_3m) begin
+ if(cs_mainlatch)
+ case(z80_A[2:0])
+ 3'b000: z80_nmi_mask <= k501_D[0];
+ 3'b101: flip <= k501_D[0];
+ default:;
+ endcase
+ end
+end
+
+//Generate VBlank NMI for Z80
+reg z80_nmi = 1;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(!z80_nmi_mask)
+ z80_nmi <= 1;
+ else if(vblank_irq_en)
+ z80_nmi <= 0;
+ end
+end
+
+//VRAM
+wire [7:0] vram_D;
+spram #(8, 11) u5J
+(
+ .clk(clk_49m),
+ .we(~n_cs_vram_wram & ~n_cs_vram & ~n_vram_wram_wr),
+ .addr(vram_wram_A),
+ .data(k501_D),
+ .q(vram_D)
+);
+//Z80 work RAM
+//Bank 0
+
+// Hiscore mux
+wire [10:0] u3J_addr = hs_access ? hs_address[10:0] : vram_wram_A;
+wire [7:0] u3J_din = hs_access ? hs_data_in : k501_D;
+wire u3J_wren = hs_access ? hs_write : (~n_cs_vram_wram & cs_wram0 & ~n_vram_wram_wr);
+wire [7:0] u3J_dout;
+assign wram0_D = hs_access ? 8'h00 : u3J_dout;
+assign hs_data_out = hs_access ? u3J_dout : 8'h00;
+
+wire [7:0] wram0_D;
+spram #(8, 11) u3J
+(
+ .clk(clk_49m),
+ .we(u3J_wren),
+ .addr(u3J_addr),
+ .data(u3J_din),
+ .q(u3J_dout)
+);
+//Bank 1
+wire [7:0] wram1_D;
+spram #(8, 11) u2J
+(
+ .clk(clk_49m),
+ .we(~n_cs_vram_wram & cs_wram1 & ~n_vram_wram_wr),
+ .addr(vram_wram_A),
+ .data(k501_D),
+ .q(wram1_D)
+);
+//Generate select lines and write enable for work RAM and VRAM
+wire n_cs_vram = z80_A[12] & ~h_cnt[1];
+wire cs_wram0 = n_cs_vram & ~z80_A[11];
+wire cs_wram1 = n_cs_vram & z80_A[11];
+wire n_vram_wram_wr = n_cs_vram_wram | n_ram_write;
+
+//Shared RAM
+wire [7:0] z80_sharedram_D, k1_sharedram_D;
+dpram_dc #(.widthad_a(11)) u17C
+(
+ .clock_a(clk_49m),
+ .address_a(z80_A[10:0]),
+ .data_a(k501_D),
+ .q_a(z80_sharedram_D),
+ .wren_a(cs_z80sharedram & ~n_z80_sharedram_wr),
+
+ .clock_b(clk_49m),
+ .address_b(k1_A[10:0]),
+ .data_b(k1_Dout),
+ .q_b(k1_sharedram_D),
+ .wren_b(cs_k1sharedram & ~k1_rw & h_cnt[1])
+);
+//Generate write enable for Z80 section of shared RAM (active low)
+wire n_z80_sharedram_wr = ~cs_z80sharedram | n_ram_write;
+
+//Secondary CPU - KONAMI-1 custom encrypted MC6809E (uses synchronous version of Greg Miller's cycle-accurate MC6809E made by
+//Sorgelig with a wrapper to decrypt XOR/XNOR-encrypted opcodes and a further modification to Greg's MC6809E to directly
+//accept the opcodes)
+wire k1_rw;
+wire [15:0] k1_A;
+wire [7:0] k1_Dout;
+KONAMI1 u18F
+(
+ .CLK(clk_49m),
+ .fallE_en(k1_E),
+ .fallQ_en(k1_Q),
+ .D(k1_Din),
+ .DOut(k1_Dout),
+ .ADDR(k1_A),
+ .RnW(k1_rw),
+ .nIRQ(k1_irq),
+ .nFIRQ(1),
+ .nNMI(1),
+ .nHALT(1),
+ .nRESET(reset)
+);
+
+//Address decoding for KONAMI-1
+wire cs_beam = (k1_A[15:13] == 3'b000) & k1_rw;
+wire cs_k1irqmask = (k1_A[15:13] == 3'b001) & ~k1_rw;
+wire cs_spriteram = (k1_A[15:13] == 3'b010);
+wire cs_k1sharedram = (k1_A[15:13] == 3'b011);
+wire cs_rom4 = (k1_A[15:13] == 3'b111);
+//Multiplex data inputs to KONAMI-1
+wire [7:0] k1_Din = cs_beam ? v_cnt:
+ (cs_spriteram & cs_spriteram0 & ~spriteram0_wr) ? spriteram_D[7:0]:
+ (cs_spriteram & cs_spriteram1 & ~spriteram1_wr) ? spriteram_D[15:8]:
+ (cs_k1sharedram & k1_rw & h_cnt[1]) ? k1_sharedram_D:
+ cs_rom4 ? eprom4_D:
+ 8'hFF;
+
+assign sub_cpu_rom_addr = k1_A[12:0];
+//KONAMI-1 ROM
+wire [7:0] eprom4_D = sub_cpu_rom_do;
+/*
+eprom_4 u19E
+(
+ .ADDR(k1_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom4_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep4_cs_i),
+ .WR(ioctl_wr)
+);
+*/
+//Generate write enable for all KONAMI-1 RAM (active low)
+wire k1_rw1 = h1d | k1_rw;
+
+//Generate IRQ mask for KONAMI-1
+reg k1_irq_mask;
+always_ff @(posedge clk_49m) begin
+ if(!reset)
+ k1_irq_mask <= 0;
+ else if(cen_3m && cs_k1irqmask)
+ k1_irq_mask <= k1_Dout[0];
+end
+
+//Generate VBlank IRQ for KONAMI-1
+reg k1_irq = 1;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(!k1_irq_mask)
+ k1_irq <= 1;
+ else if(vblank_irq_en)
+ k1_irq <= 0;
+ end
+end
+
+//-------------------------------------------------------- Video timing --------------------------------------------------------//
+
+//Konami 082 custom chip - responsible for all video timings
+wire vblk, vblank_irq_en;
+wire [8:0] h_cnt;
+wire [7:0] v_cnt;
+k082 u11G
+(
+ .reset(1),
+ .clk(clk_49m),
+ .cen(cen_6m),
+ .h_center(h_center),
+ .v_center(v_center),
+ .n_vsync(video_vsync),
+ .sync(video_csync),
+ .n_hsync(video_hsync),
+ .vblk(vblk),
+ .vblk_irq_en(vblank_irq_en),
+ .h1(h_cnt[0]),
+ .h2(h_cnt[1]),
+ .h4(h_cnt[2]),
+ .h8(h_cnt[3]),
+ .h16(h_cnt[4]),
+ .h32(h_cnt[5]),
+ .h64(h_cnt[6]),
+ .h128(h_cnt[7]),
+ .n_h256(h_cnt[8]),
+ .v1(v_cnt[0]),
+ .v2(v_cnt[1]),
+ .v4(v_cnt[2]),
+ .v8(v_cnt[3]),
+ .v16(v_cnt[4]),
+ .v32(v_cnt[5]),
+ .v64(v_cnt[6]),
+ .v128(v_cnt[7])
+);
+
+//Latch vertical counter from 082 custom chip when the horizontal counter hits 256
+reg [7:0] vcnt_lat = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m && h_cnt == 9'd256)
+ vcnt_lat <= v_cnt;
+end
+
+//Latch least significant bit of horizontal counter (to be used for sprite RAM logic)
+reg h1d;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m)
+ h1d <= h_cnt[0];
+end
+
+//XOR horizontal counter bits [7:2] with HFLIP flag
+wire [7:2] hcnt_x = h_cnt[7:2] ^ {6{flip}};
+
+//XOR latched vertical counter bits with VFLIP flag
+wire [7:0] vcnt_x = vcnt_lat ^ {8{flip}};
+
+//--------------------------------------------------------- Tile layer ---------------------------------------------------------//
+
+//Generate addresses for VRAM
+wire [10:0] vram_wram_A = h_cnt[1] ? {h_cnt[2], vcnt_x[7:3], hcnt_x[7:3]} : z80_A[10:0];
+
+//LDO, labelled D1 in the Time Pilot schematics, signals to the tilemap logic when to latch tilemap codes from VRAM. It pulses
+//low when the lower 3 bits of the horizontal counter are all 1, then on the rising edge, tilemap codes are latched.
+//Set LDO as a register and latch a 0 when the 3 least significant bits of the horizontal counter are set to 1, otherwise latch
+//a 1
+reg ldo = 1;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[2:0] == 3'b111)
+ ldo <= 0;
+ else
+ ldo <= 1;
+end
+
+//Latch tilemap code from VRAM at every rising edge of LDO (equivalent to when LDO is low and the 3 least significant bits of
+//the horizontal counter are all set to 0)
+reg [7:0] tile_code = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(!ldo && h_cnt[2:0] == 3'b000)
+ tile_code <= vram_D;
+end
+
+//Latch tilemap attributes from VRAM at the rising edge of bit 2 of the horizontal counter when !H256 is high
+reg tile_attrib_latch = 1;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[2:0] == 3'b011)
+ tile_attrib_latch <= 0;
+ else
+ tile_attrib_latch <= 1;
+end
+reg [7:0] tile_attrib = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[8] && !tile_attrib_latch && h_cnt[2:0] == 3'b100)
+ tile_attrib <= vram_D;
+end
+
+//Latch tile color information, tilemap enable and flip signal for tilemap 083 custom chip every 8 pixels
+wire tile_flip = tile_hflip ^ ~flip;
+reg tile_083_flip = 0;
+reg tilemap_en = 0;
+reg [3:0] tile_color = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(h_cnt[2:0] == 3'b011) begin
+ tile_083_flip <= tile_flip;
+ tile_color <= tile_attrib[3:0];
+ tilemap_en <= tile_attrib[4];
+ end
+ else begin
+ tile_083_flip <= tile_083_flip;
+ tile_color <= tile_color;
+ tilemap_en <= tilemap_en;
+ end
+ end
+end
+
+//Generate address lines A1 - A3 of tilemap ROMs, CRA and tile flip attributes on the falling edge of horizontal
+//counter bit 2
+reg v1l, v2l, v4l, cra, tile_hflip, tile_vflip;
+reg old_h4;
+always_ff @(posedge clk_49m) begin
+ old_h4 <= h_cnt[2];
+ if(old_h4 && !h_cnt[2]) begin
+ v1l <= vcnt_x[0];
+ v2l <= vcnt_x[1];
+ v4l <= vcnt_x[2];
+ tile_hflip <= tile_attrib[6];
+ tile_vflip <= tile_attrib[7];
+ cra <= tile_attrib[5];
+ end
+end
+
+//Address tilemap ROMs
+assign tilerom_A[12] = cra;
+assign tilerom_A[11:4] = tile_code;
+assign tilerom_A[3:0] = {hcnt_x[2] ^ tile_hflip, v4l ^ tile_vflip, v2l ^ tile_vflip, v1l ^ tile_vflip};
+
+//Tilemap ROM
+wire [12:0] tilerom_A;
+wire [7:0] eprom5_D;
+
+eprom_5 u2H
+(
+ .ADDR(tilerom_A),
+ .CLK(clk_49m),
+ .DATA(eprom5_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep5_cs_i),
+ .WR(ioctl_wr)
+);
+
+//Konami 083 custom chip 1/2 - this one shifts the pixel data from tilemap ROMs
+k083 u3G
+(
+ .CK(clk_49m),
+ .CEN(cen_6m),
+ .LOAD(h_cnt[1:0] == 2'b11),
+ .FLIP(tile_083_flip),
+ .DB0i(eprom5_D),
+ .DSH0(tile_lut_A[1:0])
+);
+
+//Tilemap lookup PROM
+wire [7:0] tile_lut_A;
+assign tile_lut_A[7:6] = 2'b00;
+assign tile_lut_A[5:2] = tile_color;
+wire [3:0] tile_D;
+tile_lut_prom u3E
+(
+ .ADDR(tile_lut_A),
+ .CLK(clk_49m),
+ .DATA(tile_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(tl_cs_i),
+ .WR(ioctl_wr)
+);
+
+//-------------------------------------------------------- Sprite layer --------------------------------------------------------//
+
+//Generate sprite RAM enables (both active low)
+wire n_cs_spriteram = ~cs_spriteram | ~h_cnt[1];
+wire cs_spriteram0 = ~n_cs_spriteram & k1_A[1];
+wire cs_spriteram1 = ~n_cs_spriteram & ~k1_A[1];
+
+//Generate write enables for sprite RAM (active low)
+wire spriteram0_wr = ~n_cs_spriteram & ~k1_rw1 & k1_A[1];
+wire spriteram1_wr = ~n_cs_spriteram & ~k1_rw1 & ~k1_A[1];
+
+//Sprite RAM
+wire [15:0] spriteram_D;
+wire [9:0] spriteram_A;
+assign spriteram_A = h_cnt[1] ? {k1_A[10:2], k1_A[0]} : {3'b000, h_cnt[7], (h_cnt[8] ^ h_cnt[7]), h_cnt[6], h_cnt[3], h_cnt[4], h_cnt[5], h_cnt[2]};
+//Bank 0 (lower 4 bits)
+spram #(4, 10) u13A
+(
+ .clk(clk_49m),
+ .we(cs_spriteram & cs_spriteram0 & spriteram0_wr),
+ .addr(spriteram_A),
+ .data(k1_Dout[3:0]),
+ .q(spriteram_D[3:0])
+);
+//Bank 0 (upper 4 bits)
+spram #(4, 10) u14A
+(
+ .clk(clk_49m),
+ .we(cs_spriteram & cs_spriteram0 & spriteram0_wr),
+ .addr(spriteram_A),
+ .data(k1_Dout[7:4]),
+ .q(spriteram_D[7:4])
+);
+//Bank 1 (lower 4 bits)
+spram #(4, 10) u11A
+(
+ .clk(clk_49m),
+ .we(cs_spriteram & cs_spriteram1 & spriteram1_wr),
+ .addr(spriteram_A),
+ .data(k1_Dout[3:0]),
+ .q(spriteram_D[11:8])
+);
+//Bank 1 (upper 4 bits)
+spram #(4, 10) u12A
+(
+ .clk(clk_49m),
+ .we(cs_spriteram & cs_spriteram1 & spriteram1_wr),
+ .addr(spriteram_A),
+ .data(k1_Dout[7:4]),
+ .q(spriteram_D[15:12])
+);
+
+//Latch all data output from sprite RAM at 1/4 of the pixel clock
+reg [15:0] spriteram_reg = 16'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_1m5)
+ spriteram_reg <= spriteram_D;
+end
+
+//Konami 503 custom chip - generates sprite addresses for lower half of sprite ROMs, sprite line buffer control, enable for
+//sprite write and sprite flip for 083 custom chip.
+wire cs_linebuffer, sprite_flip;
+wire [5:0] k503_R;
+k503 u9F
+(
+ .OB(spriteram_reg[7:0]),
+ .VCNT(vcnt_lat),
+ .H4(h_cnt[2]),
+ .H8(0),
+ .LD(h_cnt[1:0] != 2'b11),
+ .OCS(cs_linebuffer),
+ .OFLP(sprite_flip),
+ .R(k503_R)
+);
+assign spriterom_A[5] = k503_R[5];
+assign spriterom_A[3:0] = k503_R[3:0];
+
+//Latch sprite code from sprite RAM bank 1 every 8 pixels
+reg [7:0] sprite_code = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[2:0] == 3'b000)
+ sprite_code <= spriteram_reg[15:8];
+end
+
+//Assign sprite code to address the upper 7 bits and bit 4 of the sprite ROMs
+assign spriterom_A[12:6] = sprite_code[7:1];
+assign spriterom_A[4] = sprite_code[0];
+
+assign sp_rom_addr = spriterom_A;
+//Sprite ROMs
+wire [12:0] spriterom_A;
+//ROM 1/4
+wire [7:0] eprom6_D = sp_rom_do[7:0];
+/*
+eprom_6 u9C
+(
+ .ADDR(spriterom_A),
+ .CLK(clk_49m),
+ .DATA(eprom6_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep6_cs_i),
+ .WR(ioctl_wr)
+);
+*/
+//ROM 2/4
+wire [7:0] eprom7_D = sp_rom_do[15:8];
+/*
+eprom_7 u8C
+(
+ .ADDR(spriterom_A),
+ .CLK(clk_49m),
+ .DATA(eprom7_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep7_cs_i),
+ .WR(ioctl_wr)
+);
+*/
+//ROM 3/4
+wire [7:0] eprom8_D = sp_rom_do[23:16];
+/*
+eprom_8 u7C
+(
+ .ADDR(spriterom_A),
+ .CLK(clk_49m),
+ .DATA(eprom8_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep8_cs_i),
+ .WR(ioctl_wr)
+);*/
+//ROM 4/4
+wire [7:0] eprom9_D = sp_rom_do[31:24];
+/*
+eprom_9 u6C
+(
+ .ADDR(spriterom_A),
+ .CLK(clk_49m),
+ .DATA(eprom9_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep9_cs_i),
+ .WR(ioctl_wr)
+);
+*/
+//Latch sprite attributes and horizontal position every 8 pixels
+reg [4:0] sprite_attrib = 5'd0;
+reg [7:0] sprite_hpos = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[2:0] == 3'b100) begin
+ sprite_attrib <= {spriteram_reg[5], spriteram_reg[3:0]};
+ sprite_hpos <= spriteram_reg[15:8];
+ end
+end
+
+//Multiplex sprite ROM data outputs based on the state of sprite attribute bit 4
+reg spriterom_sel = 0;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[2:0] == 3'b000)
+ spriterom_sel <= sprite_attrib[4];
+end
+wire [15:0] spriterom_D = spriterom_sel ? {eprom9_D, eprom7_D} : {eprom8_D, eprom6_D};
+
+//Konami 083 custom chip 2/2 - shifts the pixel data from sprite ROMs
+k083 u7F
+(
+ .CK(clk_49m),
+ .CEN(cen_6m),
+ .LOAD(h_cnt[1:0] == 2'b11),
+ .FLIP(sprite_k083_flip),
+ .DB0i(spriterom_D[7:0]),
+ .DB1i(spriterom_D[15:8]),
+ .DSH0(sprite_lut_A[1:0]),
+ .DSH1(sprite_lut_A[3:2])
+);
+
+//Latch sprite color information, enable for sprite line buffer, sprite 083 flip at every 8 pixels
+reg [3:0] sprite_color = 4'd0;
+reg sprite_lbuff_en, sprite_k083_flip;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(h_cnt[2:0] == 3'b011) begin
+ sprite_color <= sprite_attrib[3:0];
+ sprite_lbuff_en <= cs_linebuffer;
+ sprite_k083_flip <= sprite_flip;
+ end
+ end
+end
+
+//Assign sprite color information to the upper 4 bits of the sprite lookup PROM
+assign sprite_lut_A[7:4] = sprite_color;
+
+//Sprite lookup PROM
+wire [7:0] sprite_lut_A;
+wire [3:0] sprite_lut_D;
+sprite_lut_prom u6F
+(
+ .ADDR(sprite_lut_A),
+ .CLK(clk_49m),
+ .DATA(sprite_lut_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(sl_cs_i),
+ .WR(ioctl_wr)
+);
+
+//Konami 502 custom chip, responsible for generating sprites (sits between sprite ROMs and the sprite line buffer)
+wire [7:0] sprite_lbuff_Do;
+wire [4:0] sprite_D;
+wire sprite_lbuff_sel, sprite_lbuff_dec0, sprite_lbuff_dec1;
+k502 u6B
+(
+ .RESET(1),
+ .CK1(clk_49m),
+ .CK2(clk_49m),
+ .CEN(cen_6m),
+ .LD0(h_cnt[2:0] == 3'b000),
+ .H2(h_cnt[1]),
+ .H256(h_cnt[8]),
+ .SPAL(sprite_lut_D),
+ .SPLBi({sprite_lbuff1_D, sprite_lbuff0_D}),
+ .SPLBo(sprite_lbuff_Do),
+ .OSEL(sprite_lbuff_sel),
+ .OLD(sprite_lbuff_dec1),
+ .OCLR(sprite_lbuff_dec0),
+ .COL(sprite_D)
+);
+
+//----------------------------------------------------- Sprite line buffer -----------------------------------------------------//
+
+//Generate load and clear signals for counters generating addresses to sprite line buffer
+reg sprite_lbuff0_ld, sprite_lbuff1_ld, sprite_lbuff0_clr, sprite_lbuff1_clr;
+always_ff @(posedge clk_49m) begin
+ if(h_cnt[1:0] == 2'b11) begin
+ if(sprite_lbuff_dec0 && !sprite_lbuff_dec1) begin
+ sprite_lbuff0_clr <= 0;
+ sprite_lbuff1_clr <= 1;
+ end
+ else if(!sprite_lbuff_dec0 && sprite_lbuff_dec1) begin
+ sprite_lbuff0_clr <= 1;
+ sprite_lbuff1_clr <= 0;
+ end
+ else begin
+ sprite_lbuff0_clr <= 0;
+ sprite_lbuff1_clr <= 0;
+ end
+ end
+ else begin
+ sprite_lbuff0_clr <= 0;
+ sprite_lbuff1_clr <= 0;
+ end
+ if(h_cnt[2:0] == 3'b011) begin
+ if(!sprite_lbuff_dec1) begin
+ sprite_lbuff0_ld <= 1;
+ sprite_lbuff1_ld <= 0;
+ end
+ else begin
+ sprite_lbuff0_ld <= 0;
+ sprite_lbuff1_ld <= 1;
+ end
+ end
+ else begin
+ sprite_lbuff0_ld <= 0;
+ sprite_lbuff1_ld <= 0;
+ end
+end
+
+//Generate addresses for sprite line buffer
+//Bank 0, lower 4 bits
+reg [3:0] linebuffer0_l = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(sprite_lbuff0_clr)
+ linebuffer0_l <= 4'd0;
+ else
+ if(sprite_lbuff0_ld)
+ linebuffer0_l <= sprite_hpos[3:0];
+ else
+ linebuffer0_l <= linebuffer0_l + 4'd1;
+ end
+end
+//Bank 0, upper 4 bits
+reg [3:0] linebuffer0_h = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(sprite_lbuff0_clr)
+ linebuffer0_h <= 4'd0;
+ else
+ if(sprite_lbuff0_ld)
+ linebuffer0_h <= sprite_hpos[7:4];
+ else if(linebuffer0_l == 4'hF)
+ linebuffer0_h <= linebuffer0_h + 4'd1;
+ end
+end
+wire [7:0] sprite_lbuff0_A = {linebuffer0_h, linebuffer0_l};
+//Bank 1, lower 4 bits
+reg [3:0] linebuffer1_l = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(sprite_lbuff1_clr)
+ linebuffer1_l <= 4'd0;
+ else
+ if(sprite_lbuff1_ld)
+ linebuffer1_l <= sprite_hpos[3:0];
+ else
+ linebuffer1_l <= linebuffer1_l + 4'd1;
+ end
+end
+//Bank 1, upper 4 bits
+reg [3:0] linebuffer1_h = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m) begin
+ if(sprite_lbuff1_clr)
+ linebuffer1_h <= 4'd0;
+ else
+ if(sprite_lbuff1_ld)
+ linebuffer1_h <= sprite_hpos[7:4];
+ else if(linebuffer1_l == 4'hF)
+ linebuffer1_h <= linebuffer1_h + 4'd1;
+ end
+end
+wire [7:0] sprite_lbuff1_A = {linebuffer1_h, linebuffer1_l};
+
+//Generate chip select signals for sprite line buffer
+wire cs_sprite_lbuff0 = ~(sprite_lbuff_en & sprite_lbuff_sel);
+wire cs_sprite_lbuff1 = ~(sprite_lbuff_en & ~sprite_lbuff_sel);
+
+//Sprite line buffer bank 0
+wire [3:0] sprite_lbuff0_D;
+spram #(4, 8) u7A
+(
+ .clk(clk_49m),
+ .we(cen_6m & cs_sprite_lbuff0),
+ .addr(sprite_lbuff0_A),
+ .data(sprite_lbuff_Do[3:0]),
+ .q(sprite_lbuff0_D)
+);
+
+//Sprite line buffer bank 1
+wire [3:0] sprite_lbuff1_D;
+spram #(4, 8) u7B
+(
+ .clk(clk_49m),
+ .we(cen_6m & cs_sprite_lbuff1),
+ .addr(sprite_lbuff1_A),
+ .data(sprite_lbuff_Do[7:4]),
+ .q(sprite_lbuff1_D)
+);
+
+//----------------------------------------------------- Final video output -----------------------------------------------------//
+
+//Generate HBlank (active high) while the horizontal counter is between 141 and 268
+wire hblk = (h_cnt > 140 && h_cnt < 269);
+
+//Multiplex tile and sprite data
+wire tile_sprite_sel = (tilemap_en | sprite_D[4]);
+wire [3:0] tile_sprite_D = tile_sprite_sel ? tile_D[3:0] : sprite_D[3:0];
+
+//Latch pixel data for color PROM
+reg [4:0] pixel_D;
+always_ff @(posedge clk_49m) begin
+ if(cen_6m)
+ pixel_D <= {tile_sprite_sel, tile_sprite_D};
+end
+
+//Color PROM
+wire [4:0] color_A = pixel_D;
+wire [2:0] prom_red, prom_green;
+wire [1:0] prom_blue;
+color_prom u2A
+(
+ .ADDR(color_A),
+ .CLK(clk_49m),
+ .DATA({prom_blue, prom_green, prom_red}),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(cp_cs_i),
+ .WR(ioctl_wr)
+);
+
+//Output video signal from color PROMs, otherwise output black if in HBlank or VBlank
+assign red = (hblk | vblk) ? 3'h0 : prom_red;
+assign green = (hblk | vblk) ? 3'h0 : prom_green;
+assign blue = (hblk | vblk) ? 2'h0 : prom_blue;
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/Gyruss_MiST.sv b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_MiST.sv
new file mode 100644
index 00000000..6e232bb5
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_MiST.sv
@@ -0,0 +1,277 @@
+module Gyruss_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 = {
+ "GYRUSS;;",
+ "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 [23:0] dip_sw = ~status[31:8];
+
+assign LED = ~ioctl_downl;
+assign SDRAM_CLK = clock_49;
+assign SDRAM_CKE = 1;
+
+wire clock_49, pll_locked;
+pll pll(
+ .inclk0(CLOCK_27),
+ .c0(clock_49),//49.152MHz
+ .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 [15:0] audio_l, audio_r;
+wire hs, vs, cs;
+wire hb, vb;
+wire blankn = ~(hb | vb);
+wire [2:0] r, g;
+wire [1:0] b;
+wire key_strobe;
+wire key_pressed;
+wire [7:0] key_code;
+
+wire [15:0] main_rom_addr;
+wire [15:0] main_rom_do;
+wire [12:0] sub_rom_addr;
+wire [15:0] sub_rom_do;
+wire [12:0] sp_addr;
+wire [31:0] sp_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_49 ),
+ .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 - 16'hA000;
+
+reg port1_req, port2_req;
+sdram #(49) sdram(
+ .*,
+ .init_n ( pll_locked ),
+ .clk ( clock_49 ),
+
+ .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 : {2'b00, main_rom_addr[14:1]} ),
+ .cpu1_q ( main_rom_do ),
+ .cpu2_addr ( ioctl_downl ? 16'hffff : sub_rom_addr[12:1] + 16'h3000 ),
+ .cpu2_q ( sub_rom_do ),
+ .cpu3_addr ( ),
+ .cpu3_q ( ),
+
+ // port2 for sprite graphics
+ .port2_req ( port2_req ),
+ .port2_ack ( ),
+ .port2_a ( {bg_ioctl_addr[23:15], bg_ioctl_addr[12:0], bg_ioctl_addr[14]} ), // merge sprite roms to 32-bit wide words
+ .port2_ds ( {bg_ioctl_addr[13], ~bg_ioctl_addr[13]} ),
+ .port2_we ( ioctl_downl ),
+ .port2_d ( {ioctl_dout, ioctl_dout} ),
+ .port2_q ( ),
+
+ .sp_addr ( ioctl_downl ? 16'hffff : sp_addr ),
+ .sp_q ( sp_do )
+);
+
+// ROM download controller
+always @(posedge clock_49) 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_49) begin
+ reg ioctl_downlD;
+ ioctl_downlD <= ioctl_downl;
+ if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1;
+ reset <= status[0] | buttons[1] | ~rom_loaded;
+end
+
+Gyruss Gyruss(
+ .reset(~reset),
+ .clk_49m(clock_49),
+ .coin({~m_coin2,~m_coin1}),
+ .start_buttons({~m_two_players,~m_one_player}),
+ .p1_joystick({~m_right, ~m_left, ~m_down, ~m_up}),
+ .p2_joystick({~m_right2, ~m_left2, ~m_down2, ~m_up2}),
+ .p1_fire(~m_fireA),
+ .p2_fire(~m_fire2A),
+ .btn_service(~service),
+ .dip_sw(dip_sw),
+ .video_hsync(hs),
+ .video_vsync(vs),
+ .video_csync(cs),
+ .video_hblank(hb),
+ .video_vblank(vb),
+ .video_r(r),
+ .video_g(g),
+ .video_b(b),
+ .sound_l(audio_l),
+ .sound_r(audio_r),
+ .ioctl_addr(ioctl_addr),
+ .ioctl_data(ioctl_dout),
+ .ioctl_wr(ioctl_wr),
+
+ .main_cpu_rom_addr(main_rom_addr),
+ .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]),
+ .sub_cpu_rom_addr(sub_rom_addr),
+ .sub_cpu_rom_do(sub_rom_addr[0] ? sub_rom_do[15:8] : sub_rom_do[7:0]),
+ .sp_rom_addr(sp_addr),
+ .sp_rom_do(sp_do)
+);
+
+mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video(
+ .clk_sys ( clock_49 ),
+ .SPI_SCK ( SPI_SCK ),
+ .SPI_SS3 ( SPI_SS3 ),
+ .SPI_DI ( SPI_DI ),
+ .R ( blankn ? r : 0 ),
+ .G ( blankn ? g : 0 ),
+ .B ( blankn ? {b, b[1]} : 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 )
+ );
+
+user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io(
+ .clk_sys (clock_49 ),
+ .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 ),
+ .joystick_0 (joystick_0 ),
+ .joystick_1 (joystick_1 ),
+ .status (status )
+ );
+
+dac #(.C_bits(16))dac_l(
+ .clk_i(clock_49),
+ .res_n_i(1'b1),
+ .dac_i({~audio_l[15], audio_l[14:0]}),
+ .dac_o(AUDIO_L)
+ );
+
+dac #(.C_bits(16))dac_r(
+ .clk_i(clock_49),
+ .res_n_i(1'b1),
+ .dac_i({~audio_r[15], audio_r[14:0]}),
+ .dac_o(AUDIO_R)
+ );
+
+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_49 ),
+ .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/Konami Gyruss/rtl/Gyruss_SND.sv b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_SND.sv
new file mode 100644
index 00000000..9de01f7e
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_SND.sv
@@ -0,0 +1,762 @@
+//============================================================================
+//
+// Gyruss sound PCB model
+// Copyright (C) 2021 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.
+//
+//============================================================================
+
+module Gyruss_SND
+(
+ input reset,
+ input clk_49m, //Actual frequency: 49.152MHz
+ input [23:0] dip_sw,
+ input [1:0] coin, //0 = coin 1, 1 = coin 2
+ input [1:0] start_buttons, //0 = Player 1, 1 = Player 2
+ input [3:0] p1_joystick, p2_joystick, //0 = up, 1 = down, 2 = left, 3 = right
+ input p1_fire,
+ input p2_fire,
+ input btn_service,
+ input cpubrd_A5, cpubrd_A6,
+ input cs_controls_dip1, cs_dip2, cs_dip3,
+ input irq_trigger, cs_sounddata,
+ input [7:0] cpubrd_Din,
+
+ output [7:0] controls_dip,
+ output signed [15:0] sound_l, sound_r,
+
+ input ep10_cs_i,
+ input ep11_cs_i,
+ input ep12_cs_i,
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_data,
+ input ioctl_wr
+ //The sound board contains a video passthrough but video will instead be tapped
+ //straight from the CPU board implementation (this passthrough is redundant for
+ //an FPGA implementation)
+);
+
+//------------------------------------------------------- Signal outputs -------------------------------------------------------//
+
+//Multiplex controls and DIP switches to be output to CPU board
+assign controls_dip = cs_controls_dip1 ? controls_dip1:
+ cs_dip2 ? dip_sw[15:8]:
+ cs_dip3 ? dip_sw[23:16]:
+ 8'hFF;
+
+//------------------------------------------------------- Clock division -------------------------------------------------------//
+
+//Generate clock enables for sound data and IRQ logic, and DC offset removal
+reg [8:0] div = 9'd0;
+always_ff @(posedge clk_49m) begin
+ div <= div + 9'd1;
+end
+reg [3:0] n_div = 4'd0;
+always_ff @(negedge clk_49m) begin
+ n_div <= n_div + 4'd1;
+end
+wire n_cen_3m = !n_div;
+wire cen_dcrm = !div;
+
+//Generate 3.579545MHz clock enable for Z80, 1.789772MHz clock enable for AY-3-8910s, clock enable for AY-3-8910 timer
+//(uses Jotego's fractional clock divider from JTFRAME)
+wire cen_3m58, cen_1m79, cen_timer;
+jtframe_frac_cen #(11) sound_cen
+(
+ .clk(clk_49m),
+ .n(10'd60),
+ .m(10'd824),
+ .cen({cen_timer, 8'bZZZZZZZZ, cen_1m79, cen_3m58})
+);
+
+//Also use Jotego's fractional clock divider to generate an 8MHz clock enable for the i8039 MCU
+wire cen_8m;
+jtframe_frac_cen #(2) i8039_cen
+(
+ .clk(clk_49m),
+ .n(10'd42),
+ .m(10'd258),
+ .cen({1'bZ, cen_8m})
+);
+
+//------------------------------------------------------------ CPU -------------------------------------------------------------//
+
+//Sound CPU - Zilog Z80 (uses T80s version of the T80 soft core)
+wire [15:0] sound_A;
+wire [7:0] sound_Dout;
+wire n_m1, n_mreq, n_iorq, n_rd, n_wr, n_rfsh;
+T80s u6B
+(
+ .RESET_n(reset),
+ .CLK(clk_49m),
+ .CEN(cen_3m58),
+ .INT_n(n_irq),
+ .M1_n(n_m1),
+ .MREQ_n(n_mreq),
+ .IORQ_n(n_iorq),
+ .RD_n(n_rd),
+ .WR_n(n_wr),
+ .RFSH_n(n_rfsh),
+ .A(sound_A),
+ .DI(sound_Din),
+ .DO(sound_Dout)
+);
+//Address decoding for Z80
+wire n_rw = n_rd & n_wr;
+wire cs_soundrom0 = (~n_rw & ~n_mreq & n_rfsh & (sound_A[15:13] == 3'b000));
+wire cs_soundrom1 = (~n_rw & ~n_mreq & n_rfsh & (sound_A[15:13] == 3'b001));
+wire cs_soundram = (~n_rw & ~n_mreq & n_rfsh & (sound_A[15:13] == 3'b011));
+wire cs_sound = (~n_rw & ~n_mreq & n_rfsh & (sound_A[15:13] == 3'b100));
+wire cs_ay1 = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b000));
+wire cs_ay2 = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b001));
+wire cs_ay3 = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b010));
+wire cs_ay4 = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b011));
+wire cs_ay5 = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b100));
+wire cs_i8039_irq = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b101));
+wire cs_i8039_latch = (~n_iorq & n_m1 & (sound_A[4:2] == 3'b110));
+//Multiplex data input to Z80
+wire [7:0] sound_Din = cs_soundrom0 ? eprom10_D:
+ cs_soundrom1 ? eprom11_D:
+ (cs_soundram & n_wr) ? sndram_D:
+ cs_sound ? sound_D:
+ (~ay1_bdir & ay1_bc1) ? ay1_D:
+ (~ay2_bdir & ay2_bc1) ? ay2_D:
+ (~ay3_bdir & ay3_bc1) ? ay3_D:
+ (~ay4_bdir & ay4_bc1) ? ay4_D:
+ (~ay5_bdir & ay5_bc1) ? ay5_D:
+ 8'hFF;
+
+//Sound ROMs
+//ROM 1/2
+wire [7:0] eprom10_D;
+eprom_10 u6A
+(
+ .ADDR(sound_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom10_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep10_cs_i),
+ .WR(ioctl_wr)
+);
+//ROM 2/2
+wire [7:0] eprom11_D;
+eprom_11 u8A
+(
+ .ADDR(sound_A[12:0]),
+ .CLK(clk_49m),
+ .DATA(eprom11_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep11_cs_i),
+ .WR(ioctl_wr)
+);
+
+//Sound RAM (lower 4 bits)
+wire [7:0] sndram_D;
+spram #(4, 10) u4A
+(
+ .clk(clk_49m),
+ .we(cs_soundram & ~n_wr),
+ .addr(sound_A[9:0]),
+ .data(sound_Dout[3:0]),
+ .q(sndram_D[3:0])
+);
+
+//Sound RAM (upper 4 bits)
+spram #(4, 10) u5A
+(
+ .clk(clk_49m),
+ .we(cs_soundram & ~n_wr),
+ .addr(sound_A[9:0]),
+ .data(sound_Dout[7:4]),
+ .q(sndram_D[7:4])
+);
+
+//Latch sound data coming in from CPU board
+reg [7:0] sound_D = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(n_cen_3m && cs_sounddata)
+ sound_D <= cpubrd_Din;
+end
+
+//Generate Z80 interrupts
+wire irq_clr = (~reset | ~(n_iorq | n_m1));
+reg n_irq = 1;
+always_ff @(posedge clk_49m or posedge irq_clr) begin
+ if(irq_clr)
+ n_irq <= 1;
+ else if(n_cen_3m && irq_trigger)
+ n_irq <= 0;
+end
+
+//--------------------------------------------------- Controls & DIP switches --------------------------------------------------//
+
+//Multiplex player inputs and DIP switch bank 1
+wire [7:0] controls_dip1 = ({cpubrd_A6, cpubrd_A5} == 2'b00) ? {3'b111, start_buttons, btn_service, coin}:
+ ({cpubrd_A6, cpubrd_A5} == 2'b01) ? {3'b111, p1_fire, p1_joystick[1:0], p1_joystick[3:2]}:
+ ({cpubrd_A6, cpubrd_A5} == 2'b10) ? {3'b111, p2_fire, p2_joystick[1:0], p2_joystick[3:2]}:
+ ({cpubrd_A6, cpubrd_A5} == 2'b11) ? dip_sw[7:0]:
+ 8'hFF;
+
+//--------------------------------------------------------- Sound chips --------------------------------------------------------//
+
+//Generate BC1 and BDIR signals for the five AY-3-8910s
+wire ay1_bdir = ~(~cs_ay1 | sound_A[0]);
+wire ay1_bc1 = ~(~cs_ay1 | sound_A[1]);
+wire ay2_bdir = ~(~cs_ay2 | sound_A[0]);
+wire ay2_bc1 = ~(~cs_ay2 | sound_A[1]);
+wire ay3_bdir = ~(~cs_ay3 | sound_A[0]);
+wire ay3_bc1 = ~(~cs_ay3 | sound_A[1]);
+wire ay4_bdir = ~(~cs_ay4 | sound_A[0]);
+wire ay4_bc1 = ~(~cs_ay4 | sound_A[1]);
+wire ay5_bdir = ~(~cs_ay5 | sound_A[0]);
+wire ay5_bc1 = ~(~cs_ay5 | sound_A[1]);
+
+//AY-3-8910 timer (code adapted from MiSTer-X's Gyruss core)
+reg [3:0] timer_sel;
+wire [3:0] timer_val;
+always_comb begin
+ case(timer_sel)
+ 0: timer_val = 4'h0;
+ 1: timer_val = 4'h1;
+ 2: timer_val = 4'h2;
+ 3: timer_val = 4'h3;
+ 4: timer_val = 4'h4;
+ 5: timer_val = 4'h9;
+ 6: timer_val = 4'hA;
+ 7: timer_val = 4'hB;
+ 8: timer_val = 4'hA;
+ 9: timer_val = 4'hD;
+ default: timer_val = 0;
+ endcase
+end
+reg [3:0] timer = 4'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_timer) begin
+ timer <= timer_val;
+ timer_sel <= (timer_sel == 4'd9) ? 4'd0 : (timer_sel + 4'd1);
+ end
+end
+
+//Sound chip 1 (AY-3-8910 - uses JT49 by Jotego)
+wire [7:0] ay1_D;
+wire [7:0] ay1A_raw, ay1B_raw, ay1C_raw;
+wire [5:0] ay1_filter;
+jt49_bus #(.COMP(3'b100)) u11D
+(
+ .rst_n(reset),
+ .clk(clk_49m),
+ .clk_en(cen_1m79),
+ .bdir(ay1_bdir),
+ .bc1(ay1_bc1),
+ .din(sound_Dout),
+ .sel(1),
+ .dout(ay1_D),
+ .A(ay1A_raw),
+ .B(ay1B_raw),
+ .C(ay1C_raw),
+ .IOB_out({2'bZZ, ay1_filter})
+);
+
+//Sound chip 2 (AY-3-8910 - uses JT49 by Jotego)
+wire [7:0] ay2_D;
+wire [7:0] ay2A_raw, ay2B_raw, ay2C_raw;
+wire [5:0] ay2_filter;
+jt49_bus #(.COMP(3'b100)) u12D
+(
+ .rst_n(reset),
+ .clk(clk_49m),
+ .clk_en(cen_1m79),
+ .bdir(ay2_bdir),
+ .bc1(ay2_bc1),
+ .din(sound_Dout),
+ .sel(1),
+ .dout(ay2_D),
+ .A(ay2A_raw),
+ .B(ay2B_raw),
+ .C(ay2C_raw),
+ .IOB_out({2'bZZ, ay2_filter})
+);
+
+//Sound chip 3 (AY-3-8910 - uses JT49 by Jotego)
+wire [7:0] ay3_D;
+wire [7:0] ay3A_raw, ay3B_raw, ay3C_raw;
+jt49_bus #(.COMP(3'b100)) u10B
+(
+ .rst_n(reset),
+ .clk(clk_49m),
+ .clk_en(cen_1m79),
+ .bdir(ay3_bdir),
+ .bc1(ay3_bc1),
+ .din(sound_Dout),
+ .sel(1),
+ .dout(ay3_D),
+ .A(ay3A_raw),
+ .B(ay3B_raw),
+ .C(ay3C_raw),
+ .IOA_in({4'b0000, timer})
+);
+
+//Sound chip 4 (AY-3-8910 - uses JT49 by Jotego)
+wire [7:0] ay4_D;
+wire [7:0] ay4A_raw, ay4B_raw, ay4C_raw;
+jt49_bus #(.COMP(3'b100)) u9B
+(
+ .rst_n(reset),
+ .clk(clk_49m),
+ .clk_en(cen_1m79),
+ .bdir(ay4_bdir),
+ .bc1(ay4_bc1),
+ .din(sound_Dout),
+ .sel(1),
+ .dout(ay4_D),
+ .A(ay4A_raw),
+ .B(ay4B_raw),
+ .C(ay4C_raw)
+);
+
+//Sound chip 5 (AY-3-8910 - uses JT49 by Jotego)
+wire [7:0] ay5_D;
+wire [7:0] ay5A_raw, ay5B_raw, ay5C_raw;
+jt49_bus #(.COMP(3'b100)) u8B
+(
+ .rst_n(reset),
+ .clk(clk_49m),
+ .clk_en(cen_1m79),
+ .bdir(ay5_bdir),
+ .bc1(ay5_bc1),
+ .din(sound_Dout),
+ .sel(1),
+ .dout(ay5_D),
+ .A(ay5A_raw),
+ .B(ay5B_raw),
+ .C(ay5C_raw)
+);
+
+//Sound chip 6 (Intel 8039 MCU - uses t8039_notri variant of T48)
+wire [7:0] i8039_raw;
+wire [7:0] i8039_Dout;
+wire i8039_ale, n_i8039_psen, n_i8039_rd, n_i8039_irq_clr;
+t8039_notri u7H
+(
+ .xtal_i(clk_49m),
+ .xtal_en_i(cen_8m),
+ .reset_n_i(reset),
+ .int_n_i(n_i8039_irq),
+ .ea_i(1),
+ .rd_n_o(n_i8039_rd),
+ .psen_n_o(n_i8039_psen),
+ .ale_o(i8039_ale),
+ .db_i(i8039_Din),
+ .db_o(i8039_Dout),
+ .p2_o({n_i8039_irq_clr, 3'bZZZ, eprom12_A[11:8]}),
+ .p1_o(i8039_raw)
+);
+//Multiplex data into i8039
+wire [7:0] i8039_Din = ~n_i8039_psen ? eprom12_D:
+ ~n_i8039_rd ? i8039_latch:
+ 8'hFF;
+
+//i8039 ROM
+wire [11:0] eprom12_A;
+wire [7:0] eprom12_D;
+eprom_12 u11H
+(
+ .ADDR(eprom12_A),
+ .CLK(clk_49m),
+ .DATA(eprom12_D),
+ .ADDR_DL(ioctl_addr),
+ .CLK_DL(clk_49m),
+ .DATA_IN(ioctl_data),
+ .CS_DL(ep12_cs_i),
+ .WR(ioctl_wr)
+);
+
+//Latch data from Z80 to i8039
+reg [7:0] i8039_latch = 8'd0;
+always_ff @(posedge clk_49m) begin
+ if(cen_3m58 && cs_i8039_latch)
+ i8039_latch <= sound_Dout;
+end
+
+//Latch address lines A[7:0] for MCU ROM
+reg [7:0] i8039_rom_lat = 8'd0;
+always_ff @(negedge i8039_ale) begin
+ i8039_rom_lat <= i8039_Dout;
+end
+assign eprom12_A[7:0] = i8039_rom_lat;
+
+//Generate i8039 IRQ
+reg n_i8039_irq = 1;
+always_ff @(posedge clk_49m) begin
+ if(!n_i8039_irq_clr)
+ n_i8039_irq <= 1;
+ else if(cen_3m58 && cs_i8039_irq)
+ n_i8039_irq <= 0;
+end
+
+//----------------------------------------------------- Final audio output -----------------------------------------------------//
+
+//Apply gain and remove DC offset from AY-3-8910s and i8039 (uses jt49_dcrm2 from JT49 by Jotego for DC offset removal)
+wire signed [15:0] ay1A_dcrm, ay1B_dcrm, ay1C_dcrm, ay2A_dcrm, ay2B_dcrm, ay2C_dcrm;
+wire signed [15:0] ay3A_sound, ay3B_sound, ay3C_sound, ay4A_sound, ay4B_sound, ay4C_sound, ay5A_sound, ay5B_sound, ay5C_sound;
+wire signed [15:0] i8039_sound;
+jt49_dcrm2 #(16) dcrm_ay1A
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay1A_raw, 4'd0}),
+ .dout(ay1A_dcrm)
+);
+jt49_dcrm2 #(16) dcrm_ay1B
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay1B_raw, 4'd0}),
+ .dout(ay1B_dcrm)
+);
+jt49_dcrm2 #(16) dcrm_ay1C
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay1C_raw, 4'd0}),
+ .dout(ay1C_dcrm)
+);
+
+jt49_dcrm2 #(16) dcrm_ay2A
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay2A_raw, 4'd0}),
+ .dout(ay2A_dcrm)
+);
+jt49_dcrm2 #(16) dcrm_ay2B
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay2B_raw, 4'd0}),
+ .dout(ay2B_dcrm)
+);
+jt49_dcrm2 #(16) dcrm_ay2C
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay2C_raw, 4'd0}),
+ .dout(ay2C_dcrm)
+);
+
+jt49_dcrm2 #(16) dcrm_ay3A
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay3A_raw, 4'd0}),
+ .dout(ay3A_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay3B
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay3B_raw, 4'd0}),
+ .dout(ay3B_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay3C
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay3C_raw, 4'd0}),
+ .dout(ay3C_sound)
+);
+
+jt49_dcrm2 #(16) dcrm_ay4A
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay4A_raw, 4'd0}),
+ .dout(ay4A_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay4B
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay4B_raw, 4'd0}),
+ .dout(ay4B_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay4C
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay4C_raw, 4'd0}),
+ .dout(ay4C_sound)
+);
+
+jt49_dcrm2 #(16) dcrm_ay5A
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay5A_raw, 4'd0}),
+ .dout(ay5A_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay5B
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay5B_raw, 4'd0}),
+ .dout(ay5B_sound)
+);
+jt49_dcrm2 #(16) dcrm_ay5C
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({4'd0, ay5C_raw, 4'd0}),
+ .dout(ay5C_sound)
+);
+
+jt49_dcrm2 #(16) dcrm_i8039
+(
+ .clk(clk_49m),
+ .cen(cen_dcrm),
+ .rst(~reset),
+ .din({2'd0, i8039_raw, 6'd0}),
+ .dout(i8039_sound)
+);
+
+//Two of Gyruss's AY-3-8910s contain selectable low-pass filters with the following cutoff frequencies:
+//3386.28Hz, 723.43Hz, 596.09Hz
+//Model this here (the PCB handles this via 3 74HC4066 switching ICs located at 9E, 9F and 10F)
+wire signed [15:0] ay1A_light, ay1A_med, ay1A_heavy, ay1B_light, ay1B_med, ay1B_heavy, ay1C_light, ay1C_med, ay1C_heavy;
+wire signed [15:0] ay2A_light, ay2A_med, ay2A_heavy, ay2B_light, ay2B_med, ay2B_heavy, ay2C_light, ay2C_med, ay2C_heavy;
+wire signed [15:0] ay1A_sound, ay1B_sound, ay1C_sound, ay2A_sound, ay2B_sound, ay2C_sound;
+gyruss_lpf_light ay1A_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1A_dcrm),
+ .out(ay1A_light)
+);
+gyruss_lpf_medium ay1A_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1A_dcrm),
+ .out(ay1A_med)
+);
+gyruss_lpf_heavy ay1A_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1A_dcrm),
+ .out(ay1A_heavy)
+);
+gyruss_lpf_light ay1B_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1B_dcrm),
+ .out(ay1B_light)
+);
+gyruss_lpf_medium ay1B_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1B_dcrm),
+ .out(ay1B_med)
+);
+gyruss_lpf_heavy ay1B_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1B_dcrm),
+ .out(ay1B_heavy)
+);
+gyruss_lpf_light ay1C_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1C_dcrm),
+ .out(ay1C_light)
+);
+gyruss_lpf_medium ay1C_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1C_dcrm),
+ .out(ay1C_med)
+);
+gyruss_lpf_heavy ay1C_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay1C_dcrm),
+ .out(ay1C_heavy)
+);
+
+gyruss_lpf_light ay2A_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2A_dcrm),
+ .out(ay2A_light)
+);
+gyruss_lpf_medium ay2A_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2A_dcrm),
+ .out(ay2A_med)
+);
+gyruss_lpf_heavy ay2A_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2A_dcrm),
+ .out(ay2A_heavy)
+);
+gyruss_lpf_light ay2B_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2B_dcrm),
+ .out(ay2B_light)
+);
+gyruss_lpf_medium ay2B_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2B_dcrm),
+ .out(ay2B_med)
+);
+gyruss_lpf_heavy ay2B_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2B_dcrm),
+ .out(ay2B_heavy)
+);
+gyruss_lpf_light ay2C_lpf_light
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2C_dcrm),
+ .out(ay2C_light)
+);
+gyruss_lpf_medium ay2C_lpf_medium
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2C_dcrm),
+ .out(ay2C_med)
+);
+gyruss_lpf_heavy ay2C_lpf_heavy
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(ay2C_dcrm),
+ .out(ay2C_heavy)
+);
+
+//Apply audio filtering based on the state of the low-pass filter controls
+always_comb begin
+ case(ay1_filter[1:0])
+ 2'b00: ay1A_sound = ay1A_dcrm;
+ 2'b01: ay1A_sound = ay1A_light <<< 1;
+ 2'b10: ay1A_sound = ay1A_med <<< 1;
+ 2'b11: ay1A_sound = ay1A_heavy <<< 1;
+ endcase
+ case(ay1_filter[3:2])
+ 2'b00: ay1B_sound = ay1B_dcrm;
+ 2'b01: ay1B_sound = ay1B_light <<< 1;
+ 2'b10: ay1B_sound = ay1B_med <<< 1;
+ 2'b11: ay1B_sound = ay1B_heavy <<< 1;
+ endcase
+ case(ay1_filter[5:4])
+ 2'b00: ay1C_sound = ay1C_dcrm;
+ 2'b01: ay1C_sound = ay1C_light <<< 1;
+ 2'b10: ay1C_sound = ay1C_med <<< 1;
+ 2'b11: ay1C_sound = ay1C_heavy <<< 1;
+ endcase
+ case(ay2_filter[1:0])
+ 2'b00: ay2A_sound = ay2A_dcrm;
+ 2'b01: ay2A_sound = ay2A_light <<< 1;
+ 2'b10: ay2A_sound = ay2A_med <<< 1;
+ 2'b11: ay2A_sound = ay2A_heavy <<< 1;
+ endcase
+ case(ay2_filter[3:2])
+ 2'b00: ay2B_sound = ay2B_dcrm;
+ 2'b01: ay2B_sound = ay2B_light <<< 1;
+ 2'b10: ay2B_sound = ay2B_med <<< 1;
+ 2'b11: ay2B_sound = ay2B_heavy <<< 1;
+ endcase
+ case(ay2_filter[5:4])
+ 2'b00: ay2C_sound = ay2C_dcrm;
+ 2'b01: ay2C_sound = ay2C_light <<< 1;
+ 2'b10: ay2C_sound = ay2C_med <<< 1;
+ 2'b11: ay2C_sound = ay2C_heavy <<< 1;
+ endcase
+end
+
+//Mix the left and right outputs, then apply an antialiasing low-pass filter to eliminate ringing noise from the
+//AY-3-8910s and output the final result (this game has variable low-pass filtering based on how loud the PCB's volume dials
+//are set and will be modeled externally)
+wire signed [15:0] left_mix = (ay2A_sound + ay2B_sound + ay2C_sound + ay5A_sound + ay5B_sound + ay5C_sound + i8039_sound);
+wire signed [15:0] right_mix = (ay1A_sound + ay1B_sound + ay1C_sound + ay3A_sound + ay3B_sound + ay3C_sound + ay4A_sound +
+ ay4B_sound + ay4C_sound);
+
+wire signed [15:0] left_lpf, right_lpf;
+gyruss_lpf aalpf_l
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(left_mix),
+ .out(left_lpf)
+);
+
+gyruss_lpf aalpf_r
+(
+ .clk(clk_49m),
+ .reset(~reset),
+ .in(right_mix),
+ .out(right_lpf)
+);
+
+assign sound_l = (ay2A_sound + ay2B_sound + ay2C_sound + ay5A_sound + ay5B_sound + ay5C_sound + i8039_sound);
+assign sound_r = (ay1A_sound + ay1B_sound + ay1C_sound + ay3A_sound + ay3B_sound + ay3C_sound + ay4A_sound +
+ ay4B_sound + ay4C_sound);
+//assign sound_l = left_lpf;
+//assign sound_r = right_lpf;
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/build_id.tcl b/Arcade_MiST/Konami Gyruss/rtl/build_id.tcl
new file mode 100644
index 00000000..938515d8
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/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/Konami Gyruss/rtl/custom/KONAMI-1/KONAMI1.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/KONAMI1.sv
new file mode 100644
index 00000000..9126e795
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/KONAMI1.sv
@@ -0,0 +1,79 @@
+//============================================================================
+//
+// SystemVerilog implementation of the KONAMI-1 custom chip, a custom MC6809E
+// variant with XOR/XNOR encryption
+// Implements MC6809E core by Greg Miller (synchronous version modified by
+// Sorgelig with further modifications to allow direct injection of opcodes)
+// Copyright (C) 2021 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.
+//
+//============================================================================
+
+module KONAMI1
+(
+ input CLK,
+ input fallE_en,
+ input fallQ_en,
+
+ input [7:0] D,
+ output [7:0] DOut,
+ output [15:0] ADDR,
+ output RnW,
+ output BS,
+ output BA,
+ input nIRQ,
+ input nFIRQ,
+ input nNMI,
+ output AVMA,
+ output BUSY,
+ output LIC,
+ input nHALT,
+ input nRESET
+);
+
+//Decrypt XOR/XNOR encrypted opcode
+wire [7:0] opcode = D ^ {ADDR[1], 1'b0, ~ADDR[1], 1'b0, ADDR[3], 1'b0, ~ADDR[3], 1'b0};
+
+//Passthrough to modified MC6809is core with direct opcode injection and IS_KONAMI1 parameter set
+//to TRUE
+mc6809is #(.IS_KONAMI1("TRUE")) cpucore
+(
+ .CLK(CLK),
+ .fallE_en(fallE_en),
+ .fallQ_en(fallQ_en),
+ .OP(opcode),
+ .nHALT(nHALT),
+ .nRESET(nRESET),
+ .D(D),
+ .DOut(DOut),
+ .ADDR(ADDR),
+ .RnW(RnW),
+ .BS(BS),
+ .BA(BA),
+ .nIRQ(nIRQ),
+ .nFIRQ(nFIRQ),
+ .nNMI(nNMI),
+ .AVMA(AVMA),
+ .BUSY(BUSY),
+ .LIC(LIC),
+ .nDMABREQ(1)
+);
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v b/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v
new file mode 100644
index 00000000..18467022
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v
@@ -0,0 +1,4162 @@
+`timescale 1ns / 1ns
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Greg Miller
+// Copyright (c) 2016, Greg Miller
+//
+// Create Date: 14:26:59 08/13/2016
+// Design Name:
+// Module Name: mc6809
+// Project Name: Cycle-Accurate 6809 Core
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies: Intended to be standalone Vanilla Verilog.
+//
+// Revision:
+// Revision 1.0 - Initial Release
+// Revision 1.0s - Sinchronous version (by Sorgelig)
+// Revision 1.0sk - Add direct injection of KONAMI-1 encrypted opcodes (by Ace)
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+//
+// The 6809 has incomplete instruction decoding. A collection of instructions, if met, end up actually behaving like
+// a binary-adjacent neighbor.
+//
+// The soft core permits three different behaviors for this situation, controlled by the instantiation parameter
+// ILLEGAL_INSTRUCTIONS
+//
+// "GHOST" - Mimic the 6809's incomplete decoding. This is as similar to a hard 6809 as is practical. [DEFAULT]
+//
+// "STOP" - Cause the soft core to cease execution, placing $DEAD on the address bus and R/W to 'read'. Interrupts,
+// bus control (/HALT, /DMABREQ), etc. are ignored. The core intentionally seizes in this instance.
+// (Frankly, this is useful when making changes to the core and you have a logic analyzer connected.)
+//
+// "IGNORE"- Cause the soft core to merely ignore illegal instructions. It will consider them 1-byte instructions and
+// attempt to fetch and run an exception 1 byte later.
+//
+
+module mc6809is
+#(
+ parameter ILLEGAL_INSTRUCTIONS="GHOST",
+ parameter IS_KONAMI1="FALSE"
+)
+(
+ input CLK,
+ input fallE_en,
+ input fallQ_en,
+ input [7:0] OP,
+
+ input [7:0] D,
+ output [7:0] DOut,
+ output [15:0] ADDR,
+ output RnW,
+ output BS,
+ output BA,
+ input nIRQ,
+ input nFIRQ,
+ input nNMI,
+ output AVMA,
+ output BUSY,
+ output LIC,
+ input nHALT,
+ input nRESET,
+ input nDMABREQ,
+ output [111:0] RegData
+);
+
+reg [7:0] DOutput;
+
+assign DOut = DOutput;
+
+reg RnWOut; // Combinatorial
+
+reg rLIC;
+assign LIC = rLIC;
+
+reg rAVMA;
+assign AVMA = rAVMA;
+
+reg rBUSY;
+assign BUSY = rBUSY;
+
+// Bus control
+// BS BA
+// 0 0 normal (CPU running, CPU is master)
+// 0 1 Interrupt Ack
+// 1 0 Sync Ack
+// 1 1 CPU has gone high-Z on A, D, R/W
+//
+
+assign RnW = RnWOut;
+
+
+/////////////////////////////////////////////////
+// Vectors
+`define RESET_VECTOR 16'HFFFE
+`define NMI_VECTOR 16'HFFFC
+`define SWI_VECTOR 16'HFFFA
+`define IRQ_VECTOR 16'HFFF8
+`define FIRQ_VECTOR 16'HFFF6
+`define SWI2_VECTOR 16'HFFF4
+`define SWI3_VECTOR 16'HFFF2
+`define Reserved_VECTOR 16'HFFF0
+
+//////////////////////////////////////////////////////
+// Latched registers
+//
+
+// The last-latched copy.
+reg [7:0] a;
+reg [7:0] b;
+reg [15:0] x;
+reg [15:0] y;
+reg [15:0] u;
+reg [15:0] s;
+reg [15:0] pc;
+reg [7:0] dp;
+reg [7:0] cc;
+reg [15:0] tmp;
+reg [15:0] addr;
+reg [15:0] ea;
+
+
+// Debug ability to export register contents
+assign RegData[7:0] = a;
+assign RegData[15:8] = b;
+assign RegData[31:16] = x;
+assign RegData[47:32] = y;
+assign RegData[63:48] = s;
+assign RegData[79:64] = u;
+assign RegData[87:80] = cc;
+assign RegData[95:88] = dp;
+assign RegData[111:96] = pc;
+
+
+
+// The values as being calculated
+reg [7:0] a_nxt;
+reg [7:0] b_nxt;
+reg [15:0] x_nxt;
+reg [15:0] y_nxt;
+reg [15:0] u_nxt;
+reg [15:0] s_nxt;
+reg [15:0] pc_nxt;
+reg [7:0] dp_nxt;
+reg [7:0] cc_nxt;
+reg [15:0] addr_nxt;
+reg [15:0] ea_nxt;
+reg [15:0] tmp_nxt;
+
+reg BS_nxt;
+reg BA_nxt;
+
+// for ADDR, BS/BA, assign them to the flops
+assign BS = BS_nxt;
+assign BA = BA_nxt;
+assign ADDR=addr_nxt;
+
+localparam CC_E= 8'H80;
+localparam CC_F= 8'H40;
+localparam CC_H= 8'H20;
+localparam CC_I= 8'H10;
+localparam CC_N= 8'H08;
+localparam CC_Z= 8'H04;
+localparam CC_V= 8'H02;
+localparam CC_C= 8'H01;
+
+localparam CC_E_BIT= 3'd7;
+localparam CC_F_BIT= 3'd6;
+localparam CC_H_BIT= 3'd5;
+localparam CC_I_BIT= 3'd4;
+localparam CC_N_BIT= 3'd3;
+localparam CC_Z_BIT= 3'd2;
+localparam CC_V_BIT= 3'd1;
+localparam CC_C_BIT= 3'd0;
+
+// Convenience calculations
+reg [15:0] pc_p1;
+reg [15:0] pc_p2;
+reg [15:0] pc_p3;
+reg [15:0] s_p1;
+reg [15:0] s_m1;
+reg [15:0] u_p1;
+reg [15:0] u_m1;
+reg [15:0] addr_p1;
+reg [15:0] ea_p1;
+
+//////////////////////////////////////////////////////
+// NMI Mask
+//
+// NMI is supposed to be masked - despite the name - until the 6809 loads a value into S.
+// Frankly, I'm cheating slightly. If someone does a LDS #$0, it won't disable the mask. Pretty much anything else
+// that changes the value of S from the default (which is currently $0) will clear the mask. A reset will set the mask again.
+reg NMIMask;
+
+reg NMILatched;
+reg NMISample;
+reg NMISample2;
+reg NMIClear;
+reg NMIClear_nxt;
+wire wNMIClear = NMIClear;
+
+reg IRQLatched;
+
+reg IRQSample;
+reg IRQSample2;
+reg FIRQLatched;
+reg FIRQSample;
+reg FIRQSample2;
+reg HALTLatched;
+reg HALTSample;
+reg HALTSample2;
+reg DMABREQLatched;
+reg DMABREQSample;
+reg DMABREQSample2;
+
+// Interrupt types
+localparam INTTYPE_NMI = 3'H0 ;
+localparam INTTYPE_IRQ = 3'H1 ;
+localparam INTTYPE_FIRQ = 3'H2 ;
+localparam INTTYPE_SWI = 3'H3 ;
+localparam INTTYPE_SWI2 = 3'H4 ;
+localparam INTTYPE_SWI3 = 3'H5 ;
+
+reg [2:0] IntType;
+reg [2:0] IntType_nxt;
+
+//////////////////////////////////////////////////////
+// Instruction Fetch Details
+//
+reg InstPage2;
+reg InstPage3;
+reg InstPage2_nxt;
+reg InstPage3_nxt;
+
+reg [7:0] Inst1;
+reg [7:0] Inst2;
+reg [7:0] Inst3;
+reg [7:0] Inst1_nxt;
+reg [7:0] Inst2_nxt;
+reg [7:0] Inst3_nxt;
+
+
+localparam CPUSTATE_RESET = 7'd0;
+localparam CPUSTATE_RESET0 = 7'd1;
+
+localparam CPUSTATE_RESET2 = 7'd3;
+localparam CPUSTATE_FETCH_I1 = 7'd4;
+localparam CPUSTATE_FETCH_I1V2 = 7'd5;
+localparam CPUSTATE_FETCH_I2 = 7'd8;
+
+localparam CPUSTATE_LBRA_OFFSETLOW = 7'd17;
+localparam CPUSTATE_LBRA_DONTCARE = 7'd18;
+localparam CPUSTATE_LBRA_DONTCARE2 = 7'd19;
+
+
+
+localparam CPUSTATE_BRA_DONTCARE = 7'd20;
+
+localparam CPUSTATE_BSR_DONTCARE1 = 7'd21;
+localparam CPUSTATE_BSR_DONTCARE2 = 7'd22;
+localparam CPUSTATE_BSR_RETURNLOW = 7'd23;
+localparam CPUSTATE_BSR_RETURNHIGH = 7'd24;
+
+localparam CPUSTATE_TFR_DONTCARE1 = 7'd26;
+localparam CPUSTATE_TFR_DONTCARE2 = 7'd27;
+localparam CPUSTATE_TFR_DONTCARE3 = 7'd28;
+localparam CPUSTATE_TFR_DONTCARE4 = 7'd29;
+
+localparam CPUSTATE_EXG_DONTCARE1 = 7'd30;
+localparam CPUSTATE_EXG_DONTCARE2 = 7'd31;
+localparam CPUSTATE_EXG_DONTCARE3 = 7'd32;
+localparam CPUSTATE_EXG_DONTCARE4 = 7'd33;
+localparam CPUSTATE_EXG_DONTCARE5 = 7'd34;
+localparam CPUSTATE_EXG_DONTCARE6 = 7'd35;
+
+localparam CPUSTATE_ABX_DONTCARE = 7'd36;
+
+localparam CPUSTATE_RTS_HI = 7'd38;
+localparam CPUSTATE_RTS_LO = 7'd39;
+localparam CPUSTATE_RTS_DONTCARE2 = 7'd40;
+
+localparam CPUSTATE_16IMM_LO = 7'd41;
+localparam CPUSTATE_ALU16_DONTCARE = 7'd42;
+localparam CPUSTATE_DIRECT_DONTCARE = 7'd43;
+
+localparam CPUSTATE_ALU_EA = 7'd44;
+
+localparam CPUSTATE_ALU_DONTCARE = 7'd46;
+localparam CPUSTATE_ALU_WRITEBACK = 7'd47;
+
+localparam CPUSTATE_LD16_LO = 7'd48;
+
+localparam CPUSTATE_ST16_LO = 7'd49;
+localparam CPUSTATE_ALU16_LO = 7'd50;
+
+
+
+
+localparam CPUSTATE_JSR_DONTCARE = 7'd53;
+localparam CPUSTATE_JSR_RETLO = 7'd54;
+localparam CPUSTATE_JSR_RETHI = 7'd55;
+localparam CPUSTATE_EXTENDED_ADDRLO = 7'd56;
+localparam CPUSTATE_EXTENDED_DONTCARE = 7'd57;
+localparam CPUSTATE_INDEXED_BASE = 7'd58;
+
+
+localparam CPUSTATE_IDX_DONTCARE3 = 7'd60;
+
+localparam CPUSTATE_IDX_OFFSET_LO = 7'd61;
+localparam CPUSTATE_IDX_16OFFSET_LO = 7'd62;
+
+localparam CPUSTATE_IDX_16OFF_DONTCARE0= 7'd63;
+localparam CPUSTATE_IDX_16OFF_DONTCARE1= 7'd64;
+localparam CPUSTATE_IDX_16OFF_DONTCARE2= 7'd65;
+localparam CPUSTATE_IDX_16OFF_DONTCARE3= 7'd66;
+
+localparam CPUSTATE_IDX_DOFF_DONTCARE1 = 7'd68;
+localparam CPUSTATE_IDX_DOFF_DONTCARE2 = 7'd69;
+localparam CPUSTATE_IDX_DOFF_DONTCARE3 = 7'd70;
+localparam CPUSTATE_IDX_PC16OFF_DONTCARE = 7'd71;
+
+localparam CPUSTATE_IDX_EXTIND_LO = 7'd72;
+localparam CPUSTATE_IDX_EXTIND_DONTCARE = 7'd73;
+
+localparam CPUSTATE_INDIRECT_HI = 7'd74;
+localparam CPUSTATE_INDIRECT_LO = 7'd75;
+localparam CPUSTATE_INDIRECT_DONTCARE = 7'd76;
+localparam CPUSTATE_MUL_ACTION = 7'd77;
+
+localparam CPUSTATE_PSH_DONTCARE1 = 7'd80;
+localparam CPUSTATE_PSH_DONTCARE2 = 7'd81;
+localparam CPUSTATE_PSH_DONTCARE3 = 7'd82;
+localparam CPUSTATE_PSH_ACTION = 7'd83;
+
+localparam CPUSTATE_PUL_DONTCARE1 = 7'd84;
+localparam CPUSTATE_PUL_DONTCARE2 = 7'd85;
+localparam CPUSTATE_PUL_ACTION = 7'd86;
+
+localparam CPUSTATE_NMI_START = 7'd87;
+localparam CPUSTATE_IRQ_DONTCARE = 7'd88;
+localparam CPUSTATE_IRQ_START = 7'd89;
+localparam CPUSTATE_IRQ_DONTCARE2 = 7'd90;
+localparam CPUSTATE_IRQ_VECTOR_HI = 7'd91;
+localparam CPUSTATE_IRQ_VECTOR_LO = 7'd92;
+localparam CPUSTATE_FIRQ_START = 7'd93;
+localparam CPUSTATE_CC_DONTCARE = 7'd94;
+localparam CPUSTATE_SWI_START = 7'd95;
+
+localparam CPUSTATE_TST_DONTCARE1 = 7'd96;
+localparam CPUSTATE_TST_DONTCARE2 = 7'd97;
+
+localparam CPUSTATE_DEBUG = 7'd98;
+
+localparam CPUSTATE_16IMM_DONTCARE = 7'd99;
+
+localparam CPUSTATE_HALTED = 7'd100;
+
+localparam CPUSTATE_HALT_EXIT2 = 7'd102;
+localparam CPUSTATE_STOP = 7'd105;
+localparam CPUSTATE_STOP2 = 7'd106;
+localparam CPUSTATE_STOP3 = 7'd107;
+
+
+localparam CPUSTATE_CWAI = 7'd108;
+localparam CPUSTATE_CWAI_DONTCARE1 = 7'd109;
+localparam CPUSTATE_CWAI_POST = 7'd110;
+
+localparam CPUSTATE_DMABREQ = 7'd111;
+localparam CPUSTATE_DMABREQ_EXIT = 7'd112;
+localparam CPUSTATE_SYNC = 7'd113;
+localparam CPUSTATE_SYNC_EXIT = 7'd114;
+
+localparam CPUSTATE_INT_DONTCARE = 7'd115;
+
+
+reg [6:0] CpuState = CPUSTATE_RESET;
+reg [6:0] CpuState_nxt = CPUSTATE_RESET;
+
+reg [6:0] NextState = CPUSTATE_RESET;
+reg [6:0] NextState_nxt = CPUSTATE_RESET;
+
+wire [6:0] PostIllegalState;
+
+// If we encounter something like an illegal addressing mode (an index mode that's illegal for instance)
+// What state should we go to?
+generate
+if (ILLEGAL_INSTRUCTIONS=="STOP")
+begin : postillegal
+ assign PostIllegalState = CPUSTATE_STOP;
+end
+else
+begin
+ assign PostIllegalState = CPUSTATE_FETCH_I1;
+end
+endgenerate
+
+
+
+///////////////////////////////////////////////////////////////////////
+
+//
+// MapInstruction - Considering how the core was instantiated, this
+// will either directly return D[7:0] *or* remap values from D[7:0]
+// that relate to undefined instructions in the 6809 to the instructions
+// that the 6809 actually executed when these were encountered, due to
+// incomplete decoding.
+//
+// NEG, COM, LSR, DEC - these four instructions, in Direct, Inherent (A or B)
+// Indexed, or Extended addressing do not actually decode bit 0 on the instruction.
+// Thus, for instance, a $51 encountered will be executed as a $50, which is a NEGB.
+//
+
+// Specifically, the input is an instruction; if it matches an unknown instruction that the
+// 6809 is known to ghost to another instruction, the output of the function
+// is the the instruction that actually gets executed. Otherwise, the output is the
+// input.
+
+function [7:0] MapInstruction(input [7:0] i);
+reg [3:0] topnyb;
+reg [3:0] btmnyb;
+reg [7:0] newinst;
+begin
+ newinst = i;
+
+ topnyb = i[7:4];
+ btmnyb = i[3:0];
+
+ if ( (topnyb == 4'H0) ||
+ (topnyb == 4'H4) ||
+ (topnyb == 4'H5) ||
+ (topnyb == 4'H6) ||
+ (topnyb == 4'H7)
+ )
+ begin
+ if (btmnyb == 4'H1)
+ newinst = {topnyb, 4'H0};
+ if (btmnyb == 4'H2)
+ newinst = {topnyb, 4'H3};
+ if (btmnyb == 4'H5)
+ newinst = {topnyb, 4'H4};
+ if (btmnyb == 4'HB)
+ newinst = {topnyb, 4'HA};
+ end
+ MapInstruction = newinst;
+end
+endfunction
+
+
+wire [7:0] MappedInstruction;
+generate
+if (ILLEGAL_INSTRUCTIONS=="GHOST")
+begin : ghost
+ if(IS_KONAMI1=="FALSE") //Modification by Ace: accept opcodes directly for KONAMI-1 CPU
+ assign MappedInstruction = MapInstruction(D);
+ else
+ assign MappedInstruction = MapInstruction(OP);
+end
+else
+begin
+ assign MappedInstruction = D;
+end
+endgenerate
+
+
+
+///////////////////////////////////////////////////////////////////////
+
+function IllegalInstruction(input [7:0] i);
+reg [3:0] hi;
+reg [3:0] lo;
+reg illegal;
+begin
+ illegal = 1'b0;
+ hi = i[7:4];
+ lo = i[3:0];
+ if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) )
+ begin
+ if ( (lo == 4'H1) || (lo == 4'H2) || (lo == 4'H5) || (lo == 4'HB) )
+ illegal = 1'b1;
+ if (lo == 4'HE)
+ if ( (hi == 4'H4) || (hi == 4'H5) )
+ illegal = 1'b1;
+ end
+ if (hi == 4'H3)
+ begin
+ if ( (lo == 4'H8) || (lo == 4'HE) )
+ illegal = 1'b1;
+ end
+ if (hi == 4'H1)
+ begin
+ if ( (lo == 4'H4) || (lo == 4'H5) || (lo == 4'H8) || (lo == 4'HB) )
+ illegal = 1'b1;
+ end
+ if ( (hi == 4'H8) || (hi == 4'HC) )
+ begin
+ if ( (lo == 4'H7) || (lo == 4'HF) )
+ illegal = 1'b1;
+ if ( lo == 4'HD )
+ if (hi == 4'HC)
+ illegal = 1'b1;
+ end
+ IllegalInstruction = illegal;
+end
+endfunction
+
+wire IsIllegalInstruction;
+
+generate
+if (ILLEGAL_INSTRUCTIONS=="GHOST")
+begin : never_illegal
+ assign IsIllegalInstruction = 1'b0;
+end
+else
+begin
+ assign IsIllegalInstruction = IllegalInstruction(Inst1);
+end
+endgenerate
+
+wire [6:0] IllegalInstructionState;
+generate
+if (ILLEGAL_INSTRUCTIONS=="IGNORE")
+begin : illegal_state
+ assign IllegalInstructionState = CPUSTATE_FETCH_I1;
+end
+else if (ILLEGAL_INSTRUCTIONS=="STOP")
+begin
+ assign IllegalInstructionState = CPUSTATE_STOP;
+end
+else
+begin
+ assign IllegalInstructionState = 7'd0;
+end
+endgenerate
+
+
+///////////////////////////////////////////////////////////////////////
+
+
+always @(posedge CLK)
+begin
+ reg old_sample;
+ old_sample <= NMISample2;
+
+ if (wNMIClear == 1) NMILatched <= 1;
+ else if(old_sample & ~NMISample2) NMILatched <= NMIMask;
+end
+
+//
+// The 6809 specs say that the CPU control signals are sampled on the falling edge of Q.
+// It also says that the interrupts require 1 cycle of synchronization time.
+// That's vague, as it doesn't say where "1 cycle" starts or ends. Starting from the
+// falling edge of Q, the next cycle notices an assertion. From checking a hard 6809 on
+// an analyzer, what they really mean is that it's sampled on the falling edge of Q,
+// but there's a one cycle delay from the falling edge of E (0.25 clocks from the falling edge of Q
+// where the signals were sampled) before it can be noticed.
+// So, SIGNALSample is the latched value at the falling edge of Q
+// SIGNALSample2 is the latched value at the falling edge of E (0.25 clocks after the line above)
+// SIGNALLatched is the latched value at the falling edge of E (1 cycle after the line above)
+//
+// /HALT and /DMABREQ are delayed one cycle less than interrupts. The 6809 specs infer these details,
+// but don't list the point-of-reference they're written from (for instance, they say that an interrupt requires
+// a cycle for synchronization; however, it isn't clear whether that's from the falling Q to the next falling Q,
+// a complete intermediate cycle, the falling E to the next falling E, etc.) - which, in the end, required an
+// analyzer on the 6809 to determine how many cycles before a new instruction an interrupt (or /HALT & /DMABREQ)
+// had to be asserted to be noted instead of the next instruction running start to finish.
+//
+always @(posedge CLK)
+begin
+ if(fallQ_en) begin
+ NMISample <= nNMI;
+ IRQSample <= nIRQ;
+ FIRQSample <= nFIRQ;
+ HALTSample <= nHALT;
+ DMABREQSample <= nDMABREQ;
+ end
+end
+
+
+reg rnRESET=0; // The latched version of /RESET, useful 1 clock after it's latched
+always @(posedge CLK)
+begin
+ if(fallE_en) begin
+ rnRESET <= nRESET;
+
+ NMISample2 <= NMISample;
+
+ IRQSample2 <= IRQSample;
+ IRQLatched <= IRQSample2;
+
+ FIRQSample2 <= FIRQSample;
+ FIRQLatched <= FIRQSample2;
+
+ HALTSample2 <= HALTSample;
+ HALTLatched <= HALTSample2;
+
+ DMABREQSample2 <= DMABREQSample;
+ DMABREQLatched <= DMABREQSample2;
+
+
+ if (rnRESET == 1)
+ begin
+ CpuState <= CpuState_nxt;
+
+ // Don't interpret this next item as "The Next State"; it's a special case 'after this
+ // generic state, go to this programmable state', so that a single state
+ // can be shared for many tasks. [Specifically, the stack push/pull code, which is used
+ // for PSH, PUL, Interrupts, RTI, etc.
+ NextState <= NextState_nxt;
+
+ // CPU registers latch from the combinatorial circuit
+ a <= a_nxt;
+ b <= b_nxt;
+ x <= x_nxt;
+ y <= y_nxt;
+ s <= s_nxt;
+ u <= u_nxt;
+ cc <= cc_nxt;
+ dp <= dp_nxt;
+ pc <= pc_nxt;
+ tmp <= tmp_nxt;
+ addr <= addr_nxt;
+ ea <= ea_nxt;
+
+ InstPage2 <= InstPage2_nxt;
+ InstPage3 <= InstPage3_nxt;
+ Inst1 <= Inst1_nxt;
+ Inst2 <= Inst2_nxt;
+ Inst3 <= Inst3_nxt;
+ NMIClear <= NMIClear_nxt;
+
+ IntType <= IntType_nxt;
+
+ // Once S changes at all (default is '0'), release the NMI Mask.
+ if (s != s_nxt) NMIMask <= 1'b0;
+ end
+ else
+ begin
+ CpuState <= CPUSTATE_RESET;
+ NMIMask <= 1'b1; // Mask NMI until S is loaded.
+ NMIClear <= 1'b0; // Mark us as not having serviced NMI
+ end
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////
+// Decode the Index byte
+
+localparam IDX_REG_X = 3'd0;
+localparam IDX_REG_Y = 3'd1;
+localparam IDX_REG_U = 3'd2;
+localparam IDX_REG_S = 3'd3;
+localparam IDX_REG_PC = 3'd4;
+
+localparam IDX_MODE_POSTINC1 = 4'd0;
+localparam IDX_MODE_POSTINC2 = 4'd1;
+localparam IDX_MODE_PREDEC1 = 4'd2;
+localparam IDX_MODE_PREDEC2 = 4'd3;
+localparam IDX_MODE_NOOFFSET = 4'd4;
+localparam IDX_MODE_B_OFFSET = 4'd5;
+localparam IDX_MODE_A_OFFSET = 4'd6;
+localparam IDX_MODE_5BIT_OFFSET= 4'd7; // Special case, not bit pattern 7; the offset sits in the bit pattern
+localparam IDX_MODE_8BIT_OFFSET= 4'd8;
+localparam IDX_MODE_16BIT_OFFSET = 4'd9;
+localparam IDX_MODE_D_OFFSET = 4'd11;
+localparam IDX_MODE_8BIT_OFFSET_PC = 4'd12;
+localparam IDX_MODE_16BIT_OFFSET_PC= 4'd13;
+localparam IDX_MODE_EXTENDED_INDIRECT = 4'd15;
+
+// Return:
+// Register base [3 bits]
+// Indirect [1 bit]
+// Mode [4 bits]
+
+function [7:0] IndexDecode(input [7:0] postbyte);
+reg [2:0] regnum;
+reg indirect;
+reg [3:0] mode;
+begin
+ indirect = 0;
+ mode = 0;
+
+ if (postbyte[7] == 0) // 5-bit
+ begin
+ mode = IDX_MODE_5BIT_OFFSET;
+ end
+ else
+ begin
+ mode = postbyte[3:0];
+ indirect = postbyte[4];
+ end
+ if ((mode != IDX_MODE_8BIT_OFFSET_PC) && (mode != IDX_MODE_16BIT_OFFSET_PC))
+ regnum[2:0] = postbyte[6:5];
+ else
+ regnum[2:0] = IDX_REG_PC;
+
+ IndexDecode = {indirect, mode, regnum};
+end
+endfunction
+
+wire [3:0] IndexedMode;
+wire IndexedIndirect;
+wire [2:0] IndexedRegister;
+
+assign {IndexedIndirect, IndexedMode, IndexedRegister} = IndexDecode(Inst2);
+
+/////////////////////////////////////////////////////////////////
+// Is this a JMP instruction? (irrespective of addressing mode)
+function IsJMP(input [7:0] inst);
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+
+ IsJMP = 0;
+ if ((hi == 4'H0) || (hi == 4'H6) || (hi == 4'H7))
+ if (lo == 4'HE)
+ IsJMP = 1;
+end
+endfunction
+
+///////////////////////////////////////////////////////////////////
+// Is this an 8-bit Store?
+
+localparam ST8_REG_A = 1'b0;
+localparam ST8_REG_B = 1'b1;
+
+function [1:0] IsST8(input [7:0] inst);
+reg regnum;
+reg IsStore;
+begin
+
+ IsStore = 1'b0;
+ regnum = 1'b1;
+
+ if ( (Inst1 == 8'H97) || (Inst1 == 8'HA7) || (Inst1 == 8'HB7) )
+ begin
+ IsStore = 1'b1;
+ regnum = 1'b0;
+ end
+ else if ( (Inst1 == 8'HD7) || (Inst1 == 8'HE7) || (Inst1 == 8'HF7) )
+ begin
+ IsStore = 1'b1;
+ regnum = 1'b1;
+ end
+ IsST8 = {IsStore, regnum};
+end
+endfunction
+
+wire IsStore8;
+wire Store8RegisterNum;
+
+assign {IsStore8, Store8RegisterNum} = IsST8(Inst1);
+
+
+/////////////////////////////////////////////////////////////////
+// Is this a 16-bit Store?
+
+localparam ST16_REG_X = 3'd0;
+localparam ST16_REG_Y = 3'd1;
+localparam ST16_REG_U = 3'd2;
+localparam ST16_REG_S = 3'd3;
+localparam ST16_REG_D = 3'd4;
+
+
+function [3:0] IsST16(input [7:0] inst);
+reg [3:0] hi;
+reg [3:0] lo;
+reg [2:0] regnum;
+reg IsStore;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ IsStore = 1'b0;
+ regnum = 3'b111;
+
+ if ((inst == 8'H9F) || (inst == 8'HAF) || (inst == 8'HBF))
+ begin
+ IsStore = 1;
+ if (~InstPage2)
+ regnum = ST16_REG_X;
+ else
+ regnum = ST16_REG_Y;
+ end
+ else if ((inst == 8'HDF) || (inst == 8'HEF) || (inst == 8'HFF))
+ begin
+ IsStore = 1;
+ if (~InstPage2)
+ regnum = ST16_REG_U;
+ else
+ regnum = ST16_REG_S;
+ end
+ else if ((inst == 8'HDD) || (inst == 8'HED) || (inst == 8'HFD))
+ begin
+ IsStore = 1;
+ regnum = ST16_REG_D;
+ end
+
+ IsST16 = {IsStore, regnum};
+end
+endfunction
+
+wire IsStore16;
+wire [2:0] StoreRegisterNum;
+
+assign {IsStore16, StoreRegisterNum} = IsST16(Inst1);
+
+/////////////////////////////////////////////////////////////////
+// Is this a special Immediate mode instruction, ala
+// PSH, PUL, EXG, TFR, ANDCC, ORCC
+function IsSpecialImm(input [7:0] inst);
+reg is;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ is = 0;
+
+ if (hi == 4'H1)
+ begin
+ if ( (lo == 4'HA) || (lo == 4'HC) || (lo == 4'HE) || (lo == 4'HF) ) // ORCC, ANDCC, EXG, TFR
+ is = 1;
+ end
+ else if (hi == 4'H3)
+ begin
+ if ( (lo >= 4'H3) && (lo <= 4'H7) ) // PSHS, PULS, PSHU, PULU
+ is = 1;
+ end
+ else
+ is = 0;
+
+ IsSpecialImm = is;
+end
+endfunction
+wire IsSpecialImmediate = IsSpecialImm(Inst1);
+
+/////////////////////////////////////////////////////////////////
+// Is this a one-byte instruction? [The 6809 reads 2 bytes for every instruction, minimum (it can read more). On a one-byte, we have to ensure that we haven't skipped the PC ahead.
+function IsOneByteInstruction(input [7:0] inst);
+reg is;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ is = 1'b0;
+
+ if ( (hi == 4'H4) || (hi == 4'H5) )
+ is = 1'b1;
+ else if ( hi == 4'H1)
+ begin
+ if ( (lo == 4'H2) || (lo == 4'H3) || (lo == 4'H9) || (lo == 4'HD) )
+ is = 1'b1;
+ end
+ else if (hi == 4'H3)
+ begin
+ if ( (lo >= 4'H9) && (lo != 4'HC) )
+ is = 1'b1;
+ end
+ else
+ is = 1'b0;
+
+ IsOneByteInstruction = is;
+end
+endfunction
+
+/////////////////////////////////////////////////////////////////
+// ALU16 - Simpler than the 8 bit ALU
+
+localparam ALU16_REG_X = 3'd0;
+localparam ALU16_REG_Y = 3'd1;
+localparam ALU16_REG_U = 3'd2;
+localparam ALU16_REG_S = 3'd3;
+localparam ALU16_REG_D = 3'd4;
+
+function [2:0] ALU16RegFromInst(input Page2, input Page3, input [7:0] inst);
+reg [2:0] srcreg;
+begin
+ srcreg = 3'b111; // default
+ casex ({Page2, Page3, inst}) // Note pattern for the matching below
+ 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD
+ srcreg = ALU16_REG_D;
+ 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY
+ srcreg = ALU16_REG_Y;
+ 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU
+ srcreg = ALU16_REG_U;
+ 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS
+ srcreg = ALU16_REG_S;
+ 10'b0010xx1100: // 8C,9C,AC,BC CMPX
+ srcreg = ALU16_REG_X;
+
+ 10'b0011xx0011: // C3, D3, E3, F3 ADDD
+ srcreg = ALU16_REG_D;
+
+ 10'b0011xx1100: // CC, DC, EC, FC LDD
+ srcreg = ALU16_REG_D;
+ 10'b0010xx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX
+ srcreg = ALU16_REG_X;
+ 10'b0011xx1110: // CE LDU, DE LDU, EE LDU, FE LDU
+ srcreg = ALU16_REG_U;
+ 10'b1010xx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY
+ srcreg = ALU16_REG_Y;
+ 10'b1011xx1110: // 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS
+ srcreg = ALU16_REG_S;
+ 10'b0010xx0011: // 83, 93, A3, B3 SUBD
+ srcreg = ALU16_REG_D;
+
+ 10'H03A: // 3A ABX
+ srcreg = ALU16_REG_X;
+ 10'H030: // 30 LEAX
+ srcreg = ALU16_REG_X;
+ 10'H031: // 31 LEAY
+ srcreg = ALU16_REG_Y;
+ 10'H032: // 32 LEAS
+ srcreg = ALU16_REG_S;
+ 10'H033: // 32 LEAU
+ srcreg = ALU16_REG_U;
+ default:
+ srcreg = 3'b111;
+ endcase
+ ALU16RegFromInst = srcreg;
+end
+endfunction
+
+wire [2:0] ALU16Reg = ALU16RegFromInst(InstPage2, InstPage3, Inst1);
+
+localparam ALUOP16_SUB = 3'H0;
+localparam ALUOP16_ADD = 3'H1;
+localparam ALUOP16_LD = 3'H2;
+localparam ALUOP16_CMP = 3'H3;
+localparam ALUOP16_LEA = 3'H4;
+localparam ALUOP16_INVALID = 3'H7;
+
+function [3:0] ALU16OpFromInst(input Page2, input Page3, input [7:0] inst);
+reg [2:0] aluop;
+reg writeback;
+begin
+ aluop = 3'b111;
+ writeback = 1'b1;
+ casex ({Page2, Page3, inst})
+ 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0010xx1100: // 8C,9C,AC,BC CMPX
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+
+ 10'b0011xx0011: // C3, D3, E3, F3 ADDD
+ aluop = ALUOP16_ADD;
+
+ 10'b0011xx1100: // CC, DC, EC, FC LDD
+ aluop = ALUOP16_LD;
+ 10'b001xxx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX, CE LDU, DE LDU, EE LDU, FE LDU
+ aluop = ALUOP16_LD;
+ 10'b101xxx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY, 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS
+ aluop = ALUOP16_LD;
+
+ 10'b0010xx0011: // 83, 93, A3, B3 SUBD
+ aluop = ALUOP16_SUB;
+
+ 10'H03A: // 3A ABX
+ aluop = ALUOP16_ADD;
+
+ 10'b00001100xx: // $30-$33, LEAX, LEAY, LEAS, LEAU
+ aluop = ALUOP16_LEA;
+
+ default:
+ aluop = ALUOP16_INVALID;
+ endcase
+ ALU16OpFromInst = {writeback, aluop};
+end
+endfunction
+
+wire ALU16OpWriteback;
+wire [2:0] ALU16Opcode;
+
+assign {ALU16OpWriteback, ALU16Opcode} = ALU16OpFromInst(InstPage2, InstPage3, Inst1);
+
+wire IsALU16Opcode = (ALU16Opcode != 3'b111);
+
+function [23:0] ALU16Inst(input [2:0] operation16, input [15:0] a_arg, input [15:0] b_arg, input [7:0] cc_arg);
+reg [7:0] cc_out;
+reg [15:0] ALUFn;
+reg carry;
+reg borrow;
+begin
+ cc_out = cc_arg;
+ case (operation16)
+ ALUOP16_ADD:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + b_arg;
+ cc_out[CC_V_BIT] = (a_arg[15] & b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & ~b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_SUB:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_LD:
+ begin
+ ALUFn = b_arg;
+ cc_out[CC_V_BIT] = 1'b0;
+ end
+
+ ALUOP16_CMP:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_LEA:
+ begin
+ ALUFn = a_arg;
+ end
+
+ default:
+ ALUFn = 16'H0000;
+
+ endcase
+ cc_out[CC_Z_BIT] = (ALUFn[15:0] == 16'H0000);
+ if (operation16 != ALUOP16_LEA)
+ cc_out[CC_N_BIT] = ALUFn[15];
+ ALU16Inst = {cc_out, ALUFn};
+end
+endfunction
+
+reg [2:0] ALU16_OP;
+reg [15:0] ALU16_A;
+reg [15:0] ALU16_B;
+reg [7:0] ALU16_CC;
+
+// Top 8 bits == CC, bottom 8 bits = output value
+wire [23:0] ALU16 = ALU16Inst(ALU16_OP, ALU16_A, ALU16_B, ALU16_CC);
+
+
+/////////////////////////////////////////////////////////////////
+// ALU
+
+// The ops are organized from the 4 low-order bits of the instructions for the first set of ops, then 16-31 are the second set - even though bit 4 isn't representative.
+localparam ALUOP_NEG = 5'd0;
+localparam ALUOP_COM = 5'd3;
+localparam ALUOP_LSR = 5'd4;
+localparam ALUOP_ROR = 5'd6;
+localparam ALUOP_ASR = 5'd7;
+localparam ALUOP_ASL = 5'd8;
+localparam ALUOP_LSL = 5'd8;
+localparam ALUOP_ROL = 5'd9;
+localparam ALUOP_DEC = 5'd10;
+localparam ALUOP_INC = 5'd12;
+localparam ALUOP_TST = 5'd13;
+localparam ALUOP_CLR = 5'd15;
+
+localparam ALUOP_SUB = 5'd16;
+localparam ALUOP_CMP = 5'd17;
+localparam ALUOP_SBC = 5'd18;
+localparam ALUOP_AND = 5'd20;
+localparam ALUOP_BIT = 5'd21;
+localparam ALUOP_LD = 5'd22;
+localparam ALUOP_EOR = 5'd24;
+localparam ALUOP_ADC = 5'd25;
+localparam ALUOP_OR = 5'd26;
+localparam ALUOP_ADD = 5'd27;
+
+function [5:0] ALUOpFromInst(input [7:0] inst);
+reg [4:0] op;
+reg writeback;
+begin
+ // Okay, this turned out to be simpler than I expected ...
+ op = {inst[7], inst[3:0]};
+ case (op)
+ ALUOP_CMP:
+ writeback = 0;
+ ALUOP_TST:
+ writeback = 0;
+ ALUOP_BIT:
+ writeback = 0;
+ default:
+ writeback = 1;
+ endcase
+ ALUOpFromInst = {writeback, op};
+end
+endfunction
+
+wire [4:0] ALU8Op;
+wire ALU8Writeback;
+
+assign {ALU8Writeback, ALU8Op} = ALUOpFromInst(Inst1);
+
+reg [7:0] ALU_A;
+reg [7:0] ALU_B;
+reg [7:0] ALU_CC;
+reg [4:0] ALU_OP;
+
+
+function [15:0] ALUInst(input [4:0] operation, input [7:0] a_arg, input [7:0] b_arg, input [7:0] cc_arg);
+reg [7:0] cc_out;
+reg [7:0] ALUFn;
+reg borrow;
+begin
+ cc_out = cc_arg;
+ case (operation)
+ ALUOP_NEG:
+ begin
+ ALUFn = ~a_arg + 1'b1;
+ cc_out[CC_C_BIT] = (ALUFn != 8'H00);
+ cc_out[CC_V_BIT] = (a_arg == 8'H80);
+ end
+
+ ALUOP_LSL:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {a_arg, 1'b0};
+ cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6];
+ end
+
+ ALUOP_LSR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {1'b0, a_arg};
+ end
+
+ ALUOP_ASR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {a_arg[7], a_arg};
+ end
+
+ ALUOP_ROL:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {a_arg, cc_arg[CC_C_BIT]};
+ cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6];
+ end
+
+ ALUOP_ROR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {cc_arg[CC_C_BIT], a_arg};
+ end
+
+ ALUOP_OR:
+ begin
+ ALUFn = (a_arg | b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_ADD:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]);
+ cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4];
+ end
+
+ ALUOP_SUB:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_AND:
+ begin
+ ALUFn = (a_arg & b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_BIT:
+ begin
+ ALUFn = (a_arg & b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_EOR:
+ begin
+ ALUFn = (a_arg ^ b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_CMP:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_COM:
+ begin
+ ALUFn = ~a_arg;
+ cc_out[CC_V_BIT] = 0;
+ cc_out[CC_C_BIT] = 1;
+ end
+
+ ALUOP_ADC:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg} + cc_arg[CC_C_BIT];
+ cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]);
+ cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4];
+ end
+
+ ALUOP_LD:
+ begin
+ ALUFn = b_arg;
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_INC:
+ begin
+ ALUFn = a_arg + 1'b1;
+ cc_out[CC_V_BIT] = (~a_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_DEC:
+ begin
+ ALUFn = a_arg - 1'b1;
+ cc_out[CC_V_BIT] = (a_arg[7] & ~ALUFn[7]);
+ end
+
+ ALUOP_CLR:
+ begin
+ ALUFn = 0;
+ cc_out[CC_V_BIT] = 0;
+ cc_out[CC_C_BIT] = 0;
+ end
+
+ ALUOP_TST:
+ begin
+ ALUFn = a_arg;
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_SBC:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg} - cc_arg[CC_C_BIT];
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ default:
+ ALUFn = 0;
+
+ endcase
+
+ cc_out[CC_N_BIT] = ALUFn[7];
+ cc_out[CC_Z_BIT] = !ALUFn;
+ ALUInst = {cc_out[7:0], ALUFn};
+end
+endfunction
+
+
+// Top 8 bits == CC, bottom 8 bits = output value
+wire [15:0] ALU = ALUInst(ALU_OP, ALU_A, ALU_B, ALU_CC);
+
+////////////////////////////////////////////////////////////
+
+localparam TYPE_INHERENT = 3'd0;
+localparam TYPE_IMMEDIATE = 3'd1;
+localparam TYPE_DIRECT = 3'd2;
+localparam TYPE_RELATIVE = 3'd3;
+localparam TYPE_INDEXED = 3'd4;
+localparam TYPE_EXTENDED = 3'd5;
+
+localparam TYPE_INVALID = 3'd7;
+
+// Function to decode the addressing mode the instruction uses
+function [2:0] addressing_mode_type(input [7:0] inst);
+begin
+ casex (inst)
+ 8'b0000???? : addressing_mode_type = TYPE_DIRECT;
+ 8'b0001???? :
+ begin
+ casex (inst[3:0])
+ 4'b0010:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b0011:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1001:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1101:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b0110:
+ addressing_mode_type = TYPE_RELATIVE;
+
+ 4'b0111:
+ addressing_mode_type = TYPE_RELATIVE;
+
+ 4'b1010:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1100:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1110:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1111:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ default:
+ addressing_mode_type = TYPE_INVALID;
+ endcase
+ end
+
+ 8'b0010????: addressing_mode_type = TYPE_RELATIVE;
+ 8'b0011????:
+ begin
+ casex(inst[3:0])
+ 4'b00??:
+ addressing_mode_type = TYPE_INDEXED;
+
+ 4'b01??:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1001:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b101?:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1100:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1101:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1111:
+ addressing_mode_type = TYPE_INHERENT;
+
+ default:
+ addressing_mode_type = TYPE_INVALID;
+ endcase
+ end
+
+ 8'b010?????: addressing_mode_type = TYPE_INHERENT;
+
+ 8'b0110????: addressing_mode_type = TYPE_INDEXED;
+
+ 8'b0111????: addressing_mode_type = TYPE_EXTENDED;
+
+ 8'b1000????:
+ begin
+ casex (inst[3:0])
+ 4'b0111: addressing_mode_type = TYPE_INVALID;
+ 4'b1111: addressing_mode_type = TYPE_INVALID;
+ 4'b1101: addressing_mode_type = TYPE_RELATIVE;
+ default: addressing_mode_type = TYPE_IMMEDIATE;
+ endcase
+ end
+
+ 8'b1001????: addressing_mode_type = TYPE_DIRECT;
+ 8'b1010????: addressing_mode_type = TYPE_INDEXED;
+ 8'b1011????: addressing_mode_type = TYPE_EXTENDED;
+ 8'b1100????: addressing_mode_type = TYPE_IMMEDIATE;
+ 8'b1101????: addressing_mode_type = TYPE_DIRECT;
+ 8'b1110????: addressing_mode_type = TYPE_INDEXED;
+ 8'b1111????: addressing_mode_type = TYPE_EXTENDED;
+
+ endcase
+end
+endfunction
+
+wire [2:0] AddrModeType = addressing_mode_type(Inst1);
+
+//////////////////////////////////////////////////
+
+// Individual opcodes that are the top of a column of states.
+
+localparam OPCODE_INH_ABX = 8'H3A;
+localparam OPCODE_INH_RTS = 8'H39;
+localparam OPCODE_INH_RTI = 8'H3B;
+localparam OPCODE_INH_CWAI = 8'H3C;
+localparam OPCODE_INH_MUL = 8'H3D;
+localparam OPCODE_INH_SWI = 8'H3F;
+localparam OPCODE_INH_SEX = 8'H1D;
+localparam OPCODE_INH_NOP = 8'H12;
+localparam OPCODE_INH_SYNC = 8'H13;
+localparam OPCODE_INH_DAA = 8'H19;
+
+localparam OPCODE_IMM_ORCC = 8'H1A;
+localparam OPCODE_IMM_ANDCC = 8'H1C;
+localparam OPCODE_IMM_EXG = 8'H1E;
+localparam OPCODE_IMM_TFR = 8'H1F;
+localparam OPCODE_IMM_PSHS = 8'H34;
+localparam OPCODE_IMM_PULS = 8'H35;
+localparam OPCODE_IMM_PSHU = 8'H36;
+localparam OPCODE_IMM_PULU = 8'H37;
+
+localparam OPCODE_IMM_SUBD = 8'H83;
+localparam OPCODE_IMM_CMPX = 8'H8C;
+localparam OPCODE_IMM_LDX = 8'H8E;
+localparam OPCODE_IMM_ADDD = 8'HC3;
+localparam OPCODE_IMM_LDD = 8'HCC;
+localparam OPCODE_IMM_LDU = 8'HCE;
+localparam OPCODE_IMM_CMPD = 8'H83; // Page2
+localparam OPCODE_IMM_CMPY = 8'H8C; // Page2
+localparam OPCODE_IMM_LDY = 8'H8E; // Page2
+localparam OPCODE_IMM_LDS = 8'HCE; // Page2
+localparam OPCODE_IMM_CMPU = 8'H83; // Page3
+localparam OPCODE_IMM_CMPS = 8'H8C; // Page3
+
+localparam EXGTFR_REG_D = 4'H0;
+localparam EXGTFR_REG_X = 4'H1;
+localparam EXGTFR_REG_Y = 4'H2;
+localparam EXGTFR_REG_U = 4'H3;
+localparam EXGTFR_REG_S = 4'H4;
+localparam EXGTFR_REG_PC = 4'H5;
+localparam EXGTFR_REG_A = 4'H8;
+localparam EXGTFR_REG_B = 4'H9;
+localparam EXGTFR_REG_CC = 4'HA;
+localparam EXGTFR_REG_DP = 4'HB;
+
+function IsALU8Set0(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = instr[7:4];
+ lo = instr[3:0];
+ if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) )
+ begin
+ if ( (lo != 4'H1) && (lo != 4'H2) && (lo != 4'H5) && (lo != 4'HB) && (lo != 4'HE) ) // permit NEG, COM, LSR, ROR, ASR, ASL/LSL, ROL, DEC, INC, TST, CLR
+ result = 1;
+ else
+ result = 0;
+ end
+ else
+ result = 0;
+ IsALU8Set0 = result;
+end
+endfunction
+
+function IsALU8Set1(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = instr[7:4];
+ lo = instr[3:0];
+ if ( (hi >= 4'H8) )
+ begin
+ if ( (lo <= 4'HB) && (lo != 4'H3) && (lo != 4'H7) ) // 8-bit SUB, CMP, SBC, AND, BIT, LD, EOR, ADC, OR, ADD
+ result = 1;
+ else
+ result = 0;
+ end
+ else
+ result = 0;
+ IsALU8Set1 = result;
+end
+endfunction
+
+// Determine if the instruction is performing an 8-bit op (ALU only)
+function ALU8BitOp(input [7:0] instr);
+begin
+ ALU8BitOp = IsALU8Set0(instr) | IsALU8Set1(instr);
+end
+endfunction
+
+wire Is8BitInst = ALU8BitOp(Inst1);
+
+function IsRegA(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+begin
+ hi = instr[7:4];
+ if ((hi == 4'H4) || (hi == 4'H8) || (hi == 4'H9) || (hi == 4'HA) || (hi == 4'HB) )
+ result = 1;
+ else
+ result = 0;
+ IsRegA = result;
+end
+endfunction
+
+wire IsTargetRegA = IsRegA(Inst1);
+
+//
+//
+// Decode
+// 00-0F = DIRECT
+// 10-1F = INHERENT, RELATIVE, IMMEDIATE
+// 20-2F = RELATIVE
+// 30-3F = INDEXED, IMMEDIATE (pus, pul), INHERENT
+// 40-4F = INHERENT
+// 50-5F = INHERENT
+// 60-6F = INDEXED
+// 70-7F = EXTENDED
+// 80-8F = IMMEDIATE, RELATIVE (BSR)
+// 90-9F = DIRECT
+// A0-AF = INDEXED
+// B0-BF = EXTENDED
+// C0-CF = IMMEDIATE
+// D0-DF = DIRECT
+// E0-EF = INDEXED
+// F0-FF = EXTENDED
+
+// DIRECT; 00-0F, 90-9F, D0-DF
+// INHERENT; 10-1F (12, 13, 19, 1D), 30-3F (39-3F), 40-4F, 50-5F,
+// RELATIVE: 10-1F (16, 17), 20-2F, 80-8F (8D)
+// IMMEDIATE: 10-1F (1A, 1C, 1E, 1F), 30-3F (34-37), 80-8F (80-8C, 8E), C0-CF
+// INDEXED: 60-6F, A0-AF, E0-EF
+// EXTENDED: 70-7F, B0-Bf, F0-FF
+
+localparam INST_LBRA = 8'H16; // always -- shitty numbering, damnit
+localparam INST_LBSR = 8'H17; //
+
+localparam INST_BRA = 8'H20; // always
+localparam INST_BRN = 8'H21; // never
+localparam INST_BHI = 8'H22; // CC.Z = 0 && CC.C = 0
+localparam INST_BLS = 8'H23; // CC.Z != 0 && CC.C != 0
+localparam INST_BCC = 8'H24; // CC.C = 0
+localparam INST_BHS = 8'H24; // same as BCC
+localparam INST_BCS = 8'H25; // CC.C = 1
+localparam INST_BLO = 8'H25; // same as BCS
+localparam INST_BNE = 8'H26; // CC.Z = 0
+localparam INST_BEQ = 8'H27; // CC.Z = 1
+localparam INST_BVC = 8'H28; // V = 1
+localparam INST_BVS = 8'H29; // V = 0
+localparam INST_BPL = 8'H2A; // CC.N = 0
+localparam INST_BMI = 8'H2B; // CC.N = 1
+localparam INST_BGE = 8'H2C; // CC.N = CC.V
+localparam INST_BLT = 8'H2D; // CC.N != CC.V
+localparam INST_BGT = 8'H2E; // CC.N = CC.V && CC.Z = 0
+localparam INST_BLE = 8'H2F; // CC.N != CC.V && CC.Z = 1
+localparam INST_BSR = 8'H8D; // always
+
+localparam NYB_BRA = 4'H0; // always
+localparam NYB_BRN = 4'H1; // never
+localparam NYB_BHI = 4'H2; // CC.Z = 0 && CC.C = 0
+localparam NYB_BLS = 4'H3; // CC.Z != 0 && CC.C != 0
+localparam NYB_BCC = 4'H4; // CC.C = 0
+localparam NYB_BHS = 4'H4; // same as BCC
+localparam NYB_BCS = 4'H5; // CC.C = 1
+localparam NYB_BLO = 4'H5; // same as BCS
+localparam NYB_BNE = 4'H6; // CC.Z = 0
+localparam NYB_BEQ = 4'H7; // CC.Z = 1
+localparam NYB_BVC = 4'H8; // V = 0
+localparam NYB_BVS = 4'H9; // V = 1
+localparam NYB_BPL = 4'HA; // CC.N = 0
+localparam NYB_BMI = 4'HB; // CC.N = 1
+localparam NYB_BGE = 4'HC; // CC.N = CC.V
+localparam NYB_BLT = 4'HD; // CC.N != CC.V
+localparam NYB_BGT = 4'HE; // CC.N = CC.V && CC.Z = 0
+localparam NYB_BLE = 4'HF; // CC.N != CC.V && CC.Z = 1
+
+
+
+function take_branch(input [7:0] Inst1, input [7:0] cc);
+begin
+ take_branch = 0; //default
+ if ( (Inst1 == INST_BSR) || (Inst1 == INST_LBSR) || (Inst1 == INST_LBRA) )
+ take_branch = 1;
+ else
+ case (Inst1[3:0])
+ NYB_BRA:
+ take_branch = 1;
+ NYB_BRN:
+ take_branch = 0;
+ NYB_BHI:
+ if ( ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) == 0)
+ take_branch = 1;
+ NYB_BLS:
+ if ( cc[CC_Z_BIT] | cc[CC_C_BIT] )
+ take_branch = 1;
+ NYB_BCC:
+ if ( cc[CC_C_BIT] == 0 )
+ take_branch = 1;
+ NYB_BCS:
+ if ( cc[CC_C_BIT] == 1 )
+ take_branch = 1;
+ NYB_BNE:
+ if ( cc[CC_Z_BIT] == 0 )
+ take_branch = 1;
+ NYB_BEQ:
+ if ( cc[CC_Z_BIT] == 1 )
+ take_branch = 1;
+ NYB_BVC:
+ if ( cc[CC_V_BIT] == 0)
+ take_branch = 1;
+ NYB_BVS:
+ if ( cc[CC_V_BIT] == 1)
+ take_branch = 1;
+ NYB_BPL:
+ if ( cc[CC_N_BIT] == 0 )
+ take_branch = 1;
+ NYB_BMI:
+ if (cc[CC_N_BIT] == 1)
+ take_branch = 1;
+ NYB_BGE:
+ if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0)
+ take_branch = 1;
+ NYB_BLT:
+ if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1)
+ take_branch = 1;
+ NYB_BGT:
+ if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) & (cc[CC_Z_BIT] == 0) )
+ take_branch = 1;
+ NYB_BLE:
+ if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) | (cc[CC_Z_BIT] == 1) )
+ take_branch = 1;
+ endcase
+end
+endfunction
+
+wire TakeBranch = take_branch(Inst1, cc);
+
+/////////////////////////////////////////////////////////////////////
+// Convenience function for knowing the contents for TFR, EXG
+function [15:0] EXGTFRRegister(input [3:0] regid);
+begin
+ case (regid)
+ EXGTFR_REG_D:
+ EXGTFRRegister = {a, b};
+ EXGTFR_REG_X:
+ EXGTFRRegister = x;
+ EXGTFR_REG_Y:
+ EXGTFRRegister = y;
+ EXGTFR_REG_U:
+ EXGTFRRegister = u;
+ EXGTFR_REG_S:
+ EXGTFRRegister = s;
+ EXGTFR_REG_PC:
+ EXGTFRRegister = pc_p1; // For both EXG and TFR, this is used on the 2nd byte in the instruction's cycle. The PC intended to transfer is actually the next byte.
+ EXGTFR_REG_DP:
+ EXGTFRRegister = {8'HFF, dp};
+ EXGTFR_REG_A:
+ EXGTFRRegister = {8'HFF, a};
+ EXGTFR_REG_B:
+ EXGTFRRegister = {8'HFF, b};
+ EXGTFR_REG_CC:
+ EXGTFRRegister = {8'HFF, cc};
+ default:
+ EXGTFRRegister = 16'H0;
+ endcase
+end
+endfunction
+wire [15:0] EXGTFRRegA = EXGTFRRegister(D[7:4]);
+wire [15:0] EXGTFRRegB = EXGTFRRegister(D[3:0]);
+
+// CPU state machine
+always @(*)
+begin
+ rLIC = 1'b0;
+ rAVMA = 1'b1;
+ rBUSY = 1'b0;
+
+ addr_nxt = 16'HFFFF;
+ pc_p1 = (pc+16'H1);
+ pc_p2 = (pc+16'H2);
+ pc_p3 = (pc+16'H3);
+ s_p1 = (s+16'H1);
+ s_m1 = (s-16'H1);
+ u_p1 = (u+16'H1);
+ u_m1 = (u-16'H1);
+ addr_p1 = (addr+16'H1);
+ ea_p1 = (ea+16'H1);
+ BS_nxt = 1'b0;
+ BA_nxt = 1'b0;
+
+ // These may be overridden below, but the "next" version by default should be
+ // the last latched version.
+ IntType_nxt = IntType;
+ NMIClear_nxt = NMIClear;
+ NextState_nxt = NextState;
+ a_nxt = a;
+ b_nxt = b;
+ x_nxt = x;
+ y_nxt = y;
+ s_nxt = s;
+ u_nxt = u;
+ cc_nxt = cc;
+ dp_nxt = dp;
+ pc_nxt = pc;
+ tmp_nxt = tmp;
+ ea_nxt = ea;
+
+ ALU_A = 8'H00;
+ ALU_B = 8'H00;
+ ALU_CC = 8'H00;
+ ALU_OP = 5'H00;
+
+ ALU16_OP = 3'H0;
+ ALU16_A = 16'H0000;
+ ALU16_B = 16'H0000;
+ ALU16_CC = 8'H00;
+
+ DOutput = 8'H00;
+ RnWOut = 1'b1; // read
+
+ Inst1_nxt = Inst1;
+ Inst2_nxt = Inst2;
+ Inst3_nxt = Inst3;
+ InstPage2_nxt = InstPage2;
+ InstPage3_nxt = InstPage3;
+
+ CpuState_nxt = CpuState;
+
+ case (CpuState)
+ CPUSTATE_RESET:
+ begin
+ addr_nxt = 16'HFFFF;
+ a_nxt = 0;
+ b_nxt = 0;
+ x_nxt = 0;
+ y_nxt = 0;
+ s_nxt = 16'HFFFD; // Take care about removing the reset of S. There's logic depending on the delta between s and s_nxt to clear NMIMask.
+ u_nxt = 0;
+ cc_nxt = CC_F | CC_I; // reset disables interrupts
+ dp_nxt = 0;
+ ea_nxt = 16'HFFFF;
+
+ RnWOut = 1; // read
+ rLIC = 1'b0; // Instruction incomplete
+ NMIClear_nxt= 1'b0;
+ IntType_nxt = 3'b111;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RESET0;
+ end
+
+ CPUSTATE_RESET0:
+ begin
+ addr_nxt = `RESET_VECTOR;
+ rBUSY = 1'b1;
+ pc_nxt[15:8] = D[7:0];
+ BS_nxt = 1'b1; // ACK RESET
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_RESET2;
+ end
+
+ CPUSTATE_RESET2:
+ begin
+ addr_nxt = addr_p1;
+ BS_nxt = 1'b1; // ACK RESET
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_FETCH_I1:
+ begin
+ if (~DMABREQLatched)
+ begin
+ addr_nxt = pc;
+ RnWOut = 1'b1;
+ rAVMA = 1'b0;
+ tmp_nxt = {tmp[15:4], 4'b1111};
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_DMABREQ;
+ end
+ else if (~HALTLatched)
+ begin
+ addr_nxt = pc;
+ RnWOut = 1'b1;
+ rAVMA = 1'b0;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_HALTED;
+ end
+ else // not halting, run the inst byte fetch
+ begin
+ addr_nxt = pc; // Set the address bus for the next instruction, first byte
+ pc_nxt = pc_p1;
+ RnWOut = 1; // Set for a READ
+ Inst1_nxt = MappedInstruction;
+ InstPage2_nxt = 0;
+ InstPage3_nxt = 0;
+
+ // New instruction fetch; service interrupts pending
+ if (NMILatched == 0)
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_NMI_START;
+ end
+ else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0))
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FIRQ_START;
+ end
+ else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0))
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_START;
+ end
+
+ // The actual 1st byte checks
+ else if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10.
+ begin
+ InstPage2_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else if (Inst1_nxt == 8'H11) // Page 3
+ begin
+ InstPage3_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I2;
+ end
+ end // if not halting
+ end
+
+ CPUSTATE_FETCH_I1V2:
+ begin
+ addr_nxt = pc; // Set the address bus for the next instruction, first byte
+ pc_nxt = pc_p1;
+ RnWOut = 1; // Set for a READ
+ Inst1_nxt = MappedInstruction;
+
+ if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10.
+ begin
+ if (InstPage3 == 0) // $11 $11 $11 $11 ... $11 $10 still = Page 3
+ InstPage2_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else if (Inst1_nxt == 8'H11) // Page 3
+ begin
+ if (InstPage2 == 0) // $10 $10 ... $10 $11 still = Page 2
+ InstPage3_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I2;
+ end
+ end
+
+
+ CPUSTATE_FETCH_I2: // We've fetched the first byte. If a $10 or $11 (page select), mark those flags and fetch the next byte as instruction byte 1.
+ begin
+ addr_nxt = addr_p1; // Address bus++
+ pc_nxt = pc_p1;
+ Inst2_nxt = D[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+
+ if (IsIllegalInstruction) // Skip illegal instructions
+ begin
+
+ rAVMA = 1'b1;
+ CpuState_nxt = IllegalInstructionState;
+ rLIC = 1'b1;
+ end
+ else
+ begin
+ // First byte Decode for this stage
+ case (AddrModeType)
+ TYPE_INDEXED:
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDEXED_BASE;
+ end
+
+
+ TYPE_EXTENDED:
+ begin
+ ea_nxt[15:8] = Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_EXTENDED_ADDRLO;
+ end
+ TYPE_DIRECT:
+ begin
+ ea_nxt = {dp, Inst2_nxt};
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_DIRECT_DONTCARE;
+ end
+
+ TYPE_INHERENT:
+ begin
+ if (Inst1 == OPCODE_INH_NOP)
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_DAA) // Bcd lunacy
+ begin
+ if ( ((cc[CC_C_BIT]) || (a[7:4] > 4'H9)) ||
+ ((a[7:4] > 4'H8) && (a[3:0] > 4'H9)) )
+ tmp_nxt[7:4] = 4'H6;
+ else
+ tmp_nxt[7:4] = 4'H0;
+
+ if ((cc[CC_H_BIT]) || (a[3:0] > 4'H9))
+ tmp_nxt[3:0] = 4'H6;
+ else
+ tmp_nxt[3:0] = 4'H0;
+
+ // DAA handles carry in the weirdest way.
+ // If it's already set, it remains set, even if carry-out is 0.
+ // If it wasn't set, but the output of the operation is set, carry-out gets set.
+ {tmp_nxt[8], a_nxt} = {1'b0, a} + tmp_nxt[7:0];
+
+ cc_nxt[CC_C_BIT] = cc_nxt[CC_C_BIT] | tmp_nxt[8];
+
+ cc_nxt[CC_N_BIT] = a_nxt[7];
+ cc_nxt[CC_Z_BIT] = (a_nxt == 8'H00);
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_SYNC)
+ begin
+ CpuState_nxt = CPUSTATE_SYNC;
+ rLIC = 1'b1;
+ rAVMA = 1'b0;
+ end
+ else if (Inst1 == OPCODE_INH_MUL)
+ begin
+ tmp_nxt = 16'H0000;
+ ea_nxt[15:8] = 8'H00;
+ ea_nxt[7:0] = a;
+ a_nxt = 8;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_MUL_ACTION;
+ end
+ else if (Inst1 == OPCODE_INH_RTS)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RTS_HI;
+ end
+ else if (Inst1 == OPCODE_INH_RTI)
+ begin
+ rAVMA = 1'b1;
+ tmp_nxt = 16'H1001; // Set tmp[12] to indicate an RTI being processed, and at least pull CC.
+ CpuState_nxt = CPUSTATE_PUL_ACTION;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_SWI)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_SWI_START;
+ end
+ else if (Inst1 == OPCODE_INH_CWAI)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CWAI;
+ end
+ else if (Inst1 == OPCODE_INH_SEX)
+ begin
+ a_nxt = {8{b[7]}};
+ cc_nxt[CC_N_BIT] = b[7];
+ cc_nxt[CC_Z_BIT] = {b == 8'H00};
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_ABX)
+ begin
+ x_nxt = x + b;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_ABX_DONTCARE;
+ end
+ else
+ begin
+ ALU_OP = ALU8Op;
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ ALU_B = 0;
+ ALU_CC = cc;
+ cc_nxt = ALU[15:8];
+
+ if (ALU8Writeback)
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ if (IsOneByteInstruction(Inst1)) // This check is probably superfluous. Every inherent instruction is 1 byte on the 6809.
+ pc_nxt = pc; // The 6809 auto-reads 2 bytes for every instruction. :( Adjust by not incrementing PC on the 2nd byte read.
+ end
+
+ TYPE_IMMEDIATE:
+ begin
+ if (IsSpecialImmediate)
+ begin
+ if (Inst1 == OPCODE_IMM_ANDCC)
+ begin
+ pc_nxt = pc_p1;
+ cc_nxt = cc & D; //cc_nxt & Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CC_DONTCARE;
+ end
+ else if (Inst1 == OPCODE_IMM_ORCC)
+ begin
+ pc_nxt = pc_p1;
+ cc_nxt = cc | D; //cc_nxt | Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CC_DONTCARE;
+ end
+ else if ( (Inst1 == OPCODE_IMM_PSHS) | (Inst1 == OPCODE_IMM_PSHU) )
+ begin
+ pc_nxt = pc_p1;
+ tmp_nxt[15] = 1'b0;
+ tmp_nxt[14] = Inst1[1]; // Mark whether to save to U or S.
+ tmp_nxt[13] = 1'b0; // Not pushing due to an interrupt.
+ tmp_nxt[13:8] = 6'H00;
+ tmp_nxt[7:0] = Inst2_nxt;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE1;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if ( (Inst1 == OPCODE_IMM_PULS) | (Inst1 == OPCODE_IMM_PULU) )
+ begin
+ pc_nxt = pc_p1;
+ tmp_nxt[15] = 1'b0;
+ tmp_nxt[14] = Inst1[1]; // S (0) or U (1) stack in use.
+ tmp_nxt[13:8] = 6'H00;
+ tmp_nxt[7:0] = Inst2_nxt;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PUL_DONTCARE1;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_IMM_TFR)
+ begin
+ // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2.
+
+ case (Inst2_nxt[3:0])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegA;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegA;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegA;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegA;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegA;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegA;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegA[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE1;
+
+ end
+ else if (Inst1 == OPCODE_IMM_EXG)
+ begin
+ // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2.
+
+ case (Inst2_nxt[7:4])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegB;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegB;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegB;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegB;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegB;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegB;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegB[7:0];
+ default:
+ begin
+ end
+ endcase
+ case (Inst2_nxt[3:0])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegA;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegA;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegA;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegA;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegA;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegA;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegA[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE1;
+ end
+ end
+ // Determine if this is an 8-bit ALU operation.
+ else if (Is8BitInst)
+ begin
+ ALU_OP = ALU8Op;
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ ALU_B = Inst2_nxt;
+ ALU_CC = cc;
+ cc_nxt = ALU[15:8];
+
+ if (ALU8Writeback)
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else // Then it must be a 16 bit instruction
+ begin
+ // 83 SUBD
+ // 8C CMPX
+ // 8E LDX
+ // C3 ADDD
+ // CC LDD
+ // CE LDU
+ // 108E CMPD
+ // 108C CMPY
+ // 108E LDY
+ // 10CE LDS
+ // 1183 CMPU
+ // 118C CMPS
+ // Wow, they were just stuffing them in willy-nilly ...
+
+ // LD* 16 bit immediate
+ if (IsALU16Opcode)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_16IMM_LO;
+ end
+ // there's a dead zone here; I need an else to take us back to CPUSTATE_FETCHI1 if we want to ignore illegal instructions, to CPUSTATE_DEAD if we want to catch them.
+
+ end
+
+ end
+
+ TYPE_RELATIVE:
+ begin
+ // Is this a LB** or a B**?
+ // If InstPage2 is set, it's a long branch; if clear, a normal branch.
+ if ( (InstPage2) || (Inst1 == INST_LBRA) || (Inst1 == INST_LBSR) )
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_LBRA_OFFSETLOW;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_BRA_DONTCARE;
+ end
+
+ end
+ default:
+ begin
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ endcase
+ end
+ end
+
+
+ CPUSTATE_LBRA_OFFSETLOW:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ Inst3_nxt = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_LBRA_DONTCARE;
+ end
+
+ CPUSTATE_LBRA_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if ( TakeBranch )
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_LBRA_DONTCARE2;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_BRA_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ tmp_nxt = pc;
+ if (TakeBranch)
+ begin
+ pc_nxt = pc + { {8{Inst2[7]}}, Inst2[7:0]}; // Sign-extend the 8 bit offset to 16.
+
+ if (Inst1 == INST_BSR)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE1;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+ else
+ begin
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ end
+
+ CPUSTATE_LBRA_DONTCARE2:
+ begin
+ tmp_nxt= pc;
+ addr_nxt = 16'HFFFF;
+
+ // Take branch
+ pc_nxt = pc + {Inst2[7:0], Inst3[7:0]};
+ if (Inst1 == INST_LBSR)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE1;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_BSR_DONTCARE1:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE2;
+ end
+
+ CPUSTATE_BSR_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_RETURNLOW;
+ end
+
+ CPUSTATE_BSR_RETURNLOW:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ DOutput[7:0] = tmp[7:0];
+ RnWOut = 0;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_RETURNHIGH;
+ end
+
+ CPUSTATE_BSR_RETURNHIGH:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ DOutput[7:0] = tmp[15:8];
+ RnWOut = 0;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1; // after this, RnWOut must go to 1, and the bus needs the PC placed on it.
+ end
+
+ CPUSTATE_TFR_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE2;
+ end
+
+ CPUSTATE_TFR_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE3;
+ end
+
+ CPUSTATE_TFR_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE4;
+ end
+
+ CPUSTATE_TFR_DONTCARE4:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_EXG_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE2;
+ end
+
+ CPUSTATE_EXG_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE3;
+ end
+
+ CPUSTATE_EXG_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE4;
+ end
+
+ CPUSTATE_EXG_DONTCARE4:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE5;
+ end
+
+ CPUSTATE_EXG_DONTCARE5:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE6;
+ end
+
+ CPUSTATE_EXG_DONTCARE6:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ABX_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_RTS_HI:
+ begin
+ addr_nxt = s;
+ s_nxt = s_p1;
+ pc_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RTS_LO;
+ end
+
+ CPUSTATE_RTS_LO:
+ begin
+ addr_nxt = s;
+ s_nxt = s_p1;
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_RTS_DONTCARE2;
+ end
+
+ CPUSTATE_RTS_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_16IMM_LO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_B = {Inst2, D[7:0]};
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ ALU16_A = x;
+ ALU16_REG_D:
+ ALU16_A = {a, b};
+ ALU16_REG_Y:
+ ALU16_A = y;
+ ALU16_REG_U:
+ ALU16_A = u;
+ ALU16_REG_S:
+ ALU16_A = s;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+
+ if (ALU16OpWriteback)
+ begin
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_D:
+ {cc_nxt, a_nxt, b_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ {cc_nxt, u_nxt} = ALU16;
+ ALU16_REG_S:
+ {cc_nxt, s_nxt} = ALU16;
+ default:
+ begin
+ end
+ endcase
+ end
+ else
+ cc_nxt = ALU16[23:16];
+
+ if (ALU16_OP == ALUOP16_LD)
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_16IMM_DONTCARE;
+ end
+ end
+
+ CPUSTATE_DIRECT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_ALU_EA:
+ begin
+
+ // Is Figure 18/5 Column 2? JMP (not Immediate Mode)
+ // This actually isn't done here. All checks passing in to ALU_EA should check for a JMP; FIXME EVERYWHERE
+
+ // Is Figure 18/5 Column 8? TST (not immediate mode)
+ // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST.
+
+ // Is Figure 18/5 Column 3?
+ if (IsALU8Set1(Inst1))
+ begin
+ addr_nxt = ea;
+
+ ALU_OP = ALU8Op;
+ ALU_B = D[7:0];
+ ALU_CC = cc;
+
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ cc_nxt = ALU[15:8];
+
+ if ( (ALU8Writeback) )
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ // Is Figure 18/5 Column 4? (Store, 8 bits)
+ else if (IsStore8)
+ begin
+ addr_nxt = ea;
+ RnWOut = 0; // write
+
+ ALU_OP = ALUOP_LD; // load has the same CC characteristics as store
+ ALU_A = 8'H00;
+ ALU_CC = cc;
+
+ case (Store8RegisterNum)
+ ST8_REG_A:
+ begin
+ DOutput = a;
+ ALU_B = a;
+ end
+ ST8_REG_B:
+ begin
+ DOutput = b;
+ ALU_B = b;
+ end
+
+
+ endcase
+
+ cc_nxt = ALU[15:8];
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ // Is Figure 18/5 Column 5? (Load, 16 bits)
+ else if (IsALU16Opcode & (ALU16Opcode == ALUOP16_LD))
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ x_nxt[15:8] = D[7:0];
+ ALU16_REG_D:
+ a_nxt = D[7:0];
+ ALU16_REG_Y:
+ y_nxt[15:8] = D[7:0];
+ ALU16_REG_S:
+ s_nxt[15:8] = D[7:0];
+ ALU16_REG_U:
+ u_nxt[15:8] = D[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_LD16_LO;
+
+ end
+
+ // Is Figure 18/5 Column 6? (Store, 16 bits)
+ else if (IsStore16)
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ ALU16_OP = ALUOP16_LD; // LD and ST have the same CC characteristics
+ ALU16_CC = cc;
+ ALU16_A = 8'H00;
+
+ case (StoreRegisterNum)
+ ST16_REG_X:
+ begin
+ DOutput[7:0] = x[15:8];
+ ALU16_B = x;
+ end
+ ST16_REG_Y:
+ begin
+ DOutput[7:0] = y[15:8];
+ ALU16_B = y;
+ end
+ ST16_REG_U:
+ begin
+ DOutput[7:0] = u[15:8];
+ ALU16_B = u;
+ end
+ ST16_REG_S:
+ begin
+ DOutput[7:0] = s[15:8];
+ ALU16_B = s;
+ end
+ ST16_REG_D:
+ begin
+ DOutput[7:0] = a[7:0];
+ ALU16_B = {a,b};
+ end
+ default:
+ begin
+ end
+ endcase
+
+ cc_nxt = ALU16[23:16];
+
+ RnWOut = 0; // Write
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ST16_LO;
+ end
+
+ // Is Figure 18/5 Column 7?
+ else if (IsALU8Set0(Inst1))
+ begin
+ // These are registerless instructions, ala
+ // ASL, ASR, CLR, COM, DEC, INC, (LSL), LSR, NEG, ROL, ROR
+ // and TST (special!)
+ // They require READ, Modify (the operation above), WRITE. Between the Read and the Write cycles, there's actually a /VMA
+ // cycle where the 6809 likely did the operation. We'll include a /VMA cycle for accuracy, but we'll do the work primarily in the first cycle.
+ addr_nxt = ea;
+
+ ALU_OP = ALU8Op;
+ ALU_A = D[7:0];
+ ALU_CC = cc;
+ tmp_nxt[15:8] = cc; // for debug only
+ tmp_nxt[7:0] = ALU[7:0];
+ cc_nxt = ALU[15:8];
+ if (ALU8Op == ALUOP_TST)
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TST_DONTCARE1;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_DONTCARE;
+ end
+
+ end
+
+ // Is Figure 18/5 Column 8? TST
+ // NOTE:
+ // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. [Directly above.]
+
+
+ // Is Figure 18/5 Column 9? (16-bit ALU ops, non-load)
+ else if (IsALU16Opcode && (ALU16Opcode != ALUOP16_LD) && ((Inst1 < 8'H30) || (Inst1 > 8'H33)) ) // 30-33 = LEAX, LEAY, LEAS, LEAU; don't include them here.
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ tmp_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU16_LO;
+
+ end
+
+ // Is Figure 18/5 Column 10? JSR (not Immediate Mode)
+ else if ((Inst1 == 8'H9D) || (Inst1 == 8'HAD) || (Inst1 == 8'HBD)) // JSR
+ begin
+ pc_nxt = ea;
+ addr_nxt = ea;
+ tmp_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_JSR_DONTCARE;
+ end
+ // Is Figure 18/5 Column 11? LEA(X,Y,S,U)
+ else if ((Inst1 >= 8'H30) && (Inst1<= 8'H33))
+ begin
+ addr_nxt = 16'HFFFF; // Ack, actually a valid cycle, this isn't a dontcare (/VMA) cycle!
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_A = ea;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ u_nxt = ALU16[15:0];
+ ALU16_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+
+ end
+
+ end
+
+
+ CPUSTATE_ALU_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rBUSY = 1'b1; // We do nothing here, but on the real 6809, they did the modify phase here. :|
+ CpuState_nxt = CPUSTATE_ALU_WRITEBACK;
+ end
+
+ CPUSTATE_ALU_WRITEBACK:
+ begin
+ addr_nxt = ea;
+ RnWOut = 0; // Write
+ DOutput = tmp[7:0];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_LD16_LO:
+ begin
+ addr_nxt = ea;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ begin
+ x_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = x[15:8];
+ end
+ ALU16_REG_D:
+ begin
+ b_nxt = D[7:0];
+ ALU16_B[15:8] = a;
+ end
+ ALU16_REG_Y:
+ begin
+ y_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = y[15:8];
+ end
+ ALU16_REG_S:
+ begin
+ s_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = s[15:8];
+ end
+ ALU16_REG_U:
+ begin
+ u_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = u[15:8];
+ end
+ default:
+ begin
+ end
+
+ endcase
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_A = 8'H00;
+ ALU16_B[7:0] = D[7:0];
+ cc_nxt = ALU16[23:16];
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ST16_LO:
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+ case (StoreRegisterNum)
+ ST16_REG_X:
+ DOutput[7:0] = x[7:0];
+ ST16_REG_Y:
+ DOutput[7:0] = y[7:0];
+ ST16_REG_U:
+ DOutput[7:0] = u[7:0];
+ ST16_REG_S:
+ DOutput[7:0] = s[7:0];
+ ST16_REG_D:
+ DOutput[7:0] = b[7:0];
+ default:
+ begin
+ end
+ endcase
+ RnWOut = 0; // write
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ALU16_LO:
+ begin
+ addr_nxt = ea;
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+
+ ALU16_B = {tmp[15:8], D[7:0]};
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ ALU16_A = x;
+ ALU16_REG_D:
+ ALU16_A = {a, b};
+ ALU16_REG_Y:
+ ALU16_A = y;
+ ALU16_REG_S:
+ ALU16_A = s;
+ ALU16_REG_U:
+ ALU16_A = u;
+ default:
+ ALU16_A = 16'H0;
+
+ endcase
+
+ if (ALU16OpWriteback)
+ begin
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_D:
+ {cc_nxt, a_nxt, b_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ {cc_nxt, u_nxt} = ALU16;
+ ALU16_REG_S:
+ {cc_nxt, s_nxt} = ALU16;
+ default:
+ begin
+ end
+ endcase
+ end
+ else
+ cc_nxt = ALU16[23:16];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_ALU16_DONTCARE;
+ end
+
+ CPUSTATE_ALU16_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+
+ CPUSTATE_JSR_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_JSR_RETLO;
+ end
+
+ CPUSTATE_JSR_RETLO:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ RnWOut = 0;
+ DOutput = tmp[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_JSR_RETHI;
+ end
+
+ CPUSTATE_JSR_RETHI:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ RnWOut = 0;
+ DOutput = tmp[15:8];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_EXTENDED_ADDRLO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ ea_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXTENDED_DONTCARE;
+ end
+
+ CPUSTATE_EXTENDED_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_INDEXED_BASE:
+ begin
+ addr_nxt = pc;
+
+ Inst3_nxt = D[7:0];
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc_p1;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+ ALU16_OP = ALUOP16_ADD;
+
+ case (IndexedMode)
+ IDX_MODE_NOOFFSET:
+ begin
+ case (IndexedRegister)
+ IDX_REG_X:
+ ea_nxt = x;
+ IDX_REG_Y:
+ ea_nxt = y;
+ IDX_REG_U:
+ ea_nxt = u;
+ IDX_REG_S:
+ ea_nxt = s;
+ default:
+ ea_nxt = 16'H0;
+ endcase
+
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea_nxt;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ IDX_MODE_5BIT_OFFSET:
+ begin
+ // The offset is the bottom 5 bits of the Index Postbyte, which is Inst2 here.
+ // We'll sign-extend it to 16 bits.
+ ALU16_B = { {11{Inst2[4]}}, Inst2[4:0] };
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+
+ IDX_MODE_8BIT_OFFSET_PC:
+ begin
+ ALU16_B = { {8{D[7]}}, D[7:0] };
+ pc_nxt = pc_p1;
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+ IDX_MODE_8BIT_OFFSET:
+ begin
+ ALU16_B = { {8{D[7]}}, D[7:0] };
+ pc_nxt = pc_p1;
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+ IDX_MODE_A_OFFSET:
+ begin
+ ALU16_B = { {8{a[7]}}, a[7:0] };
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ ea_nxt = ALU16[15:0];
+ end
+
+ IDX_MODE_B_OFFSET:
+ begin
+ ALU16_B = { {8{b[7]}}, b[7:0] };
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ ea_nxt = ALU16[15:0];
+ end
+
+ IDX_MODE_D_OFFSET:
+ begin
+ ALU16_B = {a, b};
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE1;
+ end
+
+ IDX_MODE_POSTINC1:
+ begin
+ ALU16_B = 16'H1;
+ ea_nxt = ALU16_A;
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ IDX_MODE_POSTINC2:
+ begin
+ ALU16_B = 16'H2;
+ ea_nxt = ALU16_A;
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0;
+ end
+
+ IDX_MODE_PREDEC1:
+ begin
+ ALU16_B = 16'HFFFF; // -1
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ IDX_MODE_PREDEC2:
+ begin
+ ALU16_B = 16'HFFFE; // -2
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0;
+ end
+
+ IDX_MODE_16BIT_OFFSET_PC:
+ begin
+ tmp_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO;
+ end
+
+ IDX_MODE_16BIT_OFFSET:
+ begin
+ tmp_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO;
+ end
+
+ IDX_MODE_EXTENDED_INDIRECT:
+ begin
+ ea_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_EXTIND_LO;
+ end
+
+ default:
+ begin
+ rLIC = 1'b1;
+ CpuState_nxt = PostIllegalState;
+ end
+
+ endcase
+ end
+
+ CPUSTATE_IDX_OFFSET_LO:
+ begin
+ tmp_nxt[7:0] = D[7:0];
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ ALU16_B = tmp_nxt;
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+ ALU16_OP = ALUOP16_ADD;
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1;
+ end
+
+
+ CPUSTATE_IDX_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ end
+
+ CPUSTATE_IDX_16OFFSET_LO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc_nxt; // Whups; tricky; not part of the actual pattern
+ default:
+ ALU16_A = x; // Default to something
+ endcase
+
+ ALU16_OP = ALUOP16_ADD;
+
+ ALU16_B = {tmp[15:8], D[7:0]};
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE1:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE0:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedRegister == IDX_REG_PC)
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_PC16OFF_DONTCARE;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3;
+ end
+ end
+
+ CPUSTATE_IDX_PC16OFF_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3;
+ end
+
+
+ CPUSTATE_IDX_16OFF_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE1:
+ begin
+ addr_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE2:
+ begin
+ addr_nxt = pc_p2;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE3:
+ begin
+ addr_nxt = pc_p3;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_EXTIND_LO:
+ begin
+ ea_nxt[7:0] = D[7:0];
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_EXTIND_DONTCARE;
+ end
+
+ CPUSTATE_IDX_EXTIND_DONTCARE:
+ begin
+ addr_nxt = pc;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ CPUSTATE_INDIRECT_HI:
+ begin
+ addr_nxt = ea;
+ tmp_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_LO;
+ end
+
+ CPUSTATE_INDIRECT_LO:
+ begin
+ addr_nxt = ea_p1;
+ ea_nxt[15:8] = tmp_nxt[15:8];
+ ea_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_INDIRECT_DONTCARE;
+ end
+
+ CPUSTATE_INDIRECT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_MUL_ACTION:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ // tmp = result
+ // ea = additor (the shifted multiplicand)
+ // a = counter
+ // b is the multiplier (which gets shifted right)
+ if (a != 8'H00)
+ begin
+ if (b[0])
+ begin
+ tmp_nxt = tmp + ea;
+ end
+ ea_nxt = {ea[14:0], 1'b0};
+ b_nxt = {1'b0, b[7:1]};
+ a_nxt = a - 8'H1;
+ end
+ else
+ begin
+ {a_nxt, b_nxt} = tmp;
+
+ cc_nxt[CC_Z_BIT] = (tmp == 0);
+ cc_nxt[CC_C_BIT] = tmp[7];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_PSH_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE2;
+ end
+
+ CPUSTATE_PSH_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE3;
+ end
+
+ CPUSTATE_PSH_DONTCARE3:
+ begin
+ addr_nxt = (Inst1[1]) ? u : s;
+
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+ CPUSTATE_PSH_ACTION:
+ begin
+ rAVMA = 1'b1;
+ if (tmp[7] & ~(tmp[15])) // PC_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = pc[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[7] & (tmp[15])) // PC_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = pc[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[7] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[6] & ~(tmp[15])) // U/S_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = (tmp[14]) ? s[7:0] : u[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[6] & (tmp[15])) // U/S_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = (tmp[14]) ? s[15:8] : u[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[6] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[5] & ~(tmp[15])) // Y_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = y[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[5] & (tmp[15])) // Y_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = y[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[5] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[4] & ~(tmp[15])) // X_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = x[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[4] & (tmp[15])) // X_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = x[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[4] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[3]) // DP
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = dp;
+ RnWOut = 1'b0; // write
+ tmp_nxt[3] = 1'b0;
+ end
+ else if (tmp[2]) // B
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = b;
+ RnWOut = 1'b0; // write
+ tmp_nxt[2] = 1'b0;
+ end
+ else if (tmp[1]) // A
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = a;
+ RnWOut = 1'b0; // write
+ tmp_nxt[1] = 1'b0;
+ end
+ else if (tmp[0]) // CC
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = cc;
+ RnWOut = 1'b0; // write
+ tmp_nxt[0] = 1'b0;
+ end
+ if (tmp[13]) // Then we're pushing for an IRQ, and LIC is supposed to be set.
+ rLIC = 1'b1;
+ if (tmp_nxt[7:0] == 8'H00)
+ begin
+ if (NextState == CPUSTATE_FETCH_I1)
+ begin
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ end
+ else
+ rAVMA = 1'b0;
+ CpuState_nxt = NextState;
+ end
+ end
+
+ CPUSTATE_PUL_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PUL_DONTCARE2;
+ end
+
+ CPUSTATE_PUL_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PUL_ACTION;
+ end
+
+ CPUSTATE_PUL_ACTION:
+ begin
+ rAVMA = 1'b1;
+ if (tmp[0]) // CC
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ cc_nxt = D[7:0];
+ if (tmp[12] == 1'b1) // This pull is from an RTI, the E flag comes from the retrieved CC, and set the tmp_nxt accordingly, indicating what other registers to retrieve
+ begin
+ if (D[CC_E_BIT])
+ tmp_nxt[7:0] = 8'HFE; // Retrieve all registers (ENTIRE) [CC is already retrieved]
+ else
+ tmp_nxt[7:0] = 8'H80; // Retrieve PC and CC [CC is already retrieved]
+ end
+ else
+ tmp_nxt[0] = 1'b0;
+ end
+ else if (tmp[1]) // A
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ a_nxt = D[7:0];
+ tmp_nxt[1] = 1'b0;
+ end
+ else if (tmp[2]) // B
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ b_nxt = D[7:0];
+ tmp_nxt[2] = 1'b0;
+ end
+ else if (tmp[3]) // DP
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ dp_nxt = D[7:0];
+ tmp_nxt[3] = 1'b0;
+ end
+ else if (tmp[4] & (~tmp[15])) // X_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ x_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[4] & tmp[15]) // X_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ x_nxt[7:0] = D[7:0];
+ tmp_nxt[4] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[5] & (~tmp[15])) // Y_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ y_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[5] & tmp[15]) // Y_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ y_nxt[7:0] = D[7:0];
+ tmp_nxt[5] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[6] & (~tmp[15])) // U/S_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ if (tmp[14])
+ s_nxt[15:8] = D[7:0];
+ else
+ u_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[6] & tmp[15]) // U/S_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ if (tmp[14])
+ s_nxt[7:0] = D[7:0];
+ else
+ u_nxt[7:0] = D[7:0];
+ tmp_nxt[6] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[7] & (~tmp[15])) // PC_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ pc_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[7] & tmp[15]) // PC_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ pc_nxt[7:0] = D[7:0];
+ tmp_nxt[7] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (NextState == CPUSTATE_FETCH_I1)
+ begin
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ end
+ else
+ rAVMA = 1'b0;
+ CpuState_nxt = NextState;
+ end
+ end
+
+ CPUSTATE_NMI_START:
+ begin
+ NMIClear_nxt = 1'b1;
+ addr_nxt = pc;
+ // tmp stands as the bits to push to the stack
+ tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_NMI;
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_IRQ_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_IRQ;
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_FIRQ_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H2081; // Save to the S stack, PC, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_FIRQ;
+ cc_nxt[CC_E_BIT] = 1'b0;
+ end
+
+ CPUSTATE_SWI_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC
+
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ if (InstPage3)
+ IntType_nxt = INTTYPE_SWI3;
+ if (InstPage2)
+ IntType_nxt = INTTYPE_SWI2;
+ else
+ IntType_nxt = INTTYPE_SWI;
+
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_IRQ_DONTCARE:
+ begin
+ NMIClear_nxt = 1'b0;
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+
+ CPUSTATE_IRQ_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ rLIC = 1'b1;
+ end
+
+ CPUSTATE_IRQ_VECTOR_HI:
+ begin
+ case (IntType)
+ INTTYPE_NMI:
+ begin
+ addr_nxt = `NMI_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_IRQ:
+ begin
+ addr_nxt = `IRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI:
+ begin
+ addr_nxt = `SWI_VECTOR;
+ end
+ INTTYPE_FIRQ:
+ begin
+ addr_nxt = `FIRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI2:
+ begin
+ addr_nxt = `SWI2_VECTOR;
+ end
+ INTTYPE_SWI3:
+ begin
+ addr_nxt = `SWI3_VECTOR;
+ end
+ default: // make the default an IRQ, even though it really should never happen
+ begin
+ addr_nxt = `IRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ endcase
+
+ pc_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_LO;
+
+
+ end
+
+ CPUSTATE_IRQ_VECTOR_LO:
+ begin
+ case (IntType)
+ INTTYPE_NMI:
+ begin
+ addr_nxt = `NMI_VECTOR+16'H1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_IRQ:
+ begin
+ addr_nxt = `IRQ_VECTOR+16'H1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI:
+ begin
+ addr_nxt = `SWI_VECTOR+16'H1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ rLIC = 1'b1;
+ end
+ INTTYPE_FIRQ:
+ begin
+ addr_nxt = `FIRQ_VECTOR+16'H1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI2:
+ begin
+ addr_nxt = `SWI2_VECTOR+16'H1;
+ rLIC = 1'b1;
+ end
+ INTTYPE_SWI3:
+ begin
+ addr_nxt = `SWI3_VECTOR+16'H1;
+ rLIC = 1'b1;
+ end
+ default:
+ begin
+ end
+ endcase
+
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_INT_DONTCARE;
+ end
+
+ CPUSTATE_INT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_CC_DONTCARE:
+ begin
+ addr_nxt = pc;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_TST_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TST_DONTCARE2;
+ end
+
+ CPUSTATE_TST_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_DEBUG:
+ begin
+ addr_nxt = tmp;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_16IMM_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_SYNC:
+ begin
+ addr_nxt = 16'HFFFF;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ rAVMA = 1'b0;
+
+ if (~(NMILatched & FIRQLatched & IRQLatched))
+ begin
+ CpuState_nxt = CPUSTATE_SYNC_EXIT;
+ end
+ end
+
+ CPUSTATE_SYNC_EXIT:
+ begin
+ addr_nxt = 16'HFFFF;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+
+ CPUSTATE_DMABREQ:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ tmp_nxt[3:0] = tmp[3:0] - 1'b1;
+ if ( (tmp[3:0] == 4'H0) | (DMABREQSample2) )
+ begin
+ CpuState_nxt = CPUSTATE_DMABREQ_EXIT;
+ end
+ end
+
+ CPUSTATE_DMABREQ_EXIT:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_HALTED:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ if (HALTSample2)
+ begin
+ CpuState_nxt = CPUSTATE_HALT_EXIT2;
+ end
+ end
+
+
+ CPUSTATE_HALT_EXIT2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_STOP:
+ begin
+ addr_nxt = 16'HDEAD;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP2;
+ end
+
+ CPUSTATE_STOP2:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP3;
+ end
+
+ CPUSTATE_STOP3:
+ begin
+ addr_nxt = 16'H0000; //{Inst1, Inst2};
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP;
+ end
+
+ // The otherwise critically useful Figure 18 in the 6809 datasheet contains an error;
+ // it lists that CWAI has a tri-stated bus while it waits for an interrupt.
+ // That is not true. SYNC tristates the bus, as do things like /HALT and /DMABREQ.
+ // CWAI does not. It waits with /VMA cycles on the bus until an interrupt occurs.
+ // The implementation here fits with the 6809 Programming Manual and other Motorola
+ // sources, not with that typo in Figure 18.
+ CPUSTATE_CWAI:
+ begin
+ addr_nxt = pc;
+ cc_nxt = {1'b1, (cc[6:0] & Inst2[6:0])}; // Set E flag, AND CC with CWAI argument
+ tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC
+
+ NextState_nxt = CPUSTATE_CWAI_POST;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_CWAI_DONTCARE1;
+ end
+
+ CPUSTATE_CWAI_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+ CPUSTATE_CWAI_POST:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+
+ CpuState_nxt = CPUSTATE_CWAI_POST;
+
+ // Wait for an interrupt
+ if (NMILatched == 0)
+ begin
+ rAVMA = 1'b1;
+ IntType_nxt = INTTYPE_NMI;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0))
+ begin
+ rAVMA = 1'b1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ IntType_nxt = INTTYPE_FIRQ;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0))
+ begin
+ rAVMA = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ IntType_nxt = INTTYPE_IRQ;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ end
+
+ default: // Picky darned Verilog.
+ begin
+ CpuState_nxt = PostIllegalState;
+ end
+
+ endcase
+end
+
+endmodule
+
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip b/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip
new file mode 100644
index 00000000..67c0410c
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip
@@ -0,0 +1,7 @@
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k082.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k083.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k501.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k502.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k503.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/KONAMI-1/KONAMI1.sv
+set_global_assignment -name VERILOG_FILE rtl/custom/KONAMI-1/mc6809isk.v
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k082.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k082.sv
new file mode 100644
index 00000000..9dd391f8
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k082.sv
@@ -0,0 +1,168 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 082 custom chip, used by
+// several Konami arcade PCBs to generate video timings
+// Copyright (C) 2020, 2021 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:
+/* _____________
+ _| |_
+reset |_|1 28|_| VCC
+ _| |_
+h1 |_|2 27|_| GND
+ _| |_
+h2 |_|3 26|_| v1
+ _| |_
+h4 |_|4 25|_| v2
+ _| |_
+h8 |_|5 24|_| v4
+ _| |_
+h16 |_|6 23|_| v8
+ _| |_
+h32 |_|7 22|_| v16
+ _| |_
+h64 |_|8 21|_| v32
+ _| |_
+h128 |_|9 20|_| v64
+ _| |_
+n_h256 |_|10 19|_| v128
+ _| |_
+h256 |_|11 18|_| n_vsync
+ _| |_
+VCC |_|12 17|_| sync
+ _| |_
+clk |_|13 16|_| vblk
+ _| |_
+GND |_|14 15|_| n_vblk
+ |_____________|
+
+Note: Pins 12 and 27 may control other features of the 082 - these, if any, have not
+been modelled yet.
+*/
+
+module k082
+(
+ input reset, //Active low
+ input clk,
+ input cen, //Set to 1 if using this code to replace a real 082
+ input [3:0] h_center, v_center, //These inputs are additions for screen centering and don't exist on the actual 082
+ output n_vsync, sync,
+ output n_hsync, //Not exposed on the original chip
+ output reg vblk = 1,
+ output n_vblk,
+ output reg vblk_irq_en = 0, //This is an extra output not present on the real 082 to signal when to
+ //trigger a VBlank IRQ (signal is active high)
+ output h1, h2, h4, h8, h16, h32, h64, h128, h256, n_h256,
+ output v1, v2, v4, v8, v16, v32, v64, v128
+);
+
+//The 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 (both counters increment by 1 when the horizontal counter is set to 48)
+//-Horizontal counter resets to 128 for a total of 383 horizontal lines
+//-Vertical counter resets to 248 for a total of 263 vertical lines (adjustable with added vertical center signal)
+//-Vertical counter increments when the horizontal counter equals 176
+//-VBlank is active when the horizontal counter is between 495 - 511 and 248 - 270
+//Model this behavior here
+always_ff @(posedge clk or negedge reset) begin
+ if(!reset) begin
+ h_cnt <= 9'd0;
+ v_cnt <= 9'd0;
+ end
+ else if(cen) begin
+ case(h_cnt)
+ 48: begin
+ v_cnt <= v_cnt + 9'd1;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 176: begin
+ h_cnt <= h_cnt + 9'd1;
+ case(v_cnt)
+ 16: begin
+ vblk <= 0;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ 271: begin
+ vblk <= 0;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ 495: begin
+ vblk <= 1;
+ vblk_irq_en <= 1;
+ v_cnt <= v_cnt + 9'd1;
+ end
+ vcnt_end: v_cnt <= vcnt_start;
+ default: v_cnt <= v_cnt + 9'd1;
+ endcase
+ end
+ 177: begin
+ vblk_irq_en <= 0;
+ h_cnt <= h_cnt + 9'd1;
+ end
+ 511: h_cnt <= 9'd128;
+ default: h_cnt <= h_cnt + 9'd1;
+ endcase
+ end
+end
+
+//The Konami 082 has both an active low VBlank and an active high VBlank - generate the active low VBlank by inverting
+//the active high VBlank generated in the previous sequential block
+assign n_vblk = ~vblk;
+
+//Generate active low HSync, VSync and composite sync
+assign n_hsync = h_center[3] ? ~(h_cnt > (182 - h_center[2:0]) && h_cnt < (215 - h_center[2:0])):
+ ~(h_cnt > (175 - h_center[2:0]) && h_cnt < (208 - h_center[2:0]));
+assign n_vsync = h_center[3] ? ~(v_cnt >= vcnt_start + 9'd1 && v_cnt <= vcnt_start + 9'd9) : ~(v_cnt >= vcnt_start && v_cnt <= vcnt_start + 9'd8);
+assign sync = n_hsync ^ n_vsync;
+
+//Assign the individual horizontal counter bits to their respective outputs (also invert bit 8 of the horizontal counter for H256)
+assign h1 = h_cnt[0];
+assign h2 = h_cnt[1];
+assign h4 = h_cnt[2];
+assign h8 = h_cnt[3];
+assign h16 = h_cnt[4];
+assign h32 = h_cnt[5];
+assign h64 = h_cnt[6];
+assign h128 = h_cnt[7];
+assign h256 = ~h_cnt[8];
+assign n_h256 = h_cnt[8];
+
+//Assign the individual vertical counter bits to their respective outputs
+assign v1 = v_cnt[0];
+assign v2 = v_cnt[1];
+assign v4 = v_cnt[2];
+assign v8 = v_cnt[3];
+assign v16 = v_cnt[4];
+assign v32 = v_cnt[5];
+assign v64 = v_cnt[6];
+assign v128 = v_cnt[7];
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k083.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k083.sv
new file mode 100644
index 00000000..f025b63f
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k083.sv
@@ -0,0 +1,101 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 083 custom chip, a custom
+// shift register used on many early Konami arcade PCBs for handling graphics
+// ROMs
+// Copyright (C) 2020, 2021 Ace & ElectronAsh
+//
+// 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:
+/* _____________
+ _| |_
+CK |_|1 28|_| VCC
+ _| |_
+FLIP |_|2 27|_| LOAD
+ _| |_
+DB1i(4) |_|3 26|_| DB1i(6)
+ _| |_
+DB1i(0) |_|4 25|_| DB1i(2)
+ _| |_
+DB0i(4) |_|5 24|_| DB0i(6)
+ _| |_
+DB0i(6) |_|6 23|_| DB0i(2)
+ _| |_
+DB1i(5) |_|7 22|_| DB1i(7)
+ _| |_
+DB1i(1) |_|8 21|_| DB1i(3)
+ _| |_
+DB0i(5) |_|9 20|_| DB0i(7)
+ _| |_
+DB0i(1) |_|10 19|_| DB0i(3)
+ _| |_
+NC |_|11 18|_| NC
+ _| |_
+DSH1(1) |_|12 17|_| DSH1(0)
+ _| |_
+DSH0(1) |_|13 16|_| DSH0(0)
+ _| |_
+GND |_|14 15|_| NC
+ |_____________|
+*/
+
+module k083
+(
+ input CK,
+ input CEN, //Set to 1 if using this code to replace a real 083
+ input FLIP,
+ input LOAD,
+ input [7:0] DB0i, DB1i,
+ output [1:0] DSH0, DSH1
+);
+
+//Internal registers (shift right and shift left)
+reg [7:0] pixel_D0_l, pixel_D0_r;
+reg [7:0] pixel_D1_l, pixel_D1_r;
+
+//Latch and shift pixel data
+always_ff @(posedge CK) begin
+ if(CEN) begin
+ if(LOAD) begin
+ pixel_D0_l <= DB0i;
+ pixel_D1_l <= DB1i;
+ pixel_D0_r <= DB0i;
+ pixel_D1_r <= DB1i;
+ end
+ else begin
+ pixel_D0_l[3:0] <= {pixel_D0_l[2:0], 1'b0};
+ pixel_D0_l[7:4] <= {pixel_D0_l[6:4], 1'b0};
+ pixel_D1_l[3:0] <= {pixel_D1_l[2:0], 1'b0};
+ pixel_D1_l[7:4] <= {pixel_D1_l[6:4], 1'b0};
+ pixel_D0_r[3:0] <= {1'b0, pixel_D0_r[3:1]};
+ pixel_D0_r[7:4] <= {1'b0, pixel_D0_r[7:5]};
+ pixel_D1_r[3:0] <= {1'b0, pixel_D1_r[3:1]};
+ pixel_D1_r[7:4] <= {1'b0, pixel_D1_r[7:5]};
+ end
+ end
+end
+
+//Output shifted pixel data (reverse the bits if FLIP is low)
+assign DSH0 = FLIP ? {pixel_D0_l[3], pixel_D0_l[7]} : {pixel_D0_r[0], pixel_D0_r[4]};
+assign DSH1 = FLIP ? {pixel_D1_l[3], pixel_D1_l[7]} : {pixel_D1_r[0], pixel_D1_r[4]};
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k501.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k501.sv
new file mode 100644
index 00000000..8bbd3afb
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k501.sv
@@ -0,0 +1,101 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 501 custom chip, used by some
+// Konami arcade PCBs for partial address decoding and obfuscation of data
+// I/O
+// Copyright (C) 2021 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:
+/* _____________
+ _| |_
+D[7] |_|1 28|_| VCC
+ _| |_
+D[6] |_|2 27|_| XD[7]
+ _| |_
+D[5] |_|3 26|_| XD[6]
+ _| |_
+D[4] |_|4 25|_| XD[5]
+ _| |_
+D[3] |_|5 24|_| XD[4]
+ _| |_
+D[2] |_|6 23|_| XD[3]
+ _| |_
+D[1] |_|7 22|_| XD[2]
+ _| |_
+D[0] |_|8 21|_| XD[1]
+ _| |_
+H2 |_|9 20|_| XD[0]
+ _| |_
+H1 |_|10 19|_| WAIT
+ _| |_
+CLK |_|11 18|_| ENABLE
+ _| |_
+RAM |_|12 17|_| WRITE
+ _| |_
+RD |_|13 16|_| NC
+ _| |_
+GND |_|14 15|_| NC
+ |_____________|
+
+Note: The data bus is bidirectional - this model splits these pins into separate data I/O
+*/
+
+module k501
+(
+ input CLK, //Clock input (add a PLL to multiply the 6.144MHz pixel clock if replacing a real 501)
+ input CEN, //Clock enable at 12.288MHz
+ input H1, H2, //Bits 0 and 1 of the horizontal counter
+ input RAM, //Chip select (active low)
+ input RD, //Z80 read input
+ output WAIT, //Z80 wait output
+ output WRITE, //Write output
+ output ENABLE, //Enable output
+ input [7:0] Di, XDi, //Inputs from data busses
+ output [7:0] Do, XDo //Outputs to data busses
+);
+
+//Data bus passthrough
+assign XDo = Di;
+assign Do = XDi;
+
+//Latch bit 0 of the horizontal counter on each edge of the clock and preset to 1 if bit 1 of the horizontal counter
+//is high
+reg [1:0] h1_reg = 2'd0;
+always_ff @(posedge CLK) begin
+ if(H2)
+ h1_reg[0] <= 1;
+ else if(CEN)
+ h1_reg <= {h1_reg[0], H1};
+end
+
+//AND both latched instances of H1
+wire h1_lat = &h1_reg;
+
+//Generate WAIT output
+assign WAIT = ~H2 | RAM;
+
+//Generate WRITE and ENABLE outputs
+assign WRITE = ~RD | ENABLE;
+assign ENABLE = h1_lat | RAM;
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv
new file mode 100644
index 00000000..717c4cee
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv
@@ -0,0 +1,162 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 502 custom chip, used for
+// generating sprites on a number of '80s Konami arcade PCBs
+// Copyright (C) 2020, 2021 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:
+/* _____________
+ _| |_
+SPLB(0) |_|1 28|_| VCC
+ _| |_
+SPLB(1) |_|2 27|_| RESET
+ _| |_
+SPLB(2) |_|3 26|_| SPLB(4)
+ _| |_
+SPLB(3) |_|4 25|_| SPLB(5)
+ _| |_
+CK1 |_|5 24|_| SPLB(6)
+ _| |_
+CK2 |_|6 23|_| SPLB(7)
+ _| |_
+H2 |_|7 22|_| OLD
+ _| |_
+LD0 |_|8 21|_| OCLR
+ _| |_
+H256 |_|9 20|_| OSEL
+ _| |_
+SPAL(3) |_|10 19|_| COL(4)
+ _| |_
+SPAL(2) |_|11 18|_| COL(3)
+ _| |_
+SPAL(1) |_|12 17|_| COL(2)
+ _| |_
+SPAL(0) |_|13 16|_| COL(1)
+ _| |_
+GND |_|14 15|_| COL(0)
+ |_____________|
+
+Note: The SPLB pins are bidirectional - this model splits these pins into separate
+ data I/O
+*/
+
+module k502
+(
+ input RESET,
+ input CK1,
+ input CK2,
+ input CEN, //Set to 1 if using this code to replace a real 502
+ input LD0,
+ input H2,
+ input H256,
+ input [3:0] SPAL,
+ input [7:0] SPLBi,
+ output OSEL,
+ output OLD,
+ output OCLR,
+ output [7:0] SPLBo,
+ output [4:0] COL
+);
+
+//As the Konami 502 doesn't have a dedicated input for bit 2 of the horizontal counter (H4), generate
+//this signal internally by dividing H2 by 2
+reg h2_div = 0;
+always_ff @(posedge H2) begin
+ h2_div <= ~h2_div;
+end
+wire h4 = h2_div;
+
+//Latch H256 on rising edge of LD0 and delay by one cycle (set to 0 if 502 is held in reset)
+reg h256_lat = 0;
+always_ff @(posedge LD0 or negedge RESET) begin
+ if(!RESET)
+ h256_lat <= 0;
+ else
+ h256_lat <= H256;
+end
+reg h256_dly = 0;
+always_ff @(posedge h256_lat or negedge RESET) begin
+ if(!RESET)
+ h256_dly <= 0;
+ else
+ h256_dly <= ~h256_dly;
+end
+
+//Generate OSEL, OLD and OCLR
+reg [1:0] osel_reg;
+always_ff @(negedge H2 or negedge RESET) begin
+ if(!RESET)
+ osel_reg <= 2'b00;
+ else begin
+ if(!h4)
+ osel_reg[1] <= h256_dly;
+ else
+ osel_reg[0] <= osel_reg[1];
+ end
+end
+assign OLD = ~osel_reg[1];
+assign OSEL = osel_reg[0];
+assign OCLR = ~osel_reg[0];
+
+//Multiplex incoming line buffer RAM data
+wire [3:0] lbuff_Dmux = OCLR ? SPLBi[3:0] : SPLBi[7:4];
+
+//Latch incoming line buffer RAM data on the falling edge of CK1
+reg [7:0] lbuff_lat;
+always_ff @(negedge CK1) begin
+ if(!RESET)
+ lbuff_lat <= 8'd0;
+ else if(CEN)
+ lbuff_lat <= SPLBi;
+end
+
+//Latch multiplexed line buffer RAM data on the falling edge of CK2
+reg [3:0] lbuff_mux_lat;
+always_ff @(negedge CK2) begin
+ if(!RESET)
+ lbuff_mux_lat <= 4'd0;
+ else if(CEN)
+ lbuff_mux_lat <= lbuff_Dmux;
+end
+
+//Assign sprite data output
+assign COL[4] = ~(|lbuff_mux_lat[3:0]);
+assign COL[3:0] = lbuff_mux_lat[3:0];
+
+//Select sprite or palette data based on a 4-way AND of the inverted latched line buffer data
+//(upper 4 bits and lower 4 bits produce separate select signals)
+wire sprite_pal_sel2 = (~lbuff_lat[7] & ~lbuff_lat[6] & ~lbuff_lat[5] & ~lbuff_lat[4]);
+wire sprite_pal_sel1 = (~lbuff_lat[3] & ~lbuff_lat[2] & ~lbuff_lat[1] & ~lbuff_lat[0]);
+
+//Multiplex sprite data from line buffer with palette data (lower 4 bits)
+wire [7:0] sprite_pal_mux;
+assign sprite_pal_mux[3:0] = osel_reg[0] ? (sprite_pal_sel1 ? SPAL : SPLBi[3:0]) : 4'h0;
+
+//Multiplex sprite data from line buffer with palette data (upper 4 bits)
+assign sprite_pal_mux[7:4] = ~osel_reg[0] ? (sprite_pal_sel2 ? SPAL : SPLBi[7:4]) : 4'h0;
+
+//Output data to sprite line buffer
+assign SPLBo = sprite_pal_mux;
+
+endmodule
+
diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv
new file mode 100644
index 00000000..bf464503
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv
@@ -0,0 +1,119 @@
+//============================================================================
+//
+// SystemVerilog implementation of the Konami 503 custom chip, used by
+// several Konami arcade PCBs for handling sprite data
+// Copyright (C) 2020, 2021 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:
+/* _____________
+ _| |_
+OB(7) |_|1 40|_| VCC
+ _| |_
+OB(6) |_|2 39|_| VCNT(7)
+ _| |_
+OB(5) |_|3 38|_| VCNT(6)
+ _| |_
+OB(4) |_|4 37|_| VCNT(5)
+ _| |_
+OB(3) |_|5 36|_| VCNT(4)
+ _| |_
+OB(2) |_|6 35|_| VCNT(3)
+ _| |_
+OB(1) |_|7 34|_| VCNT(2)
+ _| |_
+OB(0) |_|8 33|_| VCNT(1)
+ _| |_
+R(5) |_|9 32|_| VCNT(0)
+ _| |_
+R(4) |_|10 31|_| NC
+ _| |_
+R(3) |_|11 30|_| OFLP
+ _| |_
+R(2) |_|12 29|_| OCS
+ _| |_
+R(1) |_|13 28|_| NC
+ _| |_
+R(0) |_|14 27|_| NC
+ _| |_
+LD |_|15 26|_| NC
+ _| |_
+H4 |_|16 25|_| NC
+ _| |_
+H8 |_|17 24|_| NC
+ _| |_
+OCOL |_|18 23|_| NC
+ _| |_
+ODAT |_|19 22|_| NC
+ _| |_
+GND |_|20 21|_| NC
+ |_____________|
+*/
+
+module k503
+(
+ input [7:0] OB, //Sprite data input
+ input [7:0] VCNT, //Vertical counter input
+ input H4, H8, //Horizontal counter bits 2 (H4) and 3 (H8)
+ input LD, //LD input (pulses low when bits 0 and 1 of the horizontal counter are both 1)
+ output OCS, //Sprite line buffer chip select output
+ output OFLP, //Sprite flip output
+ output ODAT, //Signal to latch upper bits of sprite address
+ output OCOL, //Signal to load addresses for sprite line buffer
+ output [5:0] R //Lower 6 bits of sprite address
+);
+
+//Sum sprite bits with vertical counter
+wire [7:0] sprite_sum = OB + VCNT;
+
+//Sprite select signal
+wire sprite_sel = ~(&sprite_sum[7:4]);
+
+//Sprite flip control
+reg hflip, vflip;
+always_ff @(posedge H4) begin
+ hflip <= OB[6];
+ vflip <= OB[7];
+end
+
+//Latch sprite information
+reg [6:0] sprite;
+always_ff @(negedge H4) begin
+ sprite <= {sprite_sel, hflip, vflip, sprite_sum[3:0]};
+end
+wire sprite_vflip = sprite[4];
+assign OFLP = sprite[5];
+assign OCS = sprite[6];
+
+//Assign OCOL (sprite color) and ODAT (sprite data) outputs
+assign OCOL = ({H8, H4, LD} != 3'b100);
+assign ODAT = ({H8, H4, LD} != 3'b010);
+
+//XOR final output for R
+assign R[5] = (sprite[3] ^ sprite_vflip);
+assign R[4] = (OFLP ^ H8);
+assign R[3] = (OFLP ^ ~H4);
+assign R[2] = (sprite[2] ^ sprite_vflip);
+assign R[1] = (sprite[1] ^ sprite_vflip);
+assign R[0] = (sprite[0] ^ sprite_vflip);
+
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/hiscore.v b/Arcade_MiST/Konami Gyruss/rtl/hiscore.v
new file mode 100644
index 00000000..0fd1ef66
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/hiscore.v
@@ -0,0 +1,602 @@
+//============================================================================
+// MAME hiscore.dat support for MiSTer arcade cores.
+//
+// https://github.com/JimmyStones/Hiscores_MiSTer
+//
+// Copyright (c) 2021 Alan Steremberg
+// Copyright (c) 2021 Jim Gregory
+//
+// This program 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 program 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, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//============================================================================
+/*
+ Version history:
+ 0001 - 2021-03-06 - First marked release
+ 0002 - 2021-03-06 - Added HS_DUMPFORMAT localparam to identify dump version (for future use)
+ Add HS_CONFIGINDEX and HS_DUMPINDEX parameters to configure ioctl_indexes
+ 0003 - 2021-03-10 - Added WRITE_REPEATCOUNT and WRITE_REPEATWAIT to handle tricky write situations
+ 0004 - 2021-03-15 - Fix ram_access assignment
+ 0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes
+ 0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header
+ 0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states
+ 0008 - 2021-05-12 - Feed back core-level pause to halt startup timer
+============================================================================
+*/
+
+module hiscore
+#(
+ parameter HS_ADDRESSWIDTH=10, // Max size of game RAM address for highscores
+ parameter HS_SCOREWIDTH=8, // Max size of capture RAM For highscore data (default 8 = 256 bytes max)
+ parameter HS_CONFIGINDEX=3, // ioctl_index for config transfer
+ parameter HS_DUMPINDEX=4, // ioctl_index for dump transfer
+ parameter CFG_ADDRESSWIDTH=4, // Max size of RAM address for highscore.dat entries (default 4 = 16 entries max)
+ parameter CFG_LENGTHWIDTH=1 // Max size of length for each highscore.dat entries (default 1 = 256 bytes max)
+)
+(
+ input clk,
+ input paused, // Signal from core confirming CPU is paused
+ input reset,
+
+ input ioctl_upload,
+ input ioctl_download,
+ input ioctl_wr,
+ input [24:0] ioctl_addr,
+ input [7:0] ioctl_dout,
+ input [7:0] ioctl_din,
+ input [7:0] ioctl_index,
+
+ output [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data
+ output [7:0] data_to_ram, // Data to write to game RAM
+ output reg ram_write, // Write to game RAM (active high)
+ output ram_access, // RAM read or write required (active high)
+ output reg pause_cpu // Pause core CPU to prepare for/relax after RAM access
+);
+
+// Parameters read from config header
+reg [31:0] START_WAIT =32'd0; // Delay before beginning check process
+reg [15:0] CHECK_WAIT =16'hFF; // Delay between start/end check attempts
+reg [15:0] CHECK_HOLD =16'd2; // Hold time for start/end check reads
+reg [15:0] WRITE_HOLD =16'd2; // Hold time for game RAM writes
+reg [15:0] WRITE_REPEATCOUNT =16'b1; // Number of times to write score to game RAM
+reg [15:0] WRITE_REPEATWAIT =16'b1111; // Delay between subsequent write attempts to game RAM
+reg [7:0] ACCESS_PAUSEPAD =8'd4; // Cycles to wait with paused CPU before and after RAM access
+
+
+// State machine constants
+localparam SM_STATEWIDTH = 4; // Width of state machine net
+
+localparam SM_INIT = 0;
+localparam SM_TIMER = 1;
+
+localparam SM_CHECKPREP = 2;
+localparam SM_CHECKBEGIN = 3;
+localparam SM_CHECKSTARTVAL = 4;
+localparam SM_CHECKENDVAL = 5;
+localparam SM_CHECKCANCEL = 6;
+
+localparam SM_WRITEPREP = 7;
+localparam SM_WRITEBEGIN = 8;
+localparam SM_WRITEREADY = 9;
+localparam SM_WRITEDONE = 10;
+localparam SM_WRITECOMPLETE = 11;
+localparam SM_WRITERETRY = 12;
+
+localparam SM_STOPPED = 13;
+
+/*
+Hiscore config data structure (version 1)
+-----------------------------------------
+[16 byte header]
+[8 byte * no. of entries]
+
+- Header format
+00 00 FF FF 00 FF 00 02 00 02 00 01 11 11 00 00
+[ SW ] [ CW] [ CH] [ WH] [WRC] [WRW] [PAD]
+4 byte START_WAIT
+2 byte CHECK_WAIT
+2 byte CHECK_HOLD
+2 byte WRITE_HOLD
+2 byte WRITE_REPEATCOUNT
+2 byte WRITE_REPEATWAIT
+2 byte (padding/future use)
+
+- Entry format (when CFG_LENGTHWIDTH=1)
+00 00 43 0b 0f 10 01 00
+00 00 40 23 02 04 12 00
+[ ADDR ] LEN START END PAD
+
+4 bytes Address of ram entry (in core memory map)
+1 byte Length of ram entry in bytes
+1 byte Start value to check for at start of address range before proceeding
+1 byte End value to check for at end of address range before proceeding
+1 byte (padding)
+
+- Entry format (when CFG_LENGTHWIDTH=2)
+00 00 43 0b 00 0f 10 01
+00 00 40 23 00 02 04 12
+[ ADDR ] [LEN ] START END
+
+4 bytes Address of ram entry (in core memory map)
+2 bytes Length of ram entry in bytes
+1 byte Start value to check for at start of address range before proceeding
+1 byte End value to check for at end of address range before proceeding
+
+*/
+
+localparam HS_VERSION =8; // Version identifier for module
+localparam HS_DUMPFORMAT =1; // Version identifier for dump format
+localparam HS_HEADERLENGTH =16; // Size of header chunk (default=16 bytes)
+
+// HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data
+
+// Hiscore config and dump status
+wire downloading_config;
+wire parsing_header;
+wire downloading_dump;
+wire uploading_dump;
+reg downloaded_config = 1'b0;
+reg downloaded_dump = 1'b0;
+reg uploaded_dump = 1'b0;
+reg [3:0] initialised;
+reg writing_scores = 1'b0;
+reg checking_scores = 1'b0;
+
+assign downloading_config = ioctl_download && (ioctl_index==HS_CONFIGINDEX);
+assign parsing_header = downloading_config && (ioctl_addr<=HS_HEADERLENGTH);
+assign downloading_dump = ioctl_download && (ioctl_index==HS_DUMPINDEX);
+assign uploading_dump = ioctl_upload && (ioctl_index==HS_DUMPINDEX);
+assign ram_access = uploading_dump | writing_scores | checking_scores;
+assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0];
+
+reg [(SM_STATEWIDTH-1):0] state = SM_INIT; // Current state machine index
+reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT; // Next state machine index to move to after wait timer expires
+reg [31:0] wait_timer; // Wait timer for inital/read/write delays
+
+reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry
+reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries
+reg reset_last = 1'b0; // Last cycle reset
+reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt
+
+reg [7:0] last_ioctl_index; // Last cycle HPS IO index
+reg last_ioctl_download = 0;// Last cycle HPS IO download
+reg last_ioctl_upload = 0; // Last cycle HPS IO upload
+reg [7:0] last_ioctl_dout; // Last cycle HPS IO data out
+reg [7:0] last_ioctl_dout2; // Last cycle +1 HPS IO data out
+reg [7:0] last_ioctl_dout3; // Last cycle +2 HPS IO data out
+
+reg [24:0] ram_addr; // Target RAM address for hiscore read/write
+reg [24:0] old_io_addr;
+reg [24:0] base_io_addr;
+wire [23:0] addr_base;
+wire [(CFG_LENGTHWIDTH*8)-1:0] length;
+wire [24:0] end_addr = (addr_base + length - 1'b1);
+reg [HS_SCOREWIDTH-1:0] local_addr;
+wire [7:0] start_val;
+wire [7:0] end_val;
+
+wire [23:0] address_data_in;
+wire [(CFG_LENGTHWIDTH*8)-1:0] length_data_in;
+
+assign address_data_in = {last_ioctl_dout2, last_ioctl_dout, ioctl_dout};
+assign length_data_in = (CFG_LENGTHWIDTH == 1'b1) ? ioctl_dout : {last_ioctl_dout, ioctl_dout};
+
+wire address_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3);
+wire length_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3 + CFG_LENGTHWIDTH);
+wire startdata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd4 + CFG_LENGTHWIDTH);
+wire enddata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd5 + CFG_LENGTHWIDTH);
+
+// RAM chunks used to store configuration data
+// - address_table
+// - length_table
+// - startdata_table
+// - enddata_table
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(24))
+address_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(address_we & ioctl_wr),
+ .d_a(address_data_in),
+ .addr_b(counter),
+ .q_b(addr_base)
+);
+// Length table - variable width depending on CFG_LENGTHWIDTH
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(CFG_LENGTHWIDTH*8))
+length_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(length_we & ioctl_wr),
+ .d_a(length_data_in),
+ .addr_b(counter),
+ .q_b(length)
+);
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
+startdata_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(startdata_we & ioctl_wr),
+ .d_a(ioctl_dout),
+ .addr_b(counter),
+ .q_b(start_val)
+);
+dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
+enddata_table(
+ .clk(clk),
+ .addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
+ .we_a(enddata_we & ioctl_wr),
+ .d_a(ioctl_dout),
+ .addr_b(counter),
+ .q_b(end_val)
+);
+
+// RAM chunk used to store hiscore data
+dpram_hs #(.aWidth(HS_SCOREWIDTH),.dWidth(8))
+hiscoredata (
+ .clk(clk),
+ .addr_a(ioctl_addr[(HS_SCOREWIDTH-1):0]),
+ .we_a(downloading_dump),
+ .d_a(ioctl_dout),
+ .addr_b(local_addr),
+ .we_b(ioctl_upload),
+ .d_b(ioctl_din),
+ .q_b(data_to_ram)
+);
+
+wire [3:0] header_chunk = ioctl_addr[3:0];
+
+always @(posedge clk)
+begin
+
+ if (downloading_config)
+ begin
+ // Get header chunk data
+ if(parsing_header)
+ begin
+ if(ioctl_wr)
+ begin
+ if(header_chunk == 4'd3) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd5) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd7) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd9) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout };
+ if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= ioctl_dout;
+ end
+ end
+ else
+ begin
+ // Keep track of the largest entry during config download
+ total_entries <= ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2;
+ end
+ end
+
+ // Track completion of configuration and dump download
+ if ((last_ioctl_download != ioctl_download) && (ioctl_download == 1'b0))
+ begin
+ if (last_ioctl_index==HS_CONFIGINDEX) downloaded_config <= 1'b1;
+ if (last_ioctl_index==HS_DUMPINDEX) downloaded_dump <= 1'b1;
+ end
+
+ // Track completion of dump upload
+ if ((last_ioctl_upload != ioctl_upload) && (ioctl_upload == 1'b0))
+ begin
+ if (last_ioctl_index==HS_DUMPINDEX)
+ begin
+ uploaded_dump <= 1'b1;
+ // Mark uploaded dump as readable in case of reset
+ downloaded_dump <= 1'b1;
+ end
+ end
+
+ // Track last ioctl values
+ last_ioctl_download <= ioctl_download;
+ last_ioctl_upload <= ioctl_upload;
+ last_ioctl_index <= ioctl_index;
+ if(ioctl_download && ioctl_wr)
+ begin
+ last_ioctl_dout3 = last_ioctl_dout2;
+ last_ioctl_dout2 = last_ioctl_dout;
+ last_ioctl_dout = ioctl_dout;
+ end
+
+ if(downloaded_config)
+ begin
+ // Check for end of state machine reset to initialise state machine
+ reset_last <= reset;
+ if (reset_last == 1'b1 && reset == 1'b0)
+ begin
+ wait_timer <= START_WAIT;
+ next_state <= SM_INIT;
+ state <= SM_TIMER;
+ counter <= 1'b0;
+ initialised <= initialised + 1'b1;
+ end
+ else
+ begin
+ // Upload scores to HPS
+ if (uploading_dump == 1'b1)
+ begin
+ // generate addresses to read high score from game memory. Base addresses off ioctl_address
+ if (ioctl_addr == 25'b0) begin
+ local_addr <= 0;
+ base_io_addr <= 25'b0;
+ counter <= 1'b0000;
+ end
+ // Move to next entry when last address is reached
+ if (old_io_addr!=ioctl_addr && ram_addr==end_addr[24:0])
+ begin
+ counter <= counter + 1'b1;
+ base_io_addr <= ioctl_addr;
+ end
+ // Set game ram address for reading back to HPS
+ ram_addr <= addr_base + (ioctl_addr - base_io_addr);
+ // Set local addresses to update cached dump in case of reset
+ local_addr <= ioctl_addr[HS_SCOREWIDTH-1:0];
+ end
+
+ if (ioctl_upload == 1'b0 && downloaded_dump == 1'b1 && reset == 1'b0)
+ begin
+ // State machine to write data to game RAM
+ case (state)
+ SM_INIT: // Start state machine
+ begin
+ // Setup base addresses
+ local_addr <= 0;
+ base_io_addr <= 25'b0;
+ // Reset entry counter and states
+ counter <= 0;
+ writing_scores <= 1'b0;
+ checking_scores <= 1'b0;
+ pause_cpu <= 1'b0;
+ state <= SM_CHECKPREP;
+ end
+
+ // Start/end check states
+ // ----------------------
+ SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access
+ begin
+ state <= SM_TIMER;
+ next_state <= SM_CHECKBEGIN;
+ pause_cpu <= 1'b1;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+
+ SM_CHECKBEGIN: // Begin start/end check run - enable RAM access
+ begin
+ checking_scores <= 1'b1;
+ ram_addr <= {1'b0, addr_base};
+ state <= SM_CHECKSTARTVAL;
+ wait_timer <= CHECK_HOLD;
+ end
+
+ SM_CHECKSTARTVAL: // Start check
+ begin
+ // Check for matching start value
+ if(wait_timer != CHECK_HOLD & ioctl_din == start_val)
+ begin
+ // Prepare end check
+ ram_addr <= end_addr;
+ state <= SM_CHECKENDVAL;
+ wait_timer <= CHECK_HOLD;
+ end
+ else
+ begin
+ ram_addr <= {1'b0, addr_base};
+ if (wait_timer > 1'b0)
+ begin
+ wait_timer <= wait_timer - 1'b1;
+ end
+ else
+ begin
+ // - If no match after read wait then stop check run and schedule restart of state machine
+ next_state <= SM_CHECKCANCEL;
+ state <= SM_TIMER;
+ checking_scores <= 1'b0;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+ end
+
+ SM_CHECKENDVAL: // End check
+ begin
+ // Check for matching end value
+ if (wait_timer != CHECK_HOLD & ioctl_din == end_val)
+ begin
+ if (counter == total_entries)
+ begin
+ // If this was the last entry then move on to writing scores to game ram
+ checking_scores <= 1'b0;
+ state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused
+ counter <= 1'b0;
+ write_counter <= 1'b0;
+ ram_write <= 1'b0;
+ ram_addr <= {1'b0, addr_base};
+ end
+ else
+ begin
+ // Increment counter and restart state machine to check next entry
+ counter <= counter + 1'b1;
+ state <= SM_CHECKBEGIN;
+ end
+ end
+ else
+ begin
+ ram_addr <= end_addr;
+ if (wait_timer > 1'b0)
+ begin
+ wait_timer <= wait_timer - 1'b1;
+ end
+ else
+ begin
+ // - If no match after read wait then stop check run and schedule restart of state machine
+ next_state <= SM_CHECKCANCEL;
+ state <= SM_TIMER;
+ checking_scores <= 1'b0;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+ end
+
+ SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused
+ begin
+ pause_cpu <= 1'b0;
+ next_state <= SM_INIT;
+ state <= SM_TIMER;
+ wait_timer <= CHECK_WAIT;
+ end
+
+ // Write to game RAM states
+ // ----------------------
+ SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts)
+ begin
+ state <= SM_TIMER;
+ next_state <= SM_WRITEBEGIN;
+ pause_cpu <= 1'b1;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+
+ SM_WRITEBEGIN: // Writing scores to game RAM begins
+ begin
+ writing_scores <= 1'b1; // Enable muxes if necessary
+ write_counter <= write_counter + 1'b1;
+ state <= SM_WRITEREADY;
+ end
+
+ SM_WRITEREADY: // local ram should be correct, start write to game RAM
+ begin
+ ram_addr <= addr_base + (local_addr - base_io_addr);
+ state <= SM_TIMER;
+ next_state <= SM_WRITEDONE;
+ wait_timer <= WRITE_HOLD;
+ ram_write <= 1'b1;
+ end
+
+ SM_WRITEDONE:
+ begin
+ local_addr <= local_addr + 1'b1; // Increment to next byte of entry
+ if (ram_addr == end_addr)
+ begin
+ // End of entry reached
+ if (counter == total_entries)
+ begin
+ state <= SM_WRITECOMPLETE;
+ end
+ else
+ begin
+ // Move to next entry
+ counter <= counter + 1'b1;
+ write_counter <= 1'b0;
+ base_io_addr <= local_addr + 1'b1;
+ state <= SM_WRITEBEGIN;
+ end
+ end
+ else
+ begin
+ state <= SM_WRITEREADY;
+ end
+ ram_write <= 1'b0;
+ end
+
+ SM_WRITECOMPLETE: // Hiscore write to RAM completed
+ begin
+ ram_write <= 1'b0;
+ writing_scores <= 1'b0;
+ state <= SM_TIMER;
+ if(write_counter < WRITE_REPEATCOUNT)
+ begin
+ // Schedule next write
+ next_state <= SM_WRITERETRY;
+ local_addr <= 0;
+ wait_timer <= WRITE_REPEATWAIT;
+ end
+ else
+ begin
+ next_state <= SM_STOPPED;
+ wait_timer <= ACCESS_PAUSEPAD;
+ end
+ end
+
+ SM_WRITERETRY: // Stop pause and schedule next write
+ begin
+ pause_cpu <= 1'b0;
+ state <= SM_TIMER;
+ next_state <= SM_WRITEPREP;
+ wait_timer <= WRITE_REPEATWAIT;
+ end
+
+ SM_STOPPED:
+ begin
+ pause_cpu <= 1'b0;
+ end
+
+ SM_TIMER: // timer wait state
+ begin
+ // Do not progress timer if CPU is paused by source other than this module
+ // - Stops initial hiscore load delay being foiled by user pausing/entering OSD
+ if (paused == 1'b0 || pause_cpu == 1'b1)
+ begin
+ if (wait_timer > 1'b0)
+ wait_timer <= wait_timer - 1'b1;
+ else
+ state <= next_state;
+ end
+ end
+ endcase
+ end
+ end
+ end
+ old_io_addr<=ioctl_addr;
+end
+
+endmodule
+
+module dpram_hs #(
+ parameter dWidth=8,
+ parameter aWidth=8
+)(
+ input clk,
+
+ input [aWidth-1:0] addr_a,
+ input [dWidth-1:0] d_a,
+ input we_a,
+ output reg [dWidth-1:0] q_a,
+
+ input [aWidth-1:0] addr_b,
+ input [dWidth-1:0] d_b,
+ input we_b,
+ output reg [dWidth-1:0] q_b
+);
+
+reg [dWidth-1:0] ram [2**aWidth-1:0];
+
+always @(posedge clk) begin
+ if (we_a) begin
+ ram[addr_a] <= d_a;
+ q_a <= d_a;
+ end
+ else
+ begin
+ q_a <= ram[addr_a];
+ end
+
+ if (we_b) begin
+ ram[addr_b] <= d_b;
+ q_b <= d_b;
+ end
+ else
+ begin
+ q_b <= ram[addr_b];
+ end
+end
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Gyruss/rtl/jt49_dcrm2.v b/Arcade_MiST/Konami Gyruss/rtl/jt49_dcrm2.v
new file mode 100644
index 00000000..6646a305
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/jt49_dcrm2.v
@@ -0,0 +1,64 @@
+/* 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; // width 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
+ /* verilator lint_off WIDTH */
+ integ <= integ + pre_dout; //mult[sw+dw*2:dw];
+ /* verilator lint_on WIDTH */
+ error <= exact-{q, {dw{1'b0}}};
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Arcade_MiST/Konami Gyruss/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami Gyruss/rtl/jtframe_frac_cen.v
new file mode 100644
index 00000000..8707e766
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/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/Konami Gyruss/rtl/pll.qip b/Arcade_MiST/Konami Gyruss/rtl/pll.qip
new file mode 100644
index 00000000..afd958be
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/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/Konami Gyruss/rtl/pll.v b/Arcade_MiST/Konami Gyruss/rtl/pll.v
new file mode 100644
index 00000000..900c0e3a
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/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 Full Version
+// ************************************************************
+
+
+//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 = 105,
+ altpll_component.clk0_duty_cycle = 50,
+ altpll_component.clk0_multiply_by = 191,
+ altpll_component.clk0_phase_shift = "0",
+ altpll_component.clk1_divide_by = 360,
+ altpll_component.clk1_duty_cycle = 50,
+ altpll_component.clk1_multiply_by = 191,
+ 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 "49.114285"
+// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "14.325000"
+// 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 "49.15200000"
+// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
+// 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 "105"
+// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
+// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "191"
+// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
+// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "360"
+// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
+// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191"
+// 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/Konami Gyruss/rtl/ram_rom/dpram_dc.vhd b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/dpram_dc.vhd
new file mode 100644
index 00000000..69d4c5fb
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/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/Konami Gyruss/rtl/ram_rom/gyruss_ram_rom.qip b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/gyruss_ram_rom.qip
new file mode 100644
index 00000000..5ba746d2
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/gyruss_ram_rom.qip
@@ -0,0 +1,3 @@
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/ram_rom/rom_loader.sv
+set_global_assignment -name VHDL_FILE rtl/ram_rom/spram.vhd
+set_global_assignment -name VHDL_FILE rtl/ram_rom/dpram_dc.vhd
diff --git a/Arcade_MiST/Konami Gyruss/rtl/ram_rom/rom_loader.sv b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/rom_loader.sv
new file mode 100644
index 00000000..a0132d0d
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/rom_loader.sv
@@ -0,0 +1,452 @@
+//============================================================================
+//
+// SD card ROM loader and ROM selector for MISTer.
+// Copyright (C) 2019, 2020 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 Gyruss:
+// 0x0000 - 0x1FFF = eprom_1
+// 0x2000 - 0x3FFF = eprom_2
+// 0x4000 - 0x5FFF = eprom_3
+// 0x6000 - 0x7FFF = eprom_4
+// 0x8000 - 0x9FFF = eprom_5
+// 0xA000 - 0xBFFF = eprom_6
+// 0xC000 - 0xDFFF = eprom_7
+// 0xE000 - 0xFFFF = eprom_8
+// 0x10000 - 0x11FFF = eprom_9
+// 0x12000 - 0x13FFF = eprom_10
+// 0x14000 - 0x15FFF = eprom_11
+// 0x16000 - 0x16FFF = eprom_12
+// 0x17000 - 0x170FF = tile_lut_prom
+// 0x17100 - 0x171FF = sprite_lut_prom
+// 0x17200 - 0x1721F = color_prom
+
+module selector
+(
+ input logic [24:0] ioctl_addr,
+ output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs,
+ ep9_cs, ep10_cs, ep11_cs, ep12_cs, cp_cs, tl_cs, sl_cs
+);
+
+ always_comb begin
+ {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs, ep9_cs,
+ ep10_cs, ep11_cs, ep12_cs, cp_cs, tl_cs, sl_cs} = 0;
+ if(ioctl_addr < 'h2000)
+ ep1_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h4000)
+ ep2_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h6000)
+ ep3_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h8000)
+ ep4_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'hA000)
+ ep5_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'hC000)
+ ep6_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'hE000)
+ ep7_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h10000)
+ ep8_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h12000)
+ ep9_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h14000)
+ ep10_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h16000)
+ ep11_cs = 1; // 0x2000 13
+ else if(ioctl_addr < 'h17000)
+ ep12_cs = 1; // 0x1000 12
+ else if(ioctl_addr < 'h17100)
+ tl_cs = 1; // 0x100 8
+ else if(ioctl_addr < 'h17200)
+ sl_cs = 1; // 0x100 8
+ else
+ cp_cs = 1; // 0x20 5
+ end
+endmodule
+
+////////////
+// EPROMS //
+////////////
+
+module eprom_1
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_1
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_2
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_2
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_3
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_3
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_4
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_4
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_5
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_5
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_6
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_6
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_7
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_7
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_8
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_8
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_9
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_9
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_10
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_10
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_11
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [12: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(13)) eprom_11
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[12:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[12:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module eprom_12
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [11: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(12)) eprom_12
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[11:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[11:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+///////////
+// PROMS //
+///////////
+
+module color_prom
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [4: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(5)) color_prom_1
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[4:0]),
+ .q_a(DATA[7:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[4:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module tile_lut_prom
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [7:0] ADDR,
+ input logic [24:0] ADDR_DL,
+ input logic [3:0] DATA_IN,
+ input logic CS_DL,
+ input logic WR,
+ output logic [3:0] DATA
+);
+ dpram_dc #(.widthad_a(8)) tile_lut_prom
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[7:0]),
+ .q_a(DATA[3:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[7:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
+
+module sprite_lut_prom
+(
+ input logic CLK,
+ input logic CLK_DL,
+ input logic [7:0] ADDR,
+ input logic [24:0] ADDR_DL,
+ input logic [3:0] DATA_IN,
+ input logic CS_DL,
+ input logic WR,
+ output logic [3:0] DATA
+);
+ dpram_dc #(.widthad_a(8)) sprite_lut_prom
+ (
+ .clock_a(CLK),
+ .address_a(ADDR[7:0]),
+ .q_a(DATA[3:0]),
+
+ .clock_b(CLK_DL),
+ .address_b(ADDR_DL[7:0]),
+ .data_b(DATA_IN),
+ .wren_b(WR & CS_DL)
+ );
+endmodule
diff --git a/Arcade_MiST/Konami Gyruss/rtl/ram_rom/spram.vhd b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/spram.vhd
new file mode 100644
index 00000000..38302277
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/ram_rom/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;
diff --git a/Arcade_MiST/Konami Gyruss/rtl/sdram.sv b/Arcade_MiST/Konami Gyruss/rtl/sdram.sv
new file mode 100644
index 00000000..7fa4a0a2
--- /dev/null
+++ b/Arcade_MiST/Konami Gyruss/rtl/sdram.sv
@@ -0,0 +1,357 @@
+//
+// 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 [16:1] cpu3_addr,
+ output reg [15:0] cpu3_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
+ 2 words 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[3];
+reg [24:1] addr_latch_next[2];
+reg [16:1] addr_last[4];
+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 = 3'd0;
+localparam PORT_CPU1 = 3'd1;
+localparam PORT_CPU2 = 3'd2;
+localparam PORT_CPU3 = 3'd3;
+localparam PORT_SP = 3'd1;
+localparam PORT_REQ = 3'd4;
+
+reg [2:0] next_port[2];
+reg [2: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 if (cpu3_addr != addr_last[PORT_CPU3]) begin
+ next_port[0] = PORT_CPU3;
+ addr_latch_next[0] = { 8'd0, cpu3_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
+ PORT_CPU3: begin cpu3_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