From dd21affa1bf2d0d847cc73b8244e2fc4ab451785 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sat, 18 Jan 2020 21:36:27 +0100 Subject: [PATCH] Robotron-FPGA: Works, Sinistar has minor issues and no speech Should work with Robotron 2048, Joust, Sinistar, Splat, Bubbles, Stargate --- .../Robotron-FPGA/README.md | 192 + .../Robotron-FPGA/RobotronFPGA.qpf | 31 + .../Robotron-FPGA/RobotronFPGA.qsf | 231 + .../Robotron-FPGA/RobotronFPGA.sdc | 138 + .../Robotron-FPGA/buildall.sh | 16 + .../Robotron-FPGA/clean.bat | 15 + .../Robotron-FPGA/rtl/RobotronFPGA_MiST.sv | 354 ++ .../Robotron-FPGA/rtl/build_id.tcl | 35 + .../Robotron-FPGA/rtl/cpu68.vhd | 3963 +++++++++++++++++ .../rtl/defender_sound_board.vhd | 184 + .../Robotron-FPGA/rtl/dpram.vhd | 81 + .../Robotron-FPGA/rtl/gen_ram.vhd | 84 + .../Robotron-FPGA/rtl/pll_mist.qip | 4 + .../Robotron-FPGA/rtl/pll_mist.vhd | 429 ++ .../rtl/robotron_cpu/decoder_4.vhd | 54 + .../rtl/robotron_cpu/decoder_6.vhd | 54 + .../rtl/robotron_cpu/robotron_cpu.vhd | 1096 +++++ .../rtl/robotron_cpu/robotron_cpu_test.vhd | 363 ++ .../Robotron-FPGA/rtl/robotron_cpu/sc1.vhd | 240 + .../Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd | 160 + .../Robotron-FPGA/rtl/robotron_soc.vhd | 262 ++ .../Robotron-FPGA/rtl/sdram.sv | 253 ++ 22 files changed, 8239 insertions(+) create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd create mode 100755 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd create mode 100644 Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md new file mode 100644 index 00000000..f0291cc6 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/README.md @@ -0,0 +1,192 @@ +robotron-fpga MiST port +======================= + +Supported games: Robotron 2048, Joust, Sinistar, Bubbles, Splat, Stargate + +After loading the RBF, a CMOS clearing will happen. Reset the core to start +the game. + +Sinistar has some graphics issues, and the speech chip is not implemented. + +robotron-fpga +============= + +An implementation of the classic Robotron: 2084 video arcade game from 1982. +Both the sound board and CPU/interface boards are implemented, but are in +separate sub-projects at the moment. The CPU/interface implementation relies +on a Motorola MC6809E processor attached to the FPGA board via an adapter +board design that is part of this project. + +![robotron-cpu on NEXYS2 FPGA board](https://github.com/sharebrained/robotron-fpga/raw/master/doc/photo/robotron-on-nexys2.jpg) + +The goal is to have a complete Robotron: 2084 game implemented in a single, +compact, inexpensive FPGA board which includes the necessary peripherals: +video and sound outputs, joysticks interface, and coin/player buttons. + +Status +====== + +The CPU/interface and sound boards are implemented as separate projects. +Both appear to function well. + +The MC6809E breakout board has been fabricated, but has some design issues +that need to be addressed. The primary issue is the lack of pull-up/-down +resistors on key MC6809E signals, to keep the processor in a RESET state +until the FPGA board is ready to work with the MC6809E. I also screwed up +and put the NEXYS2 connector on the "bottom side" of the board. Smooth! + +Documentation +============= + +These documents served me well during development of this project. + +[Sean Riddle](http://seanriddle.com/) - Williams arcade machine information, +including Robotron: 2084. + +* [Hardware overview](http://seanriddle.com/willhard.html) +* [Memory map](http://seanriddle.com/memmap.gif) +* [Processor and video timing](http://seanriddle.com/timing.html) +* [BLTter description and test code](http://seanriddle.com/blittest.html) + +[Robotron-2084](http://www.robotron-2084.co.uk/) - Williams arcade machine +official documentation. + +* [Robotron schematics and instruction manuals](http://www.robotron-2084.co.uk/manualsrobotron.html) +* [Defender "later series" theory of operation](http://www.robotron-2084.co.uk/manualsdefender.html), + interesting because the Robotron and Defender hardware is quite + similar. + +Documentation for various ICs in the original Robotron: 2084 machine. + +* [MC6809E microprocessor datasheet](http://www.classiccmp.org/dunfield/r/6809e.pdf) +* [MC6809E microprocessor programming manual](http://www.classiccmp.org/dunfield/r/6809prog.pdf) +* [DM9316 Synchronous 4-Bit Binary Counter](http://www.ti.com/product/dm9316) +* National Semiconductor(?) DM7489 64-bit random access read/write memory + (no good reference) +* [Harris HM-7641 512 x 8 PROM](http://www.bitsavers.org/pdf/harris/_dataBooks/1978_Harris_Memory_Vol1.pdf) (page 2-35) +* [Harris HM-6514 1024 x 4 CMOS RAM](http://www.bitsavers.org/pdf/harris/_dataBooks/1978_Harris_Memory_Vol1.pdf) (page 3-49) +* [Mostek MK4116 16,384 x 1 bit dynamic RAM](http://hardware.speccy.org/datasheet/MK4116.pdf) +* [Signetics 8T97 hex buffer](http://www.bitsavers.org/pdf/signetics/_dataBooks/1977_Bipolar_Microprocessor.pdf) (page 96) +* [Various 74-series logic ICs](http://www.ti.com/lsds/ti/logic/home_overview.page) + +[Digilent](http://www.digilentinc.com/) - FPGA development boards and +accessories. + +* [NEXYS2 FPGA development board](http://digilentinc.com/Products/Detail.cfm?NavPath=2,400,789&Prod=NEXYS2) + +[Xilinx](http://www.xilinx.com/) - FPGA silicon and tools vendor. + +* [Spartan-3E documentation](http://www.xilinx.com/support/documentation/spartan-3e.htm) + +Requirements +============ + +* Digilent NEXYS2 Spartan-3E FPGA development board. + + This is the board I've done my development on, and is a good choice + because it has plenty of inputs, a VGA output connector, many switches + and LEDs, and enough onboard RAM and flash to meet the game's memory + needs. + +* Williams Robotron: 2084 ROM binary files: + + These files are often used with MAME, the arcade emulator. CPU board + ROM files are named "robotron.sb?", where "?" is "1" through "9" and + "a" through "c". The sound board ROM file is named "robotron.snd". + +* Python 2.7: + + Used to transform ROM and PROM files into VHDL files. + +* Xilinx ISE WebPack 13.4: + + For compiling VHDL and generating the bit file for the FPGA. + +* Digilent Adept or other JTAG tool: + + For loading the bit file into FPGA board. + +* VGA monitor: + + Video output is 31.25 kHz horizontal sync and 60 Hz vertical sync, + which is compatible with VGA monitors. The output is line-doubled + from the arcade game's original 15.625 kHz horizontal sync. + +* RC lowpass filter: + + The PWM audio output from the FPGA needs filtering to sound reasonable, + or an eight-bit DAC can be attached to the 8-bit audio output pins of + the FPGA board. + +Tools +===== + +* make_rom_file.py: + + Translates a set of Robotron ROM board ROM files + (like those you would use with the MAME arcade emulator) into a + binary file that can be loaded into the flash device on the Digilent + FPGA board. + +* make_decoder_vhdl.py: + + Translates a decoder.4 or decoder.6 file (data + dumped from decoder PROMs on the Robotron CPU board) into a VHDL + file used by the robotron_cpu project. + +* dac_out_wave.py: + + Translates the text file output of robotron_test.vhd + into a WAV file that can be played. + +* make_sound_rom.py: + + Produces rom_snd_blocks.vhd, containing VHDL ROM + blocks, from the contents of a robotron.snd ROM file. The + robotron.snd file is not provided due to copyright on the original + ROM binaries produced by Williams. I happen to have a physical + instance of the ROM board, so I'm in the clear. :-) + +Contributing +============ + +Contributions are welcome! + +Please respect Williams Electronics' copyright and do not post any VHDL +or .bit files containing their binary code. + +License +======= + +This hardware design is licensed under a +[Creative Commons Attribution-ShareAlike 3.0 Unported License] +(http://creativecommons.org/licenses/by-sa/3.0/). + +The associated software is provided under the GNU Public License, +version 3: + +This project 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 project 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 project. If not, see . + +Contact +======= + +Jared Boone + +ShareBrained Technology, Inc. + + + + +The latest version of this repository can be found at +https://github.com/sharebrained/robotron-fpga diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf new file mode 100644 index 00000000..df002df5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 17.0.1 Build 598 06/07/2017 SJ Standard Edition +# Date created = 04:04:47 October 16, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "17.0" +DATE = "04:04:47 October 16, 2017" + +# Revisions + +PROJECT_REVISION = "RobotronFPGA" diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf new file mode 100644 index 00000000..bd44a02d --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.qsf @@ -0,0 +1,231 @@ +# -------------------------------------------------------------------------- # +# +# 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 = 16:34:25 January 07, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# RobotronFPGA_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:22:13 JUNE 04, 2019" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26" +set_global_assignment -name SMART_RECOMPILE ON + +# 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" +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name TOP_LEVEL_ENTITY RobotronFPGA_MiST + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name 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 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_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/cpu1.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR" +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(Defender_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Defender_MiST) +# ------------------------- +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/RobotronFPGA_MiST.sv +set_global_assignment -name VHDL_FILE rtl/defender_sound_board.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd +set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd +set_global_assignment -name VHDL_FILE rtl/dpram.vhd +set_global_assignment -name VHDL_FILE rtl/cpu68.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_soc.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/sc1.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/robotron_cpu.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/decoder_6.vhd +set_global_assignment -name VHDL_FILE rtl/robotron_cpu/decoder_4.vhd +set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip +set_global_assignment -name VHDL_FILE ../../../common/CPU/MC6809/cpu09l_128a.vhd +set_global_assignment -name VHDL_FILE ../../../common/IO/pia6821.vhd +set_global_assignment -name VERILOG_FILE ../../../common/CPU/MC6809/mc6809i.v +set_global_assignment -name SIGNALTAP_FILE output_files/cpu1.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc new file mode 100644 index 00000000..cad1ec42 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/RobotronFPGA.sdc @@ -0,0 +1,138 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set vid_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set game_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set aud_clk "pll|altpll_component|auto_generated|pll1|clk[2]" + +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.4 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.2 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $sdram_clk] 1.000 [get_ports {LED}] +set_output_delay -add_delay -clock_fall -clock [get_clocks $vid_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] +set_clock_groups -asynchronous -group [get_clocks $game_clk] -group [get_clocks $aud_clk] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh new file mode 100755 index 00000000..2fa8e228 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/buildall.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +PROJECTS=" \ +ROBOTRON \ +JOUST \ +SPLAT \ +BUBBLES \ +STARGATE \ +SINISTAR" + +mkdir -p Releases +for PROJECT in $PROJECTS; do + echo "Compiling $PROJECT" + sed -i "s/^.define CORE_NAME.*/\`define CORE_NAME \"$PROJECT\"/" rtl/RobotronFPGA_MiST.sv + quartus_sh --flow compile RobotronFPGA.qsf && cp output_files/RobotronFPGA.rbf Releases/$PROJECT.rbf +done \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat new file mode 100644 index 00000000..c9a2cb06 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/clean.bat @@ -0,0 +1,15 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output +rmdir /s /q simulation +rmdir /s /q greybox_tmp +del PLLJ_PLLSPE_INFO.txt +del *.qws +del *.ppf +del *.qip +del *.ddb +pause diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv new file mode 100644 index 00000000..c51b7f46 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/RobotronFPGA_MiST.sv @@ -0,0 +1,354 @@ +//============================================================================ +// Robotron-FPGA MiST top-level +// +// Robotron-FPGA is Copyright 2012 ShareBrained Technology, Inc. +// +// Supports: +// Robotron 2048/Joust/Stargate/Bubbles/Splat/Sinistar + +module RobotronFPGA_MiST( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE +); + +`include "rtl/build_id.v" + +`define CORE_NAME "ROBOTRON" +//`define CORE_NAME "JOUST" +//`define CORE_NAME "SPLAT" +//`define CORE_NAME "BUBBLES" +//`define CORE_NAME "STARGATE" +//`define CORE_NAME "SINISTAR" + +localparam CONF_STR = { + `CORE_NAME,";ROM;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Swap Joysticks,Off,On;", + "T0,Reset;", + "V,v1.0.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; + +reg [7:0] SW; +reg [7:0] JA; +reg [7:0] JB; +reg [3:0] BTN; +reg blitter_sc2, sinistar; +reg [1:0] orientation; // [left/right, landscape/portrait] + +always @(*) begin + orientation = 2'b10; + SW = 8'h00; + blitter_sc2 = 0; + sinistar = 0; + + if (`CORE_NAME == "ROBOTRON") begin + BTN = { m_one_player, m_two_players, m_coin1 | m_coin2, reset }; + JA = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + JB = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + end else if (`CORE_NAME == "JOUST") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ 5'b00000, m_fireA, m_right, m_left }; + JB = ~{ 5'b00000, m_fire2A, m_right2, m_left2 }; + end else if (`CORE_NAME == "SPLAT") begin + blitter_sc2 = 1; + BTN = { m_one_player, m_two_players, m_coin1 | m_coin2, reset }; + JA = ~{ m_right2, m_left2, m_down2, m_up2, m_right, m_left, m_down, m_up }; + JB = ~{ m_right4, m_left4, m_down4, m_up4, m_right3, m_left3, m_down3, m_up3 }; + end else if (`CORE_NAME == "BUBBLES") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ 4'b0000, m_right, m_left, m_down, m_up }; + JB = ~{ 4'b0000, m_right2, m_left2, m_down2, m_up2 }; + end else if (`CORE_NAME == "STARGATE") begin + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = ~{ m_fireE, m_up, m_down, m_left | m_right, m_fireD, m_fireC, m_fireB, m_fireA }; + JB = ~{ m_fire2E, m_up2, m_down2, m_left2 | m_right2, m_fire2D, m_fire2C, m_fire2B, m_fire2A }; + end else if (`CORE_NAME == "SINISTAR") begin + sinistar = 1; + orientation = 2'b01; + BTN = { m_two_players, m_one_player, m_coin1 | m_coin2, reset }; + JA = { sin_x, 2'b00, m_right | m_left | m_right2 | m_left2, sin_y, 2'b00, m_up | m_down | m_up2 | m_down2 }; + JB = { sin_x, 2'b00, m_right | m_left | m_right2 | m_left2, sin_y, 2'b00, m_up | m_down | m_up2 | m_down2 }; + end +end + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clk_mem; +assign SDRAM_CKE = 1; + +wire clk_sys, clk_mem, clk_aud; +wire pll_locked; +pll_mist pll( + .inclk0(CLOCK_27), + .areset(0), + .c0(clk_mem),//96 + .c1(clk_sys),//12 + .c2(clk_aud),//0.89 + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire [7:0] audio; +wire hs, vs; +wire blankn; +wire [2:0] r,g; +wire [1:0] b; +wire key_pressed; +wire [7:0] key_code; +wire key_strobe; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +/* +ROM Structure: +0000-BFFF main cpu 48k +C000-CFFF snd cpu 4k +*/ +data_io data_io ( + .clk_sys ( clk_mem ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); + +reg port1_req, port2_req; +wire [23:1] mem_addr; +wire [15:0] mem_do; +wire [15:0] mem_di; +wire mem_oe; +wire mem_we; +wire ramcs; +wire romcs; +wire ramlb; +wire ramub; + +reg clkref; +always @(posedge clk_sys) clkref <= ~clkref; + +sdram #(.MHZ(96)) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clk_mem ), + .clkref ( clkref ), + + // ROM upload + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[22:0] ), + .port1_ds ( 2'b11 ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout[7:4], ioctl_dout[7:4], ioctl_dout[3:0], ioctl_dout[3:0]} ), + .port1_q ( ), + + // CPU/video access + .cpu1_addr ( ioctl_downl ? 17'h1ffff : sdram_addr ), + .cpu1_d ( mem_di ), + .cpu1_q ( mem_do ), + .cpu1_oe ( ~mem_oe & ~(ramcs & romcs) ), + .cpu1_we ( ~mem_we & ~(ramcs & romcs) ), + .cpu1_ds ( ~romcs ? 2'b11 : ~{ramub, ramlb} ) +); + +// ROM address to SDRAM address: +// 0xxx-8xxx -> 0xxx-8xxx +// DXXX-FXXX -> 9xxx-Bxxx +wire [17:1] sdram_addr = ~romcs ? {1'b0, mem_addr[16], ~mem_addr[16] & mem_addr[15], mem_addr[14:1]} : { 1'b1, mem_addr[16:1] }; + +always @(posedge clk_mem) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clk_sys) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ioctl_downl | ~rom_loaded; +end + +robotron_soc robotron_soc ( + .clock ( clk_sys ), + .clock_snd ( clk_aud ), + .vgaRed ( r ), + .vgaGreen ( g ), + .vgaBlue ( b ), + .Hsync ( hs ), + .Vsync ( vs ), + .audio_out ( audio ), + + .blitter_sc2 ( blitter_sc2 ), + .sinistar ( sinistar ), + .BTN ( BTN ), + .SIN_FIRE ( ~m_fireA & ~m_fire2A ), + .SIN_BOMB ( ~m_fireB & ~m_fire2B ), + .SW ( SW ), + .JA ( JA ), + .JB ( JB ), + + .MemAdr ( mem_addr ), + .MemDin ( mem_di ), + .MemDout ( mem_do ), + .MemOE ( mem_oe ), + .MemWR ( mem_we ), + .RamCS ( ramcs ), + .RamLB ( ramlb ), + .RamUB ( ramub ), + .FlashCS ( romcs ), + + .dl_clock ( clk_mem ), + .dl_addr ( ioctl_addr[15:0] ), + .dl_data ( ioctl_dout ), + .dl_wr ( ioctl_wr ) +); + +mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(11)) mist_video( + .clk_sys ( clk_sys ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( r ), + .G ( g ), + .B ( {b, b[1] } ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .rotate ( {orientation[1],rotate} ), + .scandoubler_disable( scandoublerD ), + .ce_divider ( 1'b1 ), + .scanlines ( scanlines ), + .blend ( blend ), + .ypbpr ( ypbpr ) + ); + +user_io #( + .STRLEN(($size(CONF_STR)>>3))) +user_io( + .clk_sys ( clk_sys ), + .conf_str ( CONF_STR ), + .SPI_CLK ( SPI_SCK ), + .SPI_SS_IO ( CONF_DATA0 ), + .SPI_MISO ( SPI_DO ) , + .SPI_MOSI ( SPI_DI ), + .buttons ( buttons ), + .switches ( switches ), + .scandoubler_disable (scandoublerD ), + .ypbpr ( ypbpr ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .status ( status ) + ); + +wire dac_o; +assign AUDIO_L = dac_o; +assign AUDIO_R = dac_o; + +dac #( + .C_bits(8)) +dac( + .clk_i(clk_aud), + .res_n_i(1), + .dac_i(audio), + .dac_o(dac_o) + ); + +// Sinistar controls +reg sin_x; +reg sin_y; + +always @(posedge clk_sys) begin + if (m_right | m_right2) sin_x <= 0; + else if (m_left | m_left2) sin_x <= 1; + + if (m_up | m_up2) sin_y <= 0; + else if (m_down | m_down2) sin_y <= 1; +end + +// General controls +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_up3, m_down3, m_left3, m_right3, m_fire3A, m_fire3B, m_fire3C, m_fire3D, m_fire3E, m_fire3F; +wire m_up4, m_down4, m_left4, m_right4, m_fire4A, m_fire4B, m_fire4C, m_fire4D, m_fire4E, m_fire4F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clk_sys ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ), + .player3 ( {m_fire3F, m_fire3E, m_fire3D, m_fire3C, m_fire3B, m_fire3A, m_up3, m_down3, m_left3, m_right3} ), + .player4 ( {m_fire4F, m_fire4E, m_fire4D, m_fire4C, m_fire4B, m_fire4A, m_up4, m_down4, m_left4, m_right4} ) +); + +endmodule diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd new file mode 100644 index 00000000..016bd9a9 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/cpu68.vhd @@ -0,0 +1,3963 @@ +--===========================================================================-- +-- +-- S Y N T H E Z I A B L E CPU68 C O R E +-- +-- www.OpenCores.Org - December 2002 +-- This core adheres to the GNU public license +-- +-- File name : cpu68.vhd +-- +-- Purpose : Implements a 6800 compatible CPU core with some +-- additional instructions found in the 6801 +-- +-- Dependencies : ieee.Std_Logic_1164 +-- ieee.std_logic_unsigned +-- +-- Author : John E. Kent +-- +--===========================================================================---- +-- +-- Revision History: +-- +-- Date: Revision Author +-- 22 Sep 2002 0.1 John Kent +-- +-- 30 Oct 2002 0.2 John Kent +-- made NMI edge triggered +-- +-- 30 Oct 2002 0.3 John Kent +-- more corrections to NMI +-- added wai_wait_state to prevent stack overflow on wai. +-- +-- 1 Nov 2002 0.4 John Kent +-- removed WAI states and integrated WAI with the interrupt service routine +-- replace Data out (do) and Data in (di) register with a single Memory Data (md) reg. +-- Added Multiply instruction states. +-- run ALU and CC out of CPU module for timing measurements. +-- +-- 3 Nov 2002 0.5 John Kent +-- Memory Data Register was not loaded on Store instructions +-- SEV and CLV were not defined in the ALU +-- Overflow Flag on NEG was incorrect +-- +-- 16th Feb 2003 0.6 John Kent +-- Rearranged the execution cycle for dual operand instructions +-- so that occurs during the following fetch cycle. +-- This allows the reduction of one clock cycle from dual operand +-- instruction. Note that this also necessitated re-arranging the +-- program counter so that it is no longer incremented in the ALU. +-- The effective address has also been re-arranged to include a +-- separate added. The STD (store accd) now sets the condition codes. +-- +-- 28th Jun 2003 0.7 John Kent +-- Added Hold and Halt signals. Hold is used to steal cycles from the +-- CPU or add wait states. Halt puts the CPU in the inactive state +-- and is only honoured in the fetch cycle. Both signals are active high. +-- +-- 9th Jan 2004 0.8 John Kent +-- Clear instruction did an alu_ld8 rather than an alu_clr, so +-- the carry bit was not cleared correctly. +-- This error was picked up by Michael Hassenfratz. +-- + +library ieee; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity cpu68 is + port ( + clk: in std_logic; + rst: in std_logic; + rw: out std_logic; + vma: out std_logic; + address: out std_logic_vector(15 downto 0); + data_in: in std_logic_vector(7 downto 0); + data_out: out std_logic_vector(7 downto 0); + hold: in std_logic; + halt: in std_logic; + irq: in std_logic; + nmi: in std_logic; + test_alu: out std_logic_vector(15 downto 0); + test_cc: out std_logic_vector(7 downto 0) + ); +end; + +architecture CPU_ARCH of cpu68 is + + constant SBIT : integer := 7; + constant XBIT : integer := 6; + constant HBIT : integer := 5; + constant IBIT : integer := 4; + constant NBIT : integer := 3; + constant ZBIT : integer := 2; + constant VBIT : integer := 1; + constant CBIT : integer := 0; + + type state_type is (reset_state, fetch_state, decode_state, + extended_state, indexed_state, read8_state, read16_state, immediate16_state, + write8_state, write16_state, + execute_state, halt_state, error_state, + mul_state, mulea_state, muld_state, + mul0_state, mul1_state, mul2_state, mul3_state, + mul4_state, mul5_state, mul6_state, mul7_state, + jmp_state, jsr_state, jsr1_state, + branch_state, bsr_state, bsr1_state, + rts_hi_state, rts_lo_state, + int_pcl_state, int_pch_state, + int_ixl_state, int_ixh_state, + int_cc_state, int_acca_state, int_accb_state, + int_wai_state, int_mask_state, + rti_state, rti_cc_state, rti_acca_state, rti_accb_state, + rti_ixl_state, rti_ixh_state, + rti_pcl_state, rti_pch_state, + pula_state, psha_state, pulb_state, pshb_state, + pulx_lo_state, pulx_hi_state, pshx_lo_state, pshx_hi_state, + vect_lo_state, vect_hi_state ); + type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, push_ad, pull_ad, int_hi_ad, int_lo_ad ); + type dout_type is (md_lo_dout, md_hi_dout, acca_dout, accb_dout, ix_lo_dout, ix_hi_dout, cc_dout, pc_lo_dout, pc_hi_dout ); + type op_type is (reset_op, fetch_op, latch_op ); + type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca ); + type accb_type is (reset_accb, load_accb, pull_accb, latch_accb ); + type cc_type is (reset_cc, load_cc, pull_cc, latch_cc ); + type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix ); + type sp_type is (reset_sp, latch_sp, load_sp ); + type pc_type is (reset_pc, latch_pc, load_ea_pc, add_ea_pc, pull_lo_pc, pull_hi_pc, inc_pc ); + type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md ); + type ea_type is (reset_ea, latch_ea, add_ix_ea, load_accb_ea, inc_ea, fetch_first_ea, fetch_next_ea ); + type iv_type is (reset_iv, latch_iv, swi_iv, nmi_iv, irq_iv ); + type nmi_type is (reset_nmi, set_nmi, latch_nmi ); + type left_type is (acca_left, accb_left, accd_left, md_left, ix_left, sp_left ); + type right_type is (md_right, zero_right, plus_one_right, accb_right ); + type alu_type is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc, + alu_and, alu_ora, alu_eor, + alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com, + alu_inx, alu_dex, alu_cpx, + alu_lsr16, alu_lsl16, + alu_ror8, alu_rol8, + alu_asr8, alu_asl8, alu_lsr8, + alu_sei, alu_cli, alu_sec, alu_clc, alu_sev, alu_clv, alu_tpa, alu_tap, + alu_ld8, alu_st8, alu_ld16, alu_st16, alu_nop, alu_daa ); + + signal op_code: std_logic_vector(7 downto 0); + signal acca: std_logic_vector(7 downto 0); + signal accb: std_logic_vector(7 downto 0); + signal cc: std_logic_vector(7 downto 0); + signal cc_out: std_logic_vector(7 downto 0); + signal xreg: std_logic_vector(15 downto 0); + signal sp: std_logic_vector(15 downto 0); + signal ea: std_logic_vector(15 downto 0); + signal pc: std_logic_vector(15 downto 0); + signal md: std_logic_vector(15 downto 0); + signal left: std_logic_vector(15 downto 0); + signal right: std_logic_vector(15 downto 0); + signal out_alu: std_logic_vector(15 downto 0); + signal iv: std_logic_vector(1 downto 0); + signal nmi_req: std_logic; + signal nmi_ack: std_logic; + + signal state: state_type; + signal next_state: state_type; + signal pc_ctrl: pc_type; + signal ea_ctrl: ea_type; + signal op_ctrl: op_type; + signal md_ctrl: md_type; + signal acca_ctrl: acca_type; + signal accb_ctrl: accb_type; + signal ix_ctrl: ix_type; + signal cc_ctrl: cc_type; + signal sp_ctrl: sp_type; + signal iv_ctrl: iv_type; + signal left_ctrl: left_type; + signal right_ctrl: right_type; + signal alu_ctrl: alu_type; + signal addr_ctrl: addr_type; + signal dout_ctrl: dout_type; + signal nmi_ctrl: nmi_type; + + +begin + +---------------------------------- +-- +-- Address bus multiplexer +-- +---------------------------------- + +addr_mux: process( clk, addr_ctrl, pc, ea, sp, iv ) +begin + case addr_ctrl is + when idle_ad => + address <= "1111111111111111"; + vma <= '0'; + rw <= '1'; + when fetch_ad => + address <= pc; + vma <= '1'; + rw <= '1'; + when read_ad => + address <= ea; + vma <= '1'; + rw <= '1'; + when write_ad => + address <= ea; + vma <= '1'; + rw <= '0'; + when push_ad => + address <= sp; + vma <= '1'; + rw <= '0'; + when pull_ad => + address <= sp; + vma <= '1'; + rw <= '1'; + when int_hi_ad => + address <= "1111111111111" & iv & "0"; + vma <= '1'; + rw <= '1'; + when int_lo_ad => + address <= "1111111111111" & iv & "1"; + vma <= '1'; + rw <= '1'; + when others => + address <= "1111111111111111"; + vma <= '0'; + rw <= '1'; + end case; +end process; + +-------------------------------- +-- +-- Data Bus output +-- +-------------------------------- +dout_mux : process( clk, dout_ctrl, md, acca, accb, xreg, pc, cc ) +begin + case dout_ctrl is + when md_hi_dout => -- alu output + data_out <= md(15 downto 8); + when md_lo_dout => + data_out <= md(7 downto 0); + when acca_dout => -- accumulator a + data_out <= acca; + when accb_dout => -- accumulator b + data_out <= accb; + when ix_lo_dout => -- index reg + data_out <= xreg(7 downto 0); + when ix_hi_dout => -- index reg + data_out <= xreg(15 downto 8); + when cc_dout => -- condition codes + data_out <= cc; + when pc_lo_dout => -- low order pc + data_out <= pc(7 downto 0); + when pc_hi_dout => -- high order pc + data_out <= pc(15 downto 8); + when others => + data_out <= "00000000"; + end case; +end process; + + +---------------------------------- +-- +-- Program Counter Control +-- +---------------------------------- + +pc_mux: process( clk, pc_ctrl, pc, out_alu, data_in, ea, hold ) +variable tempof : std_logic_vector(15 downto 0); +variable temppc : std_logic_vector(15 downto 0); +begin + case pc_ctrl is + when add_ea_pc => + if ea(7) = '0' then + tempof := "00000000" & ea(7 downto 0); + else + tempof := "11111111" & ea(7 downto 0); + end if; + when inc_pc => + tempof := "0000000000000001"; + when others => + tempof := "0000000000000000"; + end case; + + case pc_ctrl is + when reset_pc => + temppc := "1111111111111110"; + when load_ea_pc => + temppc := ea; + when pull_lo_pc => + temppc(7 downto 0) := data_in; + temppc(15 downto 8) := pc(15 downto 8); + when pull_hi_pc => + temppc(7 downto 0) := pc(7 downto 0); + temppc(15 downto 8) := data_in; + when others => + temppc := pc; + end case; + + if clk'event and clk = '0' then + if hold = '1' then + pc <= pc; + else + pc <= temppc + tempof; + end if; + end if; +end process; + +---------------------------------- +-- +-- Effective Address Control +-- +---------------------------------- + +ea_mux: process( clk, ea_ctrl, ea, out_alu, data_in, accb, xreg, hold ) +variable tempind : std_logic_vector(15 downto 0); +variable tempea : std_logic_vector(15 downto 0); +begin + case ea_ctrl is + when add_ix_ea => + tempind := "00000000" & ea(7 downto 0); + when inc_ea => + tempind := "0000000000000001"; + when others => + tempind := "0000000000000000"; + end case; + + case ea_ctrl is + when reset_ea => + tempea := "0000000000000000"; + when load_accb_ea => + tempea := "00000000" & accb(7 downto 0); + when add_ix_ea => + tempea := xreg; + when fetch_first_ea => + tempea(7 downto 0) := data_in; + tempea(15 downto 8) := "00000000"; + when fetch_next_ea => + tempea(7 downto 0) := data_in; + tempea(15 downto 8) := ea(7 downto 0); + when others => + tempea := ea; + end case; + + if clk'event and clk = '0' then + if hold = '1' then + ea <= ea; + else + ea <= tempea + tempind; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator A +-- +-------------------------------- +acca_mux : process( clk, acca_ctrl, out_alu, acca, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + acca <= acca; + else + case acca_ctrl is + when reset_acca => + acca <= "00000000"; + when load_acca => + acca <= out_alu(7 downto 0); + when load_hi_acca => + acca <= out_alu(15 downto 8); + when pull_acca => + acca <= data_in; + when others => +-- when latch_acca => + acca <= acca; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator B +-- +-------------------------------- +accb_mux : process( clk, accb_ctrl, out_alu, accb, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + accb <= accb; + else + case accb_ctrl is + when reset_accb => + accb <= "00000000"; + when load_accb => + accb <= out_alu(7 downto 0); + when pull_accb => + accb <= data_in; + when others => +-- when latch_accb => + accb <= accb; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- X Index register +-- +-------------------------------- +ix_mux : process( clk, ix_ctrl, out_alu, xreg, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + xreg <= xreg; + else + case ix_ctrl is + when reset_ix => + xreg <= "0000000000000000"; + when load_ix => + xreg <= out_alu(15 downto 0); + when pull_hi_ix => + xreg(15 downto 8) <= data_in; + when pull_lo_ix => + xreg(7 downto 0) <= data_in; + when others => +-- when latch_ix => + xreg <= xreg; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- stack pointer +-- +-------------------------------- +sp_mux : process( clk, sp_ctrl, out_alu, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + sp <= sp; + else + case sp_ctrl is + when reset_sp => + sp <= "0000000000000000"; + when load_sp => + sp <= out_alu(15 downto 0); + when others => +-- when latch_sp => + sp <= sp; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Memory Data +-- +-------------------------------- +md_mux : process( clk, md_ctrl, out_alu, data_in, md, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + md <= md; + else + case md_ctrl is + when reset_md => + md <= "0000000000000000"; + when load_md => + md <= out_alu(15 downto 0); + when fetch_first_md => + md(15 downto 8) <= "00000000"; + md(7 downto 0) <= data_in; + when fetch_next_md => + md(15 downto 8) <= md(7 downto 0); + md(7 downto 0) <= data_in; + when shiftl_md => + md(15 downto 1) <= md(14 downto 0); + md(0) <= '0'; + when others => +-- when latch_md => + md <= md; + end case; + end if; + end if; +end process; + + +---------------------------------- +-- +-- Condition Codes +-- +---------------------------------- + +cc_mux: process( clk, cc_ctrl, cc_out, cc, data_in, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + cc <= cc; + else + case cc_ctrl is + when reset_cc => + cc <= "11000000"; + when load_cc => + cc <= cc_out; + when pull_cc => + cc <= data_in; + when others => +-- when latch_cc => + cc <= cc; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- interrupt vector +-- +---------------------------------- + +iv_mux: process( clk, iv_ctrl, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + iv <= iv; + else + case iv_ctrl is + when reset_iv => + iv <= "11"; + when nmi_iv => + iv <= "10"; + when swi_iv => + iv <= "01"; + when irq_iv => + iv <= "00"; + when others => + iv <= iv; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- op code fetch +-- +---------------------------------- + +op_fetch: process( clk, data_in, op_ctrl, op_code, hold ) +begin + if clk'event and clk = '0' then + if hold = '1' then + op_code <= op_code; + else + case op_ctrl is + when reset_op => + op_code <= "00000001"; -- nop + when fetch_op => + op_code <= data_in; + when others => +-- when latch_op => + op_code <= op_code; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- Left Mux +-- +---------------------------------- + +left_mux: process( left_ctrl, acca, accb, xreg, sp, pc, ea, md ) +begin + case left_ctrl is + when acca_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= acca; + when accb_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= accb; + when accd_left => + left(15 downto 8) <= acca; + left(7 downto 0) <= accb; + when ix_left => + left <= xreg; + when sp_left => + left <= sp; + when others => +-- when md_left => + left <= md; + end case; +end process; +---------------------------------- +-- +-- Right Mux +-- +---------------------------------- + +right_mux: process( right_ctrl, data_in, md, accb, ea ) +begin + case right_ctrl is + when zero_right => + right <= "0000000000000000"; + when plus_one_right => + right <= "0000000000000001"; + when accb_right => + right <= "00000000" & accb; + when others => +-- when md_right => + right <= md; + end case; +end process; + +---------------------------------- +-- +-- Arithmetic Logic Unit +-- +---------------------------------- + +mux_alu: process( alu_ctrl, cc, left, right, out_alu, cc_out ) +variable valid_lo, valid_hi : boolean; +variable carry_in : std_logic; +variable daa_reg : std_logic_vector(7 downto 0); +begin + + case alu_ctrl is + when alu_adc | alu_sbc | + alu_rol8 | alu_ror8 => + carry_in := cc(CBIT); + when others => + carry_in := '0'; + end case; + + valid_lo := left(3 downto 0) <= 9; + valid_hi := left(7 downto 4) <= 9; + + if (cc(CBIT) = '0') then + if( cc(HBIT) = '1' ) then + if valid_hi then + daa_reg := "00000110"; + else + daa_reg := "01100110"; + end if; + else + if valid_lo then + if valid_hi then + daa_reg := "00000000"; + else + daa_reg := "01100000"; + end if; + else + if( left(7 downto 4) <= 8 ) then + daa_reg := "00000110"; + else + daa_reg := "01100110"; + end if; + end if; + end if; + else + if ( cc(HBIT) = '1' )then + daa_reg := "01100110"; + else + if valid_lo then + daa_reg := "01100000"; + else + daa_reg := "01100110"; + end if; + end if; + end if; + + case alu_ctrl is + when alu_add8 | alu_inc | + alu_add16 | alu_inx | + alu_adc => + out_alu <= left + right + ("000000000000000" & carry_in); + when alu_sub8 | alu_dec | + alu_sub16 | alu_dex | + alu_sbc | alu_cpx => + out_alu <= left - right - ("000000000000000" & carry_in); + when alu_and => + out_alu <= left and right; -- and/bit + when alu_ora => + out_alu <= left or right; -- or + when alu_eor => + out_alu <= left xor right; -- eor/xor + when alu_lsl16 | alu_asl8 | alu_rol8 => + out_alu <= left(14 downto 0) & carry_in; -- rol8/asl8/lsl16 + when alu_lsr16 | alu_lsr8 => + out_alu <= carry_in & left(15 downto 1); -- lsr + when alu_ror8 => + out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror + when alu_asr8 => + out_alu <= "00000000" & left(7) & left(7 downto 1); -- asr + when alu_neg => + out_alu <= right - left; -- neg (right=0) + when alu_com => + out_alu <= not left; + when alu_clr | alu_ld8 | alu_ld16 => + out_alu <= right; -- clr, ld + when alu_st8 | alu_st16 => + out_alu <= left; + when alu_daa => + out_alu <= left + ("00000000" & daa_reg); + when alu_tpa => + out_alu <= "00000000" & cc; + when others => + out_alu <= left; -- nop + end case; + + -- + -- carry bit + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(CBIT) <= (left(7) and right(7)) or + (left(7) and not out_alu(7)) or + (right(7) and not out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(CBIT) <= ((not left(7)) and right(7)) or + ((not left(7)) and out_alu(7)) or + (right(7) and out_alu(7)); + when alu_add16 => + cc_out(CBIT) <= (left(15) and right(15)) or + (left(15) and not out_alu(15)) or + (right(15) and not out_alu(15)); + when alu_sub16 => + cc_out(CBIT) <= ((not left(15)) and right(15)) or + ((not left(15)) and out_alu(15)) or + (right(15) and out_alu(15)); + when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 => + cc_out(CBIT) <= left(0); + when alu_rol8 | alu_asl8 => + cc_out(CBIT) <= left(7); + when alu_lsl16 => + cc_out(CBIT) <= left(15); + when alu_com => + cc_out(CBIT) <= '1'; + when alu_neg | alu_clr => + cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0); + when alu_daa => + if ( daa_reg(7 downto 4) = "0110" ) then + cc_out(CBIT) <= '1'; + else + cc_out(CBIT) <= '0'; + end if; + when alu_sec => + cc_out(CBIT) <= '1'; + when alu_clc => + cc_out(CBIT) <= '0'; + when alu_tap => + cc_out(CBIT) <= left(CBIT); + when others => -- carry is not affected by cpx + cc_out(CBIT) <= cc(CBIT); + end case; + -- + -- Zero flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_inc | alu_dec | + alu_neg | alu_com | alu_clr | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_ld8 | alu_st8 => + cc_out(ZBIT) <= not( out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_add16 | alu_sub16 | + alu_lsl16 | alu_lsr16 | + alu_inx | alu_dex | + alu_ld16 | alu_st16 | alu_cpx => + cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or + out_alu(11) or out_alu(10) or out_alu(9) or out_alu(8) or + out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_tap => + cc_out(ZBIT) <= left(ZBIT); + when others => + cc_out(ZBIT) <= cc(ZBIT); + end case; + + -- + -- negative flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_inc | alu_dec | alu_neg | alu_com | alu_clr | + alu_ld8 | alu_st8 => + cc_out(NBIT) <= out_alu(7); + when alu_add16 | alu_sub16 | + alu_lsl16 | alu_lsr16 | + alu_ld16 | alu_st16 | alu_cpx => + cc_out(NBIT) <= out_alu(15); + when alu_tap => + cc_out(NBIT) <= left(NBIT); + when others => + cc_out(NBIT) <= cc(NBIT); + end case; + + -- + -- Interrupt mask flag + -- + case alu_ctrl is + when alu_sei => + cc_out(IBIT) <= '1'; -- set interrupt mask + when alu_cli => + cc_out(IBIT) <= '0'; -- clear interrupt mask + when alu_tap => + cc_out(IBIT) <= left(IBIT); + when others => + cc_out(IBIT) <= cc(IBIT); -- interrupt mask + end case; + + -- + -- Half Carry flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(HBIT) <= (left(3) and right(3)) or + (right(3) and not out_alu(3)) or + (left(3) and not out_alu(3)); + when alu_tap => + cc_out(HBIT) <= left(HBIT); + when others => + cc_out(HBIT) <= cc(HBIT); + end case; + + -- + -- Overflow flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(VBIT) <= (left(7) and right(7) and (not out_alu(7))) or + ((not left(7)) and (not right(7)) and out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(VBIT) <= (left(7) and (not right(7)) and (not out_alu(7))) or + ((not left(7)) and right(7) and out_alu(7)); + when alu_add16 => + cc_out(VBIT) <= (left(15) and right(15) and (not out_alu(15))) or + ((not left(15)) and (not right(15)) and out_alu(15)); + when alu_sub16 | alu_cpx => + cc_out(VBIT) <= (left(15) and (not right(15)) and (not out_alu(15))) or + ((not left(15)) and right(15) and out_alu(15)); + when alu_inc => + cc_out(VBIT) <= ((not left(7)) and left(6) and left(5) and left(4) and + left(3) and left(2) and left(1) and left(0)); + when alu_dec | alu_neg => + cc_out(VBIT) <= (left(7) and (not left(6)) and (not left(5)) and (not left(4)) and + (not left(3)) and (not left(2)) and (not left(1)) and (not left(0))); + when alu_asr8 => + cc_out(VBIT) <= left(0) xor left(7); + when alu_lsr8 | alu_lsr16 => + cc_out(VBIT) <= left(0); + when alu_ror8 => + cc_out(VBIT) <= left(0) xor cc(CBIT); + when alu_lsl16 => + cc_out(VBIT) <= left(15) xor left(14); + when alu_rol8 | alu_asl8 => + cc_out(VBIT) <= left(7) xor left(6); + when alu_tap => + cc_out(VBIT) <= left(VBIT); + when alu_and | alu_ora | alu_eor | alu_com | + alu_st8 | alu_st16 | alu_ld8 | alu_ld16 | + alu_clv => + cc_out(VBIT) <= '0'; + when alu_sev => + cc_out(VBIT) <= '1'; + when others => + cc_out(VBIT) <= cc(VBIT); + end case; + + case alu_ctrl is + when alu_tap => + cc_out(XBIT) <= cc(XBIT) and left(XBIT); + cc_out(SBIT) <= left(SBIT); + when others => + cc_out(XBIT) <= cc(XBIT) and left(XBIT); + cc_out(SBIT) <= cc(SBIT); + end case; + + test_alu <= out_alu; + test_cc <= cc_out; +end process; + +------------------------------------ +-- +-- Detect Edge of NMI interrupt +-- +------------------------------------ + +nmi_handler : process( clk, rst, nmi, nmi_ack ) +begin + if clk'event and clk='0' then + if hold = '1' then + nmi_req <= nmi_req; + else + if rst='1' then + nmi_req <= '0'; + else + if (nmi='1') and (nmi_ack='0') then + nmi_req <= '1'; + else + if (nmi='0') and (nmi_ack='1') then + nmi_req <= '0'; + else + nmi_req <= nmi_req; + end if; + end if; + end if; + end if; + end if; +end process; + +------------------------------------ +-- +-- Nmi mux +-- +------------------------------------ + +nmi_mux: process( clk, nmi_ctrl, nmi_ack, hold ) +begin + if clk'event and clk='0' then + if hold = '1' then + nmi_ack <= nmi_ack; + else + case nmi_ctrl is + when set_nmi => + nmi_ack <= '1'; + when reset_nmi => + nmi_ack <= '0'; + when others => +-- when latch_nmi => + nmi_ack <= nmi_ack; + end case; + end if; + end if; +end process; + +------------------------------------ +-- +-- state sequencer +-- +------------------------------------ +process( state, op_code, cc, ea, irq, nmi_req, nmi_ack, hold, halt ) + begin + case state is + when reset_state => -- released from reset + -- reset the registers + op_ctrl <= reset_op; + acca_ctrl <= reset_acca; + accb_ctrl <= reset_accb; + ix_ctrl <= reset_ix; + sp_ctrl <= reset_sp; + pc_ctrl <= reset_pc; + ea_ctrl <= reset_ea; + md_ctrl <= reset_md; + iv_ctrl <= reset_iv; + nmi_ctrl <= reset_nmi; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= reset_cc; + -- idle the bus + dout_ctrl <= md_lo_dout; + addr_ctrl <= idle_ad; + next_state <= vect_hi_state; + + -- + -- Jump via interrupt vector + -- iv holds interrupt type + -- fetch PC hi from vector location + -- + when vect_hi_state => + -- default the registers + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + ea_ctrl <= latch_ea; + iv_ctrl <= latch_iv; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- fetch pc low interrupt vector + pc_ctrl <= pull_hi_pc; + addr_ctrl <= int_hi_ad; + dout_ctrl <= pc_hi_dout; + next_state <= vect_lo_state; + -- + -- jump via interrupt vector + -- iv holds vector type + -- fetch PC lo from vector location + -- + when vect_lo_state => + -- default the registers + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + ea_ctrl <= latch_ea; + iv_ctrl <= latch_iv; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- fetch the vector low byte + pc_ctrl <= pull_lo_pc; + addr_ctrl <= int_lo_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + -- + -- Here to fetch an instruction + -- PC points to opcode + -- Should service interrupt requests at this point + -- either from the timer + -- or from the external input. + -- + when fetch_state => + case op_code(7 downto 4) is + when "0000" | + "0001" | + "0010" | -- branch conditional + "0011" | + "0100" | -- acca single op + "0101" | -- accb single op + "0110" | -- indexed single op + "0111" => -- extended single op + -- idle ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + + when "1000" | -- acca immediate + "1001" | -- acca direct + "1010" | -- acca indexed + "1011" => -- acca extended + case op_code(3 downto 0) is + when "0000" => -- suba + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0001" => -- cmpa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0010" => -- sbca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0011" => -- subd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0100" => -- anda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0101" => -- bita + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0110" => -- ldaa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1000" => -- eora + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1001" => -- adca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1010" => -- oraa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1011" => -- adda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1100" => -- cpx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_cpx; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1101" => -- bsr / jsr + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1110" => -- lds + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when others => + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + when "1100" | -- accb immediate + "1101" | -- accb direct + "1110" | -- accb indexed + "1111" => -- accb extended + case op_code(3 downto 0) is + when "0000" => -- subb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0001" => -- cmpb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0010" => -- sbcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0011" => -- addd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0100" => -- andb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0101" => -- bitb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0110" => -- ldab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "0111" => -- stab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1000" => -- eorb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1001" => -- adcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1010" => -- orab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1011" => -- addb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1100" => -- ldd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1101" => -- std + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when "1110" => -- ldx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + when "1111" => -- stx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + when others => + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + when others => + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + end case; + md_ctrl <= latch_md; + -- fetch the op code + op_ctrl <= fetch_op; + ea_ctrl <= reset_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + iv_ctrl <= latch_iv; + if halt = '1' then + pc_ctrl <= latch_pc; + nmi_ctrl <= latch_nmi; + next_state <= halt_state; + -- service non maskable interrupts + elsif (nmi_req = '1') and (nmi_ack = '0') then + pc_ctrl <= latch_pc; + nmi_ctrl <= set_nmi; + next_state <= int_pcl_state; + -- service maskable interrupts + else + -- + -- nmi request is not cleared until nmi input goes low + -- + if(nmi_req = '0') and (nmi_ack='1') then + nmi_ctrl <= reset_nmi; + else + nmi_ctrl <= latch_nmi; + end if; + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + pc_ctrl <= latch_pc; + next_state <= int_pcl_state; + else + -- Advance the PC to fetch next instruction byte + pc_ctrl <= inc_pc; + next_state <= decode_state; + end if; + end if; + -- + -- Here to decode instruction + -- and fetch next byte of intruction + -- whether it be necessary or not + -- + when decode_state => + -- fetch first byte of address or immediate data + ea_ctrl <= fetch_first_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + iv_ctrl <= latch_iv; + case op_code(7 downto 4) is + when "0000" => + md_ctrl <= fetch_first_md; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + case op_code(3 downto 0) is + when "0001" => -- nop + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "0100" => -- lsrd + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + when "0101" => -- lsld + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_lsl16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + ix_ctrl <= latch_ix; + when "0110" => -- tap + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_tap; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "0111" => -- tpa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_tpa; + cc_ctrl <= latch_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1000" => -- inx + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inx; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + when "1001" => -- dex + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dex; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= load_ix; + when "1010" => -- clv + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_clv; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1011" => -- sev + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sev; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1100" => -- clc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_clc; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1101" => -- sec + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sec; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1110" => -- cli + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_cli; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when "1111" => -- sei + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sei; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + end case; + next_state <= fetch_state; + -- acca / accb inherent instructions + when "0001" => + md_ctrl <= fetch_first_md; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + left_ctrl <= acca_left; + right_ctrl <= accb_right; + case op_code(3 downto 0) is + when "0000" => -- sba + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "0001" => -- cba + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + when "0110" => -- tab + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= load_accb; + when "0111" => -- tba + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "1001" => -- daa + alu_ctrl <= alu_daa; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when "1011" => -- aba + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + accb_ctrl <= latch_accb; + when others => + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end case; + next_state <= fetch_state; + when "0010" => -- branch conditional + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0000" => -- bra + next_state <= branch_state; + when "0001" => -- brn + next_state <= fetch_state; + when "0010" => -- bhi + if (cc(CBIT) or cc(ZBIT)) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0011" => -- bls + if (cc(CBIT) or cc(ZBIT)) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0100" => -- bcc/bhs + if cc(CBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0101" => -- bcs/blo + if cc(CBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0110" => -- bne + if cc(ZBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "0111" => -- beq + if cc(ZBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1000" => -- bvc + if cc(VBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1001" => -- bvs + if cc(VBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1010" => -- bpl + if cc(NBIT) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1011" => -- bmi + if cc(NBIT) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1100" => -- bge + if (cc(NBIT) xor cc(VBIT)) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1101" => -- blt + if (cc(NBIT) xor cc(VBIT)) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1110" => -- bgt + if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '0' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when "1111" => -- ble + if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '1' then + next_state <= branch_state; + else + next_state <= fetch_state; + end if; + when others => + next_state <= fetch_state; + end case; + -- + -- Single byte stack operators + -- Do not advance PC + -- + when "0011" => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + case op_code(3 downto 0) is + when "0000" => -- tsx + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + when "0001" => -- ins + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0010" => -- pula + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pula_state; + when "0011" => -- pulb + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pulb_state; + when "0100" => -- des + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0101" => -- txs + left_ctrl <= ix_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= fetch_state; + when "0110" => -- psha + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= psha_state; + when "0111" => -- pshb + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= pshb_state; + when "1000" => -- pulx + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= pulx_hi_state; + when "1001" => -- rts + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= rts_hi_state; + when "1010" => -- abx + left_ctrl <= ix_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= load_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + when "1011" => -- rti + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= load_sp; + next_state <= rti_cc_state; + when "1100" => -- pshx + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= pshx_lo_state; + when "1101" => -- mul + left_ctrl <= acca_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= mul_state; + when "1110" => -- wai + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= int_pcl_state; + when "1111" => -- swi + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= int_pcl_state; + when others => + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + next_state <= fetch_state; + end case; + -- + -- Accumulator A Single operand + -- source = Acc A dest = Acc A + -- Do not advance PC + -- + when "0100" => -- acca single op + md_ctrl <= fetch_first_md; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= acca_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + acca_ctrl <= latch_acca; + cc_ctrl <= load_cc; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + end case; + next_state <= fetch_state; + -- + -- single operand acc b + -- Do not advance PC + -- + when "0101" => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + pc_ctrl <= latch_pc; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + left_ctrl <= accb_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + accb_ctrl <= latch_accb; + cc_ctrl <= load_cc; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + end case; + next_state <= fetch_state; + -- + -- Single operand indexed + -- Two byte instruction so advance PC + -- EA should hold index offset + -- + when "0110" => -- indexed single op + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + -- + -- Single operand extended addressing + -- three byte instruction so advance the PC + -- Low order EA holds high order address + -- + when "0111" => -- extended single op + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when "1000" => -- acca immediate + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0011" | -- subdd # + "1100" | -- cpx # + "1110" => -- lds # + next_state <= immediate16_state; + when "1101" => -- bsr + next_state <= bsr_state; + when others => + next_state <= fetch_state; + end case; + + when "1001" => -- acca direct + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0111" => -- staa direct + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1111" => -- sts direct + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1101" => -- jsr direct + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= jsr_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= read8_state; + end case; + + when "1010" => -- acca indexed + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + + when "1011" => -- acca extended + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when "1100" => -- accb immediate + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0011" | -- addd # + "1100" | -- ldd # + "1110" => -- ldx # + next_state <= immediate16_state; + when others => + next_state <= fetch_state; + end case; + + when "1101" => -- accb direct + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + pc_ctrl <= inc_pc; + case op_code(3 downto 0) is + when "0111" => -- stab direct + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std direct + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx direct + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + next_state <= read8_state; + end case; + + when "1110" => -- accb indexed + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= indexed_state; + + when "1111" => -- accb extended + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- increment the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + next_state <= extended_state; + + when others => + md_ctrl <= fetch_first_md; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + -- idle the pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= latch_pc; + next_state <= fetch_state; + end case; + + when immediate16_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + op_ctrl <= latch_op; + iv_ctrl <= latch_iv; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment pc + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= inc_pc; + -- fetch next immediate byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + -- + -- ea holds 8 bit index offet + -- calculate the effective memory address + -- using the alu + -- + when indexed_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- calculate effective address from index reg + -- index offest is not sign extended + ea_ctrl <= add_ix_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + -- work out next state + case op_code(7 downto 4) is + when "0110" => -- single op indexed + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + case op_code(3 downto 0) is + when "1011" => -- undefined + next_state <= fetch_state; + when "1110" => -- jmp + next_state <= jmp_state; + when others => + next_state <= read8_state; + end case; + when "1010" => -- acca indexed + case op_code(3 downto 0) is + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- jsr + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= jsr_state; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when "1110" => -- accb indexed + case op_code(3 downto 0) is + when "0111" => -- stab direct + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std direct + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx direct + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when others => + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + next_state <= fetch_state; + end case; + -- + -- ea holds the low byte of the absolute address + -- Move ea low byte into ea high byte + -- load new ea low byte to for absolute 16 bit address + -- advance the program counter + -- + when extended_state => -- fetch ea low byte + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- increment pc + pc_ctrl <= inc_pc; + -- fetch next effective address bytes + ea_ctrl <= fetch_next_ea; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + -- work out the next state + case op_code(7 downto 4) is + when "0111" => -- single op extended + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + case op_code(3 downto 0) is + when "1011" => -- undefined + next_state <= fetch_state; + when "1110" => -- jmp + next_state <= jmp_state; + when others => + next_state <= read8_state; + end case; + when "1011" => -- acca extended + case op_code(3 downto 0) is + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- jsr + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= jsr_state; + when "1111" => -- sts + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when "1111" => -- accb extended + case op_code(3 downto 0) is + when "0111" => -- stab + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- std + left_ctrl <= accd_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when "1111" => -- stx + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= read8_state; + end case; + when others => + md_ctrl <= latch_md; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + next_state <= fetch_state; + end case; + -- + -- here if ea holds low byte (direct page) + -- can enter here from extended addressing + -- read memory location + -- note that reads may be 8 or 16 bits + -- + when read8_state => -- read data + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + case op_code(7 downto 4) is + when "0110" | "0111" => -- single operand + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= execute_state; + + when "1001" | "1010" | "1011" => -- acca + case op_code(3 downto 0) is + when "0011" | -- subd + "1110" | -- lds + "1100" => -- cpx + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + -- increment the effective address in case of 16 bit load + ea_ctrl <= inc_ea; + next_state <= read16_state; +-- when "0111" => -- staa +-- left_ctrl <= acca_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st8; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write8_state; +-- when "1101" => -- jsr +-- left_ctrl <= acca_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_nop; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= latch_md; +-- ea_ctrl <= latch_ea; +-- next_state <= jsr_state; +-- when "1111" => -- sts +-- left_ctrl <= sp_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= fetch_state; + end case; + + when "1101" | "1110" | "1111" => -- accb + case op_code(3 downto 0) is + when "0011" | -- addd + "1100" | -- ldd + "1110" => -- ldx + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + -- increment the effective address in case of 16 bit load + ea_ctrl <= inc_ea; + next_state <= read16_state; +-- when "0111" => -- stab +-- left_ctrl <= accb_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st8; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write8_state; +-- when "1101" => -- std +-- left_ctrl <= accd_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; +-- when "1111" => -- stx +-- left_ctrl <= ix_left; +-- right_ctrl <= zero_right; +-- alu_ctrl <= alu_st16; +-- cc_ctrl <= latch_cc; +-- md_ctrl <= load_md; +-- ea_ctrl <= latch_ea; +-- next_state <= write16_state; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= execute_state; + end case; + when others => + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= fetch_first_md; + ea_ctrl <= latch_ea; + next_state <= fetch_state; + end case; + + when read16_state => -- read second data byte from ea + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle the effective address + ea_ctrl <= latch_ea; + -- read the low byte of the 16 bit data + md_ctrl <= fetch_next_md; + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + -- + -- 16 bit Write state + -- write high byte of ALU output. + -- EA hold address of memory to write to + -- Advance the effective address in ALU + -- + when write16_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + -- increment the effective address + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + ea_ctrl <= inc_ea; + -- write the ALU hi byte to ea + addr_ctrl <= write_ad; + dout_ctrl <= md_hi_dout; + next_state <= write8_state; + -- + -- 8 bit write + -- Write low 8 bits of ALU output + -- + when write8_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- write ALU low byte output + addr_ctrl <= write_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when jmp_state => + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- load PC with effective address + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= load_ea_pc; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when jsr_state => -- JSR + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= jsr1_state; + + when jsr1_state => -- JSR + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= jmp_state; + + when branch_state => -- Bcc + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- calculate signed branch + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + pc_ctrl <= add_ea_pc; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when bsr_state => -- BSR + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= bsr1_state; + + when bsr1_state => -- BSR + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= branch_state; + + when rts_hi_state => -- RTS + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment the sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_hi_dout; + next_state <= rts_lo_state; + + when rts_lo_state => -- RTS1 + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle the ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- read pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + when mul_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- move acca to md + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + cc_ctrl <= latch_cc; + md_ctrl <= load_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mulea_state; + + when mulea_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + md_ctrl <= latch_md; + -- idle ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- move accb to ea + ea_ctrl <= load_accb_ea; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= muld_state; + + when muld_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + md_ctrl <= latch_md; + -- clear accd + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= latch_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul0_state; + + when mul0_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 0 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(0) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul1_state; + + when mul1_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 1 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(1) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul2_state; + + when mul2_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 2 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(2) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul3_state; + + when mul3_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 3 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(3) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul4_state; + + when mul4_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 4 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(4) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul5_state; + + when mul5_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 5 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(5) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul6_state; + + when mul6_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 6 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(6) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= mul7_state; + + when mul7_state => + -- default + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- if bit 7 of ea set, add accd to md + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + if ea(7) = '1' then + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + else + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + end if; + md_ctrl <= shiftl_md; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + + when execute_state => -- execute single operand instruction + -- default + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + case op_code(7 downto 4) is + when "0110" | -- indexed single op + "0111" => -- extended single op + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + iv_ctrl <= latch_iv; + ea_ctrl <= latch_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + left_ctrl <= md_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1010" => -- dec + right_ctrl <= plus_one_right; + alu_ctrl <= alu_dec; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1100" => -- inc + right_ctrl <= plus_one_right; + alu_ctrl <= alu_inc; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1110" => -- jmp + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= write8_state; + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + md_ctrl <= latch_md; + next_state <= fetch_state; + end case; + + when others => + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + ea_ctrl <= latch_ea; + -- idle the bus + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= fetch_state; + end case; + + when psha_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write acca + addr_ctrl <= push_ad; + dout_ctrl <= acca_dout; + next_state <= fetch_state; + + when pula_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pull_ad; + dout_ctrl <= acca_dout; + next_state <= fetch_state; + + when pshb_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= push_ad; + dout_ctrl <= accb_dout; + next_state <= fetch_state; + + when pulb_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pull_ad; + dout_ctrl <= accb_dout; + next_state <= fetch_state; + + when pshx_lo_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= push_ad; + dout_ctrl <= ix_lo_dout; + next_state <= pshx_hi_state; + + when pshx_hi_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= push_ad; + dout_ctrl <= ix_hi_dout; + next_state <= fetch_state; + + when pulx_hi_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- pull ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_hi_dout; + next_state <= pulx_lo_state; + + when pulx_lo_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_lo_dout; + next_state <= fetch_state; + + -- + -- return from interrupt + -- enter here from bogus interrupts + -- + when rti_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- idle address bus + cc_ctrl <= latch_cc; + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + next_state <= rti_cc_state; + + when rti_cc_state => + -- default registers + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read cc + cc_ctrl <= pull_cc; + addr_ctrl <= pull_ad; + dout_ctrl <= cc_dout; + next_state <= rti_accb_state; + + when rti_accb_state => + -- default registers + acca_ctrl <= latch_acca; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pull_ad; + dout_ctrl <= accb_dout; + next_state <= rti_acca_state; + + when rti_acca_state => + -- default registers + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pull_ad; + dout_ctrl <= acca_dout; + next_state <= rti_ixh_state; + + when rti_ixh_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_hi_dout; + next_state <= rti_ixl_state; + + when rti_ixl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pull_ad; + dout_ctrl <= ix_lo_dout; + next_state <= rti_pch_state; + + when rti_pch_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_add16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- pull pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_hi_dout; + next_state <= rti_pcl_state; + + when rti_pcl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- idle sp + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + -- pull pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pull_ad; + dout_ctrl <= pc_lo_dout; + next_state <= fetch_state; + + -- + -- here on interrupt + -- iv register hold interrupt type + -- + when int_pcl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= push_ad; + dout_ctrl <= pc_lo_dout; + next_state <= int_pch_state; + + when int_pch_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= push_ad; + dout_ctrl <= pc_hi_dout; + next_state <= int_ixl_state; + + when int_ixl_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= push_ad; + dout_ctrl <= ix_lo_dout; + next_state <= int_ixh_state; + + when int_ixh_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= push_ad; + dout_ctrl <= ix_hi_dout; + next_state <= int_acca_state; + + when int_acca_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write acca + addr_ctrl <= push_ad; + dout_ctrl <= acca_dout; + next_state <= int_accb_state; + + + when int_accb_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= push_ad; + dout_ctrl <= accb_dout; + next_state <= int_cc_state; + + when int_cc_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= latch_cc; + sp_ctrl <= load_sp; + -- write cc + addr_ctrl <= push_ad; + dout_ctrl <= cc_dout; + nmi_ctrl <= latch_nmi; + -- + -- nmi is edge triggered + -- nmi_req is cleared when nmi goes low. + -- + if nmi_req = '1' then + iv_ctrl <= nmi_iv; + next_state <= vect_hi_state; + else + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + iv_ctrl <= irq_iv; + next_state <= int_mask_state; + else + case op_code is + when "00111110" => -- WAI (wait for interrupt) + iv_ctrl <= latch_iv; + next_state <= int_wai_state; + when "00111111" => -- SWI (Software interrupt) + iv_ctrl <= swi_iv; + next_state <= vect_hi_state; + when others => -- bogus interrupt (return) + iv_ctrl <= latch_iv; + next_state <= rti_state; + end case; + end if; + end if; + + when int_wai_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + op_ctrl <= latch_op; + ea_ctrl <= latch_ea; + -- enable interrupts + left_ctrl <= sp_left; + right_ctrl <= plus_one_right; + alu_ctrl <= alu_cli; + cc_ctrl <= load_cc; + sp_ctrl <= latch_sp; + -- idle bus + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + if (nmi_req = '1') and (nmi_ack='0') then + iv_ctrl <= nmi_iv; + nmi_ctrl <= set_nmi; + next_state <= vect_hi_state; + else + -- + -- nmi request is not cleared until nmi input goes low + -- + if (nmi_req = '0') and (nmi_ack='1') then + nmi_ctrl <= reset_nmi; + else + nmi_ctrl <= latch_nmi; + end if; + -- + -- IRQ is level sensitive + -- + if (irq = '1') and (cc(IBIT) = '0') then + iv_ctrl <= irq_iv; + next_state <= int_mask_state; + else + iv_ctrl <= latch_iv; + next_state <= int_wai_state; + end if; + end if; + + when int_mask_state => + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- Mask IRQ + left_ctrl <= sp_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sei; + cc_ctrl <= load_cc; + sp_ctrl <= latch_sp; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= vect_hi_state; + + when halt_state => -- halt CPU. + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- do nothing in ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + if halt = '1' then + next_state <= halt_state; + else + next_state <= fetch_state; + end if; + + when others => -- error state halt on undefine states + -- default + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + ix_ctrl <= latch_ix; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + iv_ctrl <= latch_iv; + op_ctrl <= latch_op; + nmi_ctrl <= latch_nmi; + ea_ctrl <= latch_ea; + -- do nothing in ALU + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + -- idle bus cycle + addr_ctrl <= idle_ad; + dout_ctrl <= md_lo_dout; + next_state <= error_state; + end case; +end process; + +-------------------------------- +-- +-- state machine +-- +-------------------------------- + +change_state: process( clk, rst, state, hold ) +begin + if clk'event and clk = '0' then + if rst = '1' then + state <= reset_state; + elsif hold = '1' then + state <= state; + else + state <= next_state; + end if; + end if; +end process; + -- output + +end CPU_ARCH; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd new file mode 100644 index 00000000..7adbb321 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/defender_sound_board.vhd @@ -0,0 +1,184 @@ +--------------------------------------------------------------------------------- +-- Defender sound board by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +--------------------------------------------------------------------------------- +-- gen_ram.vhd +-------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +--------------------------------------------------------------------------------- +-- cpu68 - Version 9th Jan 2004 0.8 +-- 6800/01 compatible CPU core +-- GNU public license - December 2002 : John E. Kent +--------------------------------------------------------------------------------- +-- Educational use only +-- Do not redistribute synthetized file with roms +-- Do not redistribute roms whatever the form +-- Use at your own risk +--------------------------------------------------------------------------------- +-- Version 0.0 -- 15/10/2017 -- +-- initial version +--------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity defender_sound_board is +port( + clk_0p89 : in std_logic; + reset : in std_logic; + hand : out std_logic; + select_sound : in std_logic_vector( 5 downto 0); + audio_out : out std_logic_vector( 7 downto 0); + rom_addr : out std_logic_vector(11 downto 0); + rom_do : in std_logic_vector( 7 downto 0); + rom_vma : out std_logic +); +end defender_sound_board; + +architecture struct of defender_sound_board is + + signal reset_n : std_logic; + + signal cpu_addr : std_logic_vector(15 downto 0); + signal cpu_di : std_logic_vector( 7 downto 0); + signal cpu_do : std_logic_vector( 7 downto 0); + signal cpu_rw : std_logic; + signal cpu_irq : std_logic; + signal cpu_vma : std_logic; + + signal wram_cs : std_logic; + signal wram_we : std_logic; + signal wram_do : std_logic_vector( 7 downto 0); + + signal rom_cs : std_logic; +-- signal rom_do : std_logic_vector( 7 downto 0); + +-- pia port a +-- bit 0-7 audio output + +-- pia port b +-- bit 0-4 select sound input (sel0-4) +-- bit 5-6 switch sound/notes/speech on/off +-- bit 7 sel5 + +-- pia io ca/cb +-- ca1 vdd +-- cb1 sound trigger (sel0-5 = 1) +-- ca2 speech data N/C +-- cb2 speech clock N/C + + signal pia_rw_n : std_logic; + signal pia_cs : std_logic; + signal pia_irqa : std_logic; + signal pia_irqb : std_logic; + signal pia_do : std_logic_vector( 7 downto 0); + signal pia_pa_o : std_logic_vector( 7 downto 0); + signal pia_pb_i : std_logic_vector( 7 downto 0); + signal pia_cb1_i : std_logic; + +begin + +reset_n <= not reset; + +-- pia cs +wram_cs <= '1' when cpu_addr(15 downto 8) = X"00" else '0'; -- 0000-007F +pia_cs <= '1' when cpu_addr(14 downto 12) = "000" and cpu_addr(10) = '1' else '0'; -- 8400-8403 ? => 0400-0403 +rom_cs <= '1' when cpu_addr(15 downto 12) = X"F" else '0'; -- F800-FFFF + +-- write enables +wram_we <= '1' when cpu_rw = '0' and wram_cs = '1' else '0'; +pia_rw_n <= '0' when cpu_rw = '0' and pia_cs = '1' else '1'; + +-- mux cpu in data between roms/io/wram +cpu_di <= + wram_do when wram_cs = '1' else + pia_do when pia_cs = '1' else + rom_do when rom_cs = '1' else X"55"; + +-- pia I/O +audio_out <= pia_pa_o; + +pia_pb_i(5 downto 0) <= select_sound(5 downto 0); +--pia_pb_i(4 downto 0) <= select_sound(4 downto 0); +--pia_pb_i(6 downto 5) <= "11"; -- assume DS1-1 and DS1-2 open +pia_pb_i(6) <= '1'; +pia_pb_i(7) <= '1'; -- Handshake to ? from rom board (drawings are confusing) + +-- pia Cb1 +pia_cb1_i <= '0' when select_sound = "111111" else '1'; + +-- pia irqs to cpu +cpu_irq <= pia_irqa or pia_irqb; + +-- microprocessor 6800 +main_cpu : entity work.cpu68 +port map( + clk => clk_0p89,-- E clock input (falling edge) + rst => reset, -- reset input (active high) + rw => cpu_rw, -- read not write output + vma => cpu_vma, -- valid memory address (active high) + address => cpu_addr, -- address bus output + data_in => cpu_di, -- data bus input + data_out => cpu_do, -- data bus output + hold => '0', -- hold input (active high) extend bus cycle + halt => '0', -- halt input (active high) grants DMA + irq => cpu_irq, -- interrupt request input (active high) + nmi => '0', -- non maskable interrupt request input (active high) + test_alu => open, + test_cc => open +); + +-- cpu program rom +--cpu_prog_rom : entity work.defender_sound +--port map( +-- clk => clk_0p89, +-- addr => cpu_addr(10 downto 0), +-- data => rom_do +--); +rom_vma <= rom_cs and cpu_vma; +rom_addr <= cpu_addr(11 downto 0); + +-- cpu wram +cpu_ram : entity work.gen_ram +generic map( dWidth => 8, aWidth => 7) +port map( + clk => clk_0p89, + we => wram_we, + addr => cpu_addr(6 downto 0), + d => cpu_do, + q => wram_do +); + +-- pia +pia : entity work.pia6821 +port map +( + clk => clk_0p89, + rst => reset, + cs => pia_cs, + rw => pia_rw_n, + addr => cpu_addr(1 downto 0), + data_in => cpu_do, + data_out => pia_do, + irqa => pia_irqa, + irqb => pia_irqb, + pa_i => (others => '0'), + pa_o => pia_pa_o, + pa_oe => open, + ca1 => '1', + ca2_i => '0', + ca2_o => open, + ca2_oe => open, + pb_i => pia_pb_i, + pb_o => open, + pb_oe => open, + cb1 => pia_cb1_i, + cb2_i => '0', + cb2_o => open, + cb2_oe => open +); + +end struct; \ No newline at end of file diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd new file mode 100644 index 00000000..284194c5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/dpram.vhd @@ -0,0 +1,81 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- dpram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity dpram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk_a : in std_logic; + we_a : in std_logic := '0'; + addr_a : in std_logic_vector((aWidth-1) downto 0); + d_a : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_a : out std_logic_vector((dWidth-1) downto 0); + + clk_b : in std_logic; + we_b : in std_logic := '0'; + addr_b : in std_logic_vector((aWidth-1) downto 0); + d_b : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_b : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of dpram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + signal addr_a_reg: std_logic_vector((aWidth-1) downto 0); + signal addr_b_reg: std_logic_vector((aWidth-1) downto 0); +begin + +-- ----------------------------------------------------------------------- + process(clk_a) + begin + if rising_edge(clk_a) then + if we_a = '1' then + ram(to_integer(unsigned(addr_a))) <= d_a; + end if; + q_a <= ram(to_integer(unsigned(addr_a))); + end if; + end process; + + process(clk_b) + begin + if rising_edge(clk_b) then + if we_b = '1' then + ram(to_integer(unsigned(addr_b))) <= d_b; + end if; + q_b <= ram(to_integer(unsigned(addr_b))); + end if; + end process; + +end architecture; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd new file mode 100644 index 00000000..f1a95608 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/gen_ram.vhd @@ -0,0 +1,84 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- gen_rwram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity gen_ram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk : in std_logic; + we : in std_logic; + addr : in std_logic_vector((aWidth-1) downto 0); + d : in std_logic_vector((dWidth-1) downto 0); + q : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of gen_ram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + + signal rAddrReg : std_logic_vector((aWidth-1) downto 0); + signal qReg : std_logic_vector((dWidth-1) downto 0); +begin +-- ----------------------------------------------------------------------- +-- Signals to entity interface +-- ----------------------------------------------------------------------- +-- q <= qReg; + +-- ----------------------------------------------------------------------- +-- Memory write +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if we = '1' then + ram(to_integer(unsigned(addr))) <= d; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Memory read +-- ----------------------------------------------------------------------- +process(clk) + begin + if rising_edge(clk) then +-- qReg <= ram(to_integer(unsigned(rAddrReg))); +-- rAddrReg <= addr; +---- qReg <= ram(to_integer(unsigned(addr))); + q <= ram(to_integer(unsigned(addr))); + end if; + end process; +--q <= ram(to_integer(unsigned(addr))); +end architecture; + diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip new file mode 100644 index 00000000..d4720390 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll_mist.vhd"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_mist.ppf"] diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd new file mode 100644 index 00000000..981d030b --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/pll_mist.vhd @@ -0,0 +1,429 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll_mist.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2014 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll_mist IS + PORT + ( + areset : IN STD_LOGIC := '0'; + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC ; + locked : OUT STD_LOGIC + ); +END pll_mist; + + +ARCHITECTURE SYN OF pll_mist 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 ; + SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire7 : 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; + self_reset_on_loss_lock : STRING; + width_clock : NATURAL + ); + PORT ( + areset : IN STD_LOGIC ; + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); + locked : OUT STD_LOGIC + ); + END COMPONENT; + +BEGIN + sub_wire7_bv(0 DOWNTO 0) <= "0"; + sub_wire7 <= To_stdlogicvector(sub_wire7_bv); + sub_wire4 <= sub_wire0(2); + sub_wire3 <= sub_wire0(0); + sub_wire1 <= sub_wire0(1); + c1 <= sub_wire1; + locked <= sub_wire2; + c0 <= sub_wire3; + c2 <= sub_wire4; + sub_wire5 <= inclk0; + sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 9, + clk0_duty_cycle => 50, + clk0_multiply_by => 32, + clk0_phase_shift => "0", + clk1_divide_by => 9, + clk1_duty_cycle => 50, + clk1_multiply_by => 4, + clk1_phase_shift => "0", + clk2_divide_by => 91, + clk2_duty_cycle => 50, + clk2_multiply_by => 3, + clk2_phase_shift => "0", + compensate_clock => "CLK0", + inclk0_input_frequency => 37037, + intended_device_family => "Cyclone III", + lpm_hint => "CBX_MODULE_PREFIX=pll_mist", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_USED", + 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_USED", + 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", + self_reset_on_loss_lock => "OFF", + width_clock => 5 + ) + PORT MAP ( + areset => areset, + inclk => sub_wire6, + clk => sub_wire0, + locked => sub_wire2 + ); + + + +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 "3" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "9" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "91" +-- 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 "96.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "0.890110" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +-- 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 "6" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "3" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "96.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "0.89000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +-- 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 "1" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_mist.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 "9" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "32" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "4" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "91" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "3" +-- 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_USED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_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: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +-- Retrieval info: USED_PORT: 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: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd new file mode 100644 index 00000000..ab4849dd --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_4.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity decoder_4 is +port ( + clk : in std_logic; + addr : in std_logic_vector(8 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of decoder_4 is + type rom is array(0 to 511) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"81",X"02",X"42",X"82",X"03",X"43",X"83",X"04",X"44",X"84",X"05",X"45",X"85",X"06",X"46",X"86", + X"07",X"47",X"87",X"08",X"48",X"88",X"09",X"49",X"89",X"0A",X"4A",X"8A",X"0B",X"4B",X"8B",X"0C", + X"4C",X"8C",X"0D",X"4D",X"8D",X"0E",X"4E",X"8E",X"0F",X"4F",X"8F",X"10",X"50",X"90",X"11",X"51", + X"91",X"12",X"52",X"92",X"13",X"53",X"93",X"14",X"54",X"94",X"15",X"55",X"95",X"16",X"56",X"96", + X"17",X"57",X"97",X"18",X"58",X"98",X"19",X"59",X"99",X"1A",X"5A",X"9A",X"1B",X"5B",X"9B",X"1C", + X"5C",X"9C",X"1D",X"5D",X"9D",X"1E",X"5E",X"9E",X"1F",X"5F",X"9F",X"20",X"60",X"A0",X"21",X"61", + X"A1",X"22",X"62",X"A2",X"23",X"63",X"A3",X"24",X"64",X"A4",X"25",X"65",X"A5",X"26",X"66",X"A6", + X"27",X"67",X"A7",X"28",X"68",X"A8",X"29",X"69",X"A9",X"2A",X"6A",X"AA",X"2B",X"6B",X"AB",X"2C", + X"6C",X"AC",X"2D",X"6D",X"AD",X"2E",X"6E",X"AE",X"2F",X"6F",X"AF",X"30",X"70",X"B0",X"31",X"71", + X"B1",X"32",X"72",X"B2",X"33",X"73",X"B3",X"34",X"74",X"B4",X"35",X"75",X"B5",X"36",X"76",X"B6", + X"37",X"77",X"B7",X"38",X"78",X"B8",X"39",X"79",X"B9",X"3A",X"7A",X"BA",X"3B",X"7B",X"BB",X"3C", + X"7C",X"BC",X"3D",X"7D",X"BD",X"3E",X"7E",X"BE",X"3F",X"7F",X"BF",X"00",X"40",X"80",X"01",X"41", + X"C3",X"CF",X"D0",X"D9",X"D2",X"C9",X"C7",X"C8",X"D4",X"80",X"A8",X"C3",X"A9",X"80",X"B1",X"B9", + X"B8",X"B1",X"80",X"D7",X"C9",X"CC",X"CC",X"C9",X"C1",X"CD",X"D3",X"80",X"C5",X"CC",X"C5",X"C3", + X"D4",X"D2",X"CF",X"CE",X"C9",X"C3",X"D3",X"80",X"C9",X"CE",X"C3",X"AE",X"80",X"C1",X"CC",X"CC", + X"80",X"D2",X"C9",X"C7",X"C8",X"D4",X"D3",X"80",X"D2",X"C5",X"D3",X"C5",X"D2",X"D6",X"C5",X"C4", + X"34",X"B3",X"73",X"33",X"B2",X"72",X"32",X"B1",X"71",X"31",X"B0",X"70",X"30",X"AF",X"6F",X"2F", + X"AE",X"6E",X"2E",X"AD",X"6D",X"2D",X"AC",X"6C",X"2C",X"AB",X"6B",X"2B",X"AA",X"6A",X"2A",X"A9", + X"69",X"29",X"A8",X"68",X"28",X"A7",X"67",X"27",X"A6",X"66",X"26",X"A5",X"65",X"25",X"A4",X"64", + X"24",X"A3",X"63",X"23",X"A2",X"62",X"22",X"A1",X"61",X"21",X"A0",X"60",X"20",X"9F",X"5F",X"1F", + X"9E",X"5E",X"1E",X"9D",X"5D",X"1D",X"9C",X"5C",X"1C",X"9B",X"5B",X"1B",X"9A",X"5A",X"1A",X"99", + X"59",X"19",X"98",X"58",X"18",X"97",X"57",X"17",X"96",X"56",X"16",X"95",X"55",X"15",X"94",X"54", + X"14",X"93",X"53",X"13",X"92",X"52",X"12",X"91",X"51",X"11",X"90",X"50",X"10",X"8F",X"4F",X"0F", + X"8E",X"4E",X"0E",X"8D",X"4D",X"0D",X"8C",X"4C",X"0C",X"8B",X"4B",X"0B",X"8A",X"4A",X"0A",X"89", + X"49",X"09",X"88",X"48",X"08",X"87",X"47",X"07",X"86",X"46",X"06",X"85",X"45",X"05",X"84",X"44", + X"04",X"83",X"43",X"03",X"82",X"42",X"02",X"81",X"74",X"B4",X"35",X"75",X"B5",X"36",X"76",X"B6", + X"37",X"77",X"B7",X"38",X"78",X"B8",X"39",X"79",X"B9",X"3A",X"7A",X"BA",X"3B",X"7B",X"BB",X"3C", + X"7C",X"BC",X"3D",X"7D",X"BD",X"3E",X"7E",X"BE",X"3F",X"7F",X"BF",X"00",X"40",X"80",X"01",X"41", + X"C3",X"CF",X"D0",X"D9",X"D2",X"C9",X"C7",X"C8",X"D4",X"80",X"A8",X"C3",X"A9",X"80",X"B1",X"B9", + X"B8",X"B1",X"80",X"D7",X"C9",X"CC",X"CC",X"C9",X"C1",X"CD",X"D3",X"80",X"C5",X"CC",X"C5",X"C3", + X"D4",X"D2",X"CF",X"CE",X"C9",X"C3",X"D3",X"80",X"C9",X"CE",X"C3",X"AE",X"80",X"C1",X"CC",X"CC", + X"80",X"D2",X"C9",X"C7",X"C8",X"D4",X"D3",X"80",X"D2",X"C5",X"D3",X"C5",X"D2",X"D6",X"C5",X"C4"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd new file mode 100644 index 00000000..0e46cdd5 --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/decoder_6.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity decoder_6 is +port ( + clk : in std_logic; + addr : in std_logic_vector(8 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of decoder_6 is + type rom is array(0 to 511) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"00",X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E", + X"0F",X"10",X"11",X"12",X"13",X"14",X"15",X"16",X"17",X"18",X"19",X"1A",X"1B",X"1C",X"1D",X"1E", + X"1F",X"20",X"21",X"22",X"23",X"24",X"25",X"26",X"27",X"28",X"29",X"2A",X"2B",X"2C",X"2D",X"2E", + X"2F",X"30",X"31",X"32",X"33",X"34",X"35",X"36",X"37",X"38",X"39",X"3A",X"3B",X"3C",X"3D",X"3E", + X"3F",X"40",X"41",X"42",X"43",X"44",X"45",X"46",X"47",X"48",X"49",X"4A",X"4B",X"4C",X"4D",X"4E", + X"4F",X"50",X"51",X"52",X"53",X"54",X"55",X"56",X"57",X"58",X"59",X"5A",X"5B",X"5C",X"5D",X"5E", + X"5F",X"60",X"61",X"62",X"63",X"64",X"65",X"66",X"67",X"68",X"69",X"6A",X"6B",X"6C",X"6D",X"6E", + X"6F",X"70",X"71",X"72",X"73",X"74",X"75",X"76",X"77",X"78",X"79",X"7A",X"7B",X"7C",X"7D",X"7E", + X"7F",X"80",X"81",X"82",X"83",X"84",X"85",X"86",X"87",X"88",X"89",X"8A",X"8B",X"8C",X"8D",X"8E", + X"8F",X"90",X"91",X"92",X"93",X"94",X"95",X"96",X"97",X"98",X"99",X"9A",X"9B",X"9C",X"9D",X"9E", + X"9F",X"A0",X"A1",X"A2",X"A3",X"A4",X"A5",X"A6",X"A7",X"A8",X"A9",X"AA",X"AB",X"AC",X"AD",X"AE", + X"AF",X"B0",X"B1",X"B2",X"B3",X"B4",X"B5",X"B6",X"B7",X"B8",X"B9",X"BA",X"BB",X"BC",X"BD",X"BE", + X"BF",X"C0",X"C1",X"C2",X"C3",X"C4",X"C5",X"C6",X"C7",X"C8",X"C9",X"CA",X"CB",X"CC",X"CD",X"CE", + X"CF",X"D0",X"D1",X"D2",X"D3",X"D4",X"D5",X"D6",X"D7",X"D8",X"D9",X"DA",X"DB",X"DC",X"DD",X"DE", + X"DF",X"E0",X"E1",X"E2",X"E3",X"E4",X"E5",X"E6",X"E7",X"E8",X"E9",X"EA",X"EB",X"EC",X"ED",X"EE", + X"EF",X"F0",X"F1",X"F2",X"F3",X"F4",X"F5",X"F6",X"F7",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"F7",X"F6",X"F5",X"F4",X"F3",X"F2",X"F1",X"F0",X"EF", + X"EE",X"ED",X"EC",X"EB",X"EA",X"E9",X"E8",X"E7",X"E6",X"E5",X"E4",X"E3",X"E2",X"E1",X"E0",X"DF", + X"DE",X"DD",X"DC",X"DB",X"DA",X"D9",X"D8",X"D7",X"D6",X"D5",X"D4",X"D3",X"D2",X"D1",X"D0",X"CF", + X"CE",X"CD",X"CC",X"CB",X"CA",X"C9",X"C8",X"C7",X"C6",X"C5",X"C4",X"C3",X"C2",X"C1",X"C0",X"BF", + X"BE",X"BD",X"BC",X"BB",X"BA",X"B9",X"B8",X"B7",X"B6",X"B5",X"B4",X"B3",X"B2",X"B1",X"B0",X"AF", + X"AE",X"AD",X"AC",X"AB",X"AA",X"A9",X"A8",X"A7",X"A6",X"A5",X"A4",X"A3",X"A2",X"A1",X"A0",X"9F", + X"9E",X"9D",X"9C",X"9B",X"9A",X"99",X"98",X"97",X"96",X"95",X"94",X"93",X"92",X"91",X"90",X"8F", + X"8E",X"8D",X"8C",X"8B",X"8A",X"89",X"88",X"87",X"86",X"85",X"84",X"83",X"82",X"81",X"80",X"7F", + X"7E",X"7D",X"7C",X"7B",X"7A",X"79",X"78",X"77",X"76",X"75",X"74",X"73",X"72",X"71",X"70",X"6F", + X"6E",X"6D",X"6C",X"6B",X"6A",X"69",X"68",X"67",X"66",X"65",X"64",X"63",X"62",X"61",X"60",X"5F", + X"5E",X"5D",X"5C",X"5B",X"5A",X"59",X"58",X"57",X"56",X"55",X"54",X"53",X"52",X"51",X"50",X"4F", + X"4E",X"4D",X"4C",X"4B",X"4A",X"49",X"48",X"47",X"46",X"45",X"44",X"43",X"42",X"41",X"40",X"3F", + X"3E",X"3D",X"3C",X"3B",X"3A",X"39",X"38",X"37",X"36",X"35",X"34",X"33",X"32",X"31",X"30",X"2F", + X"2E",X"2D",X"2C",X"2B",X"2A",X"29",X"28",X"27",X"26",X"25",X"24",X"23",X"22",X"21",X"20",X"1F", + X"1E",X"1D",X"1C",X"1B",X"1A",X"19",X"18",X"17",X"16",X"15",X"14",X"13",X"12",X"11",X"10",X"0F", + X"0E",X"0D",X"0C",X"0B",X"0A",X"09",X"08",X"07",X"06",X"05",X"04",X"03",X"02",X"01",X"00",X"00"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd new file mode 100755 index 00000000..901b252a --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu.vhd @@ -0,0 +1,1096 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga 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. +-- +-- robotron-fpga 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 robotron-fpga. If not, see +-- . +-- +-- Jan 2020: +-- Converted from bidirectional data buses to separated buses for SOC usage +-- Changed to orignal 15kHz display timing +-- Replaced PIAs from System09 (the original didn't work in Joust) +-- Added blitter SC2 selection (for Splat) +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +--library unisim; +-- use unisim.vcomponents.all; + +entity robotron_cpu is + port( + clock : in std_logic; + blitter_sc2 : in std_logic; + sinistar : in std_logic; + + -- MC6809 signals + A : in std_logic_vector(15 downto 0); + Dout : in std_logic_vector(7 downto 0); + Din : out std_logic_vector(7 downto 0); + RESET_N : out std_logic; + NMI_N : out std_logic; + FIRQ_N : out std_logic; + IRQ_N : out std_logic; + LIC : in std_logic; + AVMA : in std_logic; + R_W_N : in std_logic; + TSC : out std_logic; + HALT_N : out std_logic; + BA : in std_logic; + BS : in std_logic; + BUSY : in std_logic; + E : out std_logic; + Q : out std_logic; + + -- USB + --EppAstb : in std_logic; + --EppDstb : in std_logic; + --UsbFlag : in std_logic; + --EppWait : in std_logic; + --EppDB : in std_logic_vector(7 downto 0); + --UsbClk : in std_logic; + --UsbOE : in std_logic; + --UsbWR : in std_logic; + --UsbPktEnd : in std_logic; + --UsbDir : in std_logic; + --UsbMode : in std_logic; + --UsbAdr : in std_logic_vector(1 downto 0); + + -- Cellular RAM / StrataFlash + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDin : out std_logic_vector(15 downto 0); + MemDout : in std_logic_vector(15 downto 0); + + -- 7-segment display + SEG : out std_logic_vector(6 downto 0); + DP : out std_logic; + AN : out std_logic_vector(3 downto 0); + + -- LEDs + LED : out std_logic_vector(7 downto 0); + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + + -- VGA connector + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic; + + -- PS/2 connector + --PS2C : in std_logic; + --PS2D : in std_logic; + + -- 12-pin connectors + JA : in std_logic_vector(7 downto 0); + JB : in std_logic_vector(7 downto 0); + SIN_FIRE : in std_logic; + SIN_BOMB : in std_logic; + + -- To sound board + HAND : in std_logic := '1'; + PB : out std_logic_vector(5 downto 0) + ); +end robotron_cpu; + +architecture Behavioral of robotron_cpu is + + signal reset_request : std_logic; + signal reset_counter : unsigned(7 downto 0); + signal reset : std_logic; + + signal clock_12_phase : unsigned(11 downto 0) := (0 => '1', others => '0'); + + signal clock_q_set : boolean; + signal clock_q_clear : boolean; + signal clock_q : std_logic := '0'; + + signal clock_e_set : boolean; + signal clock_e_clear : boolean; + signal clock_e : std_logic := '0'; + + ------------------------------------------------------------------- + + signal video_count : unsigned(14 downto 0) := (others => '0'); + signal video_count_next : unsigned(14 downto 0); + signal video_address_or_mask : unsigned(13 downto 0); + signal video_address : unsigned(13 downto 0) := (others => '0'); + + signal count_240 : std_logic; + signal irq_4ms : std_logic; + + signal horizontal_sync : std_logic; + signal vertical_sync : std_logic; + + signal video_blank : boolean := true; + + ------------------------------------------------------------------- + + signal led_bcd_in : std_logic_vector(15 downto 0); + signal led_bcd_in_digit : std_logic_vector(3 downto 0); + + signal led_counter : unsigned(15 downto 0) := (others => '0'); + signal led_digit_index : unsigned(1 downto 0); + + signal led_segment : std_logic_vector(6 downto 0); + signal led_dp : std_logic; + signal led_anode : std_logic_vector(3 downto 0); + + ------------------------------------------------------------------- + + signal address : std_logic_vector(15 downto 0); + + signal write : boolean; + signal read : boolean; + + ------------------------------------------------------------------- + + signal mpu_address : std_logic_vector(15 downto 0); + signal mpu_data_in : std_logic_vector(7 downto 0); + signal mpu_data_out : std_logic_vector(7 downto 0); + + signal mpu_bus_status : std_logic; + signal mpu_bus_available : std_logic; + + signal mpu_read : boolean; + signal mpu_write : boolean; + + signal mpu_reset : std_logic := '1'; + signal mpu_halt : std_logic := '0'; + signal mpu_halted : boolean := false; + signal mpu_irq : std_logic := '0'; + signal mpu_firq : std_logic := '0'; + signal mpu_nmi : std_logic := '0'; + + ------------------------------------------------------------------- + + signal memory_address : std_logic_vector(15 downto 0); + signal memory_data_in : std_logic_vector(7 downto 0); + signal memory_data_out : std_logic_vector(7 downto 0); + + signal memory_output_enable : boolean := false; + signal memory_write : boolean := false; + signal flash_enable : boolean := false; + + signal ram_enable : boolean := false; + signal ram_lower_enable : boolean := false; + signal ram_upper_enable : boolean := false; + + ------------------------------------------------------------------- + + signal e_rom : std_logic := '0'; + signal screen_control : std_logic := '0'; + + signal rom_access : boolean; + signal ram_access : boolean; + signal hiram_access : boolean; -- Sinistar hiram + signal color_table_access : boolean; + signal widget_pia_access : boolean; + signal rom_pia_access : boolean; + signal blt_register_access : boolean; + signal video_counter_access : boolean; + signal watchdog_access : boolean; + signal control_access : boolean; + signal cmos_access : boolean; + + signal video_counter_value : std_logic_vector(7 downto 0); + + ------------------------------------------------------------------- + + signal SLAM : std_logic := '1'; + signal R_COIN : std_logic := '1'; + signal C_COIN : std_logic := '1'; + signal L_COIN : std_logic := '1'; + signal H_S_RESET : std_logic := '1'; + signal ADVANCE : std_logic := '1'; + signal AUTO_UP : std_logic := '0'; + + signal rom_pia_rs : std_logic_vector(1 downto 0) := (others => '0'); + signal rom_pia_cs : std_logic := '0'; + signal rom_pia_write : std_logic := '0'; + signal rom_pia_data_in : std_logic_vector(7 downto 0); + signal rom_pia_data_out : std_logic_vector(7 downto 0); + signal rom_pia_ca2_out : std_logic; + signal rom_pia_ca2_dir : std_logic; + signal rom_pia_irq_a : std_logic; + signal rom_pia_pa_in : std_logic_vector(7 downto 0); + signal rom_pia_pa_out : std_logic_vector(7 downto 0); + signal rom_pia_pa_dir : std_logic_vector(7 downto 0); + + signal rom_pia_cb2_out : std_logic; + signal rom_pia_cb2_dir : std_logic; + signal rom_pia_irq_b : std_logic; + signal rom_pia_pb_in : std_logic_vector(7 downto 0); + signal rom_pia_pb_out : std_logic_vector(7 downto 0); + signal rom_pia_pb_dir : std_logic_vector(7 downto 0); + + signal rom_led_digit : std_logic_vector(3 downto 0); + + ------------------------------------------------------------------- + + signal MOVE_UP_1 : std_logic := '1'; + signal MOVE_DOWN_1 : std_logic := '1'; + signal MOVE_LEFT_1 : std_logic := '1'; + signal MOVE_RIGHT_1 : std_logic := '1'; + signal PLAYER_1_START : std_logic := '1'; + signal PLAYER_2_START : std_logic := '1'; + signal FIRE_UP_1 : std_logic := '1'; + signal FIRE_DOWN_1 : std_logic := '1'; + signal FIRE_RIGHT_1 : std_logic := '1'; + signal FIRE_LEFT_1 : std_logic := '1'; + signal MOVE_UP_2 : std_logic := '1'; + signal MOVE_DOWN_2 : std_logic := '1'; + signal MOVE_LEFT_2 : std_logic := '1'; + signal MOVE_RIGHT_2 : std_logic := '1'; + signal FIRE_RIGHT_2 : std_logic := '1'; + signal FIRE_UP_2 : std_logic := '1'; + signal FIRE_DOWN_2 : std_logic := '1'; + signal FIRE_LEFT_2 : std_logic := '1'; + + signal board_interface_w1 : std_logic := '1'; -- Upright application: '1' = jumper present + + signal widget_pia_rs : std_logic_vector(1 downto 0) := (others => '0'); + signal widget_pia_cs : std_logic; + signal widget_pia_write : std_logic := '0'; + signal widget_pia_data_in : std_logic_vector(7 downto 0); + signal widget_pia_data_out : std_logic_vector(7 downto 0); + signal widget_pia_ca2_out : std_logic; + signal widget_pia_ca2_dir : std_logic; + signal widget_pia_irq_a : std_logic; + signal widget_pia_pa_in : std_logic_vector(7 downto 0); + signal widget_pia_pa_out : std_logic_vector(7 downto 0); + signal widget_pia_pa_dir : std_logic_vector(7 downto 0); + signal widget_pia_input_select : std_logic; + signal widget_pia_cb2_out : std_logic; + signal widget_pia_cb2_dir : std_logic; + signal widget_pia_irq_b : std_logic; + signal widget_pia_pb_in : std_logic_vector(7 downto 0); + signal widget_pia_pb_out : std_logic_vector(7 downto 0); + signal widget_pia_pb_dir : std_logic_vector(7 downto 0); + + signal widget_ic3_a : std_logic_vector(4 downto 1); + signal widget_ic3_b : std_logic_vector(4 downto 1); + signal widget_ic3_y : std_logic_vector(4 downto 1); + + signal widget_ic4_a : std_logic_vector(4 downto 1); + signal widget_ic4_b : std_logic_vector(4 downto 1); + signal widget_ic4_y : std_logic_vector(4 downto 1); + + ------------------------------------------------------------------- + + signal blt_rs : std_logic_vector(2 downto 0) := (others => '0'); + signal blt_reg_cs : std_logic := '0'; + signal blt_reg_data_in : std_logic_vector(7 downto 0) := (others => '0'); + + signal blt_halt : boolean := false; + signal blt_halt_ack : boolean := false; + signal blt_read : boolean := false; + signal blt_write : boolean := false; + signal blt_blt_ack : std_logic := '0'; + signal blt_address_out : std_logic_vector(15 downto 0); + signal blt_data_in : std_logic_vector(7 downto 0); + signal blt_data_out : std_logic_vector(7 downto 0); + signal blt_en_lower : boolean := false; + signal blt_en_upper : boolean := false; + + ------------------------------------------------------------------- + + function to_std_logic(L: boolean) return std_logic is + begin + if L then + return '1'; + else + return '0'; + end if; + end function; + + subtype pixel_color_t is std_logic_vector(7 downto 0); + type color_table_t is array(0 to 15) of pixel_color_t; + signal color_table : color_table_t; + + signal pixel_nibbles : std_logic_vector(7 downto 0); + signal pixel_byte_l : std_logic_vector(7 downto 0); + signal pixel_byte_h : std_logic_vector(7 downto 0); + + ------------------------------------------------------------------- + + signal decoder_4_in : std_logic_vector(8 downto 0); + signal pseudo_address : std_logic_vector(15 downto 8); + + signal decoder_6_in : std_logic_vector(8 downto 0); + signal video_prom_address : std_logic_vector(13 downto 6); + + ------------------------------------------------------------------- + + signal debug_blt_source_address : std_logic_vector(15 downto 0) := (others => '0'); + signal debug_last_mpu_address : std_logic_vector(15 downto 0) := (others => '0'); + +begin + + -- clock 0 1 2 3 4 5 6 7 8 9 10 11 + -- Q 0 0 0 1 1 1 1 1 1 0 0 0 + -- E 0 0 0 0 0 0 1 1 1 1 1 1 + -- Memory 0 0 1 1 2 2 3 3 4 4 5 5 + + -- Micro 128Mb (8M x 16) CellularRAM MT45W8MW16BGX-701 WT (marking "PW503") + -- MT: Micron Technology + -- 45: PSRAM/CellularRAM memory + -- W: 1.70-1.95V + -- 8M: 8 Meg address space + -- W: 1.7 - 3.6V + -- 16: 16-bit bus + -- B: asynchronous/page/burst read/write operation mode + -- GX: 54-ball "green" VFBGA + -- -70: 70ns access/cycle time + -- 1: 104MHz frequency + -- : standard standby power option + -- WT: -30C to +85C operating temperature + ------------------------------------------------------------------- + -- Asynchronous mode: + -- tRC (read cycle): 70 ns + -- from CE#/OE#/ADDRESS/LB#/UB# asserted to DATA valid and CE#/OE#/ADDRESS/LB#/UB# de-asserted. + -- tWC (write cycle): 70 ns + -- from CE#/ADDRESS/LB#/UB# asserted to DATA valid and CE#/WE#/LB#/UB# de-asserted. + -- tCEM: 4 us maximum + -- from WE# asserted to DATA valid and CE#/WE#/LB#/UB# de-asserted. + + -- Intel JS28F128J3D75 + ------------------------------------------------------------------- + -- Read: + -- 75 ns read/write cycle time + -- 75 ns address to output delay + -- 75 ns CE# to output delay + + reset_request <= BTN(0); + + mpu_reset <= reset; + mpu_halt <= to_std_logic(blt_halt); + mpu_irq <= rom_pia_irq_a or rom_pia_irq_b; + mpu_firq <= '0'; + mpu_nmi <= '0'; + + address <= blt_address_out when mpu_halted else + mpu_address; + write <= blt_write when mpu_halted else + mpu_write; + read <= blt_read when mpu_halted else + mpu_read; + + rom_access <= (address < X"9000" and read and e_rom = '1') or + (address >= X"D000" and read and sinistar='0') or + (address >= X"E000" and read and sinistar='1'); + ram_access <= (address < X"9000" and write) or + (address < X"9000" and read and e_rom = '0') or + (address >= X"9000" and address < X"C000") or + hiram_access; + hiram_access <= + (address >= X"D000" and address < X"E000") and sinistar='1'; + + -- Color table: write: C000-C3FF + color_table_access <= std_match(address, "110000----------"); + + -- Widget PIA: read/write: C8X4 - C8X7 + widget_pia_access <= std_match(address, "11001000----01--"); + + -- ROM PIA: read/write: C8XC - C8XF + rom_pia_access <= std_match(address, "11001000----11--"); + + -- Control address: write: C9XX + control_access <= std_match(address, "11001001--------"); + + -- Special chips: read/write? CAXX + blt_register_access <= std_match(address, "11001010--------"); + + -- Video counter: read: CBXX (even addresses) + video_counter_access <= std_match(address, "11001011-------0"); + + -- Watchdog register: write: CBFE or CBFF + watchdog_access <= std_match(address, "110010111111111-"); + + -- CMOS "nonvolatile" RAM: read/write: CC00 - CFFF + cmos_access <= std_match(address, "110011----------"); + + SLAM <= not SW(6); + H_S_RESET <= not SW(2); + ADVANCE <= not SW(1); + AUTO_UP <= not SW(0); + + PLAYER_1_START <= not BTN(3); + PLAYER_2_START <= not BTN(2); + L_COIN <= not BTN(1); + + MOVE_UP_1 <= JA(0); + MOVE_DOWN_1 <= JA(1); + MOVE_LEFT_1 <= JA(2); + MOVE_RIGHT_1 <= JA(3); + FIRE_UP_1 <= JA(4); + FIRE_DOWN_1 <= JA(5); + FIRE_LEFT_1 <= JA(6); + FIRE_RIGHT_1 <= JA(7); + + MOVE_UP_2 <= JB(0); + MOVE_DOWN_2 <= JB(1); + MOVE_LEFT_2 <= JB(2); + MOVE_RIGHT_2 <= JB(3); + FIRE_UP_2 <= JB(4); + FIRE_DOWN_2 <= JB(5); + FIRE_LEFT_2 <= JB(6); + FIRE_RIGHT_2 <= JB(7); + + video_counter_value <= std_logic_vector(video_address(13 downto 8)) & "00"; + + decoder_4_in <= screen_control & address(15 downto 8); + decoder_6_in <= screen_control & std_logic_vector(video_address(13 downto 6)); + + process(clock) + begin + if rising_edge(clock) then + ram_enable <= false; + ram_lower_enable <= false; + ram_upper_enable <= false; + + flash_enable <= false; + + memory_output_enable <= false; + memory_write <= false; + memory_data_out <= (others => '0'); + + blt_reg_cs <= '0'; + blt_blt_ack <= '0'; + + rom_pia_cs <= '0'; + rom_pia_write <= '0'; + + widget_pia_cs <= '0'; + widget_pia_write <= '0'; + + if clock_12_phase( 0) = '1' then + memory_address <= "00" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase( 4) = '1' then + memory_address <= "01" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase( 8) = '1' then + memory_address <= "10" & video_prom_address & + std_logic_vector(video_address(5 downto 0)); + end if; + + if clock_12_phase(5) = '1' then + if std_match(video_address(5 downto 0), "11-1--") then + video_blank <= true; + elsif std_match(video_address(5 downto 0), "0---1-") then + video_blank <= false; + end if; + end if; + + if clock_12_phase( 0) = '1' or + clock_12_phase( 4) = '1' or + clock_12_phase( 8) = '1' then + memory_output_enable <= true; + ram_enable <= true; + ram_lower_enable <= true; + ram_upper_enable <= true; + + if video_blank then + vgaRed <= (others => '0'); + vgaGreen <= (others => '0'); + vgaBlue <= (others => '0'); + else + vgaRed <= pixel_byte_h(2 downto 0); + vgaGreen <= pixel_byte_h(5 downto 3); + vgaBlue <= pixel_byte_h(7 downto 6); + end if; + end if; + + if clock_12_phase( 1) = '1' or + clock_12_phase( 5) = '1' or + clock_12_phase( 9) = '1' then + pixel_nibbles <= memory_data_in; + end if; + if clock_12_phase( 2) = '1' or + clock_12_phase( 6) = '1' or + clock_12_phase(10) = '1' then + + pixel_byte_l <= color_table(to_integer(unsigned(pixel_nibbles(3 downto 0)))); + pixel_byte_h <= color_table(to_integer(unsigned(pixel_nibbles(7 downto 4)))); + + if video_blank then + vgaRed <= (others => '0'); + vgaGreen <= (others => '0'); + vgaBlue <= (others => '0'); + else + vgaRed <= pixel_byte_l(2 downto 0); + vgaGreen <= pixel_byte_l(5 downto 3); + vgaBlue <= pixel_byte_l(7 downto 6); + end if; + end if; + + -- BLT-only cycles + -- NOTE: the next cycle must be a read if coming from RAM, since the + -- RAM WE# needs to deassert for a time in order for another write to + -- take place. + if clock_12_phase(11) = '1' or clock_12_phase(1) = '1' then + if mpu_halted then + if ram_access and not hiram_access then + if pseudo_address(15 downto 14) = "11" then + memory_address <= address; + else + memory_address <= pseudo_address(15 downto 14) & + address(7 downto 0) & + pseudo_address(13 downto 8); + end if; + else + memory_address <= address; + end if; + + if ram_access and write then + memory_data_out <= blt_data_out; + memory_write <= true; + else + memory_output_enable <= true; + end if; + + if ram_access then + ram_enable <= true; + ram_lower_enable <= blt_en_lower; + ram_upper_enable <= blt_en_upper; + end if; + + if rom_access then + flash_enable <= true; + end if; + + blt_blt_ack <= '1'; + end if; + end if; + + -- MPU-only cycle + -- NOTE: the next cycle must be a read if coming from RAM, since the + -- RAM WE# needs to deassert for a time in order for another write to + -- take place. + if clock_12_phase(7) = '1' then + if not mpu_halted then + if ram_access and not hiram_access then + if pseudo_address(15 downto 14) = "11" then + memory_address <= address; + else + memory_address <= pseudo_address(15 downto 14) & + address(7 downto 0) & + pseudo_address(13 downto 8); + end if; + else + memory_address <= address; + end if; + + if (ram_access or cmos_access or color_table_access) and write then + memory_data_out <= mpu_data_in; + memory_write <= true; + else + memory_output_enable <= true; + end if; + + if ram_access or cmos_access or color_table_access then + ram_enable <= true; + ram_lower_enable <= true; + ram_upper_enable <= true; + end if; + + if rom_access then + flash_enable <= true; + end if; + + if blt_register_access and write then + blt_rs <= address(2 downto 0); + blt_reg_cs <= '1'; + blt_reg_data_in <= mpu_data_in; + + -- NOTE: To display BLT source address: + if address(2 downto 0) = "010" then + debug_blt_source_address(15 downto 8) <= mpu_data_in; + end if; + + if address(2 downto 0) = "011" then + debug_blt_source_address(7 downto 0) <= mpu_data_in; + end if; + end if; + + if rom_pia_access then + rom_pia_rs <= address(1 downto 0); + rom_pia_data_in <= mpu_data_in; + rom_pia_write <= to_std_logic(write); + rom_pia_cs <= '1'; + end if; + + if widget_pia_access then + widget_pia_rs <= address(1 downto 0); + widget_pia_data_in <= mpu_data_in; + widget_pia_write <= to_std_logic(write); + widget_pia_cs <= '1'; + end if; + + if control_access and write then + screen_control <= mpu_data_in(1); + e_rom <= mpu_data_in(0); + end if; + + if color_table_access and write then + color_table(to_integer(unsigned(address(3 downto 0)))) <= mpu_data_in; + end if; + end if; + end if; + + if clock_12_phase(8) = '1' then + if not mpu_halted then + if read then + if ram_access or rom_access or cmos_access then + mpu_data_out <= memory_data_in; + end if; + + if widget_pia_access then + mpu_data_out <= widget_pia_data_out; + end if; + + if rom_pia_access then + mpu_data_out <= rom_pia_data_out; + end if; + + if video_counter_access then + mpu_data_out <= video_counter_value; + end if; + end if; + end if; + end if; + end if; + end process; + + LED <= mpu_irq & + mpu_halt & + to_std_logic(mpu_halted) & + to_std_logic(ram_access) & + to_std_logic(rom_access) & + to_std_logic(rom_pia_access) & + to_std_logic(widget_pia_access) & + to_std_logic(blt_register_access); + + led_bcd_in <= debug_blt_source_address; + + ------------------------------------------------------------------- + + horizontal_decoder: entity work.decoder_4 + port map( + clk => not clock, + addr => decoder_4_in, + data => pseudo_address + ); + + ------------------------------------------------------------------- + + vertical_decoder: entity work.decoder_6 + port map( + clk => not clock, + addr => decoder_6_in, + data => video_prom_address + ); + + ------------------------------------------------------------------- + + blt_halt_ack <= mpu_halted; + blt_data_in <= memory_data_in; + + blt: entity work.sc1 + port map( + clk => clock, + sc2 => blitter_sc2, + + reg_cs => blt_reg_cs, + reg_data_in => blt_reg_data_in, + rs => blt_rs, + + halt => blt_halt, + halt_ack => blt_halt_ack, + + blt_ack => blt_blt_ack, + blt_address_out => blt_address_out, + + blt_rd => blt_read, + blt_wr => blt_write, + + blt_data_in => blt_data_in, + blt_data_out => blt_data_out, + + en_upper => blt_en_upper, + en_lower => blt_en_lower + ); + + ------------------------------------------------------------------- + + rom_pia_pa_in <= not HAND & + not SLAM & + not C_COIN & + not L_COIN & + not H_S_RESET & + not R_COIN & + not ADVANCE & + not AUTO_UP; + PB(5 downto 0) <= rom_pia_pb_out(5 downto 0); + + rom_led_digit(0) <= rom_pia_pb_out(6); + rom_led_digit(1) <= rom_pia_pb_out(7); + rom_led_digit(2) <= rom_pia_cb2_out; + rom_led_digit(3) <= rom_pia_ca2_out; + rom_pia_pb_in <= (others => '1'); + + rom_pia: entity work.pia6821 + port map( + rst => reset, + clk => clock, + + addr => address(1 downto 0), + cs => rom_pia_cs, + rw => not rom_pia_write, + + data_in => mpu_data_in, + data_out => rom_pia_data_out, + + ca1 => count_240, + ca2_i => '1', + ca2_o => rom_pia_ca2_out, + ca2_oe => rom_pia_ca2_dir, + irqa => rom_pia_irq_a, + pa_i => rom_pia_pa_in, + pa_o => rom_pia_pa_out, + pa_oe => rom_pia_pa_dir, + + cb1 => irq_4ms, + cb2_i => '1', + cb2_o => rom_pia_cb2_out, + cb2_oe => rom_pia_cb2_dir, + irqb => rom_pia_irq_b, + pb_i => rom_pia_pb_in, + pb_o => rom_pia_pb_out, + pb_oe => rom_pia_pb_dir + ); + ------------------------------------------------------------------- + + widget_pia_input_select <= widget_pia_cb2_out; + + widget_ic3_a <= not (MOVE_RIGHT_2 & MOVE_LEFT_2 & MOVE_DOWN_2 & MOVE_UP_2); + widget_ic3_b <= not (MOVE_RIGHT_1 & MOVE_LEFT_1 & MOVE_DOWN_1 & MOVE_UP_1); + + widget_ic3_y <= widget_ic3_b when widget_pia_input_select = '1' else widget_ic3_a; + + widget_ic4_a <= not (FIRE_RIGHT_2 & FIRE_LEFT_2 & FIRE_DOWN_2 & FIRE_UP_2); + widget_ic4_b <= not (FIRE_RIGHT_1 & FIRE_LEFT_1 & FIRE_DOWN_1 & FIRE_UP_1); + + widget_ic4_y <= widget_ic4_b when widget_pia_input_select = '1' else widget_ic4_a; + + widget_pia_pa_in <= widget_ic4_y(2) & + widget_ic4_y(1) & + not PLAYER_2_START & + not PLAYER_1_START & + widget_ic3_y(4) & + widget_ic3_y(3) & + widget_ic3_y(2) & + widget_ic3_y(1) when sinistar = '0' else + widget_ic4_y(4) & + widget_ic4_y(3) & + widget_ic4_y(2) & + widget_ic4_y(1) & + widget_ic3_y(4) & + widget_ic3_y(3) & + widget_ic3_y(2) & + widget_ic3_y(1); + widget_pia_pb_in <= not board_interface_w1 & + "00000" & + widget_ic4_y(4) & + widget_ic4_y(3) when sinistar = '0' else + not board_interface_w1 & + "0" & + not PLAYER_2_START & + not PLAYER_1_START & + "00" & + not SIN_BOMB & + not SIN_FIRE; + + widget_pia: work.pia6821 + port map( + rst => reset, + clk => clock, + + addr => address(1 downto 0), + cs => widget_pia_cs, + rw => not widget_pia_write, + + data_in => mpu_data_in, + data_out => widget_pia_data_out, + + ca1 => '0', + ca2_i => '0', + ca2_o => widget_pia_ca2_out, + ca2_oe => widget_pia_ca2_dir, + irqa => widget_pia_irq_a, + pa_i => widget_pia_pa_in, + pa_o => widget_pia_pa_out, + pa_oe => widget_pia_pa_dir, + + cb1 => '0', + cb2_i => '1', + cb2_o => widget_pia_cb2_out, + cb2_oe => widget_pia_cb2_dir, + irqb => widget_pia_irq_b, + pb_i => widget_pia_pb_in, + pb_o => widget_pia_pb_out, + pb_oe => widget_pia_pb_dir + ); + + ------------------------------------------------------------------- + + E <= clock_e; + Q <= clock_q; + + Din <= mpu_data_out; + + TSC <= '0'; + + process(clock, clock_q_set) + begin + if rising_edge(clock) and clock_q_set then + -- RESET, HALT, interrupts are captured by microprocessor + -- on Q falling edge. Present once per processor clock, + -- on Q rising edge -- just because. + RESET_N <= not mpu_reset; + HALT_N <= not mpu_halt; + IRQ_N <= not mpu_irq; + FIRQ_N <= not mpu_firq; + NMI_N <= not mpu_nmi; + end if; + end process; +-- + process(clock, clock_q_set) + begin + if rising_edge(clock) and clock_q_set then + mpu_address <= A; + mpu_bus_status <= BS; + mpu_bus_available <= BA; + mpu_halted <= BS = '1' and BA = '1'; + mpu_write <= R_W_N = '0' and BA = '0'; + mpu_read <= R_W_N = '1' and BA = '0'; + + if BA = '0' then + debug_last_mpu_address <= A; + end if; + end if; + end process; + + process(clock, clock_e_set) + begin + if rising_edge(clock) and clock_e_set then + mpu_data_in <= Dout; + end if; + end process; + + ------------------------------------------------------------------- + + MemOE <= '0' when memory_output_enable else '1'; + MemWR <= '0' when memory_write else '1'; + + RamAdv <= '0'; + RamCS <= '0' when ram_enable else '1'; + RamClk <= '0'; + RamCRE <= '0'; + RamLB <= '0' when ram_lower_enable else '1'; + RamUB <= '0' when ram_upper_enable else '1'; + + FlashRp <= '1'; + FlashCS <= '0' when flash_enable else '1'; + + MemAdr <= "0000000" & memory_address; + + MemDin <= memory_data_out(7 downto 4) & + memory_data_out(7 downto 4) & + memory_data_out(3 downto 0) & + memory_data_out(3 downto 0); + memory_data_in <= MemDout(11 downto 8) & MemDout(3 downto 0); + + ------------------------------------------------------------------- + -- Video output + + Hsync <= not horizontal_sync; + Vsync <= not vertical_sync; + + ------------------------------------------------------------------- + + DP <= led_dp; + SEG <= led_segment; + AN <= led_anode; + + ------------------------------------------------------------------- + -- 1MHz, 12-phase counter. + + process(clock) + begin + if rising_edge(clock) then + clock_12_phase <= clock_12_phase rol 1; + end if; + end process; + + ------------------------------------------------------------------- + -- Q clock + + clock_q_set <= clock_12_phase(2) = '1'; + clock_q_clear <= clock_12_phase(8) = '1'; + + process(clock) + begin + if rising_edge(clock) then + if clock_q_set then + clock_q <= '1'; + elsif clock_q_clear then + clock_q <= '0'; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- E clock + + clock_e_set <= clock_12_phase(5) = '1'; + clock_e_clear <= clock_12_phase(11) = '1'; + + process(clock) + begin + if rising_edge(clock) then + if clock_e_set then + clock_e <= '1'; + elsif clock_e_clear then + clock_e <= '0'; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Reset generator + + process(clock) + begin + if rising_edge(clock) then + if reset_request = '1' then + reset_counter <= (others => '0'); + reset <= '1'; + else + if reset_counter < 100 then + reset_counter <= reset_counter + 1; + else + reset <= '0'; + end if; + end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Video counter + + video_count_next <= video_count + 1 when (video_count /= 16639) + else (others => '0'); + video_address_or_mask <= "11111100000000" when video_count_next(14) = '1' else (others => '0'); +-- irq_4ms <= video_count(11); + irq_4ms <= video_address(11); + + process(clock, clock_e_clear) + begin + -- Advance video count at end of video memory phase. + if rising_edge(clock) and clock_e_clear then + --watchdog_increment <= '0'; + video_count <= video_count_next; + video_address <= video_count_next(13 downto 0) or video_address_or_mask; + --video_address <= video_address + 1; + --if video_count(14 downto 0) = "011111111111111" then + -- watchdog_increment <= '1'; + --end if; + end if; + end process; + + ------------------------------------------------------------------- + -- Video generator + + count_240 <= '1' when video_address(13 downto 10) = "1111" else '0'; + + horizontal_sync <= '1' when video_address(5 downto 2) = "1110" else '0'; + vertical_sync <= '1' when video_address(13 downto 9) = "11111" else '0'; + + ------------------------------------------------------------------- + -- LED numeric display + + process(clock) + begin + if rising_edge(clock) then + led_counter <= led_counter + 1; + end if; + end process; + + led_digit_index <= led_counter(15 downto 14); + + with led_digit_index select + led_anode <= "1110" when "00", + "1101" when "01", + "1011" when "10", + "0111" when "11", + "1111" when others; + + with led_digit_index select + led_bcd_in_digit <= led_bcd_in( 3 downto 0) when "00", + led_bcd_in( 7 downto 4) when "01", + led_bcd_in(11 downto 8) when "10", + led_bcd_in(15 downto 12) when "11", + "XXXX" when others; + +-- bcd_demux: led_decoder +-- port map( +-- input => led_bcd_in_digit, +-- output => led_segment +-- ); + + led_dp <= '1'; + +end Behavioral; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd new file mode 100755 index 00000000..cd1cabaf --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/robotron_cpu_test.vhd @@ -0,0 +1,363 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga 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. +-- +-- robotron-fpga 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 robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity robotron_cpu_test is +end robotron_cpu_test; + +architecture behavior of robotron_cpu_test is + + component robotron_cpu + port( + CLK : in std_logic; + + -- MC6809E interface + A : in std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0); + RESET_N : out std_logic; + NMI_N : out std_logic; + FIRQ_N : out std_logic; + IRQ_N : out std_logic; + LIC : in std_logic; + AVMA : in std_logic; + R_W_N : in std_logic; + TSC : out std_logic; + HALT_N : out std_logic; + BA : in std_logic; + BS : in std_logic; + BUSY : in std_logic; + E : out std_logic; + Q : out std_logic; + + -- RAM and flash memories + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDB : inout std_logic_vector(15 downto 0); + + -- 7-segment display + SEG : out std_logic_vector(6 downto 0); + DP : out std_logic; + AN : out std_logic_vector(3 downto 0); + + -- LEDs + LED : out std_logic_vector(7 downto 0); + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + + -- VGA + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic + ); + end component; + + constant CLK_frequency : real := 48.0e6; + constant CLK_period : time := 1 sec / CLK_frequency; + + signal CLK : std_logic := '0'; + + signal A : std_logic_vector(15 downto 0) := (others => '0'); + signal D : std_logic_vector(7 downto 0); + signal RESET_N : std_logic := '1'; + signal NMI_N : std_logic := '1'; + signal FIRQ_N : std_logic := '1'; + signal IRQ_N : std_logic := '1'; + signal LIC : std_logic := '0'; + signal AVMA : std_logic := '0'; + signal R_W_N : std_logic := '0'; + signal TSC : std_logic := '0'; + signal HALT_N : std_logic := '1'; + signal BA : std_logic := '0'; + signal BS : std_logic := '0'; + signal BUSY : std_logic := '0'; + signal E : std_logic := '0'; + signal Q : std_logic := '0'; + + signal MemOE : std_logic; + signal MemWR : std_logic; + + signal RamAdv : std_logic; + signal RamCS : std_logic; + signal RamClk : std_logic; + signal RamCRE : std_logic; + signal RamLB : std_logic; + signal RamUB : std_logic; + signal RamWait : std_logic; + + signal FlashRp : std_logic; + signal FlashCS : std_logic; + signal FlashStSts : std_logic; + + signal MemAdr : std_logic_vector(23 downto 1); + signal MemDB : std_logic_vector(15 downto 0); + + signal SEG : std_logic_vector(6 downto 0); + signal DP : std_logic; + signal AN : std_logic_vector(3 downto 0); + + signal LED : std_logic_vector(7 downto 0); + + signal SW : std_logic_vector(7 downto 0) := (others => '0'); + + signal BTN : std_logic_vector(3 downto 0) := (others => '0'); + + signal vgaRed : std_logic_vector(2 downto 0); + signal vgaGreen : std_logic_vector(2 downto 0); + signal vgaBlue : std_logic_vector(1 downto 0); + signal Hsync : std_logic; + signal Vsync : std_logic; + + ------------------------------------------------------------------- + + signal bus_address : std_logic_vector(15 downto 0) := (others => '1'); + signal bus_read : std_logic := '1'; + signal bus_data : std_logic_vector(7 downto 0) := (others => 'Z'); + signal bus_available: std_logic := 'Z'; + signal bus_status : std_logic := 'Z'; + +begin + + uut: robotron_cpu PORT MAP ( + CLK => CLK, + A => A, + D => D, + RESET_N => RESET_N, + NMI_N => NMI_N, + FIRQ_N => FIRQ_N, + IRQ_N => IRQ_N, + LIC => LIC, + AVMA => AVMA, + R_W_N => R_W_N, + TSC => TSC, + HALT_N => HALT_N, + BA => BA, + BS => BS, + BUSY => BUSY, + E => E, + Q => Q, + MemOE => MemOE, + MemWR => MemWR, + RamAdv => RamAdv, + RamCS => RamCS, + RamClk => RamClk, + RamCRE => RamCRE, + RamLB => RamLB, + RamUB => RamUB, + RamWait => RamWait, + FlashRp => FlashRp, + FlashCS => FlashCS, + FlashStSts => FlashStSts, + MemAdr => MemAdr, + MemDB => MemDB, + SEG => SEG, + DP => DP, + AN => AN, + LED => LED, + SW => SW, + BTN => BTN, + vgaRed => vgaRed, + vgaGreen => vgaGreen, + vgaBlue => vgaBlue, + Hsync => Hsync, + Vsync => Vsync + ); + + CLK_process :process + begin + CLK <= '0'; + wait for CLK_period/2; + CLK <= '1'; + wait for CLK_period/2; + end process; + + bus_process: process + begin + wait until falling_edge(E); + + -- E=0 + 0 ns + wait for 20 ns; + R_W_N <= 'U'; + A <= (others => 'U'); + BA <= 'U'; + BS <= 'U'; + + -- E=0 + 20 ns + wait for 10 ns; + D <= (others => 'Z'); + + -- E=0 + 30 ns + wait for 170 ns; + + if bus_available = '0' then + R_W_N <= bus_read; + A <= bus_address; + else + R_W_N <= 'Z'; + A <= (others => 'Z'); + end if; + + BA <= bus_available; + BS <= bus_status; + + -- E=0 + 200 ns + wait until rising_edge(Q); + + -- Q=1 + wait for 200 ns; + + -- Q=1 + 200 ns + if bus_available = '0' then + if bus_read = '0' then + D <= bus_data; + end if; + end if; + end process; + + stim_proc: process + begin + BTN(0) <= '1'; + wait for 100 ns; + BTN(0) <= '0'; + + wait until rising_edge(RESET_N); + + wait until falling_edge(E); + bus_available <= '0'; + bus_status <= '0'; + + bus_address <= X"FFFE"; + bus_read <= '1'; + bus_data <= (others => 'Z'); + + wait until falling_edge(E); + bus_address <= X"9000"; + bus_read <= '1'; + bus_data <= (others => 'Z'); + + wait until falling_edge(E); + bus_address <= X"0000"; + bus_read <= '0'; + bus_data <= X"69"; + + -- Turn on ROM PIA CA2 + wait until falling_edge(E); + bus_address <= X"C80D"; + bus_read <= '0'; + bus_data <= X"3C"; + + -- IDLE + wait until falling_edge(E); + bus_address <= (others => 'Z'); + bus_read <= '1'; + bus_data <= (others => 'Z'); + + -- Turn off ROM PIA CA2 + wait until falling_edge(E); + bus_address <= X"C80D"; + bus_read <= '0'; + bus_data <= X"34"; + + -- Write BLT + wait until falling_edge(E); + bus_address <= X"CA02"; + bus_read <= '0'; + bus_data <= X"D0"; + + wait until falling_edge(E); + bus_address <= X"CA03"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA04"; + bus_read <= '0'; + bus_data <= X"33"; + + wait until falling_edge(E); + bus_address <= X"CA05"; + bus_read <= '0'; + bus_data <= X"44"; + + wait until falling_edge(E); + bus_address <= X"CA06"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA07"; + bus_read <= '0'; + bus_data <= X"00"; + + wait until falling_edge(E); + bus_address <= X"CA00"; + bus_read <= '0'; + bus_data <= X"01"; + + -- IDLE + wait until falling_edge(E); + bus_address <= (others => 'Z'); + bus_read <= '1'; + bus_data <= (others => 'Z'); + + -- HALT should assert from BLT. + wait until falling_edge(E); + wait until falling_edge(E); + + wait until falling_edge(E); + -- Release bus to BLT. + bus_status <= '1'; + bus_available <= '1'; + + -- HALT should deassert from BLT. + wait until falling_edge(E); + wait until falling_edge(E); + wait until falling_edge(E); + + wait; + end process; + +end; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd new file mode 100644 index 00000000..e3269afb --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1.vhd @@ -0,0 +1,240 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga 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. +-- +-- robotron-fpga 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 robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +-- This entity models a pair of Williams SC1 pixel BLTter ICs. +-- The interface is modified to be more conducive to synchronous +-- FPGA implementation. +-- Dec 2018 changes for SC1 or SC2 and 0 address error (DW oldgit) + +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + +entity sc1 is +port( + clk : in std_logic; + sc2 : in std_logic; + + reg_cs : in std_logic; + reg_data_in : in std_logic_vector( 7 downto 0); + rs : in std_logic_vector( 2 downto 0); + + halt : out boolean; + halt_ack : in boolean; + + blt_ack : in std_logic; + + blt_rd : out boolean; + blt_wr : out boolean; + + blt_address_out : out std_logic_vector(15 downto 0); + blt_data_in : in std_logic_vector( 7 downto 0); + blt_data_out : out std_logic_vector( 7 downto 0); + + en_upper : out boolean; + en_lower : out boolean +); +end sc1; + +architecture RTL of sc1 is + + type state_t is (state_idle, state_wait_for_halt, state_src, state_dst); + + -- control attributes + signal ctrl_span_src : std_logic := '0'; + signal ctrl_span_dst : std_logic := '0'; + signal ctrl_slow : std_logic := '0'; + signal ctrl_foreground : std_logic := '0'; + signal ctrl_solid : std_logic := '0'; + signal ctrl_shift : std_logic := '0'; + signal ctrl_no_lower : std_logic := '0'; + signal ctrl_no_upper : std_logic := '0'; + + -- 0: Run register + signal reg_ctrl : std_logic_vector( 7 downto 0) := (others => '0'); + -- 1: solid value + signal reg_solid : std_logic_vector( 7 downto 0) := (others => '0'); + -- 2, 3: source address + signal reg_src_base : std_logic_vector(15 downto 0) := (others => '0'); + -- 4, 5: destination address + signal reg_dst_base : std_logic_vector(15 downto 0) := (others => '0'); + -- 6: width + signal reg_width : std_logic_vector( 7 downto 0) := (others => '0'); + -- 7: height + signal reg_height : std_logic_vector( 7 downto 0) := (others => '0'); + + -- Internal + signal state : state_t := state_idle; + + signal blt_src_data : std_logic_vector( 7 downto 0) := (others => '0'); + signal blt_shift : std_logic_vector( 3 downto 0) := (others => '0'); + + signal src_address : std_logic_vector(15 downto 0) := (others => '0'); + signal dst_address : std_logic_vector(15 downto 0) := (others => '0'); + + signal x_count : std_logic_vector( 7 downto 0) := (others => '0'); + signal x_count_next : std_logic_vector( 7 downto 0) := (others => '0'); + signal y_count : std_logic_vector( 7 downto 0) := (others => '0'); + signal y_count_next : std_logic_vector( 7 downto 0) := (others => '0'); + + signal xorval : std_logic_vector( 7 downto 0) := (others => '0'); + +begin + -- SC1 had a bug so values had to be xored with 0X04, SC2 fixed the bug so no xor required + xorval <= x"04" when sc2='0' else x"00"; + + halt <= not (state = state_idle); + blt_rd <= (state = state_src); + blt_wr <= (state = state_dst); + + blt_address_out <= dst_address when (state = state_dst) else src_address; + + en_upper <= (state = state_src) or (not (ctrl_no_upper = '1' or (ctrl_foreground = '1' and blt_src_data(7 downto 4) = x"0") )); + en_lower <= (state = state_src) or (not (ctrl_no_lower = '1' or (ctrl_foreground = '1' and blt_src_data(3 downto 0) = x"0") )); + + blt_data_out <= reg_solid when ctrl_solid = '1' else blt_src_data; + + x_count_next <= x_count + 1; + y_count_next <= y_count + 1; + + -- break out control reg into individual signals + ctrl_no_upper <= reg_ctrl(7); + ctrl_no_lower <= reg_ctrl(6); + ctrl_shift <= reg_ctrl(5); + ctrl_solid <= reg_ctrl(4); + ctrl_foreground <= reg_ctrl(3); + --ctrl_slow <= reg_ctrl(2); + ctrl_span_dst <= reg_ctrl(1); + ctrl_span_src <= reg_ctrl(0); + + -- register access + process(clk) + begin + if rising_edge(clk) then + if reg_cs = '1' then + case rs is + -- 0: Start BLT with control attributes + when "000" => reg_ctrl <= reg_data_in; + -- 1: mask + when "001" => reg_solid <= reg_data_in; + -- 2: source address high + when "010" => reg_src_base(15 downto 8) <= reg_data_in; + -- 3: source address low + when "011" => reg_src_base( 7 downto 0) <= reg_data_in; + -- 4: destination address high + when "100" => reg_dst_base(15 downto 8) <= reg_data_in; + -- 5: destination address low + when "101" => reg_dst_base( 7 downto 0) <= reg_data_in; + -- 6: width + when "110" => reg_width <= reg_data_in xor xorval; + -- 7: height + when "111" => reg_height <= reg_data_in xor xorval; + -- Do nothing. + when others => null; + end case; + end if; + end if; + end process; + + -- state machine + process(clk) + begin + if rising_edge(clk) then + case state is + when state_idle => + if reg_cs = '1' and rs = "000" then + state <= state_wait_for_halt; + end if; + + when state_wait_for_halt => + if halt_ack then + src_address <= reg_src_base; + dst_address <= reg_dst_base; + + x_count <= (others => '0'); + y_count <= (others => '0'); + blt_shift <= (others => '0'); + + state <= state_src; + end if; + + when state_src => + if blt_ack = '1' then + if ctrl_shift = '0' then + -- unshifted + blt_src_data <= blt_data_in; + else + -- shifted right one pixel + blt_shift <= blt_data_in( 3 downto 0); + blt_src_data <= blt_shift & blt_data_in( 7 downto 4); + end if; + state <= state_dst; + end if; + + when state_dst => + if blt_ack = '1' then + state <= state_src; + + if x_count_next < reg_width then + x_count <= x_count_next; + + if ctrl_span_src = '1' then + src_address <= src_address + 256; + else + src_address <= src_address + 1; + end if; + + if ctrl_span_dst = '1' then + dst_address <= dst_address + 256; + else + dst_address <= dst_address + 1; + end if; + else + x_count <= (others => '0'); + y_count <= y_count_next; + + if y_count_next = reg_height then + state <= state_idle; + end if; + + if ctrl_span_src = '1' then + src_address <= reg_src_base + y_count_next; + else + src_address <= src_address + 1; + end if; + + if ctrl_span_dst = '1' then + dst_address <= reg_dst_base + y_count_next; + else + dst_address <= dst_address + 1; + end if; + + end if; + end if; + -- Do nothing. + when others => null; + end case; + end if; + end process; +end RTL; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd new file mode 100755 index 00000000..6433d45b --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_cpu/sc1_tb.vhd @@ -0,0 +1,160 @@ +----------------------------------------------------------------------- +-- +-- Copyright 2012 ShareBrained Technology, Inc. +-- +-- This file is part of robotron-fpga. +-- +-- robotron-fpga 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. +-- +-- robotron-fpga 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 robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +entity sc1_tb is +end sc1_tb; + +architecture behavior of sc1_tb is + + component sc1 + port( + clk : in std_logic; + reset : in std_logic; + e_sync : in std_logic; + reg_cs : in std_logic; + reg_data_in : in std_logic_vector(7 downto 0); + rs : in std_logic_vector(2 downto 0); + halt : out boolean; + halt_ack : in boolean; + blt_ack : in std_logic; + blt_address_out : out std_logic_vector(15 downto 0); + read : out boolean; + write : out boolean; + blt_data_in : in std_logic_vector(7 downto 0); + blt_data_out : out std_logic_vector(7 downto 0); + en_upper : out boolean; + en_lower : out boolean + ); + end component; + + signal clk : std_logic := '0'; + signal reset : std_logic := '0'; + signal e_sync : std_logic := '0'; + signal reg_cs : std_logic := '0'; + signal reg_data_in : std_logic_vector(7 downto 0) := (others => '0'); + signal rs : std_logic_vector(2 downto 0) := (others => '0'); + signal halt : boolean := false; + signal halt_ack : boolean := false; + signal blt_ack : std_logic := '0'; + signal blt_address_out : std_logic_vector(15 downto 0); + signal read : boolean := false; + signal write : boolean := false; + signal blt_data_in : std_logic_vector(7 downto 0) := (others => '0'); + signal blt_data_out : std_logic_vector(7 downto 0); + signal en_upper : boolean; + signal en_lower : boolean; + + constant clk_period : time := 83.333333 ns; + +begin + + uut: sc1 + port map( + clk => clk, + reset => reset, + e_sync => e_sync, + reg_cs => reg_cs, + reg_data_in => reg_data_in, + rs => rs, + halt => halt, + halt_ack => halt_ack, + blt_ack => blt_ack, + blt_address_out => blt_address_out, + read => read, + write => write, + blt_data_in => blt_data_in, + blt_data_out => blt_data_out, + en_upper => en_upper, + en_lower => en_lower + ); + + clk_process: process + begin + clk <= '0'; + wait for clk_period/2; + + clk <= '1'; + wait for clk_period/2; + end process; + + stim_proc: process + begin + e_sync <= '1'; + + wait until rising_edge(clk); + rs <= "010"; + reg_data_in <= X"11"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "011"; + reg_data_in <= X"22"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "100"; + reg_data_in <= X"33"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "101"; + reg_data_in <= X"44"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "110"; + reg_data_in <= X"00"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "111"; + reg_data_in <= X"00"; + reg_cs <= '1'; + + wait until rising_edge(clk); + rs <= "000"; + reg_data_in <= "00000001"; + reg_cs <= '1'; + + wait until rising_edge(clk); + reg_cs <= '0'; + + wait until halt = true; + halt_ack <= true; + + wait until rising_edge(clk); + blt_ack <= '1'; + blt_data_in <= X"69"; + + wait until halt = false; + blt_ack <= '0'; + halt_ack <= false; + + wait; + end process; + +end; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd new file mode 100644 index 00000000..99769a4f --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/robotron_soc.vhd @@ -0,0 +1,262 @@ +----------------------------------------------------------------------- +-- +-- A SOC-like top-level for robotron-fpga +-- (C) 2020 Slingshot +-- +-- MC6809 Cycle-Accurate 6809 Core +-- (c) 2016, Greg Miller +-- +-- Defender sound board by Dar (darfpga@aol.fr) +-- +-- robotron-fpga 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. +-- +-- robotron-fpga 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 robotron-fpga. If not, see +-- . +-- +----------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity robotron_soc is +port ( + clock : in std_logic; -- 12MHz + clock_snd : in std_logic; -- 0.89MHz + + -- Cellular RAM / StrataFlash + MemOE : out std_logic; + MemWR : out std_logic; + + RamAdv : out std_logic; + RamCS : out std_logic; + RamClk : out std_logic; + RamCRE : out std_logic; + RamLB : out std_logic; + RamUB : out std_logic; + RamWait : in std_logic; + + FlashRp : out std_logic; + FlashCS : out std_logic; + FlashStSts : in std_logic; + + MemAdr : out std_logic_vector(23 downto 1); + MemDin : out std_logic_vector(15 downto 0); + MemDout : in std_logic_vector(15 downto 0); + + blitter_sc2 : in std_logic; + sinistar : in std_logic; + + -- Switches + SW : in std_logic_vector(7 downto 0); + + -- Buttons + BTN : in std_logic_vector(3 downto 0); + SIN_FIRE : in std_logic; + SIN_BOMB : in std_logic; + + -- VGA connector + vgaRed : out std_logic_vector(2 downto 0); + vgaGreen : out std_logic_vector(2 downto 0); + vgaBlue : out std_logic_vector(1 downto 0); + Hsync : out std_logic; + Vsync : out std_logic; + + -- Audio + audio_out : out std_logic_vector(7 downto 0); + + -- 12-pin connectors + JA : in std_logic_vector(7 downto 0); + JB : in std_logic_vector(7 downto 0); + + dl_clock : in std_logic; + dl_addr : in std_logic_vector(15 downto 0); + dl_data : in std_logic_vector(7 downto 0); + dl_wr : in std_logic +); +end robotron_soc; + +architecture Behavioral of robotron_soc is + +component mc6809i is +port ( + D : in std_logic_vector( 7 downto 0); + Dout : out std_logic_vector( 7 downto 0); + ADDR : out std_logic_vector(15 downto 0); + RnW : out std_logic; + E : in std_logic; + Q : in std_logic; + BS : out std_logic; + BA : out std_logic; + nIRQ : in std_logic := '1'; + nFIRQ : in std_logic := '1'; + nNMI : in std_logic := '1'; + AVMA : out std_logic; + BUSY : out std_logic; + LIC : out std_logic; + nHALT : in std_logic := '1'; + nRESET : in std_logic := '1'; + nDMABREQ : in std_logic := '1' +); +end component mc6809i; + +signal cpu_a : std_logic_vector(15 downto 0); +signal cpu_dout : std_logic_vector( 7 downto 0); +signal cpu_din : std_logic_vector( 7 downto 0); +signal cpu_reset_n : std_logic; +signal cpu_nmi_n : std_logic; +signal cpu_firq_n : std_logic; +signal cpu_irq_n : std_logic; +signal cpu_lic : std_logic; +signal cpu_avma : std_logic; +signal cpu_rwn : std_logic; +signal cpu_halt_n : std_logic; +signal cpu_ba : std_logic; +signal cpu_bs : std_logic; +signal cpu_busy : std_logic; +signal cpu_e : std_logic; +signal cpu_q : std_logic; + +signal hand : std_logic; +signal select_sound : std_logic_vector( 5 downto 0); + +signal snd_addr : std_logic_vector(11 downto 0); +signal snd_do : std_logic_vector( 7 downto 0); +signal snd_rom_we : std_logic; + +begin + +mc6809: mc6809i +port map ( + ADDR => cpu_a, + Dout => cpu_dout, + D => cpu_din, + nReset => cpu_reset_n, + nNMI => cpu_nmi_n, + nFIRQ => cpu_firq_n, + nIRQ => cpu_irq_n, + LIC => cpu_lic, + AVMA => cpu_avma, + RnW => cpu_rwn, + nHALT => cpu_halt_n, + BA => cpu_ba, + BS => cpu_bs, + BUSY => cpu_busy, + E => cpu_e, + Q => cpu_q +); + +cpu_board: entity work.robotron_cpu +port map ( + clock => clock, + blitter_sc2 => blitter_sc2, + sinistar => sinistar, + + A => cpu_a, + Dout => cpu_dout, + Din => cpu_din, + RESET_N => cpu_reset_n, + NMI_N => cpu_nmi_n, + FIRQ_N => cpu_firq_n, + IRQ_N => cpu_irq_n, + LIC => cpu_lic, + AVMA => cpu_avma, + R_W_N => cpu_rwn, + TSC => open, + HALT_N => cpu_halt_n, + BA => cpu_ba, + BS => cpu_bs, + BUSY => cpu_busy, + E => cpu_e, + Q => cpu_q, + + -- Cellular RAM / StrataFlash + MemOE => MemOE, + MemWR => MemWR, + + RamAdv => RamAdv, + RamCS => RamCS, + RamClk => RamClk, + RamCRE => RamCRE, + RamLB => RamLB, + RamUB => RamUB, + RamWait => RamWait, + + FlashRp => FlashRp, + FlashCS => FlashCS, + FlashStSts => FlashStSts, + + MemAdr => MemAdr, + MemDin => MemDin, + MemDout => MemDout, + + -- 7-segment display +-- SEG => SEG, +-- DP => DP, +-- AN => AN, + + -- LEDs +-- LED => LED, + + -- Switches + SW => SW, + + -- Buttons + BTN => BTN, + SIN_FIRE => SIN_FIRE, + SIN_BOMB => SIN_BOMB, + + -- VGA connector + vgaRed => vgaRed, + vgaGreen => vgaGreen, + vgaBlue => vgaBlue, + Hsync => Hsync, + Vsync => Vsync, + + -- 12-pin connectors + JA => JA, + JB => JB, + + -- Sound board + PB => select_sound, + HAND => hand +); + +snd_rom : entity work.dpram +generic map( dWidth => 8, aWidth => 12) +port map( + clk_a => clock_snd, + addr_a => snd_addr, + q_a => snd_do, + clk_b => dl_clock, + we_b => snd_rom_we, + addr_b => dl_addr(11 downto 0), + d_b => dl_data +); + +snd_rom_we <= '1' when dl_wr = '1' and dl_addr(15 downto 12) = x"C" else '0'; -- C000-CFFF + +-- sound board +defender_sound_board : entity work.defender_sound_board +port map( + clk_0p89 => clock_snd, + reset => not cpu_reset_n, + hand => hand, + select_sound => select_sound, + audio_out => audio_out, + rom_addr => snd_addr, + rom_do => snd_do +); + +end Behavioral; diff --git a/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv new file mode 100644 index 00000000..55c8b97d --- /dev/null +++ b/Arcade_MiST/Williams 6809 rev.1 Hardware/Robotron-FPGA/rtl/sdram.sv @@ -0,0 +1,253 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + input clkref, + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output [15:0] port1_q, + + input [17:1] cpu1_addr, + input [15:0] cpu1_d, + output reg [15:0] cpu1_q, + input cpu1_oe, + input cpu1_we, + input [1:0] cpu1_ds +); + +parameter MHZ = 80; // 80 MHz default clock, adjust to calculate the refresh rate correctly + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us -> 842 cycles@108MHz +localparam RFRSH_CYCLES = 16'd78*MHZ/10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine + 1 word burst, CL2 +cmd issued registered + 0 RAS0 + 1 + 2 CAS0 + 3 + 4 + 5 + 6 data ready + 7 +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd3; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY; // CAS phase - 3 +localparam STATE_READ0 = STATE_CAS0 + CAS_LATENCY + 2'd2; // 6 +localparam STATE_LAST = 3'd7; + +reg [2:0] t; + +always @(posedge clk) begin + reg clkref_d; + clkref_d <= clkref; + + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; + if (~clkref_d & clkref) t <= 3'd1; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch; +reg [24:1] addr_latch_next; +reg [15:0] din_latch; +reg oe_latch; +reg we_latch; +reg [1:0] ds; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_REQ = 2'd2; + +reg [2:0] next_port; +reg [2:0] port; +reg port1_state; + +// PORT1 +always @(*) begin + if (port1_req ^ port1_state) begin + next_port = PORT_REQ; + addr_latch_next = { 1'b0, port1_a }; + end else if (cpu1_oe | cpu1_we) begin + next_port = PORT_CPU1; + addr_latch_next = { 7'd0, cpu1_addr }; + end else begin + next_port = PORT_NONE; + addr_latch_next = addr_latch; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + if(t == STATE_RAS0) begin + addr_latch <= addr_latch_next; + port <= next_port; + { oe_latch, we_latch } <= 2'b00; + + if (next_port != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[22:10]; + SDRAM_BA <= addr_latch_next[24:23]; + if (next_port == PORT_REQ) begin + { oe_latch, we_latch } <= { ~port1_we, port1_we }; + ds <= port1_ds; + din_latch <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch, we_latch } <= { cpu1_oe, cpu1_we }; + din_latch <= cpu1_d; + ds <= cpu1_ds; + end + end else begin + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch || oe_latch)) begin + sd_cmd <= we_latch?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds; + if (we_latch) begin + SDRAM_DQ <= din_latch; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[9:1] }; // auto precharge + SDRAM_BA <= addr_latch[24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch) begin + case(port) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + default: ; + endcase; + end + end +end + +endmodule