diff --git a/Bally - Astrocade_MiST/Bally Arcade - Astrocade Schematic (Excerpt from PA-1 Service Manual).gif b/Bally - Astrocade_MiST/Bally Arcade - Astrocade Schematic (Excerpt from PA-1 Service Manual).gif new file mode 100644 index 00000000..c25258ee Binary files /dev/null and b/Bally - Astrocade_MiST/Bally Arcade - Astrocade Schematic (Excerpt from PA-1 Service Manual).gif differ diff --git a/Bally - Astrocade_MiST/ReadMe.md b/Bally - Astrocade_MiST/ReadMe.md new file mode 100644 index 00000000..1e96aa27 --- /dev/null +++ b/Bally - Astrocade_MiST/ReadMe.md @@ -0,0 +1,2 @@ +Untestet need Feedback + diff --git a/Bally - Astrocade_MiST/Snapshot/bally_mist.rbf b/Bally - Astrocade_MiST/Snapshot/bally_mist.rbf new file mode 100644 index 00000000..244bdd4f Binary files /dev/null and b/Bally - Astrocade_MiST/Snapshot/bally_mist.rbf differ diff --git a/Bally - Astrocade_MiST/bally_mist.qpf b/Bally - Astrocade_MiST/bally_mist.qpf new file mode 100644 index 00000000..cd7b5d38 --- /dev/null +++ b/Bally - Astrocade_MiST/bally_mist.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# 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 = 20:08:26 November 23, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "20:08:26 November 23, 2017" + +# Revisions + +PROJECT_REVISION = "bally_mist" diff --git a/Bally - Astrocade_MiST/bally_mist.qsf b/Bally - Astrocade_MiST/bally_mist.qsf new file mode 100644 index 00000000..92bc1614 --- /dev/null +++ b/Bally - Astrocade_MiST/bally_mist.qsf @@ -0,0 +1,166 @@ +# -------------------------------------------------------------------------- # +# +# 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.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version +# Date created = 13:20:03 July 25, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# bally_mist_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 ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:08:26 NOVEMBER 23, 2017" +set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +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 PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY bally_mist + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +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 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" +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# 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(bally_mist) + + # 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(bally_mist) +# ---------------------- +set_global_assignment -name SYSTEMVERILOG_FILE rtl/bally_mist.sv +set_global_assignment -name VHDL_FILE rtl/bally_top.vhd +set_global_assignment -name VHDL_FILE rtl/bally.vhd +set_global_assignment -name VHDL_FILE rtl/ps2kbd.vhd +set_global_assignment -name VHDL_FILE rtl/bally_rams.vhd +set_global_assignment -name VHDL_FILE rtl/bally_ps2_if.vhd +set_global_assignment -name VHDL_FILE rtl/bally_io.vhd +set_global_assignment -name VHDL_FILE rtl/bally_data.vhd +set_global_assignment -name VHDL_FILE rtl/bally_col_pal.vhd +set_global_assignment -name VHDL_FILE rtl/bally_addr.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv +set_global_assignment -name VERILOG_FILE rtl/mist_io.v +set_global_assignment -name VERILOG_FILE rtl/scandoubler.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv +set_global_assignment -name VERILOG_FILE rtl/osd.v +set_global_assignment -name VHDL_FILE rtl/dac.vhd +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name VHDL_FILE rtl/sprom.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80sed.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80_Reg.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80_Pack.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80_MCode.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80_ALU.vhd +set_global_assignment -name VHDL_FILE rtl/T80/T80.vhd +set_global_assignment -name VHDL_FILE rtl/pll.vhd +set_global_assignment -name VERILOG_FILE rtl/game.v +set_global_assignment -name QIP_FILE rtl/cart.qip +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Bally - Astrocade_MiST/bally_mist.srf b/Bally - Astrocade_MiST/bally_mist.srf new file mode 100644 index 00000000..269c9bf7 --- /dev/null +++ b/Bally - Astrocade_MiST/bally_mist.srf @@ -0,0 +1,6 @@ +{ "" "" "" "Verilog HDL warning at hq2x.sv(247): extended using \"x\" or \"z\"" { } { } 0 10273 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL information at scandoubler.v(102): always construct contains both blocking and non-blocking assignments" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 113007 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 113015 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10296 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""} diff --git a/Bally - Astrocade_MiST/clean.bat b/Bally - Astrocade_MiST/clean.bat new file mode 100644 index 00000000..9a939cda --- /dev/null +++ b/Bally - Astrocade_MiST/clean.bat @@ -0,0 +1,38 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +del /s PLLJ_PLLSPE_INFO.txt +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +cd sys +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +cd .. +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del /s new_rtl_netlist +del /s old_rtl_netlist + +pause diff --git a/Bally - Astrocade_MiST/rtl/BALLY_CHECK.vhd b/Bally - Astrocade_MiST/rtl/BALLY_CHECK.vhd new file mode 100644 index 00000000..dd2f2419 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/BALLY_CHECK.vhd @@ -0,0 +1,147 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: BALLY_CHECK.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.0 Build 162 10/23/2013 SJ Web Edition +-- ************************************************************ + + +--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. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +ENTITY BALLY_CHECK IS + PORT + ( + address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); + clken : IN STD_LOGIC := '1'; + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END BALLY_CHECK; + + +ARCHITECTURE SYN OF bally_check IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "NORMAL", + clock_enable_output_a => "NORMAL", + init_file => "../roms/balcheck.hex", + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2048, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 11, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + clocken0 => clken, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: Clken NUMERIC "1" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "../roms/balcheck.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "NORMAL" +-- Retrieval info: CONSTANT: INIT_FILE STRING "../roms/balcheck.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +-- Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC "clken" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL BALLY_CHECK.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL BALLY_CHECK.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL BALLY_CHECK.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL BALLY_CHECK.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL BALLY_CHECK_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Bally - Astrocade_MiST/rtl/T80/T80.vhd b/Bally - Astrocade_MiST/rtl/T80/T80.vhd new file mode 100644 index 00000000..da01f6b4 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80.vhd @@ -0,0 +1,1080 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup. Rmoved some auto_wait bits from 0247 which caused problems +-- +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0210 : Fixed wait and halt +-- +-- 0211 : Fixed Refresh addition and IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson +-- +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- +-- 0237 : Changed 8080 I/O address output, added IntE output +-- +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- +-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode +-- +-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80 is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); +end T80; + +architecture rtl of T80 is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + -- Registers + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; + + -- Help Registers + signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register + signal IR : std_logic_vector(7 downto 0); -- Instruction register + signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector + signal RegBusA_r : std_logic_vector(15 downto 0); + + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); + + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal IntE_FF1 : std_logic; + signal IntE_FF2 : std_logic; + signal Halt_FF : std_logic; + signal BusReq_s : std_logic; + signal BusAck : std_logic; + signal ClkEn : std_logic; + signal NMI_s : std_logic; + signal INT_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); + + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; + + -- ALU signals + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); + + -- Registered micro code outputs + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); + + -- Micro code outputs + signal MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(3 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Save_ALU : std_logic; + signal PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_i : std_logic; + signal Special_LD : std_logic_vector(2 downto 0); + signal ExchangeDH : std_logic; + signal ExchangeRp : std_logic; + signal ExchangeAF : std_logic; + signal ExchangeRS : std_logic; + signal I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_INRC : std_logic; + signal SetDI : std_logic; + signal SetEI : std_logic; + signal IMode : std_logic_vector(1 downto 0); + signal Halt : std_logic; + +begin + + mcode : T80_MCode + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, + Read_To_Acc => Read_To_Acc, + Read_To_Reg => Read_To_Reg, + Set_BusB_To => Set_BusB_To, + Set_BusA_To => Set_BusA_To, + ALU_Op => ALU_Op, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, + Set_Addr_To => Set_Addr_To, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write); + + alu : T80_ALU + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + Arith16 => Arith16_r, + Z16 => Z16_r, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); + + ClkEn <= CEN and not BusAck; + + T_Res <= '1' when TState = unsigned(TStates) else '0'; + + NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and + ((Set_Addr_To = aXY) or + (MCycle = "001" and IR = "11001011") or + (MCycle = "001" and IR = "00110110")) else '0'; + + Save_Mux <= BusB when ExchangeRp = '1' else + DI_Reg when Save_ALU_r = '0' else + ALU_Q; + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + TmpAddr <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; + + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; + + Read_To_Reg_r <= "00000"; + F <= (others => '1'); + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + + elsif CLK_n'event and CLK_n = '1' then + + if ClkEn = '1' then + + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; + + MCycles <= MCycles_d; + + if IMode /= "11" then + IStatus <= IMode; + end if; + + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; + + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 + + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; + + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; + else + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; + end if; + else + XY_State <= "00"; + XY_Ind <= '0'; + end if; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= TmpAddr; + PC <= unsigned(TmpAddr); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= TmpAddr; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + end if; + when aDE => + A <= RegBusC; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(TmpAddr) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + TmpAddr <= (others =>'0'); + TmpAddr(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + TmpAddr(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + TmpAddr(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 then + DO <= BusB; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; + when others => + end case; + end if; + + end if; + + end if; + + end process; + +--------------------------------------------------------------------------- +-- +-- BC('), DE('), HL('), IX and IY +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + -- Bus A / Write + RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then + RegAddrA_r <= XY_State(1) & "11"; + end if; + + -- Bus B + RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then + RegAddrB_r <= XY_State(1) & "11"; + end if; + + -- Address from register + RegAddrC <= Alternate & Set_Addr_To(1 downto 0); + -- Jump (HL), LD SP,HL + if (JumpXY = '1' or LDSPHL = '1') then + RegAddrC <= Alternate & "10"; + end if; + if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then + RegAddrC <= XY_State(1) & "11"; + end if; + + if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then + IncDecZ <= F_Out(Flag_Z); + end if; + if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then + if ID16 = 0 then + IncDecZ <= '0'; + else + IncDecZ <= '1'; + end if; + end if; + + RegBusA_r <= RegBusA; + end if; + end if; + end process; + + RegAddrA <= + -- 16 bit increment/decrement + Alternate & IncDec_16(1 downto 0) when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else + -- EX HL,DL + Alternate & "10" when ExchangeDH = '1' and TState = 3 else + Alternate & "01" when ExchangeDH = '1' and TState = 4 else + -- Bus A / Write + RegAddrA_r; + + RegAddrB <= + -- EX HL,DL + Alternate & "01" when ExchangeDH = '1' and TState = 3 else + -- Bus B + RegAddrB_r; + + ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else + signed(RegBusA) + 1; + + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegWEH <= '0'; + RegWEL <= '0'; + if (TState = 1 and Save_ALU_r = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => + RegWEH <= not Read_To_Reg_r(0); + RegWEL <= Read_To_Reg_r(0); + when others => + end case; + end if; + + if ExchangeDH = '1' and (TState = 3 or TState = 4) then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + case IncDec_16(1 downto 0) is + when "00" | "01" | "10" => + RegWEH <= '1'; + RegWEL <= '1'; + when others => + end case; + end if; + end process; + + process (Save_Mux, RegBusB, RegBusA_r, ID16, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegDIH <= Save_Mux; + RegDIL <= Save_Mux; + + if ExchangeDH = '1' and TState = 3 then + RegDIH <= RegBusB(15 downto 8); + RegDIL <= RegBusB(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 4 then + RegDIH <= RegBusA_r(15 downto 8); + RegDIL <= RegBusA_r(7 downto 0); + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + RegDIH <= std_logic_vector(ID16(15 downto 8)); + RegDIL <= std_logic_vector(ID16(7 downto 0)); + end if; + end process; + + Regs : T80_Reg + port map( + Clk => CLK_n, + CEN => ClkEn, + WEH => RegWEH, + WEL => RegWEL, + AddrA => RegAddrA, + AddrB => RegAddrB, + AddrC => RegAddrC, + DIH => RegDIH, + DIL => RegDIL, + DOAH => RegBusA(15 downto 8), + DOAL => RegBusA(7 downto 0), + DOBH => RegBusB(15 downto 8), + DOBL => RegBusB(7 downto 0), + DOCH => RegBusC(15 downto 8), + DOCL => RegBusC(7 downto 0)); + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + BusB <= "00000000"; + when others => + BusB <= "--------"; + end case; + + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusB <= "--------"; + end case; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Generate external control signals +-- +--------------------------------------------------------------------------- + process (RESET_n,CLK_n) + begin + if RESET_n = '0' then + RFSH_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; + end if; + end if; + end process; + + MC <= std_logic_vector(MCycle); + TS <= std_logic_vector(TState); + DI_Reg <= DI; + HALT_n <= not Halt_FF; + BUSAK_n <= not BusAck; + IntCycle_n <= not IntCycle; + IntE <= IntE_FF1; + IORQ <= IORQ_i; + Stop <= I_DJNZ; + +------------------------------------------------------------------------- +-- +-- Syncronise inputs +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; + begin + if RESET_n = '0' then + BusReq_s <= '0'; + INT_s <= '0'; + NMI_s <= '0'; + OldNMI_n := '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + INT_s <= not INT_n; + if NMICycle = '1' then + NMI_s <= '0'; + elsif NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + end if; + end if; + end process; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + Auto_Wait_t1 <= Auto_Wait; + Auto_Wait_t2 <= Auto_Wait_t1; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or + (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or + No_BTR = '1' or + (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if Auto_Wait = '1' nand Auto_Wait_t2 = '0' then + + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; + end if; + end if; + end if; + end process; + + process (IntCycle, NMICycle, MCycle) + begin + Auto_Wait <= '0'; + if IntCycle = '1' or NMICycle = '1' then + if MCycle = "001" then + Auto_Wait <= '1'; + end if; + end if; + end process; + +end; diff --git a/Bally - Astrocade_MiST/rtl/T80/T80_ALU.vhd b/Bally - Astrocade_MiST/rtl/T80/T80_ALU.vhd new file mode 100644 index 00000000..95c98dab --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80_ALU.vhd @@ -0,0 +1,371 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- +-- 0240 : Added GB operations +-- +-- 0242 : Cleanup +-- +-- 0247 : Cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_ALU is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); +end T80_ALU; + +architecture rtl of T80_ALU is + + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); + begin + if Sub = '1' then + B_i := not unsigned(B); + else + B_i := unsigned(B); + end if; + + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); + Carry <= Res_i(A'length + 1); + Res <= std_logic_vector(Res_i(A'length downto 1)); + end; + + -- AddSub variables (temporary signals) + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); + + signal BitMask : std_logic_vector(7 downto 0); + +begin + + with IR(5 downto 3) select BitMask <= "00000001" when "000", + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; + + UseCarry <= not ALU_Op(2) and ALU_Op(0); + AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); + AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); + AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); + + -- bug fix - parity flag is just parity for 8080, also overflow for Z80 + process (Carry_v, Carry7_v, Q_v) + begin + if(Mode=2) then + OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor + Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else + OverFlow_v <= Carry_v xor Carry7_v; + end if; + end process; + + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + variable Q_t : std_logic_vector(7 downto 0); + variable DAA_Q : unsigned(8 downto 0); + begin + Q_t := "--------"; + F_Out <= F_In; + DAA_Q := "---------"; + case ALU_Op is + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" => + F_Out(Flag_N) <= '0'; + F_Out(Flag_C) <= '0'; + case ALU_OP(2 downto 0) is + when "000" | "001" => -- ADD, ADC + Q_t := Q_v; + F_Out(Flag_C) <= Carry_v; + F_Out(Flag_H) <= HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "010" | "011" | "111" => -- SUB, SBC, CP + Q_t := Q_v; + F_Out(Flag_N) <= '1'; + F_Out(Flag_C) <= not Carry_v; + F_Out(Flag_H) <= not HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "100" => -- AND + Q_t(7 downto 0) := BusA and BusB; + F_Out(Flag_H) <= '1'; + when "101" => -- XOR + Q_t(7 downto 0) := BusA xor BusB; + F_Out(Flag_H) <= '0'; + when others => -- OR "110" + Q_t(7 downto 0) := BusA or BusB; + F_Out(Flag_H) <= '0'; + end case; + if ALU_Op(2 downto 0) = "111" then -- CP + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + else + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + end if; + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + if Z16 = '1' then + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + end if; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + case ALU_Op(2 downto 0) is + when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP + when others => + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + end case; + if Arith16 = '1' then + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + F_Out(Flag_P) <= F_In(Flag_P); + end if; + when "1100" => + -- DAA + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 + end if; + end if; + F_Out(Flag_X) <= DAA_Q(3); + F_Out(Flag_Y) <= DAA_Q(5); + F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8); + Q_t := std_logic_vector(DAA_Q(7 downto 0)); + if DAA_Q(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= DAA_Q(7); + F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor + DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7)); + when "1101" | "1110" => + -- RLD, RRD + Q_t(7 downto 4) := BusA(7 downto 4); + if ALU_Op(0) = '1' then + Q_t(3 downto 0) := BusB(7 downto 4); + else + Q_t(3 downto 0) := BusB(3 downto 0); + end if; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + when "1001" => + -- BIT + Q_t(7 downto 0) := BusB and BitMask; + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + F_Out(Flag_P) <= '1'; + else + F_Out(Flag_Z) <= '0'; + F_Out(Flag_P) <= '0'; + end if; + F_Out(Flag_H) <= '1'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= '0'; + F_Out(Flag_Y) <= '0'; + if IR(2 downto 0) /= "110" then + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + when "1010" => + -- SET + Q_t(7 downto 0) := BusB or BitMask; + when "1011" => + -- RES + Q_t(7 downto 0) := BusB and not BitMask; + when "1000" => + -- ROT + case IR(5 downto 3) is + when "000" => -- RLC + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := BusA(7); + F_Out(Flag_C) <= BusA(7); + when "010" => -- RL + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(7); + when "001" => -- RRC + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(0); + F_Out(Flag_C) <= BusA(0); + when "011" => -- RR + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(0); + when "100" => -- SLA + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '0'; + F_Out(Flag_C) <= BusA(7); + when "110" => -- SLL (Undocumented) / SWAP + if Mode = 3 then + Q_t(7 downto 4) := BusA(3 downto 0); + Q_t(3 downto 0) := BusA(7 downto 4); + F_Out(Flag_C) <= '0'; + else + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '1'; + F_Out(Flag_C) <= BusA(7); + end if; + when "101" => -- SRA + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(7); + F_Out(Flag_C) <= BusA(0); + when others => -- SRL + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := '0'; + F_Out(Flag_C) <= BusA(0); + end case; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + if ISet = "00" then + F_Out(Flag_P) <= F_In(Flag_P); + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + end if; + when others => + null; + end case; + Q <= Q_t; + end process; +end; diff --git a/Bally - Astrocade_MiST/rtl/T80/T80_MCode.vhd b/Bally - Astrocade_MiST/rtl/T80/T80_MCode.vhd new file mode 100644 index 00000000..43cea1b5 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80_MCode.vhd @@ -0,0 +1,1944 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0235 : Added IM 2 fix by Mike Johnson +-- +-- 0238 : Added NoRead signal +-- +-- 0238b: Fixed instruction timing for POP and DJNZ +-- +-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes + +-- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR +-- +-- 0242 : Fixed I/O instruction timing, cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80_MCode is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); +end T80_MCode; + +architecture rtl of T80_MCode is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + function is_cc_true( + F : std_logic_vector(7 downto 0); + cc : bit_vector(2 downto 0) + ) return boolean is + begin + if Mode = 3 then + case cc is + when "000" => return F(7) = '0'; -- NZ + when "001" => return F(7) = '1'; -- Z + when "010" => return F(4) = '0'; -- NC + when "011" => return F(4) = '1'; -- C + when "100" => return false; + when "101" => return false; + when "110" => return false; + when "111" => return false; + end case; + else + case cc is + when "000" => return F(6) = '0'; -- NZ + when "001" => return F(6) = '1'; -- Z + when "010" => return F(0) = '0'; -- NC + when "011" => return F(0) = '1'; -- C + when "100" => return F(2) = '0'; -- PO + when "101" => return F(2) = '1'; -- PE + when "110" => return F(7) = '0'; -- P + when "111" => return F(7) = '1'; -- M + end case; + end if; + end; + +begin + + process (IR, ISet, MCycle, F, NMICycle, IntCycle) + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); + variable DPair : std_logic_vector(1 downto 0); + variable IRB : bit_vector(7 downto 0); + begin + DDD := IR(5 downto 3); + SSS := IR(2 downto 0); + DPair := IR(5 downto 4); + IRB := to_bitvector(IR); + + MCycles <= "001"; + if MCycle = "001" then + TStates <= "100"; + else + TStates <= "011"; + end if; + Prefix <= "00"; + Inc_PC <= '0'; + Inc_WZ <= '0'; + IncDec_16 <= "0000"; + Read_To_Acc <= '0'; + Read_To_Reg <= '0'; + Set_BusB_To <= "0000"; + Set_BusA_To <= "0000"; + ALU_Op <= "0" & IR(5 downto 3); + Save_ALU <= '0'; + PreserveC <= '0'; + Arith16 <= '0'; + IORQ <= '0'; + Set_Addr_To <= aNone; + Jump <= '0'; + JumpE <= '0'; + JumpXY <= '0'; + Call <= '0'; + RstP <= '0'; + LDZ <= '0'; + LDW <= '0'; + LDSPHL <= '0'; + Special_LD <= "000"; + ExchangeDH <= '0'; + ExchangeRp <= '0'; + ExchangeAF <= '0'; + ExchangeRS <= '0'; + I_DJNZ <= '0'; + I_CPL <= '0'; + I_CCF <= '0'; + I_SCF <= '0'; + I_RETN <= '0'; + I_BT <= '0'; + I_BC <= '0'; + I_BTR <= '0'; + I_RLD <= '0'; + I_RRD <= '0'; + I_INRC <= '0'; + SetDI <= '0'; + SetEI <= '0'; + IMode <= "11"; + Halt <= '0'; + NoRead <= '0'; + Write <= '0'; + + case ISet is + when "00" => + +------------------------------------------------------------------------------ +-- +-- Unprefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is +-- 8 BIT LOAD GROUP + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- LD r,r' + Set_BusB_To(2 downto 0) <= SSS; + ExchangeRp <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" => + -- LD r,n + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" => + -- LD r,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" => + -- LD (HL),r + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110110" => + -- LD (HL),n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00001010" => + -- LD A,(BC) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00011010" => + -- LD A,(DE) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00111010" => + if Mode = 3 then + -- LDD A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end if; + when "00000010" => + -- LD (BC),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00010010" => + -- LD (DE),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110010" => + if Mode = 3 then + -- LDD (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + end if; + +-- 16 BIT LOAD GROUP + when "00000001"|"00010001"|"00100001"|"00110001" => + -- LD dd,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1000"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1001"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "00101010" => + if Mode = 3 then + -- LDI A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD HL,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end if; + when "00100010" => + if Mode = 3 then + -- LDI (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD (nn),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "0101"; -- L + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "0100"; -- H + when 5 => + Write <= '1'; + when others => null; + end case; + end if; + when "11111001" => + -- LD SP,HL + TStates <= "110"; + LDSPHL <= '1'; + when "11000101"|"11010101"|"11100101"|"11110101" => + -- PUSH qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "11000001"|"11010001"|"11100001"|"11110001" => + -- POP qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1011"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + IncDec_16 <= "0111"; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "0111"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + +-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + when "11101011" => + if Mode /= 3 then + -- EX DE,HL + ExchangeDH <= '1'; + end if; + when "00001000" => + if Mode = 3 then + -- LD (nn),SP + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "1000"; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "1001"; + when 5 => + Write <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EX AF,AF' + ExchangeAF <= '1'; + end if; + when "11011001" => + if Mode = 3 then + -- RETI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + SetEI <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EXX + ExchangeRS <= '1'; + end if; + when "11100011" => + if Mode /= 3 then + -- EX (SP),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; + Set_Addr_To <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + TStates <= "100"; + Write <= '1'; + when 4 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; + Set_Addr_To <= aSP; + when 5 => + IncDec_16 <= "1111"; + TStates <= "101"; + Write <= '1'; + when others => null; + end case; + end if; + +-- 8 BIT ARITHMETIC AND LOGICAL GROUP + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- ADD A,r + -- ADC A,r + -- SUB A,r + -- SBC A,r + -- AND A,r + -- OR A,r + -- XOR A,r + -- CP A,r + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- ADD A,(HL) + -- ADC A,(HL) + -- SUB A,(HL) + -- SBC A,(HL) + -- AND A,(HL) + -- OR A,(HL) + -- XOR A,(HL) + -- CP A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + when others => null; + end case; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- ADD A,n + -- ADC A,n + -- SUB A,n + -- SBC A,n + -- AND A,n + -- OR A,n + -- XOR A,n + -- CP A,n + MCycles <= "010"; + if MCycle = "010" then + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + end if; + when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" => + -- INC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + when "00110100" => + -- INC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" => + -- DEC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0010"; + when "00110101" => + -- DEC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + ALU_Op <= "0010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + +-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + when "00100111" => + -- DAA + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + ALU_Op <= "1100"; + Save_ALU <= '1'; + when "00101111" => + -- CPL + I_CPL <= '1'; + when "00111111" => + -- CCF + I_CCF <= '1'; + when "00110111" => + -- SCF + I_SCF <= '1'; + when "00000000" => + if NMICycle = '1' then + -- NMI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when others => null; + end case; + elsif IntCycle = '1' then + -- INT (IM 2) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + else + -- NOP + end if; + when "01110110" => + -- HALT + Halt <= '1'; + when "11110011" => + -- DI + SetDI <= '1'; + when "11111011" => + -- EI + SetEI <= '1'; + +-- 16 BIT ARITHMETIC GROUP + when "00001001"|"00011001"|"00101001"|"00111001" => + -- ADD HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; + when others => + end case; + when "00000011"|"00010011"|"00100011"|"00110011" => + -- INC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when "00001011"|"00011011"|"00101011"|"00111011" => + -- DEC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + +-- ROTATE AND SHIFT GROUP + when "00000111" + -- RLCA + |"00010111" + -- RLA + |"00001111" + -- RRCA + |"00011111" => + -- RRA + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + +-- JUMP GROUP + when "11000011" => + -- JP nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + Jump <= '1'; + when others => null; + end case; + when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+C),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "01" => + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + when "10" => + -- LD A,($FF00+C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => + end case; + when "11" => + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end case; + else + -- JP cc,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Jump <= '1'; + end if; + when others => null; + end case; + end if; + when "00011000" => + if Mode /= 2 then + -- JR e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00111000" => + if Mode /= 2 then + -- JR C,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00110000" => + if Mode /= 2 then + -- JR NC,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00101000" => + if Mode /= 2 then + -- JR Z,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00100000" => + if Mode /= 2 then + -- JR NZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "11101001" => + -- JP (HL) + JumpXY <= '1'; + when "00010000" => + if Mode = 3 then + I_DJNZ <= '1'; + elsif Mode < 2 then + -- DJNZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + I_DJNZ <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= "000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + I_DJNZ <= '1'; + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + +-- CALL AND RETURN GROUP + when "11001101" => + -- CALL nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + IncDec_16 <= "1111"; + Inc_PC <= '1'; + TStates <= "100"; + Set_Addr_To <= aSP; + LDW <= '1'; + Set_BusB_To <= "1101"; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => + if IR(5) = '0' or Mode /= 3 then + -- CALL cc,nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + LDW <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + TStates <= "100"; + Set_BusB_To <= "1101"; + else + MCycles <= "011"; + end if; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + end if; + when "11001001" => + -- RET + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+nn),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "01" => + -- ADD SP,n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + ALU_Op <= "0000"; + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To <= "1000"; + Set_BusB_To <= "0110"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To <= "1001"; + Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + when others => + end case; + when "10" => + -- LD A,($FF00+nn) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "11" => + -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end case; + else + -- RET cc + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; + when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => + -- RST p + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + +-- INPUT AND OUTPUT GROUP + when "11011011" => + if Mode /= 3 then + -- IN A,(n) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + when "11010011" => + if Mode /= 3 then + -- OUT (n),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- MULTIBYTE INSTRUCTIONS +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + + when "11001011" => + if Mode /= 2 then + Prefix <= "01"; + end if; + + when "11101101" => + if Mode < 2 then + Prefix <= "10"; + end if; + + when "11011101"|"11111101" => + if Mode < 2 then + Prefix <= "11"; + end if; + + end case; + + when "01" => + +------------------------------------------------------------------------------ +-- +-- CB prefixed instructions +-- +------------------------------------------------------------------------------ + + Set_BusA_To(2 downto 0) <= IR(2 downto 0); + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" => + -- RLC r + -- RL r + -- RRC r + -- RR r + -- SLA r + -- SRA r + -- SRL r + -- SLL r (Undocumented) / SWAP r + if MCycle = "001" then + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" => + -- RLC (HL) + -- RL (HL) + -- RRC (HL) + -- RR (HL) + -- SRA (HL) + -- SRL (HL) + -- SLA (HL) + -- SLL (HL) (Undocumented) / SWAP (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- BIT b,r + if MCycle = "001" then + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + ALU_Op <= "1001"; + end if; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" => + -- BIT b,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => null; + end case; + when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" => + -- SET b,r + if MCycle = "001" then + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- SET b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- RES b,r + if MCycle = "001" then + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- RES b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end case; + + when others => + +------------------------------------------------------------------------------ +-- +-- ED prefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111" + + + |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111" + | "10100100"|"10100101"|"10100110"|"10100111" + | "10101100"|"10101101"|"10101110"|"10101111" + | "10110100"|"10110101"|"10110110"|"10110111" + | "10111100"|"10111101"|"10111110"|"10111111" + |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => + null; -- NOP, undocumented + when "01111110"|"01111111" => + -- NOP, undocumented + null; +-- 8 BIT LOAD GROUP + when "01010111" => + -- LD A,I + Special_LD <= "100"; + TStates <= "101"; + when "01011111" => + -- LD A,R + Special_LD <= "101"; + TStates <= "101"; + when "01000111" => + -- LD I,A + Special_LD <= "110"; + TStates <= "101"; + when "01001111" => + -- LD R,A + Special_LD <= "111"; + TStates <= "101"; +-- 16 BIT LOAD GROUP + when "01001011"|"01011011"|"01101011"|"01111011" => + -- LD dd,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1000"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '1'; + end if; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1001"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "01000011"|"01010011"|"01100011"|"01110011" => + -- LD (nn),dd + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1000"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1001"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 5 => + Write <= '1'; + when others => null; + end case; + when "10100000" | "10101000" | "10110000" | "10111000" => + -- LDI, LDD, LDIR, LDDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0000"; + Set_Addr_To <= aDE; + if IR(3) = '0' then + IncDec_16 <= "0110"; -- IX + else + IncDec_16 <= "1110"; + end if; + when 3 => + I_BT <= '1'; + TStates <= "101"; + Write <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0101"; -- DE + else + IncDec_16 <= "1101"; + end if; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100001" | "10101001" | "10110001" | "10111001" => + -- CPI, CPD, CPIR, CPDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0111"; + Save_ALU <= '1'; + PreserveC <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + when 3 => + NoRead <= '1'; + I_BC <= '1'; + TStates <= "101"; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" => + -- NEG + Alu_OP <= "0010"; + Set_BusB_To <= "0111"; + Set_BusA_To <= "1010"; + Read_To_Acc <= '1'; + Save_ALU <= '1'; + when "01000110"|"01001110"|"01100110"|"01101110" => + -- IM 0 + IMode <= "00"; + when "01010110"|"01110110" => + -- IM 1 + IMode <= "01"; + when "01011110"|"01110111" => + -- IM 2 + IMode <= "10"; +-- 16 bit arithmetic + when "01001010"|"01011010"|"01101010"|"01111010" => + -- ADC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0001"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01000010"|"01010010"|"01100010"|"01110010" => + -- SBC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01101111" => + -- RLD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1101"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RLD <= '1'; + Write <= '1'; + when others => + end case; + when "01100111" => + -- RRD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1110"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RRD <= '1'; + Write <= '1'; + when others => + end case; + when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => + -- RETI, RETN + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + when others => null; + end case; + when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" => + -- IN r,(C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + IORQ <= '1'; + if IR(5 downto 3) /= "110" then + Read_To_Reg <= '1'; + Set_BusA_To(2 downto 0) <= IR(5 downto 3); + end if; + I_INRC <= '1'; + when others => + end case; + when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" => + -- OUT (C),r + -- OUT (C),0 + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + if IR(5 downto 3) = "110" then + Set_BusB_To(3) <= '1'; + end if; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "10100010" | "10101010" | "10110010" | "10111010" => + -- INI, IND, INIR, INDR + -- note B is decremented AFTER being put on the bus + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + IORQ <= '1'; + Set_BusB_To <= "0110"; + Set_Addr_To <= aXY; + when 3 => + if IR(3) = '0' then + --IncDec_16 <= "0010"; + IncDec_16 <= "0110"; + else + --IncDec_16 <= "1010"; + IncDec_16 <= "1110"; + end if; + TStates <= "100"; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100011" | "10101011" | "10110011" | "10111011" => + -- OUTI, OUTD, OTIR, OTDR + -- note B is decremented BEFORE being put on the bus. + -- mikej fix for hl inc + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aXY; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + Set_BusB_To <= "0110"; + Set_Addr_To <= aBC; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0110"; -- mikej + else + IncDec_16 <= "1110"; -- mikej + end if; + IORQ <= '1'; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + end case; + + end case; + + if Mode = 1 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "011"; + end if; + end if; + + if Mode = 3 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "100"; + end if; + end if; + + if Mode < 2 then + if MCycle = "110" then + Inc_PC <= '1'; + if Mode = 1 then + Set_Addr_To <= aXY; + TStates <= "100"; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + end if; + if IRB = "00110110" or IRB = "11001011" then + Set_Addr_To <= aNone; + end if; + end if; + if MCycle = "111" then + if Mode = 0 then + TStates <= "101"; + end if; + if ISet /= "01" then + Set_Addr_To <= aXY; + end if; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + if IRB = "00110110" or ISet = "01" then + -- LD (HL),n + Inc_PC <= '1'; + else + NoRead <= '1'; + end if; + end if; + end if; + + end process; + +end; diff --git a/Bally - Astrocade_MiST/rtl/T80/T80_Pack.vhd b/Bally - Astrocade_MiST/rtl/T80/T80_Pack.vhd new file mode 100644 index 00000000..42cf6105 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80_Pack.vhd @@ -0,0 +1,217 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T80_Pack is + + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); + end component; + + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Bally - Astrocade_MiST/rtl/T80/T80_Reg.vhd b/Bally - Astrocade_MiST/rtl/T80/T80_Reg.vhd new file mode 100644 index 00000000..1c0f2638 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80_Reg.vhd @@ -0,0 +1,114 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- T80 Registers, technology independent +-- +-- Version : 0244 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t51/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : Initial release +-- +-- 0244 : Changed to single register file +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_Reg is + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); +end T80_Reg; + +architecture rtl of T80_Reg is + + type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); + +begin + + process (Clk) + begin + if Clk'event and Clk = '1' then + if CEN = '1' then + if WEH = '1' then + RegsH(to_integer(unsigned(AddrA))) <= DIH; + end if; + if WEL = '1' then + RegsL(to_integer(unsigned(AddrA))) <= DIL; + end if; + end if; + end if; + end process; + + DOAH <= RegsH(to_integer(unsigned(AddrA))); + DOAL <= RegsL(to_integer(unsigned(AddrA))); + DOBH <= RegsH(to_integer(unsigned(AddrB))); + DOBL <= RegsL(to_integer(unsigned(AddrB))); + DOCH <= RegsH(to_integer(unsigned(AddrC))); + DOCL <= RegsL(to_integer(unsigned(AddrC))); + +end; diff --git a/Bally - Astrocade_MiST/rtl/T80/T80sed.vhd b/Bally - Astrocade_MiST/rtl/T80/T80sed.vhd new file mode 100644 index 00000000..0c28ec21 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/T80/T80sed.vhd @@ -0,0 +1,179 @@ +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- ** CUSTOM 2 CLOCK MEMORY ACCESS FOR PACMAN, MIKEJ ** +-- +-- Z80 compatible microprocessor core, synchronous top level with clock enable +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0238 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0235 : First release +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80sed is + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CLKEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T80sed; + +architecture rtl of T80sed is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => 0, + IOWait => 1) + port map( + CEN => CLKEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK_n, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK_n'event and CLK_n = '1' then + if CLKEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycle_n; + end if; + if TState = "011" then + MREQ_n <= '0'; + end if; + else + if (TState = "001" or TState = "010") and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if ((TState = "001") or (TState = "010")) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + if TState = "010" and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end; diff --git a/Bally - Astrocade_MiST/rtl/bally.vhd b/Bally - Astrocade_MiST/rtl/bally.vhd new file mode 100644 index 00000000..314778ea --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally.vhd @@ -0,0 +1,450 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY is + port ( + O_AUDIO : out std_logic_vector(7 downto 0); + + O_VIDEO_R : out std_logic_vector(3 downto 0); + O_VIDEO_G : out std_logic_vector(3 downto 0); + O_VIDEO_B : out std_logic_vector(3 downto 0); + + O_HSYNC : out std_logic; + O_VSYNC : out std_logic; + O_COMP_SYNC_L : out std_logic; + O_FPSYNC : out std_logic; + + -- cart slot + O_CAS_ADDR : out std_logic_vector(12 downto 0); + O_CAS_DATA : out std_logic_vector( 7 downto 0); + I_CAS_DATA : in std_logic_vector( 7 downto 0); + O_CAS_CS_L : out std_logic; + + -- exp slot (subset for now) + O_EXP_ADDR : out std_logic_vector(15 downto 0); + O_EXP_DATA : out std_logic_vector( 7 downto 0); + I_EXP_DATA : in std_logic_vector( 7 downto 0); + I_EXP_OE_L : in std_logic; -- expansion slot driving data bus + + O_EXP_M1_L : out std_logic; + O_EXP_MREQ_L : out std_logic; + O_EXP_IORQ_L : out std_logic; + O_EXP_WR_L : out std_logic; + O_EXP_RD_L : out std_logic; + -- + O_SWITCH_COL : out std_logic_vector(7 downto 0); + I_SWITCH_ROW : in std_logic_vector(7 downto 0); + -- + I_RESET_L : in std_logic; + ENA : in std_logic; + pix_ena : out std_logic; + CLK : in std_logic; + CLK7 : in std_logic + ); +end; + +architecture RTL of BALLY is + + -- signals + signal cpu_ena : std_logic; + signal cpu_ena_gated : std_logic; + -- + signal cpu_m1_l : std_logic; + signal cpu_mreq_l : std_logic; + signal cpu_iorq_l : std_logic; + signal cpu_rd_l : std_logic; + signal cpu_wr_l : std_logic; + signal cpu_rfsh_l : std_logic; + signal cpu_halt_l : std_logic; + signal cpu_wait_l : std_logic; + signal cpu_int_l : std_logic; + signal cpu_nmi_l : std_logic; + signal cpu_busrq_l : std_logic; + signal cpu_busak_l : std_logic; + signal cpu_addr : std_logic_vector(15 downto 0); + signal cpu_data_out : std_logic_vector(7 downto 0); + signal cpu_data_in : std_logic_vector(7 downto 0); + + signal mc1 : std_logic; + signal mc0 : std_logic; + --signal mx_bus : std_logic_vector(7 downto 0); -- cpu to customs + signal mx_addr : std_logic_vector(7 downto 0); -- customs to cpu + signal mx_addr_oe_l : std_logic; + signal mx_data : std_logic_vector(7 downto 0); -- customs to cpu + signal mx_data_oe_l : std_logic; + signal mx_io : std_logic_vector(7 downto 0); -- customs to cpu + signal mx_io_oe_l : std_logic; + + signal ma_bus : std_logic_vector(15 downto 0); + signal md_bus_out : std_logic_vector(7 downto 0); + signal md_bus_in : std_logic_vector(7 downto 0); + signal md_bus_in_x : std_logic_vector(7 downto 0); + signal daten_l : std_logic; + signal datwr : std_logic; + + signal horiz_dr : std_logic; + signal vert_dr : std_logic; + signal wrctl_l : std_logic; + signal ltchdo : std_logic; + -- + -- expansion + signal exp_buzoff_l : std_logic; + signal exp_sysen : std_logic; + signal exp_casen : std_logic; + + signal sys_cs_l : std_logic; + signal rom0_dout : std_logic_vector(7 downto 0); + signal rom1_dout : std_logic_vector(7 downto 0); + signal rom_dout : std_logic_vector(7 downto 0); + signal cas_cs_l : std_logic; + + signal video_r : std_logic_vector(3 downto 0); + signal video_g : std_logic_vector(3 downto 0); + signal video_b : std_logic_vector(3 downto 0); + signal hsync : std_logic; + signal vsync : std_logic; + signal fpsync : std_logic; +begin + -- + -- cpu + -- + -- doc + -- memory map + -- 0000 - 0fff os rom / magic ram + -- 1000 - 1fff os rom + -- 2000 - 3fff cas rom + -- 4000 - 4fff screen ram + + -- in hi res screen ram from 4000 - 7fff + -- magic ram 0000 - 3fff + + -- screen + -- low res 40 bytes / line (160 pixels, 2 bits per pixel) + -- vert res 102 lines + + -- high res 80 bytes (320 pixels) and 204 lines. + -- addr 0 top left. lsb 2 bits describe right hand pixel + + -- expansion sigs + exp_buzoff_l <= '1'; -- pull up + exp_sysen <= '1'; -- pull up + exp_casen <= '1'; -- pull up + + -- other cpu signals + cpu_busrq_l <= '1'; + cpu_nmi_l <= '1'; + + cpu_ena_gated <= ENA and cpu_ena; + u_cpu : entity work.T80sed + port map ( + RESET_n => I_RESET_L, + CLK_n => CLK7, + CLKEN => cpu_ena_gated, + WAIT_n => cpu_wait_l, + INT_n => cpu_int_l, + NMI_n => cpu_nmi_l, + BUSRQ_n => cpu_busrq_l, + M1_n => cpu_m1_l, + MREQ_n => cpu_mreq_l, + IORQ_n => cpu_iorq_l, + RD_n => cpu_rd_l, + WR_n => cpu_wr_l, + RFSH_n => cpu_rfsh_l, + HALT_n => cpu_halt_l, + BUSAK_n => cpu_busak_l, + A => cpu_addr, + DI => cpu_data_in, + DO => cpu_data_out + ); + -- + -- primary addr decode + -- + p_mem_decode_comb : process(cpu_rfsh_l, cpu_rd_l, cpu_mreq_l, cpu_addr, exp_sysen, exp_casen) + variable decode : std_logic; + begin + + sys_cs_l <= '1'; -- system rom + cas_cs_l <= '1'; -- game rom + + decode := '0'; + if (cpu_rd_l = '0') and (cpu_mreq_l = '0') and (cpu_addr(15 downto 14) = "00") then + decode := '1'; + end if; + + sys_cs_l <= not (decode and (not cpu_addr(13)) and exp_sysen); + cas_cs_l <= not (decode and ( cpu_addr(13)) and exp_casen); + end process; + + --p_microcycler : process(cpu_rfsh_l, mc0, mc1) + --variable sel : std_logic_vector(1 downto 0); + --begin + --sel := mc0 & mc1; + + --if (cpu_rfsh_l = '0') then + --mx_bus <= cpu_addr(7 downto 0); + --else + --mx_bus <= x"00"; + --case sel is + --when "00" => mx_bus <= cpu_addr( 7 downto 0); + --when "01" => mx_bus <= cpu_addr(15 downto 8); + --when "10" => mx_bus <= cpu_data_out(7 downto 0); + --when "11" => mx_bus <= x"00"; -- to cpu + --when others => null; + --end case; + ---- to cpu data drive when + ----rfsh_l = '1' and mc1 = '1', mc0 direction + --end if; + --end process; + + u_rom0 : entity work.sprom + generic map ( + init_file => ".\roms\bios3159_0.hex", + widthad_a => 12, + width_a => 8 + ) + port map ( + address => cpu_addr(11 downto 0), + clock => CLK7, + q => rom0_dout + ); + + u_rom1 : entity work.sprom + generic map ( + init_file => ".\roms\bios3159_1.hex", + widthad_a => 12, + width_a => 8 + ) + port map ( + address => cpu_addr(11 downto 0), + clock => CLK7, + q => rom1_dout + ); + + p_rom_mux : process(cpu_addr, rom0_dout, rom1_dout) + begin + if (cpu_addr(12) = '0') then + rom_dout <= rom0_dout; + else + rom_dout <= rom1_dout; + end if; + + end process; + + p_cpu_src_data_mux : process(rom_dout, sys_cs_l, I_CAS_DATA, cas_cs_l, I_EXP_OE_L, I_EXP_DATA, exp_buzoff_l, + mx_addr_oe_l, mx_addr, mx_data_oe_l, mx_data, mx_io_oe_l, mx_io) + begin + -- nasty mux + if (I_EXP_OE_L = '0') or (exp_buzoff_l = '0') then + cpu_data_in <= I_EXP_DATA; + elsif (sys_cs_l = '0') then + cpu_data_in <= rom_dout; + elsif (cas_cs_l = '0') then + cpu_data_in <= I_CAS_DATA; + elsif (mx_addr_oe_l = '0') then + cpu_data_in <= mx_addr; + elsif (mx_data_oe_l = '0') then + cpu_data_in <= mx_data; + elsif (mx_io_oe_l = '0') then + cpu_data_in <= mx_io; + else + cpu_data_in <= x"FF"; + end if; + end process; + + u_addr : entity work.BALLY_ADDR + port map ( + I_MXA => cpu_addr, + I_MXD => cpu_data_out, + O_MXD => mx_addr, + O_MXD_OE_L => mx_addr_oe_l, + + -- cpu control signals + I_RFSH_L => cpu_rfsh_l, + I_M1_L => cpu_m1_l, + I_RD_L => cpu_rd_l, + I_MREQ_L => cpu_mreq_l, + I_IORQ_L => cpu_iorq_l, + O_WAIT_L => cpu_wait_l, + O_INT_L => cpu_int_l, + + -- custom + I_HORIZ_DR => horiz_dr, + I_VERT_DR => vert_dr, + O_WRCTL_L => wrctl_l, + O_LTCHDO => ltchdo, + + -- dram address + O_MA => ma_bus, + O_RAS => open, + -- misc + I_LIGHT_PEN_L => '1', + + -- clks + I_CPU_ENA => cpu_ena, + ENA => ENA, + CLK => CLK7 + ); + + u_data : entity work.BALLY_DATA + port map ( + I_MXA => cpu_addr, + I_MXD => cpu_data_out, + O_MXD => mx_data, + O_MXD_OE_L => mx_data_oe_l, + + -- cpu control signals + I_M1_L => cpu_m1_l, + I_RD_L => cpu_rd_l, + I_MREQ_L => cpu_mreq_l, + I_IORQ_L => cpu_iorq_l, + + -- memory + O_DATEN_L => daten_l, + O_DATWR => datwr, -- makes dp ram timing easier + I_MDX => md_bus_in_x, + I_MD => md_bus_in, + O_MD => md_bus_out, + O_MD_OE_L => open, + -- custom + O_MC1 => mc1, + O_MC0 => mc0, + + O_HORIZ_DR => horiz_dr, + O_VERT_DR => vert_dr, + I_WRCTL_L => wrctl_l, + I_LTCHDO => ltchdo, + + I_SERIAL1 => '0', + I_SERIAL0 => '0', + + O_VIDEO_R => video_r, + O_VIDEO_G => video_g, + O_VIDEO_B => video_b, + O_HSYNC => hsync, + O_VSYNC => vsync, + O_FPSYNC => fpsync, + -- clks + O_CPU_ENA => cpu_ena, -- cpu clock ena + O_PIX_ENA => pix_ena, -- pixel clock ena + ENA => ENA, + CLK => CLK7 +-- CLK7 => CLK7 + ); + + u_io : entity work.BALLY_IO + port map ( + I_MXA => cpu_addr, + I_MXD => cpu_data_out, + O_MXD => mx_io, + O_MXD_OE_L => mx_io_oe_l, + + -- cpu control signals + I_M1_L => cpu_m1_l, + I_RD_L => cpu_rd_l, + I_IORQ_L => cpu_iorq_l, + I_RESET_L => I_RESET_L, + + -- no pots - student project ? :) + + -- switches + O_SWITCH => O_SWITCH_COL, + I_SWITCH => I_SWITCH_ROW, + -- audio + O_AUDIO => O_AUDIO, + + -- clks + I_CPU_ENA => cpu_ena, + ENA => ENA, + CLK => CLK7 + ); + + p_video_out : process + begin + wait until rising_edge(CLK7); + if (ENA = '1') then + O_HSYNC <= hsync; + O_VSYNC <= vsync; + O_COMP_SYNC_L <= (not vsync) and (not hsync); + + O_VIDEO_R <= video_r; + O_VIDEO_G <= video_g; + O_VIDEO_B <= video_b; + O_FPSYNC <= fpsync; + end if; + end process; + + u_rams : entity work.BALLY_RAMS + port map ( + ADDR => ma_bus, + DIN => md_bus_out, + DOUT => md_bus_in, + DOUTX => md_bus_in_x, + WE => datwr, + WE_ENA_L => daten_l, -- only used for write + ENA => ENA, + CLK => CLK7 + ); + + -- drive cas + O_CAS_ADDR <= cpu_addr(12 downto 0); + O_CAS_DATA <= cpu_data_out; + O_CAS_CS_L <= cas_cs_l; + + -- drive exp + -- all sigs should be bi-dir as exp slot devices can take control of the bus + -- this will be ok for the test cart + O_EXP_ADDR <= cpu_addr; + O_EXP_DATA <= cpu_data_out; -- not quite right, should be resolved data bus so exp slot can read customs / ram + O_EXP_M1_L <= cpu_m1_l; + O_EXP_MREQ_L <= cpu_mreq_l; + O_EXP_IORQ_L <= cpu_iorq_l; + O_EXP_WR_L <= cpu_wr_l; + O_EXP_RD_L <= cpu_rd_l; + + +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/bally_addr.vhd b/Bally - Astrocade_MiST/rtl/bally_addr.vhd new file mode 100644 index 00000000..8b865fd0 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_addr.vhd @@ -0,0 +1,473 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 004 spartan3e hires release +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_ADDR is + port ( + I_MXA : in std_logic_vector(15 downto 0); + I_MXD : in std_logic_vector( 7 downto 0); + O_MXD : out std_logic_vector( 7 downto 0); + O_MXD_OE_L : out std_logic; + + -- cpu control signals + I_RFSH_L : in std_logic; + I_M1_L : in std_logic; + I_RD_L : in std_logic; + I_MREQ_L : in std_logic; + I_IORQ_L : in std_logic; + O_WAIT_L : out std_logic; + O_INT_L : out std_logic; + + -- custom + I_HORIZ_DR : in std_logic; + I_VERT_DR : in std_logic; + O_WRCTL_L : out std_logic; -- present ram write data + O_LTCHDO : out std_logic; -- latch ram read data + + -- dram address (sram now) + O_MA : out std_logic_vector(15 downto 0); + O_RAS : out std_logic; -- for simulation + + -- misc + I_LIGHT_PEN_L : in std_logic; + + -- clks + I_CPU_ENA : in std_logic; + ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_ADDR is + -- Signals + signal mxa_t1 : std_logic_vector(15 downto 0); + signal page_03 : std_logic; + signal page_47 : std_logic; + signal page_8B : std_logic; + signal ports_10_17 : std_logic; + signal vector_read : std_logic; + signal rw : std_logic; + signal iorw : std_logic; + signal mreq_l_e1 : std_logic; + signal iorq_l_e1 : std_logic; + signal start_cpu_cyc : std_logic; + signal delay_cpu_cyc : std_logic; + signal start_cpu_cyc_late : std_logic; + signal cpu_cyc : std_logic; + signal cpu_cyc_t1 : std_logic; + signal start_io_cyc : std_logic; + signal start_io_cyc_e1 : std_logic; + signal start_io_cyc_e2 : std_logic; + signal video_cyc : std_logic; + signal video_cyc_ras : std_logic; + signal video_cyc_ras_t1 : std_logic; + + signal m1_wait : std_logic; + signal io_wait : std_logic; + signal io_wait_t1 : std_logic; + signal io_wait_t2 : std_logic; + signal ras_int : std_logic; + signal ras_int_t1 : std_logic; + signal wrctl_int : std_logic; + signal wrctl_int_t1 : std_logic; + signal ltchdo_int : std_logic; + signal ltchdo_int_t1 : std_logic; + -- + signal cs : std_logic; + signal r_hi_res : std_logic; + signal r_vert_blank : std_logic_vector(7 downto 0) := x"10"; -- line 8 (7..1) + signal r_int_fb : std_logic_vector(7 downto 0); + signal r_int_ena_mode : std_logic_vector(7 downto 0); + signal r_int_line : std_logic_vector(7 downto 0); + + -- + signal horiz_dr_t1 : std_logic; + signal h_start : boolean; + signal horiz_pos : std_logic_vector(7 downto 0) := (others => '0'); + signal vert_pos : std_logic_vector(7 downto 0) := (others => '0'); + signal horiz_eol : boolean; + signal hactv : std_logic; + signal vactv : std_logic; + -- addr gen + signal vert_addr_gen : std_logic_vector(15 downto 0); + signal vert_line_sel : std_logic; + signal addr_gen : std_logic_vector(15 downto 0); + signal addr_gen_t1 : std_logic_vector(15 downto 0); + -- + signal lightpen_int : std_logic := '0'; + signal screen_int : std_logic := '0'; + signal int_out : std_logic; + signal int_auto_clear : std_logic; + signal int_auto_clear_e1 : std_logic; +begin + + p_chip_sel : process(I_CPU_ENA, I_MXA) + begin + cs <= '0'; + if (I_CPU_ENA = '1') then -- cpu access + if (I_MXA(7 downto 4) = "0000") then + cs <= '1'; + end if; + end if; + end process; + + p_reg_write : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_RD_L = '1') and (I_IORQ_L = '0') and (I_M1_L = '1') and (cs = '1') then + case I_MXA(3 downto 0) is + when x"8" => r_hi_res <= I_MXD(0); + when x"A" => r_vert_blank <= I_MXD; + when x"D" => r_int_fb <= I_MXD; -- D int vec. 3..0 set to zero for lightpen + when x"E" => r_int_ena_mode <= I_MXD; -- E + when x"F" => r_int_line <= I_MXD; -- F + when others => null; + end case; + end if; + end if; + end process; + + p_decode_cpu : process(I_MXA, I_RFSH_L, I_M1_L, I_MREQ_L, I_IORQ_L) + begin + page_03 <= '0'; + page_47 <= '0'; + page_8B <= '0'; + ports_10_17 <= '0'; + + if (I_MXA(15 downto 14) = "00") then -- 0x0000 - 0x3FFF + --if (I_MXA(14) = '0') then -- I think magic writes alias (not in high res) + page_03 <= '1'; + end if; + + if (I_MXA(15 downto 14) = "01") then -- 0x4000 - 0x7FFF + page_47 <= '1'; + end if; + + if (I_MXA(15 downto 14) = "10") then -- 0x8000 - 0xBFFF + page_8B <= '1'; + end if; + + if (I_MXA(7 downto 5) = "000") and (I_MXA(3) = '0') then + ports_10_17 <= '1'; + end if; + + vector_read <= not I_IORQ_L and not I_M1_L; -- interrupt ack + iorw <= not I_IORQ_L and I_M1_L; + rw <= not I_MREQ_L and I_RFSH_L; + + + end process; + + -- if start ram cyc and video cyc, assert wait for a clock then kick off + -- start ram cyc a clock later + p_cyc_start : process(page_03, page_47, page_8B, rw, mreq_l_e1, iorw, iorq_l_e1, i_RD_L) + begin + start_cpu_cyc <= (page_8B and rw and mreq_l_e1) or + (page_47 and rw and mreq_l_e1) or + (page_03 and rw and mreq_l_e1 and I_RD_L); -- magic write + + start_io_cyc <= iorw and iorq_l_e1; + end process; + + p_cpu_cyc : process(start_cpu_cyc, start_cpu_cyc_late, video_cyc) + begin + cpu_cyc <= (start_cpu_cyc and not video_cyc) or start_cpu_cyc_late; + delay_cpu_cyc <= start_cpu_cyc and video_cyc; + end process; + + p_ram_control_cpu_ena : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then + start_cpu_cyc_late <= delay_cpu_cyc; + + mreq_l_e1 <= I_MREQ_L; + iorq_l_e1 <= I_IORQ_L; + + ras_int <= cpu_cyc; + wrctl_int <= cpu_cyc and I_RD_L; + ltchdo_int <= cpu_cyc and not I_RD_L; + + m1_wait <= cpu_cyc and not I_M1_L; -- extra wait for instruction fetch + + start_io_cyc_e1 <= start_io_cyc; + start_io_cyc_e2 <= start_io_cyc_e1; + + if (I_RD_L = '0') and (ports_10_17 = '1') then + io_wait <= start_io_cyc or start_io_cyc_e1 or start_io_cyc_e2; + else + io_wait <= start_io_cyc; + end if; + + end if; + end if; + end process; + + p_ram_address : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + mxa_t1 <= I_MXA; + if (video_cyc_ras_t1 = '1') then + -- video addr + if (r_hi_res = '1') then + O_MA <= addr_gen_t1(14 downto 0) & '0'; + else + O_MA <= x"0" & addr_gen_t1(11 downto 0); + end if; + else + O_MA <= mxa_t1(15 downto 0); + end if; + end if; + end process; + + p_ram_control : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + + -- wrctl same timing as RAS for write + -- in real chip I think it's backedge clocked off cpu clk. We will clock it out on clk_7 + + -- ras 0 - 3 would be decoded from top 2 addr bits + -- driven for simluation. + cpu_cyc_t1 <= cpu_cyc; + ras_int_t1 <= ras_int; + + if (video_cyc_ras_t1 = '1') then + O_RAS <= '1'; + else + if (I_RD_L = '0') then + O_RAS <= cpu_cyc_t1; -- clock early for read + else + O_RAS <= ras_int_t1; + end if; + end if; + + wrctl_int_t1 <= wrctl_int; + O_WRCTL_L <= not wrctl_int_t1; + + ltchdo_int_t1 <= ltchdo_int; + O_LTCHDO <= ltchdo_int_t1; + end if; + end process; + + p_mxd_oe : process(vector_read, r_int_fb) + begin + O_MXD <= x"00"; + O_MXD_OE_L <= '1'; + if (vector_read = '1') then + -- if light pen then set bottom 4 bits to 0 (not imp) + O_MXD <= r_int_fb; + O_MXD_OE_L <= '0'; + end if; + end process; + + -- ** our wait is 1/2 cpu cycle late as our cpu drops mreq later than a real one ** + -- two wait states if opcode fetch from ram + -- two wait states for io r/w except reads from addr 10-17 which have four wait states + -- real z80's insert one wait state automatically + O_WAIT_L <= not (cpu_cyc or delay_cpu_cyc or m1_wait or start_io_cyc or io_wait); + + -- video timing + p_start_of_line : process(I_HORIZ_DR, horiz_dr_t1) + begin + h_start <= (I_HORIZ_DR = '1') and (horiz_dr_t1 = '0'); -- rising edge + end process; + + p_active_picture : process + variable vcomp : std_logic_vector(7 downto 0); + begin + wait until rising_edge(CLK); + if (ENA = '1') then + + if (I_HORIZ_DR = '1') then + horiz_pos <= (others => '0'); + elsif (I_CPU_ENA = '1') then -- clk phi + horiz_pos <= horiz_pos + "1"; + end if; + + horiz_dr_t1 <= I_HORIZ_DR; + if (I_VERT_DR = '1') then + vert_pos <= (others => '0'); + elsif h_start then + if (vert_pos = x"ff") then + null; + else + vert_pos <= vert_pos + "1"; + end if; + end if; + + -- bit of guesswork here + horiz_eol <= false; + if (I_CPU_ENA = '1') then + if (horiz_pos = x"01") then + hactv <= '1'; + elsif (horiz_pos = x"51") then + horiz_eol <= true; + hactv <= '0'; + end if; + end if; + vcomp := r_vert_blank(7 downto 0); + -- ADDR chip does video fetch for all lines - 191 lines for boot menu, 190 displayed + --if (r_hi_res = '0') then + --vcomp(0) := '0'; + --end if; + + -- vert_pos gets reset with vert_drv and then must not wrap until the next one. + vactv <= '0'; + if (vert_pos < vcomp) then -- vcomp is x2 as bits 7..1 used + vactv <= '1'; + end if; + end if; + end process; + + p_video_cyc : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then + video_cyc <= '0'; + if (hactv = '1') and (vactv = '1') and (horiz_pos(0) = '0') then + video_cyc <= '1'; + end if; + video_cyc_ras <= video_cyc; + end if; + video_cyc_ras_t1 <= video_cyc_ras; + end if; + end process; + + p_video_addr_gen : process + variable eol : boolean; + begin + wait until rising_edge(CLK); + eol := (horiz_pos = x"60") and (I_CPU_ENA = '1'); -- not critical as long as before h_start + if (ENA = '1') then + if (I_VERT_DR = '1') then + vert_addr_gen <= (others => '0'); + vert_line_sel <= '0'; + elsif eol then + vert_line_sel <= not vert_line_sel; + if (vert_line_sel = '1') or (r_hi_res = '1') then + -- inc line early + vert_addr_gen <= vert_addr_gen + x"0028"; -- 40 decimal + end if; + end if; + + if (I_VERT_DR = '1') then + addr_gen <= (others => '0'); + elsif h_start then + addr_gen <= vert_addr_gen; -- load + elsif (video_cyc_ras = '1') and (I_CPU_ENA = '1') then + addr_gen <= addr_gen + "1"; -- inc + end if; + + addr_gen_t1 <= addr_gen; + end if; + end process; + -- + -- interrupt + -- + p_interrupt : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- r_int_ena_mode + -- bit 0 light pen mode (0 continue interrupt, 1 auto int clear at next inst) + -- bit 1 light pen interrupt enable + -- bit 2 screen mode (as 0) + -- bit 3 screen interrupt enable + + -- r_int_fb interrupt vector, set lower 4 bits to 0 for light pen interrupt + -- r_int_line interrupt on line number (7..1) low res - when completes scanning + -- int ack by iorq_l and mreq_l active together + + -- guess where the interrupt happens, lets use the clock right after active video + -- also assuming first 2 lines are line 0 ?? so writing 4 will interrupt after + -- the sixth scan line (3rd whole line) + --screen_int <= '0'; + if horiz_eol then + if (vert_pos(7 downto 0) = (r_int_line(7 downto 1) & '1')) then -- low res + screen_int <= '1'; + end if; + end if; + + if (vector_read = '1') or ((int_auto_clear_e1 = '1') and (r_int_ena_mode(2) = '1')) then + screen_int <= '0'; + end if; + + lightpen_int <= '0'; + + -- auto clear + if (I_CPU_ENA = '1') and (I_M1_L = '0') then + int_auto_clear <= int_out; + int_auto_clear_e1 <= int_auto_clear; + end if; + end if; + end process; + + p_combine_interrupts : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + int_out <= '0'; + if (r_int_ena_mode(1) = '1') then + if (lightpen_int = '1') then int_out <= '1'; end if; + end if; + + if (r_int_ena_mode(3) = '1') then + if (screen_int = '1') then int_out <= '1'; end if; + end if; + end if; + end process; + O_INT_L <= not int_out; + +end architecture RTL; + diff --git a/Bally - Astrocade_MiST/rtl/bally_check_cart.vhd b/Bally - Astrocade_MiST/rtl/bally_check_cart.vhd new file mode 100644 index 00000000..5fa046d2 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_check_cart.vhd @@ -0,0 +1,124 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_CHECK_CART is + port ( + I_EXP_ADDR : in std_logic_vector(15 downto 0); + I_EXP_DATA : in std_logic_vector( 7 downto 0); + O_EXP_DATA : out std_logic_vector( 7 downto 0); + O_EXP_OE_L : out std_logic; + + I_EXP_M1_L : in std_logic; + I_EXP_MREQ_L : in std_logic; + I_EXP_IORQ_L : in std_logic; + I_EXP_WR_L : in std_logic; + I_EXP_RD_L : in std_logic; + -- + O_CHAR_MSB : out std_logic_vector(3 downto 0); + O_CHAR_LSB : out std_logic_vector(3 downto 0); + -- + I_RESET_L : in std_logic; + ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_CHECK_CART is + + component BALLY_CHECK + port ( + CLK : in std_logic; + ADDR : in std_logic_vector(10 downto 0); + DATA : out std_logic_vector(7 downto 0) + ); + end component; + + signal dout : std_logic_vector(7 downto 0); + +begin + -- chars 0-9, a = '-', b = 'E', c = 'H', d = 'L', e = 'P', f = blank + u_rom : entity work.BALLY_CHECK + port map ( + clock => CLK, + clken => ENA, + address => I_EXP_ADDR(10 downto 0), + q => dout + ); + + p_dout : process(dout, I_EXP_ADDR) + begin + O_EXP_DATA <= dout; + -- jump direct for intercept or / xor test - the tricky one ! + --if I_EXP_ADDR = x"20c4" then O_EXP_DATA <= x"31"; end if; + --if I_EXP_ADDR = x"20c5" then O_EXP_DATA <= x"c8"; end if; + --if I_EXP_ADDR = x"20c6" then O_EXP_DATA <= x"4f"; end if; + --if I_EXP_ADDR = x"20c7" then O_EXP_DATA <= x"c3"; end if; + --if I_EXP_ADDR = x"20c8" then O_EXP_DATA <= x"c8"; end if; + --if I_EXP_ADDR = x"20c9" then O_EXP_DATA <= x"21"; end if; + end process; + + p_cs : process(I_EXP_ADDR, I_EXP_RD_L, I_EXP_MREQ_L) + begin + O_EXP_OE_L <= '1'; + if (I_EXP_RD_L = '0') and (I_EXP_MREQ_L = '0') and (I_EXP_ADDR(14 downto 13) = "01") then + O_EXP_OE_L <= '0'; + end if; + end process; + + p_latch : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_EXP_ADDR(7 downto 4) = "1111") and (I_EXP_IORQ_L = '0') and (I_EXP_M1_L = '1') then + O_CHAR_MSB <= I_EXP_DATA(7 downto 4); + O_CHAR_LSB <= I_EXP_DATA(3 downto 0); + end if; + end if; + end process; + +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/bally_col_pal.vhd b/Bally - Astrocade_MiST/rtl/bally_col_pal.vhd new file mode 100644 index 00000000..e627943d --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_col_pal.vhd @@ -0,0 +1,101 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity BALLY_COL_PAL is + port ( + ADDR : in std_logic_vector(7 downto 0); + DATA : out std_logic_vector(11 downto 0) + ); +end; + +architecture RTL of BALLY_COL_PAL is + + type ROM_ARRAY is array(0 to 255) of std_logic_vector(11 downto 0); + constant ROM : ROM_ARRAY := ( + x"000", x"222", x"444", x"666", x"999", x"BBB", x"DDD", x"FFF", + x"20B", x"40E", x"61F", x"93F", x"B5F", x"D7F", x"FAF", x"FCF", + x"40B", x"60D", x"90F", x"B2F", x"D4F", x"F6F", x"F9F", x"FBF", + x"609", x"80C", x"B0E", x"D1F", x"F3F", x"F6F", x"F8F", x"FAF", + x"808", x"A0A", x"D0D", x"F0F", x"F3F", x"F5F", x"F7F", x"F9F", + x"906", x"C08", x"E0B", x"F0D", x"F2F", x"F5F", x"F7F", x"F9F", + x"B04", x"D06", x"F09", x"F0B", x"F2D", x"F4F", x"F7F", x"F9F", + x"B02", x"E04", x"F06", x"F09", x"F2B", x"F4D", x"F7F", x"F9F", + x"B00", x"E02", x"F04", x"F06", x"F39", x"F5B", x"F7D", x"F9F", + x"B00", x"E00", x"F02", x"F14", x"F36", x"F59", x"F8B", x"FAD", + x"B00", x"D00", x"F00", x"F22", x"F44", x"F66", x"F89", x"FBB", + x"900", x"C00", x"E00", x"F30", x"F52", x"F74", x"F97", x"FC9", + x"800", x"A00", x"D10", x"F40", x"F60", x"F82", x"FA5", x"FD7", + x"600", x"800", x"B30", x"D50", x"F70", x"F91", x"FC3", x"FE5", + x"400", x"620", x"940", x"B60", x"D80", x"FB0", x"FD2", x"FF4", + x"210", x"430", x"650", x"970", x"BA0", x"DC0", x"FE1", x"FF4", + x"020", x"240", x"460", x"690", x"9B0", x"BD0", x"DF1", x"FF3", + x"030", x"050", x"280", x"4A0", x"6C0", x"9E0", x"BF1", x"DF4", + x"040", x"060", x"090", x"2B0", x"4D0", x"6F0", x"9F2", x"BF4", + x"050", x"070", x"090", x"0C0", x"2E0", x"4F1", x"7F3", x"9F5", + x"050", x"080", x"0A0", x"0C0", x"0F0", x"2F2", x"5F5", x"7F7", + x"060", x"080", x"0A0", x"0D0", x"0F2", x"1F4", x"3F7", x"5F9", + x"060", x"080", x"0B0", x"0D2", x"0F4", x"0F6", x"2F9", x"4FB", + x"060", x"080", x"0A2", x"0D4", x"0F6", x"0F9", x"1FB", x"4FD", + x"060", x"082", x"0A4", x"0C6", x"0F9", x"0FB", x"1FD", x"3FF", + x"052", x"074", x"0A6", x"0C9", x"0EB", x"0FD", x"1FF", x"4FF", + x"044", x"076", x"099", x"0BB", x"0DD", x"0FF", x"2FF", x"4FF", + x"036", x"068", x"08B", x"0AD", x"0CF", x"1FF", x"3FF", x"5FF", + x"028", x"04A", x"07D", x"09F", x"0BF", x"2EF", x"5FF", x"7FF", + x"019", x"03C", x"06E", x"08F", x"2AF", x"4CF", x"7FF", x"9FF", + x"00B", x"02D", x"04F", x"27F", x"49F", x"6BF", x"9DF", x"BFF", + x"00B", x"01E", x"23F", x"45F", x"68F", x"9AF", x"BCF", x"DEF" + ); + +begin + + p_rom : process(ADDR) + begin + DATA <= ROM(to_integer(unsigned(ADDR))); + end process; + +end RTL; + diff --git a/Bally - Astrocade_MiST/rtl/bally_data.vhd b/Bally - Astrocade_MiST/rtl/bally_data.vhd new file mode 100644 index 00000000..2ecafdad --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_data.vhd @@ -0,0 +1,1039 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 004 spartan3e hires release +-- version 003 spartan3e release +-- version 001 initial release +-- +-- microcycler not used +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_DATA is + port ( + I_MXA : in std_logic_vector(15 downto 0); + I_MXD : in std_logic_vector( 7 downto 0); + O_MXD : out std_logic_vector( 7 downto 0); + O_MXD_OE_L : out std_logic; + + -- cpu control signals + I_M1_L : in std_logic; + I_RD_L : in std_logic; + I_MREQ_L : in std_logic; + I_IORQ_L : in std_logic; + + -- memory + O_DATEN_L : out std_logic; -- looks like the real chip + O_DATWR : out std_logic; -- ram ena to fake up write at rising edge of DATEN_L + I_MDX : in std_logic_vector( 7 downto 0); -- upper 8 bits for high res + I_MD : in std_logic_vector( 7 downto 0); + O_MD : out std_logic_vector( 7 downto 0); + O_MD_OE_L : out std_logic; + -- custom + O_MC1 : out std_logic; + O_MC0 : out std_logic; + + O_HORIZ_DR : out std_logic; + O_VERT_DR : out std_logic; + I_WRCTL_L : in std_logic; + I_LTCHDO : in std_logic; + + I_SERIAL1 : in std_logic; + I_SERIAL0 : in std_logic; + + O_VIDEO_R : out std_logic_vector(3 downto 0); + O_VIDEO_G : out std_logic_vector(3 downto 0); + O_VIDEO_B : out std_logic_vector(3 downto 0); + O_HSYNC : out std_logic; + O_VSYNC : out std_logic; + O_FPSYNC : out std_logic; -- first active pixel + + -- clks + O_CPU_ENA : out std_logic; -- cpu clock ena + O_PIX_ENA : out std_logic; -- pixel clock ena + ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_DATA is + + -- const + -- horizontal timing constants + -- approx 78 clocks blanking,34 for sync + + -- original 7.159 Mhz clock + constant H_LINE_SYNCS : std_logic_vector(8 downto 0) := conv_std_logic_vector( 0,9); + constant H_LINE_SYNCR : std_logic_vector(8 downto 0) := conv_std_logic_vector( 33,9); + constant H_BLANK_N1S : std_logic_vector(8 downto 0) := conv_std_logic_vector( 0,9); -- first eq + constant H_BLANK_N1R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 16,9); + constant H_BLANK_N2S : std_logic_vector(8 downto 0) := conv_std_logic_vector(227,9); -- second eq + constant H_BLANK_N2R : std_logic_vector(8 downto 0) := conv_std_logic_vector(243,9); + constant H_BLANK_B1S : std_logic_vector(8 downto 0) := conv_std_logic_vector( 0,9); -- first broad + constant H_BLANK_B1R : std_logic_vector(8 downto 0) := conv_std_logic_vector(193,9); + constant H_BLANK_B2S : std_logic_vector(8 downto 0) := conv_std_logic_vector(227,9); -- second broad + constant H_BLANK_B2R : std_logic_vector(8 downto 0) := conv_std_logic_vector(421,9); + constant H_BLANK_S : std_logic_vector(8 downto 0) := conv_std_logic_vector(444,9); -- horiz blanking + constant H_BLANK_R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 67,9); -- 78 clocks, starting 12 before sync + + constant H_BLANK_LR : std_logic_vector(8 downto 0) := conv_std_logic_vector(245,9); -- half line left reset + constant H_BLANK_RS : std_logic_vector(8 downto 0) := conv_std_logic_vector(225,9); -- half line right set + + --constant H_DRIVE_S : std_logic_vector(8 downto 0) := conv_std_logic_vector( 60,9); -- hdrive pulse + --constant H_DRIVE_R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 63,9); + --constant H_VDRIVE_R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 71,9); + -- frig to get screen centered, above numbers are measured + constant H_DRIVE_S : std_logic_vector(8 downto 0) := conv_std_logic_vector( 60+8,9); -- hdrive pulse + constant H_DRIVE_R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 63+8,9); + constant H_VDRIVE_R : std_logic_vector(8 downto 0) := conv_std_logic_vector( 71+8,9); + + constant H_LEN : std_logic_vector(8 downto 0) := conv_std_logic_vector(454,9); -- line length (455 clocks) + constant V_LEN : std_logic_vector(10 downto 0) := conv_std_logic_vector(525,11); -- frame length + + component BALLY_COL_PAL + port ( + ADDR : in std_logic_vector(7 downto 0); + DATA : out std_logic_vector(11 downto 0) + ); + end component; + + -- Signals + type array_8x8 is array (0 to 7) of std_logic_vector(7 downto 0); + type array_bool8 is array (0 to 7) of boolean; + + signal ena_cnt : std_logic_vector(1 downto 0) := "00"; + signal cpu_ena : std_logic; + signal cpu_ena_t1 : std_logic; + signal pix_ena : std_logic; + signal pix_load : std_logic; + signal cs_w : std_logic; + signal cs_r : std_logic; + -- cpu if + signal col_ld : array_bool8; + signal magic_ld : boolean; + signal r_col : array_8x8 := (x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00"); + signal r_hi_res : std_logic; + signal r_backgnd_col : std_logic_vector(1 downto 0) := "00"; + signal r_horiz_pos : std_logic_vector(5 downto 0) := "010100"; -- 20 + signal r_vert_blank : std_logic_vector(7 downto 0) := x"10"; -- line 8 (7..1) + --signal r_vert_blank : std_logic_vector(7 downto 0) := x"BF"; -- line 191 (7..1) + signal r_magic : std_logic_vector(7 downto 0) := x"00"; + signal r_expand : std_logic_vector(7 downto 0) := x"00"; + signal r_intercept : std_logic_vector(7 downto 0) := x"00"; + -- timing + signal do_horiz_dr : std_logic; + signal do_horiz_dr_t1 : std_logic; + signal do_vert_dr : std_logic; + signal do_vert_dr_int : std_logic; + signal hsync : std_logic; + signal vsync : std_logic := '0'; + signal vsync_t1 : std_logic; + signal v_1st_actv : std_logic; + + signal h_count : std_logic_vector ( 8 downto 0) := (others => '0'); + signal v_count : std_logic_vector (10 downto 0) := "00000000001"; + signal sg_line_sync : std_logic; + signal sg_blank_n1 : std_logic; + signal sg_blank_n2 : std_logic; + signal sg_blank_b1 : std_logic; + signal sg_blank_b2 : std_logic; + signal sg_hstart : std_logic; + signal sg_hstart_t1 : std_logic; + signal sg_hblank : std_logic; + signal sg_hblank_l : std_logic; + signal sg_hblank_r : std_logic; + signal sg_vblank : std_logic; + signal sg_vstart : std_logic; + -- + signal sg_blanking_EQ : std_logic; + signal sg_blanking_BRD : std_logic; + signal sg_line263 : std_logic; + signal sg_line266 : std_logic; + signal sg_line269 : std_logic; + signal sg_line272 : std_logic; + signal sg_line283 : std_logic; + signal sg_sync : std_logic; + signal sg_blank : std_logic; + signal sg_neg_sync : std_logic; + + -- + signal horiz_pos : std_logic_vector(7 downto 0); + signal vert_pos : std_logic_vector(7 downto 0); + signal hactv : std_logic; + signal vactv : std_logic; + + -- data + signal ram_write_reg : std_logic_vector(7 downto 0); + signal datwr : std_logic; + signal ltchdo_t1 : std_logic; + signal mxd_out_ena : std_logic; + signal mxd_out_intercept : std_logic; + signal mxd_out_intercept_e1 : std_logic; + -- video + signal video_cyc : std_logic; + signal video_cyc_ras : std_logic; + signal video_cyc_ras_t1 : std_logic; + signal video_cyc_ras_t2 : std_logic; + signal video_shifter : std_logic_vector(15 downto 0); + signal video_shifter_lflag : std_logic; + signal video_shifter_actv : std_logic; + + signal lflag : std_logic; -- left flag + signal lflag_inhib : std_logic; + signal lflag_e : std_logic_vector(2 downto 0); + signal hactv_e : std_logic_vector(2 downto 0); + signal col_in : std_logic_vector(7 downto 0); + signal col_out : std_logic_vector(11 downto 0); + -- datapath + signal done_magic_write : std_ulogic; + signal done_magic_write_t1 : std_ulogic; + signal expand_lower_sel : std_logic; + + signal expand_out : std_logic_vector(7 downto 0); + signal flopper_out : std_logic_vector(7 downto 0); + signal pixel_collide : std_logic_vector(3 downto 0); + + signal shifter_out : std_logic_vector(13 downto 0); + signal shifter_out_reg : std_logic_vector(5 downto 0); + + signal rotate_cnt : std_logic_vector(2 downto 0); + signal rotate_inhibit_write : std_logic; + signal rotate_pixa : std_logic_vector(7 downto 0) := (others => '0'); + signal rotate_pixb : std_logic_vector(7 downto 0) := (others => '0'); + signal rotate_pixc : std_logic_vector(7 downto 0) := (others => '0'); + signal rotate_pixd : std_logic_vector(7 downto 0) := (others => '0'); + signal rotate_out : std_logic_vector(7 downto 0); + signal magic_final : std_logic_vector(7 downto 0); + signal ram_ip_reg : std_logic_vector(7 downto 0); + signal ram_op_reg : std_logic_vector(7 downto 0); + +begin + + p_chip_sel : process(cpu_ena, I_MXA) + begin + cs_w <= '0'; + cs_r <= '0'; + if (cpu_ena = '1') then -- cpu access + if (I_MXA(7 downto 5) = "000") then + cs_w <= '1'; + end if; + end if; + if (I_MXA(7 downto 4) = "0000") then + cs_r <= '1'; + end if; + + end process; + + -- + -- registers + -- + p_reg_write : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_RD_L = '1') and (I_IORQ_L = '0') and (I_M1_L = '1') and (cs_w = '1') then + case I_MXA(4 downto 0) is + when "01000" => r_hi_res <= I_MXD(0); -- 8 + when "01001" => r_backgnd_col <= I_MXD(7 downto 6); -- 9 + r_horiz_pos <= I_MXD(5 downto 0); + when "01010" => r_vert_blank <= I_MXD; -- A + -- B + when "01100" => r_magic <= I_MXD; -- C + when "11001" => r_expand <= I_MXD; -- 19 + + when others => null; + end case; + end if; + end if; + end process; + + p_reg_write_blk_decode : process(I_RD_L, I_M1_L, I_IORQ_L, cs_w, I_MXA) + begin + -- these writes will last for several cpu_ena cycles, so you + -- will get several load pulses + col_ld <= (others => false); + magic_ld <= false; + if (I_RD_L = '1') and (I_IORQ_L = '0') and (I_M1_L = '1') and (cs_w = '1') and (I_MXA(4) = '0') then + col_ld(0) <= ( I_MXA( 3 downto 0) = x"0") or + ((I_MXA(10 downto 8) = "000") and (I_MXA(3 downto 0) = x"B")); + + col_ld(1) <= ( I_MXA( 3 downto 0) = x"1") or + ((I_MXA(10 downto 8) = "001") and (I_MXA(3 downto 0) = x"B")); + + col_ld(2) <= ( I_MXA( 3 downto 0) = x"2") or + ((I_MXA(10 downto 8) = "010") and (I_MXA(3 downto 0) = x"B")); + + col_ld(3) <= ( I_MXA( 3 downto 0) = x"3") or + ((I_MXA(10 downto 8) = "011") and (I_MXA(3 downto 0) = x"B")); + + col_ld(4) <= ( I_MXA( 3 downto 0) = x"4") or + ((I_MXA(10 downto 8) = "100") and (I_MXA(3 downto 0) = x"B")); + + col_ld(5) <= ( I_MXA( 3 downto 0) = x"5") or + ((I_MXA(10 downto 8) = "101") and (I_MXA(3 downto 0) = x"B")); + + col_ld(6) <= ( I_MXA( 3 downto 0) = x"6") or + ((I_MXA(10 downto 8) = "110") and (I_MXA(3 downto 0) = x"B")); + + col_ld(7) <= ( I_MXA( 3 downto 0) = x"7") or + ((I_MXA(10 downto 8) = "111") and (I_MXA(3 downto 0) = x"B")); + + magic_ld <= ( I_MXA( 3 downto 0) = x"C"); + end if; + end process; + + p_reg_write_blk : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + for i in 0 to 7 loop + if col_ld(i) then r_col(i) <= I_MXD; end if; + end loop; + end if; + end process; + + p_cpu_ena : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (do_horiz_dr = '1') then -- 3 clocks long + ena_cnt <= "00"; + else + ena_cnt <= ena_cnt + "1"; + end if; + + cpu_ena <= '0'; + if (ena_cnt = "10") then + cpu_ena <= '1'; + end if; + + if (r_hi_res = '1') then + pix_ena <= '1'; + else + pix_ena <= ena_cnt(0); + end if; + pix_load <= cpu_ena; + end if; + end process; + O_CPU_ENA <= cpu_ena; + O_PIX_ENA <= pix_ena; + + p_micro_gen : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- not used + O_MC1 <= '0'; + O_MC0 <= '0'; + end if; + end process; + -- + -- sync generation + -- + p_hv_count : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (h_count = H_LEN) then + h_count <= (others => '0'); + if (v_count = V_LEN) then + v_count <= "00000000001"; + else + v_count <= v_count + "1"; + end if; + else + h_count <= h_count + "1"; + end if; + end if; + end process; + + p_window_h : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- hblank + sg_hstart <= '0'; + if (h_count = H_BLANK_S) then + sg_hblank <= '1'; + elsif h_count = H_BLANK_R then + sg_hstart <= '1'; + sg_hblank <= '0'; + end if; + + if (h_count = H_BLANK_S) then + sg_hblank_l <= '1'; + elsif h_count = H_BLANK_LR then + sg_hblank_l <= '0'; + end if; + + if (h_count = H_BLANK_RS) then + sg_hblank_r <= '1'; + elsif h_count = H_BLANK_R then + sg_hblank_r <= '0'; + end if; + + if (h_count = H_DRIVE_S) then + do_horiz_dr <= '1'; + elsif h_count = H_DRIVE_R then + do_horiz_dr <= '0'; + end if; + + if (h_count = H_DRIVE_S) then + do_vert_dr <= '1'; + elsif h_count = H_VDRIVE_R then + do_vert_dr <= '0'; + end if; + + -- low res 40 bytes / line (160 pixels, 2 bits per pixel) + -- vert res 102 lines + -- two clocks / pixel + end if; + end process; + + p_sync_h : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- negative sync pulse + if (h_count = H_LINE_SYNCS) then + sg_line_sync <= '1'; + elsif h_count = H_LINE_SYNCR then + sg_line_sync <= '0'; + end if; + + -- blanking narrow1 + if (h_count = H_BLANK_N1S) then + sg_blank_n1 <= '1'; + elsif h_count = H_BLANK_N1R then + sg_blank_n1 <= '0'; + end if; + + -- blanking narrow2 + if (h_count = H_BLANK_N2S) then + sg_blank_n2 <= '1'; + elsif (h_count = H_BLANK_N2R) then + sg_blank_n2 <= '0'; + end if; + + -- blanking broad1 + if (h_count = H_BLANK_B1S) then + sg_blank_b1 <= '1'; + elsif (h_count = H_BLANK_B1R) then + sg_blank_b1 <= '0'; + end if; + + -- blanking broad2 + if h_count = H_BLANK_B2S then + sg_blank_b2 <= '1'; + elsif (h_count = H_BLANK_B2R) then + sg_blank_b2 <= '0'; + end if; + end if; + end process; + + p_window_v : process + begin + wait until rising_edge(CLK); + -- line 21 first f1 nonblanked video line ** bally chip starts at 20 with a half line + -- line 44 first f1 video line + -- line 234 last f1 video line (power up menu) + -- line 263 last f1 nonblanked video line (half line) + + -- line 283 first f2 nonblanked video line (half line) + -- line 307 first f2 video line (power up menu) + -- line 497 last f2 video line + -- line 525 last f2 nonblanked video line + + -- (vblank reg is written as 191 for boot menu) + -- there are 191 active video lines read from the video store per field (when displaying menu) + -- The bally data chip seems to get the half lines wrong however (283 whole line) + -- and it puts a half line on 20. Or, I've missread the field sync pulses. + -- doesn't really matter as we are driving a vga screen for now .. + + -- 14.2857MHz (7.1428) + -- line / 455 = 15.698 K = 29.9 frames + if (ENA = '1') then + + sg_vstart <= '0'; + if (v_count = conv_std_logic_vector( 21,11)) then + sg_vblank <= '0'; + sg_vstart <= '1'; -- field one sync to scan converter + elsif (v_count = conv_std_logic_vector( 264,11)) then + sg_vblank <= '1'; + elsif (v_count = conv_std_logic_vector( 283,11)) then + sg_vblank <= '0'; + elsif (v_count = conv_std_logic_vector( 1,11)) then + sg_vblank <= '1'; + end if; + + if (v_count = conv_std_logic_vector( 4,11)) then + vsync <= '1'; + elsif (v_count = conv_std_logic_vector( 7,11)) then + vsync <= '0'; + elsif (v_count = conv_std_logic_vector( 267,11)) then + vsync <= '1'; + elsif (v_count = conv_std_logic_vector( 270,11)) then + vsync <= '0'; + end if; + + v_1st_actv <= '0'; + if (v_count = conv_std_logic_vector( 44,11)) or + (v_count = conv_std_logic_vector( 307,11)) then + v_1st_actv <= '1'; + end if; + -- timing from rising edge of v_sync + -- 4 21 263 + -- 1 18 260 + + -- 267 283 525 + -- 1 17 259 + + -- so field 2 is displayed above field 1 - this is the same as ntsc and seems + -- to be necessary to get a correct picture on my monitor taking it's sync from vsync + end if; + end process; + + p_sync_v : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + sg_blanking_eq <= '0'; + if ( (v_count = conv_std_logic_vector( 1,11)) or + (v_count = conv_std_logic_vector( 2,11)) or + (v_count = conv_std_logic_vector( 3,11)) or + (v_count = conv_std_logic_vector( 7,11)) or + (v_count = conv_std_logic_vector( 8,11)) or + (v_count = conv_std_logic_vector( 9,11)) or + (v_count = conv_std_logic_vector(264,11)) or + (v_count = conv_std_logic_vector(265,11)) or + (v_count = conv_std_logic_vector(270,11)) or + (v_count = conv_std_logic_vector(271,11)) ) then + sg_blanking_eq <= '1'; + end if; + + sg_blanking_brd <= '0'; + if ( (v_count = conv_std_logic_vector( 4,11)) or + (v_count = conv_std_logic_vector( 5,11)) or + (v_count = conv_std_logic_vector( 6,11)) or + (v_count = conv_std_logic_vector(267,11)) or + (v_count = conv_std_logic_vector(268,11)) ) then + sg_blanking_brd <= '1'; + end if; + + sg_line263 <= '0'; + if (v_count = (conv_std_logic_vector(263,11))) then + sg_line263 <= '1'; + end if; + + sg_line266 <= '0'; + if (v_count = (conv_std_logic_vector(266,11))) then + sg_line266 <= '1'; + end if; + + sg_line269 <= '0'; + if (v_count = (conv_std_logic_vector(269,11))) then + sg_line269 <= '1'; + end if; + + sg_line272 <= '0'; + if (v_count = (conv_std_logic_vector(272,11))) then + sg_line272 <= '1'; + end if; + + sg_line283 <= '0'; + if (v_count = (conv_std_logic_vector(283,11))) then + sg_line283 <= '1'; + end if; + end if; + end process; + + p_syncgen : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + sg_sync <= '0'; + + if (sg_blanking_eq = '1') then + sg_sync <= sg_blank_n1 or sg_blank_n2; + + elsif (sg_blanking_brd = '1') then + sg_sync <= sg_blank_b1 or sg_blank_b2; + + elsif (sg_line263 = '1') then + sg_sync <= sg_blank_n2 or sg_line_sync; + + elsif (sg_line266 = '1') then + sg_sync <= sg_blank_n1 or sg_blank_b2; + + elsif (sg_line269 = '1') then + sg_sync <= sg_blank_b1 or sg_blank_n2; + + elsif (sg_line272 = '1') then + sg_sync <= sg_blank_n1; + + else + sg_sync <= sg_line_sync; -- normal line. + end if; + + sg_blank <= sg_hblank or sg_vblank; + if (sg_line263 = '1') then + sg_blank <= sg_hblank_r; -- left half line + elsif (sg_line283 = '1') then + sg_blank <= sg_hblank_l; -- right half line + end if; + + hsync <= sg_line_sync; + vsync_t1 <= vsync; + end if; + end process; + + -- code duplicated in addr chip + p_active_picture : process + variable vcomp : std_logic_vector(7 downto 0); + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (do_horiz_dr = '1') then + horiz_pos <= (others => '0'); + elsif (cpu_ena = '1') then -- clk phi + horiz_pos <= horiz_pos + "1"; + end if; + + do_horiz_dr_t1 <= do_horiz_dr; + if (do_vert_dr_int = '1') then + vert_pos <= (others => '0'); + elsif (do_horiz_dr = '1') and (do_horiz_dr_t1 = '0') then -- rising edge + if (vert_pos = x"ff") then + null; + else + vert_pos <= vert_pos + "1"; + end if; + end if; + + -- bit of guesswork here + if (cpu_ena = '1') then + if (horiz_pos = x"01") then + hactv <= '1'; + elsif (horiz_pos = x"51") then + hactv <= '0'; + end if; + end if; + vcomp := r_vert_blank(7 downto 0); + -- DATA chip does line pairs only in low res mode + if (r_hi_res = '0') then + vcomp(0) := '0'; + end if; + + vactv <= '0'; + if (vert_pos < vcomp) then + vactv <= '1'; + end if; + end if; + end process; + + p_video_cyc : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (cpu_ena = '1') then + video_cyc <= '0'; + if (hactv = '1') and (vactv = '1') and (horiz_pos(0) = '0') then + video_cyc <= '1'; + end if; + video_cyc_ras <= video_cyc; + end if; + video_cyc_ras_t1 <= video_cyc_ras; + video_cyc_ras_t2 <= video_cyc_ras_t1; -- match delay to rams + end if; + end process; + + p_left_flag : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- apparently horiz_pos 40 or above do not have any effect + if (do_horiz_dr = '1') then + lflag_inhib <= '0'; + elsif (cpu_ena = '1') and (horiz_pos(6 downto 0) = ("1001111")) then + lflag_inhib <= '1'; + end if; + + if (do_horiz_dr = '1') then + lflag <= '1'; + elsif (cpu_ena = '1') and (horiz_pos(6 downto 0) = (r_horiz_pos & '1')) and (lflag_inhib = '0') then + lflag <= '0'; + end if; + + -- pipeline delay + if (do_horiz_dr = '1') then + lflag_e <= "111"; + hactv_e <= "000"; + + elsif (cpu_ena = '1') then + lflag_e(0) <= lflag; + lflag_e(2 downto 1) <= lflag_e(1 downto 0); + hactv_e(0) <= hactv; + hactv_e(2 downto 1) <= hactv_e(1 downto 0); + end if; + end if; + end process; + + p_video_shifter : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- video cyc, grab from ram + if (pix_ena = '1') then + if (pix_load = '1') and (video_cyc_ras_t2 = '1') then + video_shifter <= I_MD(7 downto 0) & I_MDX(7 downto 0); + else + -- top left pixel is bits 7,6 + video_shifter <= video_shifter(13 downto 0) & "00"; + end if; + + end if; + + if (do_horiz_dr = '1') then + video_shifter_lflag <= '1'; + video_shifter_actv <= '0'; -- background col + elsif (pix_ena = '1') and (pix_load = '1') then + video_shifter_lflag <= lflag_e(2); + video_shifter_actv <= hactv_e(2) and vactv; + end if; + end if; + end process; + + p_col_sel : process(video_shifter, video_shifter_lflag, video_shifter_actv, + r_col, r_backgnd_col) + variable sel : std_logic_vector(2 downto 0); + begin + if (video_shifter_actv = '0') then + sel := video_shifter_lflag & r_backgnd_col; + else + sel := video_shifter_lflag & video_shifter(7+8 downto 6+8); + end if; + + col_in <= (others => '0'); + case sel is + when "000" => col_in <= r_col(0); + when "001" => col_in <= r_col(1); + when "010" => col_in <= r_col(2); + when "011" => col_in <= r_col(3); + when "100" => col_in <= r_col(4); + when "101" => col_in <= r_col(5); + when "110" => col_in <= r_col(6); + when "111" => col_in <= r_col(7); + when others => null; + end case; + end process; + + u_col : entity work.BALLY_COL_PAL + port map ( + ADDR => col_in, + DATA => col_out + ); + + p_video_out : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + sg_neg_sync <= not sg_sync; + O_HSYNC <= hsync; + O_VSYNC <= vsync_t1; + + if (sg_blank = '1') then + O_VIDEO_R <= "0000"; + O_VIDEO_G <= "0000"; + O_VIDEO_B <= "0000"; + else + O_VIDEO_R <= col_out(11 downto 8); + O_VIDEO_G <= col_out( 7 downto 4); + O_VIDEO_B <= col_out( 3 downto 0); + end if; + do_vert_dr_int <= v_1st_actv and do_vert_dr; + sg_hstart_t1 <= sg_hstart; + O_FPSYNC <= sg_hstart_t1 and sg_vstart; + end if; + end process; + O_VERT_DR <= do_vert_dr_int; + O_HORIZ_DR <= do_horiz_dr; + -- + -- data path + -- + p_ramin : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + ram_write_reg <= I_MXD; + + done_magic_write <= '0'; + if (I_WRCTL_L = '0') and (I_MXA(15 downto 14) = "00") and (cpu_ena = '1') then + done_magic_write <= '1'; + end if; + done_magic_write_t1 <= done_magic_write; -- make sure we have finished ram write + end if; + end process; + + p_expand : process(ram_write_reg, r_magic, r_expand, expand_lower_sel) + variable expand_sel : std_logic_vector(3 downto 0); + begin + if (expand_lower_sel = '1') then -- reg cleared by magic, upper when 0 + expand_sel := ram_write_reg(3 downto 0); + else + expand_sel := ram_write_reg(7 downto 4); + end if; + + if (r_magic(3) = '0') then -- bypass + expand_out <= ram_write_reg; + else + for i in 0 to 3 loop + if (expand_sel(i) = '0') then + expand_out((i*2)+1 downto i*2) <= r_expand(1 downto 0); + else + expand_out((i*2)+1 downto i*2) <= r_expand(3 downto 2); + end if; + end loop; + end if; + end process; + + p_rotate_reg : process + variable shift : std_logic; + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if magic_ld then + rotate_cnt <= "000"; + expand_lower_sel <= '0'; + shifter_out_reg <= (others => '0'); + elsif (done_magic_write_t1 = '1') then + rotate_cnt <= rotate_cnt + "1"; + expand_lower_sel <= not expand_lower_sel; + shifter_out_reg <= shifter_out(5 downto 0); + end if; + + rotate_inhibit_write <= '0'; + shift := '0'; + if (I_MXA(15 downto 14) = "00") then + if (rotate_cnt(2) = '0') then + rotate_inhibit_write <= r_magic(2); -- only if using rotate + if (cpu_ena = '1') and (I_WRCTL_L = '0') then + shift := '1'; + end if; + end if; + end if; + + if (shift = '1') then + rotate_pixa <= expand_out(7 downto 6) & rotate_pixa(7 downto 2); -- top + rotate_pixb <= expand_out(5 downto 4) & rotate_pixb(7 downto 2); + rotate_pixc <= expand_out(3 downto 2) & rotate_pixc(7 downto 2); + rotate_pixd <= expand_out(1 downto 0) & rotate_pixd(7 downto 2); + end if; + end if; + end process; + + p_rotate_shifter : process(expand_out, shifter_out_reg, r_magic, + rotate_cnt, rotate_pixa, rotate_pixb, rotate_pixc, rotate_pixd) + begin + -- r_magic bits 1,0 + shifter_out <= (others => '0'); -- default + case r_magic(1 downto 0) is + when "00" => shifter_out <= expand_out(7 downto 0) & "000000"; + when "01" => shifter_out <= shifter_out_reg(5 downto 4) & expand_out(7 downto 0) & "0000" ; + when "10" => shifter_out <= shifter_out_reg(5 downto 2) & expand_out(7 downto 0) & "00" ; + when "11" => shifter_out <= shifter_out_reg(5 downto 0) & expand_out(7 downto 0); + when others => null; + end case; + + rotate_out <= (others => '0'); -- default + case rotate_cnt(1 downto 0) is + when "00" => rotate_out <= rotate_pixa; + when "01" => rotate_out <= rotate_pixb; + when "10" => rotate_out <= rotate_pixc; + when "11" => rotate_out <= rotate_pixd; + when others => null; + end case; + end process; + + p_flopper : process(shifter_out, rotate_out, r_magic) + variable flopper_src : std_logic_vector(7 downto 0); + begin + if (r_magic(2) = '0') then -- rotate bypass + flopper_src := shifter_out(13 downto 6); + else + flopper_src := rotate_out; + end if; + + if (r_magic(6) = '0') then -- flopper bypass + flopper_out <= flopper_src; + else + flopper_out(7 downto 6) <= flopper_src(1 downto 0); + flopper_out(5 downto 4) <= flopper_src(3 downto 2); + flopper_out(3 downto 2) <= flopper_src(5 downto 4); + flopper_out(1 downto 0) <= flopper_src(7 downto 6); + end if; + end process; + + p_or_xor : process(flopper_out, ram_ip_reg, r_magic) + variable result_or : std_logic_vector(7 downto 0); + variable result_xor : std_logic_vector(7 downto 0); + begin + result_or := flopper_out or ram_ip_reg; + result_xor := flopper_out xor ram_ip_reg; + + magic_final <= (others => '0'); + case r_magic(5 downto 4) is + when "00" => magic_final <= flopper_out; -- none + when "01" => magic_final <= result_or; -- or + when "10" => magic_final <= result_xor; -- xor + when "11" => magic_final <= result_xor; -- xor and or + when others => null; + end case; + end process; + + p_intercept : process(flopper_out, ram_ip_reg) + begin + pixel_collide <= (others => '0'); + for i in 0 to 3 loop + if (flopper_out((i*2)+1 downto (i*2)) /= "00") and + (ram_ip_reg((i*2)+1 downto (i*2)) /= "00") then + pixel_collide(i) <= '1'; + end if; + end loop; + + end process; + + p_intercept_reg : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (cpu_ena = '1') then + mxd_out_intercept_e1 <= mxd_out_intercept; + end if; + + -- reset + if (mxd_out_intercept = '0') and (mxd_out_intercept_e1 = '1') and (cpu_ena = '1') then -- end of read + r_intercept(3 downto 0) <= "0000"; + elsif (datwr = '1') and (I_MXA(15 downto 14) = "00") and (rotate_inhibit_write = '0') then + -- write + if (r_magic(5) = '1') or (r_magic(4) = '1') then -- or/xor write only + r_intercept(0) <= r_intercept(0) or pixel_collide(3); + r_intercept(1) <= r_intercept(1) or pixel_collide(2); + r_intercept(2) <= r_intercept(2) or pixel_collide(1); + r_intercept(3) <= r_intercept(3) or pixel_collide(0); + + r_intercept(4) <= pixel_collide(3); + r_intercept(5) <= pixel_collide(2); + r_intercept(6) <= pixel_collide(1); + r_intercept(7) <= pixel_collide(0); + end if; + end if; + end if; + end process; + + p_output_reg : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (cpu_ena = '1') then + ltchdo_t1 <= I_LTCHDO; + ram_ip_reg <= I_MD(7 downto 0); -- used for or / xor + end if; + + if (I_MXA(15 downto 14) = "00") then -- magic write + ram_op_reg <= magic_final; + else + ram_op_reg <= ram_write_reg; + end if; + + cpu_ena_t1 <= cpu_ena; + datwr <= cpu_ena_t1 and (not I_WRCTL_L); + end if; + end process; + O_DATWR <= datwr; + -- ram out + + p_ramout : process(I_WRCTL_L, ram_op_reg, rotate_inhibit_write) + begin + O_MD_OE_L <= '1'; + O_DATEN_L <= '1'; + O_MD <= (others => 'X'); -- debug + if (I_WRCTL_L = '0') and (rotate_inhibit_write = '0') then + O_MD <= ram_op_reg; + O_MD_OE_L <= '0'; + O_DATEN_L <= '0'; + end if; + end process; + + p_mxd_out_ena : process(I_LTCHDO, ltchdo_t1, I_RD_L, I_IORQ_L, cs_r, I_MXA) + begin + + mxd_out_ena <= '0'; + mxd_out_intercept <= '0'; + + if (I_LTCHDO = '1') or (ltchdo_t1 = '1') then + mxd_out_ena <= '1'; + else + if (I_RD_L = '0') and (I_IORQ_L = '0') and (cs_r = '1') then + if (I_MXA(3 downto 0) = x"8") then -- intercept + mxd_out_ena <= '1'; + mxd_out_intercept <= '1'; + end if; + end if; + end if; + end process; + + p_mxout : process(mxd_out_ena, mxd_out_intercept, I_MD, r_intercept) + begin + O_MXD <= (others => 'X'); + O_MXD_OE_L <= '1'; + if (mxd_out_ena = '1') then + O_MXD_OE_L <= '0'; + if (mxd_out_intercept = '1') then + O_MXD <= r_intercept; + else + O_MXD <= I_MD(7 downto 0); + end if; + end if; + end process; + +end architecture RTL; + diff --git a/Bally - Astrocade_MiST/rtl/bally_io.vhd b/Bally - Astrocade_MiST/rtl/bally_io.vhd new file mode 100644 index 00000000..ec96edcb --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_io.vhd @@ -0,0 +1,405 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_IO is + port ( + I_MXA : in std_logic_vector(15 downto 0); + I_MXD : in std_logic_vector( 7 downto 0); + O_MXD : out std_logic_vector( 7 downto 0); + O_MXD_OE_L : out std_logic; + + -- cpu control signals + I_M1_L : in std_logic; -- not on real chip + I_RD_L : in std_logic; + I_IORQ_L : in std_logic; + I_RESET_L : in std_logic; + +-- I_HANDLE1 : in std_logic_vector( 8 downto 0); +-- I_HANDLE2 : in std_logic_vector( 8 downto 0); +-- I_HANDLE3 : in std_logic_vector( 8 downto 0); +-- I_HANDLE4 : in std_logic_vector( 8 downto 0); + + -- switches + O_SWITCH : out std_logic_vector( 7 downto 0); + I_SWITCH : in std_logic_vector( 7 downto 0); + -- audio + O_AUDIO : out std_logic_vector( 7 downto 0); + -- clks + I_CPU_ENA : in std_logic; + ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_IO is + -- Signals + type array_8x8 is array (0 to 7) of std_logic_vector(7 downto 0); + type array_4x8 is array (0 to 3) of std_logic_vector(7 downto 0); + type array_3x8 is array (0 to 2) of std_logic_vector(7 downto 0); + type array_4x4 is array (0 to 3) of std_logic_vector(3 downto 0); + + type array_bool8 is array (0 to 7) of boolean; + + signal cs : std_logic; + signal snd_ld : array_bool8; + signal r_snd : array_8x8 := (x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00"); + signal r_pot : array_4x8 := (x"00",x"00",x"00",x"00"); + signal mxd_out_reg : std_logic_vector(7 downto 0); + + signal io_read : std_logic; + signal switch_read : std_logic; + -- audio + signal master_ena : std_logic; + signal master_cnt : std_logic_vector(7 downto 0); + signal master_freq : std_logic_vector(7 downto 0); + + signal vibrato_cnt : std_logic_vector(18 downto 0); + signal vibrato_ena : std_logic; + + signal poly17 : std_logic_vector(16 downto 0); + signal noise_gen : std_logic_vector(7 downto 0); + + signal tone_gen : array_3x8 := (others => (others => '0')); + signal tone_gen_op : std_logic_vector(2 downto 0); +begin + + p_chip_sel : process(I_CPU_ENA, I_MXA) + begin + cs <= '0'; + if (I_CPU_ENA = '1') then -- cpu access + if (I_MXA(7 downto 4) = "0001") then + cs <= '1'; + end if; + end if; + end process; + -- + -- registers + -- + p_reg_write_blk_decode : process(I_CPU_ENA, I_RD_L, I_M1_L, I_IORQ_L, cs, I_MXA) -- no m1 gating on real chip ? + begin + -- these writes will last for several cpu_ena cycles, so you + -- will get several load pulses + snd_ld <= (others => false); + if (I_CPU_ENA = '1') then + if (I_RD_L = '1') and (I_IORQ_L = '0') and (I_M1_L = '1') and (cs = '1') then + snd_ld(0) <= ( I_MXA( 3 downto 0) = x"0") or + ((I_MXA(10 downto 8) = "000") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(1) <= ( I_MXA( 3 downto 0) = x"1") or + ((I_MXA(10 downto 8) = "001") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(2) <= ( I_MXA( 3 downto 0) = x"2") or + ((I_MXA(10 downto 8) = "010") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(3) <= ( I_MXA( 3 downto 0) = x"3") or + ((I_MXA(10 downto 8) = "011") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(4) <= ( I_MXA( 3 downto 0) = x"4") or + ((I_MXA(10 downto 8) = "100") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(5) <= ( I_MXA( 3 downto 0) = x"5") or + ((I_MXA(10 downto 8) = "101") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(6) <= ( I_MXA( 3 downto 0) = x"6") or + ((I_MXA(10 downto 8) = "110") and (I_MXA(3 downto 0) = x"8")); + + snd_ld(7) <= ( I_MXA( 3 downto 0) = x"7") or + ((I_MXA(10 downto 8) = "111") and (I_MXA(3 downto 0) = x"8")); + + end if; + end if; + end process; + + p_reg_write_blk : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_RESET_L = '0') then -- don't know if reset does reset the sound + r_snd <= (others => (others => '0')); + else + for i in 0 to 7 loop + if snd_ld(i) then r_snd(i) <= I_MXD; end if; + end loop; + end if; + end if; + end process; + + p_reg_read : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_MXA(3) = '0') then + mxd_out_reg <= I_SWITCH(7 downto 0); + else + mxd_out_reg <= x"00"; + case I_MXA(2 downto 0) is + when "100" => mxd_out_reg <= r_pot(0); --x1C + when "101" => mxd_out_reg <= r_pot(1); --x1D + when "110" => mxd_out_reg <= r_pot(2); --x1E + when "111" => mxd_out_reg <= r_pot(3); --x1F + when others => null; + end case; + end if; + end if; + end process; + + p_decode_read : process(I_MXA, I_IORQ_L, I_RD_L) + begin + -- we will return 0 for x18-1b + io_read <= '0'; + switch_read <= '0'; + if (I_MXA(7 downto 4) = "0001") then + if (I_IORQ_L = '0') and (I_RD_L = '0') then + io_read <= '1'; + if (I_MXA(3) = '0') then + switch_read <= '1'; + end if; + end if; + end if; + end process; + + p_switch_out : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + O_SWITCH <= x"00"; + if (switch_read = '1') then + case I_MXA(2 downto 0) is + when "000" => O_SWITCH <= "00000001"; + when "001" => O_SWITCH <= "00000010"; + when "010" => O_SWITCH <= "00000100"; + when "011" => O_SWITCH <= "00001000"; + when "100" => O_SWITCH <= "00010000"; + when "101" => O_SWITCH <= "00100000"; + when "110" => O_SWITCH <= "01000000"; + when "111" => O_SWITCH <= "10000000"; + when others => null; + end case; + end if; + end if; + end process; + + p_mxd_oe : process(mxd_out_reg, io_read) + begin + O_MXD <= x"00"; + O_MXD_OE_L <= '1'; + if (io_read = '1') then + O_MXD <= mxd_out_reg; + O_MXD_OE_L <= '0'; + end if; + end process; + -- + + p_pots : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- return FF when not plugged in + r_pot(0) <= x"FF"; + r_pot(1) <= x"FF"; + r_pot(2) <= x"FF"; + r_pot(3) <= x"FF"; + end if; + end process; + -- read switches 10-17, pots 1c - 1f + -- port 7 6 5 4 3 2 1 0 + -- x10 tg rt lt dn up | player 1 + -- x11 tg rt lt dn up | player 2 + -- x12 tg rt lt dn up | player 3 + -- x13 tg rt lt dn up | player 4 + -- x14 = + - x / % | keypad (right most col, bit 0 top) + -- x15 . 3 6 9 ch v | keypad + -- x16 0 2 5 8 ms ^ | keypad + -- x17 ce 1 4 7 mr c | keypad (left most col) + + -- write + -- x10 master osc + -- x11 tone a freq + -- x12 tone b freq + -- x13 tone c freq + -- x14 vibrato (7..2 value, 1..0 freq) + -- x15 noise control, tone c volume + -- bit 5 high to enable noise into mix + -- bit 4 high for noise mod, low for vibrato + -- bit 3..0 tone c vol + -- x16 tone b volume, tone a volume (7..4 b vol, 3..0 a vol) + -- x17 noise volume (vol 7..4), 7..0 for master osc modulation + + p_noise_gen : process + variable poly17_zero : std_logic; + begin + -- most probably not correct polynomial + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then + poly17_zero := '0'; + if (poly17 = "00000000000000000") then poly17_zero := '1'; end if; + poly17 <= poly17(15 downto 0) & (poly17(16) xor poly17(2) xor poly17_zero); + end if; + end if; + end process; + noise_gen <= poly17(7 downto 0); + + p_vibrato_osc : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + -- cpu clock period 0.558730s us + + -- 00 toggle output every 18.5 mS bet its 32768 clocks + -- 01 toggle output every 37 mS + -- 10 toggle output every 74 mS + -- 11 toggle output every 148 mS + + -- bit 15 every 32768 clocks + if (I_CPU_ENA = '1') then + vibrato_cnt <= vibrato_cnt + "1"; + vibrato_ena <= '0'; + case r_snd(4)(1 downto 0) is + when "00" => vibrato_ena <= vibrato_cnt(15); + when "01" => vibrato_ena <= vibrato_cnt(16); + when "10" => vibrato_ena <= vibrato_cnt(17); + when "11" => vibrato_ena <= vibrato_cnt(18); + when others => null; + end case; + end if; + end if; + end process; + + p_master_freq : process(vibrato_ena, r_snd, noise_gen) + variable mux : std_logic_vector(7 downto 0); + begin + mux := (others => '0'); -- default + if (r_snd(5)(4) = '1') then -- use noise + mux := noise_gen and r_snd(7); + else + if (vibrato_ena = '1') then + mux := r_snd(4)(7 downto 2) & "00"; + else + mux := (others => '0'); + end if; + end if; + -- add modulation to master osc freq + master_freq <= r_snd(0) + mux; + -- Arcadian mag claims that the counter is preset to the modulation value + -- when the counter hits the master osc reg value. + -- The patent / system descriptions describes an adder .... + end process; + + p_master_osc : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then -- 1.789 Mhz base clock + master_ena <= '0'; + if (master_cnt = "00000000") then + master_cnt <= master_freq; + master_ena <= '1'; + else + master_cnt <= master_cnt - "1"; + end if; + end if; + end if; + end process; + + p_tone_gen : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then -- 1.789 Mhz base clock + + for i in 0 to 2 loop + if (master_ena = '1') then + if (tone_gen(i) = "00000000") then + tone_gen(i) <= r_snd(i + 1); -- load + tone_gen_op(i) <= not tone_gen_op(i); + else + tone_gen(i) <= tone_gen(i) - '1'; + end if; + end if; + end loop; + end if; + end if; + end process; + + p_op_mixer : process + variable vol : array_4x4; + variable sum01 : std_logic_vector(4 downto 0); + variable sum23 : std_logic_vector(4 downto 0); + variable sum : std_logic_vector(5 downto 0); + begin + wait until rising_edge(CLK); + if (ENA = '1') then + if (I_CPU_ENA = '1') then + vol(0) := "0000"; + vol(1) := "0000"; + vol(2) := "0000"; + vol(3) := "0000"; + + if (tone_gen_op(0) = '1') then vol(0) := r_snd(6)(3 downto 0); end if; -- A + if (tone_gen_op(1) = '1') then vol(1) := r_snd(6)(7 downto 4); end if; -- B + if (tone_gen_op(2) = '1') then vol(2) := r_snd(5)(3 downto 0); end if; -- C + if (r_snd(5)(5) = '1') then -- noise enable + if (noise_gen(0) = '1') then vol(3) := r_snd(5)(7 downto 4); end if; -- noise + end if; + + sum01 := ('0' & vol(0)) + ('0' & vol(1)); + sum23 := ('0' & vol(2)) + ('0' & vol(3)); + sum := ('0' & sum01) + ('0' & sum23); + + if (I_RESET_L = '0') then + O_AUDIO <= "00000000"; + else + O_AUDIO <= (sum & "00"); + end if; + end if; + end if; + end process; + +end architecture RTL; + diff --git a/Bally - Astrocade_MiST/rtl/bally_mist.sv b/Bally - Astrocade_MiST/rtl/bally_mist.sv new file mode 100644 index 00000000..89cf26fc --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_mist.sv @@ -0,0 +1,158 @@ +module bally_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 +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "BALLY;BIN;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire clk_28;//28.5712 +wire clk_14;//14.2856 +wire clk_7;//7.1428 + +wire [12:0] cart_addr; +wire [7:0] cart_do; +wire cart_cs; +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; +assign LED = !ioctl_downl; + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] kbjoy; + +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [7:0] audio; + +wire pix_ena; +wire hs, vs; +wire [3:0] r,g,b; + + +pll pll +( + .inclk0(CLOCK_27), + .c0(clk_28), + .c1(clk_14), + .c2(clk_7) + ); + +video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(0)) video_mixer +( + .clk_sys(clk_28), + .ce_pix(clk_7), + .ce_pix_actual(clk_7), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R({r,r[1:0]}), + .G({g,g[1:0]}), + .B({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), + .scandoubler_disable(scandoubler_disable), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(0) +); + + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .clk_sys (clk_28 ), + .conf_str (CONF_STR ), + .SPI_SCK (SPI_SCK ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SS2 (SPI_SS2 ), + .SPI_DO (SPI_DO ), + .SPI_DI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoubler_disable ), + .ypbpr (ypbpr ), + .ps2_kbd_clk (ps2_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ), + .ioctl_download ( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); + + +cart cart ( + .clock ( clk_14 ), + .address ( ioctl_downl ? ioctl_addr : cart_addr), + .data ( ioctl_dout ), + .rden ( !ioctl_downl && !cart_cs), + .wren ( ioctl_downl && ioctl_wr), + .q ( cart_do ) + ); + +BALLY_TOP BALLY_TOP ( + .cas_addr(cart_addr), + .cas_data(cart_do), + .cas_cs_l(cart_cs), + .I_PS2_CLK (ps2_kbd_clk ), + .I_PS2_DATA (ps2_kbd_data ), + .r(r), + .g(g), + .b(b), + .hs(hs), + .vs(vs), + .AUDIO(audio), + .ena(1'b1), + .pix_ena(pix_ena), + .clk_14(clk_14), + .clk_7(clk_7), + .reset((status[0] | status[6] | buttons[1] | ioctl_downl)) + ); + +dac dac +( + .clk_i(clk_28), + .res_n_i(1'b1), + .dac_i(audio), + .dac_o(AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +endmodule diff --git a/Bally - Astrocade_MiST/rtl/bally_ps2_if.vhd b/Bally - Astrocade_MiST/rtl/bally_ps2_if.vhd new file mode 100644 index 00000000..5212017e --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_ps2_if.vhd @@ -0,0 +1,319 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + use ieee.numeric_std.all; + +entity BALLY_PS2_IF is + port ( + + I_PS2_CLK : in std_logic; + I_PS2_DATA : in std_logic; + + I_COL : in std_logic_vector(7 downto 0); + O_ROW : out std_logic_vector(7 downto 0); + + I_RESET_L : in std_logic; + I_1MHZ_ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_PS2_IF is + + signal tick_1us : std_logic; + signal kbd_press : std_logic; + signal kbd_release : std_logic; + signal kbd_reset : std_logic; + signal kbd_press_s : std_logic; + signal kbd_release_s : std_logic; + signal kbd_scancode : std_logic_vector(7 downto 0); + signal kbd_scanE0 : std_logic; + + signal col_addr : std_logic_vector(3 downto 0); + signal rowcol : std_logic_vector(7 downto 0); + signal row_mask : std_logic_vector(7 downto 0); + + signal ram_w_addr : std_logic_vector(3 downto 0); + signal ram_r_addr : std_logic_vector(3 downto 0); + signal ram_we : std_ulogic; + signal ram_din : std_logic_vector(7 downto 0); + signal ram_dout : std_logic_vector(7 downto 0); + + signal reset_cnt : std_logic_vector(4 downto 0); + signal io_ena : std_logic; + -- non-xilinx ram + type slv_array8 is array (natural range <>) of std_logic_vector(7 downto 0); + shared variable ram : slv_array8(7 downto 0) := (others => (others => '0')); + +begin + + -- port 7 6 5 4 3 2 1 0 + -- x10 tg rt lt dn up | player 1 + -- x11 tg rt lt dn up | player 2 + -- x12 tg rt lt dn up | player 3 + -- x13 tg rt lt dn up | player 4 + + + -- bit x17 x16 x15 x14 maps to pc key + -- + -- 0 c ^ v % z a q 1 + -- 1 mr ms ch / x s w 2 + -- 2 7 8 9 x c d e 3 + -- 3 4 5 6 - v f r 4 + -- 4 1 2 3 + b g t 5 + -- 5 ce 0 . = n h y 6 + + tick_1us <= I_1MHZ_ENA; + + -- Keyboard decoder + u_kbd : entity work.ps2kbd + port map( + Rst_n => I_RESET_L, + Clk => CLK, + Tick1us => tick_1us, + PS2_Clk => I_PS2_CLK, + PS2_Data => I_PS2_DATA, + Press => kbd_press, + Release => kbd_release, + Reset => kbd_reset, + ScanE0 => kbd_scanE0, + ScanCode => kbd_scancode + ); + + p_decode_scancode : process + begin + -- hopefully the tools will build a rom for this + wait until rising_edge(CLK); + -- rowcol is valid for lots of clocks, but kbd_press_t1 / release are single + -- clock strobes. must sync these to io_ena + if (kbd_press = '1') then + kbd_press_s <= '1'; + elsif (io_ena = '0') then + kbd_press_s <= '0'; + end if; + + if (kbd_release = '1') then + kbd_release_s <= '1'; + elsif (io_ena = '0') then + kbd_release_s <= '0'; + end if; + + -- top bit low for keypress + if (kbd_scanE0 = '0') then + rowcol <= x"ff"; + case kbd_scancode is + -- player 1 col 0 + when x"29" => rowcol <= x"40";-- space + -- player 2 col 1 + when x"75" => rowcol <= x"01";-- keypad8 + when x"72" => rowcol <= x"11";-- keypad2 + when x"6B" => rowcol <= x"21";-- keypad4 + when x"74" => rowcol <= x"31";-- keypad6 + when x"70" => rowcol <= x"41";-- keypad0 + -- player 3 col 2 not mapped + -- player 4 col 3 not mapped + + -- keypad col 4 + when x"16" => rowcol <= x"04";-- 1 + when x"1E" => rowcol <= x"14";-- 2 + when x"26" => rowcol <= x"24";-- 3 + when x"25" => rowcol <= x"34";-- 4 + when x"2E" => rowcol <= x"44";-- 5 + when x"36" => rowcol <= x"54";-- 6 + -- keypad col 5 + when x"15" => rowcol <= x"05";-- q + when x"1D" => rowcol <= x"15";-- w + when x"24" => rowcol <= x"25";-- e + when x"2D" => rowcol <= x"35";-- r + when x"2C" => rowcol <= x"45";-- t + when x"35" => rowcol <= x"55";-- y + -- keypad col 6 + when x"1C" => rowcol <= x"06";-- a + when x"1B" => rowcol <= x"16";-- s + when x"23" => rowcol <= x"26";-- d + when x"2B" => rowcol <= x"36";-- f + when x"34" => rowcol <= x"46";-- g + when x"33" => rowcol <= x"56";-- h + -- keypad col 7 + when x"1A" => rowcol <= x"07";-- z + when x"22" => rowcol <= x"17";-- x + when x"21" => rowcol <= x"27";-- c + when x"2A" => rowcol <= x"37";-- v + when x"32" => rowcol <= x"47";-- b + when x"31" => rowcol <= x"57";-- n + + when others => rowcol <= x"FF"; + end case; + else + rowcol <= x"ff"; + case kbd_scancode is + when x"75" => rowcol <= x"00";-- curs up + when x"72" => rowcol <= x"10";-- curs dn + when x"6B" => rowcol <= x"20";-- curs left + when x"74" => rowcol <= x"30";-- curs right + when others => rowcol <= x"FF"; + end case; + end if; + end process; + + p_expand_row : process(rowcol) + begin + row_mask <= x"01"; + case rowcol(6 downto 4) is + when "000" => row_mask <= x"01"; + when "001" => row_mask <= x"02"; + when "010" => row_mask <= x"04"; + when "011" => row_mask <= x"08"; + when "100" => row_mask <= x"10"; + when "101" => row_mask <= x"20"; + when "110" => row_mask <= x"40"; + when "111" => row_mask <= x"80"; + when others => null; + end case; + end process; + + p_reset_cnt : process(I_RESET_L, CLK) + begin + if (I_RESET_L = '0') then + reset_cnt <= "00000"; + io_ena <= '0'; + elsif rising_edge(CLK) then + -- counter used to reset ram + if (kbd_reset = '1') then + reset_cnt <= "10000"; + elsif (reset_cnt(4) = '1') then + reset_cnt <= reset_cnt + "1"; + end if; + io_ena <= not io_ena; + end if; + end process; + + p_keybd_write : process(kbd_press_s, kbd_release_s, rowcol, + kbd_reset, reset_cnt, ram_dout, row_mask, io_ena) + variable we : boolean; + begin + -- valid key ? + we := ((kbd_press_s = '1') or (kbd_release_s = '1')) and (rowcol(7) = '0'); + + if (reset_cnt(4) = '1') then + ram_w_addr <= reset_cnt(3 downto 0); + ram_din <= x"00"; + ram_we <= '1'; + else + ram_w_addr <= rowcol(3 downto 0); + + if (kbd_press_s = '1') then + ram_din <= ram_dout or row_mask; -- pressed + else + ram_din <= ram_dout and not row_mask; -- released + end if; + + ram_we <= '0'; + if we and (io_ena = '0')then + ram_we <= '1'; + end if; + end if; + + end process; + + + p_ram_w : process + variable ram_addr : integer := 0; + begin + wait until rising_edge(CLK); + if (ram_we = '1') then + ram_addr := to_integer(unsigned(ram_w_addr(2 downto 0))); + ram(ram_addr) := ram_din; + end if; + end process; + + p_ram_r : process(CLK, ram_r_addr) + variable ram_addr : integer := 0; + begin + ram_addr := to_integer(unsigned(ram_r_addr(2 downto 0))); + ram_dout <= ram(ram_addr); + end process; + + -- the io chip can access the ram when io_ena = '1' + p_ram_read_mux : process(io_ena, col_addr, rowcol) + begin + if (io_ena = '1') then + ram_r_addr <= col_addr; + else + ram_r_addr <= rowcol(3 downto 0); -- write r/m/w + end if; + end process; + + p_via_out_reg : process + begin + wait until rising_edge(CLK); + if (io_ena = '1') then + if (col_addr = x"f") then -- none + O_ROW <= x"00"; + else + O_ROW <= ram_dout; -- switches are active high + end if; + end if; + end process; + + p_col_decode : process(I_COL) + begin + col_addr <= x"F"; + case I_COL is + when x"01" => col_addr <= x"0"; + when x"02" => col_addr <= x"1"; + when x"04" => col_addr <= x"2"; + when x"08" => col_addr <= x"3"; + when x"10" => col_addr <= x"4"; + when x"20" => col_addr <= x"5"; + when x"40" => col_addr <= x"6"; + when x"80" => col_addr <= x"7"; + when others => null; + end case; + end process; + +end architecture RTL; + diff --git a/Bally - Astrocade_MiST/rtl/bally_rams.vhd b/Bally - Astrocade_MiST/rtl/bally_rams.vhd new file mode 100644 index 00000000..6a583635 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_rams.vhd @@ -0,0 +1,178 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 004 spartan3e hires release +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_RAMS is + port ( + ADDR : in std_logic_vector(15 downto 0); + DIN : in std_logic_vector(7 downto 0); + DOUT : out std_logic_vector(7 downto 0); + DOUTX : out std_logic_vector(7 downto 0); -- next byte + WE : in std_logic; + WE_ENA_L : in std_logic; -- used for write enable gate only + ENA : in std_logic; + CLK : in std_logic + ); +end; + +architecture RTL of BALLY_RAMS is + type array_7x8 is array (0 to 6) of std_logic_vector(7 downto 0); + -- + signal dout_int_h : array_7x8; + signal dout_int_l : array_7x8; + signal addr_t1 : std_logic_vector(15 downto 0); + signal int_we_h : std_logic_vector(6 downto 0); + signal int_we_l : std_logic_vector(6 downto 0); + +-- we can have 14 rams total +-- 4000-4FFF 4K + +-- 16K screen ram 4000-7fff this is aliased to 0000-3FFF for magic +-- spare 8000-BFFF (but we are only have enough rams to go to AFFF for now) +begin + p_we : process(ADDR, WE, WE_ENA_L) + variable h,l : std_logic; + begin + int_we_h <= (others => '0'); + int_we_l <= (others => '0'); + l := (not ADDR(0)) and WE and (not WE_ENA_L); + h := ADDR(0) and WE and (not WE_ENA_L); + -- + case ADDR(15 downto 12) is + when x"0" => int_we_h(0) <= h; int_we_l(0) <= l; + when x"1" => int_we_h(1) <= h; int_we_l(1) <= l; + when x"2" => int_we_h(2) <= h; int_we_l(2) <= l; + when x"3" => int_we_h(3) <= h; int_we_l(3) <= l; + -- + when x"4" => int_we_h(0) <= h; int_we_l(0) <= l; + when x"5" => int_we_h(1) <= h; int_we_l(1) <= l; + when x"6" => int_we_h(2) <= h; int_we_l(2) <= l; + when x"7" => int_we_h(3) <= h; int_we_l(3) <= l; + -- + when x"8" => int_we_h(4) <= h; int_we_l(4) <= l; + when x"9" => int_we_h(5) <= h; int_we_l(5) <= l; + when x"A" => int_we_h(6) <= h; int_we_l(6) <= l; + --when x"B" => int_we_h(7) <= h; int_we_l(7) <= l; + -- + when others => null; + end case; + end process; + + + + rams : for i in 0 to 6 generate + begin + ram_u : entity work.spram + generic map ( + init_file => "", + widthad_a => 11, + width_a => 8 + ) + port map ( + address => ADDR(11 downto 1), + clock => CLK, + data => DIN(7 downto 0), + wren => int_we_h(i), + q => dout_int_h(i)(7 downto 0) + ); + ram_l : entity work.spram + generic map ( + init_file => "", + widthad_a => 11, + width_a => 8 + ) + port map ( + address => ADDR(11 downto 1), + clock => CLK, + data => DIN(7 downto 0), + wren => int_we_l(i), + q => dout_int_l(i)(7 downto 0) + ); + end generate; + + p_addr_delay : process + begin + wait until rising_edge(CLK); + addr_t1 <= ADDR; + end process; + + p_mux : process(dout_int_l, dout_int_h, addr, addr_t1) + variable mux_h : std_logic_vector(7 downto 0); + variable mux_l : std_logic_vector(7 downto 0); + begin + + mux_h := dout_int_h(0); mux_l := dout_int_l(0); + case addr_t1(15 downto 12) is + when x"0" => mux_h := dout_int_h(0); mux_l := dout_int_l(0); + when x"1" => mux_h := dout_int_h(1); mux_l := dout_int_l(1); + when x"2" => mux_h := dout_int_h(2); mux_l := dout_int_l(2); + when x"3" => mux_h := dout_int_h(3); mux_l := dout_int_l(3); + -- + when x"4" => mux_h := dout_int_h(0); mux_l := dout_int_l(0); + when x"5" => mux_h := dout_int_h(1); mux_l := dout_int_l(1); + when x"6" => mux_h := dout_int_h(2); mux_l := dout_int_l(2); + when x"7" => mux_h := dout_int_h(3); mux_l := dout_int_l(3); + -- + when x"8" => mux_h := dout_int_h(4); mux_l := dout_int_l(4); + when x"9" => mux_h := dout_int_h(5); mux_l := dout_int_l(5); + when x"A" => mux_h := dout_int_h(6); mux_l := dout_int_l(6); + --when x"B" => mux_h := dout_int_h(7); mux_l := dout_int_l(7); + -- + when others => null; + end case; + + if (addr_t1(0) = '0') then + DOUT <= mux_l; + else + DOUT <= mux_h; + end if; + DOUTX <= mux_h; + + end process; + +end architecture RTL; diff --git a/Bally - Astrocade_MiST/rtl/bally_top.vhd b/Bally - Astrocade_MiST/rtl/bally_top.vhd new file mode 100644 index 00000000..29ed228a --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/bally_top.vhd @@ -0,0 +1,199 @@ +-- +-- A simulation model of Bally Astrocade hardware +-- Copyright (c) MikeJ - Nov 2004 +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS CODE 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 AUTHOR 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 004 spartan3e hires release +-- version 003 spartan3e release +-- version 001 initial release +-- +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity BALLY_TOP is + port ( + cas_addr : out std_logic_vector(12 downto 0); + cas_data : in std_logic_vector( 7 downto 0); + cas_cs_l : out std_logic; + I_PS2_CLK : in std_logic; + I_PS2_DATA : in std_logic; + r : out std_logic_vector(3 downto 0); + g : out std_logic_vector(3 downto 0); + b : out std_logic_vector(3 downto 0); + hs : out std_logic; + vs : out std_logic; + audio : out std_logic_vector( 7 downto 0); + ena : in std_logic; + pix_ena : out std_logic; + clk_14 : in std_logic; + clk_7 : in std_logic; + reset : in std_logic + ); +end; + +architecture RTL of BALLY_TOP is + + -- + signal switch_col : std_logic_vector(7 downto 0); + signal switch_row : std_logic_vector(7 downto 0); + signal ps2_1mhz_ena : std_logic; + signal ps2_1mhz_cnt : std_logic_vector(5 downto 0); + -- + signal video_r : std_logic_vector(3 downto 0); + signal video_g : std_logic_vector(3 downto 0); + signal video_b : std_logic_vector(3 downto 0); + signal hsync : std_logic; + signal vsync : std_logic; + signal fpsync : std_logic; + + + signal exp_addr : std_logic_vector(15 downto 0); + signal exp_data_out : std_logic_vector(7 downto 0); + signal exp_data_in : std_logic_vector(7 downto 0); + signal exp_oe_l : std_logic; + + signal exp_m1_l : std_logic; + signal exp_mreq_l : std_logic; + signal exp_iorq_l : std_logic; + signal exp_wr_l : std_logic; + signal exp_rd_l : std_logic; + -- + signal check_cart_msb : std_logic_vector(3 downto 0); + signal check_cart_lsb : std_logic_vector(7 downto 4); + + +begin + + + p_ena1mhz : process + begin + wait until rising_edge(clk_7); + -- divide by 7 + ps2_1mhz_ena <= '0'; + if (ps2_1mhz_cnt = "000110") then + ps2_1mhz_cnt <= "000000"; + ps2_1mhz_ena <= '1'; + else + ps2_1mhz_cnt <= ps2_1mhz_cnt + '1'; + end if; + end process; + + + u_bally : entity work.BALLY + port map ( + O_AUDIO => audio, + -- + O_VIDEO_R => r, + O_VIDEO_G => g, + O_VIDEO_B => b, + + O_HSYNC => hs, + O_VSYNC => vs, + O_COMP_SYNC_L => open, + O_FPSYNC => open, + -- + -- cart slot + O_CAS_ADDR => cas_addr, + O_CAS_DATA => open, + I_CAS_DATA => cas_data, + O_CAS_CS_L => cas_cs_l, + + -- exp slot (subset for now) + O_EXP_ADDR => exp_addr, + O_EXP_DATA => exp_data_out, + I_EXP_DATA => exp_data_in, + I_EXP_OE_L => exp_oe_l, + + O_EXP_M1_L => exp_m1_l, + O_EXP_MREQ_L => exp_mreq_l, + O_EXP_IORQ_L => exp_iorq_l, + O_EXP_WR_L => exp_wr_l, + O_EXP_RD_L => exp_rd_l, + -- + O_SWITCH_COL => switch_col, + I_SWITCH_ROW => switch_row, + I_RESET_L => not reset, + ENA => ena, + pix_ena => pix_ena, + CLK => clk_14, + CLK7 => clk_7 + ); + + u_ps2 : entity work.BALLY_PS2_IF + port map ( + + I_PS2_CLK => I_PS2_CLK, + I_PS2_DATA => I_PS2_DATA, + + I_COL => switch_col, + O_ROW => switch_row, + + I_RESET_L => not reset, + I_1MHZ_ENA => ps2_1mhz_ena, + CLK => clk_7 + ); + +-- u_check_cart : entity work.BALLY_CHECK_CART +-- port map ( + -- I_EXP_ADDR => exp_addr, + -- I_EXP_DATA => exp_data_out, + -- O_EXP_DATA => exp_data_in, + -- O_EXP_OE_L => exp_oe_l, + +-- I_EXP_M1_L => exp_m1_l, + -- I_EXP_MREQ_L => exp_mreq_l, + -- I_EXP_IORQ_L => exp_iorq_l, + -- I_EXP_WR_L => exp_wr_l, + -- I_EXP_RD_L => exp_rd_l, + ---- +-- O_CHAR_MSB => check_cart_msb, + -- O_CHAR_LSB => check_cart_lsb, + ---- + -- I_RESET_L => not reset, + -- ENA => ena, + -- CLK => clk_7 + -- ); + + -- if no expansion cart + exp_data_in <= x"ff"; + exp_oe_l <= '1'; + + +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/build_id.tcl b/Bally - Astrocade_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Bally - Astrocade_MiST/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/Bally - Astrocade_MiST/rtl/build_id.v b/Bally - Astrocade_MiST/rtl/build_id.v new file mode 100644 index 00000000..ab23e366 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "180725" +`define BUILD_TIME "160612" diff --git a/Bally - Astrocade_MiST/rtl/cart.qip b/Bally - Astrocade_MiST/rtl/cart.qip new file mode 100644 index 00000000..8607b3bf --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/cart.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.0" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "cart.v"] diff --git a/Bally - Astrocade_MiST/rtl/cart.v b/Bally - Astrocade_MiST/rtl/cart.v new file mode 100644 index 00000000..f4a633e7 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/cart.v @@ -0,0 +1,177 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: cart.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version +// ************************************************************ + + +//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. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module cart ( + address, + clock, + data, + rden, + wren, + q); + + input [12:0] address; + input clock; + input [7:0] data; + input rden; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri1 rden; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .rden_a (rden), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .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), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 8192, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 13, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "13" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @rden_a 0 0 0 0 rden 0 0 0 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Bally - Astrocade_MiST/rtl/dac.vhd b/Bally - Astrocade_MiST/rtl/dac.vhd new file mode 100644 index 00000000..c133f074 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/dac.vhd @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------- +-- +-- Delta-Sigma DAC +-- +-- $Id: dac.vhd,v 1.1 2006/05/10 20:57:06 arnim Exp $ +-- +-- Refer to Xilinx Application Note XAPP154. +-- +-- This DAC requires an external RC low-pass filter: +-- +-- dac_o 0---XXXXX---+---0 analog audio +-- 3k3 | +-- === 4n7 +-- | +-- GND +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity dac is + + generic ( + msbi_g : integer := 7 + ); + port ( + clk_i : in std_logic; + res_n_i : in std_logic; + dac_i : in std_logic_vector(msbi_g downto 0); + dac_o : out std_logic + ); + +end dac; + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of dac is + + signal DACout_q : std_logic; + signal DeltaAdder_s, + SigmaAdder_s, + SigmaLatch_q, + DeltaB_s : unsigned(msbi_g+2 downto 0); + +begin + + DeltaB_s(msbi_g+2 downto msbi_g+1) <= SigmaLatch_q(msbi_g+2) & + SigmaLatch_q(msbi_g+2); + DeltaB_s(msbi_g downto 0) <= (others => '0'); + + DeltaAdder_s <= unsigned('0' & '0' & dac_i) + DeltaB_s; + + SigmaAdder_s <= DeltaAdder_s + SigmaLatch_q; + + seq: process (clk_i, res_n_i) + begin + if res_n_i = '0' then + SigmaLatch_q <= to_unsigned(2**(msbi_g+1), SigmaLatch_q'length); + DACout_q <= '0'; + + elsif clk_i'event and clk_i = '1' then + SigmaLatch_q <= SigmaAdder_s; + DACout_q <= SigmaLatch_q(msbi_g+2); + end if; + end process seq; + + dac_o <= DACout_q; + +end rtl; diff --git a/Bally - Astrocade_MiST/rtl/hq2x.sv b/Bally - Astrocade_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .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), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + 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_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Bally - Astrocade_MiST/rtl/mist_io.v b/Bally - Astrocade_MiST/rtl/mist_io.v new file mode 100644 index 00000000..ad233a3b --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/mist_io.v @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// 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 . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [24:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [24:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [24:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/Bally - Astrocade_MiST/rtl/osd.v b/Bally - Astrocade_MiST/rtl/osd.v new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/osd.v @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Bally - Astrocade_MiST/rtl/pll.qip b/Bally - Astrocade_MiST/rtl/pll.qip new file mode 100644 index 00000000..68624e41 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.0" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll.vhd"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Bally - Astrocade_MiST/rtl/pll.vhd b/Bally - Astrocade_MiST/rtl/pll.vhd new file mode 100644 index 00000000..c9a1d016 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/pll.vhd @@ -0,0 +1,414 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version +-- ************************************************************ + + +--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. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll IS + PORT + ( + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC + ); +END pll; + + +ARCHITECTURE SYN OF pll IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC ; + SIGNAL sub_wire4 : STD_LOGIC ; + SIGNAL sub_wire5 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire6_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire6 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + bandwidth_type : STRING; + clk0_divide_by : NATURAL; + clk0_duty_cycle : NATURAL; + clk0_multiply_by : NATURAL; + clk0_phase_shift : STRING; + clk1_divide_by : NATURAL; + clk1_duty_cycle : NATURAL; + clk1_multiply_by : NATURAL; + clk1_phase_shift : STRING; + clk2_divide_by : NATURAL; + clk2_duty_cycle : NATURAL; + clk2_multiply_by : NATURAL; + clk2_phase_shift : STRING; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : STRING; + pll_type : STRING; + port_activeclock : STRING; + port_areset : STRING; + port_clkbad0 : STRING; + port_clkbad1 : STRING; + port_clkloss : STRING; + port_clkswitch : STRING; + port_configupdate : STRING; + port_fbin : STRING; + port_inclk0 : STRING; + port_inclk1 : STRING; + port_locked : STRING; + port_pfdena : STRING; + port_phasecounterselect : STRING; + port_phasedone : STRING; + port_phasestep : STRING; + port_phaseupdown : STRING; + port_pllena : STRING; + port_scanaclr : STRING; + port_scanclk : STRING; + port_scanclkena : STRING; + port_scandata : STRING; + port_scandataout : STRING; + port_scandone : STRING; + port_scanread : STRING; + port_scanwrite : STRING; + port_clk0 : STRING; + port_clk1 : STRING; + port_clk2 : STRING; + port_clk3 : STRING; + port_clk4 : STRING; + port_clk5 : STRING; + port_clkena0 : STRING; + port_clkena1 : STRING; + port_clkena2 : STRING; + port_clkena3 : STRING; + port_clkena4 : STRING; + port_clkena5 : STRING; + port_extclk0 : STRING; + port_extclk1 : STRING; + port_extclk2 : STRING; + port_extclk3 : STRING; + width_clock : NATURAL + ); + PORT ( + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + sub_wire6_bv(0 DOWNTO 0) <= "0"; + sub_wire6 <= To_stdlogicvector(sub_wire6_bv); + sub_wire3 <= sub_wire0(2); + sub_wire2 <= sub_wire0(0); + sub_wire1 <= sub_wire0(1); + c1 <= sub_wire1; + c0 <= sub_wire2; + c2 <= sub_wire3; + sub_wire4 <= inclk0; + sub_wire5 <= sub_wire6(0 DOWNTO 0) & sub_wire4; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 52, + clk0_duty_cycle => 50, + clk0_multiply_by => 55, + clk0_phase_shift => "0", + clk1_divide_by => 104, + clk1_duty_cycle => 50, + clk1_multiply_by => 55, + clk1_phase_shift => "0", + clk2_divide_by => 208, + clk2_duty_cycle => 50, + clk2_multiply_by => 55, + clk2_phase_shift => "0", + compensate_clock => "CLK0", + inclk0_input_frequency => 37037, + intended_device_family => "Cyclone III", + lpm_hint => "CBX_MODULE_PREFIX=pll", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_UNUSED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_UNUSED", + port_pfdena => "PORT_UNUSED", + port_phasecounterselect => "PORT_UNUSED", + port_phasedone => "PORT_UNUSED", + port_phasestep => "PORT_UNUSED", + port_phaseupdown => "PORT_UNUSED", + port_pllena => "PORT_UNUSED", + port_scanaclr => "PORT_UNUSED", + port_scanclk => "PORT_UNUSED", + port_scanclkena => "PORT_UNUSED", + port_scandata => "PORT_UNUSED", + port_scandataout => "PORT_UNUSED", + port_scandone => "PORT_UNUSED", + port_scanread => "PORT_UNUSED", + port_scanwrite => "PORT_UNUSED", + port_clk0 => "PORT_USED", + port_clk1 => "PORT_USED", + port_clk2 => "PORT_USED", + port_clk3 => "PORT_UNUSED", + port_clk4 => "PORT_UNUSED", + port_clk5 => "PORT_UNUSED", + port_clkena0 => "PORT_UNUSED", + port_clkena1 => "PORT_UNUSED", + port_clkena2 => "PORT_UNUSED", + port_clkena3 => "PORT_UNUSED", + port_clkena4 => "PORT_UNUSED", + port_clkena5 => "PORT_UNUSED", + port_extclk0 => "PORT_UNUSED", + port_extclk1 => "PORT_UNUSED", + port_extclk2 => "PORT_UNUSED", + port_extclk3 => "PORT_UNUSED", + width_clock => 5 + ) + PORT MAP ( + inclk => sub_wire5, + clk => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- 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 "52" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "104" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "208" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "28.557692" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "14.278846" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "7.139423" +-- 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 "0" +-- 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: LVDS_PHASE_SHIFT_UNIT2 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: MIRROR_CLK2 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "55" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "55" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "55" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "28.57120000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.28560000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "7.14280000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 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_SHIFT2 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +-- 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: STICKY_CLK2 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_CLK2 STRING "1" +-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA2 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 "52" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "55" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "104" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "55" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "208" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "55" +-- Retrieval info: CONSTANT: CLK2_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_UNUSED" +-- 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_UNUSED" +-- 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_USED" +-- 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: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- 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: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- 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: c2 0 0 0 0 @clk 0 0 1 2 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Bally - Astrocade_MiST/rtl/ps2kbd.vhd b/Bally - Astrocade_MiST/rtl/ps2kbd.vhd new file mode 100644 index 00000000..028989f8 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/ps2kbd.vhd @@ -0,0 +1,212 @@ +-- +-- PS/2 serial port, input only +-- +-- Version : 0242 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized 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. +-- +-- Neither the name of the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.fpgaarcade.com +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : First release +-- extended key handling added by MIKEJ +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity ps2kbd is + port( + Rst_n : in std_logic; + Clk : in std_logic; + Tick1us : in std_logic; + PS2_Clk : in std_logic; + PS2_Data : in std_logic; + Press : out std_logic; + Release : out std_logic; + Reset : out std_logic; + ScanE0 : out std_logic; + ScanCode : out std_logic_vector(7 downto 0)); +end ps2kbd; + +architecture rtl of ps2kbd is + + signal PS2_Sample : std_logic; + signal PS2_Data_s : std_logic; + + signal RX_Bit_Cnt : unsigned(3 downto 0); + signal RX_Byte : unsigned(2 downto 0); + signal RX_ShiftReg : std_logic_vector(7 downto 0); + signal RX_Release : std_logic; + signal RX_Received : std_logic; + signal RX_E0 : std_logic; + +begin + + ScanCode <= RX_ShiftReg; + + process (Clk, Rst_n) + variable PS2_Data_r : std_logic_vector(1 downto 0); + variable PS2_Clk_r : std_logic_vector(1 downto 0); + variable PS2_Clk_State : std_logic; + begin + if Rst_n = '0' then + PS2_Sample <= '0'; + PS2_Data_s <= '0'; + PS2_Data_r := "11"; + PS2_Clk_r := "11"; + PS2_Clk_State := '1'; + elsif Clk'event and Clk = '1' then + if Tick1us = '1' then + PS2_Sample <= '0'; + + -- Deglitch + if PS2_Data_r = "00" then + PS2_Data_s <= '0'; + end if; + if PS2_Data_r = "11" then + PS2_Data_s <= '1'; + end if; + if PS2_Clk_r = "00" then + if PS2_Clk_State = '1' then + PS2_Sample <= '1'; + end if; + PS2_Clk_State := '0'; + end if; + if PS2_Clk_r = "11" then + PS2_Clk_State := '1'; + end if; + + -- Double synchronise + PS2_Data_r(1) := PS2_Data_r(0); + PS2_Clk_r(1) := PS2_Clk_r(0); + PS2_Data_r(0) := PS2_Data; + PS2_Clk_r(0) := PS2_Clk; + end if; + end if; + end process; + + process (Clk, Rst_n) + variable Cnt : integer; + begin + if Rst_n = '0' then + RX_Bit_Cnt <= (others => '0'); + RX_ShiftReg <= (others => '0'); + RX_Received <= '0'; + Cnt := 0; + elsif Clk'event and Clk = '1' then + RX_Received <= '0'; + if Tick1us = '1' then + + if PS2_Sample = '1' then + if RX_Bit_Cnt = "0000" then + if PS2_Data_s = '0' then -- Start bit + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + end if; + elsif RX_Bit_Cnt = "1001" then -- Parity bit + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + -- Ignoring parity + elsif RX_Bit_Cnt = "1010" then -- Stop bit + if PS2_Data_s = '1' then + RX_Received <= '1'; + end if; + RX_Bit_Cnt <= "0000"; + else + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + RX_ShiftReg(6 downto 0) <= RX_ShiftReg(7 downto 1); + RX_ShiftReg(7) <= PS2_Data_s; + end if; + end if; + + -- TimeOut + if PS2_Sample = '1' then + Cnt := 0; + elsif Cnt = 127 then + RX_Bit_Cnt <= "0000"; + Cnt := 0; + else + Cnt := Cnt + 1; + end if; + end if; + end if; + end process; + + process (Clk, Rst_n) + begin + if Rst_n = '0' then + Press <= '0'; + Release <= '0'; + Reset <= '0'; + RX_Byte <= (others => '0'); + RX_Release <= '0'; + ScanE0 <= '0'; + RX_E0 <= '0'; + elsif Clk'event and Clk = '1' then + Press <= '0'; + Release <= '0'; + Reset <= '0'; + if RX_Received = '1' then + RX_Byte <= RX_Byte + 1; + if RX_ShiftReg = x"F0" then + RX_Release <= '1'; + elsif RX_ShiftReg = x"E0" then + RX_E0 <= '1'; + else + ScanE0 <= RX_E0; + RX_E0 <= '0'; + + RX_Release <= '0'; + -- Normal key press + if RX_Release = '0' then + Press <= '1'; + end if; + -- Normal key release + if RX_Release = '1' then + Release <= '1'; + end if; + end if; + if RX_ShiftReg = x"aa" then + Reset <= '1'; + end if; + end if; + end if; + end process; + +end; diff --git a/Bally - Astrocade_MiST/rtl/roms/BIOS3159.BIN b/Bally - Astrocade_MiST/rtl/roms/BIOS3159.BIN new file mode 100644 index 00000000..9b587b7a Binary files /dev/null and b/Bally - Astrocade_MiST/rtl/roms/BIOS3159.BIN differ diff --git a/Bally - Astrocade_MiST/rtl/roms/balcheck.bin b/Bally - Astrocade_MiST/rtl/roms/balcheck.bin new file mode 100644 index 00000000..97ea951c Binary files /dev/null and b/Bally - Astrocade_MiST/rtl/roms/balcheck.bin differ diff --git a/Bally - Astrocade_MiST/rtl/roms/balcheck.hex b/Bally - Astrocade_MiST/rtl/roms/balcheck.hex new file mode 100644 index 00000000..8799da19 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/balcheck.hex @@ -0,0 +1,129 @@ +:10000000C3AD2087878787C92F0F0F2F0055AAFF01 +:10001000282777271620F308DB15A72029DB16A74A +:100020002030DB17A7200FDB14A72836FE01CA27D4 +:1000300026FE02CABA27FE01CAD925FE02CA4F26E9 +:10004000FE102818181CFE01CA1126FE02CA4827F5 +:100050001810FE01CAEA25FE02CA7326D979E60FF6 +:100060004FD9D9147AFE3C20401600CB4320117999 +:10007000FE8420043EB1180978A720053EA018018F +:10008000AFD3FF1C7BFE3C20201E00247CFE3C20C6 +:100090001826002C7DCD0320FEA0200478C606473C +:1000A0000478FE992003AF476FD908FBC9F3D9AF95 +:1000B000470E81575F676FD93EAAD3FF3E00D30832 +:1000C0003EC8D30AAF0E14ED78A720080C79FE18AD +:1000D000280918F31E0121EF23186CFD21E220C32B +:1000E000642118044E50004F31C84F3E08D30E21F2 +:1000F00014207CED477DD30DAFD30FED5EFB1601D1 +:10010000CDCF25F3D97AA7200E7BA7200AD91E02CE +:100110000EFF21EF2318300E80D9FB0100202100B3 +:1001200000AF8657230D20FA0520F77AFEA4200A97 +:10013000C34A217CFE28281218E71E037CD6084FEC +:1001400020020EA0214A21C3E623F3FD21512118EC +:100150001318044E50004FFBFD215E21180618684D +:100160003F4F00400E000601FD6605FD6E04707EE7 +:10017000A82806DD217921184B237CFDBE0320EE43 +:100180002B7CFDBE0228167EA82806DD21912118B1 +:1001900033782F77AE28E9DD2180211827237CFDD5 +:1001A000BE03280F782FAE2806DD21AF211815AF2A +:1001B0007718EACB2030B179A72002FDE91E04218F +:1001C000C821184FB14FDDE9FD211008DD2110488D +:1001D000AF4F060179D30CAF676FFD77007868FDEC +:1001E0007700AFFD770179A7280BCB1DCB1CCB1D6A +:1001F000CB1C3D20F5DD7E00BD2013DD7E01BC2043 +:100200000DCB1030CF793C4FFE0420C618071E05D9 +:1002100021152218333E40D30C111048214A220EDA +:100220000179FD77001ABE201A23CB2130F3CB19B8 +:10023000792FFD77001ABE200723CB3930F2181A28 +:10024000792F4F1E07215A2218474080102004089A +:100250000102FDFEF7FBDFEF7FBF3E08D30CAF4F7F +:1002600057210C20D31906047EFD7700FD7701DDB0 +:100270007E00BA2017DD7E01BA20112310EA7AC66B +:10028000555779C6054FFE1420DA18071E12219320 +:100290002218383E10CDCE22CDE322FE01281CFECE +:1002A0000228143E20CDCE222CCDE322FE012812BE +:1002B000FE022812C33A231E1018021E0821A32290 +:1002C00018091E0918021E11213A23C3E623D30C74 +:1002D000DB08210401AF575F4F6F0604C93E01C917 +:1002E0003E02C9CD3323CD3323CD3323AFBD20040C +:1002F0007AB118027AA9DDBE0020E279A72807DBCF +:1003000008BB20DC1805DB08B920D579844F10D351 +:10031000010004CB3BCB24CB2430C8CB147BA720DB +:10032000041E881802CB3B7AC655570100041E886C +:1003300030B1C9DD7200FD7100C906FFDB0EDB0FB5 +:100340000E10ED78A7C2C8230C79FE1420F4DB143C +:10035000DB15DB16DB170E1CED78FEFF20710C7928 +:10036000FE2020F410D606FF3E00D30878D300D339 +:1003700004D301D305D302D306D303D3073E14D34A +:10038000093EC8D30A5021DE2306080E0BEDB32127 +:10039000D62306080E18EDB33EFFD317D316D31499 +:1003A0007AD310D311D312D313D3154210BAF3D981 +:1003B00079CB7F280A0C79FE842008D9FB18FEA788 +:1003C00020010CD9FBC31B211E13214E2318171E1D +:1003D00014216823181048443400FFFDF5F5DB9222 +:1003E0004900DB924900F3D979D9E60FA728507B61 +:1003F000D3FF21F723183979D3FF21FF2318313E8A +:10040000CBD3FF21082418283EDED3FF2111241866 +:100410001FD978D9212024A720023EA0D3FF18108D +:100420003EAAD3FF21292418073EAAD3FF21EF2398 +:1004300016023EFF06FF10FE3D20F91520F4E9FBF1 +:10044000E9454E545220342D4449475420484558DC +:1004500000524541442041444452005752495445BA +:10046000204144445200454E545220322D444947C5 +:100470005420484558005245414420504F525400A2 +:10048000575249544520504F52540053545254200F +:100490004144445200454E545220322D4449475461 +:1004A0002048455800444154410042595445205485 +:1004B0004F205752495445002A2A002A2A2A2A0046 +:1004C00030453D30463D20202020202031303D3138 +:1004D000313D31323D31333D31343D31353D3136C1 +:1004E0003D31373D20202031433D31443D31453DB4 +:1004F00031463D22474F2220544F2052554E00AFE7 +:10050000D304D300D3093E0FD301D302D303FF1B7F +:100510000040B00F00C9FF3504280C4124C9FF3545 +:1005200004320C5124C9FF3504280C6624C9FF3558 +:1005300004280C9524FF3504320CAA24C90E0CDDC6 +:10054000210D02FF32C9FE0AFA4D25C607C630C981 +:10055000D5E53EFF32EC4FFF430820FE1320F8782C +:10056000FE102001AFFE14F26E2547CD4625E1D1E5 +:10057000C9F5A72009FF3548460CB8241807FF35F0 +:1005800048460CBB24210000CD5025FE18283EFE15 +:100590001528E2114846CD3D2578CD032067CD5082 +:1005A00025FE1528D0CD3D257CB067F1A72001C9D7 +:1005B000F5CD5025FE1528C6CD3D2578CD03206FFD +:1005C000CD5025FE1528B7CD3D257DB06FF1C93E34 +:1005D000FF06FF10FE3D20F9C9CDFF24CD1625CD25 +:1005E0001E253E01CD71257E18FDCDFF24CD2E2583 +:1005F000AFCD7125E57CD3FFCDCF25CDFF24CD1622 +:1006000025FF3504320C5B243E01CD7125C17018E5 +:10061000FDCDFF24CD2625FF3504320C7624AFCD49 +:1006200071254CED7818FCCDFF24CD2625FF35042F +:10063000320C8024AFCD7125E57CD3FFCDCF25CD05 +:10064000FF24CD2E25AFCD7125C148ED6118FCCD1D +:10065000FF24CD2E25AFCD7125E57CD3FFCDCF2551 +:10066000CDFF24CD1625CD1E253E01CD7125C170AF +:100670007E18FCCDFF2421C02411040ACDFB2621C5 +:10068000D824115000CDFB2608AF082110207CEDA6 +:10069000477DD30D3E03D30EFBDB10111C32CD1171 +:1006A00027DB11111C3CCD1127DB12111C46CD118B +:1006B00027DB13111C50CD1127DB14116800CD115D +:1006C00027DB1511680ACD1127DB16116814CD112F +:1006D00027DB1711681ECD1127DB1C116832CD11E5 +:1006E00027DB1D11683CCD1127DB1E116846CD119B +:1006F00027DB1F116850CD1127189E06037ECD3DC4 +:10070000252310F97BD6185F7AC60A57FE5A20EBCC +:10071000C967E6F00F0F0F0FCD4625CD3D257CE6CE +:100720000FCD4625CD3D25C9F308A7281708DB0EB8 +:10073000CB3F111C0ACD1127DB0FD608111C14CD9D +:100740001127FBC93C0818FA11004021A627011403 +:1007500000EDB021004001DC0FEDB02112207CED56 +:10076000477DD30D3E14D309010FF811002021005D +:10077000503E04ED59FB76F3D3003CD3013CD30249 +:100780003CD303A0D3043CD3053CD3063CD307C6DB +:10079000091C1C1C1C1C1C15C2A0271100203E0497 +:1007A000ED59DDE1FB76000000000055555555552B +:1007B000AAAAAAAAAAFFFFFFFFFFCDFF24CD1625F4 +:1007C000FF3504320C8B243E01CD7125E5E5CDCFFC +:1007D00025CDFF24FF3504280C9524FF3504320C69 +:1007E000A524FF35045A0CF324CDCF25AFCD7125B8 +:1007F00078FE182003E1E1E9D17C1213D518EA371D +:00000001FF diff --git a/Bally - Astrocade_MiST/rtl/roms/bally_bios_0.vhd b/Bally - Astrocade_MiST/rtl/roms/bally_bios_0.vhd new file mode 100644 index 00000000..a9e484ff --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/bally_bios_0.vhd @@ -0,0 +1,493 @@ +-- generated with romgen v3.0 by MikeJ +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + use ieee.numeric_std.all; + +library UNISIM; + use UNISIM.Vcomponents.all; + +entity BALLY_BIOS_0 is + port ( + CLK : in std_logic; + ENA : in std_logic; + ADDR : in std_logic_vector(11 downto 0); + DATA : out std_logic_vector(7 downto 0) + ); +end; + +architecture RTL of BALLY_BIOS_0 is + + function romgen_str2bv (str : string) return bit_vector is + variable result : bit_vector (str'length*4-1 downto 0); + begin + for i in 0 to str'length-1 loop + case str(str'high-i) is + when '0' => result(i*4+3 downto i*4) := x"0"; + when '1' => result(i*4+3 downto i*4) := x"1"; + when '2' => result(i*4+3 downto i*4) := x"2"; + when '3' => result(i*4+3 downto i*4) := x"3"; + when '4' => result(i*4+3 downto i*4) := x"4"; + when '5' => result(i*4+3 downto i*4) := x"5"; + when '6' => result(i*4+3 downto i*4) := x"6"; + when '7' => result(i*4+3 downto i*4) := x"7"; + when '8' => result(i*4+3 downto i*4) := x"8"; + when '9' => result(i*4+3 downto i*4) := x"9"; + when 'A' => result(i*4+3 downto i*4) := x"A"; + when 'B' => result(i*4+3 downto i*4) := x"B"; + when 'C' => result(i*4+3 downto i*4) := x"C"; + when 'D' => result(i*4+3 downto i*4) := x"D"; + when 'E' => result(i*4+3 downto i*4) := x"E"; + when 'F' => result(i*4+3 downto i*4) := x"F"; + when others => null; + end case; + end loop; + return result; + end romgen_str2bv; + + attribute INIT_00 : string; + attribute INIT_01 : string; + attribute INIT_02 : string; + attribute INIT_03 : string; + attribute INIT_04 : string; + attribute INIT_05 : string; + attribute INIT_06 : string; + attribute INIT_07 : string; + attribute INIT_08 : string; + attribute INIT_09 : string; + attribute INIT_0A : string; + attribute INIT_0B : string; + attribute INIT_0C : string; + attribute INIT_0D : string; + attribute INIT_0E : string; + attribute INIT_0F : string; + attribute INIT_10 : string; + attribute INIT_11 : string; + attribute INIT_12 : string; + attribute INIT_13 : string; + attribute INIT_14 : string; + attribute INIT_15 : string; + attribute INIT_16 : string; + attribute INIT_17 : string; + attribute INIT_18 : string; + attribute INIT_19 : string; + attribute INIT_1A : string; + attribute INIT_1B : string; + attribute INIT_1C : string; + attribute INIT_1D : string; + attribute INIT_1E : string; + attribute INIT_1F : string; + attribute INIT_20 : string; + attribute INIT_21 : string; + attribute INIT_22 : string; + attribute INIT_23 : string; + attribute INIT_24 : string; + attribute INIT_25 : string; + attribute INIT_26 : string; + attribute INIT_27 : string; + attribute INIT_28 : string; + attribute INIT_29 : string; + attribute INIT_2A : string; + attribute INIT_2B : string; + attribute INIT_2C : string; + attribute INIT_2D : string; + attribute INIT_2E : string; + attribute INIT_2F : string; + attribute INIT_30 : string; + attribute INIT_31 : string; + attribute INIT_32 : string; + attribute INIT_33 : string; + attribute INIT_34 : string; + attribute INIT_35 : string; + attribute INIT_36 : string; + attribute INIT_37 : string; + attribute INIT_38 : string; + attribute INIT_39 : string; + attribute INIT_3A : string; + attribute INIT_3B : string; + attribute INIT_3C : string; + attribute INIT_3D : string; + attribute INIT_3E : string; + attribute INIT_3F : string; + + component RAMB16_S4 + --pragma translate_off + generic ( + INIT_00 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_01 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_02 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_03 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_04 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_05 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_06 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_07 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_08 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_09 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_10 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_11 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_12 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_13 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_14 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_15 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_16 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_17 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_18 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_19 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_20 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_21 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_22 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_23 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_24 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_25 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_26 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_27 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_28 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_29 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_30 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_31 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_32 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_33 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_34 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_35 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_36 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_37 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_38 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_39 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000" + ); + --pragma translate_on + port ( + DO : out std_logic_vector (3 downto 0); + ADDR : in std_logic_vector (11 downto 0); + CLK : in std_logic; + DI : in std_logic_vector (3 downto 0); + EN : in std_logic; + SSR : in std_logic; + WE : in std_logic + ); + end component; + + signal rom_addr : std_logic_vector(11 downto 0); + +begin + + p_addr : process(ADDR) + begin + rom_addr <= (others => '0'); + rom_addr(11 downto 0) <= ADDR; + end process; + + rom0 : if true generate + attribute INIT_00 of inst : label is "5D5D5553F11B0063F9001033F92330039D06B0D3F27A60A3F0CCC073C1383F30"; + attribute INIT_01 of inst : label is "B3E1194ED56D9ED1D52ED36DAEDB6D563E9FDA30706F70B15568F2A13E9D001D"; + attribute INIT_02 of inst : label is "B0B333315D37D3A27D3AA80B5311A86ED76D9108D69FBA387B1B106B20F50C1F"; + attribute INIT_03 of inst : label is "4712A7D397E7D7C79757B6E62AE1B3F5C584E1B04A4B30D62290B9B60373A308"; + attribute INIT_04 of inst : label is "C36393E3134242E3F31DABBBDBCB0B6C5BC0BD1CBC71A6B6C1CA96366ABA6BB7"; + attribute INIT_05 of inst : label is "BBBB8F0000078FC3000300400F77F3FB3FF330FF0A0040800000020033CC13F3"; + attribute INIT_06 of inst : label is "63533FB07FCA09AAEFAA9B11114EDFE40DD34EF38E7D0EED55553730008BBBB8"; + attribute INIT_07 of inst : label is "00DDD49FC2FE0CE83E70D97D3CD9F3D8B1F82F8AB096D70C15DC4D241C09D8B1"; + attribute INIT_08 of inst : label is "035D1706F03032591C006F03052F33081D7EDADEFFFFAF5164084718804B3403"; + attribute INIT_09 of inst : label is "11D1D119301110D59B755F0B388B98B37FCFFDA08BB83B26D7F18368781BB26D"; + attribute INIT_0A of inst : label is "581130D37B3EF4FA81F61807CA8EF4FFBBBD190653B110DBF99B9065320D9311"; + attribute INIT_0B of inst : label is "99B06855111C0D33B907D7EFB98733E20D9D8AEDB6D55597D058F7B2FB2FFF1D"; + attribute INIT_0C of inst : label is "706EB80377E0EB80EE906D8EFBCFBCFAF9D01AF281B112FE387C036F8B510D1B"; + attribute INIT_0D of inst : label is "5987DF79E803327EAF970EE9D068964D068EB9D068980377E0EFB068EB906D89"; + attribute INIT_0E of inst : label is "BF3031B9A9B057976FD4A1390DC109F88AF71BAF1293CDFF1AFF2A90713CDFFA"; + attribute INIT_0F of inst : label is "34C139D38639D06FD15891287B980303FF9811E9E31DC1D9E940198E10D7554B"; + attribute INIT_10 of inst : label is "AC0F4B82E8603CDA068DF01471B04D591E7FB68FBEF31C0C99773C6886583E8D"; + attribute INIT_11 of inst : label is "860059B6797F67E9C6797067E06C87B9870C50E8D34019B7F67E78F6E13EC377"; + attribute INIT_12 of inst : label is "BBE811D54D5D5B05C87EFA1BEB0EBF919FD22FDAD0AB377107D687EA09B06F51"; + attribute INIT_13 of inst : label is "286BF819877DE877DE396907EB3863E35187EBEBF31B3B652253536340DD80BE"; + attribute INIT_14 of inst : label is "3D90FB463D20FB563D20FB881F4AFA25BA73EF0ADFEA385CDF02DF429EBF91EB"; + attribute INIT_15 of inst : label is "00EE8F423E70783DF0676083D881888FB500E54353F3A63F2AC07583548B78FB"; + attribute INIT_16 of inst : label is "284EB363EB83D06D3D0EDC09EF6700E18333DA005DB0780D0DF21900EE8CFF66"; + attribute INIT_17 of inst : label is "FA2F9F02DFE25363F3FA2E280EC8F920EF9AA0689D4F06F6A00E6803DBD02DBD"; + attribute INIT_18 of inst : label is "6D2EDE1BD68BD9B511401B0D29BB63E1E83348AF6391280EFE7589C09D881F92"; + attribute INIT_19 of inst : label is "48870FE363C1864BD68BD48CD091C2ED36D0ED16D59D05166D9D031879861D02"; + attribute INIT_1A of inst : label is "F99EDC34BBBEDF9E4BD134D25D33912D03D3FFB7FA8E4BD1E4BD026D30D30886"; + attribute INIT_1B of inst : label is "ED93111070ECF86D7E1EBFFFAFF255F62D7806FF68DFFC3696862DFE7857CF6F"; + attribute INIT_1C of inst : label is "037373A155B9101B98EB120D755F10FBC07BA6D363E1723EF33E561BD6EDB6D0"; + attribute INIT_1D of inst : label is "1BD9B0198E10B080B7B73A155B9C01B98EB1274ABB0D755F60FB9B0198E10308"; + attribute INIT_1E of inst : label is "B98E1B0D755F2B363EB97059C03738F38E064B9F6FC4DB8860BDDEDE6D61BD86"; + attribute INIT_1F of inst : label is "6DB850D1C4D8ED5D00E261D7DA75D553808D08DB377608371D604E7EA87E9201"; + attribute INIT_20 of inst : label is "ED9111DC4D1C057D15ED193ED18CD5546D58ED95ED66D70DD0946D3ED00106F0"; + attribute INIT_21 of inst : label is "93CE15D9D001D5D063ED9FF7B026D1A980EB016D4ED56D88ED97D0F7F7C36776"; + attribute INIT_22 of inst : label is "5BB8D8606936ED04D8ED10DD4900111B8037373A154B92D2D7B7718066EDC38E"; + attribute INIT_23 of inst : label is "88C8C8800000000000000000000091D9D00C311198E1018364ED8037373A1555"; + attribute INIT_24 of inst : label is "0000000000080000808080000000000000000000000808000088000800080080"; + attribute INIT_25 of inst : label is "0008880080080000088088080008800000000088888000000800000000000800"; + attribute INIT_26 of inst : label is "8800008000008080000000000000000000000000888800880880000008808800"; + attribute INIT_27 of inst : label is "8888888008000000088000008088888008000800880880888888080888800000"; + attribute INIT_28 of inst : label is "8888000008808888888888888888888888000000800000808888880000000888"; + attribute INIT_29 of inst : label is "0000880000088880008888888880000888088888800000080880080800088080"; + attribute INIT_2A of inst : label is "0008000080008000080000080000000800000008000000000080000000000008"; + attribute INIT_2B of inst : label is "2BBED58B8D9AFA1D7BDE06B321D654A987FB325CE30997DE9A510689D31D0000"; + attribute INIT_2C of inst : label is "000000000000000000000000000000000000000000000000009C3BED9852D43D"; + attribute INIT_2D of inst : label is "B0655B8BBD911B906FFBFB999D499906A06F38B065536BFC6590D00000000000"; + attribute INIT_2E of inst : label is "06F88C4DB63E92B3B06F917EF6E3806E7777981B199B065591F6FFFF481B1E99"; + attribute INIT_2F of inst : label is "68B401388B70BBDF8DF68FD12671DAE89B1BBDE6BD5FE1262D1D9A5DB4D97DE9"; + attribute INIT_30 of inst : label is "810BB9EBF81078EA36F618FBF8A331603307716E536080ED8971D06280BA6F66"; + attribute INIT_31 of inst : label is "9F750FFC2DFF2002FEBFFE100A3E00A0256F65D177403E484E243FEFC7C805F4"; + attribute INIT_32 of inst : label is "D16D40E728E4F2ED36D2FDE2F0681D191C01D9D55AF281385E3E001D312F0398"; + attribute INIT_33 of inst : label is "9D555952D43D551163E363E3A063EB711982FFE688387E1EFD0111159B05C50E"; + attribute INIT_34 of inst : label is "D618F697EDFD9D994F4E08115D818BF01800BF59F1FEF0011B7114F1D79085FD"; + attribute INIT_35 of inst : label is "C4879A070E97FF7CB4628A61E9890C9FE09BA8C980BD1CD54DF39DC5F0B3F6F5"; + attribute INIT_36 of inst : label is "1A00254E59B03FD17E6C8591AF17FF9FE6C85959916F50F9F688DE0F9BCD9D40"; + attribute INIT_37 of inst : label is "875D170435C5307E9C22923302F41C53C130541DB3583048796E57E9D80038D3"; + attribute INIT_38 of inst : label is "DE890C08E8F8887008E0B0E000B0FE81F3128DFFFFF08791076D09CC120938D8"; + attribute INIT_39 of inst : label is "DF49718BF9DF1FFF84E83E5FFFF9E15FE53F5E812F54BF403DF606DF843DFA46"; + attribute INIT_3A of inst : label is "19D0E195EA155F7F3AE01DE93EC2F319F32F9F624EE89F733337E76E488B6AE8"; + attribute INIT_3B of inst : label is "B806F4DF0992FEFCEDD6D87A15D9B7D05E4BEDA7D308E2AED01DF6F4DF099001"; + attribute INIT_3C of inst : label is "2DAFAEDB6D5006F3DF8F188421FA509CF8F2DF367797AEDB6DF6DF36F77EBBBB"; + attribute INIT_3D of inst : label is "E51F32533787F247FF72533787F2C36288E07FF925E31E01F81CF83115DBC3DD"; + attribute INIT_3E of inst : label is "0ECFC720CE57FADE36E317240EE4A3F2D00E2AFA101DAE2287F2187E583ECA7F"; + attribute INIT_3F of inst : label is "F524E401FDD59DF211EADE61EADE51EADE41F024EDF3AA81EFC2FECF41CFCF31"; + begin + inst : RAMB16_S4 + --pragma translate_off + generic map ( + INIT_00 => romgen_str2bv(inst'INIT_00), + INIT_01 => romgen_str2bv(inst'INIT_01), + INIT_02 => romgen_str2bv(inst'INIT_02), + INIT_03 => romgen_str2bv(inst'INIT_03), + INIT_04 => romgen_str2bv(inst'INIT_04), + INIT_05 => romgen_str2bv(inst'INIT_05), + INIT_06 => romgen_str2bv(inst'INIT_06), + INIT_07 => romgen_str2bv(inst'INIT_07), + INIT_08 => romgen_str2bv(inst'INIT_08), + INIT_09 => romgen_str2bv(inst'INIT_09), + INIT_0A => romgen_str2bv(inst'INIT_0A), + INIT_0B => romgen_str2bv(inst'INIT_0B), + INIT_0C => romgen_str2bv(inst'INIT_0C), + INIT_0D => romgen_str2bv(inst'INIT_0D), + INIT_0E => romgen_str2bv(inst'INIT_0E), + INIT_0F => romgen_str2bv(inst'INIT_0F), + INIT_10 => romgen_str2bv(inst'INIT_10), + INIT_11 => romgen_str2bv(inst'INIT_11), + INIT_12 => romgen_str2bv(inst'INIT_12), + INIT_13 => romgen_str2bv(inst'INIT_13), + INIT_14 => romgen_str2bv(inst'INIT_14), + INIT_15 => romgen_str2bv(inst'INIT_15), + INIT_16 => romgen_str2bv(inst'INIT_16), + INIT_17 => romgen_str2bv(inst'INIT_17), + INIT_18 => romgen_str2bv(inst'INIT_18), + INIT_19 => romgen_str2bv(inst'INIT_19), + INIT_1A => romgen_str2bv(inst'INIT_1A), + INIT_1B => romgen_str2bv(inst'INIT_1B), + INIT_1C => romgen_str2bv(inst'INIT_1C), + INIT_1D => romgen_str2bv(inst'INIT_1D), + INIT_1E => romgen_str2bv(inst'INIT_1E), + INIT_1F => romgen_str2bv(inst'INIT_1F), + INIT_20 => romgen_str2bv(inst'INIT_20), + INIT_21 => romgen_str2bv(inst'INIT_21), + INIT_22 => romgen_str2bv(inst'INIT_22), + INIT_23 => romgen_str2bv(inst'INIT_23), + INIT_24 => romgen_str2bv(inst'INIT_24), + INIT_25 => romgen_str2bv(inst'INIT_25), + INIT_26 => romgen_str2bv(inst'INIT_26), + INIT_27 => romgen_str2bv(inst'INIT_27), + INIT_28 => romgen_str2bv(inst'INIT_28), + INIT_29 => romgen_str2bv(inst'INIT_29), + INIT_2A => romgen_str2bv(inst'INIT_2A), + INIT_2B => romgen_str2bv(inst'INIT_2B), + INIT_2C => romgen_str2bv(inst'INIT_2C), + INIT_2D => romgen_str2bv(inst'INIT_2D), + INIT_2E => romgen_str2bv(inst'INIT_2E), + INIT_2F => romgen_str2bv(inst'INIT_2F), + INIT_30 => romgen_str2bv(inst'INIT_30), + INIT_31 => romgen_str2bv(inst'INIT_31), + INIT_32 => romgen_str2bv(inst'INIT_32), + INIT_33 => romgen_str2bv(inst'INIT_33), + INIT_34 => romgen_str2bv(inst'INIT_34), + INIT_35 => romgen_str2bv(inst'INIT_35), + INIT_36 => romgen_str2bv(inst'INIT_36), + INIT_37 => romgen_str2bv(inst'INIT_37), + INIT_38 => romgen_str2bv(inst'INIT_38), + INIT_39 => romgen_str2bv(inst'INIT_39), + INIT_3A => romgen_str2bv(inst'INIT_3A), + INIT_3B => romgen_str2bv(inst'INIT_3B), + INIT_3C => romgen_str2bv(inst'INIT_3C), + INIT_3D => romgen_str2bv(inst'INIT_3D), + INIT_3E => romgen_str2bv(inst'INIT_3E), + INIT_3F => romgen_str2bv(inst'INIT_3F) + ) + --pragma translate_on + port map ( + DO => DATA(3 downto 0), + ADDR => rom_addr, + CLK => CLK, + DI => "0000", + EN => ENA, + SSR => '0', + WE => '0' + ); + end generate; + rom1 : if true generate + attribute INIT_00 of inst : label is "EFEDDCFEF008021CFC00221CFC72721CCF17F20CF60F020CF213120C06C0DAF0"; + attribute INIT_01 of inst : label is "C27EDC05F05F07FEDD05F05F06F06FD52514F203101500C2DE331071273F002F"; + attribute INIT_02 of inst : label is "CAC2222EEF07F1107F11026CE2DEA104F04F7D0AC404F2027C04200E134D0713"; + attribute INIT_03 of inst : label is "C0E060A0B0907010101000F0B0E0D0C0F0007080A0C0707030707CEF22711033"; + attribute INIT_04 of inst : label is "40502060406080D01020A040B0A0907010C01030F090B00000A0C03050F0F0E0"; + attribute INIT_05 of inst : label is "CCCCCCCCCCC00CEC0CC00DD22CC2CCCC1EEEED22C20F000C0CC0004020604070"; + attribute INIT_06 of inst : label is "1D1DFA22B4E321CAF4F3CFFCDE07C000AC0D330DC34E035EEDCFFCCE02C00C0C"; + attribute INIT_07 of inst : label is "120D0CC4E3F3D1FD1F07F07F0ECCABE0004E24E2F003FE230EC0FC011F17E000"; + attribute INIT_08 of inst : label is "05444424422055454452442204544525441D0C0B33330B0000A0E0000207C0AC"; + attribute INIT_09 of inst : label is "DEDEFEECF1CDEBEE1E4DCA02CD0CC0C2627627030C0BCE05C42020E7027CE05C"; + attribute INIT_0A of inst : label is "51CEE20E72E6F7F61CF3EF223036F7FA11E0C000CE2DCBEE403C700CE0CCCEFC"; + attribute INIT_0B of inst : label is "03C004CDCEEE20E2EF223A6FE02AE270CCED406F06FEEC34F1E766E7FE7F4AED"; + attribute INIT_0C of inst : label is "78F72F1272903ED5F7102266FE6FE6F6FCF1E6F024CEC1F302AF12BA3CCCBE2C"; + attribute INIT_0D of inst : label is "FC07F219FF1211281AC78E700004C03F03C7C12026CF1272903AE03C7C10226C"; + attribute INIT_0E of inst : label is "EA2727EC80F211201A440DCF203031A0274AFE54F210AC54F24E2800100AC4E2"; + attribute INIT_0F of inst : label is "20100DC2010DC014D222CE877ACF102A4070005C0D5E04E00CF1C020EBE4ECFC"; + attribute INIT_10 of inst : label is "7F30101117F121002A7EF01010E07CEC137BC027C74E2E10C74783030D03957E"; + attribute INIT_11 of inst : label is "007C3C0D0740E7AC0D0741E7A1E026CC7F1002A7E2010C747E7A027EAE113800"; + attribute INIT_12 of inst : label is "CE01EED01CEDE02312B74E2ECCC4C4F2C4D3B4D3E11C273022302B7033C014D2"; + attribute INIT_13 of inst : label is "024C4F20172301723725302B7212B272302B7EFC4E2E23300F321D1D023302E7"; + attribute INIT_14 of inst : label is "AE033C00AE033C00AE033C0104D34E305FB274D2D4C2010FC4D2D4D3C8C4F2FC"; + attribute INIT_15 of inst : label is "3BF914D32702A1AE41F0EB1BE0107025C139F0FC1D4D31D4D3E2BF120012033C"; + attribute INIT_16 of inst : label is "D30FE2525D12D06D2D06D020F0E23DFF1222D0203D0281AEAE4D103CF31150E0"; + attribute INIT_17 of inst : label is "4E3AC4D2D4C21D1DA24E3712FFA14F38E4F302E10554000E03EFC107D2D07D2D"; + attribute INIT_18 of inst : label is "3D04D70CDF0CFEEEFD027C07C7CE525DE12202B3E2CD03CF475D7CF17E0104F3"; + attribute INIT_19 of inst : label is "03B03CF24E73240CDB0CF02BF114706D06D05D05DE1D00105C1D001CA7C07F00"; + attribute INIT_1A of inst : label is "0705F0DFCE04CAC90CDE07D07DE2C07D07D1527527C40CDFD0CD003D07D223B4"; + attribute INIT_1B of inst : label is "7DC2ECF160C762C77AAA744F30F3CEA0ECF1CC00020A430E7F10ECF3021533E0"; + attribute INIT_1C of inst : label is "12727114ECECF1CE020ED1BE4DCA125C227C0FC2424F58275827FF0CD05D05D0"; + attribute INIT_1D of inst : label is "0CDCE1C020E727F12727114ECECE1CE020ED105E11AE4DCA125CCE1C020E727F"; + attribute INIT_1E of inst : label is "E020EEBE4DCAFC2424ECF210F12747492300FC0F0434E70270CD06D06DB0CDC7"; + attribute INIT_1F of inst : label is "9D31F23F0FC04CF032F002D0EFAEDECE106C0ACE241EF120EC036F0CFCA7CF1C"; + attribute INIT_20 of inst : label is "7FCCEED0FCDE107F807FC004DE06CEC04DD04C105D05DF20F1104D04D0020150"; + attribute INIT_21 of inst : label is "1D03DED3D002DED0004DC5A5F108D4703AFF108D07F05F403CC4F183A430E000"; + attribute INIT_22 of inst : label is "FE00C0F3E1D07F07C03CE23553002F2CF12727114FBCF4E4EAE0022CE07F0D03"; + attribute INIT_23 of inst : label is "44F4F44000055520222220000000CEDFDE10DFCD020E7020E07FF12727114EDC"; + attribute INIT_24 of inst : label is "04266000022F2200A7D7A042222241222221000066669A4A9619421CC2F07872"; + attribute INIT_25 of inst : label is "437800F8F11F95317803087F8870877222262788888708421006600000000F00"; + attribute INIT_26 of inst : label is "087421012400F0F0012484214266066066066061078877887887444210F788F8"; + attribute INIT_27 of inst : label is "F8887898887888E88FF88E88FF88888F7888887F88F88F888F88778BAB872021"; + attribute INIT_28 of inst : label is "A8887888F88FF88888F8889AC8888AAD8F88888889ACA9878000007222227888"; + attribute INIT_29 of inst : label is "84210F222258888525888DAA88822558887888888222222F780788789AF88F69"; + attribute INIT_2A of inst : label is "020F0200852580021F12027A2222024F4202222A72711111700124807444447F"; + attribute INIT_2B of inst : label is "FC04C0100CC0EEAE7E3232233323332333235525542C07F700D2004EDEED0000"; + attribute INIT_2C of inst : label is "2EAEEAEAE2222EEAE8EE2E8E22EAAE262EE8E2E44444EAAAE0C0D04CC107F07F"; + attribute INIT_2D of inst : label is "C00CE8107CCEFE10153C3C12255222026AC20274EFB0E76FEECBEEEEE404040E"; + attribute INIT_2E of inst : label is "015010FC252511C2C015CE7A0EA01FEA0000024CC03C00CECE0E0000024CC703"; + attribute INIT_2F of inst : label is "CBC12B027C0207C4F33E74E2400ECB3C7CC0ECB0CFC4E240002DC07F07F07F71"; + attribute INIT_30 of inst : label is "1F121CFC4F2D02B1004F1C4C4F322EF1202720C7E00F123D170EC8F027C2C0E0"; + attribute INIT_31 of inst : label is "2B110F4E330F30034C1F4C320CCF2030545404444CF21F021F014F0F054133FF"; + attribute INIT_32 of inst : label is "D06D01158033F06D06D3F233F3C7ED00001101CEE4F012025F272020F1000110"; + attribute INIT_33 of inst : label is "1CCEFC07F07FECFE42425252F1525E4DEE13F3303B02A7C4F411000C3D2B7E06"; + attribute INIT_34 of inst : label is "032C3EA07F409CDC3F00011E5044B1F00B401FDC05F4F331FC4FE3FE0B0203F0"; + attribute INIT_35 of inst : label is "0117DF120C165A51D6002000FD7DC37F0C7C3237C6C061051071C044F004F7FE"; + attribute INIT_36 of inst : label is "0F0254544CF126EF43E37FCC1FD4A4D13E37EDCCDD3FD6FD0E023F4FFC009C02"; + attribute INIT_37 of inst : label is "064444254444504444444545054544544440454444444054444454010E00120D"; + attribute INIT_38 of inst : label is "74E110004E502B10074F10064010F4E34F0024FFFFF033332444254444224205"; + attribute INIT_39 of inst : label is "5F976A7E025FA00A21F70000002C0A4F064FE05204D074635744347422574024"; + attribute INIT_3A of inst : label is "E1D011ED0B1EC444F34F2D0610900D0C4E3AC4D3134E1F722227A0EA025C814E"; + attribute INIT_3B of inst : label is "2C1E4E5F97C1A2F16D16DCA1DEDC17DD5F817D17D039F817D10C0E4E5F97CF1C"; + attribute INIT_3C of inst : label is "7D3F15D15DEC1E4E5F7F0F0000FA50C1F4025F0E007415D15D025F0E40072222"; + attribute INIT_3D of inst : label is "4F109F312777F107F07F312777F130E030F37F06F34F14F2A1E2F000DEDE17D1"; + attribute INIT_3E of inst : label is "A31F759953D601C7244F250D32F80050D35F8040010C14F327F1F20FF20F307F"; + attribute INIT_3F of inst : label is "4D303F1C02CC1DFE140AC0F20AC0E20AC0C205D0F34F321034E3F31F5E1F7599"; + begin + inst : RAMB16_S4 + --pragma translate_off + generic map ( + INIT_00 => romgen_str2bv(inst'INIT_00), + INIT_01 => romgen_str2bv(inst'INIT_01), + INIT_02 => romgen_str2bv(inst'INIT_02), + INIT_03 => romgen_str2bv(inst'INIT_03), + INIT_04 => romgen_str2bv(inst'INIT_04), + INIT_05 => romgen_str2bv(inst'INIT_05), + INIT_06 => romgen_str2bv(inst'INIT_06), + INIT_07 => romgen_str2bv(inst'INIT_07), + INIT_08 => romgen_str2bv(inst'INIT_08), + INIT_09 => romgen_str2bv(inst'INIT_09), + INIT_0A => romgen_str2bv(inst'INIT_0A), + INIT_0B => romgen_str2bv(inst'INIT_0B), + INIT_0C => romgen_str2bv(inst'INIT_0C), + INIT_0D => romgen_str2bv(inst'INIT_0D), + INIT_0E => romgen_str2bv(inst'INIT_0E), + INIT_0F => romgen_str2bv(inst'INIT_0F), + INIT_10 => romgen_str2bv(inst'INIT_10), + INIT_11 => romgen_str2bv(inst'INIT_11), + INIT_12 => romgen_str2bv(inst'INIT_12), + INIT_13 => romgen_str2bv(inst'INIT_13), + INIT_14 => romgen_str2bv(inst'INIT_14), + INIT_15 => romgen_str2bv(inst'INIT_15), + INIT_16 => romgen_str2bv(inst'INIT_16), + INIT_17 => romgen_str2bv(inst'INIT_17), + INIT_18 => romgen_str2bv(inst'INIT_18), + INIT_19 => romgen_str2bv(inst'INIT_19), + INIT_1A => romgen_str2bv(inst'INIT_1A), + INIT_1B => romgen_str2bv(inst'INIT_1B), + INIT_1C => romgen_str2bv(inst'INIT_1C), + INIT_1D => romgen_str2bv(inst'INIT_1D), + INIT_1E => romgen_str2bv(inst'INIT_1E), + INIT_1F => romgen_str2bv(inst'INIT_1F), + INIT_20 => romgen_str2bv(inst'INIT_20), + INIT_21 => romgen_str2bv(inst'INIT_21), + INIT_22 => romgen_str2bv(inst'INIT_22), + INIT_23 => romgen_str2bv(inst'INIT_23), + INIT_24 => romgen_str2bv(inst'INIT_24), + INIT_25 => romgen_str2bv(inst'INIT_25), + INIT_26 => romgen_str2bv(inst'INIT_26), + INIT_27 => romgen_str2bv(inst'INIT_27), + INIT_28 => romgen_str2bv(inst'INIT_28), + INIT_29 => romgen_str2bv(inst'INIT_29), + INIT_2A => romgen_str2bv(inst'INIT_2A), + INIT_2B => romgen_str2bv(inst'INIT_2B), + INIT_2C => romgen_str2bv(inst'INIT_2C), + INIT_2D => romgen_str2bv(inst'INIT_2D), + INIT_2E => romgen_str2bv(inst'INIT_2E), + INIT_2F => romgen_str2bv(inst'INIT_2F), + INIT_30 => romgen_str2bv(inst'INIT_30), + INIT_31 => romgen_str2bv(inst'INIT_31), + INIT_32 => romgen_str2bv(inst'INIT_32), + INIT_33 => romgen_str2bv(inst'INIT_33), + INIT_34 => romgen_str2bv(inst'INIT_34), + INIT_35 => romgen_str2bv(inst'INIT_35), + INIT_36 => romgen_str2bv(inst'INIT_36), + INIT_37 => romgen_str2bv(inst'INIT_37), + INIT_38 => romgen_str2bv(inst'INIT_38), + INIT_39 => romgen_str2bv(inst'INIT_39), + INIT_3A => romgen_str2bv(inst'INIT_3A), + INIT_3B => romgen_str2bv(inst'INIT_3B), + INIT_3C => romgen_str2bv(inst'INIT_3C), + INIT_3D => romgen_str2bv(inst'INIT_3D), + INIT_3E => romgen_str2bv(inst'INIT_3E), + INIT_3F => romgen_str2bv(inst'INIT_3F) + ) + --pragma translate_on + port map ( + DO => DATA(7 downto 4), + ADDR => rom_addr, + CLK => CLK, + DI => "0000", + EN => ENA, + SSR => '0', + WE => '0' + ); + end generate; +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/roms/bally_bios_1.vhd b/Bally - Astrocade_MiST/rtl/roms/bally_bios_1.vhd new file mode 100644 index 00000000..88ff69a4 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/bally_bios_1.vhd @@ -0,0 +1,493 @@ +-- generated with romgen v3.0 by MikeJ +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + use ieee.numeric_std.all; + +library UNISIM; + use UNISIM.Vcomponents.all; + +entity BALLY_BIOS_1 is + port ( + CLK : in std_logic; + ENA : in std_logic; + ADDR : in std_logic_vector(11 downto 0); + DATA : out std_logic_vector(7 downto 0) + ); +end; + +architecture RTL of BALLY_BIOS_1 is + + function romgen_str2bv (str : string) return bit_vector is + variable result : bit_vector (str'length*4-1 downto 0); + begin + for i in 0 to str'length-1 loop + case str(str'high-i) is + when '0' => result(i*4+3 downto i*4) := x"0"; + when '1' => result(i*4+3 downto i*4) := x"1"; + when '2' => result(i*4+3 downto i*4) := x"2"; + when '3' => result(i*4+3 downto i*4) := x"3"; + when '4' => result(i*4+3 downto i*4) := x"4"; + when '5' => result(i*4+3 downto i*4) := x"5"; + when '6' => result(i*4+3 downto i*4) := x"6"; + when '7' => result(i*4+3 downto i*4) := x"7"; + when '8' => result(i*4+3 downto i*4) := x"8"; + when '9' => result(i*4+3 downto i*4) := x"9"; + when 'A' => result(i*4+3 downto i*4) := x"A"; + when 'B' => result(i*4+3 downto i*4) := x"B"; + when 'C' => result(i*4+3 downto i*4) := x"C"; + when 'D' => result(i*4+3 downto i*4) := x"D"; + when 'E' => result(i*4+3 downto i*4) := x"E"; + when 'F' => result(i*4+3 downto i*4) := x"F"; + when others => null; + end case; + end loop; + return result; + end romgen_str2bv; + + attribute INIT_00 : string; + attribute INIT_01 : string; + attribute INIT_02 : string; + attribute INIT_03 : string; + attribute INIT_04 : string; + attribute INIT_05 : string; + attribute INIT_06 : string; + attribute INIT_07 : string; + attribute INIT_08 : string; + attribute INIT_09 : string; + attribute INIT_0A : string; + attribute INIT_0B : string; + attribute INIT_0C : string; + attribute INIT_0D : string; + attribute INIT_0E : string; + attribute INIT_0F : string; + attribute INIT_10 : string; + attribute INIT_11 : string; + attribute INIT_12 : string; + attribute INIT_13 : string; + attribute INIT_14 : string; + attribute INIT_15 : string; + attribute INIT_16 : string; + attribute INIT_17 : string; + attribute INIT_18 : string; + attribute INIT_19 : string; + attribute INIT_1A : string; + attribute INIT_1B : string; + attribute INIT_1C : string; + attribute INIT_1D : string; + attribute INIT_1E : string; + attribute INIT_1F : string; + attribute INIT_20 : string; + attribute INIT_21 : string; + attribute INIT_22 : string; + attribute INIT_23 : string; + attribute INIT_24 : string; + attribute INIT_25 : string; + attribute INIT_26 : string; + attribute INIT_27 : string; + attribute INIT_28 : string; + attribute INIT_29 : string; + attribute INIT_2A : string; + attribute INIT_2B : string; + attribute INIT_2C : string; + attribute INIT_2D : string; + attribute INIT_2E : string; + attribute INIT_2F : string; + attribute INIT_30 : string; + attribute INIT_31 : string; + attribute INIT_32 : string; + attribute INIT_33 : string; + attribute INIT_34 : string; + attribute INIT_35 : string; + attribute INIT_36 : string; + attribute INIT_37 : string; + attribute INIT_38 : string; + attribute INIT_39 : string; + attribute INIT_3A : string; + attribute INIT_3B : string; + attribute INIT_3C : string; + attribute INIT_3D : string; + attribute INIT_3E : string; + attribute INIT_3F : string; + + component RAMB16_S4 + --pragma translate_off + generic ( + INIT_00 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_01 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_02 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_03 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_04 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_05 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_06 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_07 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_08 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_09 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_10 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_11 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_12 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_13 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_14 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_15 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_16 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_17 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_18 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_19 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_20 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_21 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_22 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_23 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_24 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_25 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_26 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_27 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_28 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_29 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_30 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_31 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_32 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_33 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_34 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_35 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_36 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_37 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_38 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_39 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000" + ); + --pragma translate_on + port ( + DO : out std_logic_vector (3 downto 0); + ADDR : in std_logic_vector (11 downto 0); + CLK : in std_logic; + DI : in std_logic_vector (3 downto 0); + EN : in std_logic; + SSR : in std_logic; + WE : in std_logic + ); + end component; + + signal rom_addr : std_logic_vector(11 downto 0); + +begin + + p_addr : process(ADDR) + begin + rom_addr <= (others => '0'); + rom_addr(11 downto 0) <= ADDR; + end process; + + rom0 : if true generate + attribute INIT_00 of inst : label is "3F004E0B3C98F87F9028D0E000B0FE01FFFFFFFFFFFF752875289110010FF759"; + attribute INIT_01 of inst : label is "AD2AD980D0AD78FEBF4138EE9707B287EE21FFFFFEFF60FDF803E243F503116D"; + attribute INIT_02 of inst : label is "1311081A0E00132126543987402111009EE11508BFB1E3127D5ED1EA20010DB0"; + attribute INIT_03 of inst : label is "E4FF26D16F08980EB816402E88EFBBF2AD281E219EF1BD098B6E61001F28080E"; + attribute INIT_04 of inst : label is "B1BEE26FEEAB6E41E82E009EFFF0904326DE025E16D260DF8E029F816D38EF0B"; + attribute INIT_05 of inst : label is "2C71E8F6EB9E40BEFFF8F16F14F12F1B1815129B6E41EF1518BFE0A26DA815D0"; + attribute INIT_06 of inst : label is "811EA1005EFBF52AD206BA8BBBF8FB5E3989F87E38AEEEF1EA12AD580E126DE1"; + attribute INIT_07 of inst : label is "F0606B06F6787E32F0616287EE2157E381B3FDED1943FD33333989637370EE9C"; + attribute INIT_08 of inst : label is "EE41F32F94582E987E3418CEEE4127DE8100C8081F97B7F02EEE112A33EE0A12"; + attribute INIT_09 of inst : label is "F81E016E51181AE50DC000F81F8E48BE6388981C50D08F0081F8E587E387A01B"; + attribute INIT_0A of inst : label is "0A7FC6256FA0914F2419B892F21DF16FB6F08E284E7B60FB6FCE150E6FDEC0D9"; + attribute INIT_0B of inst : label is "6833D50F6EBC83FDEE309E9DD03FD6F3EAFF061B8FD7E9A8FDEE0AEF1D32DB00"; + attribute INIT_0C of inst : label is "00CF6BFF3128DFFC225DFF61FFFF777770269B17B03FD5B569B07DB1790610EE"; + attribute INIT_0D of inst : label is "FC23812F09104D09D0BD09D07D09E0AD5B000D87E7002F2B004F4B57990FF613"; + attribute INIT_0E of inst : label is "2A7F4AF224E285E482EF424E285EF3AFC242C7F2D1D43DF12701FA2F01F32381"; + attribute INIT_0F of inst : label is "1A06A5D514F0E4ED56D41144F66B12F586D7ED2F6EDDD56D4ED16A556BDA06FF"; + attribute INIT_10 of inst : label is "4F81F2F4EFC1065140DF3251F53E001FD467D0E068567D0E980F111D52D999F6"; + attribute INIT_11 of inst : label is "E8E6BD6BDF3236CF3A69D04A343B4394374354B168485F243FFD2F69D43D20D1"; + attribute INIT_12 of inst : label is "6D0ED90D018BF9031E539E330ED9D068B028F363ED6BDF3A98F69D6D3FB564B3"; + attribute INIT_13 of inst : label is "D56D37D17DC069D16D8869D1E869D386BD1ED6ED0E507800D11078F7F3066BD2"; + attribute INIT_14 of inst : label is "5557115E7017C191AF41106B0BF54035FD57DF6A47DF5A4F0E4114ED56D54D4E"; + attribute INIT_15 of inst : label is "810ED4019D001D4ED56D183333378D1113D881171F4F4110E154D4ED56D543A5"; + attribute INIT_16 of inst : label is "594F152D7999F61950688E6BD6BD9D4EE6BD5F414866BD9053D783B3501DD011"; + attribute INIT_17 of inst : label is "D96F2D1D364F3CE86D7ED9B1B409ED8F302FC27DFCA942855F216079E1F152D7"; + attribute INIT_18 of inst : label is "066BD3E883ECEE8CE281ED27D2ED300F6BD94F0E411154D54ED56D7ED3ED8E6B"; + attribute INIT_19 of inst : label is "7FFDF6FFF872787E749111D566BF1D56EBF559F5268EF21682E7F4A6837D1ED3"; + attribute INIT_1A of inst : label is "5912B740568B6FD0FF8658E976BD8EF697206BD8E7D070E4747F86BD816D8870"; + attribute INIT_1B of inst : label is "8F4658BEBA8FB48F4638BEBA87B28746108EAA8FB08746F80EAA87B5ED46D555"; + attribute INIT_1C of inst : label is "0FB7D10FB71107B7919111AB061F62BF52A407E9081C07EB10BF81155382B716"; + attribute INIT_1D of inst : label is "00004101010501500440819875A07EC1DC715D6FC1DC7D82D881C87941ED9751"; + attribute INIT_1E of inst : label is "5DF0EEF55DF0FFF88887823A22A0FCCF33F0A884004451045540154010473737"; + attribute INIT_1F of inst : label is "F9BFF2C3FFC2B2C7F887FCA2D1D01F3983FFFFF0000000055DF044855DF088E5"; + attribute INIT_20 of inst : label is "6FA5D5FC22E280E7FCAD02DA9187E9021987E87A877EDFDFBF8CDF98F9FAF1CD"; + attribute INIT_21 of inst : label is "D31633393D3333163511B9DF199B2FED06B09F608156BAFB9F180E60BD281990"; + attribute INIT_22 of inst : label is "068F11D58F8F81D933D42D85D94DEF0010010EDF81D48F11D989F71F23F06193"; + attribute INIT_23 of inst : label is "E016D9EFDB1016D226DE08E6ED9176D016D8E7BD0F80E061ED9F7DCE20EEFFFF"; + attribute INIT_24 of inst : label is "F6FD8F1DDFC860BDA88EE060BD0EC00E98090630E06F71B0BF5B6DCE07F0AD08"; + attribute INIT_25 of inst : label is "F4F3F21CE2F0EF21D9070E5EEB4F706203E86BED816D026D616DF2FD4F8DDFA8"; + attribute INIT_26 of inst : label is "93CE5D51384E98D8F021E8383E98D305E82E398D304E81E1938E5E419FE21EA1"; + attribute INIT_27 of inst : label is "87F82B006F6B0FF61F442EDF937B6BA33063337A3337A9112F8E7A55385E98D1"; + attribute INIT_28 of inst : label is "1C5BC5F64B287F24B2872D0D00FF2B0C818BF1800BDB0CFAF0F32FF0F23D3986"; + attribute INIT_29 of inst : label is "AD0D006DF81DD0DF51006DF11DF72F42FE98DD910EF5A98DDE18EF1AF02F2DAB"; + attribute INIT_2A of inst : label is "1D0E2082E401F81D021E48AC3F938EB8D0DAB6D866D086D3C6D006DFF1DD87F0"; + attribute INIT_2B of inst : label is "F88BC1B37281DB37BB203D7B10503F82B0F2D1D341FD34E7DDEC09D3C6D176D0"; + attribute INIT_2C of inst : label is "81D89CB89B888F8FBF8AAC32B8F0F8DFEA9D118ED5546021F81D2B452430F208"; + attribute INIT_2D of inst : label is "DE68F4518061BDFF2FD5DD7DF21F38ED34E5D9882222207118A67F48D38578F5"; + attribute INIT_2E of inst : label is "8F819B981DD0DF51D3DE2DEFFC18F64188FC1EFB63E9FED06D7100E1BDEFCC2E"; + attribute INIT_2F of inst : label is "E1BD61BD06C3FEDDEDE6D1861BDF81D46FF2FDAD360613DAD46011F915D55557"; + attribute INIT_30 of inst : label is "D36E28D7DF21109D02161BDE1BDE1BD88706BE9001F7DD3DE2D8F0ED6EDB6DB8"; + attribute INIT_31 of inst : label is "DBD5DC8AD7DF5126A09DE1BD48E7BDEFC8E1BD021DB146F81DBF3AE200E2EBED"; + attribute INIT_32 of inst : label is "61BDE1BD88EFD318861BDE1BDB26D6061BD27D7096D86D46D3ED50E1BDD3261B"; + attribute INIT_33 of inst : label is "111D20DBC525D0DF5100E1BD07DE1BD780EDFED17DE1BDA327DAE62EDC6211ED"; + attribute INIT_34 of inst : label is "1C6D176D016D236D9B73077FED39609418063EE8D0DF21E1BDD5DF51EFD81911"; + attribute INIT_35 of inst : label is "5204574AB9B191D57BBB633E393B92BBEF6873E30F6D315DB26D6F6D8B6D466D"; + attribute INIT_36 of inst : label is "42E3C683D0F304E0F406F0F40800F40B10F40C20F40F30F30B9F071248AF0941"; + attribute INIT_37 of inst : label is "010052AAEC89BEC89EC88BEC811E2E2E4E8E0E6D8FF00000000667CD27BD2FD8"; + attribute INIT_38 of inst : label is "0404050100625A0000000500526A00040500427A050422AA01040032AA000104"; + attribute INIT_39 of inst : label is "050405050552F34B550000040552F24040501001505505153F04000041515A00"; + attribute INIT_3A of inst : label is "00051005100450005400550455058000A240AA102A008A005500450001341042"; + attribute INIT_3B of inst : label is "0CC6220800C155551556158A008A00550045000174D0C2400001000000010005"; + attribute INIT_3C of inst : label is "6400510550510510510550550800A00A20220A2055051040F30011005D04F700"; + attribute INIT_3D of inst : label is "4AA20AA00AA20450055005510545450541054105450545450555055105500050"; + attribute INIT_3E of inst : label is "F9D004D6D2D4D6D2F9D0648662DCE4F9D90901004000400048005AA248004A80"; + attribute INIT_3F of inst : label is "FFFFFFFFFFFFFFFFFFFFF0C5F551FF0005DF0FFF8012E612168286D218161218"; + begin + inst : RAMB16_S4 + --pragma translate_off + generic map ( + INIT_00 => romgen_str2bv(inst'INIT_00), + INIT_01 => romgen_str2bv(inst'INIT_01), + INIT_02 => romgen_str2bv(inst'INIT_02), + INIT_03 => romgen_str2bv(inst'INIT_03), + INIT_04 => romgen_str2bv(inst'INIT_04), + INIT_05 => romgen_str2bv(inst'INIT_05), + INIT_06 => romgen_str2bv(inst'INIT_06), + INIT_07 => romgen_str2bv(inst'INIT_07), + INIT_08 => romgen_str2bv(inst'INIT_08), + INIT_09 => romgen_str2bv(inst'INIT_09), + INIT_0A => romgen_str2bv(inst'INIT_0A), + INIT_0B => romgen_str2bv(inst'INIT_0B), + INIT_0C => romgen_str2bv(inst'INIT_0C), + INIT_0D => romgen_str2bv(inst'INIT_0D), + INIT_0E => romgen_str2bv(inst'INIT_0E), + INIT_0F => romgen_str2bv(inst'INIT_0F), + INIT_10 => romgen_str2bv(inst'INIT_10), + INIT_11 => romgen_str2bv(inst'INIT_11), + INIT_12 => romgen_str2bv(inst'INIT_12), + INIT_13 => romgen_str2bv(inst'INIT_13), + INIT_14 => romgen_str2bv(inst'INIT_14), + INIT_15 => romgen_str2bv(inst'INIT_15), + INIT_16 => romgen_str2bv(inst'INIT_16), + INIT_17 => romgen_str2bv(inst'INIT_17), + INIT_18 => romgen_str2bv(inst'INIT_18), + INIT_19 => romgen_str2bv(inst'INIT_19), + INIT_1A => romgen_str2bv(inst'INIT_1A), + INIT_1B => romgen_str2bv(inst'INIT_1B), + INIT_1C => romgen_str2bv(inst'INIT_1C), + INIT_1D => romgen_str2bv(inst'INIT_1D), + INIT_1E => romgen_str2bv(inst'INIT_1E), + INIT_1F => romgen_str2bv(inst'INIT_1F), + INIT_20 => romgen_str2bv(inst'INIT_20), + INIT_21 => romgen_str2bv(inst'INIT_21), + INIT_22 => romgen_str2bv(inst'INIT_22), + INIT_23 => romgen_str2bv(inst'INIT_23), + INIT_24 => romgen_str2bv(inst'INIT_24), + INIT_25 => romgen_str2bv(inst'INIT_25), + INIT_26 => romgen_str2bv(inst'INIT_26), + INIT_27 => romgen_str2bv(inst'INIT_27), + INIT_28 => romgen_str2bv(inst'INIT_28), + INIT_29 => romgen_str2bv(inst'INIT_29), + INIT_2A => romgen_str2bv(inst'INIT_2A), + INIT_2B => romgen_str2bv(inst'INIT_2B), + INIT_2C => romgen_str2bv(inst'INIT_2C), + INIT_2D => romgen_str2bv(inst'INIT_2D), + INIT_2E => romgen_str2bv(inst'INIT_2E), + INIT_2F => romgen_str2bv(inst'INIT_2F), + INIT_30 => romgen_str2bv(inst'INIT_30), + INIT_31 => romgen_str2bv(inst'INIT_31), + INIT_32 => romgen_str2bv(inst'INIT_32), + INIT_33 => romgen_str2bv(inst'INIT_33), + INIT_34 => romgen_str2bv(inst'INIT_34), + INIT_35 => romgen_str2bv(inst'INIT_35), + INIT_36 => romgen_str2bv(inst'INIT_36), + INIT_37 => romgen_str2bv(inst'INIT_37), + INIT_38 => romgen_str2bv(inst'INIT_38), + INIT_39 => romgen_str2bv(inst'INIT_39), + INIT_3A => romgen_str2bv(inst'INIT_3A), + INIT_3B => romgen_str2bv(inst'INIT_3B), + INIT_3C => romgen_str2bv(inst'INIT_3C), + INIT_3D => romgen_str2bv(inst'INIT_3D), + INIT_3E => romgen_str2bv(inst'INIT_3E), + INIT_3F => romgen_str2bv(inst'INIT_3F) + ) + --pragma translate_on + port map ( + DO => DATA(3 downto 0), + ADDR => rom_addr, + CLK => CLK, + DI => "0000", + EN => ENA, + SSR => '0', + WE => '0' + ); + end generate; + rom1 : if true generate + attribute INIT_00 of inst : label is "000094C111101B1F075010064010F4C3FFFFFFFFFFFF0A600A60CC000007F4CC"; + attribute INIT_01 of inst : label is "CC10C01BE1CC030725372C0F75CA732A74C250000A40E195F7C1F014FE14218C"; + attribute INIT_02 of inst : label is "12111E18200710001000100014553668C74C2D1B5F71DCE1CCE4D24D2002BEE1"; + attribute INIT_03 of inst : label is "4C5F11C03020700F1103020F314C06F10C4174C2C4C2EF114004E2121A131D1D"; + attribute INIT_04 of inst : label is "00E4C36F4C3004C24D34D004C5FCA18C11C4C30314C03C3014C374014C014C00"; + attribute INIT_05 of inst : label is "33703C0E7204C004C5F6F06F06F06F16161616C004C14C2D155F4C311CD117C0"; + attribute INIT_06 of inst : label is "2BC4D20014C1FC10C12B22122E45FE3427CB02A72C0F74C14D210C2100E11C4C"; + attribute INIT_07 of inst : label is "F2C032030C02A723F2C3C02A74C2E00501E10C4D17310C111110103272020F71"; + attribute INIT_08 of inst : label is "74E24E3AC3125F12A723025F74E21CC4524250023FC727AC0F74C218C004C3E3"; + attribute INIT_09 of inst : label is "FD048284E201103F234852FD3F033D0F92114113F234242023F033CA72CA124C"; + attribute INIT_0A of inst : label is "225444545422CF3F1B2DC4C3F1C5FF3F804B0302034C124C5F004F005F00F230"; + attribute INIT_0B of inst : label is "F110C020E7EE210C03F20F700210C5F101FA000E5F004D35F004C34C13662220"; + attribute INIT_0C of inst : label is "000491F4F0024F4D8034F493FFFF00000067CEE7F126EEE00CF16E24A0000C0F"; + attribute INIT_0D of inst : label is "4A23220000200100102100105100107150A00106B10024A10004E111A10F493F"; + attribute INIT_0E of inst : label is "A344A34A303030F030F4A303030F4F34D42043F002D1BC4C24524B21524B2372"; + attribute INIT_0F of inst : label is "24007EDDD2F1306F06F0001150C7D3FD05F05F3F04F1105D05D3C7DC15C70144"; + attribute INIT_10 of inst : label is "1F25F3F402413CFF19C4A305FF03A2BA0107D83001007DC302BACDED1EC00049"; + attribute INIT_11 of inst : label is "E270CD15C4A30E34A314CC185185185185185164F1154F014F4D3A14C1BCE23F"; + attribute INIT_12 of inst : label is "4D04DC0024B1FC1D131D031D07F0F004F10300007D15C4A3C4F14C11C3C1D1BC"; + attribute INIT_13 of inst : label is "D05D07D07D321AC04D021AC4021AC121AC07D17C0002B707D402B744A0270CD0"; + attribute INIT_14 of inst : label is "DCF1B203181160CD2F00100E03FD19C1FC07D4A307D4A32F1300006F06F12C05"; + attribute INIT_15 of inst : label is "B207F0011F002F05F05FD100001023FCDBE010E05F2F00013E12C05D05DC0D1E"; + attribute INIT_16 of inst : label is "C75FC1EC30004927C001270CD15C7000B0CD34A20270CDE212FF172002BE0204"; + attribute INIT_17 of inst : label is "DC3F002D401580305F05FECAC0304F7F14C4D3234D3C302334A2D2B715FC1ECB"; + attribute INIT_18 of inst : label is "270CD0E020E0E020E120AD07D07D02BA15CC2F13000E12CE05D05D12C07DC70C"; + attribute INIT_19 of inst : label is "7F4B4B4A4A16151414CDEEDD175FEFD165FEDC4D39034A20203B4A3B107D07D0"; + attribute INIT_1A of inst : label is "CCD1C3F210271BCA5001D03C41AC0300C4021AC034F10830407FC1AC704D02B2"; + attribute INIT_1B of inst : label is "150C025F7024C1150D120F7024C2150C239F7025C3150D220F7025C05D05DFED"; + attribute INIT_1C of inst : label is "C5C182C4C192C4C182CCDE3C01F4A374A37E2B70020E2B7EE03F55CDD211C3F0"; + attribute INIT_1D of inst : label is "0000404150400540011010511A677710211A8899107119ABBC100119DEEFC192"; + attribute INIT_1E of inst : label is "FFF03E8FFFF03FEFFFF8F6BA88A33F0FCCF22A01551154010010451800080000"; + attribute INIT_1F of inst : label is "FCF0F30DA4D40043F02B4D3002D81FF1ECFFFFF00000000FFFF0344FFFF0384F"; + attribute INIT_20 of inst : label is "260EDE4D3030213B4D302030C02B7101102B7CB0CB07F434D47D0F01414D46D0"; + attribute INIT_21 of inst : label is "C2032001DC0002032EECE1181126605D01F11F302100E3FE1A024370CD061220"; + attribute INIT_22 of inst : label is "EE7462D0127472DC07D07D07D07D7F08208104D472D01462D04C1D0411F83E1D"; + attribute INIT_23 of inst : label is "F003DC3F182803D003D034F07DC003D003DC50CDD022F6E07DC07D03020F0000"; + attribute INIT_24 of inst : label is "4A1A046D0F0270CDD151D270CD41036FCF217B27700FD1E03F105D41CB493135"; + attribute INIT_25 of inst : label is "F3FF102001FC3412D6670C0F725F52C031F0D07D603D813D013D4A1B647D0F01"; + attribute INIT_26 of inst : label is "1D03F1E20D0F1CC04938300D0F1CC030FD0F01CC030FD0FF1D03F1F2C4D303F5"; + attribute INIT_27 of inst : label is "B14F0700D4010F4034F8014FC17E8E020030127120171CFD2F0350DF0D0F1CCF"; + attribute INIT_28 of inst : label is "0231204AC00834AC0003001000841100F461F064011C004D50FF019C4111C10D"; + attribute INIT_29 of inst : label is "313C503D472D13C412103D462D4134134318C1B0414A318C1B0514A3493A0170"; + attribute INIT_2A of inst : label is "7D6002B03020412D0111F0242F1D030115C003D403D403D003D103D482D12B49"; + attribute INIT_2B of inst : label is "F002351503600150B002318004343F0120F002DF65F0D734E13E11D003D003D0"; + attribute INIT_2C of inst : label is "1B51B51201207FC7C4F310C0D1E1D234D31DCD1CCDC00011412D01340140F043"; + attribute INIT_2D of inst : label is "D122F1012240CD0F3A12C16C4120DC30D73EDD0033333C1E51051F5189195185"; + attribute INIT_2E of inst : label is "1102CFD0ED15C41207D07D1F1322F101011021FE525105D011D23260CD1F2216"; + attribute INIT_2F of inst : label is "70CDB0CDC30D07D06D06D1270CD412D000F3A11C00011211C00011412EDEDCFE"; + attribute INIT_30 of inst : label is "0D731216C412B11D011F0CDE0CDB0CD02BC3E7140207D07D07D3F07D05D05D22"; + attribute INIT_31 of inst : label is "DF12C1FC16C41200E11DB0CD0250CD3F0270CD01118200412DF0D6303033F07D"; + attribute INIT_32 of inst : label is "A0CDD0CD023F18221E0CDD0CD413D3260CD07D120BD0BD0BD07D2260CD10C40C"; + attribute INIT_33 of inst : label is "DEED00CF17C015C4122250CD17DD0CD021BD07D17DD0CD1117D11115D1DF917D"; + attribute INIT_34 of inst : label is "003D003D803D303DC272CA7F7DFCF11302AE27D115C41290CD12C4123F172CFC"; + attribute INIT_35 of inst : label is "45254440151CCEDDA7225225FC72C1127502A7720F3DFDED413D003D203D003D"; + attribute INIT_36 of inst : label is "41042140F00000F00000F0000000000000000000000000000509054544020544"; + attribute INIT_37 of inst : label is "05040000A108E730A73006310101413121111101F008003300000867A807A302"; + attribute INIT_38 of inst : label is "0501000040000004050104400000050540010000450500004001050000400000"; + attribute INIT_39 of inst : label is "4001010105000004155555555100000750140540144005000000644140000005"; + attribute INIT_3A of inst : label is "0145010505050505550551055040A050A018A000A000A004550454001010001D"; + attribute INIT_3B of inst : label is "333FFB333200555145A1018000A004550454001000003D500040004000500050"; + attribute INIT_3C of inst : label is "1000500540540545555550510A00A08A00A00A05511510400000000044254433"; + attribute INIT_3D of inst : label is "8AA10AA08AA00510055045505150505150415041505151515550455005500500"; + attribute INIT_3E of inst : label is "19CF7280B182B0B119CF92A091807219CC00B1800001000100218AA5002102A1"; + attribute INIT_3F of inst : label is "FFFFFFFFFFFFFFFFFFFFFF40800E3FBEFFFF03FE8FE1E0E1E0C1C0B1E1E0E1E1"; + begin + inst : RAMB16_S4 + --pragma translate_off + generic map ( + INIT_00 => romgen_str2bv(inst'INIT_00), + INIT_01 => romgen_str2bv(inst'INIT_01), + INIT_02 => romgen_str2bv(inst'INIT_02), + INIT_03 => romgen_str2bv(inst'INIT_03), + INIT_04 => romgen_str2bv(inst'INIT_04), + INIT_05 => romgen_str2bv(inst'INIT_05), + INIT_06 => romgen_str2bv(inst'INIT_06), + INIT_07 => romgen_str2bv(inst'INIT_07), + INIT_08 => romgen_str2bv(inst'INIT_08), + INIT_09 => romgen_str2bv(inst'INIT_09), + INIT_0A => romgen_str2bv(inst'INIT_0A), + INIT_0B => romgen_str2bv(inst'INIT_0B), + INIT_0C => romgen_str2bv(inst'INIT_0C), + INIT_0D => romgen_str2bv(inst'INIT_0D), + INIT_0E => romgen_str2bv(inst'INIT_0E), + INIT_0F => romgen_str2bv(inst'INIT_0F), + INIT_10 => romgen_str2bv(inst'INIT_10), + INIT_11 => romgen_str2bv(inst'INIT_11), + INIT_12 => romgen_str2bv(inst'INIT_12), + INIT_13 => romgen_str2bv(inst'INIT_13), + INIT_14 => romgen_str2bv(inst'INIT_14), + INIT_15 => romgen_str2bv(inst'INIT_15), + INIT_16 => romgen_str2bv(inst'INIT_16), + INIT_17 => romgen_str2bv(inst'INIT_17), + INIT_18 => romgen_str2bv(inst'INIT_18), + INIT_19 => romgen_str2bv(inst'INIT_19), + INIT_1A => romgen_str2bv(inst'INIT_1A), + INIT_1B => romgen_str2bv(inst'INIT_1B), + INIT_1C => romgen_str2bv(inst'INIT_1C), + INIT_1D => romgen_str2bv(inst'INIT_1D), + INIT_1E => romgen_str2bv(inst'INIT_1E), + INIT_1F => romgen_str2bv(inst'INIT_1F), + INIT_20 => romgen_str2bv(inst'INIT_20), + INIT_21 => romgen_str2bv(inst'INIT_21), + INIT_22 => romgen_str2bv(inst'INIT_22), + INIT_23 => romgen_str2bv(inst'INIT_23), + INIT_24 => romgen_str2bv(inst'INIT_24), + INIT_25 => romgen_str2bv(inst'INIT_25), + INIT_26 => romgen_str2bv(inst'INIT_26), + INIT_27 => romgen_str2bv(inst'INIT_27), + INIT_28 => romgen_str2bv(inst'INIT_28), + INIT_29 => romgen_str2bv(inst'INIT_29), + INIT_2A => romgen_str2bv(inst'INIT_2A), + INIT_2B => romgen_str2bv(inst'INIT_2B), + INIT_2C => romgen_str2bv(inst'INIT_2C), + INIT_2D => romgen_str2bv(inst'INIT_2D), + INIT_2E => romgen_str2bv(inst'INIT_2E), + INIT_2F => romgen_str2bv(inst'INIT_2F), + INIT_30 => romgen_str2bv(inst'INIT_30), + INIT_31 => romgen_str2bv(inst'INIT_31), + INIT_32 => romgen_str2bv(inst'INIT_32), + INIT_33 => romgen_str2bv(inst'INIT_33), + INIT_34 => romgen_str2bv(inst'INIT_34), + INIT_35 => romgen_str2bv(inst'INIT_35), + INIT_36 => romgen_str2bv(inst'INIT_36), + INIT_37 => romgen_str2bv(inst'INIT_37), + INIT_38 => romgen_str2bv(inst'INIT_38), + INIT_39 => romgen_str2bv(inst'INIT_39), + INIT_3A => romgen_str2bv(inst'INIT_3A), + INIT_3B => romgen_str2bv(inst'INIT_3B), + INIT_3C => romgen_str2bv(inst'INIT_3C), + INIT_3D => romgen_str2bv(inst'INIT_3D), + INIT_3E => romgen_str2bv(inst'INIT_3E), + INIT_3F => romgen_str2bv(inst'INIT_3F) + ) + --pragma translate_on + port map ( + DO => DATA(7 downto 4), + ADDR => rom_addr, + CLK => CLK, + DI => "0000", + EN => ENA, + SSR => '0', + WE => '0' + ); + end generate; +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/roms/bally_check.vhd b/Bally - Astrocade_MiST/rtl/roms/bally_check.vhd new file mode 100644 index 00000000..c7462864 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/bally_check.vhd @@ -0,0 +1,379 @@ +-- generated with romgen v3.0 by MikeJ +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + use ieee.numeric_std.all; + +library UNISIM; + use UNISIM.Vcomponents.all; + +entity BALLY_CHECK is + port ( + CLK : in std_logic; + ENA : in std_logic; + ADDR : in std_logic_vector(10 downto 0); + DATA : out std_logic_vector(7 downto 0) + ); +end; + +architecture RTL of BALLY_CHECK is + + function romgen_str2bv (str : string) return bit_vector is + variable result : bit_vector (str'length*4-1 downto 0); + begin + for i in 0 to str'length-1 loop + case str(str'high-i) is + when '0' => result(i*4+3 downto i*4) := x"0"; + when '1' => result(i*4+3 downto i*4) := x"1"; + when '2' => result(i*4+3 downto i*4) := x"2"; + when '3' => result(i*4+3 downto i*4) := x"3"; + when '4' => result(i*4+3 downto i*4) := x"4"; + when '5' => result(i*4+3 downto i*4) := x"5"; + when '6' => result(i*4+3 downto i*4) := x"6"; + when '7' => result(i*4+3 downto i*4) := x"7"; + when '8' => result(i*4+3 downto i*4) := x"8"; + when '9' => result(i*4+3 downto i*4) := x"9"; + when 'A' => result(i*4+3 downto i*4) := x"A"; + when 'B' => result(i*4+3 downto i*4) := x"B"; + when 'C' => result(i*4+3 downto i*4) := x"C"; + when 'D' => result(i*4+3 downto i*4) := x"D"; + when 'E' => result(i*4+3 downto i*4) := x"E"; + when 'F' => result(i*4+3 downto i*4) := x"F"; + when others => null; + end case; + end loop; + return result; + end romgen_str2bv; + + attribute INITP_00 : string; + attribute INITP_01 : string; + attribute INITP_02 : string; + attribute INITP_03 : string; + attribute INITP_04 : string; + attribute INITP_05 : string; + attribute INITP_06 : string; + attribute INITP_07 : string; + + attribute INIT_00 : string; + attribute INIT_01 : string; + attribute INIT_02 : string; + attribute INIT_03 : string; + attribute INIT_04 : string; + attribute INIT_05 : string; + attribute INIT_06 : string; + attribute INIT_07 : string; + attribute INIT_08 : string; + attribute INIT_09 : string; + attribute INIT_0A : string; + attribute INIT_0B : string; + attribute INIT_0C : string; + attribute INIT_0D : string; + attribute INIT_0E : string; + attribute INIT_0F : string; + attribute INIT_10 : string; + attribute INIT_11 : string; + attribute INIT_12 : string; + attribute INIT_13 : string; + attribute INIT_14 : string; + attribute INIT_15 : string; + attribute INIT_16 : string; + attribute INIT_17 : string; + attribute INIT_18 : string; + attribute INIT_19 : string; + attribute INIT_1A : string; + attribute INIT_1B : string; + attribute INIT_1C : string; + attribute INIT_1D : string; + attribute INIT_1E : string; + attribute INIT_1F : string; + attribute INIT_20 : string; + attribute INIT_21 : string; + attribute INIT_22 : string; + attribute INIT_23 : string; + attribute INIT_24 : string; + attribute INIT_25 : string; + attribute INIT_26 : string; + attribute INIT_27 : string; + attribute INIT_28 : string; + attribute INIT_29 : string; + attribute INIT_2A : string; + attribute INIT_2B : string; + attribute INIT_2C : string; + attribute INIT_2D : string; + attribute INIT_2E : string; + attribute INIT_2F : string; + attribute INIT_30 : string; + attribute INIT_31 : string; + attribute INIT_32 : string; + attribute INIT_33 : string; + attribute INIT_34 : string; + attribute INIT_35 : string; + attribute INIT_36 : string; + attribute INIT_37 : string; + attribute INIT_38 : string; + attribute INIT_39 : string; + attribute INIT_3A : string; + attribute INIT_3B : string; + attribute INIT_3C : string; + attribute INIT_3D : string; + attribute INIT_3E : string; + attribute INIT_3F : string; + + component RAMB16_S9 + --pragma translate_off + generic ( + INITP_00 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_01 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_02 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_03 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_04 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_05 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_06 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INITP_07 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + + INIT_00 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_01 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_02 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_03 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_04 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_05 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_06 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_07 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_08 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_09 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_0F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_10 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_11 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_12 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_13 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_14 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_15 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_16 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_17 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_18 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_19 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_1F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_20 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_21 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_22 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_23 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_24 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_25 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_26 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_27 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_28 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_29 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_2F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_30 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_31 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_32 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_33 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_34 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_35 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_36 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_37 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_38 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_39 : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3A : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3B : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3C : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3D : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3E : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000"; + INIT_3F : bit_vector (255 downto 0) := x"0000000000000000000000000000000000000000000000000000000000000000" + ); + --pragma translate_on + port ( + DO : out std_logic_vector (7 downto 0); + DOP : out std_logic_vector (0 downto 0); + ADDR : in std_logic_vector (10 downto 0); + CLK : in std_logic; + DI : in std_logic_vector (7 downto 0); + DIP : in std_logic_vector (0 downto 0); + EN : in std_logic; + SSR : in std_logic; + WE : in std_logic + ); + end component; + + signal rom_addr : std_logic_vector(10 downto 0); + +begin + + p_addr : process(ADDR) + begin + rom_addr <= (others => '0'); + rom_addr(10 downto 0) <= ADDR; + end process; + + rom0 : if true generate + attribute INIT_00 of inst : label is "A716DB2920A715DB08F3201627772728FFAA55002F0F0F2FC98787878720ADC3"; + attribute INIT_01 of inst : label is "264FCA02FE25D9CA01FE27BACA02FE2627CA01FE3628A714DB0F20A717DB3020"; + attribute INIT_02 of inst : label is "0FE679D92673CA02FE25EACA01FE10182748CA02FE2611CA01FE1C18182810FE"; + attribute INIT_03 of inst : label is "0118A03E0520A7780918B13E042084FE79112043CB001640203CFE7A14D9D94F"; + attribute INIT_04 of inst : label is "4706C6780420A0FE2003CD7D2C002618203CFE7C24001E20203CFE7B1CFFD3AF"; + attribute INIT_05 of inst : label is "08D3003EFFD3AA3ED96F675F57810E47AFD9F3C9FB08D96F47AF032099FE7804"; + attribute INIT_06 of inst : label is "C320E221FD6C1823EF21011EF318092818FE790C0820A778ED140EAF0AD3C83E"; + attribute INIT_07 of inst : label is "0116FB5EED0FD3AF0DD37D47ED7C2014210ED3083E4FC8314F00504E04182164"; + attribute INIT_08 of inst : label is "0021200001FBD9800E301823EF21FF0E021ED90A20A77B0E20A77AD9F325CFCD"; + attribute INIT_09 of inst : label is "4F08D67C031EE718122828FE7C214AC30A20A4FE7AF72005FA200D235786AF00"; + attribute INIT_0A of inst : label is "68180618215E21FDFB4F00504E04181318215121FDF323E6C3214A21A00E0220"; + attribute INIT_0B of inst : label is "EE2003BEFD7C234B18217921DD0628A87E70046EFD0566FD0106000E40004F3F"; + attribute INIT_0C of inst : label is "FD7C232718218021DDE928AE772F783318219121DD0628A87E162802BEFD7C2B"; + attribute INIT_0D of inst : label is "21041EE9FD0220A779B13020CBEA1877AF151821AF21DD0628AE2F780F2803BE"; + attribute INIT_0E of inst : label is "FD68780077FD6F67AF0CD37901064FAF481021DD081021FDE9DD4FB14F1821C8"; + attribute INIT_0F of inst : label is "20BC017EDD1320BD007EDDF5203D1CCB1DCB1CCB1DCB0B28A7790177FDAF0077"; + attribute INIT_10 of inst : label is "0E224A214810110CD3403E3318221521051E0718C62004FE4F3C79CF3010CB0D"; + attribute INIT_11 of inst : label is "1A18F23039CB230720BE1A0077FD2F7919CBF33021CB231A20BE1A0077FD7901"; + attribute INIT_12 of inst : label is "4FAF0CD3083EBF7FEFDFFBF7FEFD02010804201080404718225A21071E4F2F79"; + attribute INIT_13 of inst : label is "C67AEA10231120BA017EDD1720BA007EDD0177FD0077FD7E040619D3200C2157"; + attribute INIT_14 of inst : label is "FE1C2801FE22E3CD22CECD103E3818229321121E0718DA2014FE4F05C6795755"; + attribute INIT_15 of inst : label is "22A321081E0218101E233AC3122802FE122801FE22E3CD2C22CECD203E142802"; + attribute INIT_16 of inst : label is "C9013EC904066F4F5F57AF01042108DB0CD323E6C3233A21111E0218091E0918"; + attribute INIT_17 of inst : label is "DB0728A779E22000BEDDA97A0218B17A0420BDAF2333CD2333CD2333CDC9023E"; + attribute INIT_18 of inst : label is "20A77B14CBC83024CB24CB3BCB040001D3104F8479D520B908DB0518DC20BB08"; + attribute INIT_19 of inst : label is "0FDB0EDBFF06C90071FD0072DDC9B130881E0400015755C67A3BCB0218881E04"; + attribute INIT_1A of inst : label is "790C7120FFFE78ED1C0E17DB16DB15DB14DBF42014FE790C23C8C2A778ED100E"; + attribute INIT_1B of inst : label is "D3143E07D303D306D302D305D301D304D300D37808D3003EFF06D610F42020FE"; + attribute INIT_1C of inst : label is "14D316D317D3FF3EB3ED180E080623D621B3ED0B0E080623DE21500AD3C83E09"; + attribute INIT_1D of inst : label is "A7FE18FBD9082084FE790C0A287FCB79D9F3BA104215D313D312D311D310D37A"; + attribute INIT_1E of inst : label is "92DBF5F5FDFF003444481018236821141E1718234E21131E211BC3FBD90C0120"; + attribute INIT_1F of inst : label is "3E311823FF21FFD379391823F721FFD37B5028A70FE6D979D9F3004992DB0049"; + attribute INIT_20 of inst : label is "1018FFD3A03E0220A7242021D978D91F18241121FFD3DE3E2818240821FFD3CB"; + attribute INIT_21 of inst : label is "FBE9F42015F9203DFE10FF06FF3E021623EF21FFD3AA3E0718242921FFD3AA3E"; + attribute INIT_22 of inst : label is "4554495257005244444120444145520058454820544749442D342052544E45E9"; + attribute INIT_23 of inst : label is "0054524F5020444145520058454820544749442D322052544E45005244444120"; + attribute INIT_24 of inst : label is "544749442D322052544E45005244444120545254530054524F50204554495257"; + attribute INIT_25 of inst : label is "002A2A2A2A002A2A004554495257204F54204554594200415441440058454820"; + attribute INIT_26 of inst : label is "36313D35313D34313D33313D32313D31313D30312020202020203D46303D4530"; + attribute INIT_27 of inst : label is "AF004E5552204F5420224F47223D46313D45313D44313D43312020203D37313D"; + attribute INIT_28 of inst : label is "35FFC924410C280435FFC9000FB040001BFF03D302D301D30F3E09D300D304D3"; + attribute INIT_29 of inst : label is "DD0C0EC924AA0C320435FF24950C280435FFC924660C280435FFC924510C3204"; + attribute INIT_2A of inst : label is "78F82013FE200843FF4FEC32FF3EE5D5C930C607C6254DFA0AFEC932FF020D21"; + attribute INIT_2B of inst : label is "35FF071824B80C464835FF0920A7F5C9D1E12546CD47256EF214FEAF012010FE"; + attribute INIT_2C of inst : label is "50CD672003CD78253DCD464811E22815FE3E2818FE2550CD00002124BB0C4648"; + attribute INIT_2D of inst : label is "6F2003CD78253DCDC62815FE2550CDF5C90120A7F167B07C253DCDD02815FE25"; + attribute INIT_2E of inst : label is "CD2516CD24FFCDC9F9203DFE10FF06FF3EC9F16FB07D253DCDB72815FE2550CD"; + attribute INIT_2F of inst : label is "16CD24FFCD25CFCDFFD37CE52571CDAF252ECD24FFCDFD187E2571CD013E251E"; + attribute INIT_30 of inst : label is "CDAF24760C320435FF2526CD24FFCDFD1870C12571CD013E245B0C320435FF25"; + attribute INIT_31 of inst : label is "CD25CFCDFFD37CE52571CDAF24800C320435FF2526CD24FFCDFC1878ED4C2571"; + attribute INIT_32 of inst : label is "25CFCDFFD37CE52571CDAF252ECD24FFCDFC1861ED48C12571CDAF252ECD24FF"; + attribute INIT_33 of inst : label is "2126FBCD0A041124C02124FFCDFC187E70C12571CD013E251ECD2516CD24FFCD"; + attribute INIT_34 of inst : label is "11CD321C1110DBFB0ED3033E0DD37D47ED7C20102108AF0826FBCD00501124D8"; + attribute INIT_35 of inst : label is "11CD00681114DB2711CD501C1113DB2711CD461C1112DB2711CD3C1C1111DB27"; + attribute INIT_36 of inst : label is "11CD3268111CDB2711CD1E681117DB2711CD14681116DB2711CD0A681115DB27"; + attribute INIT_37 of inst : label is "3DCD7E03069E182711CD5068111FDB2711CD4668111EDB2711CD3C68111DDB27"; + attribute INIT_38 of inst : label is "E67C253DCD2546CD0F0F0F0FF0E667C9EB205AFE570AC67A5F18D67BF9102325"; + attribute INIT_39 of inst : label is "CD141C1108D60FDB2711CD0A1C113FCB0EDB081728A708F3C9253DCD2546CD0F"; + attribute INIT_3A of inst : label is "ED7C201221B0ED0FDC01400021B0ED00140127A621400011FA18083CC9FB2711"; + attribute INIT_3B of inst : label is "02D33C01D33C00D3F376FB59ED043E500021200011F80F0109D3143E0DD37D47"; + attribute INIT_3C of inst : label is "043E20001127A0C2151C1C1C1C1C1C09C607D33C06D33C05D33C04D3A003D33C"; + attribute INIT_3D of inst : label is "2516CD24FFCDFFFFFFFFFFAAAAAAAAAA5555555555000000000076FBE1DD59ED"; + attribute INIT_3E of inst : label is "0C320435FF24950C280435FF24FFCD25CFCDE5E52571CD013E248B0C320435FF"; + attribute INIT_3F of inst : label is "37EA18D513127CD1E9E1E1032018FE782571CDAF25CFCD24F30C5A0435FF24A5"; + begin + inst : RAMB16_S9 + --pragma translate_off + generic map ( + INITP_00 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_01 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_02 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_03 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_04 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_05 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_06 => x"0000000000000000000000000000000000000000000000000000000000000000", + INITP_07 => x"0000000000000000000000000000000000000000000000000000000000000000", + + INIT_00 => romgen_str2bv(inst'INIT_00), + INIT_01 => romgen_str2bv(inst'INIT_01), + INIT_02 => romgen_str2bv(inst'INIT_02), + INIT_03 => romgen_str2bv(inst'INIT_03), + INIT_04 => romgen_str2bv(inst'INIT_04), + INIT_05 => romgen_str2bv(inst'INIT_05), + INIT_06 => romgen_str2bv(inst'INIT_06), + INIT_07 => romgen_str2bv(inst'INIT_07), + INIT_08 => romgen_str2bv(inst'INIT_08), + INIT_09 => romgen_str2bv(inst'INIT_09), + INIT_0A => romgen_str2bv(inst'INIT_0A), + INIT_0B => romgen_str2bv(inst'INIT_0B), + INIT_0C => romgen_str2bv(inst'INIT_0C), + INIT_0D => romgen_str2bv(inst'INIT_0D), + INIT_0E => romgen_str2bv(inst'INIT_0E), + INIT_0F => romgen_str2bv(inst'INIT_0F), + INIT_10 => romgen_str2bv(inst'INIT_10), + INIT_11 => romgen_str2bv(inst'INIT_11), + INIT_12 => romgen_str2bv(inst'INIT_12), + INIT_13 => romgen_str2bv(inst'INIT_13), + INIT_14 => romgen_str2bv(inst'INIT_14), + INIT_15 => romgen_str2bv(inst'INIT_15), + INIT_16 => romgen_str2bv(inst'INIT_16), + INIT_17 => romgen_str2bv(inst'INIT_17), + INIT_18 => romgen_str2bv(inst'INIT_18), + INIT_19 => romgen_str2bv(inst'INIT_19), + INIT_1A => romgen_str2bv(inst'INIT_1A), + INIT_1B => romgen_str2bv(inst'INIT_1B), + INIT_1C => romgen_str2bv(inst'INIT_1C), + INIT_1D => romgen_str2bv(inst'INIT_1D), + INIT_1E => romgen_str2bv(inst'INIT_1E), + INIT_1F => romgen_str2bv(inst'INIT_1F), + INIT_20 => romgen_str2bv(inst'INIT_20), + INIT_21 => romgen_str2bv(inst'INIT_21), + INIT_22 => romgen_str2bv(inst'INIT_22), + INIT_23 => romgen_str2bv(inst'INIT_23), + INIT_24 => romgen_str2bv(inst'INIT_24), + INIT_25 => romgen_str2bv(inst'INIT_25), + INIT_26 => romgen_str2bv(inst'INIT_26), + INIT_27 => romgen_str2bv(inst'INIT_27), + INIT_28 => romgen_str2bv(inst'INIT_28), + INIT_29 => romgen_str2bv(inst'INIT_29), + INIT_2A => romgen_str2bv(inst'INIT_2A), + INIT_2B => romgen_str2bv(inst'INIT_2B), + INIT_2C => romgen_str2bv(inst'INIT_2C), + INIT_2D => romgen_str2bv(inst'INIT_2D), + INIT_2E => romgen_str2bv(inst'INIT_2E), + INIT_2F => romgen_str2bv(inst'INIT_2F), + INIT_30 => romgen_str2bv(inst'INIT_30), + INIT_31 => romgen_str2bv(inst'INIT_31), + INIT_32 => romgen_str2bv(inst'INIT_32), + INIT_33 => romgen_str2bv(inst'INIT_33), + INIT_34 => romgen_str2bv(inst'INIT_34), + INIT_35 => romgen_str2bv(inst'INIT_35), + INIT_36 => romgen_str2bv(inst'INIT_36), + INIT_37 => romgen_str2bv(inst'INIT_37), + INIT_38 => romgen_str2bv(inst'INIT_38), + INIT_39 => romgen_str2bv(inst'INIT_39), + INIT_3A => romgen_str2bv(inst'INIT_3A), + INIT_3B => romgen_str2bv(inst'INIT_3B), + INIT_3C => romgen_str2bv(inst'INIT_3C), + INIT_3D => romgen_str2bv(inst'INIT_3D), + INIT_3E => romgen_str2bv(inst'INIT_3E), + INIT_3F => romgen_str2bv(inst'INIT_3F) + ) + --pragma translate_on + port map ( + DO => DATA(7 downto 0), + DOP => open, + ADDR => rom_addr, + CLK => CLK, + DI => "00000000", + DIP => "0", + EN => ENA, + SSR => '0', + WE => '0' + ); + end generate; +end RTL; diff --git a/Bally - Astrocade_MiST/rtl/roms/bios3159_0.bin b/Bally - Astrocade_MiST/rtl/roms/bios3159_0.bin new file mode 100644 index 00000000..d35d6a30 Binary files /dev/null and b/Bally - Astrocade_MiST/rtl/roms/bios3159_0.bin differ diff --git a/Bally - Astrocade_MiST/rtl/roms/bios3159_0.hex b/Bally - Astrocade_MiST/rtl/roms/bios3159_0.hex new file mode 100644 index 00000000..0968c853 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/bios3159_0.hex @@ -0,0 +1,257 @@ +:1000000000F3AFD308C3610CC307201C3C1C20FFC6 +:10001000C30A2006FA0762FFC30D20FB7610FDC954 +:10002000C31020732372C9FFC31320210000C9FF2E +:10003000C31620008B0101FFE3F5C5D5DDE5FDE525 +:10004000FD210000FD397E23117A021F3836E5D5E7 +:1000500021CB00075F16001730032AFD4F195E23DE +:1000600056D5FD660BFD6E0AFD5603FD5E02D5DD1D +:10007000E1FD7E09FD5605FD5E04C9D1E17E23CB7D +:100080003F117C00D54F3012EB0600214B01CB779E +:1000900028032AFB4F0946CDA800D179FD4607FD6C +:1000A0004E0618AAE1D123E5CB60280A1A13FD7782 +:1000B000021A13FD7703FDE5E123232323CBA0CB15 +:1000C0003830031A13772320F6EBC97B007902320C +:1000D000067D00730BC40AA4008B017E040805FC96 +:1000E00005CF03DB01EE0AB206FE060B0715071962 +:1000F000071C077D079E07B903AD076A02E107C425 +:1001000007EB0BF60AFB0A56063306C90AAC010CCC +:10011000060B06BA01970CFB0C310D1B00CC0B151E +:100120000C760B900BAC0BBD0B4B0BAA0D21031FD8 +:1001300003DE028402640341036E03290356034C69 +:10014000037F03410C6C03230040020000C0C00089 +:10015000C0080004F0002AC02F2FD0E3E3EFEF1314 +:10016000CBCFC3CF27C7CF2020D4D00003C0C0003F +:10017000C3ECCF0807C0C0C0C0C0CFC8CBCBCBCB6F +:10018000C80BCB0B0BC82000E0C3C7F3F5C5D5E502 +:10019000ED5E3E00ED473EC8D30F3E34D30DCDA0FB +:1001A000040E0FCD7E04E1D1C1F1FBC93AFA4FFE36 +:1001B000AACA19203AEC4FB7202BAFF3D315D316A8 +:1001C000010B08ED7910FC111402CDF40CCDE50102 +:1001D0003C20E7FD360900FB2AE84F22E84F010BDF +:1001E00008EDB3AFC9CDEC03FD7709FD7007FE1331 +:1001F000D8FE1CD03EFF32EC4FC9C40DDD0D2010DF +:10020000C3A004C37B042008080107E408A0040677 +:100210000105BF0A3F3F3F3FBE0DCA0DDE174D41EE +:10022000582053434F52450023204F4620504C4105 +:10023000594552530023204F462047414D45530016 +:10024000CD5602EBCB71280778E60328012F47CD66 +:100250005602EBC3B80BCB08300A7D2F6F7C2F679B +:1002600023CB08C9CB08D8C32B00AFC5D547EB19A2 +:10027000E5EDB0E1D1C110F3C9E1E1FDE1DDE1D18E +:10028000C1F1E3C9CDC002E3C5060079CB39094FFE +:10029000EBEDB0C1D12BE3C5060009C10DEB1B1B73 +:1002A000AFFF74FF6E380A3C2720F8E136FFC11813 +:1002B0006AFF74FF6EE32B77E30D20E3E1C118556D +:1002C000DDE1AF4FFF72EBFF72EB676F78E510FD7A +:1002D0004739C5E5E5FD660BFD6E0A48DDE9CDC091 +:1002E000027E23E3A72809EBFF6EA73D2720F9EB49 +:1002F00023E30D20ECE1E1C1D5C5480600CB390967 +:10030000CB21EDB0C1C5CB38AFB62310FCA7280375 +:100310003EFF12C1E1CB412802FF6AE110FDC9FF97 +:100320006AFF6CEBFF6CEBFF6E682D2600197EFEFA +:1003300050D8EB3E009E27772310F82B7EF680776F +:10034000C9682D260019CB7EC83600EBAF3E009E53 +:1003500027772310F8C96826002D19CB7EC83600F0 +:10036000FD3406C94806000D097EEE8077C9AF1A34 +:100370008E2712132310F8FE99172FFD7708C9F561 +:100380002AEF4FCDAC03011700098A22EF4F2AF163 +:100390004F5FCDAC031922F14F5AEBF1A74F7A28EA +:1003A00008AF1930013C0D20F9C3D10A444DAF16F6 +:1003B0000729171520FB098AC9EB71237023AFEBBE +:1003C000CBF4C5E547EDB0E10E2809C110F4C90E24 +:1003D00009ED410CED51D30EC95E010108790F4FB3 +:1003E000A3200310F8C9AB777882E1C9282521DD65 +:1003F0004F1600CDD903160823CDD903011C0423C1 +:10040000ED785E933805D60838063C83774779C97E +:100410000C10EC21E34F7ECB7F2806CBBF773E113B +:10042000C9E5CD7400EB0117041100FFED78A6209B +:100430000A0D1C2310F6781E12180B140F30FC7ACC +:100440000707833C1E13E1AEE67F2807AE77E67F01 +:10045000477BC901100423ED78AE20050C10F77816 +:10046000C9CB67280CE610AE77E610477907D60CA3 +:10047000C9AE77E60F477907D60BC935C0700608B5 +:1004800021D54F1600CB39300A7EB728063D2720EC +:1004900001377723CB1A10ED3ADD4FB232DD4FC969 +:1004A00021F94FCB4EC0CBCEEB21EA4F7EB7281CB3 +:1004B00035200BE5DDE5CD1405DDE1E1180EEBCBD4 +:1004C0007EEB20083D3D2004D316D3152335F202E0 +:1004D00005363B23EB21E34FCBFEEB7EB7280135FE +:1004E000237E23B628132B7EB720093659237E3D61 +:1004F0002777180E3D2777180921F84FCB46280299 +:10050000CBFE21F94FCB8EC932D44FDD22D04FCD57 +:10051000FC0518032ACE4FDD2AD04F7E23B7FA5BA5 +:100520000532EA4F3AD44F011808CB3F3002EDA311 +:100530000605CB3F3002EDA30604CB3F3009EDA307 +:10054000CB3F38072B1804052318F5B720EC3AD217 +:100550004FD3163AD34FD315C3F405FE903015CBC5 +:100560005F280878011808EDB318B0E607F6104FB9 +:10057000EDA318A720077E2332D44F189EFEB0307B +:1005800006E60F5F1C183EFEC0300911D24FEDA0E9 +:10059000EDA01887200BDD3500200ADD232323186A +:1005A000F1FED03027E60FFE09200CDD6E00DD23C2 +:1005B000DD6600DD2318DB5E235623EBFE0438D214 +:1005C000DD2BDD7200DD2BDD730018C6FEE0300A86 +:1005D000E60F06004F545D0918E6200A3AF94FEE7F +:1005E0008032F94F18ACFEF028127E32EA4F23AF6A +:1005F000D316D31522CE4FDD22D04FC9AF32EA4FEA +:1006000032F94F011808ED7910FCC978D5577E4FA3 +:10061000FEC03802D1C923E63FBA2804232318EECE +:10062000D15E2356EBCB79C27D00CB712004D1F192 +:10063000E5EBE9FDCB08F6DDCB017EDD4E02DD36D4 +:100640000200FD7106C879A7C8110300DD19CD5657 +:1006500006110500DD19E5DD5601DD5E00DD6603EE +:10066000DD6E027C411910FDBC2804FDCB08B6DD0F +:10067000CB044628317CE34623FECF3007B838044C +:1006800046B8382023DD7003DD360200DDCB04DE02 +:10069000F1DDCB044EC87A2F577B2F5F13DD73003B +:1006A000DD7201C923E3DD7502DD7403E1DDCB04F6 +:1006B0009EC9AFCD4E0BEBCBF4D30CFD5E09790F89 +:1006C0000FE63F3C571528073EFFCDE20618F679A6 +:1006D000E6033C4FAF0D28060F0FC6C018F7CDE25A +:1006E00006AFE5C532FF0F3AFF4F4F7BAEA1AE77A5 +:1006F0007DC6286F7CCE006710F1C1E123C9DD7E85 +:1007000000DD560BDD5E06DDCB01F6F57E23835F53 +:100710007E238257F14E234623CDF60ACB77202C39 +:10072000CB5F2011AFC5D547EDB012D1EB0E280934 +:10073000EBC110F1C9EBC5E5411A137723772310FC +:10074000F8702370E10E2809C110EBC9CB5F2016A9 +:10075000AFC5D547EDA01B1BEA540712D1EB0E28FD +:1007600009EBC110ECC9EBC5E5411A13772B772BC8 +:1007700010F8702B70E10E2809C110EBC9DDCB0118 +:1007800076C8DDCB01B6DD660EDD6E0DDDCB007605 +:1007900028087BED443C4F06FF09CBF406003E28B9 +:1007A000934F7843772310FC091520F7C9EB4E23AC +:1007B0004623CBF2AFC5D547EDB0EBE10E2809EBF0 +:1007C000C110F2C97EA7C8FACE07FE643006CDE19B +:1007D000072318F0E6174723EBCDA800CD680018D3 +:1007E000E3C5E5DDE5A7FAED07DD210602FE2030D1 +:1007F0000DF5CD4E08CDF40CF13D20F5183BDD96FE +:10080000005F1600210000DD4E03DD46041910FDD7 +:100810000D20F7DD5606DD5E0519CD4E08D5DD4607 +:1008200004C5E5CD6C08E1DD4E0309C1FD7E0581FF +:10083000FD770510ECD1CDF40CDDE1E1C1C9FD7E01 +:10084000060707E6033C47AF378F10FD47C9CD3E8B +:100850000848FD5605FD7E04DD860110FBFEA0382C +:10086000097A41DD860210FB57AF5FC9DD4E0306F2 +:1008700000DDE5DD210000DD39DDE5D13E0CD319D9 +:100880003E08D30CFD7E06E6C028210707EBA7ED46 +:1008900042ED42F9CBB4F5411A137723772310F8D0 +:1008A000CB21F121000039545D3D20E1CD3E08CD42 +:1008B0007400FD7E06D319E630F608CD080BEBF583 +:1008C000C5D5E5411A137723772310F8FD7E04E69A +:1008D00003280170E10E2809D1C1F1D30C10E0DD2D +:1008E000F9DDE1C9000000000000002020202020E8 +:1008F0000020505050000000004848FC48FC484888 +:100900002078807008F020C0C810204098186090AF +:10091000A040A890686060600000000010202020C7 +:100920002020104020202020204000A870D870A84F +:1009300000002020F820200000000060602040001F +:100940000000F800000000000000006060000810D7 +:10095000204080007088888888887020602020204F +:100960002070708808708080F8708808300888705F +:1009700010305090F81010F880F00808887030405F +:1009800080F0888870F80810204040407088887097 +:1009900088887070888878081060006060006060E7 +:1009A0000060600060602040102040804020100007 +:1009B00000F800F80000402010081020407088085F +:1009C000102000207088B8A8B88078708888F888CF +:1009D0008888F08888F08888F070888080808870A7 +:1009E000F08888888888F0F88080E08080F8F88037 +:1009F00080E080808070888080988878888888F8F7 +:100A0000888888702020202020700808080808881E +:100A1000708890A0C0A09088808080808080F888B6 +:100A2000D8A8A888888888C8A898888888F88888D6 +:100A3000888888F8F08888F080808070888888A806 +:100A40009068F08888F0A09088708880700888701E +:100A5000F82020202020208888888888887088882E +:100A60008850502020888888A8A8D8888888502056 +:100A700050888888885020202020F8081020408046 +:100A8000F8704040404040700080402010080070E6 +:100A90001010101010702070A8202020200020407E +:100AA000F840200020202020A87020002010F810FE +:100AB000200000885020508800002000F80020000E +:100AC00000000000DDE1E3DDE948060021D50A0968 +:100AD0007EFD7709C920435E5C2552533B2F373892 +:100AE000392A3435362D3132332B26302E3DEB77F3 +:100AF000EDA1EAEF0AC9CD080B1805CD4E0BCBF2DC +:100B0000FD7304FD720518C9CD4E0BD30CC900E06E +:100B1000A0A0A0E04040404040E020E080E0E02095 +:100B20006020E0A0A0E02020E080E020E0E080E085 +:100B3000A0E0E020202020E0A0E0A0E0E0A0E02075 +:100B4000E0004000400040E0E0E0E0EDB0C9E5E654 +:100B5000FC6F7BE603B5F5E6407B28032FC6A06A51 +:100B60002600292929545D292919CB3FCB3F5F163F +:100B70000019EBF1E1C9CD7B0B188BE5C50600CB65 +:100B800039097EC1CB4128040F0F0F0FE60FE1C9D1 +:100B9000E5C50600CB3909C1CB412809070707077E +:100BA000AEE6F01803AEE60FAE77E1C95F1600CBF4 +:100BB00023CB12195E23562BCDF40C18085F1600B8 +:100BC000197EFD7709FD740BFD750AC9DD210D0243 +:100BD000064221EE4FC5FDCB06BECDEB0BC1CB7956 +:100BE000C83EBACDE107064221ED4F78E63F3DF819 +:100BF0004FCD7B0B2007CB782803B12014CBB8C690 +:100C000006E60FC62ACB702802F680CDE1077918D8 +:100C1000DD3E2018F00603E57EC60127772003237A +:100C200010F6E123233AF84FCB4FC811F64F0603D5 +:100C30001ABE2807D021F84FCBFEC91B2B10F11884 +:100C4000F4FF3530184C570CFF0EFF431402FE140E +:100C50002804FE1320F4C747414D45064F56455220 +:100C6000003A0020FEC3CA002031CE4FFF1BCE4FFA +:100C700032000032FF0F3D32EC4FFF001517BF2945 +:100C8000081913000F0211F30D2100207E23FE55D9 +:100C90002803211802FF4AE5E5CD190D11100C01BA +:100CA0000901DDE178C630FF323E2DFF32DD6603FB +:100CB000DD6E02FF343E0882571E1004DD6601DD42 +:100CC0006E00E57CB520DB39C501010111104DFF37 +:100CD0004EC17EA72803B838063E3FFF3218E9E12F +:100CE000D147EB5E235610FA235E2356234E23464C +:100CF000E1F1C5E5FD7304FD7205C9F5E5C5CD1942 +:100D00000DFF35082009B70DE1FF34E1F147CBF1C4 +:100D1000113030FF4EFF510FC9D5FF1B0040B80105 +:100D200000FF1BB841480D55E11118000E04FF34B7 +:100D3000C9D9CD990D4FFD7E07A9E63FC821360DD3 +:100D4000E5FF76FF430B00FF454C0DC9137F0D14E3 +:100D5000550D1C610DCB60C8793C283ACB79C00E8B +:100D6000FF793CC0D978D9FE01060A28020664DB67 +:100D70001C57AF5F6719CE002710FAD97718140CEB +:100D80002004CD990D0CCBF9FF40FE3D2808E60F5D +:100D9000D9FF60D5FF36D1D9C9C5D9E5783CE63E43 +:100DA0001FD94FAF47D1FF1AC1C9F5783CE63E477E +:100DB000F1ED6F2310FBC9454E5445522000FA0156 +:100DC000D30D28130000E80D190E47554E4649472C +:100DD000485400434845434B4D4154450043414C22 +:100DE00043554C41544F52005343524942424C499F +:100DF0004E470053454C4543542047414D456708F5 +:100E0000580D2843292042414C4C59204D4647203B +:100E10003139373800FFFFFFFFFF4D280201F34F44 +:100E200031E84EFF001B0040600E001BF04E7800C2 +:100E30000017B828085FE84E08000C1019E84E7D2E +:100E400046240A4F7D5324284F7D4630464F7D531C +:100E500030644F7B04D54F0221580EE5FF43650EE9 +:100E6000FF45A10EC92F0F0F0F050E0378FE1428A2 +:100E7000AF0F0FA1FF5D290FEB78A1677994FF5D9C +:100E8000E84E1A86CB582804AEE607AE7723232314 +:100E90002377FF19E84E3E1432D64FC9AF32E34FE5 +:100EA000C901D30F029C0E13690EDD21F04E3AF3F7 +:100EB0004F474FC5E511BA0ED5E9111E00DD19E106 +:100EC000C110F0C97990FF5DE44FE60FCD0110DD50 +:100ED0007E1A82FE983003DD771ADD7E1B84FE5574 +:100EE000D0DD771BC9DDE5D11AA7C8DD661DDD6E33 +:100EF0001CFF2EAF12C97990FF5DE44FE610C82B9E +:100F00002B2B2B2B7E07074FE603FF5D260FDD56AD +:100F10001BDD5E1A47790707E603FF5D220F48FFD6 +:100F20001CC90055AAFF01020408F801FF78FF5D03 +:100F3000E34FE610C0E5DD561BDD5E1AFF3ADD72B9 +:100F40001DDD731CEBDDE5D1010308FF2CE118AFBB +:100F500021F04E11F34E35F2690FFF7730FE08385D +:100F600002E6033C12FF777877231335F2770FFF01 +:100F7000770412FF777877231335F2930F11F54E2C +:100F8000FF770A3CFE0328F5FE0728F112FF7728B9 +:100F900032F24E1ACD0110010A4F0A82FE5030DDA6 +:100FA000025F030A84FE2E30D4025721F34E4623FB +:100FB0007ECD1A0F67D53E5C9092577CFF1C3EA0F9 +:100FC00091935F7CFF1CE154FF1C3EFF32EC4F3ECF +:100FD00001182A3AF34F3DFE04D2500F21C40ECD22 +:100FE000AA0E21E50ECDAA0E21F60ECDAA0E4111B4 +:100FF000E2FFDD19C5CD2D0FC110F43E0432D54FEF +:00000001FF diff --git a/Bally - Astrocade_MiST/rtl/roms/bios3159_1.bin b/Bally - Astrocade_MiST/rtl/roms/bios3159_1.bin new file mode 100644 index 00000000..dfbc1286 Binary files /dev/null and b/Bally - Astrocade_MiST/rtl/roms/bios3159_1.bin differ diff --git a/Bally - Astrocade_MiST/rtl/roms/bios3159_1.hex b/Bally - Astrocade_MiST/rtl/roms/bios3159_1.hex new file mode 100644 index 00000000..d47a2891 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/roms/bios3159_1.hex @@ -0,0 +1,257 @@ +:10000000C9C547FF7F0001000001C1C90862A507FB +:100010000862A507FFFFFFFFFFFFFFFFFFFFFFFFD6 +:1000200031C04EFF001B0040600E001D08527009D9 +:10003000FF17B81F08191C131BC04E9400000F03B4 +:10004000CD8611214310E5FF431402FE13C078FF53 +:100050005D9F10E60F4FAE0F0F0F0F5F21C24E7E58 +:10006000A728327BA7C05779FE0EC82371345F2BB7 +:100070007E0F3807CDCA10EDB01809CD0A12CDCACF +:1000800010EBEDB021000022DA4E21DD4EE5CDC7A8 +:1000900012E1C3DE117BFF5BB810D521C14E7EC9D2 +:1000A000806061315152401407080913040506129B +:1000B0000102031170000E208A11E81011112311A2 +:1000C000DE10D8103812AF11201021E64E060B4872 +:1000D0001910FDEB21CF4EC921C24E711842CD0A35 +:1000E00012FF6B0BCF4E1838FE0220043601181B8E +:1000F000FE00087908200F3601CD1612FF5FC44EAE +:100100000B00CF4E1803CD4611084F7932C04E1860 +:100110000F3DC03602CD46113E0532C04ECD1612FF +:10012000C38410A9C0FF5FCF4E0900D04E32D84E15 +:1001300021C44E060B3ACE4EFF6632CE4EEB010B7B +:1001400000CD751118DACD16123AC04EFF5B58116A +:10015000D521CF4E11C44E060BC96211651168112D +:100160006B11FF6201FF6401FF6601FF68FF5FCF53 +:100170004E0B00C44E092B7EE60FC83E01773C3281 +:10018000C14ECD1612E10E001825CD0A1221DA4E0D +:1001900011CF4E7EFE0AC8237EA7280FB9C8792347 +:1001A0004E35EBFF584FEB2B2B182A2BB62012CDD8 +:1001B0000A12C5FF1BCF4E15000021DA4EC1B1282F +:1001C0001C79FE0E20072377233609180913131311 +:1001D0001313CD0F13347911DD4ECD0F13EB11082E +:1001E000530E07E521C24E7EA72802C631C620FF66 +:1001F00032237EA72807C60F36002B3600C620FF05 +:1002000032E13AC04E0E03C38A1221C14E7EFE0275 +:10021000C0AF772B77C9FF312800085C20402158F8 +:100220004ECDC71221E44E7EFE5C280134237EA70A +:100230002819FE52281534C9AF32E34F21E44E7E0F +:10024000CB41201AA7C8237EA7C8353E08FF312816 +:1002500000204F28403D20F53C11184918182396DE +:10026000FE0BD8343E08FF31D8FF2050804C3D2093 +:10027000F53E0A11180121E54E8621804E01D8FF76 +:10028000093D20FC0E0DFF560E00F5410E0CFF56E9 +:10029000CB4F2016CB473E0428023E08B04F068BBA +:1002A000FF36F1FF5DC112FF32C948CBD921B4122C +:1002B000FF34F1C9202A4F564552464C4F572A2049 +:1002C00000202B2D62633D11CF4E3AC04E0E0DFF24 +:1002D000583AD94E070DFF58EB010600AFFF1A0E32 +:1002E00013FF56CD0F13200D0D79FE0920F33E0E9E +:1002F000CD0F1328ECEB7EE60F2005CD031318F687 +:10030000FE0EC001060009A7412BED6710FBC906D0 +:1003100005EBE5ED6F2310FB77E1EBC97662000793 +:1003200007070707FFFFFFFF31964FFF4D3502829A +:10033000DC4FFF4D280201F34FFF1B964F0C0000CE +:10034000F331964FFF0019A917151BE44F04000065 +:100350001BA24F22000017BE67081D0000A00B550E +:100360001D7A001E09001D57001D09001D2B001DD0 +:1003700009001D04002109000F0221283322AC4F7F +:1003800021783322B34F21501F22BA4F21504722E8 +:10039000C14FCDB314DD210D02FF374C022442DCE6 +:1003A0004F3AF34FFE0538023E0432A44FFE0238A6 +:1003B00004FE0538023E0432A24F3AA44F473AA247 +:1003C0004F4F16007ACD5B16C5D57AC631DD5E0477 +:1003D000DD56051D1DFD4E06FF32FD5E07FD56086C +:1003E000D5FF32D17BC6065F1414010104FD6605FA +:1003F000FD6E043E10FF24D1D5DDE57A06004A21CA +:10040000964F090909CDE215DDE1D1C1AFB0280948 +:100410003EC0DD7706051806003E80DD7706140D28 +:10042000AFB120A03E03F5FF510532A34FCD90148C +:10043000F1F5C630114C2F0E44FF32FF5128FF1446 +:10044000F13D20E2CDB314CD4916AF32DD4FFF436D +:100450001402FF45581418F6416B14558314578342 +:10046000145983145B8314538A14C0CD49163AA3DC +:100470004F3CE60332A34FCD5B16DDCB067E28EE64 +:10048000C3BB14D615CB3FC31D16CD4916FF48C9B3 +:100490003AA34FCD5B16DD7E0306030F380210FB37 +:1004A000480600FD09FD7E00D3133E09D3153E1119 +:1004B000D310C9FF1BB841200D00C9DD4E00DD4639 +:1004C00002DDCB06762003AF474F78B7200141DD30 +:1004D000700078B720050E00CD7E16DD7E01CDAB15 +:1004E000162813CDA916280E41CDA9162808DD46D9 +:1004F00001CDA916203CDD7701DD7703DD5605DD52 +:100500005E04CD2415FD6605FD6E040101043E1058 +:10051000FF243AA54FDD77043AA64FDD7705CDFFDE +:1005200015C39014D5FF3B00EB0600110104FF2A10 +:10053000D1C9016C171180173E0521B117F5C5D53A +:10054000E51AD304C5DD5605DD5E04CD2415E13E74 +:1005500010010104FF24FF5107E1011808EDB3D198 +:10056000C1F13D2807130303030318D1FD5605FD10 +:100570005E04FD210000FD19110004FD7E0021B87C +:100580004101200DEDB12005032B7318F7FD231554 +:1005900020E9DDCB0676280421A44F35DDCB06BE4D +:1005A0000E040D79CD5B16DDCB067E28180600C53E +:1005B0007921964F09090937CDE215C1FF5479C554 +:1005C000B7CDE215C1FF511E79B720D621A24F3514 +:1005D00035280234C93ADC4F3D2732DC4FC2401384 +:1005E000FF78FD4E093004CBA1CBE9FD5E07FD5637 +:1005F000083E0C835F140643DD210D02FF36C9DD82 +:10060000CB067EC8DD7E03CD2E17DD5605DD5E04EC +:10061000E5CD2415E10101043E10FF24C9CD5B1690 +:10062000AFB02003DD7E02DD7702DDAE012812EEE1 +:100630000C280EEE0CEE032808EE03DDCB06762028 +:1006400003DD7E01DD770318B63AA44FB73E0228DA +:100650000621A24F3E089632D54FC9D5E5FF5B6E05 +:1006600016D5FDE1FF5B7616D5DDE1E1D1C9441772 +:100670004E1758176217A84FAF4FB64FBD4FFF77B1 +:1006800020B72808DD460178CDAB16C8FF770447B0 +:10069000043E800710FD473E08CDAB16200247C937 +:1006A000060F3E08CDAB1647C93E08D516080F5FAA +:1006B000A0CDBF167B28061520F437CB12D1C9C5B3 +:1006C000D5E5F5DD5604DD5E05CB57280A7AFE0038 +:1006D000282FD604571830CB5F280A7AFE9830218D +:1006E000C604571822CB47280A7BFE0B2813D604D2 +:1006F0005F1814CB4F280A7BFE5B2805C6045F18E1 +:1007000006F137CB121823D5D5C15158FF3B00E174 +:10071000EB7EB720EC012800097EB720E47A32A5F1 +:100720004F7B32A64FF11600CB3AE1D1C1C92189E6 +:1007300017CB47C0219117CB4FC0218D17CB5FC07E +:10074000219517C9FDEEE1D49917180C0118C8BD01 +:10075000B2A89D171C7D011C9F968D85A1171C2D8D +:10076000011C7E77706AA51718590118001414002F +:1007700000455100054001501140014400000000B7 +:100780000703070387040001801455410014050581 +:1007900014004155141450501408A82A20FFC3C354 +:1007A000FF0CFC3F30AA8282AAB362F887F8F8F8FF +:1007B000F8EFFF3F00FFFDF5F58FEE3E00FFFDF582 +:1007C000F54E883800FFFDF5F548443400FFFDF58F +:1007D000F50000000000000000FFFFFFFFFFC3E87E +:1007E00019F3FF1180DD210D023ADC4FB72808FF15 +:1007F000374C020B42DC4FAFD30C32FF0FFBC9FF6B +:100800000DDC614FDA4F194F1809FF0DDC784FDB13 +:100810004F3D4FFD7E07B7C80AB7C87EB7280911FC +:100820001200197EB72801C90A3D02200D3ADC4F9B +:10083000B73E1028023E0232DC4FE5DDE50A6F26A6 +:10084000002929116802DDCB00763E402801AF194E +:10085000EBFF3AEB060511280036FF1910FB1600D6 +:10086000DD5E0F626B2919118F1D19EBC1E1E523C4 +:10087000360123030303CDD319030323360123CD0C +:10088000D319E13680FF13124F01D71FC94809DD84 +:1008900021614F1804DD21784FDD4E0011800021C9 +:1008A0008000FF7EDD7409DD7508DD7204DD7303F1 +:1008B000C9DD21784F782F1805DD21614F78E6E0FA +:1008C0000F0F0F0FFE0E20023E0CDD770FC9DD7EED +:1008D00001E660FE20280FD0DDCB075EC8DD3601C3 +:1008E00000DD360701C9DD7E06FE48300EDD36022A +:1008F00002DD360180218B1DFF3EC9DD360100FE81 +:1009000058301D3A904FB7C01E4CDD560B15FF3BBB +:1009100000EB11D7FF06007E7023B6701920F8C9CE +:10092000FE60300C1E40DDCB007620DE1E5818DA4B +:10093000DDCB0076280CFF0DDD614F08AD1FA64F03 +:10094000180AFF0DDD784F64BD1FA24FDD3611067A +:10095000DD361280DD360168DD7E0BD608FE1330F1 +:1009600002C62057FF542B7EFE05CE00776069DD5E +:1009700021124F3EC0FF120E0C21021FF3FF34FF65 +:1009800051FA3E0132DE4FC921F41EF53E08D3195B +:10099000F1FE01D8FE043003CDC81903FE02D8FED3 +:1009A000053003CDC819FE03D803083E8132904FAD +:1009B00008CDC819FE04D80321E51DF53E0CD31956 +:1009C000F1CDC819FE05D803F5D50A573E08FF2218 +:1009D000D1F1C91A771303231A77231303360003BF +:1009E000230AEB86EB7713C9FF4D1E0284F44F31C7 +:1009F000064FFF001B064FD600007B02F84F17B8CA +:100A0000D60819C31D13124FC09F1F02F3FF005FCA +:100A1000DA4F0C00CB1D1B00406801FF1B6841F83A +:100A20000C001B124F8F00000D100D023708020B37 +:100A3000C4A24F3788020BC4A64F052C1B352C01CE +:100A40000B7A1D02AF32904F3AA14F1E5801BE1DC6 +:100A5000CD88193AA54F1E4001B91DCD88193E4FCA +:100A600032144F32174FDD21614FDD360010211552 +:100A70004FCD301DDD21784FDD360050CD301D3A91 +:100A8000904FB7281DDD218F4FDD360010DD360C6D +:100A900003DD360840DD360648DD360B0ACD501D35 +:100AA000180B3E08D319FF234C2A08F41E1112001C +:100AB000DD21184F0120043E02B820020E60DD71D6 +:100AC00000DD360701DD360C03DD1910EC3E1DEDAF +:100AD000473E74D30DFF5164F3DD210D02FF002B5F +:100AE0001208FF33403540010B871D3320020BBB3A +:100AF00007531B0D01683207531B513C2B0808FF9D +:100B0000384002FF0043140245341B02DD21184F18 +:100B10001112000604C5D5CDCE18D1C1DD193ADEBB +:100B20004F3D28DF10EF18DB02C30C1A3AF84FCB09 +:100B30007FC8FF7808281B09281B5CB9185DB1180D +:100B4000558F18579518938D1854FF17560A18513A +:100B5000E117C032323232320808D9DDE53E74D3B3 +:100B60000D3EC8D30F21124FCD671DCD251DAF32CD +:100B7000FF0FDDCB01462028110514FF28261EDDBE +:100B80006E122C2CFF1EDDCB016E203021D71D16DE +:100B900000DD5E0F195E2356EBFF1E210C1F1808A7 +:100BA000110416FF28213C1FFF1EDD720EDD730DA0 +:100BB00021154FCD501DDDE108D9FBC921081F18B3 +:100BC000E7F5C5D5E5DDE521194F1111000604CD86 +:100BD0001A1D231116000603CD1A1DAF32FF0F0692 +:100BE00004DD21184FDDCB01762811DD660EDD6EA8 +:100BF0000DDD7E0FD30C36C0DDCB01B6DDCB017E23 +:100C0000282BDD560BDD5E06DD7E00FF38DD720E23 +:100C1000DD730DDD770F210040197EEB36C0B7285C +:100C200008DDCB01BEDDCB01EEDDCB01F6111200FC +:100C3000DD1910B121124FCD671D28123E76D30D5C +:100C4000DD7E0BFE323E0030023E6AD30FFBDD211B +:100C5000184F0604218B1D111200DDCB017E280CDC +:100C6000FF3EDDCB075E2804DDCB01BEDD1910EAB7 +:100C7000060221154FCD671DCAF81CCD251DFBDDD1 +:100C8000CB0146C2031DDDCB016E2025DD7E03DDD9 +:100C9000B604DDB608DDB6092017DD7702DDCB012D +:100CA000662036DD36124BDDCB01DEDDCB01E618EA +:100CB0002821831DFF3E2808DDCB01DEDDCB01A608 +:100CC000DD7E1191F2D61CDD5E12161E1ADD771242 +:100CD000131ADDCB01DEDD7711DD7E0FDDBE1028BE +:100CE00007DDCB01DEDD7710DDCB015E2020211595 +:100CF0004FCD501D05C2751CFBCD0002DDE1E1D1D9 +:100D0000C1F1C921781DFF3E21154FCD251DDDCB39 +:100D1000019E21124FCD501D18DE7E23E6A0280132 +:100D2000341910F6C9F3DD7EFF77A7C023772BC9EE +:100D3000DD360332DD360180DD360701DD360C019C +:100D4000DD360604DD360B28DD360F06DD36124BA8 +:100D5000DDE5D1F3DD36FF00237E73A728065F7E35 +:100D60002B1B12C92B73C9F35E2323562B2B7BA796 +:100D7000D5DDE1C9C11B591B0A44474554205245E2 +:100D8000414459002F0A4844524157009F095B00D3 +:100D9000030F00030F00040F00020C00040F0001FA +:100DA0000B00040F00000800040F00FF0600040FF2 +:100DB00000FE0400030F00FD0348162C430E1244EE +:100DC000280D3FA27D0B87A27D6C870606000000E0 +:100DD00030300000800F0FF81D061E101E181E2454 +:100DE0001E321E421E0111081C3E6B08083C7EA9E3 +:100DF000083C7EEB89081CAE0A0A0205400051003F +:100E00000400010000400A0A0203500014000140DF +:100E10000A0A0202540055400A0702041000054065 +:100E2000540050000A060205004045001000500022 +:100E300040000A05020600400100050014005400AD +:100E400050000A05010501441040406004000F03F2 +:100E5000050155000545401501405001401500545D +:100E60007004020F02051550545050505050551543 +:100E70004B04030F02055500150015001400054032 +:100E8000D2140001041301100000455440005555D0 +:100E900040000AA800000AA200010AAA801402AABF +:100EA000005000A8054005555400155550005455F4 +:100EB00050005005540050015500100155401000DD +:100EC00005500000015000000040000001400000FB +:100ED0000054D23C000D04070110000045544000AE +:100EE000555540000AA800000A88150116A555416D +:100EF00015555555010C20303830B2F2F63C3C30D7 +:100F00003030474F54204D45000001010000030FD1 +:100F100000440011551015555002AA0002A200020B +:100F2000AA8000AA0000A80015550055555051553B +:100F3000504155004155004555000155000004162B +:100F400000055000005555000155554005555550B8 +:100F500015541554155005541540015415400154AD +:100F60001550055405541550015555400055550070 +:100F70000015540002AAAA8000AAAA0012AAAA84F4 +:100F800010A82A041020080452AAAA8510200804D8 +:100F90001000000410000004008011B00900C9CD49 +:100FA000991F247E0C8D129606A82496F0CD991FC9 +:100FB00012BD06BD248D12BD068D2470F0CD991F83 +:100FC00018E112E106E118E112BD06C812C806E1F7 +:100FD00012E106EE12E1F088EFFF3F00FFFDF5F0B1 +:100FE000E0B0FF3FE105058F054CF0FFFFFFFFFF7D +:100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:00000001FF diff --git a/Bally - Astrocade_MiST/rtl/scandoubler.v b/Bally - Astrocade_MiST/rtl/scandoubler.v new file mode 100644 index 00000000..5a3ccd17 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/scandoubler.v @@ -0,0 +1,195 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// 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 . + +// TODO: Delay vsync one line + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Bally - Astrocade_MiST/rtl/spram.vhd b/Bally - Astrocade_MiST/rtl/spram.vhd new file mode 100644 index 00000000..d86010fc --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/spram.vhd @@ -0,0 +1,91 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY spram IS + GENERIC + ( + init_file : string := ""; + --numwords_a : natural; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + data : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + wren : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END spram; + + +ARCHITECTURE SYN OF spram IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "SINGLE_PORT", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + wren_a => wren, + clock0 => clock, + address_a => address, + data_a => data, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Bally - Astrocade_MiST/rtl/sprom.vhd b/Bally - Astrocade_MiST/rtl/sprom.vhd new file mode 100644 index 00000000..292a214f --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/sprom.vhd @@ -0,0 +1,83 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY sprom IS + GENERIC + ( + init_file : string := ""; + --numwords_a : natural; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END sprom; + + +ARCHITECTURE SYN OF sprom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Bally - Astrocade_MiST/rtl/video_mixer.sv b/Bally - Astrocade_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..ec953e53 --- /dev/null +++ b/Bally - Astrocade_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd7, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule