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 00000000..63b9885e Binary files /dev/null and b/Coleco - Vision_MiST/Snapshot/ColecoVision_MiST.rbf differ 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 00000000..6a967b55 Binary files /dev/null and b/Coleco - Vision_MiST/rtl/roms/COLECO-SHORT-DELAY.BIO differ diff --git a/Coleco - Vision_MiST/rtl/roms/COLECO.BIO b/Coleco - Vision_MiST/rtl/roms/COLECO.BIO new file mode 100644 index 00000000..ba4b278e Binary files /dev/null and b/Coleco - Vision_MiST/rtl/roms/COLECO.BIO differ 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 00000000..3872bc27 Binary files /dev/null and b/Coleco - Vision_MiST/rtl/roms/ONYX.BIO differ diff --git a/Coleco - Vision_MiST/rtl/roms/coleco29.asm b/Coleco - Vision_MiST/rtl/roms/coleco29.asm new file mode 100644 index 00000000..6e1f725d --- /dev/null +++ b/Coleco - Vision_MiST/rtl/roms/coleco29.asm @@ -0,0 +1,4939 @@ +;*************************************** +; +; Note: Markers like [1] indicate bytes that can be +; saved by obvious (or nearly so) optimizations, +; and [0] indicates that cycles can be saved. +; +; Some of the optimizations can't be made because +; they will change locked address, and some are +; so non-obvious that I can't figure out what I +; was thinking when I marked them! +; +;*************************************** + +; LOCKED ADDRESSES -- THESE *MUST* BE CORRECT OR SOME CARTRIDGES WILL NOT RUN! +; +; In order to allow easy verification, these addresses have labels +; starting with an 'A' and containing the locked address. +; +; These are the important addresses (like vectors), plus a few used by the +; small-time offenders. +; +; 0000 0066 080B 18A3 +; 0008 0069 08C0 18D4. +; 0010 006A 143B 18F7* +; 0018 006C 144D 1968 +; 0020 01B1* 1463 196B +; 0028 01D5 14B4 1CCA. +; 0030 023B. 14C1 1D43 +; 0038 02EE 14C3 1D47 +; 003B. 07E8* 15A3 1F61 +; 158B* +; +; ...and these are the addresses used by three of the four Interphase +; games, most of which have vectors available. +; +; 0213. 114A*. 1BAA* 1D3E*. +; 025E. 18E9. 1C27. 1D57. +; 027F. 1979*. 1C4F* 1D5A. +; 0300. 1B1D*. 1C82*. 1D60*. +; 1105* 1BA3. 1D01*. 1D66*. +; +; These two were called from Boulder Dash, but the call instructions +; themselves may be unreachable from the rest of the game. +; +; 01C1* 026A* +; +; Any address with a '*' is only referenced by ONE game that I can find. +; Note that Interphase games account for 11 out of 15 of these. Any address +; with a '.' has a vector available. Note also that all but two Interphase- +; only addresses (18 of 20) have vectors! Oh the humanity! +; +; These are in the "OS7SYM" file which was provided to Adam programmers: +; +;FREQ_SWEEP EQU 000FCH ! +;ATN_SWEEP EQU 0012FH ! +;DECLSN EQU 00190H ! +;DECMSN EQU 0019BH ! +;MSNTOLSN EQU 001A6H ! + + + +O EQU 0FFH ; filler for unused bytes + +;*************************************** +; RAM usage +;*************************************** + + ORG 7000H + + DS 12 ; default CtlState storage? + DS 20 +SndArray DS 2 ; music array pointer? +NoiseP DS 2 ; Pointer to program for noise generator +Tone1P DS 2 ; Pointer to program for tone1 generator +Tone2P DS 2 ; Pointer to program for tone2 generator +Tone3P DS 2 ; Pointer to program for tone3 generator +NoiseCtlShad DS 1 ; Noise control register shadow + + ORG 73B9H + +Stack DS 1 ; Default initial stack pointer +ParmArea DS 9 ; Parameter storage for PCOPY parameters +VDP0Shad DS 1 ; VDP register 0 shadow +VDP1Shad DS 1 ; VDP register 1 shadow + DS 1 ; unused? +D73C6 DS 1 ; flag byte? +WrtRAMSprt DS 1 ; BlkWrtVRAM to RAM sprite attr table if =1 +RandSeed DS 2 ; Random number seed +D73CA DS 1 ; unknown +D73CB DS 1 ; unknown +D73CC DS 1 ; unknown +D73CD DS 2 ; unknown +D73CF DS 2 ; unknown +D73D1 DS 2 ; unknown +TimerList DS 2 ; Pointer to timer list +TimerAux DS 2 ; Pointer to end of timer aux storage +RawCtlState DS 20 ; Raw controller state table (2 x 10 bytes) +PulseCnt1 DS 1 ; Pulse counter #1 +PulseCnt2 DS 1 ; Pulse counter #2 + DS 1 ; unused? +Joy1Shad DS 1 ; shadow for joystick #1 +Joy2Shad DS 1 ; shadow for joystick #2 +Key1Shad DS 1 ; shadow for keypad #1 +Key2Shad DS 1 ; shadow for keypad #2 +VDPBaseShad EQU $ ; shadow for VDP table base addresses +SprtTabShad DS 2 ; shadow for sprite table VRAM base addr +SprtPatTabShad DS 2 ; shadow for sprite pattern generator VRAM base addr +NameTabShad DS 2 ; shadow for name table VRAM base address +PatGenTabShad DS 2 ; shadow for pattern generator VRAM base addr +ClrTabShad DS 2 ; shadow for color table VRAM base address + DS 2 ; unused? +D73FE DS 2 ; temp3 + +;*************************************** +; Cartridge header addresses +;*************************************** + + ORG 8000H + +Cart_Sig DS 2 ; AA55 = title screen, 55AA = no screen +RamSprtTab DS 2 ; RAM sprite attribute table pointer +RAMSprtIdx DS 2 ; sprite index table pointer +VDP_Temp DS 2 ; pointer to temp image storage (up to 40 bytes used) +CtlState DS 2 ; pointer to controller state table (2 + 2x5 bytes) +Cart_Start DS 2 ; start of cart code +V_RST_08H DS 3 ; RST 08H vector +V_RST_10H DS 3 ; RST 10H vector +V_RST_18H DS 3 ; RST 18H vector +V_RST_20H DS 3 ; RST 20H vector +V_RST_28H DS 3 ; RST 28H vector +V_RST_30H DS 3 ; RST 30H vector +V_RST_38H DS 3 ; RST 38H vector +V_NMI DS 3 ; NMI vector (vertical blank interrupt) +Cart_Title DS 0 ; Title string "LINE 3/LINE 2/yyyy" + +;*************************************** +; Offsets into data blocks +;*************************************** + +; Offsets into RawCtlState + +RawCtlLeft EQU 00H ; raw left controller state +RawCtlRight EQU 0AH ; raw right controller state + +; Offsets into RawCtlLeft and RawCtlRight + +RawCtlLFBit EQU 00H ; previous left fire bit +RawCtlLFState EQU 01H ; left fire button state +RawCtlDBits EQU 02H ; previous directional bits +RawCtlDState EQU 03H ; directionals state +; EQU 04H ; unused? +; EQU 05H ; unused? +RawCtlRFBit EQU 06H ; previous right fire bit +RawCtlRFState EQU 07H ; right fire button state +RawCtlKPBit EQU 08H ; previous keypad bits +RawCtlKPState EQU 09H ; keypad state + +; Offsets into CtlState table + +CtlStateLFlag EQU 00H ; left controller flags +CtlStateRFlag EQU 01H ; right controller flags +CtlStateLeft EQU 02H ; left controller state +CtlStateRight EQU 07H ; right controller state + +; CtlStateLF/CtlStateRF bits + +CtlCheckMe EQU 80H ; 7 ; if =0, do not check this ctrl at all +; EQU 40H ; 6 ; unused? +; EQU 20H ; 5 ; unused? +CtlCheckKP EQU 10H ; 4 ; check keypad +CtlCheckRFire EQU 08H ; 3 ; check right fire button +CtlCheckSpinner EQU 04H ; 2 ; check spinner +CtlCheckDir EQU 02H ; 1 ; check directionals +CtlCheckLFire EQU 01H ; 0 ; check left fire button + +; Offsets into CtlStateLeft and CtlStateRight + +CtlStateLFire EQU 00H ; left fire button +CtlStateDir EQU 01H ; directionals +CtlStateSpin EQU 02H ; spinner value +CtlStateRFire EQU 03H ; right fire button +CtlStateKey EQU 04H ; key code + +;*************************************** +; I/O port addresses +;*************************************** + +IO_KP_Select EQU 080H ; Keypad select output port +IO_Joy_Select EQU 0C0H ; Joystick select output port +IO_Joy1 EQU 0FCH ; Joystick 1 input port +IO_Joy2 EQU 0FFH ; Joystick 2 input port +IO_Sound EQU 0FFH ; Sound chip output port +IO_VDP_Data EQU 0BEH ; VDP data port +IO_VDP_Addr EQU 0BFH ; VDP VRAM address output port +IO_VDP_Status EQU 0BFH ; VDP status input port + + + ORG 0000H + +;*************************************** +; Everything starts here +;*************************************** +A0000 LD SP,Stack ; Initialize stack pointer + JR L006E ; Go to rest of cold-start code + +;*************************************** +; These are the RST vectors, mixed with some (formerly) wasted bytes +;*************************************** +P_AddSound +P_StopTimer +P_TestTimer +P_InitRAMSprt +P_CopyRAMSprt DB 1 + DW 1 + +A0008 JP V_RST_08H + +P_InitSound +P_StartTimer +P_BaseLoad DB 2 + DW 1,2 + +A0010 JP V_RST_10H + +D0482 DB 2 + DW -2,1 + +A0018 JP V_RST_18H + +D064F DB 2 + DW 1,-2 + +A0020 JP V_RST_20H + +D06C1 DB 2 + DW 2,1 + +A0028 JP V_RST_28H + +P_InitTimers DB 2 + DW 2,2 + +A0030 JP V_RST_30H + +P_WriteReg DB 2 + DW 1,1 + +A0038 JP V_RST_38H + +;*************************************** +; 1FFD Random +; +; Returns a random number in A. This routine apparently +; uses a pseudo-random shift register algorithm based on +; the XOR of bits 8 and 15. +;*************************************** +A003B +_Random LD HL,(RandSeed) + BIT 7,H ; Set the carry flag to + JR Z,L0048 ; bit 8 XOR bit 15 + BIT 0,H + JR Z,L004C +L004F OR A ; Clear carry flag +L0050 RL L ; Rotate the carry into HL + RL H + LD (RandSeed),HL ; Update the random number seed + LD A,L ; Return the LSB + RET + +L0048 BIT 0,H + JR Z,L004F +D1AC4 ; DB '7' +L004C SCF ; Set carry flag + JR L0050 + +; DE = DE + IX + +L0478 PUSH IX + EX (SP),HL +L047C ADD HL,DE + EX DE,HL + POP HL + RET + +P_WrtVRAM +P_ReadVRAM DB 3 + DW -2,2,2 + + DB O + +;*************************************** +; NMI vector +;*************************************** +A0066 JP V_NMI + +;*************************************** +; I'm not really sure what these are for, but aside from the +; jump vectors at the end of the ROM, they are probably the +; only ROM addresses that you should reference directly. +;*************************************** +A0069 DB 60 ; this might mean a 60hz display (NTSC) +A006A DW D16AB ; this points to the font bitmap for 'A' +A006C DW D1623 ; this points to the font bitmap for '0' + +;*************************************** +; +; First part of cold start code +; +;*************************************** +L006E LD HL,(Cart_Sig) ; Check first word of cart for 55AAH + LD A,L ; 8000=55H and 8001=AAH + CP 55H + JR NZ,L0081 + LD A,H + CP 0AAH + JR NZ,L0081 + LD HL,(Cart_Start) ; If 55H/AAH, jump into cartridge + JP (HL) + +L0081 CALL NoSound ; Turn off sound +D1AC0 EQU $+1 ; DB '3' + LD HL,0033H ; Initialize random seed + LD (RandSeed),HL + CALL InitCtlState ; Clear all controller state flags +; XOR A ; (A-reg is already = 00H) +D1ABF ; DB '2' + LD (D73C6),A ; Clear some unknown flags + LD (WrtRAMSprt),A ; Clear BlkWrtVRAM RAM sprite attr flag + JP L1319 ; Go display copyright screen + +;*************************************** +; PCopy +; +; This routine copies in-line paramters for the subroutines. +; +; The descriptor table entries are 2 bytes each. The first word +; of the descriptor list is the number of descriptors in the list. +; +; (Note: for optimization purposes, the number of descriptors is now a byte) +; +; If an entry is positive, it contains the number of bytes to copy +; to the storage area. +; +; The parameters are 2 bytes each and normally contain the +; address of the data to be copied into the storage area. +; +; If a descriptor table entry is negative, the next parameter +; is taken as a 2-byte literal and stored directly in the data area. +; +; If a parameter word is zero, the next parameter word contains the +; address of the real parameter word to use. This is done before +; checking for a negative descriptor table entry. +; +; ENTRY BC points to parameter descriptor table +; DE points to parameter storage area +; (SP+2) = return address of calling routine +; EXIT: DE points to first unused byte of storage area +;*************************************** +PCopy POP HL ; Swap caller's return address + EX (SP),HL ; (the parameter pointer) to + PUSH HL ; the top of the stack + LD A,(BC) ; HL = first descriptor table word + LD L,A + INC BC + LD H,00H + EX (SP),HL ; Swap parameter pointer + PUSH DE ; with storage pointer + +; Get next parameter word + +L00A3 LD E,(HL) ; DE = next parameter word + INC HL + LD D,(HL) + INC HL + PUSH HL ; Save parameter pointer + LD A,E ; Check if parameter = 0 + OR D + JR NZ,L00B7 ; Branch if = 0 + +; Handle zero parameter word + + POP HL ; Get back parameter pointer + LD E,(HL) ; DE = next parameter word + INC HL + LD D,(HL) + INC HL + PUSH HL ; Save parameter pointer + EX DE,HL ; DE = (DE) + LD E,(HL) + INC HL + LD D,(HL) + +; Check sign of descriptor word + +L00B7 INC BC ; Get MSB of descriptor + LD A,(BC) + RLCA + JR NC,L00DA ; Branch if positive + +; Handle negative descriptor word + + INC BC ; Point to next descriptor word + POP HL ; HL = parameter pointer + EX (SP),HL ; Swap with storage pointer + LD (HL),E ; Store DE in storage area + INC HL + LD (HL),D + INC HL +L00C4 POP DE ; DE = storage pointer + EX (SP),HL ; Swap it with parameter counter + DEC HL ; Decrement count + LD A,H ; Test for zero count + OR L + JR Z,L00D6 +L00D0 EX (SP),HL ; Swap counter back on stack + PUSH HL ; Put storage pointer back on stack + EX DE,HL ; HL = parameter pointer + JR L00A3 ; Go back for next parameter + +L00D6 POP HL ; Get storage pointer + EX DE,HL ; DE = storage pointer, HL = parm pointer + EX (SP),HL ; Put parm pointer back on stack + JP (HL) ; Return to caller + +; Handle positive descriptor word + +L00DA POP HL ; Swap parameter pointer + EX (SP),HL ; and storage pointer + PUSH HL + RRCA ; Restore value of MSB + LD H,A ; H = MSB + DEC BC ; L = LSB + LD A,(BC) + LD L,A + EX (SP),HL ; HL = storage pointer, TOS = count + INC BC ; Point to next descriptor + INC BC +L00E5 LD A,(DE) ; Copy next parameter byte + LD (HL),A + INC HL + INC DE + EX (SP),HL ; HL = count, TOS = storage pointer + DEC HL ; Decrement counter + LD A,H ; Loop until count is zero + OR L + JR Z,L00F8 ; Branch if count = 0 +L00F4 EX (SP),HL ; HL = storage pointer, TOS = count + JR L00E5 ; Go back to copy next byte + +L00F8 POP HL ; HL = storage pointer + JR L00C4 ; Go check for end of parameter list + +;*************************************** +; +; SOUND ROUTINES BEGIN HERE +; +;*************************************** + +; Process the duration and twang values? + +L00FC LD A,(IX+07H) + OR A + JR NZ,L010C + LD A,(IX+05H) + DEC A + RET Z + LD (IX+05H),A + RET + +L010C PUSH IX + POP HL + LD DE,0006H + ADD HL,DE + CALL L0190 + RET NZ + CALL L01A6 + DEC HL + LD A,(HL) + DEC A + RET Z + LD (HL),A + DEC HL + DEC HL + LD A,(IX+07H) + CALL A01B1 + INC HL + RES 2,(HL) + JR L015D + +; Process the decay? + +L012F LD A,(IX+08H) + OR A + RET Z + PUSH IX + POP HL + LD DE,0009H + ADD HL,DE + CALL L0190 + RET NZ + CALL L01A6 + DEC HL + CALL L0190 + JR Z,L0161 + LD A,(HL) + AND 0F0H + LD E,A + DEC HL + DEC HL + DEC HL + DEC HL + LD A,(HL) + AND 0F0H + ADD A,E + LD E,A + LD A,(HL) + AND 0FH + OR E + LD (HL),A +L015D OR 0FFH + RET + +D1AC3 ; DB '6' +L0161 LD (HL),00H + RET + +;*************************************** +; +; Put up the introduction screen +; +;*************************************** +L1352 POP HL ; End of list, clean up + + LD HL,Title_Msgs ; Put up "COLECOVISION" title screen + CALL ScrnMsgs + + LD HL,A143B ; Point to color table +; LD DE,0000H ; Table index + LD D,B ; (BC=0 from ScrnMsgs) + LD E,C + LD IY,0012H ; Byte count + CALL _BlkWrtVRAM4 ; Color table + LD BC,01C0H ; Unblank the screen + CALL _WriteReg + LD HL,Cart_Sig ; Check first 2 bytes of cartridge + LD A,(HL) ; If 8000<>AA 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