From c97f2d02568a3aa717de2377a9bef556bbebf3ec Mon Sep 17 00:00:00 2001 From: Gehstock Date: Sun, 23 Sep 2018 18:32:01 +0200 Subject: [PATCH] All Coleco Vision --- Coleco - Vision_MiST/ColecoVision_MiST.qpf | 29 + Coleco - Vision_MiST/ColecoVision_MiST.qsf | 238 + Coleco - Vision_MiST/ColecoVision_MiST.srf | 9 + Coleco - Vision_MiST/README.txt | 3 + .../Snapshot/ColecoVision_MiST.rbf | Bin 0 -> 273250 bytes Coleco - Vision_MiST/clean.bat | 38 + Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv | 423 ++ .../rtl/ColecoVision_MiST.sv.bak | 84 + Coleco - Vision_MiST/rtl/T80/t80.vhd | 1094 ++++ Coleco - Vision_MiST/rtl/T80/t80_alu.vhd | 362 ++ Coleco - Vision_MiST/rtl/T80/t80_mcode.vhd | 2014 +++++++ Coleco - Vision_MiST/rtl/T80/t80_pack.vhd | 212 + Coleco - Vision_MiST/rtl/T80/t80_reg.vhd | 105 + Coleco - Vision_MiST/rtl/T80/t80a.vhd | 286 + Coleco - Vision_MiST/rtl/build_id.tcl | 35 + Coleco - Vision_MiST/rtl/build_id.v | 2 + Coleco - Vision_MiST/rtl/cart.qip | 3 + Coleco - Vision_MiST/rtl/cart.v | 172 + Coleco - Vision_MiST/rtl/clocks.vhd | 125 + Coleco - Vision_MiST/rtl/colecovision.vhd | 435 ++ Coleco - Vision_MiST/rtl/colecovision.vhd.bak | 478 ++ Coleco - Vision_MiST/rtl/cvBios.vhd | 169 + Coleco - Vision_MiST/rtl/cv_ctrl.vhd | 152 + Coleco - Vision_MiST/rtl/dac.vhd | 71 + Coleco - Vision_MiST/rtl/dpSDRAM64Mb.vhd | 371 ++ Coleco - Vision_MiST/rtl/hq2x.sv | 454 ++ Coleco - Vision_MiST/rtl/keyboard.vhd | 206 + Coleco - Vision_MiST/rtl/mist_io.v | 496 ++ Coleco - Vision_MiST/rtl/osd.v | 179 + Coleco - Vision_MiST/rtl/pll.qip | 4 + Coleco - Vision_MiST/rtl/pll.v | 393 ++ Coleco - Vision_MiST/rtl/pll.vhd.bak | 424 ++ Coleco - Vision_MiST/rtl/ps2kbd.vhd | 202 + Coleco - Vision_MiST/rtl/ps2kbd_pkg.vhd | 140 + .../rtl/roms/COLECO-SHORT-DELAY.BIO | Bin 0 -> 8192 bytes Coleco - Vision_MiST/rtl/roms/COLECO.BIO | Bin 0 -> 8192 bytes Coleco - Vision_MiST/rtl/roms/CVbios.hex | 258 + Coleco - Vision_MiST/rtl/roms/ONYX.BIO | Bin 0 -> 8192 bytes Coleco - Vision_MiST/rtl/roms/coleco29.asm | 4939 +++++++++++++++++ Coleco - Vision_MiST/rtl/scandoubler.v | 183 + Coleco - Vision_MiST/rtl/sn76489/COPYING | 340 ++ Coleco - Vision_MiST/rtl/sn76489/README | 143 + .../rtl/sn76489/sn76489_attenuator.vhd | 114 + .../rtl/sn76489/sn76489_clock_div.vhd | 134 + .../rtl/sn76489/sn76489_comp_pack.vhd | 96 + .../rtl/sn76489/sn76489_latch_ctrl.vhd | 138 + .../rtl/sn76489/sn76489_noise.vhd | 281 + .../rtl/sn76489/sn76489_tone.vhd | 189 + .../rtl/sn76489/sn76489_top.vhd | 197 + .../rtl/vdp18/vdp18_addr_mux.vhd | 228 + .../rtl/vdp18/vdp18_clk_gen.vhd | 154 + .../rtl/vdp18/vdp18_col_mux.vhd | 184 + .../rtl/vdp18/vdp18_col_pack-p.vhd | 83 + .../rtl/vdp18/vdp18_comp_pack-p.vhd | 205 + Coleco - Vision_MiST/rtl/vdp18/vdp18_core.vhd | 394 ++ .../rtl/vdp18/vdp18_core_comp_pack-p.vhd | 49 + .../rtl/vdp18/vdp18_cpuio.vhd | 572 ++ Coleco - Vision_MiST/rtl/vdp18/vdp18_ctrl.vhd | 410 ++ .../rtl/vdp18/vdp18_hor_vert.vhd | 243 + .../rtl/vdp18/vdp18_pack-p.vhd | 281 + .../rtl/vdp18/vdp18_pattern.vhd | 233 + .../rtl/vdp18/vdp18_sprite.vhd | 441 ++ Coleco - Vision_MiST/rtl/video_mixer.sv | 242 + 63 files changed, 20139 insertions(+) create mode 100644 Coleco - Vision_MiST/ColecoVision_MiST.qpf create mode 100644 Coleco - Vision_MiST/ColecoVision_MiST.qsf create mode 100644 Coleco - Vision_MiST/ColecoVision_MiST.srf create mode 100644 Coleco - Vision_MiST/README.txt create mode 100644 Coleco - Vision_MiST/Snapshot/ColecoVision_MiST.rbf create mode 100644 Coleco - Vision_MiST/clean.bat create mode 100644 Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv create mode 100644 Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv.bak create mode 100644 Coleco - Vision_MiST/rtl/T80/t80.vhd create mode 100644 Coleco - Vision_MiST/rtl/T80/t80_alu.vhd create mode 100644 Coleco - Vision_MiST/rtl/T80/t80_mcode.vhd create mode 100644 Coleco - Vision_MiST/rtl/T80/t80_pack.vhd create mode 100644 Coleco - Vision_MiST/rtl/T80/t80_reg.vhd create mode 100644 Coleco - Vision_MiST/rtl/T80/t80a.vhd create mode 100644 Coleco - Vision_MiST/rtl/build_id.tcl create mode 100644 Coleco - Vision_MiST/rtl/build_id.v create mode 100644 Coleco - Vision_MiST/rtl/cart.qip create mode 100644 Coleco - Vision_MiST/rtl/cart.v create mode 100644 Coleco - Vision_MiST/rtl/clocks.vhd create mode 100644 Coleco - Vision_MiST/rtl/colecovision.vhd create mode 100644 Coleco - Vision_MiST/rtl/colecovision.vhd.bak create mode 100644 Coleco - Vision_MiST/rtl/cvBios.vhd create mode 100644 Coleco - Vision_MiST/rtl/cv_ctrl.vhd create mode 100644 Coleco - Vision_MiST/rtl/dac.vhd create mode 100644 Coleco - Vision_MiST/rtl/dpSDRAM64Mb.vhd create mode 100644 Coleco - Vision_MiST/rtl/hq2x.sv create mode 100644 Coleco - Vision_MiST/rtl/keyboard.vhd create mode 100644 Coleco - Vision_MiST/rtl/mist_io.v create mode 100644 Coleco - Vision_MiST/rtl/osd.v create mode 100644 Coleco - Vision_MiST/rtl/pll.qip create mode 100644 Coleco - Vision_MiST/rtl/pll.v create mode 100644 Coleco - Vision_MiST/rtl/pll.vhd.bak create mode 100644 Coleco - Vision_MiST/rtl/ps2kbd.vhd create mode 100644 Coleco - Vision_MiST/rtl/ps2kbd_pkg.vhd create mode 100644 Coleco - Vision_MiST/rtl/roms/COLECO-SHORT-DELAY.BIO create mode 100644 Coleco - Vision_MiST/rtl/roms/COLECO.BIO create mode 100644 Coleco - Vision_MiST/rtl/roms/CVbios.hex create mode 100644 Coleco - Vision_MiST/rtl/roms/ONYX.BIO create mode 100644 Coleco - Vision_MiST/rtl/roms/coleco29.asm create mode 100644 Coleco - Vision_MiST/rtl/scandoubler.v create mode 100644 Coleco - Vision_MiST/rtl/sn76489/COPYING create mode 100644 Coleco - Vision_MiST/rtl/sn76489/README create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_attenuator.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_clock_div.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_comp_pack.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_latch_ctrl.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_noise.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_tone.vhd create mode 100644 Coleco - Vision_MiST/rtl/sn76489/sn76489_top.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_addr_mux.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_clk_gen.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_col_mux.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_col_pack-p.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_comp_pack-p.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_core.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_core_comp_pack-p.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_cpuio.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_ctrl.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_hor_vert.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_pack-p.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_pattern.vhd create mode 100644 Coleco - Vision_MiST/rtl/vdp18/vdp18_sprite.vhd create mode 100644 Coleco - Vision_MiST/rtl/video_mixer.sv diff --git a/Coleco - Vision_MiST/ColecoVision_MiST.qpf b/Coleco - Vision_MiST/ColecoVision_MiST.qpf new file mode 100644 index 00000000..44433ccb --- /dev/null +++ b/Coleco - Vision_MiST/ColecoVision_MiST.qpf @@ -0,0 +1,29 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version +# Date created = 12:51:57 September 10, 2018 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.0" +DATE = "12:51:57 September 10, 2018" + +# Revisions +PROJECT_REVISION = "ColecoVision_MiST" diff --git a/Coleco - Vision_MiST/ColecoVision_MiST.qsf b/Coleco - Vision_MiST/ColecoVision_MiST.qsf new file mode 100644 index 00000000..56b3846b --- /dev/null +++ b/Coleco - Vision_MiST/ColecoVision_MiST.qsf @@ -0,0 +1,238 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version +# Date created = 10:10:49 September 11, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# ColecoVision_MiST_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:07:56 MARCH 10, 2017" +set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_top.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_tone.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_noise.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_latch_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_comp_pack.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_clock_div.vhd +set_global_assignment -name VHDL_FILE rtl/sn76489/sn76489_attenuator.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_sprite.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_pattern.vhd +set_global_assignment -name VHDL_FILE "rtl/vdp18/vdp18_pack-p.vhd" +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_hor_vert.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_cpuio.vhd +set_global_assignment -name VHDL_FILE "rtl/vdp18/vdp18_core_comp_pack-p.vhd" +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_core.vhd +set_global_assignment -name VHDL_FILE "rtl/vdp18/vdp18_comp_pack-p.vhd" +set_global_assignment -name VHDL_FILE "rtl/vdp18/vdp18_col_pack-p.vhd" +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_col_mux.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_clk_gen.vhd +set_global_assignment -name VHDL_FILE rtl/vdp18/vdp18_addr_mux.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80a.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80_reg.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80_pack.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80_mcode.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80_alu.vhd +set_global_assignment -name VHDL_FILE rtl/T80/t80.vhd +set_global_assignment -name VHDL_FILE rtl/colecovision.vhd +set_global_assignment -name VHDL_FILE rtl/cv_ctrl.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ColecoVision_MiST.sv +set_global_assignment -name VHDL_FILE rtl/clocks.vhd +set_global_assignment -name VHDL_FILE rtl/cvBios.vhd +set_global_assignment -name VHDL_FILE rtl/dpSDRAM64Mb.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv +set_global_assignment -name VERILOG_FILE rtl/mist_io.v +set_global_assignment -name VERILOG_FILE rtl/osd.v +set_global_assignment -name VERILOG_FILE rtl/scandoubler.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv +set_global_assignment -name VHDL_FILE rtl/dac.vhd +set_global_assignment -name VHDL_FILE rtl/keyboard.vhd +set_global_assignment -name VHDL_FILE rtl/ps2kbd.vhd +set_global_assignment -name VHDL_FILE rtl/ps2kbd_pkg.vhd +set_global_assignment -name VERILOG_FILE rtl/pll.v +set_global_assignment -name QIP_FILE rtl/cart.qip + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY ColecoVision_MiST +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# start EDA_TOOL_SETTINGS(eda_simulation) +# --------------------------------------- + + # EDA Netlist Writer Assignments + # ============================== + set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation + +# end EDA_TOOL_SETTINGS(eda_simulation) +# ------------------------------------- + +# ------------------------------- +# start ENTITY(ColecoVision_MiST) + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top + set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top + set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(ColecoVision_MiST) +# ----------------------------- +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Coleco - Vision_MiST/ColecoVision_MiST.srf b/Coleco - Vision_MiST/ColecoVision_MiST.srf new file mode 100644 index 00000000..87f3faf9 --- /dev/null +++ b/Coleco - Vision_MiST/ColecoVision_MiST.srf @@ -0,0 +1,9 @@ +{ "" "" "" "Verilog HDL or VHDL warning at vdp18_ctrl.vhd(156): conditional expression evaluates to a constant" { } { } 0 10037 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL information at scandoubler.v(102): always construct contains both blocking and non-blocking assignments" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Output pins are stuck at VCC or GND" { } { } 0 13024 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Tri-state node(s) do not directly drive top-level pin(s)" { } { } 0 13046 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "5 hierarchies have connectivity warnings - see the Connectivity Checks report folder" { } { } 0 12241 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10273 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 13049 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 13410 "" 0 0 "Quartus II" 0 -1 0 ""} diff --git a/Coleco - Vision_MiST/README.txt b/Coleco - Vision_MiST/README.txt new file mode 100644 index 00000000..560080bb --- /dev/null +++ b/Coleco - Vision_MiST/README.txt @@ -0,0 +1,3 @@ +Coleco Vision Port to Mist FPGA by Gehstock + +32k Roms will not work at this Time \ No newline at end of file diff --git a/Coleco - Vision_MiST/Snapshot/ColecoVision_MiST.rbf b/Coleco - Vision_MiST/Snapshot/ColecoVision_MiST.rbf new file mode 100644 index 0000000000000000000000000000000000000000..63b9885e10a57a704144bb77cfc1b8db86e607d0 GIT binary patch literal 273250 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�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 PEd_Du|NV;-6Epu0W}i*{ literal 0 HcmV?d00001 diff --git a/Coleco - Vision_MiST/clean.bat b/Coleco - Vision_MiST/clean.bat new file mode 100644 index 00000000..748b4d5b --- /dev/null +++ b/Coleco - Vision_MiST/clean.bat @@ -0,0 +1,38 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +cd sys +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +cd .. +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del *.cdf +del *.rpt +del /s new_rtl_netlist +del /s old_rtl_netlist +pause diff --git a/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv b/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv new file mode 100644 index 00000000..ccafeb3b --- /dev/null +++ b/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv @@ -0,0 +1,423 @@ +module ColecoVision_MiST( + input CLOCK_27, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output LED, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + 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 "build_id.v" +localparam CONF_STR = +{ + "CVision;;", + "F,COLBINROM;", + "O23,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "O4,Switch Joystick,Off,On;", + "T6,Reset;", + "V,v1.0.",`BUILD_DATE +}; + + +wire clk_sys, clk_pix, clock_mem_s; +wire clock_vdp_en_s, clock_5m_en_s, clock_3m_en_s; +wire pll_locked_s; +wire reset_s = status[0] | status[6] | buttons[1] | ioctl_download; +wire [7:0]r, g, b; +wire hs, vs; +wire ypbpr; +wire [31:0]status; +wire scandoubler_disable; +wire [1:0] buttons, switches; +wire [7:0]audio; +assign SDRAM_A[12] = 1'b0; +assign LED = ~ioctl_download; +wire ioctl_download; +wire [7:0] ioctl_index; +wire ioctl_ce, ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; +wire [7:0] joy1, joy2; +wire [7:0] joya = status[4] ? joy2 : joy1; +wire [7:0] joyb = status[4] ? joy1 : joy2; +wire [1:0]ctrl_p1_s; +wire [1:0]ctrl_p2_s; +wire [1:0]ctrl_p3_s; +wire [1:0]ctrl_p4_s; +wire [1:0]ctrl_p5_s; +wire [1:0]ctrl_p6_s; +wire [1:0]ctrl_p7_s = 2'b11; +wire [1:0]ctrl_p8_s; +wire [1:0]ctrl_p9_s = 2'b11; +wire [14:0]cart_addr; +wire [7:0]cart_do; +wire cart_en_80_n_s; +wire cart_en_a0_n_s; +wire cart_en_c0_n_s; +wire cart_en_e0_n_s; +wire [10:0]ps2_key; +wire pressed = ps2_key[9]; +wire [8:0] code = ps2_key[8:0]; +wire [16:0]ram_addr_s;//128K ??? +wire [7:0]ram_do_s; +wire [7:0]ram_di_s; +wire ram_ce_s; +wire ram_oe_s; +wire ram_we_s; +wire [13:0]vram_addr_s;//16K +wire [7:0]vram_do_s; +wire [7:0]vram_di_s; +wire vram_ce_s; +wire vram_oe_s; +wire vram_we_s; + +pll pll ( + .inclk0 (CLOCK_27), + .c0 (clk_sys),//21.428571 + .c1 (clk_pix),//5.35714275 + .c2 (clock_mem_s),//100 MHz 0º + .c3 (SDRAM_CLK),// 100 MHz -90° + .locked (pll_locked_s) + ); + +clocks clocks ( + .clock_i (clk_sys), + .por_i (~pll_locked_s), + .clock_vdp_en_o(clock_vdp_en_s), + .clock_5m_en_o (clock_5m_en_s), + .clock_3m_en_o (clock_3m_en_s) + ); + +colecovision #( + .num_maq_g (5), + .compat_rgb_g (0)) +colecovision ( + .clock_i (clk_sys), + .clk_en_10m7_i (clock_vdp_en_s), + .clk_en_5m37_i (clock_5m_en_s), + .clk_en_3m58_i (clock_3m_en_s), + .reset_i (reset_s), + .por_n_i (pll_locked_s), +//Controller Interface + .ctrl_p1_i (ctrl_p1_s), + .ctrl_p2_i (ctrl_p2_s), + .ctrl_p3_i (ctrl_p3_s), + .ctrl_p4_i (ctrl_p4_s), + .ctrl_p5_o (ctrl_p5_s), + .ctrl_p6_i (ctrl_p6_s), + .ctrl_p7_i (ctrl_p7_s), + .ctrl_p8_o (ctrl_p8_s), + .ctrl_p9_i (ctrl_p9_s), +//CPU RAM Interface + .ram_addr_o (ram_addr_s), + .ram_ce_o (ram_ce_s), + .ram_we_o (ram_we_s), + .ram_oe_o (ram_oe_s), + .ram_data_i (ram_do_s), + .ram_data_o (ram_di_s), +//Video RAM Interface + .vram_addr_o (vram_addr_s), + .vram_ce_o (vram_ce_s), + .vram_oe_o (vram_oe_s), + .vram_we_o (vram_we_s), + .vram_data_i (vram_do_s), + .vram_data_o (vram_di_s), +//Cartridge ROM Interface + .cart_addr_o (cart_addr), + .cart_data_i (cart_do), + .cart_en_80_n_o (cart_en_80_n_s), + .cart_en_a0_n_o (cart_en_a0_n_s), + .cart_en_c0_n_o (cart_en_c0_n_s), + .cart_en_e0_n_o (cart_en_e0_n_s), +//Audio Interface + .audio_o (audio), +//RGB Video Interface + .col_o (), + .rgb_r_o (r), + .rgb_g_o (g), + .rgb_b_o (b), + .hsync_n_o (hs), + .vsync_n_o (vs), + .comp_sync_n_o (), +//DEBUG + .D_cpu_addr () + ); + +dac #( + .msbi_g (15)) +dac ( + .clk_i (clk_sys), + .res_i (reset_s), + .dac_i ({~audio[7], audio[6:0], 8'b00000000}), + .dac_o (AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + +dpSDRAM64Mb #( + .freq_g (100)) +dpSDRAM64Mb ( + .clock_i (clock_mem_s), + .reset_i (reset_s), + .refresh_i (1'b1), +//Port 0 + .port0_cs_i (vram_ce_s), + .port0_oe_i (vram_oe_s), + .port0_we_i (vram_we_s), + .port0_addr_i ({"000011111",vram_addr_s}), + .port0_data_i (vram_di_s), + .port0_data_o (vram_do_s), +//Port 1 + .port1_cs_i (ram_ce_s), + .port1_oe_i (ram_oe_s), + .port1_we_i (ram_we_s), + .port1_addr_i ({"000000",ram_addr_s}), + .port1_data_i (ram_di_s), + .port1_data_o (ram_do_s), +//SDRAM in board + .mem_cke_o (SDRAM_CKE), + .mem_cs_n_o (SDRAM_nCS), + .mem_ras_n_o (SDRAM_nRAS), + .mem_cas_n_o (SDRAM_nCAS), + .mem_we_n_o (SDRAM_nWE), + .mem_udq_o (SDRAM_DQMH), + .mem_ldq_o (SDRAM_DQML), + .mem_ba_o (SDRAM_BA), + .mem_addr_o (SDRAM_A[11:0]), + .mem_data_io (SDRAM_DQ) + ); + +cart cart ( + .clock(clk_sys), + .address(ioctl_download ? ioctl_addr[14:0] : cart_addr), + .data(ioctl_dout), + .wren(ioctl_wr), + .q(cart_do) + ); + + +always @(posedge clk_sys) begin + reg old_state; + old_state <= ps2_key[10]; + + if(old_state != ps2_key[10]) begin + casex(code) + 'hX75: btn_up <= pressed; + 'hX72: btn_down <= pressed; + 'hX6B: btn_left <= pressed; + 'hX74: btn_right <= pressed; + 'hX16: btn_1 <= pressed; // 1 + 'hX1E: btn_2 <= pressed; // 2 + 'hX26: btn_3 <= pressed; // 3 + 'hX15: btn_4 <= pressed; // q + 'hX1D: btn_5 <= pressed; // w + 'hX24: btn_6 <= pressed; // e + 'hX1C: btn_7 <= pressed; // a + 'hX1B: btn_8 <= pressed; // s + 'hX23: btn_9 <= pressed; // d + 'hX1A: btn_s <= pressed; // z + 'hX22: btn_0 <= pressed; // x + 'hX21: btn_p <= pressed; // c + 'hX1F: btn_pt <= pressed; // gui l + 'hX27: btn_pt <= pressed; // gui r + 'hX11: btn_bt <= pressed; // alt + + 'hX25: btn_4 <= pressed; // 4 + 'hX2E: btn_5 <= pressed; // 5 + 'hX36: btn_6 <= pressed; // 6 + 'hX3D: btn_7 <= pressed; // 7 + 'hX3E: btn_8 <= pressed; // 8 + 'hX46: btn_9 <= pressed; // 9 + 'hX45: btn_0 <= pressed; // 0 + + 'h012: btn_arm <= pressed; // shift l + 'h059: btn_arm <= pressed; // shift r + 'hX14: btn_fire <= pressed; // ctrl + endcase + end +end + +reg btn_up = 0; +reg btn_down = 0; +reg btn_left = 0; +reg btn_right = 0; +reg btn_1 = 0; +reg btn_2 = 0; +reg btn_3 = 0; +reg btn_4 = 0; +reg btn_5 = 0; +reg btn_6 = 0; +reg btn_7 = 0; +reg btn_8 = 0; +reg btn_9 = 0; +reg btn_s = 0; +reg btn_0 = 0; +reg btn_p = 0; +reg btn_pt = 0; +reg btn_bt = 0; +reg btn_arm = 0; +reg btn_fire = 0; + +wire m_right = btn_right | joya[0]; +wire m_left = btn_left | joya[1]; +wire m_down = btn_down | joya[2]; +wire m_up = btn_up | joya[3]; +wire m_fire = btn_fire | joya[4]; +wire m_arm = btn_arm | joya[5]; +wire m_1 = btn_1; +wire m_2 = btn_2; +wire m_3 = btn_3; +wire m_s = btn_s | joya[6]; +wire m_0 = btn_0; +wire m_p = btn_p | joya[7]; +wire m_pt = btn_pt; +wire m_bt = btn_bt; + +wire [0:19] keypad0 = {m_0,m_1,m_2, m_3,btn_4,btn_5, btn_6,btn_7,btn_8, btn_9,m_s,m_p, m_pt,m_bt,m_up, m_down,m_left,m_right, m_fire,m_arm}; +wire [0:19] keypad1 = {1'b0,1'b0,1'b0, 1'b0,1'b0,1'b0, 1'b0,1'b0,1'b0, 1'b0,joyb[6],joyb[7], 1'b0,1'b0,joyb[3], joyb[2],joyb[1],joyb[0], joyb[4],joyb[5]}; +wire [0:19] keypad[2] = '{keypad0,keypad1}; + +reg [3:0] ctrl1[2] = '{'0,'0}; +assign {ctrl_p1_s[0],ctrl_p2_s[0],ctrl_p3_s[0],ctrl_p4_s[0]} = ctrl1[0]; +assign {ctrl_p1_s[1],ctrl_p2_s[1],ctrl_p3_s[1],ctrl_p4_s[1]} = ctrl1[1]; + +localparam cv_key_0_c = 4'b0011; +localparam cv_key_1_c = 4'b1110; +localparam cv_key_2_c = 4'b1101; +localparam cv_key_3_c = 4'b0110; +localparam cv_key_4_c = 4'b0001; +localparam cv_key_5_c = 4'b1001; +localparam cv_key_6_c = 4'b0111; +localparam cv_key_7_c = 4'b1100; +localparam cv_key_8_c = 4'b1000; +localparam cv_key_9_c = 4'b1011; +localparam cv_key_asterisk_c = 4'b1010; +localparam cv_key_number_c = 4'b0101; +localparam cv_key_pt_c = 4'b0100; +localparam cv_key_bt_c = 4'b0010; +localparam cv_key_none_c = 4'b1111; + +generate + genvar i; + for (i = 0; i <= 1; i++) begin : ctl + always_comb begin + reg [3:0] ctl1, ctl2; + reg p61,p62; + + ctl1 = 4'b1111; + ctl2 = 4'b1111; + p61 = 1; + p62 = 1; + + if (~ctrl_p5_s[i]) begin + casex(keypad[i][0:13]) + 'b1xxxxxxxxxxxxx: ctl1 = cv_key_0_c; + 'b01xxxxxxxxxxxx: ctl1 = cv_key_1_c; + 'b001xxxxxxxxxxx: ctl1 = cv_key_2_c; + 'b0001xxxxxxxxxx: ctl1 = cv_key_3_c; + 'b00001xxxxxxxxx: ctl1 = cv_key_4_c; + 'b000001xxxxxxxx: ctl1 = cv_key_5_c; + 'b0000001xxxxxxx: ctl1 = cv_key_6_c; + 'b00000001xxxxxx: ctl1 = cv_key_7_c; + 'b000000001xxxxx: ctl1 = cv_key_8_c; + 'b0000000001xxxx: ctl1 = cv_key_9_c; + 'b00000000001xxx: ctl1 = cv_key_asterisk_c; + 'b000000000001xx: ctl1 = cv_key_number_c; + 'b0000000000001x: ctl1 = cv_key_pt_c; + 'b00000000000001: ctl1 = cv_key_bt_c; + 'b00000000000000: ctl1 = cv_key_none_c; + endcase + p61 = ~keypad[i][19]; // button 2 + end + + if (~ctrl_p8_s[i]) begin + ctl2 = ~keypad[i][14:17]; + p62 = ~keypad[i][18]; // button 1 + end + + ctrl1[i] = ctl1 & ctl2; + ctrl_p6_s[i] = p61 & p62; + end + end +endgenerate + + + +mist_io #( + .STRLEN ($size(CONF_STR)>>3) + ) +user_io ( + .clk_sys (clk_sys ), + .CONF_DATA0 (CONF_DATA0 ), + .SPI_SCK (SPI_SCK ), + .SPI_DI (SPI_DI ), + .SPI_DO (SPI_DO ), + .SPI_SS2 (SPI_SS2 ), + .conf_str (CONF_STR ), + .ypbpr (ypbpr ), + .status (status ), + .scandoubler_disable(scandoubler_disable), + .buttons (buttons ), + .switches (switches ), + .ps2_key (ps2_key ), + .joystick_0 (joy1 ), + .joystick_1 (joy2 ), + .ioctl_ce (ioctl_ce ), + .ioctl_wr (ioctl_wr ), + .ioctl_index (ioctl_index ), + .ioctl_download(ioctl_download), + .ioctl_addr (ioctl_addr ), + .ioctl_dout (ioctl_dout ) + ); + +video_mixer #( + .LINE_LENGTH (290 ), + .HALF_DEPTH (0 ) + ) +video_mixer ( + .clk_sys (clk_sys ), + .ce_pix (clk_pix ), + .ce_pix_actual (clk_pix ), + .SPI_SCK (SPI_SCK ), + .SPI_SS3 (SPI_SS3 ), + .SPI_DI (SPI_DI ), + .R (r[7:2]), + .G (g[7:2]), + .B (b[7:2]), + .HSync (hs ), + .VSync (vs ), + .VGA_R (VGA_R ), + .VGA_G (VGA_G ), + .VGA_B (VGA_B ), + .VGA_VS (VGA_VS ), + .VGA_HS (VGA_HS ), + .scanlines (scandoubler_disable ? 2'b00 : {status[3:2] == 3, status[3:2] == 2}), + .scandoubler_disable(scandoubler_disable), + .hq2x (status[3:2]==1), + .ypbpr (ypbpr ), + .ypbpr_full (1 ), + .line_start (0 ), + .mono (0 ) + ); + +endmodule \ No newline at end of file diff --git a/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv.bak b/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv.bak new file mode 100644 index 00000000..4b5e55ed --- /dev/null +++ b/Coleco - Vision_MiST/rtl/ColecoVision_MiST.sv.bak @@ -0,0 +1,84 @@ +module ColecoVision_MiST( + input CLOCK_27 + +); + +wire clock_master_s, clock_mem_s, sdram_clock_o; +wire pll_locked_s; + +pll pll ( + .inclk0 (CLOCK_27), + .c0 (clock_master_s),//21.428571 + .c1 (clock_mem_s),//100 MHz 0º + .c2 (sdram_clock_o),// 100 MHz -90° + .locked (pll_locked_s) + ); + +wire por_n_s; +wire clock_vdp_en_s, clock_5m_en_s, clock_3m_en_s; + +clocks clocks ( + .clock_i (clock_master_s), + .por_i (~por_n_s), + .clock_vdp_en_o(clock_vdp_en_s), + .clock_5m_en_o (clock_5m_en_s), + .clock_3m_en_o (clock_3m_en_s) + ); + +colecovision #( + .num_maq_g (5), + .compat_rgb_g (0)) +colecovision ( + .clock_i (clock_master_s), + .clk_en_10m7_i (clock_vdp_en_s), + .clk_en_5m37_i (clock_5m_en_s), + .clk_en_3m58_i (clock_3m_en_s), + .reset_i (reset_s), + .por_n_i (por_n_s), +//Controller Interface + .ctrl_p1_i => ctrl_p1_s, + .ctrl_p2_i => ctrl_p2_s, + .ctrl_p3_i => ctrl_p3_s, + .ctrl_p4_i => ctrl_p4_s, + .ctrl_p5_o => ctrl_p5_s, + .ctrl_p6_i => ctrl_p6_s, + .ctrl_p7_i => ctrl_p7_s, + .ctrl_p8_o => ctrl_p8_s, + .ctrl_p9_i => ctrl_p9_s, +//CPU RAM Interface + .ram_addr_o => ram_addr_s, + .ram_ce_o => ram_ce_s, + .ram_we_o => ram_we_s, + .ram_oe_o => ram_oe_s, + .ram_data_i => d_from_ram_s, + .ram_data_o => d_to_ram_s, +//Video RAM Interface + .vram_addr_o => vram_addr_s, + .vram_ce_o => vram_ce_s, + .vram_oe_o => vram_oe_s, + .vram_we_o => vram_we_s, + .vram_data_i => vram_do_s, + .vram_data_o => vram_di_s, +//Cartridge ROM Interface + .cart_addr_o => open, + .cart_data_i => (others => '1'), + .cart_en_80_n_o => open, + .cart_en_a0_n_o => open, + .cart_en_c0_n_o => open, + .cart_en_e0_n_o => open, +//Audio Interface + .audio_o => open, + .audio_signed_o => audio_signed_s, +//RGB Video Interface + .col_o => rgb_col_s, + .rgb_r_o => open, + .rgb_g_o => open, + .rgb_b_o => open, + .hsync_n_o => rgb_hsync_n_s, + .vsync_n_o => rgb_vsync_n_s, + .comp_sync_n_o => open, +//DEBUG + .D_cpu_addr () + ); + +endmodule \ No newline at end of file diff --git a/Coleco - Vision_MiST/rtl/T80/t80.vhd b/Coleco - Vision_MiST/rtl/T80/t80.vhd new file mode 100644 index 00000000..18a053a3 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80.vhd @@ -0,0 +1,1094 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0249 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0210 : Fixed wait and halt +-- +-- 0211 : Fixed Refresh addition and IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson +-- +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- +-- 0237 : Changed 8080 I/O address output, added IntE output +-- +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- +-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode +-- +-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM +-- +-- 0247 : Fixed bus req/ack cycle +-- +-- 0248 : add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 +-- +-- 0249 : add undocumented XY-Flags for CPI/CPD by TobiFlex 22.07.2012 +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80 is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); +end T80; + +architecture rtl of T80 is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + -- Registers + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; + + -- Help Registers + signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register + signal IR : std_logic_vector(7 downto 0); -- Instruction register + signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector + signal RegBusA_r : std_logic_vector(15 downto 0); + + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); + + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal IntE_FF1 : std_logic; + signal IntE_FF2 : std_logic; + signal Halt_FF : std_logic; + signal BusReq_s : std_logic; + signal BusAck : std_logic; + signal ClkEn : std_logic; + signal NMI_s : std_logic; + signal INT_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); + + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; + + -- ALU signals + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); + + -- Registered micro code outputs + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal ALU_cpi_r : std_logic; + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); + + -- Micro code outputs + signal MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(3 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal ALU_cpi : std_logic; + signal Save_ALU : std_logic; + signal PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_i : std_logic; + signal Special_LD : std_logic_vector(2 downto 0); + signal ExchangeDH : std_logic; + signal ExchangeRp : std_logic; + signal ExchangeAF : std_logic; + signal ExchangeRS : std_logic; + signal I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_INRC : std_logic; + signal SetDI : std_logic; + signal SetEI : std_logic; + signal IMode : std_logic_vector(1 downto 0); + signal Halt : std_logic; + signal XYbit_undoc : std_logic; + +begin + + mcode : T80_MCode + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + XY_State => XY_State, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, + Read_To_Acc => Read_To_Acc, + Read_To_Reg => Read_To_Reg, + Set_BusB_To => Set_BusB_To, + Set_BusA_To => Set_BusA_To, + ALU_Op => ALU_Op, + ALU_cpi => ALU_cpi, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, + Set_Addr_To => Set_Addr_To, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write, + XYbit_undoc => XYbit_undoc); + + alu : T80_ALU + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + Arith16 => Arith16_r, + Z16 => Z16_r, + ALU_cpi => ALU_cpi_r, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); + + ClkEn <= CEN and not BusAck; + + T_Res <= '1' when TState = unsigned(TStates) else '0'; + + NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and + ((Set_Addr_To = aXY) or + (MCycle = "001" and IR = "11001011") or + (MCycle = "001" and IR = "00110110")) else '0'; + + Save_Mux <= BusB when ExchangeRp = '1' else + DI_Reg when Save_ALU_r = '0' else + ALU_Q; + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + TmpAddr <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; + + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; + + Read_To_Reg_r <= "00000"; + F <= (others => '1'); + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + ALU_cpi_r <= '0'; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + + elsif CLK_n'event and CLK_n = '1' then + + if ClkEn = '1' then + + ALU_Op_r <= "0000"; + ALU_cpi_r <= '0'; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; + + MCycles <= MCycles_d; + + if IMode /= "11" then + IStatus <= IMode; + end if; + + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; + + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 + + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; + + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; + else + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; + end if; + else + XY_State <= "00"; + XY_Ind <= '0'; + end if; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= TmpAddr; + PC <= unsigned(TmpAddr); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= TmpAddr; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + end if; + when aDE => + A <= RegBusC; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(TmpAddr) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + Save_ALU_r <= Save_ALU; + ALU_cpi_r <= ALU_cpi; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + TmpAddr <= (others =>'0'); + TmpAddr(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + TmpAddr(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + TmpAddr(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 and Auto_Wait_t1 = '0' then + DO <= BusB; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; + when others => + end case; + if XYbit_undoc='1' then + DO <= ALU_Q; + end if; + end if; + + end if; + + end if; + + end process; + +--------------------------------------------------------------------------- +-- +-- BC('), DE('), HL('), IX and IY +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + -- Bus A / Write + RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then + RegAddrA_r <= XY_State(1) & "11"; + end if; + + -- Bus B + RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then + RegAddrB_r <= XY_State(1) & "11"; + end if; + + -- Address from register + RegAddrC <= Alternate & Set_Addr_To(1 downto 0); + -- Jump (HL), LD SP,HL + if (JumpXY = '1' or LDSPHL = '1') then + RegAddrC <= Alternate & "10"; + end if; + if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then + RegAddrC <= XY_State(1) & "11"; + end if; + + if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then + IncDecZ <= F_Out(Flag_Z); + end if; + if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then + if ID16 = 0 then + IncDecZ <= '0'; + else + IncDecZ <= '1'; + end if; + end if; + + RegBusA_r <= RegBusA; + end if; + end if; + end process; + + RegAddrA <= + -- 16 bit increment/decrement + Alternate & IncDec_16(1 downto 0) when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else + -- EX HL,DL + Alternate & "10" when ExchangeDH = '1' and TState = 3 else + Alternate & "01" when ExchangeDH = '1' and TState = 4 else + -- Bus A / Write + RegAddrA_r; + + RegAddrB <= + -- EX HL,DL + Alternate & "01" when ExchangeDH = '1' and TState = 3 else + -- Bus B + RegAddrB_r; + + ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else + signed(RegBusA) + 1; + + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegWEH <= '0'; + RegWEL <= '0'; + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => + RegWEH <= not Read_To_Reg_r(0); + RegWEL <= Read_To_Reg_r(0); + when others => + end case; + end if; + + if ExchangeDH = '1' and (TState = 3 or TState = 4) then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + case IncDec_16(1 downto 0) is + when "00" | "01" | "10" => + RegWEH <= '1'; + RegWEL <= '1'; + when others => + end case; + end if; + end process; + + process (Save_Mux, RegBusB, RegBusA_r, ID16, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegDIH <= Save_Mux; + RegDIL <= Save_Mux; + + if ExchangeDH = '1' and TState = 3 then + RegDIH <= RegBusB(15 downto 8); + RegDIL <= RegBusB(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 4 then + RegDIH <= RegBusA_r(15 downto 8); + RegDIL <= RegBusA_r(7 downto 0); + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + RegDIH <= std_logic_vector(ID16(15 downto 8)); + RegDIL <= std_logic_vector(ID16(7 downto 0)); + end if; + end process; + + Regs : T80_Reg + port map( + Clk => CLK_n, + CEN => ClkEn, + WEH => RegWEH, + WEL => RegWEL, + AddrA => RegAddrA, + AddrB => RegAddrB, + AddrC => RegAddrC, + DIH => RegDIH, + DIL => RegDIL, + DOAH => RegBusA(15 downto 8), + DOAL => RegBusA(7 downto 0), + DOBH => RegBusB(15 downto 8), + DOBL => RegBusB(7 downto 0), + DOCH => RegBusC(15 downto 8), + DOCL => RegBusC(7 downto 0)); + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + BusB <= "00000000"; + when others => + BusB <= "--------"; + end case; + + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusB <= "--------"; + end case; + if XYbit_undoc='1' then + BusA <= DI_Reg; + BusB <= DI_Reg; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Generate external control signals +-- +--------------------------------------------------------------------------- + process (RESET_n,CLK_n) + begin + if RESET_n = '0' then + RFSH_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; + end if; + end if; + end process; + + MC <= std_logic_vector(MCycle); + TS <= std_logic_vector(TState); + DI_Reg <= DI; + HALT_n <= not Halt_FF; + BUSAK_n <= not BusAck; + IntCycle_n <= not IntCycle; + IntE <= IntE_FF1; + IORQ <= IORQ_i; + Stop <= I_DJNZ; + +------------------------------------------------------------------------- +-- +-- Syncronise inputs +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; + begin + if RESET_n = '0' then + BusReq_s <= '0'; + INT_s <= '0'; + NMI_s <= '0'; + OldNMI_n := '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + INT_s <= not INT_n; + if NMICycle = '1' then + NMI_s <= '0'; + elsif NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + end if; + end if; + end process; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + else + Auto_Wait_t1 <= Auto_Wait or IORQ_i; + end if; + Auto_Wait_t2 <= Auto_Wait_t1; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or + (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or + No_BTR = '1' or + (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; + end if; + end if; + end if; + end process; + + process (IntCycle, NMICycle, MCycle) + begin + Auto_Wait <= '0'; + if IntCycle = '1' or NMICycle = '1' then + if MCycle = "001" then + Auto_Wait <= '1'; + end if; + end if; + end process; + +end; diff --git a/Coleco - Vision_MiST/rtl/T80/t80_alu.vhd b/Coleco - Vision_MiST/rtl/T80/t80_alu.vhd new file mode 100644 index 00000000..ce8f9755 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80_alu.vhd @@ -0,0 +1,362 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0249 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- +-- 0240 : Added GB operations +-- +-- 0242 : Cleanup +-- +-- 0247 : Cleanup +-- +-- 0249 : add undocumented XY-Flags for CPI/CPD by TobiFlex 22.07.2012 +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_ALU is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_cpi : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); +end T80_ALU; + +architecture rtl of T80_ALU is + + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); + begin + if Sub = '1' then + B_i := not unsigned(B); + else + B_i := unsigned(B); + end if; + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); + Carry <= Res_i(A'length + 1); + Res <= std_logic_vector(Res_i(A'length downto 1)); + end; + + -- AddSub variables (temporary signals) + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); + signal Q_cpi : std_logic_vector(4 downto 0); + + signal BitMask : std_logic_vector(7 downto 0); + +begin + + with IR(5 downto 3) select BitMask <= "00000001" when "000", + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; + + UseCarry <= not ALU_Op(2) and ALU_Op(0); + AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); + AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); + AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); + OverFlow_v <= Carry_v xor Carry7_v; + + AddSub(BusA(3 downto 0), BusB(3 downto 0), '1', HalfCarry_v, Q_cpi(3 downto 0), Q_cpi(4)); + + process (Arith16, ALU_OP, ALU_cpi, F_In, BusA, BusB, IR, Q_v, Q_cpi, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + variable Q_t : std_logic_vector(7 downto 0); + variable DAA_Q : unsigned(8 downto 0); + begin + Q_t := "--------"; + F_Out <= F_In; + DAA_Q := "---------"; + case ALU_Op is + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" => + F_Out(Flag_N) <= '0'; + F_Out(Flag_C) <= '0'; + case ALU_OP(2 downto 0) is + when "000" | "001" => -- ADD, ADC + Q_t := Q_v; + F_Out(Flag_C) <= Carry_v; + F_Out(Flag_H) <= HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "010" | "011" | "111" => -- SUB, SBC, CP + Q_t := Q_v; + F_Out(Flag_N) <= '1'; + F_Out(Flag_C) <= not Carry_v; + F_Out(Flag_H) <= not HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "100" => -- AND + Q_t(7 downto 0) := BusA and BusB; + F_Out(Flag_H) <= '1'; + when "101" => -- XOR + Q_t(7 downto 0) := BusA xor BusB; + F_Out(Flag_H) <= '0'; + when others => -- OR "110" + Q_t(7 downto 0) := BusA or BusB; + F_Out(Flag_H) <= '0'; + end case; + if ALU_Op(2 downto 0) = "111" then -- CP + if ALU_cpi='1' then --CPI + F_Out(Flag_X) <= Q_cpi(3); + F_Out(Flag_Y) <= Q_cpi(1); + else + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + else + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + end if; + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + if Z16 = '1' then + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + end if; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + case ALU_Op(2 downto 0) is + when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP + when others => + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + end case; + if Arith16 = '1' then + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + F_Out(Flag_P) <= F_In(Flag_P); + end if; + when "1100" => + -- DAA + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 + end if; + end if; + F_Out(Flag_X) <= DAA_Q(3); + F_Out(Flag_Y) <= DAA_Q(5); + F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8); + Q_t := std_logic_vector(DAA_Q(7 downto 0)); + if DAA_Q(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= DAA_Q(7); + F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor + DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7)); + when "1101" | "1110" => + -- RLD, RRD + Q_t(7 downto 4) := BusA(7 downto 4); + if ALU_Op(0) = '1' then + Q_t(3 downto 0) := BusB(7 downto 4); + else + Q_t(3 downto 0) := BusB(3 downto 0); + end if; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + when "1001" => + -- BIT + Q_t(7 downto 0) := BusB and BitMask; + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + F_Out(Flag_P) <= '1'; + else + F_Out(Flag_Z) <= '0'; + F_Out(Flag_P) <= '0'; + end if; + F_Out(Flag_H) <= '1'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= '0'; + F_Out(Flag_Y) <= '0'; + if IR(2 downto 0) /= "110" then + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + when "1010" => + -- SET + Q_t(7 downto 0) := BusB or BitMask; + when "1011" => + -- RES + Q_t(7 downto 0) := BusB and not BitMask; + when "1000" => + -- ROT + case IR(5 downto 3) is + when "000" => -- RLC + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := BusA(7); + F_Out(Flag_C) <= BusA(7); + when "010" => -- RL + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(7); + when "001" => -- RRC + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(0); + F_Out(Flag_C) <= BusA(0); + when "011" => -- RR + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(0); + when "100" => -- SLA + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '0'; + F_Out(Flag_C) <= BusA(7); + when "110" => -- SLL (Undocumented) / SWAP + if Mode = 3 then + Q_t(7 downto 4) := BusA(3 downto 0); + Q_t(3 downto 0) := BusA(7 downto 4); + F_Out(Flag_C) <= '0'; + else + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '1'; + F_Out(Flag_C) <= BusA(7); + end if; + when "101" => -- SRA + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(7); + F_Out(Flag_C) <= BusA(0); + when others => -- SRL + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := '0'; + F_Out(Flag_C) <= BusA(0); + end case; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + if ISet = "00" then + F_Out(Flag_P) <= F_In(Flag_P); + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + end if; + when others => + null; + end case; + Q <= Q_t; + end process; + +end; diff --git a/Coleco - Vision_MiST/rtl/T80/t80_mcode.vhd b/Coleco - Vision_MiST/rtl/T80/t80_mcode.vhd new file mode 100644 index 00000000..5b18e674 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80_mcode.vhd @@ -0,0 +1,2014 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0249 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0235 : Added IM 2 fix by Mike Johnson +-- +-- 0238 : Added NoRead signal +-- +-- 0238b: Fixed instruction timing for POP and DJNZ +-- +-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes +-- +-- 0242 : Fixed I/O instruction timing, cleanup +-- +-- 0242a: 31st of August, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) +-- Fixed INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR instructions +-- +-- 0248 : add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 +-- +-- 0249 : add undocumented XY-Flags for CPI/CPD by TobiFlex 22.07.2012 +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_MCode is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + XY_State : in std_logic_vector(1 downto 0); + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + ALU_cpi : out std_logic; --for undoc XY-Flags + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + XYbit_undoc : out std_logic + ); +end T80_MCode; + +architecture rtl of T80_MCode is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + function is_cc_true( + F : std_logic_vector(7 downto 0); + cc : bit_vector(2 downto 0) + ) return boolean is + begin + if Mode = 3 then + case cc is + when "000" => return F(7) = '0'; -- NZ + when "001" => return F(7) = '1'; -- Z + when "010" => return F(4) = '0'; -- NC + when "011" => return F(4) = '1'; -- C + when "100" => return false; + when "101" => return false; + when "110" => return false; + when "111" => return false; + end case; + else + case cc is + when "000" => return F(6) = '0'; -- NZ + when "001" => return F(6) = '1'; -- Z + when "010" => return F(0) = '0'; -- NC + when "011" => return F(0) = '1'; -- C + when "100" => return F(2) = '0'; -- PO + when "101" => return F(2) = '1'; -- PE + when "110" => return F(7) = '0'; -- P + when "111" => return F(7) = '1'; -- M + end case; + end if; + end; + +begin + + process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); + variable DPair : std_logic_vector(1 downto 0); + variable IRB : bit_vector(7 downto 0); + begin + DDD := IR(5 downto 3); + SSS := IR(2 downto 0); + DPair := IR(5 downto 4); + IRB := to_bitvector(IR); + + MCycles <= "001"; + if MCycle = "001" then + TStates <= "100"; + else + TStates <= "011"; + end if; + Prefix <= "00"; + Inc_PC <= '0'; + Inc_WZ <= '0'; + IncDec_16 <= "0000"; + Read_To_Acc <= '0'; + Read_To_Reg <= '0'; + Set_BusB_To <= "0000"; + Set_BusA_To <= "0000"; + ALU_Op <= "0" & IR(5 downto 3); + ALU_cpi <= '0'; + Save_ALU <= '0'; + PreserveC <= '0'; + Arith16 <= '0'; + IORQ <= '0'; + Set_Addr_To <= aNone; + Jump <= '0'; + JumpE <= '0'; + JumpXY <= '0'; + Call <= '0'; + RstP <= '0'; + LDZ <= '0'; + LDW <= '0'; + LDSPHL <= '0'; + Special_LD <= "000"; + ExchangeDH <= '0'; + ExchangeRp <= '0'; + ExchangeAF <= '0'; + ExchangeRS <= '0'; + I_DJNZ <= '0'; + I_CPL <= '0'; + I_CCF <= '0'; + I_SCF <= '0'; + I_RETN <= '0'; + I_BT <= '0'; + I_BC <= '0'; + I_BTR <= '0'; + I_RLD <= '0'; + I_RRD <= '0'; + I_INRC <= '0'; + SetDI <= '0'; + SetEI <= '0'; + IMode <= "11"; + Halt <= '0'; + NoRead <= '0'; + Write <= '0'; + XYbit_undoc <= '0'; + + case ISet is + when "00" => + +------------------------------------------------------------------------------ +-- +-- Unprefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is +-- 8 BIT LOAD GROUP + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- LD r,r' + Set_BusB_To(2 downto 0) <= SSS; + ExchangeRp <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" => + -- LD r,n + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" => + -- LD r,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" => + -- LD (HL),r + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110110" => + -- LD (HL),n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00001010" => + -- LD A,(BC) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00011010" => + -- LD A,(DE) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00111010" => + if Mode = 3 then + -- LDD A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end if; + when "00000010" => + -- LD (BC),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00010010" => + -- LD (DE),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110010" => + if Mode = 3 then + -- LDD (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + end if; + +-- 16 BIT LOAD GROUP + when "00000001"|"00010001"|"00100001"|"00110001" => + -- LD dd,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1000"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1001"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "00101010" => + if Mode = 3 then + -- LDI A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD HL,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end if; + when "00100010" => + if Mode = 3 then + -- LDI (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD (nn),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "0101"; -- L + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "0100"; -- H + when 5 => + Write <= '1'; + when others => null; + end case; + end if; + when "11111001" => + -- LD SP,HL + TStates <= "110"; + LDSPHL <= '1'; + when "11000101"|"11010101"|"11100101"|"11110101" => + -- PUSH qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "11000001"|"11010001"|"11100001"|"11110001" => + -- POP qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1011"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + IncDec_16 <= "0111"; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "0111"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + +-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + when "11101011" => + if Mode /= 3 then + -- EX DE,HL + ExchangeDH <= '1'; + end if; + when "00001000" => + if Mode = 3 then + -- LD (nn),SP + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "1000"; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "1001"; + when 5 => + Write <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EX AF,AF' + ExchangeAF <= '1'; + end if; + when "11011001" => + if Mode = 3 then + -- RETI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + SetEI <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EXX + ExchangeRS <= '1'; + end if; + when "11100011" => + if Mode /= 3 then + -- EX (SP),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; + Set_Addr_To <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + TStates <= "100"; + Write <= '1'; + when 4 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; + Set_Addr_To <= aSP; + when 5 => + IncDec_16 <= "1111"; + TStates <= "101"; + Write <= '1'; + when others => null; + end case; + end if; + +-- 8 BIT ARITHMETIC AND LOGICAL GROUP + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- ADD A,r + -- ADC A,r + -- SUB A,r + -- SBC A,r + -- AND A,r + -- OR A,r + -- XOR A,r + -- CP A,r + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- ADD A,(HL) + -- ADC A,(HL) + -- SUB A,(HL) + -- SBC A,(HL) + -- AND A,(HL) + -- OR A,(HL) + -- XOR A,(HL) + -- CP A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + when others => null; + end case; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- ADD A,n + -- ADC A,n + -- SUB A,n + -- SBC A,n + -- AND A,n + -- OR A,n + -- XOR A,n + -- CP A,n + MCycles <= "010"; + if MCycle = "010" then + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + end if; + when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" => + -- INC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + when "00110100" => + -- INC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" => + -- DEC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0010"; + when "00110101" => + -- DEC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + ALU_Op <= "0010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + +-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + when "00100111" => + -- DAA + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + ALU_Op <= "1100"; + Save_ALU <= '1'; + when "00101111" => + -- CPL + I_CPL <= '1'; + when "00111111" => + -- CCF + I_CCF <= '1'; + when "00110111" => + -- SCF + I_SCF <= '1'; + when "00000000" => + if NMICycle = '1' then + -- NMI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when others => null; + end case; + elsif IntCycle = '1' then + -- INT (IM 2) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + else + -- NOP + end if; + when "01110110" => + -- HALT + Halt <= '1'; + when "11110011" => + -- DI + SetDI <= '1'; + when "11111011" => + -- EI + SetEI <= '1'; + +-- 16 BIT ARITHMETIC GROUP + when "00001001"|"00011001"|"00101001"|"00111001" => + -- ADD HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; + when others => + end case; + when "00000011"|"00010011"|"00100011"|"00110011" => + -- INC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when "00001011"|"00011011"|"00101011"|"00111011" => + -- DEC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + +-- ROTATE AND SHIFT GROUP + when "00000111" + -- RLCA + |"00010111" + -- RLA + |"00001111" + -- RRCA + |"00011111" => + -- RRA + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + +-- JUMP GROUP + when "11000011" => + -- JP nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + Jump <= '1'; + when others => null; + end case; + when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+C),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "01" => + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + when "10" => + -- LD A,($FF00+C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => + end case; + when "11" => + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end case; + else + -- JP cc,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Jump <= '1'; + end if; + when others => null; + end case; + end if; + when "00011000" => + if Mode /= 2 then + -- JR e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00111000" => + if Mode /= 2 then + -- JR C,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00110000" => + if Mode /= 2 then + -- JR NC,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00101000" => + if Mode /= 2 then + -- JR Z,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00100000" => + if Mode /= 2 then + -- JR NZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "11101001" => + -- JP (HL) + JumpXY <= '1'; + when "00010000" => + if Mode = 3 then + I_DJNZ <= '1'; + elsif Mode < 2 then + -- DJNZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + I_DJNZ <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= "000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + I_DJNZ <= '1'; + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + +-- CALL AND RETURN GROUP + when "11001101" => + -- CALL nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + IncDec_16 <= "1111"; + Inc_PC <= '1'; + TStates <= "100"; + Set_Addr_To <= aSP; + LDW <= '1'; + Set_BusB_To <= "1101"; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => + if IR(5) = '0' or Mode /= 3 then + -- CALL cc,nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + LDW <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + TStates <= "100"; + Set_BusB_To <= "1101"; + else + MCycles <= "011"; + end if; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + end if; + when "11001001" => + -- RET + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+nn),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "01" => + -- ADD SP,n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + ALU_Op <= "0000"; + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To <= "1000"; + Set_BusB_To <= "0110"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To <= "1001"; + Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + when others => + end case; + when "10" => + -- LD A,($FF00+nn) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "11" => + -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end case; + else + -- RET cc + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; + when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => + -- RST p + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + +-- INPUT AND OUTPUT GROUP + when "11011011" => + if Mode /= 3 then + -- IN A,(n) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + when "11010011" => + if Mode /= 3 then + -- OUT (n),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- MULTIBYTE INSTRUCTIONS +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + + when "11001011" => + if Mode /= 2 then + Prefix <= "01"; + end if; + + when "11101101" => + if Mode < 2 then + Prefix <= "10"; + end if; + + when "11011101"|"11111101" => + if Mode < 2 then + Prefix <= "11"; + end if; + + end case; + + when "01" => + +------------------------------------------------------------------------------ +-- +-- CB prefixed instructions +-- +------------------------------------------------------------------------------ + + Set_BusA_To(2 downto 0) <= IR(2 downto 0); + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" => + -- RLC r + -- RL r + -- RRC r + -- RR r + -- SLA r + -- SRA r + -- SRL r + -- SLL r (Undocumented) / SWAP r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- R/S (IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + + + when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" => + -- RLC (HL) + -- RL (HL) + -- RRC (HL) + -- RR (HL) + -- SRA (HL) + -- SRL (HL) + -- SLA (HL) + -- SLL (HL) (Undocumented) / SWAP (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- BIT b,r + if XY_State="00" then + if MCycle = "001" then + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + ALU_Op <= "1001"; + end if; + else + -- BIT b,(IX+d), undocumented + MCycles <= "010"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => null; + end case; + end if; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" => + -- BIT b,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => null; + end case; + when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" => + -- SET b,r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- SET b,(IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- SET b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- RES b,r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- RES b,(IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- RES b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end case; + + when others => + +------------------------------------------------------------------------------ +-- +-- ED prefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111" + + + |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111" + | "10100100"|"10100101"|"10100110"|"10100111" + | "10101100"|"10101101"|"10101110"|"10101111" + | "10110100"|"10110101"|"10110110"|"10110111" + | "10111100"|"10111101"|"10111110"|"10111111" + |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => + null; -- NOP, undocumented + when "01111110"|"01111111" => + -- NOP, undocumented + null; +-- 8 BIT LOAD GROUP + when "01010111" => + -- LD A,I + Special_LD <= "100"; + TStates <= "101"; + when "01011111" => + -- LD A,R + Special_LD <= "101"; + TStates <= "101"; + when "01000111" => + -- LD I,A + Special_LD <= "110"; + TStates <= "101"; + when "01001111" => + -- LD R,A + Special_LD <= "111"; + TStates <= "101"; +-- 16 BIT LOAD GROUP + when "01001011"|"01011011"|"01101011"|"01111011" => + -- LD dd,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1000"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '1'; + end if; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1001"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "01000011"|"01010011"|"01100011"|"01110011" => + -- LD (nn),dd + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1000"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1001"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 5 => + Write <= '1'; + when others => null; + end case; + when "10100000" | "10101000" | "10110000" | "10111000" => + -- LDI, LDD, LDIR, LDDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0000"; + Set_Addr_To <= aDE; + if IR(3) = '0' then + IncDec_16 <= "0110"; -- IX + else + IncDec_16 <= "1110"; + end if; + when 3 => + I_BT <= '1'; + TStates <= "101"; + Write <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0101"; -- DE + else + IncDec_16 <= "1101"; + end if; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100001" | "10101001" | "10110001" | "10111001" => + -- CPI, CPD, CPIR, CPDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0111"; + ALU_cpi <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + when 3 => + NoRead <= '1'; + I_BC <= '1'; + TStates <= "101"; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" => + -- NEG + Alu_OP <= "0010"; + Set_BusB_To <= "0111"; + Set_BusA_To <= "1010"; + Read_To_Acc <= '1'; + Save_ALU <= '1'; + when "01000110"|"01001110"|"01100110"|"01101110" => + -- IM 0 + IMode <= "00"; + when "01010110"|"01110110" => + -- IM 1 + IMode <= "01"; + when "01011110"|"01110111" => + -- IM 2 + IMode <= "10"; +-- 16 bit arithmetic + when "01001010"|"01011010"|"01101010"|"01111010" => + -- ADC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0001"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01000010"|"01010010"|"01100010"|"01110010" => + -- SBC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01101111" => + -- RLD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1101"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RLD <= '1'; + Write <= '1'; + when others => + end case; + when "01100111" => + -- RRD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1110"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RRD <= '1'; + Write <= '1'; + when others => + end case; + when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => + -- RETI, RETN + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + when others => null; + end case; + when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" => + -- IN r,(C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + IORQ <= '1'; + if IR(5 downto 3) /= "110" then + Read_To_Reg <= '1'; + Set_BusA_To(2 downto 0) <= IR(5 downto 3); + end if; + I_INRC <= '1'; + when others => + end case; + when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" => + -- OUT (C),r + -- OUT (C),0 + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + if IR(5 downto 3) = "110" then + Set_BusB_To(3) <= '1'; + end if; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "10100010" | "10101010" | "10110010" | "10111010" => + -- INI, IND, INIR, INDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + IORQ <= '1'; + Set_BusB_To <= "0110"; + Set_Addr_To <= aXY; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0110"; -- 0242a + else + IncDec_16 <= "1110"; -- 0242a + end if; + TStates <= "100"; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100011" | "10101011" | "10110011" | "10111011" => + -- OUTI, OUTD, OTIR, OTDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aXY; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + Set_BusB_To <= "0110"; + Set_Addr_To <= aBC; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0110"; -- 0242a + else + IncDec_16 <= "1110"; -- 0242a + end if; + IORQ <= '1'; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + end case; + + end case; + + if Mode = 1 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "011"; + end if; + end if; + + if Mode = 3 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "100"; + end if; + end if; + + if Mode < 2 then + if MCycle = "110" then + Inc_PC <= '1'; + if Mode = 1 then + Set_Addr_To <= aXY; + TStates <= "100"; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + end if; + if IRB = "00110110" or IRB = "11001011" then + Set_Addr_To <= aNone; + end if; + end if; + if MCycle = "111" then + if Mode = 0 then + TStates <= "101"; + end if; + if ISet /= "01" then + Set_Addr_To <= aXY; + end if; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + if IRB = "00110110" or ISet = "01" then + -- LD (HL),n + Inc_PC <= '1'; + else + NoRead <= '1'; + end if; + end if; + end if; + + end process; + +end; diff --git a/Coleco - Vision_MiST/rtl/T80/t80_pack.vhd b/Coleco - Vision_MiST/rtl/T80/t80_pack.vhd new file mode 100644 index 00000000..95a03bea --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80_pack.vhd @@ -0,0 +1,212 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T80_Pack is + + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); + end component; + + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + XY_State : in std_logic_vector(1 downto 0); + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + ALU_cpi : out std_logic; + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + XYbit_undoc : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_cpi : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Coleco - Vision_MiST/rtl/T80/t80_reg.vhd b/Coleco - Vision_MiST/rtl/T80/t80_reg.vhd new file mode 100644 index 00000000..52417e36 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80_reg.vhd @@ -0,0 +1,105 @@ +-- +-- T80 Registers, technology independent +-- +-- Version : 0244 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t51/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : Initial release +-- +-- 0244 : Changed to single register file +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_Reg is + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); +end T80_Reg; + +architecture rtl of T80_Reg is + + type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); + +begin + + process (Clk) + begin + if Clk'event and Clk = '1' then + if CEN = '1' then + if WEH = '1' then + RegsH(to_integer(unsigned(AddrA))) <= DIH; + end if; + if WEL = '1' then + RegsL(to_integer(unsigned(AddrA))) <= DIL; + end if; + end if; + end if; + end process; + + DOAH <= RegsH(to_integer(unsigned(AddrA))); + DOAL <= RegsL(to_integer(unsigned(AddrA))); + DOBH <= RegsH(to_integer(unsigned(AddrB))); + DOBL <= RegsL(to_integer(unsigned(AddrB))); + DOCH <= RegsH(to_integer(unsigned(AddrC))); + DOCL <= RegsL(to_integer(unsigned(AddrC))); + +end; diff --git a/Coleco - Vision_MiST/rtl/T80/t80a.vhd b/Coleco - Vision_MiST/rtl/T80/t80a.vhd new file mode 100644 index 00000000..77293494 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/T80/t80a.vhd @@ -0,0 +1,286 @@ +-- +-- Z80 compatible microprocessor core, asynchronous top level +-- +-- Version : 0247a (+k01) +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +-- 0247 : Fixed bus req/ack cycle +-- +-- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) +-- Fixed IORQ_n, RD_n, WR_n bus timing +-- +------------------------------------------------------------------------------- +-- +k01 : 2010.10.25 by KdL +-- Added RstKeyLock and swioRESET_n +-- +-- 2016.08 by Fabio Belavenuto: Refactoring signal names +-- +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80a is + generic( + mode_g : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + reset_n_i : in std_logic; + clock_i : in std_logic; + clock_en_i : in std_logic; + address_o : out std_logic_vector(15 downto 0); + data_i : in std_logic_vector(7 downto 0); + data_o : out std_logic_vector(7 downto 0); + wait_n_i : in std_logic; + int_n_i : in std_logic; + nmi_n_i : in std_logic; + m1_n_o : out std_logic; + mreq_n_o : out std_logic; + iorq_n_o : out std_logic; + rd_n_o : out std_logic; + wr_n_o : out std_logic; + refresh_n_o : out std_logic; + halt_n_o : out std_logic; + busrq_n_i : in std_logic; + busak_n_o : out std_logic + ); +end T80a; + +architecture rtl of T80a is + + signal reset_s : std_logic; + signal int_cycle_n_s : std_logic; + signal iorq_s : std_logic; + signal noread_s : std_logic; + signal write_s : std_logic; + signal mreq_s : std_logic; + signal mreq_inhibit_s : std_logic; + signal ireq_inhibit_n_s : std_logic; -- 0247a + signal req_inhibit_s : std_logic; + signal rd_s : std_logic; + signal mreq_n_s : std_logic; + signal iorq_n_s : std_logic; + signal rd_n_s : std_logic; + signal wr_n_s : std_logic; + signal wr_n_j_s : std_logic; -- 0247a + signal rfsh_n_s : std_logic; + signal busak_n_s : std_logic; + signal address_s : std_logic_vector(15 downto 0); + signal data_out_s : std_logic_vector(7 downto 0); + signal data_r : std_logic_vector (7 downto 0); -- Input synchroniser + signal wait_s : std_logic; + signal m_cycle_s : std_logic_vector(2 downto 0); + signal t_state_s : std_logic_vector(2 downto 0); + +begin + + mreq_n_s <= not mreq_s or (req_inhibit_s and mreq_inhibit_s); + rd_n_s <= not rd_s or req_inhibit_s; + wr_n_j_s <= wr_n_s; -- 0247a (why ???) + + busak_n_o <= busak_n_s; + mreq_n_o <= mreq_n_s when busak_n_s = '1' else 'Z'; + iorq_n_o <= iorq_n_s or ireq_inhibit_n_s when busak_n_s = '1' else 'Z'; -- 0247a + rd_n_o <= rd_n_s when busak_n_s = '1' else 'Z'; + wr_n_o <= wr_n_j_s when busak_n_s = '1' else 'Z'; -- 0247a + refresh_n_o <= rfsh_n_s when busak_n_s = '1' else 'Z'; + address_o <= address_s when busak_n_s = '1' else (others => 'Z'); + data_o <= data_out_s; + + process (reset_n_i, clock_i) + begin + if reset_n_i = '0' then + reset_s <= '0'; + elsif rising_edge(clock_i) then + reset_s <= '1'; + end if; + end process; + + u0 : T80 + generic map( + Mode => mode_g, + IOWait => 1 + ) + port map( + CEN => clock_en_i, + M1_n => m1_n_o, + IORQ => iorq_s, + NoRead => noread_s, + Write => write_s, + RFSH_n => rfsh_n_s, + HALT_n => halt_n_o, + WAIT_n => wait_s, + INT_n => int_n_i, + NMI_n => nmi_n_i, + RESET_n => reset_s, + BUSRQ_n => busrq_n_i, + BUSAK_n => busak_n_s, + CLK_n => clock_i, + A => address_s, + DInst => data_i, + DI => data_r, + DO => data_out_s, + MC => m_cycle_s, + TS => t_state_s, + IntCycle_n => int_cycle_n_s + ); + + process (clock_i, clock_en_i) + begin + if falling_edge(clock_i) and clock_en_i = '1' then + wait_s <= wait_n_i; + if t_state_s = "011" and busak_n_s = '1' then + data_r <= data_i; + end if; + end if; + end process; + + process (clock_i) -- 0247a + begin + if rising_edge(clock_i) then + ireq_inhibit_n_s <= not iorq_s; + end if; + end process; + + process (reset_s, clock_i, clock_en_i) -- 0247a + begin + if reset_s = '0' then + wr_n_s <= '1'; + elsif falling_edge(clock_i) and clock_en_i = '1' then + if iorq_s = '0' then + if t_state_s = "010" then + wr_n_s <= not write_s; + elsif t_state_s = "011" then + wr_n_s <= '1'; + end if; + else + if t_state_s = "001" and iorq_n_s = '0' then + wr_n_s <= not write_s; + elsif t_state_s = "011" then + wr_n_s <= '1'; + end if; + end if; + end if; + end process; + + process (reset_s, clock_i, clock_en_i) -- 0247a + begin + if reset_s = '0' then + req_inhibit_s <= '0'; + elsif rising_edge(clock_i) and clock_en_i = '1' then + if m_cycle_s = "001" and t_state_s = "010" and wait_s = '1' then + req_inhibit_s <= '1'; + else + req_inhibit_s <= '0'; + end if; + end if; + end process; + + process (reset_s, clock_i, clock_en_i) + begin + if reset_s = '0' then + mreq_inhibit_s <= '0'; + elsif falling_edge(clock_i) and clock_en_i = '1' then + if m_cycle_s = "001" and t_state_s = "010" then + mreq_inhibit_s <= '1'; + else + mreq_inhibit_s <= '0'; + end if; + end if; + end process; + + process(reset_s, clock_i, clock_en_i) -- 0247a + begin + if reset_s = '0' then + rd_s <= '0'; + iorq_n_s <= '1'; + mreq_s <= '0'; + elsif falling_edge(clock_i) and clock_en_i = '1' then + if m_cycle_s = "001" then + if t_state_s = "001" then + rd_s <= int_cycle_n_s; + mreq_s <= int_cycle_n_s; + iorq_n_s <= int_cycle_n_s; + end if; + if t_state_s = "011" then + rd_s <= '0'; + iorq_n_s <= '1'; + mreq_s <= '1'; + end if; + if t_state_s = "100" then + mreq_s <= '0'; + end if; + else + if t_state_s = "001" and noread_s = '0' then + iorq_n_s <= not iorq_s; + mreq_s <= not iorq_s; + if iorq_s = '0' then + rd_s <= not write_s; + elsif iorq_n_s = '0' then + rd_s <= not write_s; + end if; + end if; + if t_state_s = "011" then + rd_s <= '0'; + iorq_n_s <= '1'; + mreq_s <= '0'; + end if; + end if; + end if; + end process; + +end; diff --git a/Coleco - Vision_MiST/rtl/build_id.tcl b/Coleco - Vision_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..481e9ebf --- /dev/null +++ b/Coleco - Vision_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "sys/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/Coleco - Vision_MiST/rtl/build_id.v b/Coleco - Vision_MiST/rtl/build_id.v new file mode 100644 index 00000000..6efa26c3 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "180816" +`define BUILD_TIME "200421" diff --git a/Coleco - Vision_MiST/rtl/cart.qip b/Coleco - Vision_MiST/rtl/cart.qip new file mode 100644 index 00000000..8607b3bf --- /dev/null +++ b/Coleco - Vision_MiST/rtl/cart.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.0" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "cart.v"] diff --git a/Coleco - Vision_MiST/rtl/cart.v b/Coleco - Vision_MiST/rtl/cart.v new file mode 100644 index 00000000..7c93cc39 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/cart.v @@ -0,0 +1,172 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: cart.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module cart ( + address, + clock, + data, + wren, + q); + + input [14:0] address; + input clock; + input [7:0] data; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 32768, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 15, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "32768" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "15" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32768" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "15" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 15 0 INPUT NODEFVAL "address[14..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// Retrieval info: CONNECT: @address_a 0 0 15 0 address 0 0 15 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL cart_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Coleco - Vision_MiST/rtl/clocks.vhd b/Coleco - Vision_MiST/rtl/clocks.vhd new file mode 100644 index 00000000..645740b4 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/clocks.vhd @@ -0,0 +1,125 @@ +------------------------------------------------------------------------------- +-- +-- CoelcoFPGA project +-- +-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity clocks is + port ( + clock_i : in std_logic; -- 21 MHz + por_i : in std_logic; + clock_vdp_en_o : out std_logic; + clock_5m_en_o : out std_logic; + clock_3m_en_o : out std_logic + ); +end entity; + +architecture rtl of clocks is + + -- Clocks + signal clk1_cnt_q : unsigned(1 downto 0); + signal clk2_cnt_q : unsigned(1 downto 0); + signal clock_vdp_en_s : std_logic := '0'; -- 10.7 MHz + signal clock_5m_en_s : std_logic := '0'; + signal clock_3m_en_s : std_logic := '0'; + +begin + + ----------------------------------------------------------------------------- + process (clock_i, por_i) + begin + if por_i = '1' then + clk1_cnt_q <= (others => '0'); + clock_vdp_en_s <= '0'; + clock_5m_en_s <= '0'; + + elsif rising_edge(clock_i) then + + -- Clock counter -------------------------------------------------------- + if clk1_cnt_q = 3 then + clk1_cnt_q <= (others => '0'); + else + clk1_cnt_q <= clk1_cnt_q + 1; + end if; + + -- 10.7 MHz clock enable ------------------------------------------------ + case clk1_cnt_q is + when "01" | "11" => + clock_vdp_en_s <= '1'; + when others => + clock_vdp_en_s <= '0'; + end case; + + -- 5.37 MHz clock enable ------------------------------------------------ + case clk1_cnt_q is + when "11" => + clock_5m_en_s <= '1'; + when others => + clock_5m_en_s <= '0'; + end case; + end if; + end process; + + + ----------------------------------------------------------------------------- + process (clock_i, por_i) + begin + if por_i = '1' then + clk2_cnt_q <= (others => '0'); + elsif rising_edge(clock_i) then + if clock_vdp_en_s = '1' then + if clk2_cnt_q = 0 then + clk2_cnt_q <= "10"; + else + clk2_cnt_q <= clk2_cnt_q - 1; + end if; + end if; + end if; + end process; + + clock_3m_en_s <= clock_vdp_en_s when clk2_cnt_q = 0 else '0'; + + -- + clock_vdp_en_o <= clock_vdp_en_s; + clock_5m_en_o <= clock_5m_en_s; + clock_3m_en_o <= clock_3m_en_s; + +end architecture; \ No newline at end of file diff --git a/Coleco - Vision_MiST/rtl/colecovision.vhd b/Coleco - Vision_MiST/rtl/colecovision.vhd new file mode 100644 index 00000000..2c81895c --- /dev/null +++ b/Coleco - Vision_MiST/rtl/colecovision.vhd @@ -0,0 +1,435 @@ +------------------------------------------------------------------------------- +-- +-- ColecoFPGA project +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity colecovision is + generic ( + num_maq_g : integer := 0; + compat_rgb_g : integer := 0 + ); + port ( + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + clk_en_5m37_i : in std_logic; + clk_en_3m58_i : in std_logic; + reset_i : in std_logic; -- Reset, tbem acionado quando por_n_i for 0 + por_n_i : in std_logic; -- Power-on Reset + -- Controller Interface --------------------------------------------------- + ctrl_p1_i : in std_logic_vector( 1 downto 0); + ctrl_p2_i : in std_logic_vector( 1 downto 0); + ctrl_p3_i : in std_logic_vector( 1 downto 0); + ctrl_p4_i : in std_logic_vector( 1 downto 0); + ctrl_p5_o : out std_logic_vector( 1 downto 0); + ctrl_p6_i : in std_logic_vector( 1 downto 0); + ctrl_p7_i : in std_logic_vector( 1 downto 0); + ctrl_p8_o : out std_logic_vector( 1 downto 0); + ctrl_p9_i : in std_logic_vector( 1 downto 0); + -- CPU RAM Interface ------------------------------------------------------ + ram_addr_o : out std_logic_vector(16 downto 0); -- 128K + ram_ce_o : out std_logic; + ram_oe_o : out std_logic; + ram_we_o : out std_logic; + ram_data_i : in std_logic_vector( 7 downto 0); + ram_data_o : out std_logic_vector( 7 downto 0); + -- Video RAM Interface ---------------------------------------------------- + vram_addr_o : out std_logic_vector(13 downto 0); -- 16K + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + vram_we_o : out std_logic; + vram_data_i : in std_logic_vector( 7 downto 0); + vram_data_o : out std_logic_vector( 7 downto 0); + -- Cartridge ROM Interface ------------------------------------------------ + cart_addr_o : out std_logic_vector(14 downto 0); -- 32K + cart_data_i : in std_logic_vector( 7 downto 0); + cart_oe_n_o : out std_logic; + cart_en_80_n_o : out std_logic; + cart_en_a0_n_o : out std_logic; + cart_en_c0_n_o : out std_logic; + cart_en_e0_n_o : out std_logic; + -- Audio Interface -------------------------------------------------------- + audio_o : out std_logic_vector(7 downto 0); + -- RGB Video Interface ---------------------------------------------------- + col_o : out std_logic_vector( 3 downto 0); + cnt_hor_o : out std_logic_vector( 8 downto 0); + cnt_ver_o : out std_logic_vector( 7 downto 0); + rgb_r_o : out std_logic_vector( 7 downto 0); + rgb_g_o : out std_logic_vector( 7 downto 0); + rgb_b_o : out std_logic_vector( 7 downto 0); + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + comp_sync_n_o : out std_logic; + -- DEBUG + D_cpu_addr : out std_logic_vector(15 downto 0) + ); + +end entity; + +-- pragma translate_off +use std.textio.all; +-- pragma translate_on + +architecture Behavior of colecovision is + + -- Reset + signal reset_n_s : std_logic; + + -- CPU signals + signal clk_en_cpu_s : std_logic; + signal nmi_n_s : std_logic; + signal iorq_n_s : std_logic; + signal m1_n_s : std_logic; + signal m1_wait_q : std_logic; + signal rd_n_s : std_logic; + signal wr_n_s : std_logic; + signal mreq_n_s : std_logic; + signal rfsh_n_s : std_logic; + signal cpu_addr_s : std_logic_vector(15 downto 0); + signal d_to_cpu_s : std_logic_vector( 7 downto 0); + signal d_from_cpu_s : std_logic_vector( 7 downto 0); + + -- Address Decoder + signal mem_access_s : std_logic; + signal io_access_s : std_logic; + signal io_read_s : std_logic; + signal io_write_s : std_logic; + + -- machine id +-- signal machine_id_cs_s : std_logic; +-- constant machine_id_c : std_logic_vector(7 downto 0) := std_logic_vector(to_unsigned(num_maq_g, 8)); + + -- Config port + signal cfg_port_cs_s : std_logic; + signal cfg_page_cs_s : std_logic; + signal cfg_page_r : std_logic_vector(7 downto 0); + + -- BIOS + signal bios_data_i : std_logic_vector( 7 downto 0); + signal multcart_q : std_logic; + signal bios_ce_s : std_logic; + signal bios_oe_s : std_logic; + signal bios_we_s : std_logic; + + -- RAM + signal ram_ce_s : std_logic; + + -- VDP18 signal + signal d_from_vdp_s : std_logic_vector( 7 downto 0); + signal vdp_r_n_s : std_logic; + signal vdp_w_n_s : std_logic; + + -- SN76489 signal + signal audio_s : signed(7 downto 0); + signal psg_ready_s : std_logic; + signal psg_we_n_s : std_logic; + + -- Controller signals + signal d_from_ctrl_s : std_logic_vector( 7 downto 0); + signal ctrl_r_n_s : std_logic; + signal ctrl_en_key_n_s : std_logic; + signal ctrl_en_joy_n_s : std_logic; + + -- Cartridge + signal cart_en_q : std_logic; + signal cart_en_80_n_s : std_logic; + signal cart_en_a0_n_s : std_logic; + signal cart_en_c0_n_s : std_logic; + signal cart_en_e0_n_s : std_logic; + signal ext_cart_ce_s : std_logic; + signal cart_ce_s : std_logic; + signal cart_oe_s : std_logic; + signal cart_we_s : std_logic; + +begin + + -- CPU + cpu: entity work.T80a + generic map ( + mode_g => 0 + ) + port map ( + clock_i => clock_i, + clock_en_i => clk_en_cpu_s, + reset_n_i => reset_n_s, + address_o => cpu_addr_s, + data_i => d_to_cpu_s, + data_o => d_from_cpu_s, + wait_n_i => '1', + int_n_i => '1', + nmi_n_i => nmi_n_s, + m1_n_o => m1_n_s, + mreq_n_o => mreq_n_s, + iorq_n_o => iorq_n_s, + rd_n_o => rd_n_s, + wr_n_o => wr_n_s, + refresh_n_o => rfsh_n_s, + halt_n_o => open, + busrq_n_i => '1', + busak_n_o => open + ); + + lr: entity work.cvBios + port map ( + clock => clock_i, + address => cpu_addr_s(12 downto 0), + q => bios_data_i + ); + + ----------------------------------------------------------------------------- + -- TMS9928A Video Display Processor + ----------------------------------------------------------------------------- + vdp18_b : entity work.vdp18_core + generic map ( + compat_rgb_g => compat_rgb_g + ) + port map ( + clock_i => clock_i, + clk_en_10m7_i => clk_en_10m7_i, + clk_en_5m37_i => clk_en_5m37_i, + reset_n_i => por_n_i, + csr_n_i => vdp_r_n_s, + csw_n_i => vdp_w_n_s, + mode_i => cpu_addr_s(0), + int_n_o => nmi_n_s, + cd_i => d_from_cpu_s, + cd_o => d_from_vdp_s, + vram_ce_o => vram_ce_o, + vram_oe_o => vram_oe_o, + vram_we_o => vram_we_o, + vram_a_o => vram_addr_o, + vram_d_o => vram_data_o, + vram_d_i => vram_data_i, + -- + col_o => col_o, + cnt_hor_o => cnt_hor_o, + cnt_ver_o => cnt_ver_o, + rgb_r_o => rgb_r_o, + rgb_g_o => rgb_g_o, + rgb_b_o => rgb_b_o, + hsync_n_o => hsync_n_o, + vsync_n_o => vsync_n_o, + comp_sync_n_o => comp_sync_n_o + ); + + ----------------------------------------------------------------------------- + -- SN76489 Programmable Sound Generator + ----------------------------------------------------------------------------- + psg_b : entity work.sn76489_top + generic map ( + clock_div_16_g => 1 + ) + port map ( + clock_i => clock_i, + clock_en_i => clk_en_3m58_i, + res_n_i => reset_n_s, + ce_n_i => psg_we_n_s, + we_n_i => psg_we_n_s, + ready_o => psg_ready_s, + d_i => d_from_cpu_s, + aout_o => audio_s + ); + + audio_o <= std_logic_vector(audio_s); + + ----------------------------------------------------------------------------- + -- Controller ports + ----------------------------------------------------------------------------- + ctrl_b : entity work.cv_ctrl + port map ( + clock_i => clock_i, + clk_en_3m58_i => clk_en_3m58_i, + reset_n_i => reset_n_s, + ctrl_en_key_n_i => ctrl_en_key_n_s, + ctrl_en_joy_n_i => ctrl_en_joy_n_s, + a1_i => cpu_addr_s(1), + ctrl_p1_i => ctrl_p1_i, + ctrl_p2_i => ctrl_p2_i, + ctrl_p3_i => ctrl_p3_i, + ctrl_p4_i => ctrl_p4_i, + ctrl_p5_o => ctrl_p5_o, + ctrl_p6_i => ctrl_p6_i, + ctrl_p7_i => ctrl_p7_i, + ctrl_p8_o => ctrl_p8_o, + ctrl_p9_i => ctrl_p9_i, + d_o => d_from_ctrl_s + ); + + -- Glue + reset_n_s <= not reset_i; + clk_en_cpu_s <= clk_en_3m58_i and psg_ready_s and not m1_wait_q; + + + ----------------------------------------------------------------------------- + -- Process m1_wait + -- + -- Purpose: + -- Implements flip-flop U8A which asserts a wait states controlled by M1. + -- + m1_wait: process (clock_i, reset_n_s, m1_n_s) + begin + if reset_n_s = '0' or m1_n_s = '1' then + m1_wait_q <= '0'; + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' then + m1_wait_q <= not m1_wait_q; + end if; + end if; + end process m1_wait; + + ----------------------------------------------------------------------------- + -- Misc outputs + ----------------------------------------------------------------------------- + --loader_ce_s <= not rd_n_s and bios_ce_s when loader_q = '1' else '0'; + bios_we_s <= not wr_n_s and bios_ce_s;-- when loader_q = '1' else '0'; + bios_oe_s <= not rd_n_s and bios_ce_s; + + cart_ce_s <= not (cart_en_80_n_s and cart_en_A0_n_s and cart_en_C0_n_s and cart_en_E0_n_s);-- and not ext_cart_en_q; + cart_oe_s <= (not rd_n_s) and cart_ce_s; + cart_we_s <= (not wr_n_s) and cart_ce_s when multcart_q = '1' else '0'; + + -- RAM map + -- 1111111 + -- 65432109876543210 + -- 00000 - 01FFF = BIOS (8K) 0000xxxxxxxxxxxxx + -- 02000 - 03FFF = RAM (8K) 0001xxxxxxxxxxxxx + -- 08000 - 0FFFF = Multicart (32K) 01xxxxxxxxxxxxxxx + -- 10000 - 17FFF = Cartridge (32K) 10xxxxxxxxxxxxxxx + -- + ram_addr_o <= + -- 1111111 + -- 6543210 + "0000" & cpu_addr_s(12 downto 0) when bios_ce_s = '1' else +-- "0001" & cpu_addr_s(12 downto 0) when ram_ce_s = '1' else -- 8K linear RAM + "0001" & cpu_addr_s(12 downto 0) when ram_ce_s = '1' and multcart_q = '1' else -- 8K linear RAM + "0001100" & cpu_addr_s( 9 downto 0) when ram_ce_s = '1' and multcart_q = '0' else -- 1K mirrored RAM + -- "01" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and bios_q = '1' else + "01" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '1' and cart_oe_s = '1' else + "10" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '1' and cart_we_s = '1' else + "10" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '0' else + (others => '0'); + + ram_data_o <= d_from_cpu_s; + ram_ce_o <= ram_ce_s or bios_ce_s or cart_ce_s; + ram_we_o <= (not wr_n_s and ram_ce_s) or bios_we_s or cart_we_s; + ram_oe_o <= (not rd_n_s and ram_ce_s) or bios_oe_s or cart_oe_s; + + cart_addr_o <= cpu_addr_s(14 downto 0); + cart_oe_n_o <= not cart_oe_s; + cart_en_80_n_o <= cart_en_80_n_s or rd_n_s when cart_en_q = '1' else '1'; + cart_en_a0_n_o <= cart_en_A0_n_s or rd_n_s when cart_en_q = '1' else '1'; + cart_en_c0_n_o <= cart_en_C0_n_s or rd_n_s when cart_en_q = '1' else '1'; + cart_en_e0_n_o <= cart_en_E0_n_s or rd_n_s when cart_en_q = '1' else '1'; + + -- Address decoding + mem_access_s <= '1' when mreq_n_s = '0' and rfsh_n_s = '1' else '0'; + io_access_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' else '0'; + io_read_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' and rd_n_s = '0' else '0'; + io_write_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' and wr_n_s = '0' else '0'; + + -- memory + bios_ce_s <= '1' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "000" else '0'; -- BIOS => 0000 to 1FFF + ram_ce_s <= '1' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "011" else '0'; -- RAM => 6000 to 7FFF + cart_en_80_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "100" else '1'; -- Cartridge 80 => 8000 to 9FFF + cart_en_a0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "101" else '1'; -- Cartridge A0 => A000 to BFFF + cart_en_c0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "110" else '1'; -- Cartridge C0 => C000 to DFFF + cart_en_e0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "111" else '1'; -- Cartridge E0 => E000 to FFFF + + -- I/O + cfg_port_cs_s <= '1' when io_write_s = '1' and cpu_addr_s(7 downto 0) = X"52" else '0'; -- Config Port => 52 + ---machine_id_cs_s <= '1' when io_read_s = '1' and cpu_addr_s(7 downto 0) = X"53" else '0'; -- Machine ID read => 53 + cfg_page_cs_s <= '1' when io_access_s = '1' and cpu_addr_s(7 downto 0) = X"54" else '0'; -- Page port => 54 + ctrl_en_key_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "100" else '1'; -- Controller key set => 80 to 9F + vdp_w_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "101" else '1'; -- VDP write => A0 to BF + vdp_r_n_s <= '0' when io_read_s = '1' and cpu_addr_s(7 downto 5) = "101" else '1'; -- VDP read => A0 to BF + ctrl_en_joy_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "110" else '1'; -- Controller joy set => C0 to DF + psg_we_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "111" else '1'; -- PSG write => E0 to FF + ctrl_r_n_s <= '0' when io_read_s = '1' and cpu_addr_s(7 downto 5) = "111" else '1'; -- Controller read => E0 to FF + + -- Write I/O port 52 + process (por_n_i, reset_i, clock_i) + begin + if por_n_i = '0' then + cart_en_q <= '1'; + multcart_q <= '1'; + -- bios_q <= '1'; + elsif reset_i = '1' then + multcart_q <= '1'; + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' and cfg_port_cs_s = '1' then + cart_en_q <= d_from_cpu_s(2); + multcart_q <= d_from_cpu_s(1); + -- bios_q <= d_from_cpu_s(0); + end if; + end if; + end process; + + -- Write I/O port 54 + process (por_n_i, clock_i) + begin + if por_n_i = '0' then + cfg_page_r <= (others => '0'); + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' and cfg_page_cs_s = '1' and wr_n_s = '0' then + cfg_page_r <= d_from_cpu_s; + end if; + end if; + end process; + + -- MUX data CPU + d_to_cpu_s <= -- Memory + -- d_from_loader_s when loader_ce_s = '1' else + bios_data_i when bios_ce_s = '1' else + ram_data_i when ram_ce_s = '1' else + cart_data_i when cart_ce_s = '1' else + -- I/O + d_from_vdp_s when vdp_r_n_s = '0' else + d_from_ctrl_s when ctrl_r_n_s = '0' else + --machine_id_c when machine_id_cs_s = '1' else + cfg_page_r when cfg_page_cs_s = '1' else + (others => '1'); + + -- Debug + D_cpu_addr <= cpu_addr_s; + + +end architecture; diff --git a/Coleco - Vision_MiST/rtl/colecovision.vhd.bak b/Coleco - Vision_MiST/rtl/colecovision.vhd.bak new file mode 100644 index 00000000..f737e1ae --- /dev/null +++ b/Coleco - Vision_MiST/rtl/colecovision.vhd.bak @@ -0,0 +1,478 @@ +------------------------------------------------------------------------------- +-- +-- ColecoFPGA project +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity colecovision is + generic ( + num_maq_g : integer := 0; + compat_rgb_g : integer := 0 + ); + port ( + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + clk_en_5m37_i : in std_logic; + clk_en_3m58_i : in std_logic; + reset_i : in std_logic; -- Reset, tbem acionado quando por_n_i for 0 + por_n_i : in std_logic; -- Power-on Reset + -- Controller Interface --------------------------------------------------- + ctrl_p1_i : in std_logic_vector( 1 downto 0); + ctrl_p2_i : in std_logic_vector( 1 downto 0); + ctrl_p3_i : in std_logic_vector( 1 downto 0); + ctrl_p4_i : in std_logic_vector( 1 downto 0); + ctrl_p5_o : out std_logic_vector( 1 downto 0); + ctrl_p6_i : in std_logic_vector( 1 downto 0); + ctrl_p7_i : in std_logic_vector( 1 downto 0); + ctrl_p8_o : out std_logic_vector( 1 downto 0); + ctrl_p9_i : in std_logic_vector( 1 downto 0); + -- CPU RAM Interface ------------------------------------------------------ + ram_addr_o : out std_logic_vector(16 downto 0); -- 128K + ram_ce_o : out std_logic; + ram_oe_o : out std_logic; + ram_we_o : out std_logic; + ram_data_i : in std_logic_vector( 7 downto 0); + ram_data_o : out std_logic_vector( 7 downto 0); + -- Video RAM Interface ---------------------------------------------------- + vram_addr_o : out std_logic_vector(13 downto 0); -- 16K + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + vram_we_o : out std_logic; + vram_data_i : in std_logic_vector( 7 downto 0); + vram_data_o : out std_logic_vector( 7 downto 0); + -- Cartridge ROM Interface ------------------------------------------------ + cart_addr_o : out std_logic_vector(14 downto 0); -- 32K + cart_data_i : in std_logic_vector( 7 downto 0); + cart_oe_n_o : out std_logic; + cart_en_80_n_o : out std_logic; + cart_en_a0_n_o : out std_logic; + cart_en_c0_n_o : out std_logic; + cart_en_e0_n_o : out std_logic; + -- Audio Interface -------------------------------------------------------- + audio_o : out std_logic_vector(7 downto 0); + audio_signed_o : out signed(7 downto 0); + -- RGB Video Interface ---------------------------------------------------- + col_o : out std_logic_vector( 3 downto 0); + cnt_hor_o : out std_logic_vector( 8 downto 0); + cnt_ver_o : out std_logic_vector( 7 downto 0); + rgb_r_o : out std_logic_vector( 7 downto 0); + rgb_g_o : out std_logic_vector( 7 downto 0); + rgb_b_o : out std_logic_vector( 7 downto 0); + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + comp_sync_n_o : out std_logic; + -- SPI + spi_miso_i : in std_logic; + spi_mosi_o : out std_logic; + spi_sclk_o : out std_logic; + spi_cs_n_o : out std_logic; + sd_cd_n_i : in std_logic; + -- DEBUG + D_cpu_addr : out std_logic_vector(15 downto 0) + ); + +end entity; + +-- pragma translate_off +use std.textio.all; +-- pragma translate_on + +architecture Behavior of colecovision is + + -- Reset + signal reset_n_s : std_logic; + + -- CPU signals + signal clk_en_cpu_s : std_logic; + signal nmi_n_s : std_logic; + signal iorq_n_s : std_logic; + signal m1_n_s : std_logic; + signal m1_wait_q : std_logic; + signal rd_n_s : std_logic; + signal wr_n_s : std_logic; + signal mreq_n_s : std_logic; + signal rfsh_n_s : std_logic; + signal cpu_addr_s : std_logic_vector(15 downto 0); + signal d_to_cpu_s : std_logic_vector( 7 downto 0); + signal d_from_cpu_s : std_logic_vector( 7 downto 0); + + -- Address Decoder + signal mem_access_s : std_logic; + signal io_access_s : std_logic; + signal io_read_s : std_logic; + signal io_write_s : std_logic; + + -- machine id + signal machine_id_cs_s : std_logic; + constant machine_id_c : std_logic_vector(7 downto 0) := std_logic_vector(to_unsigned(num_maq_g, 8)); + + -- Config port + signal cfg_port_cs_s : std_logic; + signal cfg_page_cs_s : std_logic; + signal cfg_page_r : std_logic_vector(7 downto 0); + + -- BIOS + signal loader_ce_s : std_logic; + signal d_from_loader_s : std_logic_vector( 7 downto 0); + signal loader_q : std_logic; + signal multcart_q : std_logic; + signal bios_ce_s : std_logic; + signal bios_oe_s : std_logic; + signal bios_we_s : std_logic; + + -- RAM + signal ram_ce_s : std_logic; + + -- VDP18 signal + signal d_from_vdp_s : std_logic_vector( 7 downto 0); + signal vdp_r_n_s : std_logic; + signal vdp_w_n_s : std_logic; + + -- SN76489 signal + signal audio_s : signed(7 downto 0); + signal psg_ready_s : std_logic; + signal psg_we_n_s : std_logic; + + -- Controller signals + signal d_from_ctrl_s : std_logic_vector( 7 downto 0); + signal ctrl_r_n_s : std_logic; + signal ctrl_en_key_n_s : std_logic; + signal ctrl_en_joy_n_s : std_logic; + + -- SPI + signal d_from_spi_s : std_logic_vector( 7 downto 0); + signal spi_cs_s : std_logic; + signal spi_wr_s : std_logic; + signal spi_rd_s : std_logic; + + -- Cartridge + signal ext_cart_en_q : std_logic; + signal cart_en_80_n_s : std_logic; + signal cart_en_a0_n_s : std_logic; + signal cart_en_c0_n_s : std_logic; + signal cart_en_e0_n_s : std_logic; + signal ext_cart_ce_s : std_logic; + signal cart_ce_s : std_logic; + signal cart_oe_s : std_logic; + signal cart_we_s : std_logic; + +begin + + -- CPU + cpu: entity work.T80a + generic map ( + mode_g => 0 + ) + port map ( + clock_i => clock_i, + clock_en_i => clk_en_cpu_s, + reset_n_i => reset_n_s, + address_o => cpu_addr_s, + data_i => d_to_cpu_s, + data_o => d_from_cpu_s, + wait_n_i => '1', + int_n_i => '1', + nmi_n_i => nmi_n_s, + m1_n_o => m1_n_s, + mreq_n_o => mreq_n_s, + iorq_n_o => iorq_n_s, + rd_n_o => rd_n_s, + wr_n_o => wr_n_s, + refresh_n_o => rfsh_n_s, + halt_n_o => open, + busrq_n_i => '1', + busak_n_o => open + ); + + -- Loader + lr: entity work.loaderrom + port map ( + clk => clock_i, + addr => cpu_addr_s(12 downto 0), + data => d_from_loader_s + ); + + ----------------------------------------------------------------------------- + -- TMS9928A Video Display Processor + ----------------------------------------------------------------------------- + vdp18_b : entity work.vdp18_core + generic map ( + compat_rgb_g => compat_rgb_g + ) + port map ( + clock_i => clock_i, + clk_en_10m7_i => clk_en_10m7_i, + clk_en_5m37_i => clk_en_5m37_i, + reset_n_i => por_n_i, + csr_n_i => vdp_r_n_s, + csw_n_i => vdp_w_n_s, + mode_i => cpu_addr_s(0), + int_n_o => nmi_n_s, + cd_i => d_from_cpu_s, + cd_o => d_from_vdp_s, + vram_ce_o => vram_ce_o, + vram_oe_o => vram_oe_o, + vram_we_o => vram_we_o, + vram_a_o => vram_addr_o, + vram_d_o => vram_data_o, + vram_d_i => vram_data_i, + -- + col_o => col_o, + cnt_hor_o => cnt_hor_o, + cnt_ver_o => cnt_ver_o, + rgb_r_o => rgb_r_o, + rgb_g_o => rgb_g_o, + rgb_b_o => rgb_b_o, + hsync_n_o => hsync_n_o, + vsync_n_o => vsync_n_o, + comp_sync_n_o => comp_sync_n_o + ); + + ----------------------------------------------------------------------------- + -- SN76489 Programmable Sound Generator + ----------------------------------------------------------------------------- + psg_b : entity work.sn76489_top + generic map ( + clock_div_16_g => 1 + ) + port map ( + clock_i => clock_i, + clock_en_i => clk_en_3m58_i, + res_n_i => reset_n_s, + ce_n_i => psg_we_n_s, + we_n_i => psg_we_n_s, + ready_o => psg_ready_s, + d_i => d_from_cpu_s, + aout_o => audio_s + ); + + audio_o <= std_logic_vector(audio_s); + audio_signed_o <= audio_s; + + ----------------------------------------------------------------------------- + -- Controller ports + ----------------------------------------------------------------------------- + ctrl_b : entity work.cv_ctrl + port map ( + clock_i => clock_i, + clk_en_3m58_i => clk_en_3m58_i, + reset_n_i => reset_n_s, + ctrl_en_key_n_i => ctrl_en_key_n_s, + ctrl_en_joy_n_i => ctrl_en_joy_n_s, + a1_i => cpu_addr_s(1), + ctrl_p1_i => ctrl_p1_i, + ctrl_p2_i => ctrl_p2_i, + ctrl_p3_i => ctrl_p3_i, + ctrl_p4_i => ctrl_p4_i, + ctrl_p5_o => ctrl_p5_o, + ctrl_p6_i => ctrl_p6_i, + ctrl_p7_i => ctrl_p7_i, + ctrl_p8_o => ctrl_p8_o, + ctrl_p9_i => ctrl_p9_i, + d_o => d_from_ctrl_s + ); + + -- SPI + sd: entity work.spi + port map ( + clock_i => clk_en_3m58_i, + reset_i => reset_i, + addr_i => cpu_addr_s(0), + cs_i => spi_cs_s, + wr_i => spi_wr_s, + rd_i => spi_rd_s, + data_i => d_from_cpu_s, + data_o => d_from_spi_s, + -- SD card interface + spi_cs_o => spi_cs_n_o, + spi_sclk_o => spi_sclk_o, + spi_mosi_o => spi_mosi_o, + spi_miso_i => spi_miso_i, + sd_cd_n_i => sd_cd_n_i + ); + + spi_wr_s <= not wr_n_s; + spi_rd_s <= not rd_n_s; + + -- Glue + reset_n_s <= not reset_i; + clk_en_cpu_s <= clk_en_3m58_i and psg_ready_s and not m1_wait_q; + + + ----------------------------------------------------------------------------- + -- Process m1_wait + -- + -- Purpose: + -- Implements flip-flop U8A which asserts a wait states controlled by M1. + -- + m1_wait: process (clock_i, reset_n_s, m1_n_s) + begin + if reset_n_s = '0' or m1_n_s = '1' then + m1_wait_q <= '0'; + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' then + m1_wait_q <= not m1_wait_q; + end if; + end if; + end process m1_wait; + + ----------------------------------------------------------------------------- + -- Misc outputs + ----------------------------------------------------------------------------- + loader_ce_s <= not rd_n_s and bios_ce_s when loader_q = '1' else '0'; + bios_we_s <= not wr_n_s and bios_ce_s when loader_q = '1' else '0'; + bios_oe_s <= not rd_n_s and bios_ce_s; + + cart_ce_s <= not (cart_en_80_n_s and cart_en_A0_n_s and cart_en_C0_n_s and cart_en_E0_n_s) and not ext_cart_en_q; + ext_cart_ce_s <= not (cart_en_80_n_s and cart_en_A0_n_s and cart_en_C0_n_s and cart_en_E0_n_s) and ext_cart_en_q; + cart_oe_s <= (not rd_n_s) and cart_ce_s; + cart_we_s <= (not wr_n_s) and cart_ce_s when multcart_q = '1' else '0'; + + -- RAM map + -- 1111111 + -- 65432109876543210 + -- 00000 - 01FFF = BIOS (8K) 0000xxxxxxxxxxxxx + -- 02000 - 03FFF = RAM (8K) 0001xxxxxxxxxxxxx + -- 08000 - 0FFFF = Multicart (32K) 01xxxxxxxxxxxxxxx + -- 10000 - 17FFF = Cartridge (32K) 10xxxxxxxxxxxxxxx + -- + ram_addr_o <= + -- 1111111 + -- 6543210 + "0000" & cpu_addr_s(12 downto 0) when bios_ce_s = '1' else +-- "0001" & cpu_addr_s(12 downto 0) when ram_ce_s = '1' else -- 8K linear RAM + "0001" & cpu_addr_s(12 downto 0) when ram_ce_s = '1' and multcart_q = '1' else -- 8K linear RAM + "0001100" & cpu_addr_s( 9 downto 0) when ram_ce_s = '1' and multcart_q = '0' else -- 1K mirrored RAM + "01" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and loader_q = '1' else + "01" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '1' and cart_oe_s = '1' else + "10" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '1' and cart_we_s = '1' else + "10" & cpu_addr_s(14 downto 0) when cart_ce_s = '1' and multcart_q = '0' else + (others => '0'); + + ram_data_o <= d_from_cpu_s; + ram_ce_o <= ram_ce_s or bios_ce_s or cart_ce_s; + ram_we_o <= (not wr_n_s and ram_ce_s) or bios_we_s or cart_we_s; + ram_oe_o <= (not rd_n_s and ram_ce_s) or bios_oe_s or cart_oe_s; + + cart_addr_o <= cpu_addr_s(14 downto 0); + cart_oe_n_o <= not cart_oe_s; + cart_en_80_n_o <= cart_en_80_n_s or rd_n_s when ext_cart_en_q = '1' else '1'; + cart_en_a0_n_o <= cart_en_A0_n_s or rd_n_s when ext_cart_en_q = '1' else '1'; + cart_en_c0_n_o <= cart_en_C0_n_s or rd_n_s when ext_cart_en_q = '1' else '1'; + cart_en_e0_n_o <= cart_en_E0_n_s or rd_n_s when ext_cart_en_q = '1' else '1'; + + -- Address decoding + mem_access_s <= '1' when mreq_n_s = '0' and rfsh_n_s = '1' else '0'; + io_access_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' else '0'; + io_read_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' and rd_n_s = '0' else '0'; + io_write_s <= '1' when iorq_n_s = '0' and m1_n_s = '1' and wr_n_s = '0' else '0'; + + -- memory + bios_ce_s <= '1' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "000" else '0'; -- BIOS => 0000 to 1FFF + ram_ce_s <= '1' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "011" else '0'; -- RAM => 6000 to 7FFF + cart_en_80_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "100" else '1'; -- Cartridge 80 => 8000 to 9FFF + cart_en_a0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "101" else '1'; -- Cartridge A0 => A000 to BFFF + cart_en_c0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "110" else '1'; -- Cartridge C0 => C000 to DFFF + cart_en_e0_n_s <= '0' when mem_access_s = '1' and cpu_addr_s(15 downto 13) = "111" else '1'; -- Cartridge E0 => E000 to FFFF + + -- I/O + spi_cs_s <= '1' when io_access_s = '1' and cpu_addr_s(7 downto 1) = "0101000" else '0'; -- SPI (R/W) => 50 to 51 + cfg_port_cs_s <= '1' when io_write_s = '1' and cpu_addr_s(7 downto 0) = X"52" else '0'; -- Config Port => 52 + machine_id_cs_s <= '1' when io_read_s = '1' and cpu_addr_s(7 downto 0) = X"53" else '0'; -- Machine ID read => 53 + cfg_page_cs_s <= '1' when io_access_s = '1' and cpu_addr_s(7 downto 0) = X"54" else '0'; -- Page port => 54 + ctrl_en_key_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "100" else '1'; -- Controller key set => 80 to 9F + vdp_w_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "101" else '1'; -- VDP write => A0 to BF + vdp_r_n_s <= '0' when io_read_s = '1' and cpu_addr_s(7 downto 5) = "101" else '1'; -- VDP read => A0 to BF + ctrl_en_joy_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "110" else '1'; -- Controller joy set => C0 to DF + psg_we_n_s <= '0' when io_write_s = '1' and cpu_addr_s(7 downto 5) = "111" else '1'; -- PSG write => E0 to FF + ctrl_r_n_s <= '0' when io_read_s = '1' and cpu_addr_s(7 downto 5) = "111" else '1'; -- Controller read => E0 to FF + + -- Write I/O port 52 + process (por_n_i, reset_i, clock_i) + begin + if por_n_i = '0' then + ext_cart_en_q <= '1'; + multcart_q <= '1'; + loader_q <= '1'; + elsif reset_i = '1' then + multcart_q <= '1'; + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' and cfg_port_cs_s = '1' then + ext_cart_en_q <= d_from_cpu_s(2); + multcart_q <= d_from_cpu_s(1); + loader_q <= d_from_cpu_s(0); + end if; + end if; + end process; + + -- Write I/O port 54 + process (por_n_i, clock_i) + begin + if por_n_i = '0' then + cfg_page_r <= (others => '0'); + elsif rising_edge(clock_i) then + if clk_en_3m58_i = '1' and cfg_page_cs_s = '1' and wr_n_s = '0' then + cfg_page_r <= d_from_cpu_s; + end if; + end if; + end process; + + -- MUX data CPU + d_to_cpu_s <= -- Memory + d_from_loader_s when loader_ce_s = '1' else + ram_data_i when bios_ce_s = '1' else + ram_data_i when ram_ce_s = '1' else + ram_data_i when cart_ce_s = '1' else + cart_data_i when ext_cart_ce_s = '1' else + -- I/O + d_from_vdp_s when vdp_r_n_s = '0' else + d_from_ctrl_s when ctrl_r_n_s = '0' else + d_from_spi_s when spi_cs_s = '1' else + machine_id_c when machine_id_cs_s = '1' else + cfg_page_r when cfg_page_cs_s = '1' else + (others => '1'); + + -- Debug + D_cpu_addr <= cpu_addr_s; + + +end architecture; diff --git a/Coleco - Vision_MiST/rtl/cvBios.vhd b/Coleco - Vision_MiST/rtl/cvBios.vhd new file mode 100644 index 00000000..959f502e --- /dev/null +++ b/Coleco - Vision_MiST/rtl/cvBios.vhd @@ -0,0 +1,169 @@ +-- megafunction wizard: %ROM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: cvBios.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY cvBios IS + PORT + ( + address : IN STD_LOGIC_VECTOR (12 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +END cvBios; + + +ARCHITECTURE SYN OF cvbios IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + address_a : IN STD_LOGIC_VECTOR (12 DOWNTO 0); + clock0 : IN STD_LOGIC ; + q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(7 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => "./roms/CVbios.hex", + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 8192, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => "CLOCK0", + widthad_a => 13, + width_a => 8, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "./roms/CVbios.hex" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "13" +-- Retrieval info: PRIVATE: WidthData NUMERIC "8" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/CVbios.hex" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +-- Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL cvBios.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL cvBios.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL cvBios.cmp FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL cvBios.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL cvBios_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/Coleco - Vision_MiST/rtl/cv_ctrl.vhd b/Coleco - Vision_MiST/rtl/cv_ctrl.vhd new file mode 100644 index 00000000..5714c7c4 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/cv_ctrl.vhd @@ -0,0 +1,152 @@ +------------------------------------------------------------------------------- +-- +-- FPGA Colecovision +-- +-- $Id: cv_ctrl.vhd,v 1.3 2006/01/08 23:58:04 arnim Exp $ +-- +-- Controller Interface Module +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity cv_ctrl is + + port ( + clock_i : in std_logic; + clk_en_3m58_i : in std_logic; + reset_n_i : in std_logic; + ctrl_en_key_n_i : in std_logic; + ctrl_en_joy_n_i : in std_logic; + a1_i : in std_logic; + ctrl_p1_i : in std_logic_vector(2 downto 1); + ctrl_p2_i : in std_logic_vector(2 downto 1); + ctrl_p3_i : in std_logic_vector(2 downto 1); + ctrl_p4_i : in std_logic_vector(2 downto 1); + ctrl_p5_o : out std_logic_vector(2 downto 1); + ctrl_p6_i : in std_logic_vector(2 downto 1); + ctrl_p7_i : in std_logic_vector(2 downto 1); + ctrl_p8_o : out std_logic_vector(2 downto 1); + ctrl_p9_i : in std_logic_vector(2 downto 1); + d_o : out std_logic_vector(7 downto 0) + ); + +end cv_ctrl; + + +architecture rtl of cv_ctrl is + + signal sel_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the R/S flip-flop which selects the controller function. + -- + seq: process (clock_i, reset_n_i) + variable ctrl_en_v : std_logic_vector(1 downto 0); + begin + if reset_n_i = '0' then + sel_q <= '0'; + + elsif clock_i'event and clock_i = '1' then + if clk_en_3m58_i = '1' then + ctrl_en_v := ctrl_en_key_n_i & ctrl_en_joy_n_i; + case ctrl_en_v is + when "01" => + sel_q <= '0'; + when "10" => + sel_q <= '1'; + when others => + null; + end case; + end if; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Controller select + ----------------------------------------------------------------------------- + ctrl_p5_o(1) <= sel_q; + ctrl_p5_o(2) <= sel_q; + ctrl_p8_o(1) <= not sel_q; + ctrl_p8_o(2) <= not sel_q; + + + ----------------------------------------------------------------------------- + -- Process ctrl_read + -- + -- Purpose: + -- Read multiplexer for the controller lines. + -- NOTE: The quadrature decoders are not implemented! + -- + ctrl_read: process (a1_i, + ctrl_p1_i, ctrl_p2_i, ctrl_p3_i, ctrl_p4_i, + ctrl_p6_i, ctrl_p7_i) + variable idx_v : natural range 1 to 2; + begin + if a1_i = '0' then + -- read controller #1 + idx_v := 1; + else + -- read controller #2 + idx_v := 2; + end if; + + d_o <= '0' & -- quadrature information + ctrl_p6_i(idx_v) & + ctrl_p7_i(idx_v) & + '1' & -- quadrature information + ctrl_p3_i(idx_v) & + ctrl_p2_i(idx_v) & + ctrl_p4_i(idx_v) & + ctrl_p1_i(idx_v); + end process ctrl_read; + -- + ----------------------------------------------------------------------------- + + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/dac.vhd b/Coleco - Vision_MiST/rtl/dac.vhd new file mode 100644 index 00000000..560e85e2 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/dac.vhd @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------- +-- +-- Delta-Sigma DAC +-- +-- $Id: dac.vhd,v 1.1 2006/11/29 14:17:19 arnim Exp $ +-- +-- Refer to Xilinx Application Note XAPP154. +-- +-- This DAC requires an external RC low-pass filter: +-- +-- dac_o 0---XXXXX---+---0 analog audio +-- 2K2 | +-- === 10n +-- | +-- GND +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity dac is + + generic ( + msbi_g : integer := 7 + ); + port ( + clk_i : in std_logic; + res_i : in std_logic; + dac_i : in std_logic_vector(msbi_g downto 0); + dac_o : out std_logic + ); + +end entity; + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of dac is + + signal DACout_q : std_logic; + signal DeltaAdder_s, + SigmaAdder_s, + SigmaLatch_q, + DeltaB_s : unsigned(msbi_g+2 downto 0); + +begin + + DeltaB_s(msbi_g+2 downto msbi_g+1) <= SigmaLatch_q(msbi_g+2) & + SigmaLatch_q(msbi_g+2); + DeltaB_s(msbi_g downto 0) <= (others => '0'); + + DeltaAdder_s <= unsigned('0' & '0' & dac_i) + DeltaB_s; + + SigmaAdder_s <= DeltaAdder_s + SigmaLatch_q; + + seq: process (clk_i, res_i) + begin + if res_i = '1' then + SigmaLatch_q <= to_unsigned(2**(msbi_g+1), SigmaLatch_q'length); + DACout_q <= '0'; + + elsif clk_i'event and clk_i = '1' then + SigmaLatch_q <= SigmaAdder_s; + DACout_q <= SigmaLatch_q(msbi_g+2); + end if; + end process seq; + + dac_o <= DACout_q; + +end architecture; diff --git a/Coleco - Vision_MiST/rtl/dpSDRAM64Mb.vhd b/Coleco - Vision_MiST/rtl/dpSDRAM64Mb.vhd new file mode 100644 index 00000000..9d5ccfb7 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/dpSDRAM64Mb.vhd @@ -0,0 +1,371 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- +-- +-- SDRAM dual-port emulation +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity dpSDRAM64Mb is + generic ( + freq_g : integer := 100 + ); + port ( + clock_i : in std_logic; + reset_i : in std_logic; + refresh_i : in std_logic := '1'; + -- Port 0 + port0_cs_i : in std_logic; + port0_oe_i : in std_logic; + port0_we_i : in std_logic; + port0_addr_i : in std_logic_vector(22 downto 0); + port0_data_i : in std_logic_vector( 7 downto 0); + port0_data_o : out std_logic_vector( 7 downto 0); + -- Port 1 + port1_cs_i : in std_logic; + port1_oe_i : in std_logic; + port1_we_i : in std_logic; + port1_addr_i : in std_logic_vector(22 downto 0); + port1_data_i : in std_logic_vector( 7 downto 0); + port1_data_o : out std_logic_vector( 7 downto 0); + -- SDRAM in board + mem_cke_o : out std_logic; + mem_cs_n_o : out std_logic; + mem_ras_n_o : out std_logic; + mem_cas_n_o : out std_logic; + mem_we_n_o : out std_logic; + mem_udq_o : out std_logic; + mem_ldq_o : out std_logic; + mem_ba_o : out std_logic_vector( 1 downto 0); + mem_addr_o : out std_logic_vector(11 downto 0); + mem_data_io : inout std_logic_vector(15 downto 0) + ); +end entity; + +architecture Behavior of dpSDRAM64Mb is + + constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect + constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation + constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read + constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write + constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate + constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all + constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh + constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set + -- SD-RAM control signals + signal SdrCmd_s : std_logic_vector(3 downto 0); + signal SdrBa_s : std_logic_vector(1 downto 0); + signal SdrUdq_s : std_logic; + signal SdrLdq_s : std_logic; + signal SdrAdr_s : std_logic_vector(11 downto 0); + signal SdrDat_s : std_logic_vector(15 downto 0); + + signal ram0_req_s : std_logic; + signal ram0_ack_s : std_logic; + signal ram0_addr_s : std_logic_vector(22 downto 0); + signal ram0_din_s : std_logic_vector( 7 downto 0); + signal ram0_dout_s : std_logic_vector( 7 downto 0); + signal ram0_we_s : std_logic; + + signal ram1_req_s : std_logic; + signal ram1_ack_s : std_logic; + signal ram1_addr_s : std_logic_vector(22 downto 0); + signal ram1_din_s : std_logic_vector( 7 downto 0); + signal ram1_dout_s : std_logic_vector( 7 downto 0); + signal ram1_we_s : std_logic; + +begin + + -- Detectar pedido na porta 0 + process (reset_i, clock_i) + variable pcs_v : std_logic_vector(1 downto 0); + variable acesso_v : std_logic; + begin + if reset_i = '1' then + port0_data_o <= (others => '1'); + ram0_we_s <= '0'; + ram0_req_s <= '0'; + pcs_v := "00"; + elsif rising_edge(clock_i) then + if ram0_req_s = '1' and ram0_ack_s = '1' then + if ram0_we_s = '0' then + port0_data_o <= ram0_dout_s; + end if; + ram0_req_s <= '0'; + end if; + + if pcs_v = "01" then + ram0_addr_s <= port0_addr_i; + ram0_req_s <= '1'; + if port0_we_i = '1' then + ram0_din_s <= port0_data_i; + ram0_we_s <= '1'; + else + ram0_we_s <= '0'; + end if; + end if; + + acesso_v := port0_cs_i and (port0_oe_i or port0_we_i); + pcs_v := pcs_v(0) & acesso_v; + + end if; + end process; + + -- Detectar pedido na porta 1 + process (reset_i, clock_i) + variable pcs_v : std_logic_vector(1 downto 0); + variable acesso_v : std_logic; + begin + if reset_i = '1' then + port1_data_o <= (others => '1'); + ram1_we_s <= '0'; + ram1_req_s <= '0'; + pcs_v := "00"; + elsif rising_edge(clock_i) then + if ram1_req_s = '1' and ram1_ack_s = '1' then + if ram1_we_s = '0' then + port1_data_o <= ram1_dout_s; + end if; + ram1_req_s <= '0'; + end if; + + if pcs_v = "01" then + ram1_addr_s <= port1_addr_i; + ram1_req_s <= '1'; + if port1_we_i = '1' then + ram1_din_s <= port1_data_i; + ram1_we_s <= '1'; + else + ram1_we_s <= '0'; + end if; + end if; + + acesso_v := port1_cs_i and (port1_oe_i or port1_we_i); + pcs_v := pcs_v(0) & acesso_v; + + end if; + end process; + + ---------------------------- + process (clock_i) + + type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne ); + variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null; + variable SdrRoutineSeq_v : unsigned( 7 downto 0) := X"00"; + variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000"; + variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000"; + variable SdrPort_v : std_logic := '0'; + variable SdrAddress_v : std_logic_vector(22 downto 0); + + begin + + if rising_edge(clock_i) then + + ram0_ack_s <= '0'; + ram1_ack_s <= '0'; + + case SdrRoutine_v is + + when SdrRoutine_Null => + SdrCmd_s <= SdrCmd_xx_c; + SdrDat_s <= (others => 'Z'); + + if refreshDelayCounter_v = 0 then + SdrRoutine_v := SdrRoutine_Init; + end if; + + when SdrRoutine_Init => + if SdrRoutineSeq_v = X"00" then + SdrCmd_s <= SdrCmd_pr_c; + SdrAdr_s <= (others => '1'); + SdrBa_s <= "00"; + SdrUdq_s <= '1'; + SdrLdq_s <= '1'; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then + SdrCmd_s <= SdrCmd_re_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"14" then + SdrCmd_s <= SdrCmd_ms_c; + SdrAdr_s <= "00" & "1" & "00" & "010" & "0" & "000"; -- Single, Standard, CAS Latency=2, WT=0(seq), BL=1 + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"17" then + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := X"00"; + SdrRoutine_v := SdrRoutine_Idle; + else + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + end if; + + when SdrRoutine_Idle => + SdrCmd_s <= SdrCmd_xx_c; + SdrDat_s <= (others => 'Z'); + + if ram0_req_s = '1' and ram0_ack_s = '0' then + SdrPort_v := '0'; + SdrAddress_v := ram0_addr_s; + if ram0_we_s = '1' then + SdrRoutine_v := SdrRoutine_WriteOne; + else + SdrRoutine_v := SdrRoutine_ReadOne; + end if; + elsif ram1_req_s = '1' and ram1_ack_s = '0' then + SdrPort_v := '1'; + SdrAddress_v := ram1_addr_s; + if ram1_we_s = '1' then + SdrRoutine_v := SdrRoutine_WriteOne; + else + SdrRoutine_v := SdrRoutine_ReadOne; + end if; + elsif SdrRefreshCounter_v < 4096 and refresh_i = '1' then + SdrRoutine_v := SdrRoutine_RefreshAll; + SdrRefreshCounter_v := SdrRefreshCounter_v + 1; + end if; + when SdrRoutine_RefreshAll => + if SdrRoutineSeq_v = X"00" then + SdrCmd_s <= SdrCmd_re_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"06" then + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := X"00"; + SdrRoutine_v := SdrRoutine_Idle; + else + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + end if; + + when SdrRoutine_ReadOne => + if SdrRoutineSeq_v = X"00" then + SdrCmd_s <= SdrCmd_ac_c; + SdrBa_s <= SdrAddress_v(22 downto 21); + SdrAdr_s <= SdrAddress_v(20 downto 9); -- Row (12 bits) + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"02" then + SdrCmd_s <= SdrCmd_rd_c; + SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge + SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); -- Col (8 bits) + SdrUdq_s <= '0'; + SdrLdq_s <= '0'; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"05" then + if SdrPort_v = '0' then + if SdrAddress_v(0) = '0' then + ram0_dout_s <= mem_data_io(7 downto 0); + else + ram0_dout_s <= mem_data_io(15 downto 8); + end if; + ram0_ack_s <= '1'; + else + if SdrAddress_v(0) = '0' then + ram1_dout_s <= mem_data_io(7 downto 0); + else + ram1_dout_s <= mem_data_io(15 downto 8); + end if; + ram1_ack_s <= '1'; + end if; + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"06" then + SdrRoutineSeq_v := X"00"; + SdrRoutine_v := SdrRoutine_Idle; + else + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + end if; + + when SdrRoutine_WriteOne => + if SdrRoutineSeq_v = X"00" then + SdrCmd_s <= SdrCmd_ac_c; + SdrBa_s <= SdrAddress_v(22 downto 21); + SdrAdr_s <= SdrAddress_v(20 downto 9); + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"02" then + SdrCmd_s <= SdrCmd_wr_c; + SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge + SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); + SdrUdq_s <= not SdrAddress_v(0); + SdrLdq_s <= SdrAddress_v(0); + if SdrPort_v = '0' then + SdrDat_s <= ram0_din_s & ram0_din_s; + else + SdrDat_s <= ram1_din_s & ram1_din_s; + end if; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"03" then + if SdrPort_v = '0' then + ram0_ack_s <= '1'; + else + ram1_ack_s <= '1'; + end if; + SdrCmd_s <= SdrCmd_xx_c; + SdrDat_s <= (others => 'Z'); + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + elsif SdrRoutineSeq_v = X"05" then + SdrRoutineSeq_v := X"00"; + SdrRoutine_v := SdrRoutine_Idle; + else + SdrCmd_s <= SdrCmd_xx_c; + SdrRoutineSeq_v := SdrRoutineSeq_v + 1; + end if; + end case; + + refreshDelayCounter_v := refreshDelayCounter_v + 1; + + if refreshDelayCounter_v >= ( freq_g * 1000 * 64 ) then + refreshDelayCounter_v := x"000000"; + SdrRefreshCounter_v := x"0000"; + end if; + end if; + end process; + + mem_cke_o <= '1'; + mem_cs_n_o <= SdrCmd_s(3); + mem_ras_n_o <= SdrCmd_s(2); + mem_cas_n_o <= SdrCmd_s(1); + mem_we_n_o <= SdrCmd_s(0); + mem_udq_o <= SdrUdq_s; + mem_ldq_o <= SdrLdq_s; + mem_ba_o <= SdrBa_s; + mem_addr_o <= SdrAdr_s; + mem_data_io <= SdrDat_s; + +end architecture; \ No newline at end of file diff --git a/Coleco - Vision_MiST/rtl/hq2x.sv b/Coleco - Vision_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/Coleco - Vision_MiST/rtl/keyboard.vhd b/Coleco - Vision_MiST/rtl/keyboard.vhd new file mode 100644 index 00000000..f6b3ff87 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/keyboard.vhd @@ -0,0 +1,206 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.all; + +use work.kbd_pkg.all; + +entity colecoKeyboard is + port ( + clk : in std_logic; + reset : in std_logic; + -- inputs from PS/2 port + ps2_clk : inout std_logic; + ps2_data : inout std_logic; + -- user outputs + keys : out std_logic_vector(15 downto 0); + joy : out std_logic_vector(15 downto 0); + core_reload_o : out std_logic; + home_o : out std_logic + + ); +end colecoKeyboard; + +architecture SYN of colecoKeyboard is + + component ps2kbd + port ( + clk : in std_logic; + rst_n : in std_logic; + tick1us : in std_logic; + ps2_clk : in std_logic; + ps2_data : in std_logic; + + reset : out std_logic; + press : out std_logic; + release : out std_logic; + scancode : out std_logic_vector(7 downto 0) + ); + end component; + + signal rst_n : std_logic; + + -- 1us tick for PS/2 interface + signal tick1us : std_logic; + + signal ps2_reset : std_logic; + signal ps2_press : std_logic; + signal ps2_release : std_logic; + signal ps2_scancode : std_logic_vector(7 downto 0); + signal ctrl_s : std_logic := '0'; + signal alt_s : std_logic := '0'; + signal home_s : std_logic := '0'; + +begin + + rst_n <= not reset; + + -- produce a 1us tick from the 20MHz ref clock + process (clk, reset) + variable count : integer range 0 to 19; + begin + if reset = '1' then + tick1us <= '0'; + count := 0; + elsif rising_edge (clk) then + if count = 19 then + tick1us <= '1'; + count := 0; + else + tick1us <= '0'; + count := count + 1; + end if; + end if; + end process; + + latchInputs: process (clk, rst_n) + begin + -- note: all inputs are active HIGH + + if rst_n = '0' then + keys <= (others => '0'); + joy <= (others => '0'); + core_reload_o <= '0'; + home_s <= '0'; + elsif rising_edge (clk) then + core_reload_o <= '0'; + + if (ps2_press or ps2_release) = '1' then + case ps2_scancode is + -- this is not a valid scancode + -- but stuff the right button in here + when SCANCODE_X => + keys(0) <= ps2_press; + when SCANCODE_8 => + keys(1) <= ps2_press; + when SCANCODE_4 => + keys(2) <= ps2_press; + when SCANCODE_5 => + keys(3) <= ps2_press; + when SCANCODE_7 => + keys(5) <= ps2_press; + when SCANCODE_Q => -- '#' + keys(6) <= ps2_press; + when SCANCODE_2 => + keys(7) <= ps2_press; + when SCANCODE_W => -- '*' + keys(9) <= ps2_press; + when SCANCODE_0 => + keys(10) <= ps2_press; + when SCANCODE_9 => + keys(11) <= ps2_press; + when SCANCODE_3 => + keys(12) <= ps2_press; + when SCANCODE_1 => + keys(13) <= ps2_press; + when SCANCODE_6 => + keys(14) <= ps2_press; + ------------------------------------------------ + when SCANCODE_ESC => -- soft reset key : ESC + keys(8) <= ps2_press; + ------------------------------------------------- + when SCANCODE_UP => + joy(0) <= ps2_press; + when SCANCODE_DOWN => + joy(1) <= ps2_press; + when SCANCODE_LEFT => + joy(2) <= ps2_press; + when SCANCODE_RIGHT => + joy(3) <= ps2_press; + when SCANCODE_Z => + joy(4) <= ps2_press; + when SCANCODE_LCTRL => + ctrl_s <= ps2_press; + when SCANCODE_LALT => + alt_s <= ps2_press; + when SCANCODE_BACKSPACE => + if alt_s = '1' and ctrl_s = '1' then + core_reload_o <= '1'; + end if; + when SCANCODE_HOME => + home_s <= ps2_press; + when others => + null; + end case; + end if; -- ps2_press or release + if (ps2_reset = '1') then + keys <= (others => '0'); + joy <= (others => '0'); + end if; + end if; -- rising_edge (clk) + end process latchInputs; + + ps2kbd_inst : ps2kbd + port map ( + clk => clk, + rst_n => rst_n, + tick1us => tick1us, + ps2_clk => ps2_clk, + ps2_data => ps2_data, + + reset => ps2_reset, + press => ps2_press, + release => ps2_release, + scancode => ps2_scancode + ); + + home_o <= home_s; + +end SYN; diff --git a/Coleco - Vision_MiST/rtl/mist_io.v b/Coleco - Vision_MiST/rtl/mist_io.v new file mode 100644 index 00000000..1cfcb753 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/mist_io.v @@ -0,0 +1,496 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2015-2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output [1:0] img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input [1:0] sd_rd, + input [1:0] sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + + // ps2 alternative interface. + + // [8] - extended, [9] - pressed, [10] - toggles with every press/release + output reg [10:0] ps2_key = 0, + + // [24] - toggles with every event + output reg [24:0] ps2_mouse = 0, + + // ARM -> FPGA download + input ioctl_ce, + input ioctl_wait, + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output reg ioctl_wr = 0, + output reg [13:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg [1:0] mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire drive_sel = sd_rd[1] | sd_wr[1]; +wire [7:0] sd_cmd = { 4'h6, sd_conf, sd_sdhc, sd_wr[drive_sel], sd_rd[drive_sel] }; + +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +reg [7:0] spi_data_out; + +// SPI transmitter +always@(negedge SPI_SCK) spi_do <= spi_data_out[~bit_cnt]; + +reg [7:0] spi_data_in; +reg spi_data_ready = 0; + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + reg [6:0] sbuf; + reg [31:0] sd_lba_r; + reg drive_sel_r; + + if(CONF_DATA0) begin + bit_cnt <= 0; + byte_cnt <= 0; + spi_data_out <= core_type; + end + else + begin + bit_cnt <= bit_cnt + 1'd1; + sbuf <= {sbuf[5:0], SPI_DI}; + + // finished reading command byte + if(bit_cnt == 7) begin + if(!byte_cnt) cmd <= {sbuf, SPI_DI}; + + spi_data_in <= {sbuf, SPI_DI}; + spi_data_ready <= ~spi_data_ready; + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + + spi_data_out <= 0; + case({(!byte_cnt) ? {sbuf, SPI_DI} : cmd}) + // reading config string + 8'h14: if(byte_cnt < STRLEN) spi_data_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8]; + + // reading sd card status + 8'h16: if(byte_cnt == 0) begin + spi_data_out <= sd_cmd; + sd_lba_r <= sd_lba; + drive_sel_r <= drive_sel; + end else if (byte_cnt == 1) begin + spi_data_out <= drive_sel_r; + end else if(byte_cnt < 6) spi_data_out <= sd_lba_r[(5-byte_cnt)<<3 +:8]; + + // reading sd card write data + 8'h18: spi_data_out <= sd_buff_din; + endcase + end + end +end + +reg [31:0] ps2_key_raw = 0; +wire pressed = (ps2_key_raw[15:8] != 8'hf0); +wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0)); + +// transfer to clk_sys domain +always@(posedge clk_sys) begin + reg old_ss1, old_ss2; + reg old_ready1, old_ready2; + reg [2:0] b_wr; + reg got_ps2 = 0; + + old_ss1 <= CONF_DATA0; + old_ss2 <= old_ss1; + old_ready1 <= spi_data_ready; + old_ready2 <= old_ready1; + + sd_buff_wr <= b_wr[0]; + if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; + b_wr <= (b_wr<<1); + + if(old_ss2) begin + got_ps2 <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + sd_buff_addr <= 0; + if(got_ps2) begin + if(cmd == 4) ps2_mouse[24] <= ~ps2_mouse[24]; + if(cmd == 5) begin + ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]}; + if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed + if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released + if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed + end + end + end + else + if(old_ready2 ^ old_ready1) begin + + if(cmd == 8'h18 && ~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + + if(byte_cnt < 2) begin + + if (cmd == 8'h19) sd_ack_conf <= 1; + if((cmd == 8'h17) || (cmd == 8'h18)) sd_ack <= 1; + mount_strobe <= 0; + + if(cmd == 5) ps2_key_raw <= 0; + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_data_in; + 8'h02: joystick_0 <= spi_data_in; + 8'h03: joystick_1 <= spi_data_in; + + // store incoming ps2 mouse bytes + 8'h04: begin + got_ps2 <= 1; + case(byte_cnt) + 2: ps2_mouse[7:0] <= spi_data_in; + 3: ps2_mouse[15:8] <= spi_data_in; + 4: ps2_mouse[23:16] <= spi_data_in; + endcase + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_data_in; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + got_ps2 <= 1; + ps2_key_raw[31:0] <= {ps2_key_raw[23:0], spi_data_in}; + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_data_in; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_data_in; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_data_in; + b_wr <= 1; + end + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 2) stick_idx <= spi_data_in[2:0]; + else if(byte_cnt == 3) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_data_in; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_data_in; + end else if(byte_cnt == 4) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_data_in; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_data_in; + end + end + + // notify image selection + 8'h1c: mount_strobe[spi_data_in[0]] <= 1; + + // send image info + 8'h1d: if(byte_cnt<6) img_size[(byte_cnt-2)<<3 +:8] <= spi_data_in; + + // status, 32bit version + 8'h1e: if(byte_cnt<6) status[(byte_cnt-2)<<3 +:8] <= spi_data_in; + default: ; + endcase + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [13:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin +// addr <= ioctl_index ? 14'd9 : 14'd0; //.p files loaded at $4009, ROM is at 0 + addr <= 14'd0; + ioctl_download <= 1; + end else begin + ioctl_addr <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + ioctl_addr <= addr; + ioctl_dout <= {sbuf, SPI_DI}; + addr <= addr + 1'd1; + ioctl_wr <= 1; + end else + ioctl_wr <= 0; + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +endmodule diff --git a/Coleco - Vision_MiST/rtl/osd.v b/Coleco - Vision_MiST/rtl/osd.v new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Coleco - Vision_MiST/rtl/osd.v @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/Coleco - Vision_MiST/rtl/pll.qip b/Coleco - Vision_MiST/rtl/pll.qip new file mode 100644 index 00000000..aaef684a --- /dev/null +++ b/Coleco - Vision_MiST/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.0" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Coleco - Vision_MiST/rtl/pll.v b/Coleco - Vision_MiST/rtl/pll.v new file mode 100644 index 00000000..6fa5c561 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/pll.v @@ -0,0 +1,393 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + c1, + c2, + c3, + locked); + + input inclk0; + output c0; + output c1; + output c2; + output c3; + output locked; + + wire [4:0] sub_wire0; + wire sub_wire3; + wire [0:0] sub_wire8 = 1'h0; + wire [2:2] sub_wire5 = sub_wire0[2:2]; + wire [0:0] sub_wire4 = sub_wire0[0:0]; + wire [3:3] sub_wire2 = sub_wire0[3:3]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire c3 = sub_wire2; + wire locked = sub_wire3; + wire c0 = sub_wire4; + wire c2 = sub_wire5; + wire sub_wire6 = inclk0; + wire [1:0] sub_wire7 = {sub_wire8, sub_wire6}; + + altpll altpll_component ( + .inclk (sub_wire7), + .clk (sub_wire0), + .locked (sub_wire3), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 63, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 50, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 126, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 25, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 27, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 100, + altpll_component.clk2_phase_shift = "0", + altpll_component.clk3_divide_by = 27, + altpll_component.clk3_duty_cycle = 50, + altpll_component.clk3_multiply_by = 100, + altpll_component.clk3_phase_shift = "-2500", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_USED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "63" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "126" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "27" +// Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "27" +// 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: DUTY_CYCLE3 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "21.428572" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "5.357143" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "100.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 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: MIRROR_CLK3 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "50" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "25" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "100" +// Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "100" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "21.42857100" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "5.35714300" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 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: OUTPUT_FREQ_UNIT3 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_SHIFT3 STRING "-2500.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: PHASE_SHIFT_UNIT3 STRING "ps" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK3 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_CLK3 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_CLKENA3 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 "63" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "126" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "25" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "27" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "100" +// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "27" +// Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "100" +// Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "-2500" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_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_USED" +// 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: 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: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3" +// 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: @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: c3 0 0 0 0 @clk 0 0 1 3 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Coleco - Vision_MiST/rtl/pll.vhd.bak b/Coleco - Vision_MiST/rtl/pll.vhd.bak new file mode 100644 index 00000000..c0171a21 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/pll.vhd.bak @@ -0,0 +1,424 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll1.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll1 IS + PORT + ( + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC ; + locked : OUT STD_LOGIC + ); +END pll1; + + +ARCHITECTURE SYN OF pll1 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 ( + 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 => 16000000, + clk0_duty_cycle => 50, + clk0_multiply_by => 7142857, + clk0_phase_shift => "0", + clk1_divide_by => 12, + clk1_duty_cycle => 50, + clk1_multiply_by => 25, + clk1_phase_shift => "0", + clk2_divide_by => 12, + clk2_duty_cycle => 50, + clk2_multiply_by => 25, + clk2_phase_shift => "-2500", + compensate_clock => "CLK0", + inclk0_input_frequency => 20833, + intended_device_family => "Cyclone IV E", + lpm_hint => "CBX_MODULE_PREFIX=pll1", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_UNUSED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_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 ( + 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 "1" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1" +-- 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 "21.428572" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.000000" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "48.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 IV E" +-- 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 "deg" +-- 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 "1" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "1" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "21.42857100" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1" +-- 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 "-90.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll1.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 "16000000" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "7142857" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "12" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "25" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "12" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "25" +-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "-2500" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20833" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_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: 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: @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 pll1.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll1.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll1.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll1.cmp TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll1.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll1_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Coleco - Vision_MiST/rtl/ps2kbd.vhd b/Coleco - Vision_MiST/rtl/ps2kbd.vhd new file mode 100644 index 00000000..f3cbeaaa --- /dev/null +++ b/Coleco - Vision_MiST/rtl/ps2kbd.vhd @@ -0,0 +1,202 @@ +-- PS/2 serial port, input only +-- +-- Version : 0242 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.fpgaarcade.com +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : First release +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity ps2kbd is + port( + Rst_n : in std_logic; + Clk : in std_logic; + Tick1us : in std_logic; + PS2_Clk : in std_logic; + PS2_Data : in std_logic; + Press : out std_logic; + Release : out std_logic; + Reset : out std_logic; + ScanCode : out std_logic_vector(7 downto 0)); +end ps2kbd; + +architecture rtl of ps2kbd is + + signal PS2_Sample : std_logic; + signal PS2_Data_s : std_logic; + + signal RX_Bit_Cnt : unsigned(3 downto 0); + signal RX_Byte : unsigned(2 downto 0); + signal RX_ShiftReg : std_logic_vector(7 downto 0); + signal RX_Release : std_logic; + signal RX_Received : std_logic; + +begin + + ScanCode <= RX_ShiftReg; + + process (Clk, Rst_n) + variable PS2_Data_r : std_logic_vector(1 downto 0); + variable PS2_Clk_r : std_logic_vector(1 downto 0); + variable PS2_Clk_State : std_logic; + begin + if Rst_n = '0' then + PS2_Sample <= '0'; + PS2_Data_s <= '0'; + PS2_Data_r := "11"; + PS2_Clk_r := "11"; + PS2_Clk_State := '1'; + elsif Clk'event and Clk = '1' then + if Tick1us = '1' then + PS2_Sample <= '0'; + + -- Deglitch + if PS2_Data_r = "00" then + PS2_Data_s <= '0'; + end if; + if PS2_Data_r = "11" then + PS2_Data_s <= '1'; + end if; + if PS2_Clk_r = "00" then + if PS2_Clk_State = '1' then + PS2_Sample <= '1'; + end if; + PS2_Clk_State := '0'; + end if; + if PS2_Clk_r = "11" then + PS2_Clk_State := '1'; + end if; + + -- Double synchronise + PS2_Data_r(1) := PS2_Data_r(0); + PS2_Clk_r(1) := PS2_Clk_r(0); + PS2_Data_r(0) := PS2_Data; + PS2_Clk_r(0) := PS2_Clk; + end if; + end if; + end process; + + process (Clk, Rst_n) + variable Cnt : integer; + begin + if Rst_n = '0' then + RX_Bit_Cnt <= (others => '0'); + RX_ShiftReg <= (others => '0'); + RX_Received <= '0'; + Cnt := 0; + elsif Clk'event and Clk = '1' then + RX_Received <= '0'; + if Tick1us = '1' then + + if PS2_Sample = '1' then + if RX_Bit_Cnt = "0000" then + if PS2_Data_s = '0' then -- Start bit + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + end if; + elsif RX_Bit_Cnt = "1001" then -- Parity bit + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + -- Ignoring parity + elsif RX_Bit_Cnt = "1010" then -- Stop bit + if PS2_Data_s = '1' then + RX_Received <= '1'; + end if; + RX_Bit_Cnt <= "0000"; + else + RX_Bit_Cnt <= RX_Bit_Cnt + 1; + RX_ShiftReg(6 downto 0) <= RX_ShiftReg(7 downto 1); + RX_ShiftReg(7) <= PS2_Data_s; + end if; + end if; + + -- TimeOut + if PS2_Sample = '1' then + Cnt := 0; + elsif Cnt = 127 then + RX_Bit_Cnt <= "0000"; + Cnt := 0; + else + Cnt := Cnt + 1; + end if; + end if; + end if; + end process; + + process (Clk, Rst_n) + begin + if Rst_n = '0' then + Press <= '0'; + Release <= '0'; + Reset <= '0'; + RX_Byte <= (others => '0'); + RX_Release <= '0'; + elsif Clk'event and Clk = '1' then + Press <= '0'; + Release <= '0'; + Reset <= '0'; + if RX_Received = '1' then + RX_Byte <= RX_Byte + 1; + if RX_ShiftReg = x"F0" then + RX_Release <= '1'; + elsif RX_ShiftReg = x"E0" then + else + RX_Release <= '0'; + -- Normal key press + if RX_Release = '0' then + Press <= '1'; + end if; + -- Normal key release + if RX_Release = '1' then + Release <= '1'; + end if; + end if; + if RX_ShiftReg = x"aa" then + Reset <= '1'; + end if; + end if; + end if; + end process; + +end; diff --git a/Coleco - Vision_MiST/rtl/ps2kbd_pkg.vhd b/Coleco - Vision_MiST/rtl/ps2kbd_pkg.vhd new file mode 100644 index 00000000..44c59f3f --- /dev/null +++ b/Coleco - Vision_MiST/rtl/ps2kbd_pkg.vhd @@ -0,0 +1,140 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2002, Daniel Wallner (jesus@opencores.org) +-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package kbd_pkg is + + constant SCANCODE_BACKQUOTE : std_logic_vector(7 downto 0) := X"0E"; + constant SCANCODE_A : std_logic_vector(7 downto 0) := X"1C"; + constant SCANCODE_B : std_logic_vector(7 downto 0) := X"32"; + constant SCANCODE_C : std_logic_vector(7 downto 0) := X"21"; + constant SCANCODE_D : std_logic_vector(7 downto 0) := X"23"; + constant SCANCODE_E : std_logic_vector(7 downto 0) := X"24"; + constant SCANCODE_F : std_logic_vector(7 downto 0) := X"2B"; + constant SCANCODE_G : std_logic_vector(7 downto 0) := X"34"; + constant SCANCODE_H : std_logic_vector(7 downto 0) := X"33"; + constant SCANCODE_I : std_logic_vector(7 downto 0) := X"43"; + constant SCANCODE_J : std_logic_vector(7 downto 0) := X"3B"; + constant SCANCODE_K : std_logic_vector(7 downto 0) := X"42"; + constant SCANCODE_L : std_logic_vector(7 downto 0) := X"4B"; + constant SCANCODE_M : std_logic_vector(7 downto 0) := X"3A"; + constant SCANCODE_N : std_logic_vector(7 downto 0) := X"31"; + constant SCANCODE_O : std_logic_vector(7 downto 0) := X"44"; + constant SCANCODE_P : std_logic_vector(7 downto 0) := X"4D"; + constant SCANCODE_Q : std_logic_vector(7 downto 0) := X"15"; + constant SCANCODE_R : std_logic_vector(7 downto 0) := X"2D"; + constant SCANCODE_S : std_logic_vector(7 downto 0) := X"1B"; + constant SCANCODE_T : std_logic_vector(7 downto 0) := X"2C"; + constant SCANCODE_U : std_logic_vector(7 downto 0) := X"3C"; + constant SCANCODE_V : std_logic_vector(7 downto 0) := X"2A"; + constant SCANCODE_W : std_logic_vector(7 downto 0) := X"1D"; + constant SCANCODE_X : std_logic_vector(7 downto 0) := X"22"; + constant SCANCODE_Y : std_logic_vector(7 downto 0) := X"35"; + constant SCANCODE_Z : std_logic_vector(7 downto 0) := X"1A"; + constant SCANCODE_0 : std_logic_vector(7 downto 0) := X"45"; + constant SCANCODE_1 : std_logic_vector(7 downto 0) := X"16"; + constant SCANCODE_2 : std_logic_vector(7 downto 0) := X"1E"; + constant SCANCODE_3 : std_logic_vector(7 downto 0) := X"26"; + constant SCANCODE_4 : std_logic_vector(7 downto 0) := X"25"; + constant SCANCODE_5 : std_logic_vector(7 downto 0) := X"2E"; + constant SCANCODE_6 : std_logic_vector(7 downto 0) := X"36"; + constant SCANCODE_7 : std_logic_vector(7 downto 0) := X"3D"; + constant SCANCODE_8 : std_logic_vector(7 downto 0) := X"3E"; + constant SCANCODE_9 : std_logic_vector(7 downto 0) := X"46"; + constant SCANCODE_QUOTE : std_logic_vector(7 downto 0) := X"52"; + constant SCANCODE_SEMICOLON : std_logic_vector(7 downto 0) := X"4C"; + constant SCANCODE_COMMA : std_logic_vector(7 downto 0) := X"41"; + constant SCANCODE_MINUS : std_logic_vector(7 downto 0) := X"4E"; + constant SCANCODE_PERIOD : std_logic_vector(7 downto 0) := X"49"; + constant SCANCODE_SLASH : std_logic_vector(7 downto 0) := X"4A"; + constant SCANCODE_ENTER : std_logic_vector(7 downto 0) := X"5A"; + constant SCANCODE_HOME : std_logic_vector(7 downto 0) := X"6C"; + constant SCANCODE_INS : std_logic_vector(7 downto 0) := X"70"; -- E0 + constant SCANCODE_PGUP : std_logic_vector(7 downto 0) := X"7D"; -- E0 + constant SCANCODE_PGDN : std_logic_vector(7 downto 0) := X"7A"; -- E0 + constant SCANCODE_UP : std_logic_vector(7 downto 0) := X"75"; -- E0 + constant SCANCODE_DOWN : std_logic_vector(7 downto 0) := X"72"; -- E0 + constant SCANCODE_LEFT : std_logic_vector(7 downto 0) := X"6B"; -- E0 + constant SCANCODE_BACKSPACE : std_logic_vector(7 downto 0) := X"66"; + constant SCANCODE_RIGHT : std_logic_vector(7 downto 0) := X"74"; -- E0 + constant SCANCODE_SPACE : std_logic_vector(7 downto 0) := X"29"; + constant SCANCODE_LSHIFT : std_logic_vector(7 downto 0) := X"12"; + constant SCANCODE_RSHIFT : std_logic_vector(7 downto 0) := X"59"; + constant SCANCODE_TAB : std_logic_vector(7 downto 0) := X"0D"; + constant SCANCODE_ESC : std_logic_vector(7 downto 0) := X"76"; + constant SCANCODE_EQUALS : std_logic_vector(7 downto 0) := X"55"; + constant SCANCODE_F1 : std_logic_vector(7 downto 0) := X"05"; + constant SCANCODE_F2 : std_logic_vector(7 downto 0) := X"06"; + constant SCANCODE_F3 : std_logic_vector(7 downto 0) := X"04"; + constant SCANCODE_F4 : std_logic_vector(7 downto 0) := X"0C"; + constant SCANCODE_F5 : std_logic_vector(7 downto 0) := X"03"; + constant SCANCODE_F6 : std_logic_vector(7 downto 0) := X"0B"; + constant SCANCODE_F7 : std_logic_vector(7 downto 0) := X"83"; + constant SCANCODE_F8 : std_logic_vector(7 downto 0) := X"0A"; + constant SCANCODE_F9 : std_logic_vector(7 downto 0) := X"01"; + constant SCANCODE_F10 : std_logic_vector(7 downto 0) := X"09"; + constant SCANCODE_F11 : std_logic_vector(7 downto 0) := X"78"; + constant SCANCODE_F12 : std_logic_vector(7 downto 0) := X"07"; + constant SCANCODE_CAPSLOCK : std_logic_vector(7 downto 0) := X"58"; + constant SCANCODE_BACKSLASH : std_logic_vector(7 downto 0) := X"5D"; + constant SCANCODE_LCTRL : std_logic_vector(7 downto 0) := X"14"; + constant SCANCODE_LALT : std_logic_vector(7 downto 0) := X"11"; + alias SCANCODE_TILDE : std_logic_vector(7 downto 0) is SCANCODE_BACKQUOTE; + constant SCANCODE_OPENBRKT : std_logic_vector(7 downto 0) := X"54"; + alias SCANCODE_OPENBRACE : std_logic_vector(7 downto 0) is SCANCODE_OPENBRKT; + constant SCANCODE_CLOSEBRKT : std_logic_vector(7 downto 0) := X"5B"; + alias SCANCODE_CLOSEBRACE : std_logic_vector(7 downto 0) is SCANCODE_CLOSEBRKT; + constant SCANCODE_END : std_logic_vector(7 downto 0) := X"69"; -- E0 + alias SCANCODE_PAD0 : std_logic_vector(7 downto 0) is SCANCODE_INS; + alias SCANCODE_PAD1 : std_logic_vector(7 downto 0) is SCANCODE_END; + alias SCANCODE_PAD2 : std_logic_vector(7 downto 0) is SCANCODE_DOWN; + alias SCANCODE_PAD3 : std_logic_vector(7 downto 0) is SCANCODE_PGDN; + alias SCANCODE_PAD4 : std_logic_vector(7 downto 0) is SCANCODE_LEFT; + constant SCANCODE_PAD5 : std_logic_vector(7 downto 0) := X"73"; + alias SCANCODE_PAD6 : std_logic_vector(7 downto 0) is SCANCODE_RIGHT; + alias SCANCODE_PAD7 : std_logic_vector(7 downto 0) is SCANCODE_HOME; + alias SCANCODE_PAD8 : std_logic_vector(7 downto 0) is SCANCODE_UP; + alias SCANCODE_PAD9 : std_logic_vector(7 downto 0) is SCANCODE_PGUP; + + type kbd_row is array (natural range <>) of std_logic_vector(7 downto 0); + type kbd_col is array (natural range <>) of std_logic_vector(7 downto 0); + +end; diff --git a/Coleco - Vision_MiST/rtl/roms/COLECO-SHORT-DELAY.BIO b/Coleco - Vision_MiST/rtl/roms/COLECO-SHORT-DELAY.BIO new file mode 100644 index 0000000000000000000000000000000000000000..6a967b55d668bb8ba4aed4a42281e885fd4de28b GIT binary patch literal 8192 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 literal 0 HcmV?d00001 diff --git a/Coleco - Vision_MiST/rtl/roms/CVbios.hex b/Coleco - Vision_MiST/rtl/roms/CVbios.hex new file mode 100644 index 00000000..e9c2fd9c --- /dev/null +++ b/Coleco - Vision_MiST/rtl/roms/CVbios.hex @@ -0,0 +1,258 @@ +:020000040000FA +:2000000031B973C36E00FFFFC30C80FFFFFFFFFFC30F80FFFFFFFFFFC31280FFFFFFFFFF6D +:20002000C31580FFFFFFFFFFC31880FFFFFFFFFFC31B80FFFFFFFFFFC31E802AC873CB7CB1 +:200040002806CB4428061807CB442803371801B7CB15CB1422C8737DC9FFFFFFFFFFFFFF7A +:20006000FFFFFFFFFFFFC321803CAB1623162A00807DFE55C281007CFEAAC281002A0A8014 +:20008000E9CDD61F21330022C873CD05113E0032C67332C773C31913E1E3E50A6F030A03EB +:2000A00067E3D55E235623E57BB2C2B700E15E235623E5EB5E2356030A07D2DA0003E1E393 +:2000C00073237223D1E32BAFBCC2D000BDCAD600E3E5EBC3A300E1EBE3E9E1E3E50F670BE1 +:2000E0000A6FE303031A772313E32BAFBDC2F400BCCAF800E3C3E500E1C3C400DD7E07FED6 +:20010000002009DD7E053DC8DD7705C9DDE5E11E06160019CD90012015CDA6012B7E3DC884 +:20012000772B2BDD7E07CDB10123CB96F6FFC9DD7E08FE00C8DDE5E116001E0919CD90014F +:200140002021CDA6012BCD900128167EE6F05F2B2B2B2B7EE6F0835F7EE60FB377F6FF18E4 +:20016000023600C9DD7E04CB6128040F0F0F0FE60FB1D3FFC9DD7E03E60FB2D3FFDD7E0315 +:20018000E6F057DD7E04E60FB20F0F0F0FD3FFC93E00ED67D601F5ED6FF1C93E00ED6FD671 +:2001A00001F5ED67F1C97EE6F0470F0F0F0FB077C90600CB7F280206FF8677237E88772B2D +:2001C000C92A20702B2B480600CB01CB01095E2356D5DDE1C9DD7501DD74021AE63F47DD1B +:2001E0007E00E6C0B0DD7700C9DD7E00FEFFC8E63FFE3EC0DDE5E1235E2356EBC902000179 +:2002000000020001FD0111BA73CD98003ABA73472ABB7322207023235E2356EB1E0A16003C +:2002200036FF1910FB3600214C022222702224702226702228703EFF322A703E9FD3FF3EEE +:20024000BFD3FF3EDFD3FF3EFFD3FFC9FF01000100014D0211BA73CD98003ABA7347C5CD12 +:20026000C101DD7E00E63FC1B8C8DD70002B2B562B5EDD7301DD7202CD5F03CD9502C90675 +:2002800001CDC1013E00DDBE00C8CDD6021E0A1600DD1918EFDDE5214C02222270222470B2 +:2002A0002226702228700601CDC101DD7E00FE002821FEFF2815DD7E00E6C00707075F16CF +:2002C0000021227019DDE5D17323721E0A1600DD1918D8DDE1C9CDE901FEFFC8FE3E20062E +:2002E0001E07160019E9CD2F01CDFC002011DD7E00F5CD5F03C1DD7E00B82803CD9502C91F +:200300003E9F0E901680DD2A2470CD4E033EBF0EB016A0DD2A2670CD4E033EDF0ED016C016 +:20032000DD2A2870CD4E033EFF0EF0DD2A2270DD5E001C2004D3FF1814CD6401DD7E04E63C +:200340000F212A70BE2806770EE0CD6401C9DD5E001C2004D3FF1806CD6401CD7501C9DD01 +:200360007E00E63FF5DD3600FFDD6E01DD66027E47CB6F281CC5E61F23DD7501DD7402DD8F +:200380003604F0DD7705DD360700DD360800C36104CB67280FCB5F2805C1CD5E02C93EFFC9 +:2003A000F5C36104E63CFE042028FDE1FDE5C5235EDD73012356DD720223FDE5F1D5FDE1EA +:2003C00011C603D5FDE916001E07FD19116104D5FDE9C578E603FE00202023232323DD75C4 +:2003E00001DD74022B110500CD7804010300EDB8DD360700DD3608001867FE01201B1E0664 +:20040000160019DD7501DD74022B1CCD7804010500EDB8DD3608001848FE0220281E0616CF +:200420000019F1F5E6C020012BDD7501DD74022B1E09CD7804010200EDB83E00121B1B0E4E +:2004400003EDB8181C1E08160019DD7501DD74022BDDE5FDE11E09FD19FDE5D1010700ED15 +:20046000B8DDE5E1F1C1FEFFC857E63FFE042002063E7AE6C0B077C9DDE5FDE1FD19FDE51E +:20048000D1C90200FEFF010001820411BA73CD98002ABA735E2356EB3ABC73FE00280337B6 +:2004A0001801B75E2356234E2346233E00021AF5E60FCAE7043DCAF1053DCA00063DCA008E +:2004C000063D2802F1C91A1F1F1F1FE60F475E235623B72810F1F5E5C5EBCDA304C1E15E4B +:2004E00023562310F0F1C9CD72051A6F131A85FD77052600F13038F53AC373CB4F2831EB6C +:20050000444D6E2600E5292929E5030A6F030A67C1FDE1F1CB7F2803CD9405CDE805CB771A +:200520002803CD9405CDE805CB6F2803CD9405C9EB4E0600C5FDE1237E23666FE5C5D5FDE5 +:20054000E53E03CD271CC1E15D54092BCB3CCB1DCB3CCB1DCB3CCB1DCB2BCB2BCB2BB7ED8B +:200560005223E5FDE1E1292929C1093E04CD271CF1C9C5FDE1D55E2356CB7A20147AFE7061 +:2005800038063E8012180A80218705010100CD011DD113C9F5C5FDE5D5E53E03CD271CE1DC +:2005A000D1FDE1C1F1F5C5FDE5D5E5CB67200D093E04CD271CE1D1FDE1C1F1C9094D44FD28 +:2005C000E5E1E50AC50108002A06800906082B7710FCD5FD2101003E04CD271CD1C1130335 +:2005E000E12B7CB520DC18CDC5010001EB09EBC1C9CD7205131AFD7705131AFD7706F1C962 +:200600000303030303EB237E5F1600D5235E23562386024E0600C5FDE1EBD1F1D03E01CDD0 +:20062000271CC9DDE52ACD73D1732372237023EB3ACB733C21CA73BE200D3E0032CB732A33 +:20064000D17322CD73180732CB73ED53CD73C902000100FEFF014F0611BA73CD98003ABA2F +:20066000732ABB7332CA733E0032CB7332CC7322D17322CD7322CF73C93AC673F53E003254 +:20068000C6733ACC7321CB73BE28312ACF735E2356234623D5DDE1E5CDE3063ACC733C215F +:2006A000CA73BE200E3E0032CC732AD17322CF73E1180732CC73E122CF7318C6F132C673A0 +:2006C000C902000200010001C10611BA73CD9800DD2ABA733ABC73473AC673FE012004CD9A +:2006E0002306C9DD6601DD6E007E4FE60FCAFF063DCA870A3DCADF083DCA5509C3A20EDDAD +:200700005603DD5E02D5FDE1FD5602FD5E01CDE8074BFD5604FD5E03CDE80743FD5E0016B3 +:200720000019191E05195E2356EBC5D14E234623DD7E05CB7F2804CD0B08C9C5D5E5FE70AD +:200740002802380767DD6E047E18352A0680DD5605DD5E04E5D5E5010400CD3E1DE17EFE5F +:20076000802003D11819232346235E160023EB18012910FDE5C1EBD113131313CD3E1DE19D +:200780007EFE80280F5E2356234E234623DDE5CD0B08DDE1E1D1C1C5D5E5DD6605DD6E0469 +:2007A0003E70BC38032A06807323722371237023DDE5CD9808DDE1E1D1C1DDE5CD0B08DDB3 +:2007C000E1DD56053E70BA281E381CDD5E04D92A0680E523235E16002346EB18012910FDF4 +:2007E000E5D9C1E1CD011DC9E5CB2ACB1BCB2ACB1BCB2ACB1BCB7A20092180FF19E1D01E79 +:200800007FC921800019E1D81E80C9C5D5E5D9E1D1C1CDC008D97BCB7F2003FE20D081CB5B +:200820007FC0B7C8CB7B28207983D5FE2138023E205F1600D5FDE1D17BD9C5ED444F06004C +:2008400009EB09EBC1D9181C7B81FE1F280F380D3E2093D55F1600D5FDE1D11807C50600A4 +:20086000C5FDE1C11E007A83CB7F2019FE183015C5D5D9C5D5E5FDE53E02CD271CFDE1E138 +:20088000D1C1D9D1C1D9C5060009EB01200009EBC1D91C7BB820CFC9CDC008C50600C5FDEB +:2008A000E1C1C5D5E5FDE53E02CDA31BFDE1E1D1C1C5060009012000EB09EBC10520E3C9B3 +:2008C000E5CB7A280426FF180226006A2929292929CB7B280416FF1802160019EBE1C9FDC4 +:2008E0002A0680DD6E02DD6603110100194E234678FE00280BFEFFC2540A79FEF9FA540A45 +:20090000234E234678FE00280BFEFFC2540A79FEF9FA540A2B2B7EFE00CACA092B4E23461E +:20092000210800097DFD7701DD6E00DD660111050019EB1A6F131A67E5DD6E02DD66031144 +:200940000000197ECB270100004FE1097EF680FD7703C3000AFD2A0680DD6E02DD6603114B +:200960000100194E234678FE00280BFEFFC2540A79FEE1FA540A234E234678FE00280BFEAF +:20098000FFC2540A79FEE1FA540A2B2B7EFE00CACA092B4E2346212000097DFD7701DD6EB0 +:2009A00000DD660111050019EB1A6F131A67E5DD6E02DD6603110000197ECB270100004F5A +:2009C000E1097EF680FD77031836DD6E02DD6603110100197EFD7701DD6E00DD660111051E +:2009E0000019EB1A6F131A67E5DD6E02DD6603110000197ECB270100004FE1097EFD770395 +:200A0000DD6E02DD6603110300197EFD7700DD6E00DD660111050019EB1A6F131A67E5DD9C +:200A20006E02DD6603110000197ECB270100004FE109237EDD6E00DD66011101001986FD4E +:200A40007702AF1600DD5E04FDE5E1FD210100CDBE1F1832FDE5DDE5FDE5FDE5AF1600DD39 +:200A60005E04E1FD210100CDBB1F3E00FDE1FD77013E80FD7703AF1600DDE1DD5E04E1FD07 +:200A8000210100CDBE1FC9FD2A06803AC373CB4F2004CBB81802CBF8FD7003E5DD6603DD8E +:200AA0006E027EFD7704EE8077235E7BE607ED44C608FD77012356CDE807FD7311235E7BDC +:200AC000E607FD77002356CDE807FD73122A068011130019FD5612FD5E11010303CD9808CC +:200AE000DD5605DD5E04DD7E06DDE1FD2A0680FD7705D52A068001060009010B007AFE70B1 +:200B00003005CDE21F1803EBEDB02A068011130019D9ED5B068021080019EBD9FD2A0680E8 +:200B2000FD4E0506097E91FE12300EFE093802D609D96F2600197ED9772310E9D12A0680E7 +:200B400001110009010B007AFE703005CDDF1F1802EDB0DDE5ED5B068021130019EB0114F2 +:200B6000000906091A13D511080019E55F16004FC53E09900600D60338030418F978FD2A16 +:200B80000680FD8612FDCB037EFD21010020293E03CDBB1FC12A0680C51184001959CB3B5E +:200BA000CB3BCB3B16003E09904F060009FD2101003E04CDBB1F1821CB2FCB2FCB2FFE03AE +:200BC000301757D5E53E03CDBB1FE111680019D1FD2101003E04CDBB1FC1E1D11086DDE1C2 +:200BE000D9DD5603DD5E02DD4605DD4E04D9DDE5E1FD2A0680FD7E04874F0600110600199E +:200C0000095E23562A0680017C0009E5C50105007AFE703005CDE21F1803EBEDB0FD2A0653 +:200C200080C1FD09FD7E04FD2A0680FD7702D12A06800164000906041ADDBE01D53016D928 +:200C40008787876F260009E5D9D1EBC5010800EDB0C1EB1830DD9601D98787876F260019F8 +:200C6000E5D9D17AFE703014C5E5D5010800CDE21F010800E109EBE109C11809EBC5010800 +:200C800000EDB0C1EBD11310AFFD2A0680ED5B0680211C0019FD4E00060009E5DDE1216415 +:200CA0000019E53E1008E15623E5010F00095EEBFD4601AF05FABC0C291718F85FCD2F0ECC +:200CC000FD7E003CFD7700FE082804FE102005011000DD09DD23083D28030818C9E1FDCB8B +:200CE000037E201F2A068001840009FD5602FDCB034E20040E0F18020E0006097EA1B277C8 +:200D00002310F9FD7E05FDCB047E2802C6094F2A0680111300190609773C2310FBFDCB03ED +:200D20007E20735916002A0680011C0009FD2109003E03CDBE1FFD2A06802A068001840069 +:200D400009DD2A0680011300DD090609DD7E00DD23CB3FCB3FCB3F5F1600C53E0990060064 +:200D6000FE033805D6030418F7FD8611FE20301778FD8612FE18300FDDE5E53E04FD2101E6 +:200D800000CDBE1FE1DDE1C123130578FE0020BCFD2A068018540600C5798080804F21006F +:200DA00000111800783DFAAC0D1918F9FD2A0680FD7E1280FE18302BCB3FCB3FCB3F57597F +:200DC000D5011C0009ED4B068009E5FD2103003E03CDBE1FE111680019D1FD2103003E04B9 +:200DE000CDBE1FC10478FE0320AEFD2A0680FD460678FE802821FD4E07FD6611FD6E12B70E +:200E0000ED4228132A068011080019FD5E06FD5607010303CD0B08FD2A06802A0680111363 +:200E20000019FD5E11FD5612010303CD0B08C9FDCB03462016DDB600DD77007CDDB608DDF6 +:200E400077087DDDB610DD77101814B72803DD77007CB72803DD77087DB72803DD7710FDB3 +:200E6000CB037E283CDDE5016800DD09FD4602FDCB034E20040E0F18020E007BB72808DDAB +:200E80007E00A1B0DD77007CB72808DD7E08A1B0DD77087DB72808DD7E10A1B0DD7710DD5B +:200EA000E1C9C5D9DD6603DD6E027E234E2346235E2356D987875F160023194E2346235E35 +:200EC00023566069C17948CB3FCB3FCB3FCB3F47C5DDE5E5D5DD6E04DD6605DD23DD2323E4 +:200EE000235E2356D5FDE1D1E17EFDCB007E2802CBFFFD7700231AD96F260009FD7501FD43 +:200F00007402D9131AD96F260019FD7503FD7404D91310BFFDE1010400FD09D1FD6E00FD07 +:200F20006601FD23FD23E5DDE1FDE5D543CDFA1FD1FDE11520E6C92AD373CB6ECC490FCB5C +:200F400066200523232318F2C9E5CB5E282BCB76200D235E23561B7BB22034E1E5182C2338 +:200F60005E2356EB5E23561B7BB22023235E23562B2B722B73E1E5181223352010E1E5CBE4 +:200F800076280823237E2B772BE1E5CBFEE1C9722B7318F902000200020001940F11BA73D8 +:200FA000CD98002ABA73ED5BBC7322D3733630EB22D573C90100010001B40F11BE73CD98A5 +:200FC000003ABE734F2AD37347110300B72808CB66206A190D20F8CB6E2062CBEECB7628CF +:200FE0005CCB5E2858235E2356D52AD373E5CB66202ECB6E20237EE648FE48201C23237EDB +:20100000BA381620082B7EBB380F283123562B5E1B1B1B1B7323721800E1232323E518CEF9 +:201020000600B7E1D1E52AD573ED524D6B6223232323EDB0010800ED4222D573E1C902001A +:2010400001000200013E1011BF73CD98002AC0733ABF734FEB2AD373AF47CB6E283EE57E2B +:20106000E610F62077AFB2200BB12802CBF6237323731842CBDE79B7281BD5EB2AD573EB06 +:20108000CBF623732372EBD1732372237323722322D57318212373237223181ACB662006D8 +:2010A0002323230418B4D5E5232323043630EBE1CBA6EBD118A4E1CBAE78C9010001000117 +:2010C000BB1011C273CD98003AC2734F2AD37347110300B72808CB66200C190D20F8CB6E56 +:2010E0002004CB7E2003AF180ACB762002CBEECBBE3E01B7C90F06010309000A0F020B07DC +:201100000F0504080FD3C0AFDD2A0880DD23DD23FD21D773060ADD7700DD23FD7700FD236F +:20112000FD7700FD230520EE32EB7332EC7332EE7332EF7332F07332F173C900C97CFE0089 +:201140002004DBFC1802DBFF2FC9DBFC2F32EE73DBFF2F32EF73D380CD3B11DBFC2F32F0DE +:2011600073DBFF2F32F173D3C0C9DBFC21EB73CB672008CB6F200335180134DBFFCB672046 +:201180000923CB6F200335180134C97DFE01281A01EB737CFE002801030A5FAF02CD3D1183 +:2011A00057E60F6F7AE640671816D380CD3D1157D3C0E60F21F51006004F096E7AE64067F9 +:2011C000C9CD4A11FD21D773DD2A0880DDE5DD7E00CB7F281E47110200DD19E60728093AD2 +:2011E000EE7321EB73CD201278E61828063AF073CD3F12DDE1DD7E01CB7F282347110A00A0 +:20120000FD19110700DD19E60728093AEF7321EC73CD201278E61828063AF173CD3F12C948 +:201220004FCB482804CDB91279CB402804CD891279CB5028097EDD8602DD7702AF77C94F34 +:20124000CB582804CDE91279CB602803CD5012C9C5D5E5E60F5FFD4608FD7E09FE00201AD6 +:201260007BB82805FD7308181C3E01FD770921F5101600197EDD7704180B7BB82807FD7386 +:2012800008AFFD7709E1D1C1C9C5D5E6405FFD4600FD7E01FE0020137BB82805FD730018E7 +:2012A000153E01FD7701DD7300180B7BB82807FD7300AFFD7701D1C1C9C5D5E60F5FFD4670 +:2012C00002FD7E03FE0020137BB82805FD730218153E01FD7703DD7301180B7BB82807FDD5 +:2012E0007302AFFD7703D1C1C9C5D5E6405FFD4606FD7E07FE0020137BB82805FD730618EF +:20130000153E01FD7707DD7303180B7BB82807FD7306AFFD7707D1C1C92100001100403E7B +:2013200000CDD418CDE918CD271921A318116000E5D57EFEFF281B470421C31411080010E8 +:2013400015D1D5FD2101003E03CDBE1FD1E1132318DED1E118031918E6214D14118500FDF1 +:201360002116003E02CDBE1F21631411A500FD2116003E02CDBE1F21C114119B00FD21021E +:20138000003E02CDBE1F21B41411AA02FD210D003E02CDBE1F213B141100003E04FD2112B5 +:2013A00000CDBE1F06010EC0CDD91F2100807EFEAA204C237EFE552046212480CD4619115A +:2013C0002480210102CD5119212480CD461923545DCD461921C101CD5119212480CD461912 +:2013E00023CD46192311AC02FD2104003E02CDBE1FCD681906010E80CDD91F2A0A80E9214A +:20140000791411AA01FD210D003E02CDBE1F21861411E401FD211A003E02CDBE1F21A014C6 +:20142000112702FD2114003E02CDBE1F21008ACD6B1906010E80CDD91F18FE000000F0F00A +:20144000F0F0F0F0F0F0F0D08090B0304060616869707178798081888964656C74757C8468 +:20146000858C8D62636A6B72737A7B82838A8B66676D76777D86878E8F5455524E20474181 +:201480004D45204F46464245464F524520494E53455254494E472043415254524944474584 +:2014A0004F5220455850414E53494F4E204D4F44554C452E1D203139383220434F4C45430B +:2014C0004F1E1F00000000000000003F7FFFFFF3F3F0F00080C0C0C0C000003F7FFFFFF3CF +:2014E000F3F3F30080C0C0C0C0C0C0F0F0F0F0F0F0F0F0FFFFFFF0F0FFFFFFC0C0C0000079 +:20150000000000F1F1F17B7B7B3F3FE0E0E0C0C0C080801F3F7F79787F7F3F80C0E0E0001E +:2015200080C0E0F3F3FBFBFBFFFFFFC0C0C0C0C0C0C0C0F3F3FFFF7F3F0000C0C0C0C08095 +:20154000000000F0F0FFFFFFFF00000000C0C0C0C000003F1F1F1F0E0E0000800000000077 +:20156000000000F0F0F0F0F0F000001F01797F3F1F0000E0E0E0E0C0800000FFF7F7F7F3BE +:20158000F30000C0C0C0C0C0C000007E81BDA1A1BD817E1F04040400000000446C5454009B +:2015A0000000000000000000000000202020202000200050505000000000005050F850F89B +:2015C0005050002078A07028F02000C0C810204098180040A0A040A8906800202020000023 +:2015E0000000002040808080402000201008080810200020A8702070A82000002020F8204B +:201600002000000000000020204000000000F800000000000000000000200000081020409A +:20162000800000708898A8C88870002060202020207000708808304080F800F80810300892 +:2016400088700010305090F8101000F880F00808887000384080F088887000F80810204012 +:201660004040007088887088887000708888780810E000000020002000000000002000200A +:2016800020400010204080402010000000F800F8000000402010081020400070881020206A +:2016A0000020007088A8B8B080780020508888F8888800F08888F08888F00070888080801A +:2016C000887000F08888888888F000F88080F08080F800F88080F0808080007880808098B2 +:2016E000887800888888F888888800702020202020700008080808088870008890A0C0A00A +:20170000908800808080808080F80088D8A8A8888888008888C8A8988888007088888888B9 +:20172000887000F08888F08080800070888888A8906800F08888F0A0908800708880700801 +:20174000887000F82020202020200088888888888870008888888888502000888888A8A839 +:20176000D8880088885020508888008888502020202000F80810204080F800F8C0C0C0C069 +:20178000C0F8000080402010080000F81818181818F8000000205088000000000000000039 +:2017A0000000F8402010000000000000007088F88888000000F0487048F000000078808069 +:2017C0008078000000F0484848F0000000F080E080F0000000F080E080800000007880B899 +:2017E00088700000008888F88888000000F8202020F8000000702020A0E000000090A0C069 +:20180000A09000000080808080F800000088D8A8888800000088C8A89888000000F8888868 +:2018200088F8000000F088F08080000000F888A890E0000000F888F8A09000000078807018 +:2018400008F0000000F8202020200000008888888870000000888890A0400000008888A850 +:20186000D88800000088602060880000008850202020000000F8102040F800384020C02008 +:201880004038004020100810204000E01020182010E00040A8100000000000A850A850A820 +:2018A00050A80001020E0F0809121303040E0F05140000050010110A0B1516060710110504 +:2018C00014000001020E0F03040E0F03040E0F0C0D1718FF4F7DD3BF7CF640D3BF79D3BE99 +:2018E0001B7AB320F8CDDC1FC906000E00CDD91F06010E80CDD91F3E02210018CDB81F3E69 +:2019000004210020CDB81F3E03210000CDB81F3E0021001BCDB81F3E01210038CDB81F0678 +:20192000070E00CDD91FC9218B15111D00FD2160003E03CDBE1F21A315110000FD210100A3 +:201940003E03CDBE1FC90100007EFE2FC8230318F8C5FDE13E20991F06004F09444D626BB4 +:2019600050593E02CDBE1FC921001711FF001B7AB320FB2B7CB520F3C92100001100403E78 +:2019800000CD821FCD851F060F0E04CDD91FCD7F1F217C1A112500FD2116003E02CDBE1F06 +:2019A00021921A116500FD2117003E02CDBE1F11C500CDCA1A110501CDCA1A114501CDCA88 +:2019C0001A118501CDCA1A11E501CDCA1A112502CDCA1A116502CDCA1A11A502CDCA1A1171 +:2019E0000501CDD71A114501CDDC1A118501CDE11A21C21A11E501CDE41A21C31A112502B5 +:201A0000CDE41A21C41A116502CDE41A21C51A11A502CDE41A110F01CDD71A114F01CDDC4D +:201A20001A118F01CDE11A11F101CDEE1A113102CDEE1A117102CDEE1A11B102CDEE1A112F +:201A40002F02CDD71A116F02CDDC1A11AF02CDE11A11FB01CDFB1A113B02CDFB1A117B021B +:201A6000CDFB1A11BB02CDFB1A2AFA731120003EF4CD821F06010EC0CDD91FC9544F2053F3 +:201A8000454C4543542047414D45204F5054494F4E2C505245535320425554544F4E204F82 +:201AA0004E204B45595041442E31203D20534B494C4C20312F4F4E4520504C41594552321E +:201AC00033343536373854574F5321A91AFD2116003E02CDBE1FC921BF1A180821C01A1880 +:201AE0000321C11AFD2101003E02CDBE1FC921C61AFD2103003E02CDBE1FC921C91AFD211E +:201B000001003E02CDBE1FC902000100020001081B11BA73CD98003ABA732ABB734F060031 +:201B2000DD21F273DD09DD09DD7500DD74013AC373CB4F282779FE032806FE042810181CE3 +:201B400006047DB420040E0318280E07182406037DB420040E7F181A0EFF1816FD21761B7D +:201B6000FD09FD09FD7E00FD4601CB3CCB1D3D20F94DCDCA1CC907050B060A020B0406034B +:201B80000500010001000100FEFF020001801B11BA73CD98003ABA73ED5BBB73FD2ABF73C9 +:201BA0002ABD73CDAA1BCD3E1DC9FD22FE73DD21F2734F0600FE0420073AC373CB4F282CF9 +:201BC000FD21FF1BFD09FD7E00FE00281FCB23CB123D20F9C5ED4BFE73FD7E00FE00280BCC +:201BE000CB21CB103D20F9ED43FE73C1E5DD09DD09DD6E00DD660119EBE1ED4BFE73C902CD +:201C0000030003030500010001000100FEFF020001041C11BA73CD98003ABA73ED5BBB7313 +:201C2000FD2ABF732ABD73F5FE0020223AC773FE01201BF1E52A02807BCB27CB275F19EBCA +:201C4000FDE5C179CB27CB274FE1EDB01807F1CDAA1BCD011DC90100010001561C11BA73AE +:201C6000CD98003ABA7347AF2A048077233CB820FAC90100010001721C11BA73CD98003A15 +:201C8000BA73DD2A0480F5FD21F273FD5E00FD56017BD3BF7AF640D3BFF12A0280DD4E004E +:201CA000DD2306000909090906040EBEEDA3000020FA3D20E5C902000100010001B61C1187 +:201CC000BA73CD98002ABA734C4579D3BF78C680D3BF78FE0020047932C37378FE01200419 +:201CE0007932C473C90300FEFF0200020001E51C11BA73CD98002ABA73ED5BBC73ED4BBECC +:201D000073E5D5E1110040197DD3BF7CD3BFC5D1E10EBE43EDA30000C2141D15FA211D20B8 +:201D2000F3C90300FEFF0200020001221D11BA73CD98002ABA73ED5BBC73ED4BBE737BD37B +:201D4000BF7AD3BFC5D10EBE43EDA20000C2491D15FA561D20F3C9DBBFC9DD21961D1810C2 +:201D6000DD21B71D180ADD21E51D1804DD21071ED908DDE508F508F1D9D5D9D1FD21010020 +:201D80002A0680CDA31BDDE1DDE5DDE9130B78B1D920E1DDE1C92A0680010800E5D109EBB7 +:201DA000CD001FCD721ECD5D1EFE012006CD891ECD9A1ED92318D52A0680010800E5D10913 +:201DC000EBCD4E1FCD721ECD5D1EFE012013CD891E2A0680010800E5D109EBCD4E1FCD9A8F +:201DE0001ED92318A72A0680010800E5D109EBCD121FCD721ECD5D1EFE012006CD891ECD9E +:201E00009A1ED923C38C1D2A0680010800E5D109EBCDAB1E08F508F1D9E5D9D12A0680019A +:201E2000080009FD210400CD271CCD5D1EFE012024CD891E2A0680010800E5D109EBCDEA46 +:201E40001E3E04D9E5D9D12A068001080009FD210400CD271CD923232323C38C1D08F508F0 +:201E6000F1FE03200A21C373CB4E28033E01C93E00C908F508F1D9E5D9D12A068001080085 +:201E800009FD210100CD271CC93E04D9D5D9D12A0680FD210100CDA31BC93E04D9E5D9D1DA +:201EA0002A0680FD210100CD271CC9E5DDE1D5FDE1010800DD7E00DD23571E04CB17CB1486 +:201EC000CB12CB141D20F51E04CB17CB15CB12CB151D20F5FD7400FD7510FD23FD7400FDC0 +:201EE0007510FD230B79B020CBC9011000E57E23121312130B79FE082001E179B020EFC9E7 +:201F0000010800463E80CB101F30FB1223130D20F2C9E5DDE1EB010800DDCB0016CB1EDD44 +:201F2000CB0116CB1EDDCB0216CB1EDDCB0316CB1EDDCB0416CB1EDDCB0516CB1EDDCB067E +:201F400016CB1EDDCB0716CB1E230D20CCC901070009037E12132B0B78B120F7C9FFFFFFFC +:201F6000FFC30003C38804C3C706C35A1DC3601DC3661DC36C1DC34A11C38B11C37919C31C +:201F80002719C3D418C3E918C36A11C30E1BC38C1BC3101CC35A1CC3761CC39A0FC3B80F87 +:201FA000C34410C3BF10C3BC1CC3ED1CC32A1DC35506C30302C35102C31D1BC3A31BC327A5 +:201FC0001CC3661CC3821CC3AA0FC3C40FC35310C3CB10C3370FC33B02C3CA1CC3571DC3BD +:201FE000011DC33E1DC36406C37906C3C111C31302C35E02C37F02C3A304C3D806C33B0059 +:00000001FF diff --git a/Coleco - Vision_MiST/rtl/roms/ONYX.BIO b/Coleco - Vision_MiST/rtl/roms/ONYX.BIO new file mode 100644 index 0000000000000000000000000000000000000000..3872bc27820a53e4af8dca1c7101105bef57e598 GIT binary patch literal 8192 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 or 8001<>55, + CP 0AAH + JR NZ,L13B7 ; put up "please turn machine off + INC HL ; before inserting cartridge" msg + LD A,(HL) + CP 55H +L13B7 JP NZ,L13FF + + LD HL,Cart_Title ; Find name string + LD D,H ; Display address = first string + LD E,L + CALL L1946 ; Scan for first '/' + PUSH HL ; Save address of first '/' + LD HL,0201H ; Screen address for first string + CALL L1951 ; Display first string centered + + POP HL ; Recover address of first '/' + INC HL ; Adjust for second string + LD D,H ; Display address = second string + LD E,L + CALL L1946 ; Scan for second '/' + PUSH HL ; Save address of second '/' + LD HL,01C1H ; Screen address for second string + CALL L1951 ; Display second string centered + + POP HL ; Recover address of second '/' + INC HL ; Adjust for third string + LD DE,02ACH ; Screen address for copyright date + LD IY,0004H ; 4 bytes + CALL _BlkWrtVRAM2 + + CALL A1968 ; "Respect the seven second delay we + ; use" - Donald Fagen, "The Nightfly" + + LD BC,0180H ; Blank screen + CALL _WriteReg + + LD HL,(Cart_Start) ; Get start address + JP (HL) ; Jump into cartridge + + DB O,O,O,O,O,O,O,O,O,O + DB O + + +; Add A (signed byte) to (HL) + +A01B1 LD B,00H ; sign-extend A -> BA + BIT 7,A + JR Z,L01B9 + DEC B +L01B9 ADD A,(HL) + LD (HL),A + INC HL + LD A,(HL) + ADC A,B + LD (HL),A + DEC HL + RET + + DB O + +; Index into the 7020H array using B as the index +; B = 1 returns HL = (7020H)+2 and IX = (HL) + +A01C1 LD HL,(SndArray) ; HL = (7020H)-2 + B*4 + DEC HL + DEC HL + LD C,B + LD B,00H + ADD HL,BC + ADD HL,BC + ADD HL,BC + ADD HL,BC + LD E,(HL) ; IX = (HL) + INC HL + LD D,(HL) + PUSH DE + POP IX + RET + + DB O + +; Update function code? (Used by Carnival!) + +A01D5 LD (IX+01H),L + LD (IX+02H),H + LD A,(DE) + AND 3FH + LD B,A + LD A,(IX+00H) + AND 0C0H + OR B + LD (IX+00H),A + RET + +; Get command list pointer? + +L01E9 LD A,(IX+00H) + CP 0FFH + RET Z + AND 3FH + CP 3EH + RET NZ + PUSH IX + POP HL + INC HL + LD E,(HL) + INC HL + LD D,(HL) + EX DE,HL + RET + + DB O,O,O,O,O,O + +;*************************************** +; 1FB2 PInitSound +; +; Parameter block version of 1FEE +; +; Parm 1 (byte) = number of array elements +; Parm 2 (word) = pointer to array of pointers +; +;*************************************** +_PInitSound LD BC,P_InitSound + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD B,A + LD HL,(ParmArea+1) + +;*************************************** +; 1FEE InitSound +; +; Initializes 7020 with HL, clears out the array pointed to by +; (HL+2) to contain an FF every ten bytes for B times, then stores +; a zero at the end. Then the sound variables are initialized and +; the sound chip is silenced. +; +; Array at 7020H contains a list of four-byte entries. The +; second word of the list contains a pointer to a list of +; 10-byte blocks, and the second word of each other entry +; probably contains a pointer into this list as well. The +; first word of each four-byte entry is apparently a pointer +; to a list of command bytes. +; +; Each 10 byte block has the following format: +; +; +0 bits 0-5 = function code (3EH is special) +; bits 6-7 = channel code (0=noise, else tone channel number) +; +1,+2 pointer to list of command bytes +; +3 low 8 bits of frequency +; +4 bits 0-3 = high 2 bits of frequency or noise control +; bits 4-7 = amplitude (00H=max, 0FH=off) +; +5 duration counter? +; +6 bits 0-3 = twang time counter? +; bits 4-7 = twang time? +; +7 twang offset? (signed byte) +; +8 bits 0-3 = decay high counter? +; bits 4-7 = decay high nibble? +; +9 bits 0-3 = decay low counter? +; bits 4-7 = decay low nibble? +; +; ENTRY B = number of array elements +; HL = pointer to array of pointers +;*************************************** +A0213 +_InitSound LD (SndArray),HL + INC HL + INC HL + LD E,(HL) + INC HL + LD D,(HL) + EX DE,HL + LD DE,000AH +NoSoundP EQU $+1 ; null sound program = single FFH byte +L0220 LD (HL),0FFH + ADD HL,DE + DJNZ L0220 + LD (HL),D + CALL L0297 + LD A,(HL) ; = 0FFH + LD (NoiseCtlShad),A + JR A023B + + DB O,O,O,O,O,O,O,O,O,O + DB O,O,O + +;*************************************** +; 1FD6 NoSound +; +; This routine silences the sound chip. +;*************************************** +A023B +_NoSound LD A,9FH + OUT (IO_Sound),A + LD A,0BFH + OUT (IO_Sound),A + LD A,0DFH + OUT (IO_Sound),A + LD A,0FFH + OUT (IO_Sound),A + RET + + DB O,O,O,O,O + +;*************************************** +; 1FB5 PAddSound +; +; Parameter block version of 1FF1 +; +; Parm 1 (byte) = index into array at 7020H +;*************************************** +_PAddSound LD BC,P_AddSound + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD B,A + +;*************************************** +; 1FF1 AddSound +; +; This routine seets up a new entry in the sound list. (?) +; +; ENTRY B = index into array at 7020H, 1 = first entry +;*************************************** +A025E +_AddSound PUSH BC + CALL A01C1 + LD A,(IX+00H) + AND 3FH + POP BC + CP B + RET Z +A026A LD (IX+00H),B + DEC HL + DEC HL + LD D,(HL) + DEC HL + LD E,(HL) + LD (IX+01H),E + LD (IX+02H),D + CALL L035F + JR L0295 + + DB O,O + +;*************************************** +; 1FF4 UpdateSound +; +; This routine updates the current sound pointers +; by searching through the sound list. +;*************************************** +A027F +_UpdateSound LD B,01H + CALL A01C1 +L0284 XOR A + CP (IX+00H) + RET Z + CALL L02D6 + LD DE,000AH + ADD IX,DE + JR L0284 + +; Update stream pointers + +L0295 CALL L0297 + PUSH IX + + LD B,01H + CALL A01C1 +L02AB LD A,(IX+00H) + OR A + JR Z,L02D3 + INC A + JR Z,L02CB + LD A,(IX+00H) + AND 0C0H + RLCA + RLCA + RLCA + LD E,A + LD D,00H + LD HL,NoiseP + ADD HL,DE + PUSH IX + POP DE + LD (HL),E + INC HL + LD (HL),D +L02CB LD DE,000AH + ADD IX,DE + JR L02AB + +L02D3 POP IX + RET + +L02D6 CALL L01E9 + CP 0FFH + RET Z + CP 3EH + JR NZ,L02E6 + LD DE,0007H + ADD HL,DE + JP (HL) + +L0297 LD HL,NoSoundP + LD (NoiseP),HL + LD (Tone1P),HL + LD (Tone2P),HL + LD (Tone3P),HL + RET + + DB O,O,O + +L02E6 CALL L012F + CALL L00FC + RET NZ +A02EE LD A,(IX+00H) ; (called by Carnival) + PUSH AF + CALL L035F + POP BC + LD A,(IX+00H) + CP B + RET Z + JR L0295 + +D1AC6 DB 'TWO' + +;*************************************** +; 1F61 DoSound +; +; This updates the sound chip registers based on the +; current sound array pointers for each channel. +;*************************************** +A0300 +_DoSound LD A,9FH + LD C,90H +D0587 EQU $+1 + LD D,80H + LD IX,(Tone1P) + CALL L034E + LD A,0BFH + LD C,0B0H + LD D,0A0H + LD IX,(Tone2P) + CALL L034E + LD A,0DFH + LD C,0D0H + LD D,0C0H + LD IX,(Tone3P) + CALL L034E + LD A,0FFH + LD C,0F0H + LD IX,(NoiseP) + LD E,(IX+00H) + INC E + JR Z,L0335 + CALL L0164 + LD A,(IX+04H) + AND 0FH + LD HL,NoiseCtlShad + CP (HL) + RET Z + LD (HL),A + LD C,0E0H + +; Send amplitude or noise control to sound chip + +L0164 LD A,(IX+04H) + BIT 4,C + JR Z,L016F + RRCA + RRCA + RRCA + RRCA +L016F AND 0FH + OR C +L0335 OUT (IO_Sound),A + RET + +L034E LD E,(IX+00H) + INC E + JR Z,L0335 + CALL L0164 + +; Send freqency to sound chip + +L0175 LD A,(IX+03H) + AND 0FH + OR D + OUT (IO_Sound),A + LD A,(IX+03H) + AND 0F0H + LD D,A + LD A,(IX+04H) + AND 0FH + OR D + RRCA + RRCA + RRCA + RRCA + JR L0335 + +L035F LD A,(IX+00H) + AND 3FH + PUSH AF + LD (IX+00H),0FFH + LD L,(IX+01H) + LD H,(IX+02H) + LD A,(HL) + LD B,A + BIT 5,A + JR Z,L0391 + PUSH BC + AND 1FH + INC HL + LD (IX+01H),L + LD (IX+02H),H + LD (IX+04H),0F0H + LD (IX+05H),A + JR L03F0 + +L0391 BIT 4,A + JR Z,L03A4 + BIT 3,A + JR Z,L039E + POP BC + JP _AddSound + +L039E LD A,0FFH + PUSH AF + JR L03F8 + +L03A4 AND 3CH + CP 04H + JR NZ,L03D2 + POP IY + PUSH IY + PUSH BC + INC HL + LD E,(HL) + LD (IX+01H),E + INC HL + LD D,(HL) + LD (IX+02H),D + INC HL + PUSH IY + POP AF + PUSH DE + POP IY + LD DE,L03C6 + PUSH DE + JP (IY) + +L03C6 LD DE,0007H + ADD IY,DE + LD DE,L0461 + PUSH DE + JP (IY) + +L03D2 PUSH BC + LD A,B + AND 03H + JR NZ,L03FA + INC HL + INC HL + INC HL + INC HL + LD (IX+01H),L + LD (IX+02H),H + DEC HL + LD DE,0005H + CALL L0478 ; DE = DE + IX + LD BC,0003H + LDDR +L03F0 LD (IX+07H),00H +L03F4 LD (IX+08H),00H +L03F8 JR L0461 + +L03FA DEC A ; CP 01H + JR NZ,L0419 + LD DE,0006H + ADD HL,DE + LD (IX+01H),L + LD (IX+02H),H + DEC HL + INC E + CALL L0478 ; DE = DE + IX + LD BC,0005H + LDDR + JR L03F4 + +L0419 DEC A ; CP 02H + JR NZ,L0445 + LD DE,0006H + ADD HL,DE + POP AF + PUSH AF + AND 0C0H + JR NZ,L0429 + DEC HL +L0429 LD (IX+01H),L + LD (IX+02H),H + DEC HL + LD E,09H + CALL L0478 ; DE = DE + IX + LD BC,0002H + LDDR + XOR A + LD (DE),A + DEC DE + DEC DE + LD C,03H + LDDR + JR L0461 + +L0445 LD DE,0008H + ADD HL,DE + LD (IX+01H),L + LD (IX+02H),H + DEC HL + INC E + CALL L0478 ; DE = DE + IX + LD BC,0007H + LDDR +L0461 PUSH IX + POP HL + POP AF + POP BC + CP 0FFH + RET Z + LD D,A + AND 3FH + CP 04H + JR NZ,L0472 + LD B,3EH +L0472 LD A,D + AND 0C0H + OR B + LD (HL),A + RET + +;*************************************** +; +; VIDEO ROUTINES BEGIN HERE +; +;*************************************** + +;*************************************** +; 1F64 +; +; Parameter block version of 1FF7 +; +; Parm 1 (lit) = ? +; Parm 2 (byte) = ? +;*************************************** +L0488 LD BC,D0482 + LD DE,ParmArea + CALL PCopy + LD HL,(ParmArea) + LD E,(HL) + INC HL + LD D,(HL) + EX DE,HL + LD A,(ParmArea+2) + OR A ; (clears carry) + JR Z,L04A3 + SCF + +;*************************************** +; 1FF7 +; +; ENTRY HL = ? +; C-flag = ? +;*************************************** +L04A3 LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD C,(HL) + INC HL + LD B,(HL) + INC HL + LD A,00H ; note: must preserve carry here! + LD (BC),A + LD A,(DE) + PUSH AF + AND 0FH + JR Z,L04E7 + DEC A + JR Z,L05F1 + DEC A + JR Z,L0600 + DEC A + JR Z,L0600 + DEC A + JR NZ,L04E5 + +; 04A3/1FF7 Function 4 + +L04C6 LD A,(DE) + RRA + RRA + RRA + RRA + AND 0FH + LD B,A + LD E,(HL) + INC HL + LD D,(HL) + INC HL + OR A + JR Z,L04E5 +L04D5 POP AF + PUSH AF + PUSH HL + PUSH BC + EX DE,HL + CALL L04A3 + POP BC + POP HL + LD E,(HL) + INC HL + LD D,(HL) + INC HL + DJNZ L04D5 +L04E5 POP AF + RET + +; 04A3/1FF7 Function 1 + +L05F1 CALL L0572 + INC DE + LD A,(DE) + LD (IY+05H),A + INC DE + LD A,(DE) + LD (IY+06H),A + POP AF + RET + +; 04A3/1FF7 Functions 2 & 3 + +L0600 INC BC + INC BC + INC BC + INC BC + INC BC + EX DE,HL + INC HL + LD A,(HL) + LD E,A + LD D,00H + PUSH DE + INC HL + LD E,(HL) + INC HL + LD D,(HL) + INC HL + ADD A,(HL) + LD (BC),A + LD C,(HL) + LD B,00H + PUSH BC + POP IY + EX DE,HL + POP DE + POP AF + RET NC + LD A,01H ; Sprite pattern gen table + JP _BlkWrtVRAM + +; 04A3/1FF7 Function 0 + +L04E7 CALL L0572 + LD A,(DE) + LD L,A + INC DE + LD A,(DE) + ADD A,L + LD (IY+05H),A + LD H,00H + POP AF + RET NC ; this is the carry flag from L04A3 + PUSH AF + LD A,(VDP0Shad) ; Check for hi-res graphics + BIT 1,A + JR Z,L0530 ; Branch if not + EX DE,HL + LD B,H + LD C,L + LD L,(HL) + LD H,00H + PUSH HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + PUSH HL + INC BC + LD A,(BC) + LD L,A + INC BC + LD A,(BC) + LD H,A + POP BC + POP IY + POP AF + BIT 7,A + CALL NZ,L0594 + INC D ; DE = DE + 0100H + BIT 6,A + CALL NZ,L0594 + INC D ; DE = DE + 0100H + BIT 5,A + RET Z +L0594 PUSH AF + PUSH BC + PUSH IY + PUSH DE + PUSH HL + CALL _BlkWrtVRAM3 ; Pattern generator table + POP HL + POP DE + POP IY + POP BC + POP AF + PUSH AF + PUSH BC + PUSH IY + PUSH DE + PUSH HL + BIT 4,A + JR NZ,L05BC + ADD HL,BC + CALL _BlkWrtVRAM4 ; Color table +L05B5 POP HL + POP DE + POP IY + POP BC + POP AF + RET + +L0530 EX DE,HL + LD C,(HL) + LD B,00H + PUSH BC + POP IY + INC HL + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + PUSH HL + PUSH BC + PUSH DE + PUSH IY + CALL _BlkWrtVRAM3 ; Pattern generator table + POP BC + POP HL + LD E,L + LD D,H + ADD HL,BC + DEC HL + SRL H + RR L + SRL H + RR L + SRL H + RR L + SRA E + SRA E + SRA E + OR A + SBC HL,DE + INC HL + PUSH HL + POP IY + POP HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + POP BC + ADD HL,BC + CALL _BlkWrtVRAM4 ; Color table + POP AF + RET + +L05BC ADD HL,BC + LD C,L + LD B,H + PUSH IY + POP HL +L05C2 PUSH HL + LD A,(BC) + PUSH BC + LD BC,0008H + LD HL,(VDP_Temp) + ADD HL,BC + LD B,C +L05CE DEC HL + LD (HL),A + DJNZ L05CE + PUSH DE + CALL L1EA5 ; LD A,04H LD IY,0001H JP _BlkWrtVRAM + POP DE + POP BC + INC DE + INC BC + POP HL + DEC HL + LD A,H + OR L + JR NZ,L05C2 + JR L05B5 + +L0572 PUSH BC + POP IY + PUSH DE + LD E,(HL) + INC HL + LD D,(HL) + BIT 7,D + JR NZ,L0591 + LD A,D + CP 70H + JR C,L0588 + LD A,80H + LD (DE),A + JR L0591 + +L0588 LD HL,D0587 + LD BC,0001H + CALL _WrtVRAM +L0591 POP DE + INC DE + RET + +;*************************************** +; 1F67 +; +; Parameter block version of 1FFA +; +; Parm 1 (word) = ??? +; Parm 2 (byte) = ??? +;*************************************** +L06C7 LD BC,D06C1 + LD DE,ParmArea + CALL PCopy + LD IX,(ParmArea) + LD A,(ParmArea+2) + LD B,A + +;*************************************** +; 1FFA +; +; ENTRY IX = ??? +; A = ??? +;*************************************** +L06D8 LD A,(D73C6) + DEC A + JR NZ,L06E3 + +L0623 PUSH IX + LD HL,(73CDH) + POP DE + LD (HL),E + INC HL + LD (HL),D + INC HL + LD (HL),B + INC HL + EX DE,HL + LD A,(73CBH) + INC A + LD HL,73CAH + CP (HL) + EX DE,HL + JR NZ,L0669 + XOR A + LD HL,(73D1H) +L0669 LD (73CDH),HL + LD (73CBH),A + RET + +L06E3 LD L,(IX+00H) + LD H,(IX+01H) + LD A,(HL) + LD C,A + AND 0FH + JR Z,L06FF + DEC A + JP Z,L0A87 + DEC A + JR Z,L08DF + DEC A + JP Z,L0955 + JP L0EA2 + +L08DF LD E,0F9H + CALL L08E0 + LD HL,0008H + JP L0999 + +L06FF LD E,(IX+02H) + LD D,(IX+03H) + PUSH DE + POP IY + LD E,(IY+01H) + LD D,(IY+02H) + CALL A07E8 + LD C,E + LD E,(IY+03H) + LD D,(IY+04H) + CALL A07E8 + LD B,E + LD E,(IY+00H) + LD D,00H + ADD HL,DE + ADD HL,DE + LD E,05H + ADD HL,DE + LD E,(HL) + INC HL + LD D,(HL) + EX DE,HL + PUSH BC + POP DE + LD C,(HL) + INC HL + LD B,(HL) + INC HL + LD A,(IX+05H) + BIT 7,A + JP NZ,A080B + PUSH BC + PUSH DE + PUSH HL + CP 70H + JR Z,L0744 + JR C,L074B +L0744 LD H,A + LD L,(IX+04H) + JR L0780 + +L074B LD HL,(VDP_Temp) + LD E,(IX+04H) + LD D,(IX+05H) + PUSH HL + PUSH DE + PUSH HL + LD BC,0004H + CALL _ReadVRAM + POP HL + LD A,(HL) + CP 80H + JR NZ,L0766 + POP DE + JR L077F + +L0766 INC HL + INC HL + LD B,(HL) + INC HL + LD E,(HL) + LD D,00H + INC HL + EX DE,HL + DB 0FEH ; CP n - skips the ADD HL,HL +L0771 ADD HL,HL + DJNZ L0771 + PUSH HL + POP BC + EX DE,HL + POP DE + INC DE + INC DE + INC DE + INC DE + CALL _ReadVRAM +L077F POP HL +L0780 LD A,(HL) + CP 80H + JR Z,L0794 + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD C,(HL) + INC HL + LD B,(HL) + INC HL + PUSH IX + CALL A080B + POP IX +L0794 POP HL + POP DE + POP BC + PUSH BC + PUSH DE + PUSH HL + LD L,(IX+04H) + LD H,(IX+05H) + LD A,70H + CP H + JR C,L07A8 + LD HL,(VDP_Temp) +L07A8 LD (HL),E + INC HL + LD (HL),D + INC HL + LD (HL),C + INC HL + LD (HL),B + INC HL + PUSH IX + CALL L0898 + POP IX + POP HL + POP DE + POP BC + PUSH IX + CALL A080B + POP IX + LD D,(IX+05H) + LD A,70H + CP D + RET Z + RET C + LD E,(IX+04H) + EXX + LD HL,(VDP_Temp) + PUSH HL + INC HL + INC HL + LD E,(HL) + LD D,00H + INC HL + LD B,(HL) + EX DE,HL + DB 0FEH ; CP n - skips the ADD HL,HL +L07DD ADD HL,HL + DJNZ L07DD + PUSH HL + EXX + POP BC + POP HL + JP _WrtVRAM + +L08E0 LD IY,(VDP_Temp) + LD L,(IX+02H) + LD H,(IX+03H) + INC HL + LD C,(HL) + INC HL + LD B,(HL) + LD A,B + OR A + JR Z,L0900 + INC A + JR NZ,L0A54 + LD A,C + CP E + JP M,L0A54 +L0900 INC HL + LD C,(HL) + INC HL + LD B,(HL) + LD A,B + OR A + JR Z,L0914 + INC A + JR NZ,L0A54 + LD A,C + CP E + JP M,L0A54 +L0914 DEC HL + DEC HL + LD A,(HL) + OR A + JR Z,L09CA + DEC HL + LD C,(HL) + INC HL + LD B,(HL) + RET + +L09CA POP HL ; get rid of return address + LD L,(IX+02H) + LD H,(IX+03H) + INC HL + LD A,(HL) + CALL L09D5 + LD A,(HL) +L09FD LD (IY+03H),A +L0A00 LD L,(IX+02H) + LD H,(IX+03H) + INC HL + INC HL + INC HL + LD A,(HL) + LD (IY+00H),A + CALL L09D8 + INC HL + LD A,(HL) + LD L,(IX+00H) + LD H,(IX+01H) + INC HL + ADD A,(HL) + LD (IY+02H),A + XOR A ; Sprite attribute table + LD D,A + LD E,(IX+04H) + PUSH IY + JR L0A7E + +L0A54 POP DE ; get rid of return address + PUSH IY + PUSH IX + PUSH IY + PUSH IY + XOR A ; Sprite attribute table + LD D,A + LD E,(IX+04H) + POP HL + CALL L1E92 ; LD IY,0001H / JP _BlkReadVRAM + XOR A + POP IY + LD (IY+01H),A + LD A,80H + LD (IY+03H),A + XOR A ; Sprite attribute table + LD D,A + POP IX + LD E,(IX+04H) +L0A7E POP HL + JP L1EA7 ; LD IY,0001H / JP _BlkWrtVRAM + +;*************************************** +; +; Initialize the video chip +; +;*************************************** +L1319 CALL InitScrn + +; Initialize the character cells for "COLECOVISION" + + LD HL,A18A3 ; Point to character cell usage list + LD DE,0060H ; Starting character code = 60H +L1330 PUSH HL + LD A,(HL) ; Get block ID + RLCA ; Multiply index by 8 + JP C,L1352 ; Check for end of list + RLCA + RLCA + LD C,A ; Load BC with block offset + LD B,D ; (D-reg = 00H here) + LD HL,A14C3 ; Point to block data +L1356 ADD HL,BC ; Point HL to block image + PUSH DE + CALL _BlkWrtVRAM31 ; LD A,03H LD IY,0001H JP _BlkWrtVRAM + POP DE + POP HL + INC DE + INC HL + JR L1330 + +InitScrn XOR A ; Fill VRAM from address 0000H + LD H,A ; with 00H + LD L,A ; + LD DE,4000H ; length 4000H + CALL _FillVRAM ; Do the fill + CALL _InitVDP ; Initialize the video chip + JP _InitFont ; Initialize the text font + + DB O,O,O,O,O,O,O,O,O,O + +A07E8 PUSH HL + SRA D + RR E + SRA D + RR E + SRA D + RR E + BIT 7,D + LD HL,0FF80H + JR NZ,L0802 + ADD HL,DE + POP HL + RET NC + LD E,7FH + RET + +L0802 LD H,00H ; LD HL,0080H + ADD HL,DE + POP HL + RET C + LD E,80H + RET + + DB O + +A080B PUSH BC ; (called by Antarctic Adventure and Destructor) + PUSH DE + PUSH HL + EXX + POP HL + POP DE + POP BC + CALL A08C0 + EXX + LD A,E + BIT 7,A + JR NZ,L081E + CP 20H + RET NC +L081E ADD A,C + BIT 7,A + RET NZ + OR A + RET Z + BIT 7,E + JR Z,L0848 + LD A,C + ADD A,E + PUSH DE + CP 21H + JR C,L0831 + LD A,20H +L0831 LD E,A + LD D,00H + PUSH DE + POP IY + POP DE + LD A,E + EXX + PUSH BC + NEG + LD C,A + LD B,00H + ADD HL,BC + EX DE,HL + ADD HL,BC + EX DE,HL + POP BC + EXX + JR L0864 + +L0848 LD A,E + ADD A,C + CP 1FH + JR Z,L085D + JR C,L085D + LD A,20H + SUB E + PUSH DE + LD E,A + LD D,00H + PUSH DE + POP IY + POP DE + JR L0864 + +L085D PUSH BC + LD B,00H + PUSH BC + POP IY + POP BC +L0864 LD E,00H +L0866 LD A,D + ADD A,E + BIT 7,A + JR NZ,L0885 + CP 18H + JR NC,L0885 + PUSH BC + PUSH DE + EXX + PUSH BC + PUSH DE + PUSH HL + PUSH IY + CALL _BlkWrtVRAM2 + POP IY + POP HL + POP DE + POP BC + EXX + POP DE + POP BC +L0885 EXX + PUSH BC + LD B,00H + ADD HL,BC + EX DE,HL + LD C,20H + ADD HL,BC + EX DE,HL + POP BC + EXX + INC E + LD A,E + CP B + JR NZ,L0866 + RET + +L0898 CALL A08C0 + PUSH BC + LD B,00H + PUSH BC + POP IY + POP BC +L08A2 PUSH BC + PUSH DE + PUSH HL + PUSH IY + LD A,02H ; Name table + CALL _BlkReadVRAM + POP IY + POP HL + POP DE + POP BC + PUSH BC + LD B,00H + ADD HL,BC + LD C,20H + EX DE,HL + ADD HL,BC + EX DE,HL + POP BC + DEC B + JR NZ,L08A2 + RET + + DB O,O,O,O + +A08C0 PUSH HL + LD H,00H ; sign-extend D -> HL + BIT 7,D + JR Z,L08CB + DEC H +L08CB LD L,D + ADD HL,HL ; HL = D * 32 (signed multiply) + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + LD D,00H ; sign-extend E -> DE + BIT 7,E + JR Z,L08DB + DEC D +L08DB JP L047C ; DE = (D * 32) + E (signed arithmetic) + +L0955 LD E,0E1H + CALL L08E0 + LD HL,0020H +L0999 ADD HL,BC + LD A,L + CALL L09D5 + LD A,(HL) + OR 80H + JP L09FD + +L0A87 LD IY,(VDP_Temp) + LD A,(VDP0Shad) ; Check for hi-res graphics + BIT 1,A + SET 7,B + JR NZ,L0A98 ; Branch if so + RES 7,B +L0A98 LD (IY+03H),B + PUSH HL + LD L,(IX+02H) + LD H,(IX+03H) + LD A,(HL) + LD (IY+04H),A + XOR 80H + LD (HL),A + INC HL + LD E,(HL) + LD A,E + AND 07H + NEG + ADD A,08H + LD (IY+01H),A + INC HL + LD D,(HL) + CALL A07E8 + LD (IY+11H),E + INC HL + LD E,(HL) + LD A,E + AND 07H + LD (IY+00H),A + INC HL + LD D,(HL) + CALL A07E8 + LD (IY+12H),E + LD HL,(VDP_Temp) + LD DE,0013H + ADD HL,DE + LD E,(IY+11H) + LD D,(IY+12H) + LD BC,0303H + CALL L0898 + LD E,(IX+04H) + LD D,(IX+05H) + LD A,(IX+06H) + POP IX + LD IY,(VDP_Temp) + LD (IY+05H),A + PUSH DE + LD HL,(VDP_Temp) + LD BC,0006H + ADD HL,BC + LD C,0BH + LD A,D + CP 70H + JR NC,L0B07 + CALL _ReadVRAM + JR L0B0A + +L0B07 EX DE,HL + LDIR +L0B0A LD HL,(VDP_Temp) + PUSH HL + LD DE,0013H + ADD HL,DE + EXX + POP DE + LD HL,0008H + ADD HL,DE + EX DE,HL + EXX + LD IY,(VDP_Temp) + LD C,(IY+05H) + LD B,09H +L0B25 LD A,(HL) + SUB C + CP 12H + JR NC,L0B39 + CP 09H + JR C,L0B31 + SUB 09H +L0B31 EXX + LD L,A + LD H,00H + ADD HL,DE + LD A,(HL) + EXX + LD (HL),A +L0B39 INC HL + DJNZ L0B25 + POP DE + LD HL,(VDP_Temp) + PUSH HL + LD BC,0011H + ADD HL,BC + LD C,0BH + LD A,D + CP 70H + JR NC,L0B51 + CALL _WrtVRAM + DB 11H ; LD DE,n - skips LDIR instruction +L0B51 LDIR + POP DE + PUSH IX + LD HL,0013H + ADD HL,DE + EX DE,HL + LD BC,0014H + ADD HL,BC + LD B,09H +L0B64 LD A,(DE) + INC DE + PUSH DE + LD DE,0008H + ADD HL,DE + PUSH HL + LD E,A +; LD D,00H + LD C,A + PUSH BC + LD A,09H + SUB B + LD B,D +L0B76 SUB 03H + JR C,L0B7D + INC B + JR L0B76 + +L0B7D LD A,B + LD IY,(VDP_Temp) + ADD A,(IY+12H) + BIT 7,(IY+03H) + JR NZ,L0BB8 + LD A,03H ; Pattern generator table + CALL L1E92 ; LD IY,0001H / JP _BlkReadVRAM + POP BC + LD HL,(VDP_Temp) + PUSH BC + LD DE,0084H + ADD HL,DE + LD E,C + SRL E + SRL E + SRL E +; LD D,00H + LD A,09H + SUB B + LD C,A + LD B,D + ADD HL,BC + JR L0BD6 + +L0BB8 SRA A + SRA A + SRA A + CP 03H + JR NC,L0BD9 + LD D,A + PUSH DE + PUSH HL + LD A,03H ; Pattern generator table + CALL L1E92 ; LD IY,0001H / JP _BlkReadVRAM + POP HL + LD DE,0068H + ADD HL,DE + POP DE +L0BD6 CALL L1E90 ; LD A,04H LD IY,0001H JP _BlkReadVRAM +L0BD9 POP BC + POP HL + POP DE + DJNZ L0B64 + POP IX + EXX + LD E,(IX+02H) + LD D,(IX+03H) + LD C,(IX+04H) + LD B,(IX+05H) + EXX + PUSH IX + POP HL + LD IY,(VDP_Temp) + LD A,(IY+04H) + ADD A,A + LD C,A + LD DE,0006H + LD B,D + ADD HL,DE + ADD HL,BC + LD E,(HL) + INC HL + LD D,(HL) + LD HL,(VDP_Temp) + LD BC,007CH + ADD HL,BC + PUSH HL + PUSH BC + LD C,05H + LD A,D + CP 70H + JR NC,L0C1A + CALL _ReadVRAM + JR L0C1D + +L0C1A EX DE,HL + LDIR +L0C1D LD IY,(VDP_Temp) + POP BC + ADD IY,BC + LD A,(IY+04H) + LD IY,(VDP_Temp) + LD (IY+02H),A + POP DE + LD HL,(VDP_Temp) + LD BC,0064H + ADD HL,BC + LD B,04H +L0C38 LD A,(DE) + CP (IX+01H) + PUSH DE + EXX + LD H,00H + JR NC,L0C55 + ADD A,A + ADD A,A + ADD A,A + LD L,A + ADD HL,BC + PUSH HL + EXX + POP DE +L0C7C EX DE,HL + PUSH BC + LD BC,0008H + LDIR + EX DE,HL + JR L0C84 + +L0C55 SUB (IX+01H) + ADD A,A + ADD A,A + ADD A,A + LD L,A + ADD HL,DE + PUSH HL + EXX + POP DE + LD A,D + CP 70H + JR NC,L0C7C + PUSH BC + PUSH HL + PUSH DE + LD BC,0008H + PUSH BC + CALL _ReadVRAM + POP BC + POP HL + ADD HL,BC + EX DE,HL + POP HL + ADD HL,BC +L0C84 POP BC + POP DE + INC DE + DJNZ L0C38 + LD IY,(VDP_Temp) + LD DE,(VDP_Temp) + LD HL,001CH + ADD HL,DE + LD C,(IY+00H) + LD B,00H + ADD HL,BC + PUSH HL + POP IX + LD HL,0064H + ADD HL,DE + PUSH HL + LD A,10H +L0CA5 EX AF,AF' + POP HL + LD D,(HL) + INC HL + PUSH HL + LD BC,000FH + ADD HL,BC + LD E,(HL) + EX DE,HL + LD B,(IY+01H) + XOR A +L0CB4 DEC B ; cheap HL=HL< + HEX 3C 66 06 0C 18 00 18 00 ; ? + HEX 3E 63 67 6B 6E 60 3E 00 ; @ +D16AB HEX 1C 36 63 63 7F 63 63 00 ; A + HEX 7E 63 63 7E 63 63 7E 00 ; B + HEX 1E 33 60 60 60 33 1E 00 ; C + HEX 7C 66 63 63 63 66 7C 00 ; D + HEX 7F 60 60 7E 60 60 7F 00 ; E + HEX 7F 60 60 7E 60 60 60 00 ; F + HEX 1F 30 60 67 63 33 1F 00 ; G + HEX 63 63 63 7F 63 63 63 00 ; H + HEX 3F 0C 0C 0C 0C 0C 3F 00 ; I + HEX 03 03 03 03 03 63 3E 00 ; J + HEX 63 66 6C 78 7C 6E 67 00 ; K + HEX 60 60 60 60 60 60 7F 00 ; L + HEX 63 77 7F 7F 6B 63 63 00 ; M + HEX 63 73 7B 7F 6F 67 63 00 ; N + HEX 3E 63 63 63 63 63 3E 00 ; O + HEX 7E 63 63 63 7E 60 60 00 ; P + HEX 3E 63 63 63 6F 66 3D 00 ; Q + HEX 7E 63 63 67 7C 6E 67 00 ; R + HEX 3C 66 60 3E 03 63 3E 00 ; S + HEX 3F 0C 0C 0C 0C 0C 0C 00 ; T + HEX 63 63 63 63 63 63 3E 00 ; U + HEX 63 63 63 77 3E 1C 08 00 ; V + HEX 63 63 6B 7F 7F 77 63 00 ; W + HEX 63 77 3E 1C 3E 77 63 00 ; X + HEX 33 33 33 1E 0C 0C 0C 00 ; Y + HEX 7F 07 0E 1C 38 70 7F 00 ; Z + HEX 1E 18 18 18 18 18 1E 00 ; [ + HEX 00 60 30 18 0C 06 03 00 ; \ + HEX 3C 0C 0C 0C 0C 0C 3C 00 ; ] + HEX 08 1C 36 63 00 00 00 00 ; ^ + HEX 00 00 00 00 00 00 7F 00 ; _ + HEX 18 18 0C 00 00 00 00 00 ; ` + HEX 00 00 3C 06 3E 66 3E 00 ; a + HEX 60 60 7C 66 66 66 7C 00 ; b + HEX 00 00 3C 66 60 66 3C 00 ; c + HEX 06 06 3E 66 66 66 3E 00 ; d + HEX 00 00 3C 66 7E 60 3C 00 ; e + HEX 1C 36 30 78 30 30 30 00 ; f + HEX 00 00 3E 66 66 3E 06 3C ; g + HEX 60 60 7C 66 66 66 66 00 ; h + HEX 18 00 38 18 18 18 3C 00 ; i + HEX 06 00 0E 06 06 66 3C 00 ; j + HEX 60 60 66 6C 78 6C 66 00 ; k + HEX 38 18 18 18 18 18 3C 00 ; l + HEX 00 00 76 7F 6B 63 63 00 ; m + HEX 00 00 7C 66 66 66 66 00 ; n + HEX 00 00 3C 66 66 66 3C 00 ; o + HEX 00 00 7C 66 66 7C 60 60 ; p + HEX 00 00 3E 66 66 3E 06 03 ; q + HEX 00 00 7C 66 60 60 60 00 ; r + HEX 00 00 3E 60 3C 06 7C 00 ; s + HEX 00 18 3C 18 18 18 0C 00 ; t + HEX 00 00 66 66 66 66 3E 00 ; u + HEX 00 00 66 66 66 3C 18 00 ; v + HEX 00 00 63 63 6B 7F 36 00 ; w + HEX 00 00 66 3C 18 3C 66 00 ; x + HEX 00 00 66 66 66 3E 06 7C ; y + HEX 00 00 7E 0C 18 30 7E 00 ; z + HEX 0C 18 18 30 18 18 0C 00 ; { + HEX 18 18 18 00 18 18 18 00 ; | + HEX 30 18 18 0C 18 18 30 00 ; } + HEX 30 5A 0C 00 00 00 00 00 ; ~ + HEX 54 28 54 28 54 28 54 00 ; del + +; Character cell to font data mapping for COLECOVISION + +A18A3 HEX 01 02 0E 0F 08 09 12 13 ; CV + HEX 03 04 0E 0F 05 14 00 00 ; OI + HEX 05 00 10 11 0A 0B 15 16 ; LS + HEX 06 07 10 11 05 14 00 00 ; EI + HEX 01 02 0E 0F 03 04 0E 0F ; CO + HEX 03 04 0E 0F 0C 0D 17 18 ; ON + HEX FF ; end of list + +;*************************************** +; 1F82 FillVRAM +; +; Fills a block of VRAM with the same byte +; +; ENTRY HL = start VRAM address +; DE = count +; A = fill byte +; EXIT AF, C, DE destroyed +;*************************************** +A18D4 +_FillVRAM LD C,A ; Save fill byte + LD A,L ; Output low byte of VRAM address + OUT (IO_VDP_Addr),A + LD A,H ; Output high byte of VRAM address + OR 40H ; set "this is an address" bit + OUT (IO_VDP_Addr),A +L18DD LD A,C ; Get back fill byte (and delay?) + OUT (IO_VDP_Data),A ; Store data byte + DEC DE ; Decrement count + LD A,D + OR E + JR NZ,L18DD ; Store bytes until done + JP _VDP_Status ; Read VDP status register + + DB O + +;*************************************** +; 1F85 InitVDP +; +; Initialize the VDP chip +;*************************************** +A18E9 +_InitVDP LD BC,0000H ; Register 0: half-text 32x24 mode + CALL _WriteReg + + LD BC,0180H ; Reg 1, 32x24 mode, 16K DRAM, blank + CALL _WriteReg + NOP + NOP + +A18F7 ; (called by Tomarc the Barbarian) + + LD A,03H ; Pattern generator table + LD HL,0000H ; VRAM address 0000H + CALL _BaseLoad + + LD A,02H ; Name table (display) + LD HL,1800H ; VRAM address 1800H + CALL _BaseLoad + + XOR A ; Sprite attribute table + LD HL,1B00H ; VRAM address 1B00H + CALL _BaseLoad + + LD A,04H ; Color table + LD HL,2000H ; VRAM address 2000H + CALL _BaseLoad + + LD A,01H ; Sprite pattern generator +D1AC5 EQU $+2 ; DB '8' + LD HL,3800H ; VRAM address 3800H + CALL _BaseLoad + + LD BC,0700H ; Reg 7 (FG/BG color), set both to 0 + JP _WriteReg + +;*************************************** +; 1F7F InitFont +; +; Initialize pattern generator (font) table +;*************************************** +_InitFont LD HL,A158B ; Point to main ASCII bitmaps + LD DE,001DH ; First character code = 1DH + LD IY,0063H ; bug fixed (was 0060) + CALL _BlkWrtVRAM3 ; Pattern generator table + + LD HL,A15A3 ; Point to blank bitmap + LD DE,0000H ; First character code = 00H +_BlkWrtVRAM31 LD A,03H ; Pattern generator table + JP L1EA7 ; LD IY,0001H / JP _BlkWrtVRAM + +;*************************************** +; +; Search for '/' character in text pointed to by HL. +; +; ENTRY HL points to text +; +; EXIT: HL points to '/' character +; BC = number of bytes before '/' character +; +;*************************************** +L1946 LD BC,0000H ; Initialize count to zero +L1949 LD A,(HL) ; Get next byte + CP '/' ; Return if '/' character + RET Z + INC HL ; Point to next byte + INC BC ; Increment count + JR L1949 ; Go back for more + +;*************************************** +; +; Center a line of text on the screen. +; +; ENTRY BC = length of text +; DE = pointer to text +; HL = screen position at left end of line +; +;*************************************** +L1951 PUSH BC ; Move BC to IY (count) + POP IY + LD A,20H ; A = (20H - C) / 2 + SBC A,C ; (centering offset) + RRA + LD B,00H + LD C,A + ADD HL,BC ; HL = HL + BC + EX DE,HL ; HL = text ptr, DE = scrn position + JP _BlkWrtVRAM2 ; LD A,02H / JP _BlkWrtVRAM + +;*************************************** +; +; Delay routines +; +; 1968 is the infamous "seven second delay" and is apparently +; not called elsewhere in the ROM and shouldn't be called by +; "well behaved" cartridges. Which means that it would be safe +; to change, except that some Xonox cartridges call it. However, +; shortening the delay would probably make some of those games +; more playable, so we can change it in the name of humanity. +; +; 196B delays using a count in the HL register. The delay is +; approximately H/3 seconds. +; +;*************************************** +;A1968 LD HL,1700H ; Too long +;A196B LD DE,00FFH ; Load inner loop count +;L196E DEC DE +; LD A,D +; OR E +; JR NZ,L196E +; DEC HL +; LD A,H +; OR L +; JR NZ,A196B +; RET + +; This replacement is based on Kev's patch. Every outer loop it checks +; both left fire buttons and aborts the delay loop if either is pressed. +; +; The main difference is that I save the AF and BC registers on the +; assumption that anyone "byte-fisted" enough to call the ROM instead of +; spending a few bytes to write his own might also expect it not to mess +; with the A register or B register. +; +; The other side-effect of this replacement delay routine is that the +; joystick ports are left in stick mode, but this is probably okay. + +L196C JR Z,L1978 ; exit if pressed + + LD DE,00E8H ; load inner loop counter (about 10% less) +L196E DEC DE ; do inner loop + LD A,D + OR E + JR NZ,L196E + + DEC HL ; do outer loop + LD A,H + OR L + JR NZ,L196B + +L1978 POP BC ; restore regs & return + POP AF + RET + +A1968 LD HL,1700H ; startup screen delay timer +A196B PUSH AF ; original routine didn't mess with A or B! + PUSH BC + +L196B OUT (0C0H),A ; select left fire/stick mode + IN A,(0FCH) ; read left fire button + LD B,A + IN A,(0FFH) ; read right fire button + AND B ; OR the two sticks together + AND 40H ; mask out the fire button bit + JR L196C + +;*************************************** +; 1F7C SkillScrn +; +; Displays the skill select screen and returns +;*************************************** +A1979 +_SkillScrn CALL InitScrn ; Clear VRAM and initialize the VDP + + LD BC,0F04H ; Reg 0FH (FG/BG color), value = 4 + CALL _WriteReg ; write it + + LD HL,Skill_Msgs ; Put up skill screen messages + CALL ScrnMsgs + + LD HL,(ClrTabShad) ; Get color table VRAM addr + LD DE,0020H ; 32 bytes + LD A,0F4H ; Fill with F4H + CALL _FillVRAM ; fill it + + LD BC,01C0H ; Unblank the screen + JP _WriteReg + +D1AC9 EQU $+3 ; DB 'S' +D1A7C DB 'TO SELECT GAME OPTION,' +D1AA9 DB '1 = SKILL 1/ONE PLAYER' + +; HL=msg,IY=len,DE=scrn +Skill_Msgs DW D1A7C,22*1024+0025H ; 'TO SELECT GAME OPTION,' + DW D1A92,23*1024+0065H ; 'PRESS BUTTON ON KEYPAD.' + DW D1AA9,22*1024+00C5H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+0105H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+0145H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+0185H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+01E5H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+0225H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+0265H ; '1 = SKILL 1/ONE PLAYER' + DW D1AA9,22*1024+02A5H ; '1 = SKILL 1/ONE PLAYER' + DW D1ABF,01*1024+0105H ; '2' + DW D1AC0,01*1024+0145H ; '3' + DW D1AC1,01*1024+0185H ; '4' + DW D1AC2,01*1024+01E5H ; '5' + DW D1AC3,01*1024+0225H ; '6' + DW D1AC4,01*1024+0265H ; '7' + DW D1AC5,01*1024+02A5H ; '8' + DW D1ABF,01*1024+010FH ; '2' + DW D1AC0,01*1024+014FH ; '3' + DW D1AC1,01*1024+018FH ; '4' + DW D1AC6,03*1024+01F1H ; 'TWO' + DW D1AC6,03*1024+0231H ; 'TWO' + DW D1AC6,03*1024+0271H ; 'TWO' + DW D1AC6,03*1024+02B1H ; 'TWO' + DW D1ABF,01*1024+022FH ; '2' + DW D1AC0,01*1024+026FH ; '3' + DW D1AC1,01*1024+02AFH ; '4' + DW D1AC9,01*1024+01FBH ; 'S' + DW D1AC9,01*1024+023BH ; 'S' + DW D1AC9,01*1024+027BH ; 'S' + DW D1AC9,01*1024+02BBH ; 'S' + DW 0 ; End of table + +;*************************************** +; Put up the "no cartridge" message +;*************************************** + +L13FF LD HL,No_Cart_Msgs ; Put up "TURN GAME OFF" messages + CALL ScrnMsgs + + LD HL,8A00H ; Wait a long time for the user to see + CALL A196B + + LD BC,0180H ; Then blank the screen + CALL _WriteReg + +L1439 JR L1439 ; and go to sleep + NOP ; to allow for patching + +; HL=msg,IY=len,DE=scrn +No_Cart_Msgs DW D1479,13*1024+01AAH ; 'TURN GAME OFF' + DW D1486,26*1024+01E4H ; 'BEFORE INSERTING CARTRIDGE' + DW D14A0,20*1024+0227H ; 'OR EXPANSION MODULE.' + DW 0 ; End of table + +;*************************************** +; Display a bunch of text all over the screen +; +; ENTRY: HL=table pointer +; EXIT: BC=0 +; +; The table is a bunch of 4-byte entries: +; 0-1 address of message text data +; 2 low byte of screen address +; 3 high byte of screen address in low 2 bits +; message text length in high 6 bits +;*************************************** + +ScrnMsgs LD C,(HL) ; Get message address to BC + INC HL + LD B,(HL) + INC HL + + LD A,C ; Test for end of table + OR B + RET Z + + LD E,(HL) ; Get display address to DE + INC HL + LD A,(HL) + AND 03H + LD D,A + + LD A,(HL) ; Get message length to A + INC HL + RRCA + RRCA + AND 3FH + + PUSH BC ; Save message address + EX (SP),HL ; Msg addr to HL, save table pointer + + LD C,A ; Move message length to IY + LD B,0 + PUSH BC + POP IY + + CALL _BlkWrtVRAM2 ; LD A,02H/JP _BlkWrtVRAM + + POP HL ; Recover table pointer + JR ScrnMsgs ; Loop for next message + +;*************************************** +; 1FAF +; +; Parameter block version of 1FE5 +; +; Parm 1 (byte) = ? +; Parm 2 (lit) = ? +;*************************************** +L0655 LD BC,D064F + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD HL,(ParmArea+1) + +;*************************************** +; 1FE5 +; +; ENTRY A = ? +; HL = ? +;*************************************** +L0664 LD (73CAH),A + XOR A +; LD (73CBH),A + LD (73CCH),A + LD (73D1H),HL +; LD (73CDH),HL + LD (73CFH),HL + JP L0669 + +;*************************************** +; 1F88 ReadSpinner +; +; This was included to support the "spinner" control that +; was originally planned to be in the regular controllers. +; It was later included in the Super Action controllers. +; Early versions of the controller circuit board even have +; circuit traces and holes for the spinner parts. +; +; Apparently the 20H bit is a direction bit, and the 10H +; bit is a "pulse" bit. +;*************************************** +_ReadSpinner LD HL,PulseCnt1 ; Point to first pulse counter + IN A,(IO_Joy1) ; Read joystick 1 + CALL L117D ; Do first pulse counter + INC HL ; Point to second pulse counter + IN A,(IO_Joy2) ; Read joystick 2 + +L117D BIT 4,A ; Test 10H bit + RET NZ ; Return if set (no pulse) +L1182 BIT 5,A ; Test 20H bit + JR NZ,L1189 ; Inc counter if set + DEC (HL) ; Dec counter if clear + RET + +D1AC1 ; DB '4' +L1189 INC (HL) + RET + +;*************************************** +; 1FE8 +; +; +;*************************************** +L0679 LD A,(D73C6) + PUSH AF + XOR A + LD (D73C6),A +L0682 LD A,(73CCH) + LD HL,73CBH + CP (HL) + JR Z,L06BC + LD HL,(73CFH) + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD B,(HL) + INC HL + PUSH DE + POP IX + PUSH HL + CALL L06E3 + LD A,(73CCH) + INC A + LD HL,73CAH + CP (HL) + JR NZ,L06B3 + XOR A + LD HL,(73D1H) + LD (73CFH),HL + POP HL + JR L06B9 + +L06B3 POP HL + LD (73CFH),HL +L06B9 LD (73CCH),A + JR L0682 + +L06BC POP AF + LD (D73C6),A + RET + + DB O,O,O,O,O,O,O,O,O,O + DB O,O,O,O,O + +;*************************************** +; 1F8B PBaseLoad +; +; Parameter block version of 1FB8 +; +; P1 (byte) = base register code +; P2 (word) = raw unshifted VRAM address +;*************************************** +_PBaseLoad LD BC,P_BaseLoad + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD HL,(ParmArea+1) + +;*************************************** +; 1FB8 BaseLoad +; +; This routine loads a VDP base register with the +; specified base address. The base address is stored +; in one of the shadow registers at 73F2. +; +; ENTRY A = base register code +; HL = raw unshifted VRAM address +;*************************************** +A1B1D +_BaseLoad LD C,A ; VDP register code to BC + LD B,00H + LD IX,VDPBaseShad + ADD IX,BC ; Index into shadow address table + ADD IX,BC + LD (IX+00H),L ; Store shadow copy of base address + LD (IX+01H),H + LD A,(VDP0Shad) ; Get current graphics mode + BIT 1,A + JR Z,L1B5C ; If not in hi-res graphics, go shift + LD A,C + CP 03H ; Special handling for pattern gen + JR Z,L1B40 + CP 04H ; and color tables + JR NZ,L1B5C ; Else branch to go shift + +; Set color table base address in hi-res graphics mode + + LD B,03H ; VDP register 3 = color table + LD A,L ; If VRAM addr = 0, + OR H + LD C,7FH ; set base register to 7FH (1FC0H) + JR Z,L1B72 + LD C,0FFH ; Else set it to FFH (3FC0H) + JR L1B72 + +; Set pattern generator base address in hi-res graphics mode + +L1B40 LD B,04H ; VDP register 4 = pattern generator + LD A,L ; If VRAM addr = 0, + OR H + LD C,03H ; set base register to 03H (1800H) + JR Z,L1B72 + LD C,07H ; Else set it to 07H (3800H) + JR L1B72 + +L1B5C LD IY,D1B76 ; Get address of shift table + ADD IY,BC ; Index into it + ADD IY,BC + LD A,(IY+00H) ; Get shift count + LD B,(IY+01H) ; Get VDP register number +L1B6A SRL H ; Shift the base address right + RR L ; to adjust for VDP register + DEC A + JR NZ,L1B6A + LD C,L ; Get shifted VDP register data +L1B72 JP _WriteReg ; Write it to the VDP chip + +; Shift table for VDP base addresses (shift, reg num) + +D1B76 DB 7,5 ; 0 = Sprite attribute table + DB 11,6 ; 1 = Sprite pattern generator + DB 10,2 ; 2 = Name table + DB 11,4 ; 3 = Pattern generator + DB 6,3 ; 4 = Color table + +; ReadVRAM with the bug fixed + +XReadVRAM LD A,C ; no bug if C=00H + OR A + JR Z,XReadVRAM_a + + INC B ; else account for the missing page + +XReadVRAM_a JP ReadVRAM + +;*************************************** +; 1F8E PBlkReadVRAM +; +; Parameter block version of 1FBB +; +; Parm 1 (byte) = VDP table number (0-4) +; Parm 2 (byte) = VDP table index LSB +; Parm 3 (byte) = VDP table index MSB +; Parm 4 (lit) = pointer to data buffer +; Parm 5 (word) = VDP table entry count +;*************************************** +P_BlkReadVRAM +P_BlkWrtVRAM DB 5 + DW 1,1,1,-2,2 + +_PBlkReadVRAM LD BC,P_BlkReadVRAM + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD DE,(ParmArea+1) + LD IY,(ParmArea+5) + LD HL,(ParmArea+3) + +;*************************************** +; 1FBB BlkReadVRAM +; +; ENTRY A = VDP table number (0-4) +; DE = VDP table index +; HL points to data buffer +; IY = VDP table entry count +;*************************************** +A1BA3 +_BlkReadVRAM CALL VRAM_Index + JR XReadVRAM + + DB O,O + +;*************************************** +; VRAM_Index +; +; This routine returns the actual VRAM address and size +; of a block of VDP table entries. +; +; ENTRY DE = VDP table index +; IY = number of VDP table entries +; A = VDP table number (0-4) +; +; EXIT: BC = number of bytes to move to VRAM +; DE = VRAM address +; HL register is not changed +;*************************************** +A1BAA +VRAM_Index LD (D73FE),IY ; Save byte count + LD IX,VDPBaseShad ; VDP base addr shadow array + LD C,A ; BC = VRAM table index + LD B,00H + CP 04H ; Check if color table + JR NZ,L1BC0 + LD A,(VDP0Shad) ; Yes, check for hi-res graphics + BIT 1,A ; Don't shift color table unless + JR Z,L1BEC ; using hi-res graphics +L1BC0 LD IY,D1BFF ; Point to shift table + ADD IY,BC ; Index into shift table + LD A,(IY+00H) ; Get shift value + OR A + JR Z,L1BEC ; Branch if no shift +L1BCD SLA E ; Shift VRAM offset + RL D + DEC A + JR NZ,L1BCD ; until done + PUSH BC ; Save VRAM table index + LD BC,(D73FE) ; Get original byte count + LD A,(IY+00H) ; Get shift value + OR A + JR Z,L1BEB ; Branch if no shift +L1BE0 SLA C ; Shift byte count + RL B + DEC A + JR NZ,L1BE0 ; until done + LD (D73FE),BC ; Save shifted byte count +L1BEB POP BC ; Get back VRAM table index +L1BEC PUSH HL ; Save HL + ADD IX,BC ; Index into base addr shadow array + ADD IX,BC + LD L,(IX+00H) ; Get base VRAM address from shadow + LD H,(IX+01H) + ADD HL,DE ; Add shifted offset to base addr + EX DE,HL ; Put VRAM address in DE + POP HL ; Restore HL + LD BC,(D73FE) ; Get byte count + RET + +; Shift table for indexes into VDP tables (1, 4, or 8 bytes per entry) + +D1BFF DB 2 ; 0 = Sprite attribute table + DB 3 ; 1 = Sprite pattern generator table + DB 0 ; 2 = Name table + DB 3 ; 3 = Pattern generator table + DB 3 ; 4 = Color table + +; Copy high 4 bits of (HL) into low 4 bits of (HL) + +L01A6 LD A,(HL) + AND 0F0H + LD B,A + RRCA + RRCA + RRCA + RRCA + OR B + LD (HL),A + RET + +;*************************************** +; 1F91 PBlkWrtVRAM +; +; Parameter block version of 1FBE +; +; Parm 1 (byte) = VDP table number (0-4) +; Parm 2 (byte) = VDP table index LSB +; Parm 3 (byte) = VDP table index MSB +; Parm 4 (lit) = pointer to data to be written +; Parm 5 (word) = VDP table entry count +;*************************************** +_PBlkWrtVRAM LD BC,P_BlkWrtVRAM + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + LD DE,(ParmArea+1) + LD IY,(ParmArea+5) + LD HL,(ParmArea+3) + + DB 01H ; LD BC,nnnn +_BlkWrtVRAM2 LD A,02H ; name table (character cells) + +;*************************************** +; 1FBE BlkWrtVRAM +; +; ENTRY A = VDP table number (0-4) +; DE = VDP table index +; HL points to data to be written +; IY = VDP table entry count +; 73C7H = 01H to write to RAM sprite attr table +;*************************************** +A1C27 +_BlkWrtVRAM PUSH AF ; Save VDP table number + OR A ; If not sprite attribute table, + JR NZ,L1C4E ; always write to the VDP + LD A,(WrtRAMSprt) ; Check RAM sprite attr table flag + DEC A + JR NZ,L1C4E ; Write to VDP if not 01H + EX (SP),HL ; Clean up stack and save data pointer + LD HL,(RamSprtTab) ; Get pointer at 8002H + ADD HL,DE ; DE*4 = sprite table + ADD HL,DE + ADD HL,DE + ADD HL,DE ; dest addr = (8002H) + DE + EX DE,HL + PUSH IY ; BC = table entry count + POP BC + SLA C ; C = C * 4 for sprite table + SLA C ; I hope BC was <= 3FH! + POP HL ; Restore (source) data pointer + LDIR ; Copy it + RET + +_BlkWrtVRAM3 LD A,03H ; Pattern generator table + DB 01H ; LD BC,nnnn +_BlkWrtVRAM4 LD A,04H ; Color table + JR _BlkWrtVRAM + + DB O,O + +L1C4E POP AF ; Restore VDP table number +A1C4F ; (Called by Aquattack) + CALL VRAM_Index ; Adjust for VDP table size + JR XWrtVRAM ; Write the data to VRAM + +;*************************************** +; 1F94 PInitRAMSprt +; +; Parameter block version of 1FC1 +; +; Parm 1 (byte) = number of sprites +;*************************************** +_PInitRAMSprt LD BC,P_InitRAMSprt + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + +;*************************************** +; 1FC1 InitRAMSprt +; +; This routine initializes the RAM sprite index table +; pointed to by 8004H with values from 00H to A-1 +; +; ENTRY A = number of sprites +;*************************************** +_InitRAMSprt LD B,A ; B = count + XOR A ; Init fill to zero + LD HL,(RAMSprtIdx) ; Get pointer to RAM sprite index table +L1C6B LD (HL),A ; Initialize array entry + INC HL ; Increment array pointer + INC A ; Increment fill value + CP B ; Go back until done + JR NZ,L1C6B + RET + +; WrtVRAM with the bug fixed + +XWrtVRAM LD A,C ; no bug if C=00H + OR A + JR Z,XWrtVRAM_a + + INC B ; else account for the missing page + +XWrtVRAM_a JP _WrtVRAM + + DB O,O + +;*************************************** +; 1F97 PCopyRAMSprt +; +; Parameter block version of 1FC4 +; +; Parm 1 (byte) = number of sprites +;*************************************** +_PCopyRAMSprt LD BC,P_CopyRAMSprt + LD DE,ParmArea + CALL PCopy + LD A,(ParmArea) + +;*************************************** +; 1FC4 CopyRAMSprt +; +; This routine copies data from the RAM sprite attribute +; table at (8002H) to VRAM. The RAM sprite index table at +; (8004H) contains a list of one byte indexes into the RAM +; sprite attribute table. Each byte corresponds to one real +; (VRAM) sprite attr table entry and references one RAM +; sprite attr table entry to use as a template. +; +; ENTRY A = number of sprites +;*************************************** +A1C82 +_CopyRAMSprt LD IX,(RAMSprtIdx) ; Get pointer to RAM sprite index table + PUSH AF + LD IY,SprtTabShad ; Get sprite table base VRAM address + LD E,(IY+00H) + LD D,(IY+01H) + LD A,E ; Send LSB of address + OUT (IO_VDP_Addr),A + LD A,D + OR 40H ; Set write flag + OUT (IO_VDP_Addr),A ; Send MSB of address + POP AF +L1C9A LD HL,(RamSprtTab) ; Get pointer at 8002H + LD C,(IX+00H) ; Get next index byte from 8004H table + INC IX + LD B,00H ; HL = (8002H) + (IX)*4 + ADD HL,BC + ADD HL,BC + ADD HL,BC + ADD HL,BC + LD B,04H ; B = count for 4 bytes of data + LD C,IO_VDP_Data ; C = output port +L1CAC OUTI ; Output a byte of data + NOP ; Wait for the VDP to catch up + NOP + JR NZ,L1CAC ; Loop until 4 bytes copied + DEC A + JR NZ,L1C9A ; Loop until all sprites copied + RET + + DB O,O,O,O,O,O + +;*************************************** +; 1FA6 PWriteReg +; +; Parameter block version of 1FD9 +; +; Parm 1 (byte) = VDP register number +; Parm 2 (byte) = data to write to register +;*************************************** + +_PWriteReg LD BC,P_WriteReg + LD DE,ParmArea + CALL PCopy + LD HL,(ParmArea) + LD C,H + LD B,L + +;*************************************** +; 1FD9 WriteReg +; +; ENTRY B = VDP register number +; C = data to write to register +;*************************************** +A1CCA +_WriteReg LD A,C ; Send VDP register data + OUT (IO_VDP_Addr),A + LD A,B + ADD A,80H ; Set "write register" bit + OUT (IO_VDP_Addr),A ; Send register number + LD A,B ; If register 0... + OR A + JR NZ,L1CDB + LD A,C + LD (VDP0Shad),A ; ...update register 0 shadow +L1CDB LD A,B ; If register 1... + CP 01H ; If this is changed to DEC A, Smurf won't work! + RET NZ + LD A,C + LD (VDP1Shad),A ; ...update register 1 shadow + RET + +; Decrement low 4 bits of (HL) + +L0190 XOR A + RRD + SUB 01H + PUSH AF + RLD + POP AF + RET + +; Decrement high 4 bits of (HL) (NOT USED!) +; +;L019B XOR A +; RLD +; SUB 01H +; PUSH AF +; RRD +; POP AF +; RET + +;*************************************** +; 1FA9 PWrtVRAM +; +; Parameter block version of 1FDF +; +; Parm 1 (lit) = pointer to data to be written +; Parm 2 (word) = VRAM address +; Parm 3 (word) = byte count +;*************************************** +_PWrtVRam LD BC,P_WrtVRAM + LD DE,ParmArea + CALL PCopy + LD HL,(ParmArea) + LD DE,(ParmArea+2) + LD BC,(ParmArea+4) + +;*************************************** +; 1FDF WrtVRAM +; +; ENTRY HL points to data to be written +; DE = VRAM address +; BC = byte count (see note) +; EXIT: HL = first byte after data that was written +; AF, B, D destroyed +; +; Note: there is a bug which causes 256 too few bytes to be +; copied if the B and C registers are both non-zero, +; and there are games which do depend on this! +; BlkWrtVRAM is also affected by this, but is +; probably never called with enough bytes to matter. +;*************************************** +A1D01 +_WrtVRAM LD A,E ; Send LSB of address + OUT (IO_VDP_Addr),A + LD A,D + ADD A,40H ; Send MSB of address + 40H + OUT (IO_VDP_Addr),A + LD D,B ; D = MSB of byte count + LD B,C ; B = LSB of byte count + LD C,IO_VDP_Data ; C = port address +L1D14 OUTI ; Output a byte of data + NOP ; Wait for the VDP to catch up + NOP + JR NZ,L1D14 ; LSB loop + DEC D ; Decrement MSB of count + RET M ; MSB loop + JR NZ,L1D14 ; BUG: should have been JR L1D14 + RET + +; HL=msg,IY=len,DE=scrn +Title_Msgs DW A144D,22*1024+0085H ; first row of COLECOVISION + DW A1463,22*1024+00A5H ; second row of COLECOVISION + DW A14C1,02*1024+009BH ; TM + DW A14B4,13*1024+02AAH ; 'c 1982 COLECO' + DW 0 ; End of table + +;*************************************** +; 1FAC PReadVRAM +; +; Parameter block version of 1FE2 +; +; Parm 1 (lit) = pointer to data buffer +; Parm 2 (word) = VRAM address +; Parm 3 (word) = byte count +;*************************************** + +_PReadVRAM LD BC,P_ReadVRam + LD DE,ParmArea + CALL PCopy + LD HL,(ParmArea) + LD DE,(ParmArea+2) + LD BC,(ParmArea+4) + +;*************************************** +; 1FE2 ReadVRAM +; +; ENTRY HL points to data buffer +; DE = VRAM address +; BC = byte count (see note) +; EXIT: HL = first byte after data that was read +; AF, B, D destroyed +; +; Note: there is a bug which causes 256 too few bytes to be +; copied if the B and C registers are both non-zero, +; and there are games which do depend on this! +; BlkReadVRAM is also affected by this, but is +; probably never called with enough bytes to matter. +;*************************************** +A1D3E +_ReadVRAM LD A,E ; Send LSB of address + OUT (IO_VDP_Addr),A + LD A,D ; Send MSB of address +A1D43 EQU $+1 ; (Used by many Coleco carts) + OUT (IO_VDP_Addr),A + LD D,B ; D = MSB of byte count + LD B,C ; B = LSB of byte count +A1D47 EQU $+1 ; (Used by many Coleco carts) + LD C,IO_VDP_Data ; C = port address +L1D49 INI ; Input a byte of data + NOP ; Wait for the VDP to catch up + NOP + JR NZ,L1D49 ; LSB loop + DEC D ; Decrement MSB of count + RET M ; MSB loop + JR NZ,L1D49 ; BUG: should have been JR L1D49 + RET + + DB O,O,O,O + +;*************************************** +; 1FDC VDP_Status +; +; This routine returns the VDP status byte in A. +; +; EXIT: A = VDP status byte +;*************************************** +A1D57 +_VDP_Status IN A,(IO_VDP_Status) ; Get VDP status + RET ; and return + +;*************************************** +; 1F6A FlipRL +; +; Right/Left flip a list of images +; +; ENTRY A = VDP table code (0-4) +; BC = number of VDP table entries +; DE = source VDP table index +; HL = destination VDP table index +;*************************************** +A1D5A +_FlipRL LD IX,__FlipRL + JR L1D70 + +;*************************************** +; 1F6D FlipUD +; +; Up/Down flip a list of images +; +; ENTRY A = VDP table code (0-4) +; BC = number of VDP table entries +; DE = source VDP table index +; HL = destination VDP table index +;*************************************** +A1D60 +_FlipUD LD IX,__FlipUD + JR L1D70 + +;*************************************** +; 1F70 Rotate +; +; Rotate a list of images by 90 degrees clockwise +; +; ENTRY A = VDP table code (0-4) +; BC = number of VDP table entries +; DE = source VDP table index +; HL = destination VDP table index +;*************************************** +A1D66 +_Rotate LD IX,__Rotate + JR L1D70 + +;*************************************** +; 1F73 Expand +; +; Expand a list of 8x8 images to 16x16 +; +; ENTRY A = VDP table code (0-4) +; BC = number of VDP table entries +; DE = source VDP table index +; HL = destination VDP table index +;*************************************** +_Expand LD IX,__Expand +L1D70 EXX ; Swap register sets + EX AF,AF' ; AF' = VDP table + PUSH IX ; Save routine address +L1D74 EX AF,AF' ; AF = VDP table + PUSH AF + EX AF,AF' + POP AF + EXX ; DE = original DE + PUSH DE + EXX + POP DE + LD HL,(VDP_Temp) ; HL = (VDP_Temp) + CALL L1E92 ; LD IY,0001H / JP _BlkReadVRAM + POP IX ; IX = routine address + PUSH IX + JP (IX) ; Jump into the routine + +__Rotate LD HL,(VDP_Temp) ; HL = temp + LD BC,0008H ; DE = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoRotate ; Rotate the image + CALL L1E72 ; Copy the image back to VRAM + CALL L1E5D ; Check for hi-res graphics + JR Z,L1E02 ; Exit if not hi-res graphics + CALL L1E89 ; Read the source color table entry + CALL L1E9A ; Write the dest color table entry +L1E02 JR L1D8CEXX ; Done with routine + +__FlipRL LD HL,(VDP_Temp) ; DE = temp + LD BC,0008H ; HL = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoFlipLR ; Flip the image + CALL L1E72 ; Copy the image back to VRAM + CALL L1E5D ; Check for hi-res grahpics + JR Z,L1DB3 ; Exit if not hi-res graphics + CALL L1E89 ; Read source color table entry + CALL L1E9A ; Write dest color table entry +L1DB3 EXX ; Swap register set + JR L1D8CHL ; Done with routine + +__FlipUD LD HL,(VDP_Temp) ; DE = temp + LD BC,0008H ; HL = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoFlipUD ; Flip the image + CALL L1E72 ; Copy the image back to VRAM + CALL L1E5D ; Check for hi-res graphics + JR Z,L1D8CEXX ; Exit if not hi-res graphics + CALL L1E89 ; Read source color table entry + LD HL,(VDP_Temp) ; HL = temp + LD BC,0008H ; DE = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoFlipUD ; Flip the color table + CALL L1E9A ; Write dest color table entry +L1D8CEXX EXX ; Swap register set +L1D8CHL INC HL ; Increment dest index +L1D8C INC DE ; Increment VDP table index + DEC BC ; Decrement count + LD A,B ; Check for count = 0 + OR C + EXX ; Swap register set + JR NZ,L1D74 ; Go back until count = 0 + POP IX ; Clean up stack + RET + +__Expand LD HL,(VDP_Temp) ; HL = temp + LD BC,0008H ; DE = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoExpand ; Expand the image + EX AF,AF' ; A = VDP table code + PUSH AF + EX AF,AF' + POP AF + EXX ; DE = dest index + PUSH HL + EXX + POP DE + LD HL,(VDP_Temp) ; HL = temp + 8 + LD BC,0008H + ADD HL,BC + LD IY,0004H ; Write 4 entries + CALL _BlkWrtVRAM ; to the VRAM table + CALL L1E5D ; Check for hi-res graphics + JR Z,L1E55 ; Exit if not hi-res graphics + CALL L1E89 ; Read source color table entry + LD HL,(VDP_Temp) ; HL = temp + LD BC,0008H ; DE = temp + 8 + LD E,L + LD D,H + ADD HL,BC + EX DE,HL + CALL DoExpandCT ; Expand the color table + LD A,04H ; A = VDP color table code + EXX ; DE = dest index + PUSH HL + EXX + POP DE + LD HL,(VDP_Temp) ; HL = temp + 8 + LD BC,0008H + ADD HL,BC + LD IY,0004H ; Write 4 entries back + CALL _BlkWrtVRAM +L1E55 EXX ; Swap register set + INC HL ; Increment dest index + INC HL ; four times + INC HL ; + JR L1D8CHL ; Done with routine + +L1E5D EX AF,AF' ; A = VDP table code + PUSH AF + EX AF,AF' + POP AF + CP 03H ; Pattern generator table? + JP NZ,L10E6 ; Return zero if not + LD HL,VDP0Shad ; Check for hi-res mode + XOR A ; Prepare to return zero + BIT 1,(HL) + RET Z ; Return zero if not + INC A ; Return 1 if in hi-res mode + RET ; (Z-flag set according to A-reg) + +L1E72 EX AF,AF' ; A = VDP table code + PUSH AF + EX AF,AF' + POP AF + EXX ; DE = dest index + PUSH HL + EXX + POP DE + LD HL,(VDP_Temp) ; HL = temp + 8 + LD BC,0008H + ADD HL,BC + JR L1EA7 + +L1E89 EXX ; DE = source index + PUSH DE + EXX + POP DE + LD HL,(VDP_Temp) ; HL = temp +L1E90 LD A,04H ; A = VDP color table code +L1E92 LD IY,0001H ; Read one entry + JP _BlkReadVRAM ; from the color table + +L1E9A EXX ; DE = dest index + PUSH HL + EXX + POP DE + LD HL,(VDP_Temp) ; HL = temp +L1EA5 LD A,04H ; A = VDP color table code +L1EA7 LD IY,0001H ; Write one entry + JP _BlkWrtVRAM ; to the color table + +DoExpand PUSH HL ; IX = source + POP IX + PUSH DE ; IY = dest + POP IY + LD B,08H ; Initialize count +L1EB4 LD A,(IX+00H) ; Get source byte + INC IX + LD D,A ; Copy source byte into D + LD E,04H ; Initialize bit count +L1EBC RL A ; Shift source bit into H + RL H + RL D ; Shift copy of bit into H + RL H + DEC E ; Loop for four bits + JR NZ,L1EBC + LD E,04H ; Initialize bit count +L1EC9 RL A ; Shift source bit into L + RL L + RL D ; Shift copy of bit into L + RL L + DEC E ; Loop for four bits + JR NZ,L1EC9 + LD (IY+00H),H ; Store bits in first row + LD (IY+10H),L + INC IY + LD (IY+00H),H ; Store bits in second row + LD (IY+10H),L + INC IY + DJNZ L1EB4 ; Loop until done + RET + +DoExpandCT LD B,10H ; Initialize count + PUSH HL ; Save source addr +L1EEE LD A,(HL) ; Get next source byte + INC HL + LD (DE),A ; Store it twice + INC DE + LD (DE),A + INC DE + DEC BC ; Decrement count + LD A,B + CP 08H ; If count = 8 + JR NZ,L1EFB + POP HL ; get back source addr +L1EFB DJNZ L1EEE ; Loop until done + RET + +DoFlipLR LD B,08H ; Initialize count +L1F03 LD C,(HL) ; Get next byte + LD A,80H ; Set terminator bit +L1F06 RL C ; Shift a bit out + RRA ; Shift it in + JR NC,L1F06 ; Loop until done + LD (DE),A ; Save byte + INC HL ; Point to next bytes + INC DE + DJNZ L1F03 ; Loop until done + RET + +DoRotate PUSH HL ; IX = source + POP IX + EX DE,HL ; HL = destination + LD B,08H ; Initialize count +L1F19 RL (IX+00H) ; Shift a column of bits from the + RR (HL) ; source into a row of bits in + RL (IX+01H) ; the destination + RR (HL) + RL (IX+02H) + RR (HL) + RL (IX+03H) + RR (HL) + RL (IX+04H) + RR (HL) + RL (IX+05H) + RR (HL) + RL (IX+06H) + RR (HL) + RL (IX+07H) + RR (HL) + INC HL ; Increment destination + DJNZ L1F19 ; Loop until done + RET + +DoFlipUD LD BC,0008H ; Dest = dest + 8 + ADD HL,BC + LD B,C ; Initialize count = 8 +L1F53 DEC HL ; Decrement source + LD A,(HL) ; Get source byte + LD (DE),A ; Store in destination + INC DE ; Increment destination + DJNZ L1F53 ; Loop until done + RET + +;*************************************** +; 1F79 ReadCtl +; +; Read a joystick or keypad controller and a fire button +; +; ENTRY H = 0 for left control, 1 for right +; L = 0 for joystick/left fire, 1 for keypad/right fire +; EXIT: H = fire button in 40H bit +; L = joystick directionals or key code +; E = old pulse counter (only if L=0) +;*************************************** +_ReadCtl LD A,L ; Check if reading keypad + CP 01H + JR Z,L11AA ; Branch if reading keypad + LD BC,PulseCnt1 ; Point BC to pulse counter + LD A,H + OR A + JR Z,L1199 ; branch if left controller + INC BC ; Point BC to PulseCnt2 +L1199 LD A,(BC) ; E = old pulse counter value + LD E,A + XOR A ; Clear pulse counter + LD (BC),A + CALL L113D ; Read joystick port + LD D,A ; Save port bits in D + AND 0FH + LD L,A ; L = directional bits + JR L11BC + +; Read the keypad + +L11AA OUT (IO_KP_Select),A ; Select keypad mode + CALL L113D ; Read joystick port + LD D,A ; Save port bits in D + OUT (IO_Joy_Select),A ; Select joystick mode + AND 0FH ; Mask off keypad bits + LD HL,Keypad_Table ; Index into keypad table + LD B,00H + LD C,A + ADD HL,BC + LD L,(HL) ; L = key code (or 0FH if none) +L11BC LD A,D + AND 40H + LD H,A ; H = right fire button bit + RET + +; Jump vectors. Please call these instead of using addresses +; within the ROM itself. Since the code is so sloppy that +; hundreds of bytes can be squeezed out of it, it's too tempting +; to reassemble an optimized ROM with room to add something cool. + +A1F61 +DoSound JP _DoSound +L1F64 JP L0488 ; video P04A3 +L1F67 JP L06C7 ; video P06D8 +FlipRL JP _FlipRL +FlipUD JP _FlipUD +Rotate JP _Rotate +Expand JP _Expand +ReadCtlRaw JP _ReadCtlRaw +ReadCtl JR _ReadCtl + DB O +SkillScrn JP _SkillScrn +InitFont JP _InitFont +FillVRAM JP _FillVRAM +InitVDP JP _InitVDP +ReadSpinner JP _ReadSpinner +PBaseLoad JP _PBaseLoad +PBlkReadVRAM JP _PBlkReadVRAM +PBlkWrtVRAM JP _PBlkWrtVRAM +PInitRAMSprt JP _PInitRAMSprt +PCopyRAMSprt JP _PCopyRAMSprt +PInitTimers JP _PInitTimers +PStopTimer JP _PStopTimer +PStartTimer JP _PStartTimer +PTestTimer JP _PTestTimer +PWriteReg JP _PWriteReg +PWrtVRAM JP _PWrtVRam +PReadVRAM JP _PReadVRAM +L1FAF JP L0655 ; video P0664 +PInitSound JP _PInitSound +PAddSound JP _PAddSound +BaseLoad JP _BaseLoad +BlkReadVRAM JP _BlkReadVRAM +BlkWrtVRAM JP _BlkWrtVRAM +InitRAMSprt JP _InitRAMSprt +CopyRAMSprt JP _CopyRAMSprt +InitTimers JP _InitTimers +StopTimer JP _StopTimer +StartTimer JP _StartTimer +TestTimer JP _TestTimer +RunTimers JP _RunTimers +NoSound JP _NoSound +WriteReg JP _WriteReg +VDP_Status JP _VDP_Status +WrtVRAM JP _WrtVRAM +ReadVRAM JP _ReadVRAM +L1FE5 JP L0664 ; video +L1FE8 JP L0679 ; video (no P) +ReadCtlState JP _ReadCtlState +InitSound JP _InitSound +AddSound JP _AddSound ; 1FF1-1FF3 +UpdateSound JP _UpdateSound ; 1FF4-1FF6 +L1FF7 JP L04A3 ; video +L1FFA JP L06D8 ; video +Random JP _Random + +D2000 END \ No newline at end of file diff --git a/Coleco - Vision_MiST/rtl/scandoubler.v b/Coleco - Vision_MiST/rtl/scandoubler.v new file mode 100644 index 00000000..e85cba43 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/scandoubler.v @@ -0,0 +1,183 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Coleco - Vision_MiST/rtl/sn76489/COPYING b/Coleco - Vision_MiST/rtl/sn76489/COPYING new file mode 100644 index 00000000..60549be5 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Coleco - Vision_MiST/rtl/sn76489/README b/Coleco - Vision_MiST/rtl/sn76489/README new file mode 100644 index 00000000..33630144 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/README @@ -0,0 +1,143 @@ + +An SN76489AN Compatible Implementation in VHDL +============================================== +Version: $Date: 2006/06/18 19:28:40 $ + +Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +See the file COPYING. + + +Integration +----------- + +The sn76489 design exhibits all interface signals as the original chip. It +only differs in the audio data output which is provided as an 8 bit signed +vector instead of an analog output pin. + + generic ( + clock_div_16_g : integer := 1 + -- Set to '1' when operating the design in SN76489 mode. The primary clock + -- input is divided by 16 in this variant. The data sheet mentions the + -- SN76494 which contains a divide-by-2 clock input stage. Set the generic + -- to '0' to enable this mode. + ); + port ( + clock_i : in std_logic; + -- Primary clock input + -- Drive with the target frequency or any integer multiple of it. + + clock_en_i : in std_logic; + -- Clock enable + -- A '1' on this input qualifies a valid rising edge on clock_i. A '0' + -- disables the next rising clock edge, effectivley halting the design + -- until the next enabled rising clock edge. + -- Can be used to run the core at lower frequencies than applied on + -- clock_i. + + res_n_i : in std_logic; + -- Asynchronous low active reset input. + -- Sets all sequential elements to a known state. + + ce_n_i : in std_logic; + -- Chip enable, low active. + + we_n_i : in std_logic; + -- Write enable, low active. + + ready_o : out std_logic; + -- Ready indication to microprocessor. + + d_i : in std_logic_vector(0 to 7); + -- Data input + -- MSB 0 ... 7 LSB + + aout_o : out signed(0 to 7) + -- Audio output, signed vector + -- MSB/SIGN 0 ... 7 LSB + ); + + +Both 8 bit vector ports are defined (0 to 7) which declares bit 0 to be the +MSB and bit 7 to be the LSB. This has been implemented according to TI's data +sheet, thus all register/data format figures apply 1:1 for this design. +Many systems will flip the system data bus bit wise before it is connected to +this PSG. This is simply achieved with the following VHDL construct: + + signal data_s : std_logic_vector(7 downto 0); + + ... + d_i => data_s, + ... + +d_i and data_s will be assigned from left to right, resulting in the expected +bit assignment: + + d_i data_s + 0 7 + 1 6 + ... + 6 1 + 7 0 + + +As this design is fully synchronous, care has to be taken when the design +replaces an SN76489 in asynchronous mode. No problems are expected when +interfacing the code to other synchronous components. + + +Design Hierarchy +---------------- + + sn76489_top + | + +-- sn76489_latch_ctrl + | + +-- sn76489_clock_div + | + +-- sn76489_tone + | | + | \-- sn76489_attentuator + | + +-- sn76489_tone + | | + | \-- sn76489_attentuator + | + +-- sn76489_tone + | | + | \-- sn76489_attentuator + | + \-- sn76489_noise + | + \-- sn76489_attentuator + +Resulting compilation sequence: + + sn76489_comp_pack-p.vhd + sn76489_top.vhd + sn76489_latch_ctrl.vhd + sn76489_latch_ctrl-c.vhd + sn76489_clock_div.vhd + sn76489_clock_div-c.vhd + sn76489_attenuator.vhd + sn76489_attenuator-c.vhd + sn76489_tone.vhd + sn76489_tone-c.vhd + sn76489_noise.vhd + sn76489_noise-c.vhd + sn76489_top-c.vhd + +Skip the files containing VHDL configurations when analyzing the code for +synthesis. + + +References +---------- + +* TI Data sheet SN76489.pdf + ftp://ftp.whtech.com/datasheets%20&%20manuals/SN76489.pdf + +* John Kortink's article on the SN76489: + http://web.inter.nl.net/users/J.Kortink/home/articles/sn76489/ + +* Maxim's "SN76489 notes" in + http://www.smspower.org/maxim/docs/SN76489.txt diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_attenuator.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_attenuator.vhd new file mode 100644 index 00000000..444064e5 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_attenuator.vhd @@ -0,0 +1,114 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_attenuator.vhd,v 1.7 2006/02/27 20:30:10 arnim Exp $ +-- +-- Attenuator Module +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sn76489_attenuator is + + port ( + attenuation_i : in std_logic_vector(0 to 3); + factor_i : in signed(0 to 1); + product_o : out signed(0 to 7) + ); + +end sn76489_attenuator; + + +architecture rtl of sn76489_attenuator is + +begin + + ----------------------------------------------------------------------------- + -- Process attenuate + -- + -- Purpose: + -- Determine the attenuation and generate the resulting product. + -- + -- The maximum attenuation value is 31 which corresponds to volume off. + -- As described in the data sheet, the maximum "playing" attenuation is + -- 28 = 16 + 8 + 4 + -- + -- The table for the volume constants is derived from the following + -- formula (each step is 2dB voltage): + -- v(0) = 31 + -- v(n+1) = v(n) * 0.79432823 + -- + attenuate: process (attenuation_i, + factor_i) + + type volume_t is array (natural range 0 to 15) of natural; + constant volume_c : volume_t := + (31, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0); + + variable attenuation_v : unsigned(attenuation_i'range); + variable volume_v : signed(product_o'range); + + begin + + attenuation_v := unsigned(attenuation_i); + + -- volume look-up table + volume_v := to_signed(volume_c(to_integer(attenuation_v)), + product_o'length); + + -- this replaces a multiplier and consumes a bit fewer + -- resources + case to_integer(factor_i) is + when +1 => + product_o <= volume_v; + when -1 => + product_o <= -volume_v; + when others => + product_o <= (others => '0'); + end case; + + end process attenuate; + -- + ----------------------------------------------------------------------------- + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_clock_div.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_clock_div.vhd new file mode 100644 index 00000000..eab86beb --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_clock_div.vhd @@ -0,0 +1,134 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_clock_div.vhd,v 1.4 2005/10/10 21:51:27 arnim Exp $ +-- +-- Clock Divider Circuit +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity sn76489_clock_div is + + generic ( + clock_div_16_g : integer := 1 + ); + port ( + clock_i : in std_logic; + clock_en_i : in std_logic; + res_n_i : in std_logic; + clk_en_o : out boolean + ); + +end sn76489_clock_div; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of sn76489_clock_div is + + signal cnt_s, + cnt_q : unsigned(3 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential counter element. + -- + seq: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + cnt_q <= (others => '0'); + elsif clock_i'event and clock_i = '1' then + cnt_q <= cnt_s; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process comb + -- + -- Purpose: + -- Implements the combinational counter logic. + -- + comb: process (clock_en_i, + cnt_q) + begin + -- default assignments + cnt_s <= cnt_q; + clk_en_o <= false; + + if clock_en_i = '1' then + + if cnt_q = 0 then + clk_en_o <= true; + + if clock_div_16_g = 1 then + cnt_s <= to_unsigned(15, cnt_q'length); + elsif clock_div_16_g = 0 then + cnt_s <= to_unsigned( 1, cnt_q'length); + else + -- pragma translate_off + assert false + report "Generic clock_div_16_g must be either 0 or 1." + severity failure; + -- pragma translate_on + end if; + + else + cnt_s <= cnt_q - 1; + + end if; + + end if; + + end process comb; + -- + ----------------------------------------------------------------------------- + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_comp_pack.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_comp_pack.vhd new file mode 100644 index 00000000..06b12c83 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_comp_pack.vhd @@ -0,0 +1,96 @@ +------------------------------------------------------------------------------- +-- +-- $Id: sn76489_comp_pack-p.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $ +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package sn76489_comp_pack is + + component sn76489_attenuator + port ( + attenuation_i : in std_logic_vector(0 to 3); + factor_i : in signed(0 to 1); + product_o : out signed(0 to 7) + ); + end component; + + component sn76489_tone + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + we_i : in boolean; + d_i : in std_logic_vector(0 to 7); + r2_i : in std_logic; + ff_o : out std_logic; + tone_o : out signed(0 to 7) + ); + end component; + + component sn76489_noise + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + we_i : in boolean; + d_i : in std_logic_vector(0 to 7); + r2_i : in std_logic; + tone3_ff_i : in std_logic; + noise_o : out signed(0 to 7) + ); + end component; + + component sn76489_latch_ctrl + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + ce_n_i : in std_logic; + we_n_i : in std_logic; + d_i : in std_logic_vector(0 to 7); + ready_o : out std_logic; + tone1_we_o : out boolean; + tone2_we_o : out boolean; + tone3_we_o : out boolean; + noise_we_o : out boolean; + r2_o : out std_logic + ); + end component; + + component sn76489_clock_div + generic ( + clock_div_16_g : integer := 1 + ); + port ( + clock_i : in std_logic; + clock_en_i : in std_logic; + res_n_i : in std_logic; + clk_en_o : out boolean + ); + end component; + + component sn76489_top + generic ( + clock_div_16_g : integer := 1 + ); + port ( + clock_i : in std_logic; + clock_en_i : in std_logic; + res_n_i : in std_logic; + ce_n_i : in std_logic; + we_n_i : in std_logic; + ready_o : out std_logic; + d_i : in std_logic_vector(0 to 7); + aout_o : out signed(0 to 7) + ); + end component; + +end sn76489_comp_pack; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_latch_ctrl.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_latch_ctrl.vhd new file mode 100644 index 00000000..789720c2 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_latch_ctrl.vhd @@ -0,0 +1,138 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_latch_ctrl.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $ +-- +-- Latch Control Unit +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity sn76489_latch_ctrl is + + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + ce_n_i : in std_logic; + we_n_i : in std_logic; + d_i : in std_logic_vector(0 to 7); + ready_o : out std_logic; + tone1_we_o : out boolean; + tone2_we_o : out boolean; + tone3_we_o : out boolean; + noise_we_o : out boolean; + r2_o : out std_logic + ); + +end sn76489_latch_ctrl; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of sn76489_latch_ctrl is + + signal reg_q : std_logic_vector(0 to 2); + signal we_q : boolean; + signal ready_q : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + reg_q <= (others => '0'); + we_q <= false; + ready_q <= '0'; + + elsif clock_i'event and clock_i = '1' then + -- READY Flag Output ---------------------------------------------------- + if ready_q = '0' and we_q then + if clk_en_i then + -- assert READY when write access happened + ready_q <= '1'; + end if; + elsif ce_n_i = '1' then + -- deassert READY when access has finished + ready_q <= '0'; + end if; + + -- Register Selection --------------------------------------------------- + if ce_n_i = '0' and we_n_i = '0' then + if clk_en_i then + if d_i(0) = '1' then + reg_q <= d_i(1 to 3); + end if; + we_q <= true; + end if; + else + we_q <= false; + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + tone1_we_o <= reg_q(0 to 1) = "00" and we_q; + tone2_we_o <= reg_q(0 to 1) = "01" and we_q; + tone3_we_o <= reg_q(0 to 1) = "10" and we_q; + noise_we_o <= reg_q(0 to 1) = "11" and we_q; + + r2_o <= reg_q(2); + + ready_o <= ready_q + when ce_n_i = '0' else + '1'; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_noise.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_noise.vhd new file mode 100644 index 00000000..647d3cdc --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_noise.vhd @@ -0,0 +1,281 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_noise.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $ +-- +-- Noise Generator +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sn76489_noise is + + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + we_i : in boolean; + d_i : in std_logic_vector(0 to 7); + r2_i : in std_logic; + tone3_ff_i : in std_logic; + noise_o : out signed(0 to 7) + ); + +end sn76489_noise; + + +--use work.sn76489_comp_pack.sn76489_attenuator; + +architecture rtl of sn76489_noise is + + signal nf_q : std_logic_vector(0 to 1); + signal fb_q : std_logic; + signal a_q : std_logic_vector(0 to 3); + signal freq_cnt_q : unsigned(0 to 6); + signal freq_ff_q : std_logic; + + signal shift_source_s, + shift_source_q : std_logic; + signal shift_rise_edge_s : boolean; + + signal lfsr_q : std_logic_vector(0 to 15); + + signal freq_s : signed(0 to 1); + +begin + + ----------------------------------------------------------------------------- + -- Process cpu_regs + -- + -- Purpose: + -- Implements the registers writable by the CPU. + -- + cpu_regs: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + nf_q <= (others => '0'); + fb_q <= '0'; + a_q <= (others => '1'); + + elsif clock_i'event and clock_i = '1' then + if clk_en_i and we_i then + if r2_i = '0' then + -- access to control register + -- both access types can write to the control register! + nf_q <= d_i(6 to 7); + fb_q <= d_i(5); + + else + -- access to attenuator register + -- both access types can write to the attenuator register! + a_q <= d_i(4 to 7); + + end if; + end if; + end if; + end process cpu_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process freq_gen + -- + -- Purpose: + -- Implements the frequency generation components. + -- + freq_gen: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + freq_cnt_q <= (others => '0'); + freq_ff_q <= '0'; + + elsif clock_i'event and clock_i = '1' then + if clk_en_i then + if freq_cnt_q = 0 then + -- reload frequency counter according to NF setting + case nf_q is + when "00" => + freq_cnt_q <= to_unsigned(16 * 2 - 1, freq_cnt_q'length); + when "01" => + freq_cnt_q <= to_unsigned(16 * 4 - 1, freq_cnt_q'length); + when "10" => + freq_cnt_q <= to_unsigned(16 * 8 - 1, freq_cnt_q'length); + when others => + null; + end case; + + freq_ff_q <= not freq_ff_q; + + else + -- decrement frequency counter + freq_cnt_q <= freq_cnt_q - 1; + + end if; + + end if; + end if; + end process freq_gen; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Multiplex the source of the LFSR's shift enable + ----------------------------------------------------------------------------- + shift_source_s <= tone3_ff_i + when nf_q = "11" else + freq_ff_q; + + ----------------------------------------------------------------------------- + -- Process rise_edge + -- + -- Purpose: + -- Detect the rising edge of the selected LFSR shift source. + -- + rise_edge: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + shift_source_q <= '0'; + + elsif clock_i'event and clock_i = '1' then + if clk_en_i then + shift_source_q <= shift_source_s; + end if; + end if; + end process rise_edge; + -- + ----------------------------------------------------------------------------- + + -- detect rising edge on shift source + shift_rise_edge_s <= shift_source_q = '0' and shift_source_s = '1'; + + + ----------------------------------------------------------------------------- + -- Process lfsr + -- + -- Purpose: + -- Implements the LFSR that generates noise. + -- Note: This implementation shifts the register right, i.e. from index + -- 15 towards 0 => bit 15 is the input, bit 0 is the output + -- + -- Tapped bits according to MAME's sn76496.c, implemented in function + -- lfsr_tapped_f. + -- + lfsr: process (clock_i, res_n_i) + + function lfsr_tapped_f(lfsr : in std_logic_vector) return std_logic is + constant tapped_bits_c : std_logic_vector(0 to 15) + -- tapped bits are 0, 2, 15 + := "1010000000000001"; + variable parity_v : std_logic; + begin + parity_v := '0'; + + for idx in lfsr'low to lfsr'high loop + parity_v := parity_v xor (lfsr(idx) and tapped_bits_c(idx)); + end loop; + + return parity_v; + end; + + begin + if res_n_i = '0' then + -- reset LFSR to "0000000000000001" + lfsr_q <= (others => '0'); + lfsr_q(lfsr_q'right) <= '1'; + + elsif clock_i'event and clock_i = '1' then + if clk_en_i then + if we_i and r2_i = '0' then + -- write to noise register + -- -> reset LFSR + lfsr_q <= (others => '0'); + lfsr_q(lfsr_q'right) <= '1'; + + elsif shift_rise_edge_s then + + -- shift LFSR left towards MSB + for idx in lfsr_q'right-1 downto lfsr_q'left loop + lfsr_q(idx) <= lfsr_q(idx+1); + end loop; + + -- determine input bit + if fb_q = '0' then + -- "Periodic" Noise + -- -> input to LFSR is output + lfsr_q(lfsr_q'right) <= lfsr_q(lfsr_q'left); + else + -- "White" Noise + -- -> input to LFSR is parity of tapped bits + lfsr_q(lfsr_q'right) <= lfsr_tapped_f(lfsr_q); + end if; + + end if; + + end if; + end if; + end process lfsr; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Map output of LFSR to signed value for attenuator. + ----------------------------------------------------------------------------- + freq_s <= to_signed(+1, 2) + when lfsr_q(0) = '1' else + to_signed( 0, 2); + + + ----------------------------------------------------------------------------- + -- The attenuator itself + ----------------------------------------------------------------------------- + attenuator_b : entity work.sn76489_attenuator + port map ( + attenuation_i => a_q, + factor_i => freq_s, + product_o => noise_o + ); + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_tone.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_tone.vhd new file mode 100644 index 00000000..4d39a5a4 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_tone.vhd @@ -0,0 +1,189 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_tone.vhd,v 1.5 2006/02/27 20:30:10 arnim Exp $ +-- +-- Tone Generator +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +--use work.sn76489_comp_pack.all; + +entity sn76489_tone is + + port ( + clock_i : in std_logic; + clk_en_i : in boolean; + res_n_i : in std_logic; + we_i : in boolean; + d_i : in std_logic_vector(0 to 7); + r2_i : in std_logic; + ff_o : out std_logic; + tone_o : out signed(0 to 7) + ); + +end sn76489_tone; + +architecture rtl of sn76489_tone is + + signal f_q : std_logic_vector(0 to 9); + signal a_q : std_logic_vector(0 to 3); + signal freq_cnt_q : unsigned(0 to 9); + signal freq_ff_q : std_logic; + + signal freq_s : signed(0 to 1); + + function all_zero(a : in std_logic_vector) return boolean is + variable result_v : boolean; + begin + result_v := true; + + for idx in a'low to a'high loop + if a(idx) /= '0' then + result_v := false; + end if; + end loop; + + return result_v; + end; + +begin + + ----------------------------------------------------------------------------- + -- Process cpu_regs + -- + -- Purpose: + -- Implements the registers writable by the CPU. + -- + cpu_regs: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + f_q <= (others => '0'); + a_q <= (others => '1'); + + elsif clock_i'event and clock_i = '1' then + if clk_en_i and we_i then + if r2_i = '0' then + -- access to frequency register + if d_i(0) = '0' then + f_q(0 to 5) <= d_i(2 to 7); + else + f_q(6 to 9) <= d_i(4 to 7); + end if; + + else + -- access to attenuator register + -- both access types can write to the attenuator register! + a_q <= d_i(4 to 7); + + end if; + end if; + end if; + end process cpu_regs; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process freq_gen + -- + -- Purpose: + -- Implements the frequency generation components. + -- + freq_gen: process (clock_i, res_n_i) + begin + if res_n_i = '0' then + freq_cnt_q <= (others => '0'); + freq_ff_q <= '0'; + + elsif clock_i'event and clock_i = '1' then + if clk_en_i then + if freq_cnt_q = 0 then + -- update counter from frequency register + freq_cnt_q <= unsigned(f_q); + + -- and toggle the frequency flip-flop if enabled + if not all_zero(f_q) then + freq_ff_q <= not freq_ff_q; + else + -- if frequency setting is 0, then keep flip-flop at +1 + freq_ff_q <= '1'; + end if; + + else + -- decrement frequency counter + freq_cnt_q <= freq_cnt_q - 1; + + end if; + end if; + end if; + end process freq_gen; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Map frequency flip-flop to signed value for attenuator. + ----------------------------------------------------------------------------- + freq_s <= to_signed(+1, 2) + when freq_ff_q = '1' else + to_signed(-1, 2); + + + ----------------------------------------------------------------------------- + -- The attenuator itself + ----------------------------------------------------------------------------- + attenuator_b : entity work.sn76489_attenuator + port map ( + attenuation_i => a_q, + factor_i => freq_s, + product_o => tone_o + ); + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + ff_o <= freq_ff_q; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/sn76489/sn76489_top.vhd b/Coleco - Vision_MiST/rtl/sn76489/sn76489_top.vhd new file mode 100644 index 00000000..04b8ca41 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/sn76489/sn76489_top.vhd @@ -0,0 +1,197 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's SN76489AN. +-- +-- $Id: sn76489_top.vhd,v 1.9 2006/02/27 20:30:10 arnim Exp $ +-- +-- Chip Toplevel +-- +-- References: +-- +-- * TI Data sheet SN76489.pdf +-- ftp://ftp.whtech.com/datasheets%20&%20manuals/SN76489.pdf +-- +-- * John Kortink's article on the SN76489: +-- http://web.inter.nl.net/users/J.Kortink/home/articles/sn76489/ +-- +-- * Maxim's "SN76489 notes" in +-- http://www.smspower.org/maxim/docs/SN76489.txt +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sn76489_top is + + generic ( + clock_div_16_g : integer := 1 + ); + port ( + clock_i : in std_logic; -- Normally 3.58 MHz + clock_en_i : in std_logic; -- For high clocks + res_n_i : in std_logic; + ce_n_i : in std_logic; + we_n_i : in std_logic; + ready_o : out std_logic; + d_i : in std_logic_vector(0 to 7); + aout_o : out signed(0 to 7) + ); + +end entity; + +architecture struct of sn76489_top is + + signal clk_en_s : boolean; + + signal tone1_we_s, + tone2_we_s, + tone3_we_s, + noise_we_s : boolean; + signal r2_s : std_logic; + + signal tone1_s, + tone2_s, + tone3_s, + noise_s : signed(0 to 7); + + signal tone3_ff_s : std_logic; + +begin + + ----------------------------------------------------------------------------- + -- Clock Divider + ----------------------------------------------------------------------------- + clock_div_b : entity work.sn76489_clock_div + generic map ( + clock_div_16_g => clock_div_16_g + ) + port map ( + clock_i => clock_i, + clock_en_i => clock_en_i, + res_n_i => res_n_i, + clk_en_o => clk_en_s + ); + + + ----------------------------------------------------------------------------- + -- Latch Control = CPU Interface + ----------------------------------------------------------------------------- + latch_ctrl_b : entity work.sn76489_latch_ctrl + port map ( + clock_i => clock_i, + clk_en_i => clk_en_s, + res_n_i => res_n_i, + ce_n_i => ce_n_i, + we_n_i => we_n_i, + d_i => d_i, + ready_o => ready_o, + tone1_we_o => tone1_we_s, + tone2_we_o => tone2_we_s, + tone3_we_o => tone3_we_s, + noise_we_o => noise_we_s, + r2_o => r2_s + ); + + + ----------------------------------------------------------------------------- + -- Tone Channel 1 + ----------------------------------------------------------------------------- + tone1_b : entity work.sn76489_tone + port map ( + clock_i => clock_i, + clk_en_i => clk_en_s, + res_n_i => res_n_i, + we_i => tone1_we_s, + d_i => d_i, + r2_i => r2_s, + ff_o => open, + tone_o => tone1_s + ); + + ----------------------------------------------------------------------------- + -- Tone Channel 2 + ----------------------------------------------------------------------------- + tone2_b : entity work.sn76489_tone + port map ( + clock_i => clock_i, + clk_en_i => clk_en_s, + res_n_i => res_n_i, + we_i => tone2_we_s, + d_i => d_i, + r2_i => r2_s, + ff_o => open, + tone_o => tone2_s + ); + + ----------------------------------------------------------------------------- + -- Tone Channel 3 + ----------------------------------------------------------------------------- + tone3_b : entity work.sn76489_tone + port map ( + clock_i => clock_i, + clk_en_i => clk_en_s, + res_n_i => res_n_i, + we_i => tone3_we_s, + d_i => d_i, + r2_i => r2_s, + ff_o => tone3_ff_s, + tone_o => tone3_s + ); + + ----------------------------------------------------------------------------- + -- Noise Channel + ----------------------------------------------------------------------------- + noise_b : entity work.sn76489_noise + port map ( + clock_i => clock_i, + clk_en_i => clk_en_s, + res_n_i => res_n_i, + we_i => noise_we_s, + d_i => d_i, + r2_i => r2_s, + tone3_ff_i => tone3_ff_s, + noise_o => noise_s + ); + + + aout_o <= tone1_s + tone2_s + tone3_s + noise_s; + +end architecture; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_addr_mux.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_addr_mux.vhd new file mode 100644 index 00000000..9ff8c8f8 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_addr_mux.vhd @@ -0,0 +1,228 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_addr_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $ +-- +-- Address Multiplexer / Generator +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vdp18_pack.access_t; +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.hv_t; + +entity vdp18_addr_mux is + + port ( + access_type_i : in access_t; + opmode_i : in opmode_t; + num_line_i : in hv_t; + reg_ntb_i : in std_logic_vector(0 to 3); + reg_ctb_i : in std_logic_vector(0 to 7); + reg_pgb_i : in std_logic_vector(0 to 2); + reg_satb_i : in std_logic_vector(0 to 6); + reg_spgb_i : in std_logic_vector(0 to 2); + reg_size1_i : in boolean; + cpu_vram_a_i : in std_logic_vector(0 to 13); + pat_table_i : in std_logic_vector(0 to 9); + pat_name_i : in std_logic_vector(0 to 7); + spr_num_i : in std_logic_vector(0 to 4); + spr_line_i : in std_logic_vector(0 to 3); + spr_name_i : in std_logic_vector(0 to 7); + vram_a_o : out std_logic_vector(0 to 13) + ); + +end vdp18_addr_mux; + + +use work.vdp18_pack.all; + +architecture rtl of vdp18_addr_mux is + +begin + + ----------------------------------------------------------------------------- + -- Process mux + -- + -- Purpose: + -- Generates the VRAM address based on the current access type. + -- + mux: process (access_type_i, opmode_i, + num_line_i, + reg_ntb_i, reg_ctb_i, reg_pgb_i, + reg_satb_i, reg_spgb_i, + reg_size1_i, + cpu_vram_a_i, + pat_table_i, pat_name_i, + spr_num_i, spr_name_i, + spr_line_i) + variable num_line_v : std_logic_vector(num_line_i'range); + begin + -- default assignment + vram_a_o <= (others => '0'); + num_line_v := std_logic_vector(num_line_i); + + case access_type_i is + -- CPU Access ----------------------------------------------------------- + when AC_CPU => + vram_a_o <= cpu_vram_a_i; + + -- Pattern Name Table Access -------------------------------------------- + when AC_PNT => + vram_a_o(0 to 3) <= reg_ntb_i; + vram_a_o(4 to 13) <= pat_table_i; + + -- Pattern Color Table Access ------------------------------------------- + when AC_PCT => + case opmode_i is + when OPMODE_GRAPH1 => + vram_a_o( 0 to 7) <= reg_ctb_i; + vram_a_o( 8) <= '0'; + vram_a_o( 9 to 13) <= pat_name_i(0 to 4); + + when OPMODE_GRAPH2 => + vram_a_o( 0) <= reg_ctb_i(0); + vram_a_o( 1 to 2) <= num_line_v(1 to 2) and + -- remaining bits in CTB mask color + -- lookups + (reg_ctb_i(1) & reg_ctb_i(2)); + vram_a_o( 3 to 10) <= pat_name_i and + -- remaining bits in CTB mask color + -- lookups + (reg_ctb_i(3) & reg_ctb_i(4) & + reg_ctb_i(5) & reg_ctb_i(6) & + reg_ctb_i(7) & "111"); + vram_a_o(11 to 13) <= num_line_v(6 to 8); + + when others => + null; + end case; + + -- Pattern Generator Table Access --------------------------------------- + when AC_PGT => + case opmode_i is + when OPMODE_TEXTM | + OPMODE_GRAPH1 => + vram_a_o( 0 to 2) <= reg_pgb_i; + vram_a_o( 3 to 10) <= pat_name_i; + vram_a_o(11 to 13) <= num_line_v(6 to 8); + + when OPMODE_MULTIC => + vram_a_o( 0 to 2) <= reg_pgb_i; + vram_a_o( 3 to 10) <= pat_name_i; + vram_a_o(11 to 13) <= num_line_v(4 to 6); + + when OPMODE_GRAPH2 => + vram_a_o( 0) <= reg_pgb_i(0); + vram_a_o( 1 to 2) <= num_line_v(1 to 2) and + -- remaining bits in PGB mask pattern + -- lookups + (reg_pgb_i(1) & reg_pgb_i(2)); + vram_a_o( 3 to 10) <= pat_name_i and + -- remaining bits in CTB mask pattern + -- lookups + (reg_ctb_i(3) & reg_ctb_i(4) & + reg_ctb_i(5) & reg_ctb_i(6) & + reg_ctb_i(7) & "111"); + vram_a_o(11 to 13) <= num_line_v(6 to 8); + + when others => + null; + end case; + + -- Sprite Test ---------------------------------------------------------- + when AC_STST | + AC_SATY => + vram_a_o( 0 to 6) <= reg_satb_i; + vram_a_o( 7 to 11) <= spr_num_i; + vram_a_o(12 to 13) <= "00"; + + -- Sprite Attribute Table: X -------------------------------------------- + when AC_SATX => + vram_a_o( 0 to 6) <= reg_satb_i; + vram_a_o( 7 to 11) <= spr_num_i; + vram_a_o(12 to 13) <= "01"; + + -- Sprite Attribute Table: Name ----------------------------------------- + when AC_SATN => + vram_a_o( 0 to 6) <= reg_satb_i; + vram_a_o( 7 to 11) <= spr_num_i; + vram_a_o(12 to 13) <= "10"; + + -- Sprite Attribute Table: Color ---------------------------------------- + when AC_SATC => + vram_a_o( 0 to 6) <= reg_satb_i; + vram_a_o( 7 to 11) <= spr_num_i; + vram_a_o(12 to 13) <= "11"; + + -- Sprite Pattern, Upper Part ------------------------------------------- + when AC_SPTH => + vram_a_o( 0 to 2) <= reg_spgb_i; + if not reg_size1_i then + -- 8x8 sprite + vram_a_o( 3 to 10) <= spr_name_i; + vram_a_o(11 to 13) <= spr_line_i(1 to 3); + else + -- 16x16 sprite + vram_a_o( 3 to 8) <= spr_name_i(0 to 5); + vram_a_o( 9) <= '0'; + vram_a_o(10 to 13) <= spr_line_i; + end if; + + -- Sprite Pattern, Lower Part ------------------------------------------- + when AC_SPTL => + vram_a_o( 0 to 2) <= reg_spgb_i; + vram_a_o( 3 to 8) <= spr_name_i(0 to 5); + vram_a_o( 9) <= '1'; + vram_a_o(10 to 13) <= spr_line_i; + + when others => + null; + + end case; + + end process mux; + -- + ----------------------------------------------------------------------------- + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_clk_gen.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_clk_gen.vhd new file mode 100644 index 00000000..6c208907 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_clk_gen.vhd @@ -0,0 +1,154 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_clk_gen.vhd,v 1.8 2006/06/18 10:47:01 arnim Exp $ +-- +-- Clock Generator +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity vdp18_clk_gen is + + port ( + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + reset_i : in boolean; + clk_en_5m37_o : out boolean; + clk_en_3m58_o : out boolean; + clk_en_2m68_o : out boolean + ); + +end vdp18_clk_gen; + + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of vdp18_clk_gen is + + signal cnt_q : unsigned(3 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- * clock counter + -- + seq: process (clock_i, reset_i) + variable cnt_v : integer range -256 to 255; + begin + if reset_i then + cnt_q <= (others => '0'); + + elsif clock_i'event and clock_i = '1' then + if clk_en_10m7_i = '1' then + if cnt_q = 11 then + -- wrap after counting 12 clocks + cnt_q <= (others => '0'); + else + cnt_q <= cnt_q + 1; + end if; + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process clk_en + -- + -- Purpose: + -- Generates the derived clock enable signals. + -- + clk_en: process (clk_en_10m7_i, + cnt_q) + variable cnt_v : integer range -256 to 255; + begin + cnt_v := to_integer(cnt_q); + + -- 5.37 MHz clock enable -------------------------------------------------- + if clk_en_10m7_i = '1' then + case cnt_v is + when 1 | 3 | 5 | 7 | 9 | 11 => + clk_en_5m37_o <= true; + when others => + clk_en_5m37_o <= false; + end case; + else + clk_en_5m37_o <= false; + end if; + + -- 3.58 MHz clock enable -------------------------------------------------- + if clk_en_10m7_i = '1' then + case cnt_v is + when 2 | 5 | 8 | 11 => + clk_en_3m58_o <= true; + when others => + clk_en_3m58_o <= false; + end case; + else + clk_en_3m58_o <= false; + end if; + + -- 2.68 MHz clock enable -------------------------------------------------- + if clk_en_10m7_i = '1' then + case cnt_v is + when 3 | 7 | 11 => + clk_en_2m68_o <= true; + when others => + clk_en_2m68_o <= false; + end case; + else + clk_en_2m68_o <= false; + end if; + + end process clk_en; + -- + ----------------------------------------------------------------------------- + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_mux.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_mux.vhd new file mode 100644 index 00000000..e8c40327 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_mux.vhd @@ -0,0 +1,184 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_col_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $ +-- +-- Color Information Multiplexer +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity vdp18_col_mux is + + generic ( + compat_rgb_g : integer := 0 + ); + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + vert_active_i : in boolean; + hor_active_i : in boolean; + blank_i : in boolean; + reg_col0_i : in std_logic_vector(0 to 3); + pat_col_i : in std_logic_vector(0 to 3); + spr0_col_i : in std_logic_vector(0 to 3); + spr1_col_i : in std_logic_vector(0 to 3); + spr2_col_i : in std_logic_vector(0 to 3); + spr3_col_i : in std_logic_vector(0 to 3); + col_o : out std_logic_vector(0 to 3); + rgb_r_o : out std_logic_vector(0 to 7); + rgb_g_o : out std_logic_vector(0 to 7); + rgb_b_o : out std_logic_vector(0 to 7) + ); + +end vdp18_col_mux; + + +library ieee; +use ieee.numeric_std.all; + +use work.vdp18_col_pack.all; + +architecture rtl of vdp18_col_mux is + + signal col_s : std_logic_vector(0 to 3); + +begin + + ----------------------------------------------------------------------------- + -- Process col_mux + -- + -- Purpose: + -- Multiplexes the color information from different sources. + -- + col_mux: process (blank_i, + hor_active_i, vert_active_i, + spr0_col_i, spr1_col_i, + spr2_col_i, spr3_col_i, + pat_col_i, + reg_col0_i) + begin + if not blank_i then + if hor_active_i and vert_active_i then + -- priority decoder + if spr0_col_i /= "0000" then + col_s <= spr0_col_i; + elsif spr1_col_i /= "0000" then + col_s <= spr1_col_i; + elsif spr2_col_i /= "0000" then + col_s <= spr2_col_i; + elsif spr3_col_i /= "0000" then + col_s <= spr3_col_i; + elsif pat_col_i /= "0000" then + col_s <= pat_col_i; + else + col_s <= reg_col0_i; + end if; + + else + -- display border + col_s <= reg_col0_i; + end if; + + else + -- blank color channels during horizontal and vertical + -- trace back + -- required to initialize colors for each new scan line + col_s <= (others => '0'); + end if; + end process col_mux; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process rgb_reg + -- + -- Purpose: + -- Converts the color information to simple RGB and saves these in + -- output registers. + -- + rgb_reg: process (clock_i, reset_i) + variable col_v : natural range 0 to 15; + variable rgb_r_v, + rgb_g_v, + rgb_b_v : rgb_val_t; + variable rgb_table_v : rgb_table_t; + begin + if reset_i then + rgb_r_o <= (others => '0'); + rgb_g_o <= (others => '0'); + rgb_b_o <= (others => '0'); + + elsif clock_i'event and clock_i = '1' then + if clk_en_5m37_i then + -- select requested RGB table + if compat_rgb_g = 1 then + rgb_table_v := compat_rgb_table_c; + else + rgb_table_v := full_rgb_table_c; + end if; + + -- assign color to RGB channels + col_v := to_integer(unsigned(col_s)); + rgb_r_v := rgb_table_v(col_v)(r_c); + rgb_g_v := rgb_table_v(col_v)(g_c); + rgb_b_v := rgb_table_v(col_v)(b_c); + -- + rgb_r_o <= std_logic_vector(to_unsigned(rgb_r_v, 8)); + rgb_g_o <= std_logic_vector(to_unsigned(rgb_g_v, 8)); + rgb_b_o <= std_logic_vector(to_unsigned(rgb_b_v, 8)); + end if; + + end if; + end process rgb_reg; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + col_o <= col_s; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_pack-p.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_pack-p.vhd new file mode 100644 index 00000000..1d179def --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_col_pack-p.vhd @@ -0,0 +1,83 @@ +------------------------------------------------------------------------------- +-- +-- $Id: vdp18_col_pack-p.vhd,v 1.3 2006/02/28 22:30:41 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package vdp18_col_pack is + + constant r_c : natural := 0; + constant g_c : natural := 1; + constant b_c : natural := 2; + + subtype rgb_val_t is natural range 0 to 255; + type rgb_triple_t is array (natural range 0 to 2) of + rgb_val_t; + type rgb_table_t is array (natural range 0 to 15) of + rgb_triple_t; + + ----------------------------------------------------------------------------- + -- Simple RGB Value Array + -- + -- Refer to http://junior.apk.net/~drushel/pub/coleco/twwmca/wk970202.html + -- This is the MF & MdK variant. Note: only the upper three bits are used. + -- + -- + constant compat_rgb_table_c : rgb_table_t := ( + -- R G B + ( 0, 0, 0), -- Transparent + ( 0, 0, 0), -- Black + ( 32, 192, 32), -- Medium Green + ( 96, 224, 96), -- Light Green + ( 32, 32, 224), -- Dark Blue + ( 64, 96, 224), -- Light Blue + (160, 32, 32), -- Dark Red + ( 64, 192, 224), -- Cyan + (224, 32, 32), -- Medium Red + (224, 96, 96), -- Light Red + (192, 192, 32), -- Dark Yellow + (192, 192, 128), -- Light Yellow + ( 32, 128, 32), -- Dark Green + (192, 64, 160), -- Magenta + (160, 160, 160), -- Gray + (224, 224, 224) -- White + ); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Full RGB Value Array + -- + -- Refer to tms9928a.c of the MAME source distribution. + -- + constant full_rgb_table_c : rgb_table_t := ( + -- R G B + ( 0, 0, 0), -- Transparent RGB + ( 0, 0, 0), -- Black 000 + ( 33, 200, 66), -- Medium Green 162 + ( 94, 220, 120), -- Light Green 263 + ( 84, 85, 237), -- Dark Blue 227 + (125, 118, 252), -- Light Blue 337 + (212, 82, 77), -- Dark Red 622 + ( 66, 235, 245), -- Cyan 277 + (252, 85, 84), -- Medium Red 722 + (255, 121, 120), -- Light Red 733 + (212, 193, 84), -- Dark Yellow 662 + (230, 206, 128), -- Light Yellow 764 + ( 33, 176, 59), -- Dark Green 151 + (201, 91, 186), -- Magenta 625 + (204, 204, 204), -- Gray 333 + (255, 255, 255) -- White 777 + ); + -- + ----------------------------------------------------------------------------- + +end vdp18_col_pack; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_comp_pack-p.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_comp_pack-p.vhd new file mode 100644 index 00000000..b24b866a --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_comp_pack-p.vhd @@ -0,0 +1,205 @@ +------------------------------------------------------------------------------- +-- +-- $Id: vdp18_comp_pack-p.vhd,v 1.23 2006/02/28 22:30:41 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.hv_t; +use work.vdp18_pack.access_t; + +package vdp18_comp_pack is + + component vdp18_clk_gen + port ( + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + reset_i : in boolean; + clk_en_5m37_o : out boolean; + clk_en_3m58_o : out boolean; + clk_en_2m68_o : out boolean + ); + end component; + + component vdp18_hor_vert + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + ntsc_pal_i : in std_logic; + num_pix_o : out hv_t; + num_line_o : out hv_t; + vert_inc_o : out boolean; + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + blank_o : out boolean; + cnt_hor_o : out std_logic_vector(8 downto 0); + cnt_ver_o : out std_logic_vector(7 downto 0) + ); + end component; + + component vdp18_ctrl + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + vram_read_i : in boolean; + vram_write_i : in boolean; + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + num_pix_i : in hv_t; + num_line_i : in hv_t; + vert_inc_i : in boolean; + reg_blank_i : in boolean; + reg_size1_i : in boolean; + stop_sprite_i : in boolean; + clk_en_acc_o : out boolean; + access_type_o : out access_t; + vert_active_o : out boolean; + hor_active_o : out boolean; + irq_o : out boolean + ); + end component; + + component vdp18_cpuio + port ( + clock_i : in std_logic; + clk_en_10m7_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + rd_i : in boolean; + wr_i : in boolean; + mode_i : in std_logic; + cd_i : in std_logic_vector(0 to 7); + cd_o : out std_logic_vector(0 to 7); + cd_oe_o : out std_logic; + access_type_i : in access_t; + opmode_o : out opmode_t; + vram_read_o : out boolean; + vram_write_o : out boolean; + vram_we_o : out std_logic; + vram_a_o : out std_logic_vector(0 to 13); + vram_d_o : out std_logic_vector(0 to 7); + vram_d_i : in std_logic_vector(0 to 7); + spr_coll_i : in boolean; + spr_5th_i : in boolean; + spr_5th_num_i : in std_logic_vector(0 to 4); + reg_ev_o : out boolean; + reg_16k_o : out boolean; + reg_blank_o : out boolean; + reg_size1_o : out boolean; + reg_mag1_o : out boolean; + reg_ntb_o : out std_logic_vector(0 to 3); + reg_ctb_o : out std_logic_vector(0 to 7); + reg_pgb_o : out std_logic_vector(0 to 2); + reg_satb_o : out std_logic_vector(0 to 6); + reg_spgb_o : out std_logic_vector(0 to 2); + reg_col1_o : out std_logic_vector(0 to 3); + reg_col0_o : out std_logic_vector(0 to 3); + irq_i : in boolean; + int_n_o : out std_logic + ); + end component; + + component vdp18_addr_mux + port ( + access_type_i : in access_t; + opmode_i : in opmode_t; + num_line_i : in hv_t; + reg_ntb_i : in std_logic_vector(0 to 3); + reg_ctb_i : in std_logic_vector(0 to 7); + reg_pgb_i : in std_logic_vector(0 to 2); + reg_satb_i : in std_logic_vector(0 to 6); + reg_spgb_i : in std_logic_vector(0 to 2); + reg_size1_i : in boolean; + cpu_vram_a_i : in std_logic_vector(0 to 13); + pat_table_i : in std_logic_vector(0 to 9); + pat_name_i : in std_logic_vector(0 to 7); + spr_num_i : in std_logic_vector(0 to 4); + spr_line_i : in std_logic_vector(0 to 3); + spr_name_i : in std_logic_vector(0 to 7); + vram_a_o : out std_logic_vector(0 to 13) + ); + end component; + + component vdp18_pattern + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + access_type_i : in access_t; + num_line_i : in hv_t; + vram_d_i : in std_logic_vector(0 to 7); + vert_inc_i : in boolean; + vsync_n_i : in std_logic; + reg_col1_i : in std_logic_vector(0 to 3); + reg_col0_i : in std_logic_vector(0 to 3); + pat_table_o : out std_logic_vector(0 to 9); + pat_name_o : out std_logic_vector(0 to 7); + pat_col_o : out std_logic_vector(0 to 3) + ); + end component; + + component vdp18_sprite + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + access_type_i : in access_t; + num_pix_i : in hv_t; + num_line_i : in hv_t; + vram_d_i : in std_logic_vector(0 to 7); + vert_inc_i : in boolean; + reg_size1_i : in boolean; + reg_mag1_i : in boolean; + spr_5th_o : out boolean; + spr_5th_num_o : out std_logic_vector(0 to 4); + stop_sprite_o : out boolean; + spr_coll_o : out boolean; + spr_num_o : out std_logic_vector(0 to 4); + spr_line_o : out std_logic_vector(0 to 3); + spr_name_o : out std_logic_vector(0 to 7); + spr0_col_o : out std_logic_vector(0 to 3); + spr1_col_o : out std_logic_vector(0 to 3); + spr2_col_o : out std_logic_vector(0 to 3); + spr3_col_o : out std_logic_vector(0 to 3) + ); + end component; + + component vdp18_col_mux + generic ( + compat_rgb_g : integer := 0 + ); + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + vert_active_i : in boolean; + hor_active_i : in boolean; + blank_i : in boolean; + reg_col0_i : in std_logic_vector(0 to 3); + pat_col_i : in std_logic_vector(0 to 3); + spr0_col_i : in std_logic_vector(0 to 3); + spr1_col_i : in std_logic_vector(0 to 3); + spr2_col_i : in std_logic_vector(0 to 3); + spr3_col_i : in std_logic_vector(0 to 3); + col_o : out std_logic_vector(0 to 3); + rgb_r_o : out std_logic_vector(0 to 7); + rgb_g_o : out std_logic_vector(0 to 7); + rgb_b_o : out std_logic_vector(0 to 7) + ); + end component; + +end vdp18_comp_pack; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_core.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_core.vhd new file mode 100644 index 00000000..d263b914 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_core.vhd @@ -0,0 +1,394 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_core.vhd,v 1.28 2006/06/18 10:47:01 arnim Exp $ +-- +-- Core Toplevel +-- +-- Notes: +-- This core implements a simple VRAM interface which is suitable for a +-- synchronous SRAM component. There is currently no support of the +-- original DRAM interface. +-- +-- Please be aware that the colors might me slightly different from the +-- original TMS9918. It is assumed that the simplified conversion to RGB +-- encoding is equivalent to the compatability mode of the V9938. +-- Implementing a 100% correct color encoding for RGB would require +-- significantly more logic and 8-bit wide RGB DACs. +-- +-- References: +-- +-- * TI Data book TMS9918.pdf +-- http://www.bitsavers.org/pdf/ti/_dataBooks/TMS9918.pdf +-- +-- * Sean Young's tech article: +-- http://bifi.msxnet.org/msxnet/tech/tms9918a.txt +-- +-- * Paul Urbanus' discussion of the timing details +-- http://bifi.msxnet.org/msxnet/tech/tmsposting.txt +-- +-- * Richard F. Drushel's article series +-- "This Week With My Coleco ADAM" +-- http://junior.apk.net/~drushel/pub/coleco/twwmca/index.html +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity vdp18_core is + generic ( + compat_rgb_g : integer := 0 + ); + port ( + -- Global Interface ------------------------------------------------------- + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + clk_en_5m37_i : in std_logic; + reset_n_i : in std_logic; + -- CPU Interface ---------------------------------------------------------- + csr_n_i : in std_logic; + csw_n_i : in std_logic; + mode_i : in std_logic; + int_n_o : out std_logic; + cd_i : in std_logic_vector(0 to 7); + cd_o : out std_logic_vector(0 to 7); + -- VRAM Interface --------------------------------------------------------- + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + vram_we_o : out std_logic; + vram_a_o : out std_logic_vector(0 to 13); + vram_d_o : out std_logic_vector(0 to 7); + vram_d_i : in std_logic_vector(0 to 7); + -- Video Interface -------------------------------------------------------- + col_o : out std_logic_vector(0 to 3); + cnt_hor_o : out std_logic_vector(8 downto 0); + cnt_ver_o : out std_logic_vector(7 downto 0); + rgb_r_o : out std_logic_vector(0 to 7); + rgb_g_o : out std_logic_vector(0 to 7); + rgb_b_o : out std_logic_vector(0 to 7); + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + comp_sync_n_o : out std_logic + ); + +end vdp18_core; + + +use work.vdp18_comp_pack.all; +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.hv_t; +use work.vdp18_pack.access_t; +use work.vdp18_pack.to_boolean_f; + +architecture struct of vdp18_core is + + signal reset_s : boolean; + + signal clk_en_10m7_s, + clk_en_5m37_s, + clk_en_acc_s : boolean; + + signal opmode_s : opmode_t; + + signal access_type_s : access_t; + + signal num_pix_s, + num_line_s : hv_t; + signal hsync_n_s, + vsync_n_s : std_logic; + signal blank_s : boolean; + + signal vert_inc_s : boolean; + + signal reg_blank_s, + reg_size1_s, + reg_mag1_s : boolean; + + signal spr_5th_s : boolean; + signal spr_5th_num_s : std_logic_vector(0 to 4); + + signal stop_sprite_s : boolean; + signal vert_active_s, + hor_active_s : boolean; + + signal rd_s, + wr_s : boolean; + + signal reg_ntb_s : std_logic_vector(0 to 3); + signal reg_ctb_s : std_logic_vector(0 to 7); + signal reg_pgb_s : std_logic_vector(0 to 2); + signal reg_satb_s : std_logic_vector(0 to 6); + signal reg_spgb_s : std_logic_vector(0 to 2); + signal reg_col1_s, + reg_col0_s : std_logic_vector(0 to 3); + signal cpu_vram_a_s : std_logic_vector(0 to 13); + + signal pat_table_s : std_logic_vector(0 to 9); + signal pat_name_s : std_logic_vector(0 to 7); + signal pat_col_s : std_logic_vector(0 to 3); + + signal spr_num_s : std_logic_vector(0 to 4); + signal spr_line_s : std_logic_vector(0 to 3); + signal spr_name_s : std_logic_vector(0 to 7); + signal spr0_col_s, + spr1_col_s, + spr2_col_s, + spr3_col_s : std_logic_vector(0 to 3); + signal spr_coll_s : boolean; + + signal irq_s : boolean; + +-- signal false_s : boolean; + + signal vram_read_s : boolean; + signal vram_write_s : boolean; + +begin + + -- temporary defaults + -- false_s <= false; + + clk_en_10m7_s <= to_boolean_f(clk_en_10m7_i); + clk_en_5m37_s <= to_boolean_f(clk_en_5m37_i); + rd_s <= not to_boolean_f(csr_n_i); + wr_s <= not to_boolean_f(csw_n_i); + + reset_s <= reset_n_i = '0'; + + ----------------------------------------------------------------------------- + -- Horizontal and Vertical Timing Generator + ----------------------------------------------------------------------------- + hor_vert_b : vdp18_hor_vert + port map ( + clock_i => clock_i, + clk_en_5m37_i => clk_en_5m37_s, + reset_i => reset_s, + opmode_i => opmode_s, + ntsc_pal_i => '0', -- NTSC + num_pix_o => num_pix_s, + num_line_o => num_line_s, + vert_inc_o => vert_inc_s, + hsync_n_o => hsync_n_s, + vsync_n_o => vsync_n_s, + blank_o => blank_s, + cnt_hor_o => cnt_hor_o, + cnt_ver_o => cnt_ver_o + ); + + hsync_n_o <= hsync_n_s; + vsync_n_o <= vsync_n_s; + comp_sync_n_o <= not (hsync_n_s xor vsync_n_s); + + + ----------------------------------------------------------------------------- + -- Control Module + ----------------------------------------------------------------------------- + ctrl_b : vdp18_ctrl + port map ( + clock_i => clock_i, + clk_en_5m37_i => clk_en_5m37_s, + reset_i => reset_s, + opmode_i => opmode_s, + vram_read_i => vram_read_s, + vram_write_i => vram_write_s, + vram_ce_o => vram_ce_o, + vram_oe_o => vram_oe_o, + num_pix_i => num_pix_s, + num_line_i => num_line_s, + vert_inc_i => vert_inc_s, + reg_blank_i => reg_blank_s, + reg_size1_i => reg_size1_s, + stop_sprite_i => stop_sprite_s, + clk_en_acc_o => clk_en_acc_s, + access_type_o => access_type_s, + vert_active_o => vert_active_s, + hor_active_o => hor_active_s, + irq_o => irq_s + ); + + + ----------------------------------------------------------------------------- + -- CPU I/O Module + ----------------------------------------------------------------------------- + cpu_io_b : vdp18_cpuio + port map ( + clock_i => clock_i, + clk_en_10m7_i => clk_en_10m7_s, + clk_en_acc_i => clk_en_acc_s, + reset_i => reset_s, + rd_i => rd_s, + wr_i => wr_s, + mode_i => mode_i, + cd_i => cd_i, + cd_o => cd_o, + cd_oe_o => open, + access_type_i => access_type_s, + opmode_o => opmode_s, + vram_read_o => vram_read_s, + vram_write_o => vram_write_s, + vram_we_o => vram_we_o, + vram_a_o => cpu_vram_a_s, + vram_d_o => vram_d_o, + vram_d_i => vram_d_i, + spr_coll_i => spr_coll_s, + spr_5th_i => spr_5th_s, + spr_5th_num_i => spr_5th_num_s, + reg_ev_o => open, + reg_16k_o => open, + reg_blank_o => reg_blank_s, + reg_size1_o => reg_size1_s, + reg_mag1_o => reg_mag1_s, + reg_ntb_o => reg_ntb_s, + reg_ctb_o => reg_ctb_s, + reg_pgb_o => reg_pgb_s, + reg_satb_o => reg_satb_s, + reg_spgb_o => reg_spgb_s, + reg_col1_o => reg_col1_s, + reg_col0_o => reg_col0_s, + irq_i => irq_s, + int_n_o => int_n_o + ); + + + ----------------------------------------------------------------------------- + -- VRAM Address Multiplexer + ----------------------------------------------------------------------------- + addr_mux_b : vdp18_addr_mux + port map ( + access_type_i => access_type_s, + opmode_i => opmode_s, + num_line_i => num_line_s, + reg_ntb_i => reg_ntb_s, + reg_ctb_i => reg_ctb_s, + reg_pgb_i => reg_pgb_s, + reg_satb_i => reg_satb_s, + reg_spgb_i => reg_spgb_s, + reg_size1_i => reg_size1_s, + cpu_vram_a_i => cpu_vram_a_s, + pat_table_i => pat_table_s, + pat_name_i => pat_name_s, + spr_num_i => spr_num_s, + spr_line_i => spr_line_s, + spr_name_i => spr_name_s, + vram_a_o => vram_a_o + ); + + + ----------------------------------------------------------------------------- + -- Pattern Generator + ----------------------------------------------------------------------------- + pattern_b : vdp18_pattern + port map ( + clock_i => clock_i, + clk_en_5m37_i => clk_en_5m37_s, + clk_en_acc_i => clk_en_acc_s, + reset_i => reset_s, + opmode_i => opmode_s, + access_type_i => access_type_s, + num_line_i => num_line_s, + vram_d_i => vram_d_i, + vert_inc_i => vert_inc_s, + vsync_n_i => vsync_n_s, + reg_col1_i => reg_col1_s, + reg_col0_i => reg_col0_s, + pat_table_o => pat_table_s, + pat_name_o => pat_name_s, + pat_col_o => pat_col_s + ); + + + ----------------------------------------------------------------------------- + -- Sprite Generator + ----------------------------------------------------------------------------- + sprite_b : vdp18_sprite + port map ( + clock_i => clock_i, + clk_en_5m37_i => clk_en_5m37_s, + clk_en_acc_i => clk_en_acc_s, + reset_i => reset_s, + access_type_i => access_type_s, + num_pix_i => num_pix_s, + num_line_i => num_line_s, + vram_d_i => vram_d_i, + vert_inc_i => vert_inc_s, + reg_size1_i => reg_size1_s, + reg_mag1_i => reg_mag1_s, + spr_5th_o => spr_5th_s, + spr_5th_num_o => spr_5th_num_s, + stop_sprite_o => stop_sprite_s, + spr_coll_o => spr_coll_s, + spr_num_o => spr_num_s, + spr_line_o => spr_line_s, + spr_name_o => spr_name_s, + spr0_col_o => spr0_col_s, + spr1_col_o => spr1_col_s, + spr2_col_o => spr2_col_s, + spr3_col_o => spr3_col_s + ); + + + ----------------------------------------------------------------------------- + -- Color Multiplexer + ----------------------------------------------------------------------------- + col_mux_b : vdp18_col_mux + generic map ( + compat_rgb_g => compat_rgb_g + ) + port map ( + clock_i => clock_i, + clk_en_5m37_i => clk_en_5m37_s, + reset_i => reset_s, + vert_active_i => vert_active_s, + hor_active_i => hor_active_s, + blank_i => blank_s, + reg_col0_i => reg_col0_s, + pat_col_i => pat_col_s, + spr0_col_i => spr0_col_s, + spr1_col_i => spr1_col_s, + spr2_col_i => spr2_col_s, + spr3_col_i => spr3_col_s, + col_o => col_o, + rgb_r_o => rgb_r_o, + rgb_g_o => rgb_g_o, + rgb_b_o => rgb_b_o + ); + +end struct; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_core_comp_pack-p.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_core_comp_pack-p.vhd new file mode 100644 index 00000000..8cf260c0 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_core_comp_pack-p.vhd @@ -0,0 +1,49 @@ +------------------------------------------------------------------------------- +-- +-- $Id: vdp18_core_comp_pack-p.vhd,v 1.10 2006/02/28 22:30:41 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package vdp18_core_comp_pack is + + component vdp18_core + generic ( + is_pal_g : boolean := false; + compat_rgb_g : integer := 0 + ); + port ( + clock_i : in std_logic; + clk_en_10m7_i : in std_logic; + reset_n_i : in std_logic; + csr_n_i : in std_logic; + csw_n_i : in std_logic; + mode_i : in std_logic; + int_n_o : out std_logic; + cd_i : in std_logic_vector(0 to 7); + cd_o : out std_logic_vector(0 to 7); + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + vram_we_o : out std_logic; + vram_a_o : out std_logic_vector(0 to 13); + vram_d_o : out std_logic_vector(0 to 7); + vram_d_i : in std_logic_vector(0 to 7); + col_o : out std_logic_vector(0 to 3); + cnt_hor_o : out std_logic_vector(8 downto 0); + cnt_ver_o : out std_logic_vector(7 downto 0); + rgb_r_o : out std_logic_vector(0 to 7); + rgb_g_o : out std_logic_vector(0 to 7); + rgb_b_o : out std_logic_vector(0 to 7); + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + comp_sync_n_o : out std_logic + ); + end component; + +end vdp18_core_comp_pack; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_cpuio.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_cpuio.vhd new file mode 100644 index 00000000..bdf78042 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_cpuio.vhd @@ -0,0 +1,572 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_cpuio.vhd,v 1.17 2006/06/18 10:47:01 arnim Exp $ +-- +-- CPU I/O Interface Module +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vdp18_pack.access_t; +use work.vdp18_pack.opmode_t; + +entity vdp18_cpuio is + + port ( + clock_i : in std_logic; + clk_en_10m7_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + rd_i : in boolean; + wr_i : in boolean; + mode_i : in std_logic; + cd_i : in std_logic_vector(0 to 7); + cd_o : out std_logic_vector(0 to 7); + cd_oe_o : out std_logic; + access_type_i : in access_t; + opmode_o : out opmode_t; + vram_read_o : out boolean; + vram_write_o : out boolean; + vram_we_o : out std_logic; + vram_a_o : out std_logic_vector(0 to 13); + vram_d_o : out std_logic_vector(0 to 7); + vram_d_i : in std_logic_vector(0 to 7); + spr_coll_i : in boolean; + spr_5th_i : in boolean; + spr_5th_num_i : in std_logic_vector(0 to 4); + reg_ev_o : out boolean; + reg_16k_o : out boolean; + reg_blank_o : out boolean; + reg_size1_o : out boolean; + reg_mag1_o : out boolean; + reg_ntb_o : out std_logic_vector(0 to 3); + reg_ctb_o : out std_logic_vector(0 to 7); + reg_pgb_o : out std_logic_vector(0 to 2); + reg_satb_o : out std_logic_vector(0 to 6); + reg_spgb_o : out std_logic_vector(0 to 2); + reg_col1_o : out std_logic_vector(0 to 3); + reg_col0_o : out std_logic_vector(0 to 3); + irq_i : in boolean; + int_n_o : out std_logic + ); + +end vdp18_cpuio; + + +library ieee; +use ieee.numeric_std.all; + +use work.vdp18_pack.all; + +architecture rtl of vdp18_cpuio is + + type state_t is (ST_IDLE, + ST_RD_MODE0, ST_WR_MODE0, + ST_RD_MODE1, + ST_WR_MODE1_1ST, ST_WR_MODE1_1ST_IDLE, + ST_WR_MODE1_2ND_VREAD, ST_WR_MODE1_2ND_VWRITE, + ST_WR_MODE1_2ND_RWRITE); + signal state_s, + state_q : state_t; + + signal buffer_q : std_logic_vector(0 to 7); + + signal addr_q : unsigned(0 to 13); + + signal incr_addr_s, + load_addr_s : boolean; + + signal wrbuf_cpu_s : boolean; + signal sched_rdvram_s, + rdvram_sched_q, + rdvram_q : boolean; + signal abort_wrvram_s, + sched_wrvram_s, + wrvram_sched_q, + wrvram_q : boolean; + + signal write_tmp_s : boolean; + signal tmp_q : std_logic_vector(0 to 7); + signal write_reg_s : boolean; + + -- control register bits ---------------------------------------------------- + type ctrl_reg_t is array (natural range 7 downto 0) of + std_logic_vector(0 to 7); + signal ctrl_reg_q : ctrl_reg_t; + + -- status register ---------------------------------------------------------- + signal status_reg_s : std_logic_vector(0 to 7); + signal destr_rd_status_s : boolean; + signal sprite_5th_q : boolean; + signal sprite_5th_num_q : std_logic_vector(0 to 4); + signal sprite_coll_q : boolean; + signal int_n_q : std_logic; + + + type read_mux_t is (RDMUX_STATUS, RDMUX_READAHEAD); + signal read_mux_s : read_mux_t; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (clock_i, reset_i) + variable incr_addr_v : boolean; + begin + if reset_i then + state_q <= ST_IDLE; + buffer_q <= (others => '0'); + addr_q <= (others => '0'); + rdvram_sched_q <= false; + rdvram_q <= false; + wrvram_sched_q <= false; + wrvram_q <= false; + + elsif clock_i'event and clock_i = '1' then + -- default assignments + incr_addr_v := incr_addr_s; + + if clk_en_10m7_i then + -- update state vector ------------------------------------------------ + state_q <= state_s; + + -- buffer and flag control -------------------------------------------- + if wrbuf_cpu_s then + -- write read-ahead buffer from CPU bus + buffer_q <= cd_i; + -- immediately stop read-ahead + rdvram_sched_q <= false; + rdvram_q <= false; + elsif clk_en_acc_i and rdvram_q and access_type_i = AC_CPU then + -- write read-ahead buffer from VRAM during CPU access slot + buffer_q <= vram_d_i; + -- stop scanning for CPU data + rdvram_q <= false; + -- increment read-ahead address + incr_addr_v := true; + end if; + + if sched_rdvram_s then + -- immediately stop write-back + wrvram_sched_q <= false; + wrvram_q <= false; + -- schedule read-ahead + rdvram_sched_q <= true; + end if; + + if sched_wrvram_s then + -- schedule write-back + wrvram_sched_q <= true; + end if; + + if abort_wrvram_s then + -- stop scanning for write-back + wrvram_q <= false; + end if; + + if rdvram_sched_q and clk_en_acc_i then + -- align scheduled read-ahead with access slot phase + rdvram_sched_q <= false; + rdvram_q <= true; + end if; + if wrvram_sched_q and clk_en_acc_i then + -- align scheduled write-back with access slot phase + wrvram_sched_q <= false; + wrvram_q <= true; + end if; + + -- manage address ----------------------------------------------------- + if load_addr_s then + addr_q(6 to 13) <= unsigned(tmp_q); + addr_q(0 to 5) <= unsigned(cd_i(2 to 7)); + elsif incr_addr_v then + addr_q <= addr_q + 1; + end if; + + end if; + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + vram_read_o <= rdvram_q; + vram_write_o <= wrvram_q; + + ----------------------------------------------------------------------------- + -- Process wback_ctrl + -- + -- Purpose: + -- Write-back control. + -- + wback_ctrl: process (clk_en_acc_i, + access_type_i, + wrvram_q) + begin + -- default assignments + abort_wrvram_s <= false; + incr_addr_s <= false; + vram_we_o <= '0'; + + if wrvram_q then + if access_type_i = AC_CPU then + -- signal write access to VRAM + vram_we_o <= '1'; + + if clk_en_acc_i then + -- clear write-back flag and increment address + abort_wrvram_s <= true; + incr_addr_s <= true; + end if; + end if; + end if; + end process wback_ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process reg_if + -- + -- Purpose: + -- Implements the register interface. + -- + reg_if: process (clock_i, reset_i) + variable reg_addr_v : unsigned(0 to 2); + begin + if reset_i then + tmp_q <= (others => '0'); + ctrl_reg_q <= (others => (others => '0')); + sprite_coll_q <= false; + sprite_5th_q <= false; + sprite_5th_num_q <= (others => '0'); + int_n_q <= '1'; + ctrl_reg_q(1) <= X"C0"; + ctrl_reg_q(2) <= X"02"; + ctrl_reg_q(3) <= X"2C"; + ctrl_reg_q(7) <= X"F7"; + + elsif clock_i'event and clock_i = '1' then + if clk_en_10m7_i then + -- Temporary register ------------------------------------------------- + if write_tmp_s then + tmp_q <= cd_i; + end if; + + -- Registers 0 to 7 --------------------------------------------------- + if write_reg_s then + reg_addr_v := unsigned(cd_i(5 to 7)); + ctrl_reg_q(to_integer(reg_addr_v)) <= tmp_q; + end if; + + end if; + + -- Fifth sprite handling ------------------------------------------------ + if spr_5th_i and not sprite_5th_q then + sprite_5th_q <= true; + sprite_5th_num_q <= spr_5th_num_i; + elsif destr_rd_status_s then + sprite_5th_q <= false; + end if; + + -- Sprite collision flag ------------------------------------------------ + if spr_coll_i then + sprite_coll_q <= true; + elsif destr_rd_status_s then + sprite_coll_q <= false; + end if; + + -- Interrupt ------------------------------------------------------------ + if irq_i then + int_n_q <= '0'; + elsif destr_rd_status_s then + int_n_q <= '1'; + end if; + end if; + end process reg_if; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process access_ctrl + -- + -- Purpose: + -- Implements the combinational logic for the CPU I/F FSM. + -- Decodes the CPU I/F FSM state and generates the control signals for the + -- register and VRAM logic. + -- + access_ctrl: process (state_q, + rd_i, wr_i, + mode_i, + cd_i) + type transfer_mode_t is (TM_NONE, + TM_RD_MODE0, TM_WR_MODE0, + TM_RD_MODE1, TM_WR_MODE1); + variable transfer_mode_v : transfer_mode_t; + begin + -- default assignments + state_s <= state_q; + sched_rdvram_s <= false; + sched_wrvram_s <= false; + wrbuf_cpu_s <= false; + write_tmp_s <= false; + write_reg_s <= false; + load_addr_s <= false; + read_mux_s <= RDMUX_STATUS; + destr_rd_status_s <= false; + + -- determine transfer mode + transfer_mode_v := TM_NONE; + if mode_i = '0' then + if rd_i then + transfer_mode_v := TM_RD_MODE0; + end if; + if wr_i then + transfer_mode_v := TM_WR_MODE0; + end if; + else + if rd_i then + transfer_mode_v := TM_RD_MODE1; + end if; + if wr_i then + transfer_mode_v := TM_WR_MODE1; + end if; + end if; + + -- FSM state transitions + case state_q is + -- ST_IDLE: waiting for CPU access -------------------------------------- + when ST_IDLE => + case transfer_mode_v is + when TM_RD_MODE0 => + state_s <= ST_RD_MODE0; + when TM_WR_MODE0 => + state_s <= ST_WR_MODE0; + when TM_RD_MODE1 => + state_s <= ST_RD_MODE1; + when TM_WR_MODE1 => + state_s <= ST_WR_MODE1_1ST; + when others => + null; + end case; + + -- ST_RD_MODE0: read from VRAM ------------------------------------------ + when ST_RD_MODE0 => + -- set read mux + read_mux_s <= RDMUX_READAHEAD; + + if transfer_mode_v = TM_NONE then + -- CPU finished read access: + -- schedule new read-ahead and return to idle + state_s <= ST_IDLE; + sched_rdvram_s <= true; + end if; + + -- ST_WR_MODE0: write to VRAM ------------------------------------------- + when ST_WR_MODE0 => + -- write data from CPU to write-back/read-ahead buffer + wrbuf_cpu_s <= true; + + if transfer_mode_v = TM_NONE then + -- CPU finished write access: + -- schedule new write-back and return to idle + state_s <= ST_IDLE; + sched_wrvram_s <= true; + end if; + + -- ST_RD_MODE1: read from status register ------------------------------- + when ST_RD_MODE1 => + -- set read mux + read_mux_s <= RDMUX_STATUS; + + if transfer_mode_v = TM_NONE then + -- CPU finished read access: + -- destructive read of status register and return to IDLE + destr_rd_status_s <= true; + state_s <= ST_IDLE; + end if; + + -- ST_WR_MODE1_1ST: save first byte ------------------------------------- + when ST_WR_MODE1_1ST => + -- update temp register + write_tmp_s <= true; + + if transfer_mode_v = TM_NONE then + -- CPU finished write access: + -- become idle but remember that the first byte of a paired write + -- has been written + state_s <= ST_WR_MODE1_1ST_IDLE; + end if; + + -- ST_WR_MODE1_1ST_IDLE: wait for next access --------------------------- + when ST_WR_MODE1_1ST_IDLE => + -- determine type of next access + case transfer_mode_v is + when TM_RD_MODE0 => + state_s <= ST_RD_MODE0; + when TM_WR_MODE0 => + state_s <= ST_WR_MODE0; + when TM_RD_MODE1 => + state_s <= ST_RD_MODE1; + when TM_WR_MODE1 => + case cd_i(0 to 1) is + when "00" => + state_s <= ST_WR_MODE1_2ND_VREAD; + when "01" => + state_s <= ST_WR_MODE1_2ND_VWRITE; + when "10" | "11" => + state_s <= ST_WR_MODE1_2ND_RWRITE; + when others => + null; + end case; + when others => + null; + end case; + + -- ST_WR_MODE1_2ND_VREAD: write second byte of address, then read ahead - + when ST_WR_MODE1_2ND_VREAD => + load_addr_s <= true; + + if transfer_mode_v = TM_NONE then + -- CPU finished write access: + -- schedule new read-ahead and return to idle + sched_rdvram_s <= true; + state_s <= ST_IDLE; + end if; + + -- ST_WR_MODE1_2ND_VWRITE: write second byte of address + when ST_WR_MODE1_2ND_VWRITE => + load_addr_s <= true; + + if transfer_mode_v = TM_NONE then + -- CPU finished write access: + -- return to idle + state_s <= ST_IDLE; + end if; + + -- ST_WR_MODE1_2ND_RWRITE: write to register ---------------------------- + when ST_WR_MODE1_2ND_RWRITE => + write_reg_s <= true; + + if transfer_mode_v = TM_NONE then + -- CPU finished write access: + -- return to idle + state_s <= ST_IDLE; + end if; + + when others => + null; + + end case; + + end process access_ctrl; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process mode_decode + -- + -- Purpose: + -- Decodes the display mode from the M1, M2, M3 bits. + -- + mode_decode: process (ctrl_reg_q) + variable mode_v : std_logic_vector(0 to 2); + begin + mode_v := ctrl_reg_q(1)(3) & -- M1 + ctrl_reg_q(1)(4) & -- M2 + ctrl_reg_q(0)(6); -- M3 + + case mode_v is + when "000" => + opmode_o <= OPMODE_GRAPH1; + when "001" => + opmode_o <= OPMODE_GRAPH2; + when "010" => + opmode_o <= OPMODE_MULTIC; + when "100" => + opmode_o <= OPMODE_TEXTM; + when others => + opmode_o <= OPMODE_TEXTM; + end case; + end process mode_decode; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Build status register + ----------------------------------------------------------------------------- + status_reg_s <= not int_n_q & + to_std_logic_f(sprite_5th_q) & + to_std_logic_f(sprite_coll_q) & + sprite_5th_num_q; + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + vram_a_o <= std_logic_vector(addr_q); + vram_d_o <= buffer_q; + + cd_o <= buffer_q when read_mux_s = RDMUX_READAHEAD else status_reg_s; + cd_oe_o <= '1' when rd_i else '0'; + + reg_ev_o <= to_boolean_f(ctrl_reg_q(0)(7)); + reg_16k_o <= to_boolean_f(ctrl_reg_q(1)(0)); + reg_blank_o <= not to_boolean_f(ctrl_reg_q(1)(1)); + reg_size1_o <= to_boolean_f(ctrl_reg_q(1)(6)); + reg_mag1_o <= to_boolean_f(ctrl_reg_q(1)(7)); + reg_ntb_o <= ctrl_reg_q(2)(4 to 7); + reg_ctb_o <= ctrl_reg_q(3); + reg_pgb_o <= ctrl_reg_q(4)(5 to 7); + reg_satb_o <= ctrl_reg_q(5)(1 to 7); + reg_spgb_o <= ctrl_reg_q(6)(5 to 7); + reg_col1_o <= ctrl_reg_q(7)(0 to 3); + reg_col0_o <= ctrl_reg_q(7)(4 to 7); + int_n_o <= int_n_q or not ctrl_reg_q(1)(2); + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_ctrl.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_ctrl.vhd new file mode 100644 index 00000000..6b6f8b23 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_ctrl.vhd @@ -0,0 +1,410 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_ctrl.vhd,v 1.26 2006/06/18 10:47:01 arnim Exp $ +-- +-- Timing Controller +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.hv_t; +use work.vdp18_pack.access_t; + +entity vdp18_ctrl is + + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + vram_read_i : in boolean; + vram_write_i : in boolean; + vram_ce_o : out std_logic; + vram_oe_o : out std_logic; + num_pix_i : in hv_t; + num_line_i : in hv_t; + vert_inc_i : in boolean; + reg_blank_i : in boolean; + reg_size1_i : in boolean; + stop_sprite_i : in boolean; + clk_en_acc_o : out boolean; + access_type_o : out access_t; + vert_active_o : out boolean; + hor_active_o : out boolean; + irq_o : out boolean + ); + +end vdp18_ctrl; + + +use work.vdp18_pack.all; + +architecture rtl of vdp18_ctrl is + + ----------------------------------------------------------------------------- + -- This enables a workaround for a bug in XST. + -- ISE 8.1.02i implements wrong functionality otherwise :-( + -- + constant xst_bug_wa_c : boolean := true; + -- + ----------------------------------------------------------------------------- + + signal access_type_s : access_t; + + -- pragma translate_off + -- Testbench signals -------------------------------------------------------- + -- + signal ac_s : std_logic_vector(3 downto 0); + -- + ----------------------------------------------------------------------------- + -- pragma translate_on + + signal vert_active_q, + hor_active_q : boolean; + signal sprite_active_q : boolean; + signal sprite_line_act_q : boolean; + +begin + + -- pragma translate_off + -- Testbench signals -------------------------------------------------------- + -- + ac_s <= enum_to_vec_f(access_type_s); + -- + ----------------------------------------------------------------------------- + -- pragma translate_on + + + ----------------------------------------------------------------------------- + -- Process decode_access + -- + -- Purpose: + -- Decode horizontal counter value to access type. + -- + decode_access: process (opmode_i, + num_pix_i, + vert_active_q, + sprite_line_act_q, + reg_size1_i) + variable num_pix_plus_6_v : hv_t; + variable mod_6_v : hv_t; + variable num_pix_plus_8_v : hv_t; + variable num_pix_plus_32_v : hv_t; + variable num_pix_spr_v : integer; + begin + -- default assignment + access_type_s <= AC_CPU; + + -- prepare number of pixels for pattern operations + num_pix_plus_6_v := num_pix_i + 6; + num_pix_plus_8_v := num_pix_i + 8; + num_pix_plus_32_v := num_pix_i + 32; + num_pix_spr_v := to_integer(num_pix_i and "111111110"); + + case opmode_i is + -- Graphics I, II and Multicolor Mode ----------------------------------- + when OPMODE_GRAPH1 | + OPMODE_GRAPH2 | + OPMODE_MULTIC => + -- + -- Patterns + -- + if vert_active_q then + if num_pix_plus_8_v(0) = '0' then + if not xst_bug_wa_c then + + -- original code, we want this + case num_pix_plus_8_v(6 to 7) is + when "01" => + access_type_s <= AC_PNT; + when "10" => + if opmode_i /= OPMODE_MULTIC then + -- no access to pattern color table in multicolor mode + access_type_s <= AC_PCT; + end if; + when "11" => + access_type_s <= AC_PGT; + when others => + null; + end case; + + else + + -- workaround for XST bug, we need this + if num_pix_plus_8_v(6 to 7) = "01" then + access_type_s <= AC_PNT; + elsif num_pix_plus_8_v(6 to 7) = "10" then + if opmode_i /= OPMODE_MULTIC then + access_type_s <= AC_PCT; + end if; + elsif num_pix_plus_8_v(6 to 7) = "11" then + access_type_s <= AC_PGT; + end if; + + end if; + end if; + end if; + + -- + -- Sprite test + -- + if sprite_line_act_q then + if num_pix_i(0) = '0' and + num_pix_i(0 to 5) /= "011111" and + num_pix_i(6 to 7) = "00" and + num_pix_i(4 to 5) /= "00" then + -- sprite test interleaved with pattern accesses + access_type_s <= AC_STST; + end if; + if (num_pix_plus_32_v(0 to 4) = "00000" or + num_pix_plus_32_v(0 to 5) = "000010") and + num_pix_plus_32_v(6 to 7) /= "00" then + -- sprite tests before starting pattern phase + access_type_s <= AC_STST; + end if; + + -- + -- Sprite Attribute Table and Sprite Pattern Table + -- + case num_pix_spr_v is + when 250 | -78 | + -62 | -46 => + access_type_s <= AC_SATY; + when 254 | -76 | + -60 | -44 => + access_type_s <= AC_SATX; + when 252 | -74 | + -58 | -42 => + access_type_s <= AC_SATN; + when -86 | -70 | + -54 | -38 => + access_type_s <= AC_SATC; + when -84 | -68 | + -52 | -36 => + access_type_s <= AC_SPTH; + when -82 | -66 | + -50 | -34 => + if reg_size1_i then + access_type_s <= AC_SPTL; + end if; + when others => + null; + end case; + end if; + + -- Text Mode ------------------------------------------------------------ + when OPMODE_TEXTM => + if vert_active_q and + num_pix_plus_6_v(0) = '0' and + num_pix_plus_6_v(0 to 4) /= "01111" then + mod_6_v := mod_6_f(num_pix_plus_6_v); + case mod_6_v(6 to 7) is + when "00" => + access_type_s <= AC_PNT; + when "10" => + access_type_s <= AC_PGT; + when others => + null; + end case; + end if; + + -- Unknown -------------------------------------------------------------- +-- when others => +-- null; + + end case; + + end process decode_access; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process vert_flags + -- + -- Purpose: + -- Track the vertical position with flags. + -- + vert_flags: process (clock_i, reset_i) + begin + if reset_i then + vert_active_q <= false; + sprite_active_q <= false; + sprite_line_act_q <= false; + + elsif clock_i'event and clock_i = '1' then + if clk_en_5m37_i then + -- line-local sprite processing + if sprite_active_q then + -- sprites are globally enabled + if vert_inc_i then + -- reload at beginning of every new line + -- => scan with STST + sprite_line_act_q <= true; + end if; + + if num_pix_i = hv_sprite_start_c then + -- reload when access to sprite memory starts + sprite_line_act_q <= true; + end if; + end if; + + if vert_inc_i then + -- global sprite processing + if reg_blank_i then + sprite_active_q <= false; + sprite_line_act_q <= false; + elsif num_line_i = -2 then + -- start at line -1 + sprite_active_q <= true; + -- initialize immediately + sprite_line_act_q <= true; + elsif num_line_i = 191 then + -- stop at line 192 + sprite_active_q <= false; + -- force stop + sprite_line_act_q <= false; + end if; + + -- global vertical display + if reg_blank_i then + vert_active_q <= false; + elsif num_line_i = -1 then + -- start vertical display at line 0 + vert_active_q <= true; + elsif num_line_i = 191 then + -- stop at line 192 + vert_active_q <= false; + end if; + end if; + + if stop_sprite_i then + -- stop processing of sprites in this line + sprite_line_act_q <= false; + end if; + + end if; + end if; + end process vert_flags; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process hor_flags + -- + -- Purpose: + -- Track the horizontal position. + -- + hor_flags: process (clock_i, reset_i) + begin + if reset_i then + hor_active_q <= false; + + elsif clock_i'event and clock_i = '1' then + if clk_en_5m37_i then + if not reg_blank_i and + num_pix_i = -1 then + hor_active_q <= true; + end if; + + if opmode_i = OPMODE_TEXTM then + if num_pix_i = 239 then + hor_active_q <= false; + end if; + else + if num_pix_i = 255 then + hor_active_q <= false; + end if; + end if; + end if; + end if; + end process hor_flags; + -- + ----------------------------------------------------------------------------- + + vram_ctrl: process (clock_i) + variable read_b_v : boolean; + begin + if rising_edge(clock_i) then + if clk_en_5m37_i then + vram_ce_o <= '0'; + vram_oe_o <= '0'; + if access_type_s = AC_CPU then + if vram_read_i and not read_b_v then + vram_ce_o <= '1'; + vram_oe_o <= '1'; + read_b_v := true; + elsif vram_write_i and not read_b_v then + vram_ce_o <= '1'; + -- + read_b_v := true; + else + read_b_v := false; + end if; + else + if not read_b_v then + vram_ce_o <= '1'; + vram_oe_o <= '1'; + read_b_v := true; + else + read_b_v := false; + end if; + end if; + end if; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Ouput mapping + ----------------------------------------------------------------------------- + -- generate clock enable for flip-flops working on access_type + clk_en_acc_o <= clk_en_5m37_i and num_pix_i(8) = '1'; + access_type_o <= access_type_s; + vert_active_o <= vert_active_q; + hor_active_o <= hor_active_q; + irq_o <= vert_inc_i and num_line_i = 191; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_hor_vert.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_hor_vert.vhd new file mode 100644 index 00000000..07c7e63c --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_hor_vert.vhd @@ -0,0 +1,243 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_hor_vert.vhd,v 1.11 2006/06/18 10:47:01 arnim Exp $ +-- +-- Horizontal / Vertical Timing Generator +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.hv_t; + +entity vdp18_hor_vert is + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + ntsc_pal_i : in std_logic; + num_pix_o : out hv_t; + num_line_o : out hv_t; + vert_inc_o : out boolean; + hsync_n_o : out std_logic; + vsync_n_o : out std_logic; + blank_o : out boolean; + cnt_hor_o : out std_logic_vector(8 downto 0); + cnt_ver_o : out std_logic_vector(7 downto 0) + ); + +end vdp18_hor_vert; + + +use work.vdp18_pack.all; + +architecture rtl of vdp18_hor_vert is + + signal last_line_s : hv_t; + signal first_line_s : hv_t; + + signal first_pix_s : hv_t; + signal last_pix_s : hv_t; + + signal cnt_hor_q : hv_t; + signal cnt_vert_q : hv_t; + + signal vert_inc_s : boolean; + + signal hblank_q, + vblank_q : boolean; + + signal cnt_hor_s : unsigned(8 downto 0); + signal cnt_ver_s : unsigned(7 downto 0); + +begin + + ----------------------------------------------------------------------------- + -- Prepare comparison signals for NTSC and PAL. + -- + first_line_s <= hv_first_line_ntsc_c when ntsc_pal_i = '0' else hv_first_line_pal_c; + last_line_s <= hv_last_line_ntsc_c when ntsc_pal_i = '0' else hv_last_line_pal_c; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process opmode_mux + -- + -- Purpose: + -- Generates the horizontal counter limits based on the current operating + -- mode. + -- + opmode_mux: process (opmode_i) + begin + if opmode_i = OPMODE_TEXTM then + first_pix_s <= hv_first_pix_text_c; + last_pix_s <= hv_last_pix_text_c; + else + first_pix_s <= hv_first_pix_graph_c; + last_pix_s <= hv_last_pix_graph_c; + end if; + end process opmode_mux; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process counters + -- + -- Purpose: + -- Implements the horizontal and vertical counters. + -- + counters: process (clock_i, reset_i, first_line_s) + begin + if reset_i then + cnt_hor_q <= hv_first_pix_text_c; + cnt_vert_q <= first_line_s; + hsync_n_o <= '1'; + vsync_n_o <= '1'; + hblank_q <= false; + vblank_q <= false; + + elsif clock_i'event and clock_i = '1' then + if clk_en_5m37_i then + -- The horizontal counter --------------------------------------------- + if cnt_hor_q = last_pix_s then + cnt_hor_q <= first_pix_s; + else + cnt_hor_q <= cnt_hor_q + 1; + end if; + + -- The vertical counter ----------------------------------------------- + if cnt_vert_q = last_line_s then + cnt_vert_q <= first_line_s; + elsif vert_inc_s then + -- increment when horizontal counter is at trigger position + cnt_vert_q <= cnt_vert_q + 1; + end if; + + -- Horizontal sync ---------------------------------------------------- + if cnt_hor_q = -64 then -- -64 -44 -56 + hsync_n_o <= '0'; + elsif cnt_hor_q = -38 then -- -38 -18 -30 + hsync_n_o <= '1'; + end if; + if cnt_hor_q = -72 then -- -72 -62 -69 + hblank_q <= true; + elsif cnt_hor_q = -13 then -- -14 -4 -11 + hblank_q <= false; + end if; + + -- Vertical sync ------------------------------------------------------ + if ntsc_pal_i = '1' then + if cnt_vert_q = 244 then + vsync_n_o <= '0'; + elsif cnt_vert_q = 247 then + vsync_n_o <= '1'; + end if; + + if cnt_vert_q = 242 then + vblank_q <= true; + elsif cnt_vert_q = first_line_s + 13 then + vblank_q <= false; + end if; + else + if cnt_vert_q = 218 then + vsync_n_o <= '0'; + elsif cnt_vert_q = 221 then + vsync_n_o <= '1'; + end if; + + if cnt_vert_q = 215 then + vblank_q <= true; + elsif cnt_vert_q = first_line_s + 13 then + vblank_q <= false; + end if; + end if; + end if; + end if; + end process counters; + -- + ----------------------------------------------------------------------------- + + + -- comparator for vertical line increment + vert_inc_s <= clk_en_5m37_i and cnt_hor_q = hv_vertical_inc_c; + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + num_pix_o <= cnt_hor_q; + num_line_o <= cnt_vert_q; + vert_inc_o <= vert_inc_s; + blank_o <= hblank_q or vblank_q; + + -- Generate horizontal and vertical counters for VGA/HDMI (in top) + process (reset_i, clock_i) + begin + if reset_i then + cnt_hor_s <= (others => '0'); + cnt_ver_s <= (others => '0'); + elsif rising_edge(clock_i) then + if clk_en_5m37_i then + if cnt_hor_q = -12 then + cnt_hor_s <= (others => '0'); + else + cnt_hor_s <= cnt_hor_s + 1; + end if; + if vert_inc_s then + if cnt_vert_q = -12 then + cnt_ver_s <= (others => '0'); + else + cnt_ver_s <= cnt_ver_s + 1; + end if; + end if; + end if; + end if; + end process; + + cnt_hor_o <= std_logic_vector(cnt_hor_s); + cnt_ver_o <= std_logic_vector(cnt_ver_s); + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_pack-p.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_pack-p.vhd new file mode 100644 index 00000000..74448868 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_pack-p.vhd @@ -0,0 +1,281 @@ +------------------------------------------------------------------------------- +-- +-- $Id: vdp18_pack-p.vhd,v 1.14 2006/02/22 23:07:05 arnim Exp $ +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package vdp18_pack is + + ----------------------------------------------------------------------------- + -- Subtype for horizontal/vertical counters/positions. + -- + subtype hv_t is signed(0 to 8); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Constants for first and last vertical line of NTSC and PAL mode. + -- + constant hv_first_line_ntsc_c : hv_t := to_signed(-40, hv_t'length); -- 262 + constant hv_last_line_ntsc_c : hv_t := to_signed(221, hv_t'length); + -- + constant hv_first_line_pal_c : hv_t := to_signed(-65, hv_t'length); -- 312 + constant hv_last_line_pal_c : hv_t := to_signed(247, hv_t'length); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Constants for first and last horizontal pixel in text and graphics. + -- + constant hv_first_pix_text_c : hv_t := to_signed(-102, hv_t'length); -- 342 + constant hv_last_pix_text_c : hv_t := to_signed(239, hv_t'length); + -- + constant hv_first_pix_graph_c : hv_t := to_signed(-86, hv_t'length); -- 342 + constant hv_last_pix_graph_c : hv_t := to_signed(255, hv_t'length); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Miscellaneous constants for horizontal phases. + -- + constant hv_vertical_inc_c : hv_t := to_signed(-32, hv_t'length); + constant hv_sprite_start_c : hv_t := to_signed(247, hv_t'length); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Operating modes of the VDP18 core. + -- + type opmode_t is (OPMODE_GRAPH1, OPMODE_GRAPH2, + OPMODE_MULTIC, OPMODE_TEXTM); + -- + constant opmode_graph1_c : std_logic_vector(0 to 2) := "000"; + constant opmode_graph2_c : std_logic_vector(0 to 2) := "001"; + constant opmode_multic_c : std_logic_vector(0 to 2) := "010"; + constant opmode_textm_c : std_logic_vector(0 to 2) := "100"; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Access types. + -- + type access_t is (-- pattern access + -- read Pattern Name Table + AC_PNT, + -- read Pattern Generator Table + AC_PGT, + -- read Pattern Color Table + AC_PCT, + -- sprite access + -- sprite test read (y coordinate) + AC_STST, + -- read Sprite Attribute Table/Y + AC_SATY, + -- read Sprite Attribute Table/X + AC_SATX, + -- read Sprite Attribute Table/N + AC_SATN, + -- read Sprite Attribute Table/C + AC_SATC, + -- read Sprite Pattern Table/high quadrant + AC_SPTH, + -- read Sprite Pattern Table/low quadrant + AC_SPTL, + -- + -- CPU access + AC_CPU, + -- + -- no access at all + AC_NONE + ); + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Function enum_to_vec_f + -- + -- Purpose: + -- Translate access_t enumeration type to std_logic_vector. + -- + function enum_to_vec_f(enum : in access_t) return + std_logic_vector; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Function to_boolean_f + -- + -- Purpose: + -- Converts a std_logic value to boolean. + -- + function to_boolean_f(val : in std_logic) return boolean; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Function to_std_logic_f + -- + -- Purpose: + -- Converts a boolean value to std_logic. + -- + function to_std_logic_f(val : in boolean) return std_logic; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Function mod_6_f + -- + -- Purpose: + -- Calculate the modulo of 6. + -- Only the positive part is considered. + -- + function mod_6_f(val : in hv_t) return hv_t; + -- + ----------------------------------------------------------------------------- + +end vdp18_pack; + + +package body vdp18_pack is + + ----------------------------------------------------------------------------- + -- Function enum_to_vec_f + -- + -- Purpose: + -- Translate access_t enumeration type to std_logic_vector. + -- + function enum_to_vec_f(enum : in access_t) return + std_logic_vector is + variable result_v : std_logic_vector(3 downto 0); + begin + case enum is + when AC_NONE => + result_v := "0000"; + when AC_PNT => + result_v := "0001"; + when AC_PGT => + result_v := "0010"; + when AC_PCT => + result_v := "0011"; + when AC_STST => + result_v := "0100"; + when AC_SATY => + result_v := "0101"; + when AC_SATX => + result_v := "0110"; + when AC_SATN => + result_v := "0111"; + when AC_SATC => + result_v := "1000"; + when AC_SPTL => + result_v := "1001"; + when AC_SPTH => + result_v := "1010"; + when AC_CPU => + result_v := "1111"; + when others => + result_v := "UUUU"; + end case; + + return result_v; + end; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Function to_boolean_f + -- + -- Purpose: + -- Converts a std_logic value to boolean. + -- + function to_boolean_f(val : in std_logic) return boolean is + variable result_v : boolean; + begin + case to_X01(val) is + when '1' => + result_v := true; + when '0' => + result_v := false; + when others => + result_v := false; + end case; + + return result_v; + end; + -- + ----------------------------------------------------------------------------- + + ----------------------------------------------------------------------------- + -- Function to_std_logic_f + -- + -- Purpose: + -- Converts a boolean value to std_logic. + -- + function to_std_logic_f(val : in boolean) return std_logic is + variable result_v : std_logic; + begin + case val is + when true => + result_v := '1'; + when false => + result_v := '0'; + end case; + + return result_v; + end; + -- + ----------------------------------------------------------------------------- + + ----------------------------------------------------------------------------- + -- Function mod_6_f + -- + -- Purpose: + -- Calculate the modulo of 6. + -- Only the positive part is considered. + -- + function mod_6_f(val : in hv_t) return hv_t is + variable mod_v : natural; + variable result_v : hv_t; + begin + if val(0) = '0' then + result_v := (others => '0'); + mod_v := 0; + for idx in 0 to 255 loop + if val = idx then + result_v := to_signed(mod_v, hv_t'length); + end if; + + if mod_v < 5 then + mod_v := mod_v + 1; + else + mod_v := 0; + end if; + end loop; + else + result_v := (others => '-'); + end if; + + return result_v; + end; + -- + ----------------------------------------------------------------------------- + +end vdp18_pack; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_pattern.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_pattern.vhd new file mode 100644 index 00000000..08b22092 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_pattern.vhd @@ -0,0 +1,233 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_pattern.vhd,v 1.8 2006/06/18 10:47:06 arnim Exp $ +-- +-- Pattern Generation Controller +-- +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vdp18_pack.opmode_t; +use work.vdp18_pack.access_t; +use work.vdp18_pack.hv_t; + +entity vdp18_pattern is + + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + opmode_i : in opmode_t; + access_type_i : in access_t; + num_line_i : in hv_t; + vram_d_i : in std_logic_vector(0 to 7); + vert_inc_i : in boolean; + vsync_n_i : in std_logic; + reg_col1_i : in std_logic_vector(0 to 3); + reg_col0_i : in std_logic_vector(0 to 3); + pat_table_o : out std_logic_vector(0 to 9); + pat_name_o : out std_logic_vector(0 to 7); + pat_col_o : out std_logic_vector(0 to 3) + ); + +end vdp18_pattern; + + +library ieee; +use ieee.numeric_std.all; + +use work.vdp18_pack.all; + +architecture rtl of vdp18_pattern is + + signal pat_cnt_q : unsigned(0 to 9); + signal pat_name_q, + pat_tmp_q, + pat_shift_q, + pat_col_q : std_logic_vector(0 to 7); + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements: + -- * pattern shift register + -- * pattern color register + -- * pattern counter + -- + seq: process (clock_i, reset_i) + begin + if reset_i then + pat_cnt_q <= (others => '0'); + pat_name_q <= (others => '0'); + pat_tmp_q <= (others => '0'); + pat_shift_q <= (others => '0'); + pat_col_q <= (others => '0'); + + elsif clock_i'event and clock_i = '1' then + if clk_en_5m37_i then + -- shift pattern with every pixel clock + pat_shift_q(0 to 6) <= pat_shift_q(1 to 7); + end if; + + if clk_en_acc_i then + -- determine register update based on current access type ------------- + case access_type_i is + when AC_PNT => + -- store pattern name + pat_name_q <= vram_d_i; + -- increment pattern counter + pat_cnt_q <= pat_cnt_q + 1; + + when AC_PCT => + -- store pattern color in temporary register + pat_tmp_q <= vram_d_i; + + when AC_PGT => + if opmode_i = OPMODE_MULTIC then + -- set shift register to constant value + -- this value generates 4 bits of color1 + -- followed by 4 bits of color0 + pat_shift_q <= "11110000"; + -- set pattern color from pattern generator memory + pat_col_q <= vram_d_i; + else + -- all other modes: + -- store pattern line in shift register + pat_shift_q <= vram_d_i; + -- move pattern color from temporary register to color register + pat_col_q <= pat_tmp_q; + end if; + + when others => + null; + + end case; + + end if; + + if vert_inc_i then + -- redo patterns of if there are more lines inside this pattern + if num_line_i(0) = '0' then + case opmode_i is + when OPMODE_TEXTM => + if num_line_i(6 to 8) /= "111" then + pat_cnt_q <= pat_cnt_q - 40; + end if; + + when OPMODE_GRAPH1 | + OPMODE_GRAPH2 | + OPMODE_MULTIC => + if num_line_i(6 to 8) /= "111" then + pat_cnt_q <= pat_cnt_q - 32; + end if; + end case; + end if; + end if; + + if vsync_n_i = '0' then + -- reset pattern counter at end of active display area + pat_cnt_q <= (others => '0'); + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process col_gen + -- + -- Purpose: + -- Generates the color of the current pattern pixel. + -- + col_gen: process (opmode_i, + pat_shift_q, + pat_col_q, + reg_col1_i, + reg_col0_i) + variable pix_v : std_logic; + begin + -- default assignment + pat_col_o <= "0000"; + pix_v := pat_shift_q(0); + + case opmode_i is + -- Text Mode ------------------------------------------------------------ + when OPMODE_TEXTM => + if pix_v = '1' then + pat_col_o <= reg_col1_i; + else + pat_col_o <= reg_col0_i; + end if; + + -- Graphics I, II and Multicolor Mode ----------------------------------- + when OPMODE_GRAPH1 | + OPMODE_GRAPH2 | + OPMODE_MULTIC => + if pix_v = '1' then + pat_col_o <= pat_col_q(0 to 3); + else + pat_col_o <= pat_col_q(4 to 7); + end if; + + when others => + null; + + end case; + end process col_gen; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output Mapping + ----------------------------------------------------------------------------- + pat_table_o <= std_logic_vector(pat_cnt_q); + pat_name_o <= pat_name_q; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/vdp18/vdp18_sprite.vhd b/Coleco - Vision_MiST/rtl/vdp18/vdp18_sprite.vhd new file mode 100644 index 00000000..d198f310 --- /dev/null +++ b/Coleco - Vision_MiST/rtl/vdp18/vdp18_sprite.vhd @@ -0,0 +1,441 @@ +------------------------------------------------------------------------------- +-- +-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A. +-- +-- $Id: vdp18_sprite.vhd,v 1.11 2006/06/18 10:47:06 arnim Exp $ +-- +-- Sprite Generation Controller +-- +-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vdp18_pack.hv_t; +use work.vdp18_pack.access_t; + +entity vdp18_sprite is + + port ( + clock_i : in std_logic; + clk_en_5m37_i : in boolean; + clk_en_acc_i : in boolean; + reset_i : in boolean; + access_type_i : in access_t; + num_pix_i : in hv_t; + num_line_i : in hv_t; + vram_d_i : in std_logic_vector(0 to 7); + vert_inc_i : in boolean; + reg_size1_i : in boolean; + reg_mag1_i : in boolean; + spr_5th_o : out boolean; + spr_5th_num_o : out std_logic_vector(0 to 4); + stop_sprite_o : out boolean; + spr_coll_o : out boolean; + spr_num_o : out std_logic_vector(0 to 4); + spr_line_o : out std_logic_vector(0 to 3); + spr_name_o : out std_logic_vector(0 to 7); + spr0_col_o : out std_logic_vector(0 to 3); + spr1_col_o : out std_logic_vector(0 to 3); + spr2_col_o : out std_logic_vector(0 to 3); + spr3_col_o : out std_logic_vector(0 to 3) + ); + +end vdp18_sprite; + + +library ieee; +use ieee.numeric_std.all; + +use work.vdp18_pack.all; + +architecture rtl of vdp18_sprite is + + subtype sprite_number_t is unsigned(0 to 4); + type sprite_numbers_t is array (natural range 0 to 3) of sprite_number_t; + signal sprite_numbers_q : sprite_numbers_t; + + signal sprite_num_q : unsigned(0 to 4); + signal sprite_idx_q : unsigned(0 to 2); + signal sprite_name_q : std_logic_vector(0 to 7); + + subtype sprite_x_pos_t is unsigned(0 to 7); + type sprite_xpos_t is array (natural range 0 to 3) of sprite_x_pos_t; + signal sprite_xpos_q : sprite_xpos_t; + type sprite_ec_t is array (natural range 0 to 3) of std_logic; + signal sprite_ec_q : sprite_ec_t; + type sprite_xtog_t is array (natural range 0 to 3) of std_logic; + signal sprite_xtog_q : sprite_xtog_t; + + subtype sprite_col_t is std_logic_vector(0 to 3); + type sprite_cols_t is array (natural range 0 to 3) of sprite_col_t; + signal sprite_cols_q : sprite_cols_t; + + subtype sprite_pat_t is std_logic_vector(0 to 15); + type sprite_pats_t is array (natural range 0 to 3) of sprite_pat_t; + signal sprite_pats_q : sprite_pats_t; + + signal sprite_line_s, + sprite_line_q : std_logic_vector(0 to 3); + signal sprite_visible_s : boolean; + +begin + + ----------------------------------------------------------------------------- + -- Process seq + -- + -- Purpose: + -- Implements the sequential elements. + -- + seq: process (clock_i, reset_i) + variable sprite_idx_inc_v, + sprite_idx_dec_v : unsigned(sprite_idx_q'range); + variable sprite_idx_v : natural range 0 to 3; + begin + if reset_i then + sprite_numbers_q <= (others => (others => '0')); + sprite_num_q <= (others => '0'); + sprite_idx_q <= (others => '0'); + sprite_line_q <= (others => '0'); + sprite_name_q <= (others => '0'); + sprite_cols_q <= (others => (others => '0')); + sprite_xpos_q <= (others => (others => '0')); + sprite_ec_q <= (others => '0'); + sprite_xtog_q <= (others => '0'); + sprite_pats_q <= (others => (others => '0')); + + elsif clock_i'event and clock_i = '1' then + -- sprite index will be incremented during sprite tests + sprite_idx_inc_v := sprite_idx_q + 1; + -- sprite index will be decremented at end of sprite pattern data + sprite_idx_dec_v := sprite_idx_q - 1; + -- just save typing + sprite_idx_v := to_integer(sprite_idx_q(1 to 2)); + + if clk_en_5m37_i then + -- pre-decrement index counter when sprite reading starts + if num_pix_i = hv_sprite_start_c and sprite_idx_q > 0 then + sprite_idx_q <= sprite_idx_dec_v; + end if; + + ----------------------------------------------------------------------- + -- X position counters + ----------------------------------------------------------------------- + for idx in 0 to 3 loop + if num_pix_i(0) = '0' or + (sprite_ec_q(idx) = '1' and num_pix_i(0 to 3) = "1111") then + if sprite_xpos_q(idx) /= 0 then + -- decrement counter until 0 + sprite_xpos_q(idx) <= sprite_xpos_q(idx) - 1; + else + -- toggle magnification flag + sprite_xtog_q(idx) <= not sprite_xtog_q(idx); + end if; + end if; + end loop; + + ----------------------------------------------------------------------- + -- Sprite pattern shift registers + ----------------------------------------------------------------------- + for idx in 0 to 3 loop + if sprite_xpos_q(idx) = 0 then -- x counter elapsed + -- decide when to shift pattern information + -- case 1: pixel number is >= 0 + -- => active display area + -- case 2: early clock bit is set and pixel number is between + -- -32 and 0 + -- shift if + -- magnification not enbled + -- or + -- magnification enabled and toggle marker true + if (num_pix_i(0) = '0' or + (sprite_ec_q(idx) = '1' and num_pix_i(0 to 3) = "1111")) and + (sprite_xtog_q(idx) = '1' or not reg_mag1_i) then + -- + -- shift pattern left and fill vacated position with + -- transparent information + sprite_pats_q(idx)(0 to 14) <= sprite_pats_q(idx)(1 to 15); + sprite_pats_q(idx)(15) <= '0'; + end if; + end if; + + -- clear pattern at end of visible display + -- this removes "left-overs" when a sprite overlaps the right border + if num_pix_i = "011111111" then + sprite_pats_q(idx) <= (others => '0'); + end if; + end loop; + end if; + + + if vert_inc_i then + -- reset sprite num counter and sprite index counter + sprite_num_q <= (others => '0'); + sprite_idx_q <= (others => '0'); + + elsif clk_en_acc_i then + case access_type_i is + when AC_STST => + -- increment sprite number counter + sprite_num_q <= sprite_num_q + 1; + + if sprite_visible_s then + if sprite_idx_q < 4 then + -- store sprite number + sprite_numbers_q(sprite_idx_v) <= sprite_num_q; + -- and increment index counter + sprite_idx_q <= sprite_idx_inc_v; + end if; + end if; + + when AC_SATY => + -- store sprite line + sprite_line_q <= sprite_line_s; + + when AC_SATX => + -- save x position + sprite_xpos_q(sprite_idx_v) <= unsigned(vram_d_i); + -- reset toggle flag for magnified sprites + sprite_xtog_q(sprite_idx_v) <= '0'; + + when AC_SATN => + -- save sprite name + sprite_name_q <= vram_d_i; + + when AC_SATC => + -- save sprite color + sprite_cols_q(sprite_idx_v) <= vram_d_i(4 to 7); + -- and save early clock bit + sprite_ec_q(sprite_idx_v) <= vram_d_i(0); + + when AC_SPTH => + -- save upper pattern data + sprite_pats_q(sprite_idx_v)(0 to 7) + <= vram_d_i; + -- set lower part to transparent + sprite_pats_q(sprite_idx_v)(8 to 15) + <= (others => '0'); + + if not reg_size1_i then + -- decrement index counter in 8-bit mode + sprite_idx_q <= sprite_idx_dec_v; + end if; + + when AC_SPTL => + -- save lower pattern data + sprite_pats_q(sprite_idx_v)(8 to 15) <= vram_d_i; + + -- always decrement index counter + sprite_idx_q <= sprite_idx_dec_v; + + when others => + null; + end case; + + end if; + + end if; + end process seq; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process calc_vert + -- + -- Purpose: + -- Calculates the displayed line of the sprite and determines whether it + -- is visible on the current line or not. + -- + calc_vert: process (clk_en_acc_i, access_type_i, + vram_d_i, + num_pix_i, num_line_i, + sprite_num_q, sprite_idx_q, + reg_size1_i, reg_mag1_i) + variable sprite_line_v : signed(0 to 8); + variable vram_d_v : signed(0 to 8); + begin + -- default assignments + sprite_visible_s <= false; + stop_sprite_o <= false; + + vram_d_v := resize(signed(vram_d_i), 9); + -- determine if y information from VRAM should be treated + -- as a signed or unsigned number + if vram_d_v < -31 then + -- treat as unsigned number + vram_d_v(0) := '0'; + end if; + + sprite_line_v := num_line_i - vram_d_v; + if reg_mag1_i then + -- unmagnify line number + sprite_line_v := shift_right(sprite_line_v, 1); + end if; + + -- check result bounds + if sprite_line_v >= 0 then + if reg_size1_i then + -- double sized sprite: 16 data lines + if sprite_line_v < 16 then + sprite_visible_s <= true; + end if; + else + -- standard sized sprite: 8 data lines + if sprite_line_v < 8 then + sprite_visible_s <= true; + end if; + end if; + end if; + + -- finally: line number of current sprite + sprite_line_s <= std_logic_vector(sprite_line_v(5 to 8)); + + if clk_en_acc_i then + -- determine when to stop sprite scanning + if access_type_i = AC_STST then + if vram_d_v = 208 then + -- stop upon Y position 208 + stop_sprite_o <= true; + end if; + + if sprite_idx_q = 4 then + -- stop when all sprite positions have been vacated + stop_sprite_o <= true; + end if; + + if sprite_num_q = 31 then + -- stop when all sprites have been read + stop_sprite_o <= true; + end if; + end if; + + -- stop sprite reading when last active sprite has been processed + if sprite_idx_q = 0 and + ( access_type_i = AC_SPTL or + (access_type_i = AC_SPTH and not reg_size1_i)) then + stop_sprite_o <= true; + end if; + end if; + + -- stop sprite reading when no sprite is active on current line + if num_pix_i = hv_sprite_start_c and sprite_idx_q = 0 then + stop_sprite_o <= true; + end if; + end process calc_vert; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process fifth + -- + -- Purpose: + -- Detects the fifth sprite. + -- + fifth: process (clk_en_acc_i, access_type_i, + sprite_visible_s, + sprite_idx_q, + sprite_num_q) + begin + -- default assignments + spr_5th_o <= false; + spr_5th_num_o <= (others => '0'); + + if clk_en_acc_i and access_type_i = AC_STST then + if sprite_visible_s and sprite_idx_q = 4 then + spr_5th_o <= true; + spr_5th_num_o <= std_logic_vector(sprite_num_q); + end if; + end if; + end process fifth; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process col_mux + -- + -- Purpose: + -- Implements the color multiplexers. + -- + col_mux: process (sprite_cols_q, + sprite_pats_q, + sprite_xpos_q) + variable num_spr_pix_v : unsigned(0 to 2); + begin + -- default assignments + -- sprite colors are set to transparent + spr0_col_o <= (others => '0'); + spr1_col_o <= (others => '0'); + spr2_col_o <= (others => '0'); + spr3_col_o <= (others => '0'); + num_spr_pix_v := (others => '0'); + + if sprite_xpos_q(0) = 0 and sprite_pats_q(0)(0) = '1' then + spr0_col_o <= sprite_cols_q(0); + num_spr_pix_v := num_spr_pix_v + 1; + end if; + if sprite_xpos_q(1) = 0 and sprite_pats_q(1)(0) = '1' then + spr1_col_o <= sprite_cols_q(1); + num_spr_pix_v := num_spr_pix_v + 1; + end if; + if sprite_xpos_q(2) = 0 and sprite_pats_q(2)(0) = '1' then + spr2_col_o <= sprite_cols_q(2); + num_spr_pix_v := num_spr_pix_v + 1; + end if; + if sprite_xpos_q(3) = 0 and sprite_pats_q(3)(0) = '1' then + spr3_col_o <= sprite_cols_q(3); + num_spr_pix_v := num_spr_pix_v + 1; + end if; + + spr_coll_o <= num_spr_pix_v > 1; + end process col_mux; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Output mapping + ----------------------------------------------------------------------------- + spr_num_o <= std_logic_vector(sprite_num_q) + when access_type_i = AC_STST else + std_logic_vector(sprite_numbers_q(to_integer(sprite_idx_q(1 to 2)))); + spr_line_o <= sprite_line_q; + spr_name_o <= sprite_name_q; + +end rtl; diff --git a/Coleco - Vision_MiST/rtl/video_mixer.sv b/Coleco - Vision_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Coleco - Vision_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule