diff --git a/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.qpf b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.qpf new file mode 100644 index 00000000..7e76628f --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.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 = "BankPanic" + diff --git a/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.qsf b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.qsf new file mode 100644 index 00000000..c1b58567 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.qsf @@ -0,0 +1,241 @@ +# -------------------------------------------------------------------------- # +# +# 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 = 15:08:12 December 26, 2022 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# BankPanic_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP +set_global_assignment -name TOP_LEVEL_ENTITY BankPanic_MiST + +# 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/bankp.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(BankPanic) + + # Pin & Location Assignments + # ========================== +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[*] + + # Fitter Assignments + # ================== +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 + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== +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 + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(BankPanic) +# ------------------ +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=1" +set_global_assignment -name SYSTEMVERILOG_FILE rtl/BankPanic_MiST.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/x74139.v +set_global_assignment -name VERILOG_FILE rtl/x74138.v +set_global_assignment -name VHDL_FILE rtl/sn76489_audio.vhd +set_global_assignment -name VERILOG_FILE rtl/pll_mist.v +set_global_assignment -name QIP_FILE rtl/pll_mist.qip +set_global_assignment -name VERILOG_FILE rtl/dpram.v +set_global_assignment -name VERILOG_FILE rtl/core.v +set_global_assignment -name VERILOG_FILE rtl/clk_en.v +set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name SIGNALTAP_FILE output_files/bankp.stp +set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.sdc b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.sdc new file mode 100644 index 00000000..59bf935d --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/BankPanic.sdc @@ -0,0 +1,135 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set aud_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Sega Bank Panic Hardware/Readme.md b/Arcade_MiST/Sega Bank Panic Hardware/Readme.md new file mode 100644 index 00000000..cc52344a --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/Readme.md @@ -0,0 +1,10 @@ +# BankPanic for MiSTerFPGA + +## General description +This is the port of Bank Panic for MiSTerFPGA by Pierco (Pierre Cornier). I tried to reproduce the PCB as much as possible so it should be very close to the original hardware. + +I would like to give special thanks to Mark Haysman from RetroClinic for sharing the equations of the PAL 315-5075, and to David Shadoff, Alan Steremberg & Chockichoc for their support and friendship! + +MiST port, SDRAM controller and convert to fully synchronous logic by Gyorgy Szombathelyi. + +Original core: https://github.com/MiSTer-devel/Arcade-BankPanic_MiSTer \ No newline at end of file diff --git a/Arcade_MiST/Sega Bank Panic Hardware/meta/BankPanic.mra b/Arcade_MiST/Sega Bank Panic Hardware/meta/BankPanic.mra new file mode 100644 index 00000000..6799bb8c --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/meta/BankPanic.mra @@ -0,0 +1,89 @@ + + BankPanic + + no + no + + + + + 1984 + Sanritsu/Sega + Shooter/1stPerson + + bankp + 0247 + bankpanic + + + 15kHz + horizontal + + + 2 + 2-way + + 3 + + + + + + + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 202108231828 + diff --git a/Arcade_MiST/Sega Bank Panic Hardware/meta/Combat Hawk.mra b/Arcade_MiST/Sega Bank Panic Hardware/meta/Combat Hawk.mra new file mode 100644 index 00000000..c6ca2d2a --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/meta/Combat Hawk.mra @@ -0,0 +1,57 @@ + + Combat Hawk + no + no + 1987 + Sanritsu/Sega + Shooter/1stPerson + combh + 0247 + bankpanic + 15kHz + horizontal + 2 + 2-way + 3 + + + + + + + + + + + + 01 + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/BankPanic_MiST.sv b/Arcade_MiST/Sega Bank Panic Hardware/rtl/BankPanic_MiST.sv new file mode 100644 index 00000000..0fa2fce5 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/BankPanic_MiST.sv @@ -0,0 +1,284 @@ + +module BankPanic_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 = { + "BANKP;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.0.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire [7:0] dsw = status[15:8]; +wire [1:0] orientation = {core_mod[0] & dsw[0], core_mod[0]}; + +assign LED = ~ioctl_downl; +assign AUDIO_R = AUDIO_L; + +wire clk_sys, clk_mem, pll_locked; +pll_mist pll( + .inclk0(CLOCK_27), + .c0(clk_mem),//93 + .c1(clk_sys),//31 + .locked(pll_locked) + ); +assign SDRAM_CLK = clk_mem; +assign SDRAM_CKE = 1; + +wire [63: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 ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; + +user_io #( + .STRLEN(($size(CONF_STR)>>3))) +user_io( + .clk_sys (clk_sys ), + .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 ) + ); + +data_io data_io( + .clk_sys ( clk_sys ), + .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 ) +); + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clk_sys) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +wire [15:0] cpu_rom_addr; +wire cpu_rom_cs; +wire [15:0] cpu_rom_data; +wire [13:0] bg_rom_addr; +wire [15:0] bg_rom_data; +wire [13:0] sp_rom_addr; +wire [31:0] sp_rom_data; +reg port1_req, port2_req; + +// ROM download controller +always @(posedge clk_sys) 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 + +sdram #(93) sdram +( + .*, + .init_n ( pll_locked ), + .clk ( clk_mem ), + + // Bank 0-1 ops + .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 ( ), + + // Main CPU + .cpu1_addr ( cpu_rom_addr[15:1] ), + .cpu1_cs ( cpu_rom_cs ), + .cpu1_q ( cpu_rom_data ), + + .cpu2_addr ( bg_rom_addr[13:1] + 19'h8000 ), + .cpu2_q ( bg_rom_data ), + + // Bank 2-3 ops + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( ioctl_addr[23:1] ), + .port2_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .sp_addr ( sp_rom_addr + 17'h5000 ), + .sp_q ( sp_rom_data ) +); + +wire [15:0] audio; +wire hs, vs, cs; +wire hb, vb; +wire blankn = ~(hb | vb); +wire [2:0] g, r; +wire [1:0] b; + +wire [7:0] p1 = { m_fireB, m_fireD, m_coin1, m_fireA, core_mod[0] ? {1'b0, m_down, 1'b0, m_up} : {m_left, 1'b0, m_right, 1'b0} }; +wire [7:0] p2 = { m_fire2B, m_two_players, m_one_player, m_fire2A, core_mod[0] ? {1'b0, m_down2, 1'b0, m_up2} : {m_left2, 1'b0, m_right2, 1'b0} }; +wire [7:0] p3 = { 4'd0, m_fireE, m_coin2, m_fire2C, m_fireC }; + +core u_core( + .reset ( reset ), + .clk_sys ( clk_sys ), + .p1 ( p1 ), + .p2 ( p2 ), + .p3 ( p3 ), + .dsw ( dsw ), + .ioctl_index ( ioctl_index ), + .ioctl_download ( ioctl_downl ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ), + .ioctl_wr ( ioctl_wr ), + .red ( r ), + .green ( g ), + .blue ( b ), + .vs ( vs ), + .vb ( vb ), + .hs ( hs ), + .hb ( hb ), + .ce_pix ( ), + .sound ( audio ), + .hoffs ( 0 ), + .cpu_rom_addr ( cpu_rom_addr ), + .cpu_rom_cs ( cpu_rom_cs ), + .cpu_rom_data ( cpu_rom_addr[0] ? cpu_rom_data[15:8] : cpu_rom_data[7:0] ), + .bg_rom_addr ( bg_rom_addr ), + .bg_rom_data ( bg_rom_addr[0] ? bg_rom_data[15:8] : bg_rom_data[7:0] ), + .sp_rom_addr ( sp_rom_addr ), + .sp_rom_data ( sp_rom_data ) +); + +mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clk_sys ), + .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 ) + ); + +dac #( + .C_bits(16)) +dac_l( + .clk_i(clk_sys), + .res_n_i(1), + .dac_i(audio), + .dac_o(AUDIO_L) + ); + + +// General controls +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 ( clk_sys ), + .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/Sega Bank Panic Hardware/rtl/build_id.tcl b/Arcade_MiST/Sega Bank Panic Hardware/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/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/Sega Bank Panic Hardware/rtl/clk_en.v b/Arcade_MiST/Sega Bank Panic Hardware/rtl/clk_en.v new file mode 100644 index 00000000..f0192c91 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/clk_en.v @@ -0,0 +1,23 @@ + +module clk_en #( + parameter DIV=12, + parameter OFFSET=0 +) +( + input ref_clk, + output reg cen +); + +reg [15:0] cnt = OFFSET; +always @(posedge ref_clk) begin + if (cnt == DIV) begin + cnt <= 16'd0; + cen <= 1'b1; + end + else begin + cen <= 1'b0; + cnt <= cnt + 16'd1; + end +end + +endmodule diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/core.v b/Arcade_MiST/Sega Bank Panic Hardware/rtl/core.v new file mode 100644 index 00000000..ce2bc010 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/core.v @@ -0,0 +1,752 @@ + +module core( + input reset, + input clk_sys, + + input [7:0] p1, + input [7:0] p2, + input [7:0] p3, + input [7:0] dsw, + + input [7:0] ioctl_index, + input ioctl_download, + input [26:0] ioctl_addr, + input [15:0] ioctl_dout, + input ioctl_wr, + + output [2:0] red, + output [2:0] green, + output [1:0] blue, + output reg vb, + output hb, + output vs, + output reg hs, + output ce_pix, + input [4:0] hoffs, + + output [15:0] sound, + + output [15:0] cpu_rom_addr, + output cpu_rom_cs, + input [7:0] cpu_rom_data, + output [13:0] bg_rom_addr, + input [7:0] bg_rom_data, + output [13:0] sp_rom_addr, + input [23:0] sp_rom_data + +); + +/******** LOAD ROMs ********/ + +wire [7:0] col_data = ioctl_dout; +wire [7:0] fg_color_addr = ioctl_download ? ioctl_addr - 27'h24020 : rc_addr; +wire fg_color_wren = ioctl_download && ioctl_addr >= 27'h24020 && ioctl_addr < 27'h24120 ? ioctl_wr : 1'b0; +wire [7:0] bg_color_addr = ioctl_download ? ioctl_addr - 27'h24120 : sc_addr; +wire bg_color_wren = ioctl_download && ioctl_addr >= 27'h24120 && ioctl_addr < 27'h24220 ? ioctl_wr : 1'b0; +wire [4:0] pal_addr = ioctl_download ? ioctl_addr - 27'h24000 : { back, col }; +wire pal_wren = ioctl_download && ioctl_addr >= 27'h24000 && ioctl_addr < 27'h24020 ? ioctl_wr : 1'b0; + +/******** RGB ********/ + +reg [7:0] color; +always @(posedge clk_sys) + if (clk_en_514) color <= u8H[2] ? pal_data : 8'd0; + +assign ce_pix = clk_en_514; +assign { blue, green, red } = color; + +/******** CLOCKS ********/ + +// 31/12 =2.5833 +// 31/6 =5.1666 + +wire clk_en_257, clk_en_514; +clk_en #(11) mcpu_clk_en(clk_sys, clk_en_257); +clk_en #(5) pxl_clk_en(clk_sys, clk_en_514); + + +/******** PAL 315-5074 ********/ + +wire rld_n = ~(&sh[1:0] & hcount[8]) /* synthesis keep */; +wire rch_set_n = ~(sh[0] & ~sh[1] & sh[2] & hcount[8]) /* synthesis keep */; +wire rcol_set_n = ~(sh[0] & sh[1] & ~sh[2] & hcount[8]) /* synthesis keep */; +wire rad_sel_n = hcount[8] & ~vb /* synthesis keep */; +wire sld_n = ~(&hcount[2:0] & hcount[8]) /* synthesis keep */; +wire sch_set_n = ~(hcount[0] & ~hcount[1] & ~hcount[2] & hcount[8]) /* synthesis keep */; +wire scol_set_n = ~(hcount[0] & hcount[1] & ~hcount[2] & hcount[8]) /* synthesis keep */; +wire sad_sel_n = ~hcount[2] & ~vb /* synthesis keep */; + +/******** PAL 315-5075 ********/ + +reg cpusel_n; +reg o13; // cpu wait +reg rf16, rf15, rf14, rf13; + +wire pre = ~hcount[8]; +reg oldh2; +always @(posedge clk_sys) begin + oldh2 <= hcount[2]; + if (~pre) cpusel_n <= 1'b1; + if (pre & ~oldh2 & hcount[2]) begin + cpusel_n <= hcount[5] & hs; + end +end + +wire srwr_n = ~((vb & ~sram_cs_n & ~mcpu_wr_n) + | (~sram_cs_n & ~mcpu_wr_n & rf16)); +wire rrwr_n = ~((vb & ~rram_cs_n & ~mcpu_wr_n) + | (~rram_cs_n & sram_cs_n & ~mcpu_wr_n & ~hcount[8] & ~cpusel_n) + | (~rram_cs_n & ~mcpu_wr_n & ~hcount[8] & ~cpusel_n & rf15)); + + +//always @(posedge clk_en_514) begin +always @(posedge clk_sys) begin + if (clk_en_514) begin + o13 <= ~((~vb & ~sram_cs_n & ~rf15) + | (~vb & ~rram_cs_n & cpusel_n)); + rf14 <= ~vb & ~sram_cs_n & ~rf15; + rf15 <= (rf15 & ~sram_cs_n) + | (hcount[0] & hcount[1] & ~hcount[2] & rf14); + rf16 <= (rf16 & ~sram_cs_n) + | (~sram_cs_n & rf15); + end +end + + +/******** VIDEO ********/ + +reg [8:0] hcount /* synthesis keep */; +reg [8:0] vcount /* synthesis keep */; +wire u1D_co; +wire u1E_co; +wire u1G_co; +wire u1H_co; + +always @(posedge clk_sys) begin + if (clk_en_514) begin + hcount <= hcount + 1'd1; + if (hcount == 9'h1ff) hcount <= 9'h0c0; + end +end +assign hb = hcount[8:0] > 192 && hcount[8:0] <= 256 + 32; + +assign vs = vcount[8]; + +always @(posedge clk_sys) begin + if (clk_en_514) begin + if (hcount == 9'h0c4) begin + vcount <= vcount + 1'd1; + if (vcount == 9'h1ff) vcount <= 9'h0f8; + if (vcount == 9'h10f) vb <= 0; + if (vcount == 9'h1ef) vb <= 1; + end + end +end + +// 1C +wire [8:0] hc2 = hcount - hoffs; +always @(posedge clk_sys) begin + if (hc2[8]) hs <= 1'b0; + else if (clk_en_514) begin + if (hc2[2:0] == 3'b011) hs <= |hc2[5:4]; // hc2[2] rising edge + end +end + + +/******** MCPU ********/ + +wire wait_n = o13 & rdy_n; + +wire [7:0] mcpu_din; +wire [15:0] mcpu_addr; +wire [7:0] mcpu_dout; +wire mcpu_rd_n; +wire mcpu_wr_n; +wire mcpu_m1_n; +wire mcpu_mreq_n; +wire mcpu_iorq_n; +wire mcpu_rfsh_n; +reg mcpu_nmi_n; +wire mcpu_wait_n = wait_n; + +// u8H is used by the CPU to reset NMI state + +reg oldvb; +always @(posedge clk_sys) begin + oldvb <= vb; + if (~oldvb & vb & u8H[4]) begin + mcpu_nmi_n <= 1'b0; + end + if (~u8H[4]) mcpu_nmi_n <= 1'b1; +end + +t80s mcpu( + .reset_n ( ~reset ), + .clk ( clk_sys ), + .cen ( clk_en_257 ), + .wait_n ( mcpu_wait_n ), + .int_n ( 1'b1 ), + .nmi_n ( mcpu_nmi_n ), + .busrq_n ( 1'b1 ), + .m1_n ( mcpu_m1_n ), + .mreq_n ( mcpu_mreq_n ), + .iorq_n ( mcpu_iorq_n ), + .rd_n ( mcpu_rd_n ), + .wr_n ( mcpu_wr_n ), + .rfsh_n ( mcpu_rfsh_n ), + .halt_n ( ), + .busak_n ( ), + .A ( mcpu_addr ), + .DI ( mcpu_din ), + .DO ( mcpu_dout ) +); + +/******** MCPU MEMORY CS ********/ + +wire [3:0] u7A_Y1; +wire [3:0] u7A_Y2; +wire [3:0] u7B_Y1; +wire [3:0] u7B_Y2; + +x74139 u7A( + .E1 ( u7B_Y2[3] ), + .A1 ( { mcpu_addr[13], 1'b0 } ), + .O1 ( u7A_Y1 ), + .E2 ( u7A_Y1[2] ), + .A2 ( mcpu_addr[12:11] ), + .O2 ( u7A_Y2 ) +); + +x74139 u7B( + .E1 ( mcpu_mreq_n ), + .A1 ( { mcpu_rfsh_n, 1'b0 } ), + .O1 ( u7B_Y1 ), + .E2 ( u7B_Y1[2] ), + .A2 ( mcpu_addr[15:14] ), + .O2 ( u7B_Y2 ) +); + +wire mcpu_rom_cs_n_0 = u7B_Y2[0]; // $0000-$3fff +wire mcpu_rom_cs_n_1 = u7B_Y2[1]; // $4000-$7fff +wire mcpu_rom_cs_n_2 = u7B_Y2[2]; // $8000-$bfff +wire mcpu_rom_cs_n_3 = u7A_Y1[0]; // $c000-$ffff + +wire wram_cs_n = u7A_Y2[0]; // wram $e000-$e7ff +wire rram_cs_n = u7A_Y2[2]; // rram $f000-$f7ff +wire sram_cs_n = u7A_Y2[3]; // sram $f800-$ffff + +/******** MCPU MEMORIES ********/ + +wire [7:0] mcpu_rom0_q; +wire [7:0] mcpu_rom1_q; +wire [7:0] mcpu_rom2_q; +wire [7:0] mcpu_rom3_q; +wire [7:0] mcpu_wram_q; +wire [7:0] sram_q; +wire [7:0] rram_q; + +// 3E 3F 3H 3I 3J muxes for RRAM/SRAM address, (r|s)ad_sel_n is active (low) on blank +wire [10:0] avr = ~rad_sel_n ? mcpu_addr[10:0] : { sh[1], xv[7:3], xsh[7:3] }; +wire [10:0] avs = ~sad_sel_n ? mcpu_addr[10:0] : { hcount[1], xv[7:3], xh[7:3] }; + +`ifdef EXT_ROM +assign cpu_rom_addr = mcpu_addr[15:0]; +assign mcpu_rom0_q = cpu_rom_data; +assign mcpu_rom1_q = cpu_rom_data; +assign mcpu_rom2_q = cpu_rom_data; +assign mcpu_rom3_q = cpu_rom_data; +assign cpu_rom_cs = ~(mcpu_rom_cs_n_0 & mcpu_rom_cs_n_1 & mcpu_rom_cs_n_2 & mcpu_rom_cs_n_3); + +`else +wire [7:0] mcpu_rom_data = ioctl_dout[7:0]; +wire [13:0] mcpu_rom0_addr = ioctl_download ? ioctl_addr : mcpu_addr[13:0]; +wire mcpu_rom0_wren_a = ioctl_download && ioctl_addr < 27'h4000 ? ioctl_wr : 1'b0; +wire [13:0] mcpu_rom1_addr = ioctl_download ? ioctl_addr : mcpu_addr[13:0]; +wire mcpu_rom1_wren_a = ioctl_download && ioctl_addr < 27'h8000 ? ioctl_wr : 1'b0; +wire [13:0] mcpu_rom2_addr = ioctl_download ? ioctl_addr : mcpu_addr[13:0]; +wire mcpu_rom2_wren_a = ioctl_download && ioctl_addr < 27'hc000 ? ioctl_wr : 1'b0; +wire [13:0] mcpu_rom3_addr = ioctl_download ? ioctl_addr : mcpu_addr[13:0]; +wire mcpu_rom3_wren_a = ioctl_download && ioctl_addr < 27'hf000 ? ioctl_wr : 1'b0; + +dpram #(14,8) mcpu_rom0( + .clock ( clk_sys ), + .address_a ( mcpu_rom0_addr ), + .data_a ( mcpu_rom_data ), + .q_a ( mcpu_rom0_q ), + .rden_a ( 1'b1 ), + .wren_a ( mcpu_rom0_wren_a ) +); + +dpram #(14,8) mcpu_rom1( + .clock ( clk_sys ), + .address_a ( mcpu_rom1_addr ), + .data_a ( mcpu_rom_data ), + .q_a ( mcpu_rom1_q ), + .rden_a ( 1'b1 ), + .wren_a ( mcpu_rom1_wren_a ) +); + +dpram #(14,8) mcpu_rom2( + .clock ( clk_sys ), + .address_a ( mcpu_rom2_addr ), + .data_a ( mcpu_rom_data ), + .q_a ( mcpu_rom2_q ), + .rden_a ( 1'b1 ), + .wren_a ( mcpu_rom2_wren_a ) +); + +dpram #(14,8) mcpu_rom3( + .clock ( clk_sys ), + .address_a ( mcpu_rom3_addr ), + .data_a ( mcpu_rom_data ), + .q_a ( mcpu_rom3_q ), + .rden_a ( 1'b1 ), + .wren_a ( mcpu_rom3_wren_a ) +); +`endif + +dpram #(11,8) mcpu_wram( + .clock ( clk_sys ), + .address_a ( mcpu_addr[10:0] ), + .data_a ( mcpu_dout ), + .q_a ( mcpu_wram_q ), + .rden_a ( 1'b1 ), + .wren_a ( ~wram_cs_n & ~mcpu_wr_n ) +); + +// vram bg + +dpram #(11,8) sram( + .clock ( clk_sys ), + .address_a ( avs ), + .data_a ( mcpu_dout ), + .q_a ( sram_q ), + .rden_a ( 1'b1 ), + .wren_a ( ~srwr_n ) +); + +// vram fg + +dpram #(11,8) rram( + .clock ( clk_sys ), + .address_a ( avr ), + .data_a ( mcpu_dout ), + .q_a ( rram_q ), + .rden_a ( 1'b1 ), + .wren_a ( ~rrwr_n ) +); + +/******** MCPU I/O & DATA BUS ********/ + +wire [7:0] u6E_Y, u6D_Y; + +wire IN1 = ~u6D_Y[0]; +wire IN2 = ~u6D_Y[1]; +wire IN3 = ~u6D_Y[2]; +wire DSW = ~u6D_Y[4]; +wire SN1 = u6E_Y[0]; +wire SN2 = u6E_Y[1]; +wire SN3 = u6E_Y[2]; +wire SCR = ~u6E_Y[5]; +wire IOW = ~u6E_Y[7]; + +x74138 u6E( + .G1 ( 1'b1 ), + .G2A ( mcpu_iorq_n ), + .G2B ( mcpu_wr_n ), + .A ( mcpu_addr[2:0] ), + .Y ( u6E_Y ) +); + +x74138 u6D( + .G1 ( 1'b1 ), + .G2A ( mcpu_iorq_n ), + .G2B ( mcpu_rd_n ), + .A ( mcpu_addr[2:0] ), + .Y ( u6D_Y ) +); + +reg [7:0] u2J; +reg [7:0] u8H; + +always @(posedge clk_sys) begin + if (~mcpu_wr_n) begin + if (SCR) u2J <= mcpu_dout; + if (IOW) u8H <= mcpu_dout; + end +end + +assign mcpu_din = + ~wram_cs_n ? mcpu_wram_q : + ~sram_cs_n ? sram_q : + ~rram_cs_n ? rram_q : + ~mcpu_rom_cs_n_0 ? mcpu_rom0_q : + ~mcpu_rom_cs_n_1 ? mcpu_rom1_q : + ~mcpu_rom_cs_n_2 ? mcpu_rom2_q : + ~mcpu_rom_cs_n_3 ? mcpu_rom3_q : + IN1 ? p1 : + IN2 ? p2 : + IN3 ? p3 : + DSW ? dsw : + 8'h0; + + +/******** SCROLL COUNT ********/ + +reg [7:0] sh; +always @(posedge clk_sys) begin : U2HU2I + if (clk_en_514) begin + if (!hcount[8]) sh <= u2J; + else sh <= sh + 1'd1; + end +end + +// flip +wire bflip = u8H[5]; +wire [7:0] xv = vcount[7:0] ^ {8{bflip}}; +wire [7:3] xh = hcount[7:3] ^ {5{bflip}}; +wire [7:2] xsh = sh[7:2] ^ {{5{bflip}}, rhinv}; + +/******** COL/CH registers ********/ + +// COLors & CHaracters +// It captures VRAM data to build tile & color addresses +// timing signals are generated by the PAL 315-5074 + +reg [7:0] r3l; +reg [7:0] r2l; +reg [7:0] r4l; +reg [7:0] r3b; +reg [7:0] r3c; + +always @(posedge clk_sys) begin + + if (clk_en_514) begin + if (!rcol_set_n) r3l <= rram_q; // rcol_set_n rising edge + if (!rch_set_n) begin // rch_set_n rising edge + r2l <= rram_q; + r4l <= r3l; + end + end + if (oldvb & ~vb) begin + r2l <= 8'd0; + r4l <= 8'd0; + end +end + +always @(posedge clk_sys) begin + + if (clk_en_514) begin + if (!scol_set_n) r3b <= sram_q; + if (!sch_set_n) r3c <= sram_q; + end + if (oldvb & ~vb) begin + r3b <= 8'd0; + r3c <= 8'd0; + end +end + +/******** BG/FG shift registers ********/ + +// shift & select high or low bits of ROM data +// translated to verilog to avoid a lot of 74LS194 instances + +reg [3:0] r4a; +reg [4:0] r4k; +reg sinv; +reg rinv; + +// tile flip code +wire shinv = r3b[3] ^ bflip; +wire rhinv = r4l[2] ^ bflip; + +// 4K & 4A for stable address/inv signals +always @(posedge clk_sys) begin + + if (clk_en_514) begin + if (!sld_n) begin + r4a <= r3b[7:4]; + sinv <= shinv; + end + if (!rld_n) begin + r4k <= r4l[7:3]; + rinv <= rhinv; + end + end + +end + +// bit select +wire ss0 = sinv ? 1'b1 : ~sld_n; +wire ss1 = sinv ? ~sld_n : 1'b1; +wire rs0 = rinv ? 1'b1 : ~rld_n; +wire rs1 = rinv ? ~rld_n : 1'b1; + +// extract bits from ROM data +wire [2:0] sex = sinv ? { sra[7], srb[7], src[7] } : { sra[0], srb[0], src[0] }; +wire [1:0] rex = rinv ? { rra[3], rrb[3] } : { rra[0], rrb[0] }; + + +// shift registers +reg [7:0] sra, srb, src; +reg [3:0] rra, rrb; +always @(posedge clk_sys) begin + if (clk_en_514) begin + + if (ss0 & ss1) begin + sra <= srom_dout_a; + srb <= srom_dout_b; + src <= srom_dout_c; + end + else if (~ss0 & ss1) begin + sra <= { 1'b0, sra[7:1] }; + srb <= { 1'b0, srb[7:1] }; + src <= { 1'b0, src[7:1] }; + end + else if (ss0 & ~ss1) begin + sra <= { sra[6:0], 1'b0 }; + srb <= { srb[6:0], 1'b0 }; + src <= { src[6:0], 1'b0 }; + end + + if (rs0 & rs1) begin + rra <= rrom_dout[7:4]; + rrb <= rrom_dout[3:0]; + end + else if (~rs0 & rs1) begin + rra <= { 1'b0, rra[3:1] }; + rrb <= { 1'b0, rrb[3:1] }; + end + else if (rs0 & ~rs1) begin + rra <= { rra[2:0], 1'b0 }; + rrb <= { rrb[2:0], 1'b0 }; + end + + end +end + +/******** BG/FG color palette ********/ + +wire [7:0] rc_addr = { 1'b0, r4k, rex }; +wire [7:0] sc_addr = { 1'b0, r4a, sex }; + +wire [3:0] scol; +wire [3:0] rcol; +wire [7:0] pal_data; + +// priority & transparency +wire rex_n = ~|rcol; +wire sex_n = ~|scol; +wire sel_n = (rex_n | ~sex_n | u8H[0]) & (rex_n | u8H[1]); +wire [3:0] col = sel_n ? scol : rcol; + +dpram #(8,4) fg_color_lut( + .clock ( clk_sys ), + .address_a ( fg_color_addr ), + .data_a ( col_data[3:0] ), + .q_a ( rcol ), + .rden_a ( 1'b1 ), + .wren_a ( fg_color_wren ) +); + +dpram #(8,4) bg_color_lut( + .clock ( clk_sys ), + .address_a ( bg_color_addr ), + .data_a ( col_data[3:0] ), + .q_a ( scol ), + .rden_a ( 1'b1 ), + .wren_a ( bg_color_wren ) +); + +// back is a palette switch +// the only difference between the two palettes is color 7 (2F/40) +wire back = u8H[3]; +dpram #(5,8) palette( + .clock ( clk_sys ), + .address_a ( pal_addr ), + .data_a ( col_data ), + .q_a ( pal_data ), + .rden_a ( 1'b1 ), + .wren_a ( pal_wren ) +); + +/******** GFX ROMs ********/ + +wire [13:0] rca = { r4l[1:0], r2l, xsh[2], xv[2:0] }; +wire [13:0] sca = { r3b[2:0], r3c, xv[2:0] }; + +wire [7:0] gfx_rom1_q; +wire [7:0] gfx_rom2_q; +wire [7:0] gfx_rom3_q; +wire [7:0] gfx_rom4_q; +wire [7:0] gfx_rom5_q; +wire [7:0] gfx_rom6_q; +wire [7:0] gfx_rom7_q; +wire [7:0] gfx_rom8_q; + +wire [7:0] rrom_dout = ~rca[13] ? gfx_rom1_q : gfx_rom2_q; +wire [7:0] srom_dout_a = ~sca[13] ? gfx_rom3_q : gfx_rom4_q; +wire [7:0] srom_dout_b = ~sca[13] ? gfx_rom5_q : gfx_rom6_q; +wire [7:0] srom_dout_c = ~sca[13] ? gfx_rom7_q : gfx_rom8_q; + +`ifdef EXT_ROM +reg [13:0] rca_reg, sca_reg; // register for stability +always @(posedge clk_sys) begin + rca_reg <= rca; + sca_reg <= sca; +end +assign bg_rom_addr = rca_reg; +assign sp_rom_addr = sca_reg; +assign gfx_rom1_q = bg_rom_data; +assign gfx_rom2_q = bg_rom_data; + +assign gfx_rom3_q = sp_rom_data[ 7: 0]; +assign gfx_rom4_q = sp_rom_data[ 7: 0]; +assign gfx_rom5_q = sp_rom_data[15: 8]; +assign gfx_rom6_q = sp_rom_data[15: 8]; +assign gfx_rom7_q = sp_rom_data[23:16]; +assign gfx_rom8_q = sp_rom_data[23:16]; + +`else +wire [7:0] gfx_rom_data = ioctl_dout; +wire [12:0] gfx_rom1_addr = ioctl_download ? ioctl_addr - 27'h10000 : rca[12:0]; +wire gfx_rom1_wren_a = ioctl_download && ioctl_addr >= 27'h10000 && ioctl_addr < 27'h12000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom2_addr = ioctl_download ? ioctl_addr - 27'h12000 : rca[12:0]; +wire gfx_rom2_wren_a = ioctl_download && ioctl_addr >= 27'h12000 && ioctl_addr < 27'h14000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom3_addr = ioctl_download ? ioctl_addr - 27'h14000 : sca[12:0]; +wire gfx_rom3_wren_a = ioctl_download && ioctl_addr >= 27'h14000 && ioctl_addr < 27'h16000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom4_addr = ioctl_download ? ioctl_addr - 27'h16000 : sca[12:0]; +wire gfx_rom4_wren_a = ioctl_download && ioctl_addr >= 27'h16000 && ioctl_addr < 27'h18000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom5_addr = ioctl_download ? ioctl_addr - 27'h18000 : sca[12:0]; +wire gfx_rom5_wren_a = ioctl_download && ioctl_addr >= 27'h18000 && ioctl_addr < 27'h1a000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom6_addr = ioctl_download ? ioctl_addr - 27'h1a000 : sca[12:0]; +wire gfx_rom6_wren_a = ioctl_download && ioctl_addr >= 27'h1a000 && ioctl_addr < 27'h1c000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom7_addr = ioctl_download ? ioctl_addr - 27'h1c000 : sca[12:0]; +wire gfx_rom7_wren_a = ioctl_download && ioctl_addr >= 27'h1c000 && ioctl_addr < 27'h1e000 ? ioctl_wr : 1'b0; +wire [12:0] gfx_rom8_addr = ioctl_download ? ioctl_addr - 27'h1e000 : sca[12:0]; +wire gfx_rom8_wren_a = ioctl_download && ioctl_addr >= 27'h1e000 && ioctl_addr < 27'h20000 ? ioctl_wr : 1'b0; + +// fg + +dpram #(13,8) gfx_rom1( + .clock ( clk_sys ), + .address_a ( gfx_rom1_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom1_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom1_wren_a ) +); + +dpram #(13,8) gfx_rom2( + .clock ( clk_sys ), + .address_a ( gfx_rom2_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom2_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom2_wren_a ) +); + +// bg + +dpram #(13,8) gfx_rom3( + .clock ( clk_sys ), + .address_a ( gfx_rom3_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom3_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom3_wren_a ) +); + +dpram #(13,8) gfx_rom4( + .clock ( clk_sys ), + .address_a ( gfx_rom4_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom4_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom4_wren_a ) +); + +dpram #(13,8) gfx_rom5( + .clock ( clk_sys ), + .address_a ( gfx_rom5_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom5_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom5_wren_a ) +); + +dpram #(13,8) gfx_rom6( + .clock ( clk_sys ), + .address_a ( gfx_rom6_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom6_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom6_wren_a ) +); + +dpram #(13,8) gfx_rom7( + .clock ( clk_sys ), + .address_a ( gfx_rom7_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom7_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom7_wren_a ) +); + +dpram #(13,8) gfx_rom8( + .clock ( clk_sys ), + .address_a ( gfx_rom8_addr ), + .data_a ( gfx_rom_data ), + .q_a ( gfx_rom8_q ), + .rden_a ( 1'b1 ), + .wren_a ( gfx_rom8_wren_a ) +); +`endif + +/******** AUDIO ********/ + +// /RDY are open-collector outputs on original schematic + +wire rdy1; +wire rdy2; +wire rdy3; +wire rdy_n = rdy1 & rdy2 & rdy3; + +wire [13:0] mix_audio1; +wire [13:0] mix_audio2; +wire [13:0] mix_audio3; + +assign sound = mix_audio1 + mix_audio2 + mix_audio3; + +sn76489_audio usnd1( + .clk_i ( clk_sys ), + .en_clk_psg_i ( clk_en_257 ), + .ce_n_i ( SN1 ), + .wr_n_i ( mcpu_wr_n | SN1 ), + .ready_o ( rdy1 ), + .data_i ( mcpu_dout ), + .mix_audio_o ( mix_audio1 ) +); + +sn76489_audio usnd2( + .clk_i ( clk_sys ), + .en_clk_psg_i ( clk_en_257 ), + .ce_n_i ( SN2 ), + .wr_n_i ( mcpu_wr_n | SN2 ), + .ready_o ( rdy2 ), + .data_i ( mcpu_dout ), + .mix_audio_o ( mix_audio2 ) +); + +sn76489_audio usnd3( + .clk_i ( clk_sys ), + .en_clk_psg_i ( clk_en_257 ), + .ce_n_i ( SN3 ), + .wr_n_i ( mcpu_wr_n | SN3 ), + .ready_o ( rdy3 ), + .data_i ( mcpu_dout ), + .mix_audio_o ( mix_audio3 ) +); + + +endmodule diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/dpram.v b/Arcade_MiST/Sega Bank Panic Hardware/rtl/dpram.v new file mode 100644 index 00000000..e5e87fbc --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/dpram.v @@ -0,0 +1,137 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: dpram.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 17.0.0 Build 595 04/25/2017 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 2017 Intel Corporation. All rights reserved. +//Your use of Intel 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 Intel Program License +//Subscription Agreement, the Intel Quartus Prime License Agreement, +//the Intel 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 Intel and sold by Intel 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 dpram +#( + parameter ADDRWIDTH=12, + parameter DATAWIDTH=8 +) +( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + rden_a, + rden_b, + q_a, + q_b); + + input [ADDRWIDTH-1:0] address_a; + input [ADDRWIDTH-1:0] address_b; + input clock; + input [DATAWIDTH-1:0] data_a; + input [DATAWIDTH-1:0] data_b; + input wren_a; + input wren_b; + input rden_a; + input rden_b; + output [DATAWIDTH-1:0] q_a; + output [DATAWIDTH-1:0] q_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri0 wren_a; + tri0 wren_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [DATAWIDTH-1:0] sub_wire0; + wire [DATAWIDTH-1:0] sub_wire1; + wire [DATAWIDTH-1:0] q_a = rden_a ? sub_wire0[DATAWIDTH-1:0] : {DATAWIDTH{1'b0}}; + wire [DATAWIDTH-1:0] q_b = rden_b ? sub_wire1[DATAWIDTH-1:0] : {DATAWIDTH{1'b0}}; + + altsyncram altsyncram_component ( + .address_a (address_a), + .address_b (address_b), + .clock0 (clock), + .data_a (data_a), + .data_b (data_b), + .wren_a (wren_a), + .wren_b (wren_b), + .q_a (sub_wire0), + .q_b (sub_wire1), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .eccstatus (), + .rden_a (1'b1), + .rden_b (1'b1)); + defparam + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.indata_reg_b = "CLOCK0", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2**ADDRWIDTH, + altsyncram_component.numwords_b = 2**ADDRWIDTH, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.outdata_reg_b = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = ADDRWIDTH, + altsyncram_component.widthad_b = ADDRWIDTH, + altsyncram_component.width_a = DATAWIDTH, + altsyncram_component.width_b = DATAWIDTH, + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0"; + + +endmodule diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.qip b/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.qip new file mode 100644 index 00000000..6182871f --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.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_mist.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_mist.ppf"] diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.v b/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.v new file mode 100644 index 00000000..8d5a964e --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/pll_mist.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll_mist.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll_mist ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 9, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 31, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 27, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 31, + 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_mist", + 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 "9" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "93.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "31.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "16" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "93.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "31.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "31" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "27" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "31" +// 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_mist.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/sdram.sv b/Arcade_MiST/Sega Bank Panic Hardware/rtl/sdram.sv new file mode 100644 index 00000000..9b1b8d1b --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/sdram.sv @@ -0,0 +1,352 @@ +// +// 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 [19:1] cpu1_addr, + input cpu1_cs, + output reg [15:0] cpu1_q, + input [19:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [31:0] port2_q, + + input [17:2] sp_addr, + output reg [31:0] sp_q +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b001; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 - data0 read burst terminated + 1 ras0 + 2 data1 returned + 3 CAS0 data1 returned + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_DS1b = 3'd0; +localparam STATE_READ1b = 3'd4; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; // Fast Input register latching incoming SDRAM data + +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [19:1] addr_last[2]; +reg [17:2] addr_last2[2]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CPU2 = 2'd2; +localparam PORT_SP = 2'd1; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [11:0] refresh_cnt; +reg need_refresh; + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[1]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 5'd0, cpu2_addr }; + end else if (cpu1_cs && cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 5'd0, cpu1_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, 6'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; + need_refresh <= (refresh_cnt >= RFRSH_CYCLES); + + 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][19: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 <= 0; + 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 else if (need_refresh && !oe_latch[0] & !we_latch[0]) begin + refresh <= 1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: port2_q[15:0] <= sd_din; + PORT_SP : sp_q[15:0] <= sd_din; + default: ; + endcase; + end + + //set DQM two cycles before the 2nd word in the burst + if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + + if(t == STATE_READ1b && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end + PORT_SP : begin sp_q[31:16] <= sd_din; end + default: ; + endcase; + end + end +end + +endmodule diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/sn76489_audio.vhd b/Arcade_MiST/Sega Bank Panic Hardware/rtl/sn76489_audio.vhd new file mode 100644 index 00000000..218f6d62 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/sn76489_audio.vhd @@ -0,0 +1,908 @@ +-- +-- SN76489 Complex Sound Generator +-- Matthew Hagerty +-- July 2020 +-- https://dnotq.io +-- + +-- Released under the 3-Clause BSD License: +-- +-- Copyright 2020 Matthew Hagerty (matthew dnotq io) +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- 1. Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- 3. Neither the name of the copyright holder nor the names of its +-- contributors may be used to endorse or promote products derived from this +-- software without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. + +-- +-- A huge amount of effort has gone into making this core as accurate as +-- possible to the real IC, while at the same time making it usable in all +-- digital SoC designs, i.e. retro-computer and game systems, etc. Design +-- elements from the real IC were used and implemented when possible, with any +-- work-around or changes noted along with the reasons. +-- +-- Synthesized and FPGA proven: +-- +-- * Xilinx Spartan-6 LX16, SoC 21.477MHz system clock, 3.58MHz clock-enable. +-- +-- +-- References: +-- +-- * The SN76489 datasheet +-- * Insight gained from the AY-3-8910/YM-2149 die-shot and reverse-engineered +-- schematics (similar audio chips from the same era). +-- * Real hardware (SN76489 in a ColecoVision game console). +-- * Chip quirks, use, and abuse details from friends and retro enthusiasts. +-- +-- +-- Generates: +-- +-- * Unsigned 12-bit output for each channel. +-- * Unsigned 14-bit summation of the four channels. +-- * Signed 14-bit PCM summation of the four channels, with each channel +-- converted to -/+ zero-centered level or -/+ full-range level. +-- +-- The tone counters are period-limited to prevent the very high frequency +-- outputs that the original IC is capable of producing. Frequencies above +-- 20KHz cause problems in all-digital systems with sampling rates around +-- 44.1KHz to 48KHz. The primary use of these high frequencies was as a +-- carrier for amplitude modulated (AM) audio. The high frequency would be +-- filtered out by external electronics, leaving only the low frequency audio. +-- +-- When the tone counters are limited, the output square-wave is disabled, but +-- the amplitude can still be changed, which allows the A.M. technique to still +-- work in a digital Soc. +-- +-- I/O requires at least two clock-enable cycles. This could be modified to +-- operate faster, i.e. based on the input-clock directly. All inputs are +-- registered at the system-clock rate. +-- +-- Optionally simulates the original 32-clock (clock-enable) I/O cycle. +-- +-- The SN76489 does not have an external reset and the original IC "wakes up" +-- generating a tone. This implementation sets the default output level to +-- full attenuation (silent output). If the original functionality is desired, +-- modify the channel period and level register initial values. + +-- +-- Basic I/O interface use: +-- +-- Set-up data on data_i. +-- Set ce_n_i and wr_n_i low. +-- Observe ready_o and wait for it to become high. +-- Set wr_n_i high, if done writing to the chip set ce_n_i high. + +-- +-- Version history: +-- +-- July 21 2020 +-- V1.0. Release. SoC tested. +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sn76489_audio is +generic -- 0 = normal I/O, 32 clocks per write + -- 1 = fast I/O, around 2 clocks per write + ( FAST_IO_G : std_logic := '0' + + -- Minimum allowable period count (see comments further + -- down for more information), recommended: + -- 6 18643.46Hz First audible count. + -- 17 6580.04Hz Counts at 16 are known to be used for + -- amplitude-modulation. + ; MIN_PERIOD_CNT_G : integer := 6 +); +port + ( clk_i : in std_logic -- System clock + ; en_clk_psg_i : in std_logic -- PSG clock enable + ; ce_n_i : in std_logic -- chip enable, active low + ; wr_n_i : in std_logic -- write enable, active low + ; ready_o : out std_logic -- low during I/O operations + ; data_i : in std_logic_vector(7 downto 0) + ; ch_a_o : out unsigned(11 downto 0) + ; ch_b_o : out unsigned(11 downto 0) + ; ch_c_o : out unsigned(11 downto 0) + ; noise_o : out unsigned(11 downto 0) + ; mix_audio_o : out unsigned(13 downto 0) + ; pcm14s_o : out unsigned(13 downto 0) +); +end sn76489_audio; + +architecture rtl of sn76489_audio is + + -- Registered I/O. + signal ce_n_r : std_logic := '1'; + signal wr_n_r : std_logic := '1'; + signal din_r : unsigned(7 downto 0) := x"00"; + signal ready_r : std_logic := '1'; + signal ready_x : std_logic; + + -- I/O FSM. + type io_state_t is (IO_IDLE, IO_OP, IO_WAIT); + signal io_state_r : io_state_t := IO_IDLE; + signal io_state_x : io_state_t; + signal io_cnt_r : unsigned(4 downto 0) := (others => '0'); + signal io_cnt_x : unsigned(4 downto 0); + signal en_reg_wr_s : std_logic; + + -- Register file. + signal reg_addr_r : unsigned(2 downto 0) := (others => '0'); + signal reg_sel_s : unsigned(2 downto 0); + + signal ch_a_period_r : unsigned(9 downto 0) := (others => '0'); + signal ch_a_period_x : unsigned(9 downto 0); + signal ch_a_level_r : unsigned(11 downto 0) := (others => '0'); + signal ch_a_level_x : unsigned(11 downto 0); + + signal ch_b_period_r : unsigned(9 downto 0) := (others => '0'); + signal ch_b_period_x : unsigned(9 downto 0); + signal ch_b_level_r : unsigned(11 downto 0) := (others => '0'); + signal ch_b_level_x : unsigned(11 downto 0); + + signal ch_c_period_r : unsigned(9 downto 0) := (others => '0'); + signal ch_c_period_x : unsigned(9 downto 0); + signal ch_c_level_r : unsigned(11 downto 0) := (others => '0'); + signal ch_c_level_x : unsigned(11 downto 0); + + signal noise_ctrl_r : std_logic := '0'; + signal noise_ctrl_x : std_logic; + signal noise_shift_r : unsigned(1 downto 0) := (others => '0'); + signal noise_shift_x : unsigned(1 downto 0); + signal noise_level_r : unsigned(11 downto 0) := (others => '0'); + signal noise_level_x : unsigned(11 downto 0); + signal noise_rst_r : std_logic := '0'; + signal noise_rst_x : std_logic; + + -- Clock conditioning counters and enables. + signal clk_div16_r : unsigned(3 downto 0) := (others => '0'); + signal clk_div16_x : unsigned(3 downto 0); + signal en_cnt_r : std_logic := '0'; + signal en_cnt_x : std_logic; + + -- Channel tone counters. + signal ch_a_cnt_r : unsigned(9 downto 0) := (others => '0'); + signal ch_a_cnt_x : unsigned(9 downto 0); + signal flatline_a_s : std_logic; + signal tone_a_r : std_logic := '1'; + signal tone_a_x : std_logic; + + signal ch_b_cnt_r : unsigned(9 downto 0) := (others => '0'); + signal ch_b_cnt_x : unsigned(9 downto 0); + signal flatline_b_s : std_logic; + signal tone_b_r : std_logic := '1'; + signal tone_b_x : std_logic; + + signal ch_c_cnt_r : unsigned(9 downto 0) := (others => '0'); + signal ch_c_cnt_x : unsigned(9 downto 0); + signal flatline_c_s : std_logic; + signal tone_c_r : std_logic := '1'; + signal tone_c_x : std_logic; + signal c_ff_r : std_logic := '1'; + signal c_ff_x : std_logic; + + -- Noise counter. + signal noise_cnt_r : unsigned(6 downto 0) := (others => '0'); + signal noise_cnt_x : unsigned(6 downto 0); + signal noise_ff_r : std_logic := '1'; + signal noise_ff_x : std_logic; + + -- 15-bit Noise LFSR. + signal noise_lfsr_r : std_logic_vector(14 downto 0) := b"100_0000_0000_0000"; + signal noise_lfsr_x : std_logic_vector(14 downto 0); + signal noise_fb_s : std_logic; + signal noise_s : std_logic; + + -- Amplitude / Attenuation control. + signal level_a_s : unsigned(11 downto 0); + signal level_b_s : unsigned(11 downto 0); + signal level_c_s : unsigned(11 downto 0); + signal level_n_s : unsigned(11 downto 0); + + -- DAC. + signal dac_a_r : unsigned(11 downto 0) := (others => '0'); + signal dac_b_r : unsigned(11 downto 0) := (others => '0'); + signal dac_c_r : unsigned(11 downto 0) := (others => '0'); + signal dac_n_r : unsigned(11 downto 0) := (others => '0'); + signal sum_audio_r : unsigned(13 downto 0) := (others => '0'); + + -- Digital to Analogue Output-level lookup table ROM. + -- + -- The 4-bit level from the channel register is used as an index into a + -- calculated table of values that represent the equivalent voltage. + -- + -- The output scale is amplitude logarithmic. + -- + -- ln10 = Natural logarithm of 10, ~= 2.302585 + -- amp = Amplitude in voltage, 0.2, 1.45, etc. + -- dB = decibel value in dB, -1.5, -3, etc. + -- + -- dB = 20 * log(amp) / ln10 + -- amp = 10 ^ (dB / 20) + -- + -- -1.5dB = 0.8413951416 + -- -2.0dB = 0.7943282347 + -- -3.0dB = 0.7079457843 + -- + -- The datasheet defines 16 attenuation steps that are -2.0dB apart. + -- + -- 1V reference values based on sixteen 2.0dB steps: + -- + -- 1.0000, 0.7943, 0.6310, 0.5012, 0.3981, 0.3162, 0.2512, 0.1995, + -- 0.1585, 0.1259, 0.1000, 0.0794, 0.0631, 0.0501, 0.0398, 0.0316 + -- + -- A 7-bit number (0..128) can support a scaled version of the reference + -- list without having any duplicate values, but the difference is small at + -- the bottom-end. Duplicate values means several volume levels produce the + -- same output level, and is not accurate. + -- + -- Using using a 12-bit output value means the four channels can be summed + -- into a 14-bit value without overflow, and leaves room for adjustments if + -- converting to something like 16-bit PCM. The 12-bit values also provide + -- a nicer curve, and are easier to initialize in VHDL. + -- + -- The lowest volume level needs to go to 0 in a digital SoC to prevent + -- noise that would be filtered in a real system with external electronics. + + signal dac_level_s : unsigned(11 downto 0); + + type dacrom_type is array (0 to 15) of unsigned(11 downto 0); + signal dacrom_ar : dacrom_type := ( + -- 4095,3253,2584,2052,1630,1295,1029, 817, + -- 649, 516, 409, 325, 258, 205, 163, 129 (forced to 0) + x"FFF",x"CB5",x"A18",x"804",x"65E",x"50F",x"405",x"331", + x"289",x"204",x"199",x"145",x"102",x"0CD",x"0A3",x"000"); + + -- PCM signed 14-bit. + signal sign_a_r : unsigned(11 downto 0) := (others => '0'); + signal sign_a_x : unsigned(11 downto 0); + signal sign_b_r : unsigned(11 downto 0) := (others => '0'); + signal sign_b_x : unsigned(11 downto 0); + signal sign_c_r : unsigned(11 downto 0) := (others => '0'); + signal sign_c_x : unsigned(11 downto 0); + signal sign_n_r : unsigned(11 downto 0) := (others => '0'); + signal sign_n_x : unsigned(11 downto 0); + signal pcm14s_r : unsigned(13 downto 0) := (others => '0'); + +begin + + -- Register the input data at the full clock rate. + process ( clk_i ) begin + if rising_edge(clk_i) then + ce_n_r <= ce_n_i; + wr_n_r <= wr_n_i; + din_r <= unsigned(data_i); + -- Ready is very fast so the external CPU will see the signal + -- in time to extend the I/O operation. + ready_r <= ready_x; + end if; + end process; + + -- Registered output. + ready_o <= ready_r; + + + -- ----------------------------------------------------------------------- + -- + -- External bus cycle FSM. + -- + -- The SN76489 can only be written (registers cannot be read back), and + -- only when the chip is selected. + -- + -- A write operation takes 32 clock cycles. A fast-IO mode is available + -- if legacy timing is not important. + + bus_io : process + ( ce_n_r, wr_n_r + , io_state_r, io_cnt_r, ready_r + ) begin + + io_state_x <= io_state_r; + io_cnt_x <= io_cnt_r; + ready_x <= ready_r; + en_reg_wr_s <= '0'; + + case io_state_r is + + when IO_IDLE => + -- Wait for CE_n and WR_n. + if ce_n_r = '0' and wr_n_r = '0' then + io_state_x <= IO_OP; + ready_x <= '0'; + + if FAST_IO_G = '1' then + -- No delay. + io_cnt_x <= (others => '0'); + else + -- The real IC takes 32 cycles for an I/O operation. + io_cnt_x <= to_unsigned(31, io_cnt_x'length); + end if; + end if; + + when IO_OP => + if io_cnt_r = 0 then + io_state_x <= IO_WAIT; + en_reg_wr_s <= '1'; + ready_x <= '1'; + else + io_cnt_x <= io_cnt_r - 1; + end if; + + when IO_WAIT => + -- The CPU must end the write-cycle; fine if CE_n is still asserted. + if wr_n_r = '1' then + io_state_x <= IO_IDLE; + end if; + + end case; + end process; + + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + if en_clk_psg_i = '1' then + io_state_r <= io_state_x; + io_cnt_r <= io_cnt_x; + end if; + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Registers. Setting the channel tone period requires two writes to set + -- the full 10-bit value. Bit numbering is n..0, which is *BACKWARDS* from + -- TI's bit numbering during this era. + -- + -- 7654 3210 + -- R0 1000 PPPP Channel A tone period 3..0. + -- 0-PP PPPP Channel A tone period 9..4. + -- R1 1001 AAAA Channel A attenuation. + -- R2 1010 PPPP Channel B tone period 3..0. + -- 0-PP PPPP Channel B tone period 9..4. + -- R3 1011 AAAA Channel B attenuation. + -- R4 1100 PPPP Channel C tone period 3..0. + -- 0-PP PPPP Channel C tone period 9..4. + -- R5 1101 AAAA Channel C attenuation. + -- R6 1110 -F-- Noise feedback, 0=periodic, 1=white noise + -- 1110 --SS Noise shift rate, 00=N/512, 01=N/1024, 10=N/2048, 11=Channel C + -- R7 1111 AAAA Noise attenuation. + + -- The register last written is latched, so any bytes written with a '0' in + -- the MS-bit will go to the same register. + + -- The output-level is converted to the equivalent DAC value and stored as + -- as the look-up result, rather than the 4-bit level index. This allows + -- sharing of the ROM lookup table, and uses less FPGA resources. + + dac_level_s <= dacrom_ar(to_integer(unsigned(din_r(3 downto 0)))); + + register_file : process + ( din_r, reg_addr_r, reg_sel_s, dac_level_s, en_reg_wr_s + , ch_a_period_r, ch_a_level_r + , ch_b_period_r, ch_b_level_r + , ch_c_period_r, ch_c_level_r + , noise_ctrl_r, noise_level_r, noise_shift_r + ) begin + + -- Register writes go to the specified register, data writes go to the + -- previously written register. + if din_r(7) = '0' then + reg_sel_s <= reg_addr_r; + else + reg_sel_s <= din_r(6 downto 4); + end if; + + ch_a_period_x <= ch_a_period_r; + ch_a_level_x <= ch_a_level_r; + ch_b_period_x <= ch_b_period_r; + ch_b_level_x <= ch_b_level_r; + ch_c_period_x <= ch_c_period_r; + ch_c_level_x <= ch_c_level_r; + + noise_ctrl_x <= noise_ctrl_r; + noise_shift_x <= noise_shift_r; + noise_level_x <= noise_level_r; + noise_rst_x <= '0'; + + + case reg_sel_s is + + when "000" => + if din_r(7) = '0' then + ch_a_period_x <= din_r(5 downto 0) & ch_a_period_r(3 downto 0); + else + ch_a_period_x <= ch_a_period_r(9 downto 4) & din_r(3 downto 0); + end if; + + when "001" => + ch_a_level_x <= dac_level_s; + + when "010" => + if din_r(7) = '0' then + ch_b_period_x <= din_r(5 downto 0) & ch_b_period_r(3 downto 0); + else + ch_b_period_x <= ch_b_period_r(9 downto 4) & din_r(3 downto 0); + end if; + + when "011" => + ch_b_level_x <= dac_level_s; + + when "100" => + if din_r(7) = '0' then + ch_c_period_x <= din_r(5 downto 0) & ch_c_period_r(3 downto 0); + else + ch_c_period_x <= ch_c_period_r(9 downto 4) & din_r(3 downto 0); + end if; + + when "101" => + ch_c_level_x <= dac_level_s; + + when "110" => + noise_ctrl_x <= din_r(2); + noise_shift_x <= din_r(1 downto 0); + -- Writing to the noise control register resets the LFSR to its + -- initialization value. + noise_rst_x <= en_reg_wr_s; + + -- "111" + when others => + noise_level_x <= dac_level_s; + + null; + end case; + end process; + + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + if en_clk_psg_i = '1' then + + noise_rst_r <= noise_rst_x; + + if en_reg_wr_s = '1' then + -- Latch the register when the write specifies a register. + reg_addr_r <= reg_sel_s; + + ch_a_period_r <= ch_a_period_x; + ch_a_level_r <= ch_a_level_x; + ch_b_period_r <= ch_b_period_x; + ch_b_level_r <= ch_b_level_x; + ch_c_period_r <= ch_c_period_x; + ch_c_level_r <= ch_c_level_x; + + noise_ctrl_r <= noise_ctrl_x; + noise_shift_r <= noise_shift_x; + noise_level_r <= noise_level_x; + end if; + + end if; + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Clock conditioning. Reduce the input clock to provide the divide by + -- sixteen clock-phases. + -- + + clk_div16_x <= clk_div16_r + 1; + en_cnt_x <= '1' when clk_div16_r = 0 else '0'; + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + if en_clk_psg_i = '1' then + clk_div16_r <= clk_div16_x; + en_cnt_r <= en_cnt_x; + end if; + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Channel tone counters. The counters *always* count. + -- + -- The counters count *down* and load the period when they reach zero. The + -- zero-check-and-load are all part of the same cycle. An implementation in + -- C might look like this: + -- + -- { + -- if ( counter == 0 ) { + -- tone = !tone; + -- counter = period; + -- } + -- + -- counter--; + -- } + -- + -- With the period work-around described below: + -- + -- { + -- if ( counter == 0 ) + -- { + -- if ( period > 0 and period < 6 ) { + -- tone = 1; + -- } else { + -- tone = !tone; + -- } + -- + -- counter = period; + -- } + -- + -- counter--; + -- } + -- + -- This also demonstrates why changing the tone period will not take effect + -- until the next cycle of the counter. Interestingly, the same counter is + -- used in the AY-3-8910 and YM-2149, only slightly modified to count up + -- (actually, in silicon both up and down counters are present + -- simultaneously) and reset on a >= period condition. + -- + + -- Amplitude Modulation. + -- + -- With a typical 3.5MHz to 4.0MHz (max) input clock, the main-clock divide + -- by sixteen produces a 223.72KHz clock into the tone counters. With small + -- period counts, frequencies *well over* the human hearing range can be + -- produced. + -- + -- The problem with the frequencies over 20KHz is, in a digital SoC the high + -- frequencies do not filter out like they do when the output is connected + -- to an external low-pass filter and inductive load (speaker), like they + -- are with the real IC. + -- + -- In an all digital system with digital audio, the generated frequencies + -- should never be more than the Nyquist frequency (twice the sample rate). + -- Typical sample rates are 44.1KHz or 48KHz, so any frequency over 20KHz + -- should not be output (and is not audible to a human anyway). + -- + -- The work-around here is to flat-line the toggle flip-flop for any tone + -- counter with a period that produces a frequency over the Nyquist rate. + -- This change still allows the technique of modulating the output with + -- rapid volume level changes. + -- + -- Based on a typical PSG clock of 3.58MHz for a Z80-based system, the + -- period counts that cause frequencies above 20KHz are: + -- + -- f = CLK / (32 * Count) + -- + -- Clk 3,579,545Hz 2.793651ns + -- + -- Cnt Frequency Period + -- 1 111860.78Hz 8.9396us + -- 2 55930.39Hz 17.8793us + -- 3 37286.92Hz 26.8190us + -- 4 27965.19Hz 35.7587us + -- 5 22372.15Hz 44.6984us + -- --------------------------- + -- 6 18643.46Hz 53.6381us First audible count. + -- 7 15980.11Hz 62.5777us + -- 8 13982.59Hz 71.5174us + -- 9 12428.97Hz 80.4571us + -- 10 11186.07Hz 89.3968us + -- 11 10169.16Hz 98.3365us + -- 12 9321.73Hz 107.2762us + -- 13 8604.67Hz 116.2158us + -- 14 7990.05Hz 125.1555us + -- 15 7457.38Hz 134.0952us + -- 16 6991.29Hz 143.0349us Used by some software for level-modulation. + -- --------------------------- + -- 17 6580.04Hz 151.9746us + -- ... + -- 0 109.23Hz 9.1542ms A count of zero is the maximum period. + -- + -- While a count of 6 is technically the Nyquist cut-off, some game software + -- is known to use a period of 16 as the base frequency for the amplitude + -- modulation hack. While audible, the 7KHz tone is not very musical, and + -- causes a harsh (if not painful) undertone to the sound being created with + -- the amplitude modulation. + -- + -- Suffice to say, setting the flat-line cut-off to 16 should not affect the + -- audio for most software in any negative way, but can help some software + -- sound better. + + + -- A channel counter and tone flip-flop. + ch_a_cnt_x <= + -- Load uses count-enable next-state look-ahead when counter is 0. + ch_a_period_r when (en_cnt_x = '1' and ch_a_cnt_r = 0) else + -- Counting uses the current-state. + ch_a_cnt_r - 1 when en_cnt_r = '1' else + ch_a_cnt_r; + + flatline_a_s <= + '1' when ch_a_period_r > 0 and ch_a_period_r < MIN_PERIOD_CNT_G else + '0'; + + tone_a_x <= + -- Flat-line the output for counts that produce frequencies > 20KHz. + '1' when flatline_a_s = '1' else + -- Toggle channel tone flip-flop when the counter reaches 0. + -- Same look-ahead condition as the counter-load. + not tone_a_r when (en_cnt_x = '1' and ch_a_cnt_r = 0) else + tone_a_r; + + -- B channel counter and tone flip-flop. + ch_b_cnt_x <= + ch_b_period_r when (en_cnt_x = '1' and ch_b_cnt_r = 0) else + ch_b_cnt_r - 1 when en_cnt_r = '1' else + ch_b_cnt_r; + + flatline_b_s <= + '1' when ch_b_period_r > 0 and ch_b_period_r < MIN_PERIOD_CNT_G else + '0'; + + tone_b_x <= + '1' when flatline_b_s = '1' else + not tone_b_r when (en_cnt_x = '1' and ch_b_cnt_r = 0) else + tone_b_r; + + -- C channel counter and tone flip-flop. + ch_c_cnt_x <= + ch_c_period_r when (en_cnt_x = '1' and ch_c_cnt_r = 0) else + ch_c_cnt_r - 1 when en_cnt_r = '1' else + ch_c_cnt_r; + + flatline_c_s <= + '1' when ch_c_period_r > 0 and ch_c_period_r < MIN_PERIOD_CNT_G else + '0'; + + tone_c_x <= flatline_c_s or c_ff_r; + + -- The work-around to limit high frequency outputs interferes with Channel-C + -- being able to clock the noise shift register. This is a work-around to + -- that work-around, to always have an output from Channel-C that can be + -- used to clock the noise shift register. + c_ff_x <= + not c_ff_r when (en_cnt_x = '1' and ch_c_cnt_r = 0) else + c_ff_r; + + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + + if en_clk_psg_i = '1' then + ch_a_cnt_r <= ch_a_cnt_x; + tone_a_r <= tone_a_x; + + ch_b_cnt_r <= ch_b_cnt_x; + tone_b_r <= tone_b_x; + + ch_c_cnt_r <= ch_c_cnt_x; + tone_c_r <= tone_c_x; + c_ff_r <= c_ff_x; + end if; + + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Noise period counter. A continuous counter to further divide the input + -- clock by 32, 64, or 128. The output goes to a selector, controlled by the + -- noise register, to choose one of the three rates, or the output flip-flop + -- of channel C, to drive the LFSR. + + noise_cnt_x <= + noise_cnt_r + 1 when en_cnt_r = '1' else + noise_cnt_r; + + with noise_shift_r select + noise_ff_x <= -- N = PSG input clock, typical 3.58MHz. + noise_cnt_r(4) when "00", -- N / 512 = approx 6991.2988Hz 143.034us + noise_cnt_r(5) when "01", -- N / 1024 = approx 3495.6494Hz 286.069us + noise_cnt_r(6) when "10", -- N / 2048 = approx 1747.8247Hz 572.139us + c_ff_r when others; -- "11" -- Channel C tone as the clock. + + + -- The noise can be periodic or white depending on the feedback-bit in the + -- noise control register. 0 = periodic, which just disables the XOR of the + -- LFSR and loops the single initialization bit through the shift register. + -- + -- Noise 15-bit right-shift LFSR with taps at 0 and 1, LS-bit is the output. + -- Reset loads the LFSR with 0x4000 to prevent lock-up. The same pattern + -- can be obtained with a left-shift, taps at 13 and 14, MS-bit output. + -- + -- Accurate implementation in C, no branching: + -- + -- uint32_t lfsr; + -- uint8_t noise_bit; + -- + -- // A 15-input NOR gate ensures init with 100_0000_0000_0000 + -- lfsr = (1 << 14); + -- + -- // Taps at 0 and 1, mask result. + -- int32_t fb = ((lfsr >> 0) ^ (lfsr >> 1)) & 1; + -- + -- // Right-shift, feedback bit to the most-significant bit. + -- lfsr = (lfsr >> 1) | (fb << 14); + -- + -- noise_bit = (lfsr & 1); + -- + + noise_fb_s <= + (noise_ctrl_r and noise_lfsr_r(1)) xor noise_lfsr_r(0); + noise_lfsr_x <= noise_fb_s & noise_lfsr_r(14 downto 1); + noise_s <= noise_lfsr_r(0); + + + process + ( clk_i, en_clk_psg_i, noise_rst_r + ) begin + if rising_edge(clk_i) then + + -- ** NOTE: This reset is active high. + if noise_rst_r = '1' then + noise_cnt_r <= (others => '0'); + noise_ff_r <= '1'; + noise_lfsr_r <= b"100_0000_0000_0000"; + + elsif en_clk_psg_i = '1' then + noise_cnt_r <= noise_cnt_x; + noise_ff_r <= noise_ff_x; + -- Look-ahead rising-edge detect the noise flip-flop. + if noise_ff_r = '0' and noise_ff_x = '1' then + noise_lfsr_r <= noise_lfsr_x; + end if; + end if; + + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Amplitude / Attenuation control. The amplitude of each channel is + -- controlled by the channel's 4-bit attenuation register. + -- + -- The "level" in the SN76489 is an amount of attenuation, and the channel's + -- level has already been converted into its DAC level. When the tone + -- flip-flop is '0', the most attenuation (minimum DAC level) is output. + + level_a_s <= + (others => '0') when tone_a_r = '0' else + ch_a_level_r; + + level_b_s <= + (others => '0') when tone_b_r = '0' else + ch_b_level_r; + + level_c_s <= + (others => '0') when tone_c_r = '0' else + ch_c_level_r; + + level_n_s <= + (others => '0') when noise_s = '0' else + noise_level_r; + + + -- ----------------------------------------------------------------------- + -- + -- Output registers and unsigned summation. If the level had not already + -- been converted to the output level, this would also be the DAC section. + -- + + ch_a_o <= dac_a_r; + ch_b_o <= dac_b_r; + ch_c_o <= dac_c_r; + noise_o <= dac_n_r; + mix_audio_o <= sum_audio_r; + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + if en_clk_psg_i = '1' then + + dac_a_r <= level_a_s; + dac_b_r <= level_b_s; + dac_c_r <= level_c_s; + dac_n_r <= level_n_s; + + -- Sum the audio channels. + sum_audio_r <= ("00" & level_a_s) + ("00" & level_b_s) + + ("00" & level_c_s) + ("00" & level_n_s); + end if; + end if; + end process; + + + -- ----------------------------------------------------------------------- + -- + -- Signed zero-centered 14-bit PCM. + -- + + -- Make a -/+ level value depending on the tone state. When the flat-line + -- work-around for frequencies over the Nyquist rate is in effect, adjust + -- the unsigned level-range to a signed-level range. + -- + -- signed_level = + -- level - (range / 2) when flat-line + -- + -- otherwise, -/+ zero-centered square-wave: + -- + -- signed_level = + -- -(level / 2) when tone == 0 + -- (level / 2) when tone == 1 + + sign_a_x <= + ch_a_level_r - x"800" when flatline_a_s = '1' else + ("1" & (not ch_a_level_r(11 downto 1))) + 1 when tone_a_r = '0' else + ("0" & ch_a_level_r(11 downto 1)); + + sign_b_x <= + ch_b_level_r - x"800" when flatline_b_s = '1' else + ("1" & (not ch_b_level_r(11 downto 1))) + 1 when tone_b_r = '0' else + ("0" & ch_b_level_r(11 downto 1)); + + sign_c_x <= + ch_c_level_r - x"800" when flatline_c_s = '1' else + ("1" & (not ch_c_level_r(11 downto 1))) + 1 when tone_c_r = '0' else + ("0" & ch_c_level_r(11 downto 1)); + + sign_n_x <= + ("1" & (not noise_level_r(11 downto 1))) + 1 when noise_s = '0' else + ("0" & noise_level_r(11 downto 1)); + + + pcm14s_o <= pcm14s_r; + + + process + ( clk_i, en_clk_psg_i + ) begin + if rising_edge(clk_i) then + if en_clk_psg_i = '1' then + + sign_a_r <= sign_a_x; + sign_b_r <= sign_b_x; + sign_c_r <= sign_c_x; + sign_n_r <= sign_n_x; + + -- Sum to signed 14-bit and left-align to signed 16-bit. + pcm14s_r <= + (sign_a_r(11) & sign_a_r(11) & sign_a_r) + + (sign_b_r(11) & sign_b_r(11) & sign_b_r) + + (sign_c_r(11) & sign_c_r(11) & sign_c_r) + + (sign_n_r(11) & sign_n_r(11) & sign_n_r); + + end if; + end if; + end process; + +end rtl; diff --git a/Arcade_MiST/Sega Bank Panic Hardware/rtl/x74138.v b/Arcade_MiST/Sega Bank Panic Hardware/rtl/x74138.v new file mode 100644 index 00000000..a3afed51 --- /dev/null +++ b/Arcade_MiST/Sega Bank Panic Hardware/rtl/x74138.v @@ -0,0 +1,14 @@ + +module x74138( + input G1, + input G2A, + input G2B, + input [2:0] A, + output reg [7:0] Y +); + +always @* + if (~G2B & ~G2A & G1) Y = ~(1<