From ab51b822bb8e7bddd1e6e51c3ad0eaeda8877216 Mon Sep 17 00:00:00 2001 From: gehstock Date: Tue, 17 Jul 2018 14:41:52 +0200 Subject: [PATCH] Atari 7800 New Attempt --- Atari - 7800_TeST/Atari7800.qpf | 30 + Atari - 7800_TeST/Atari7800.qsf | 231 +++ Atari - 7800_TeST/Atari7800.qws | Bin 0 -> 2082 bytes Atari - 7800_TeST/Atari7800.srf | 2 + Atari - 7800_TeST/Snapshot/Atari7800.rbf | Bin 0 -> 342209 bytes Atari - 7800_TeST/clean.bat | 37 + Atari - 7800_TeST/rtl/ALU.sv | 110 ++ Atari - 7800_TeST/rtl/Atari7800.sv | 444 ++++++ Atari - 7800_TeST/rtl/BIOS_ROM.v | 169 +++ Atari - 7800_TeST/rtl/RIOT.sv | 174 +++ Atari - 7800_TeST/rtl/TIA.sv | 477 +++++++ Atari - 7800_TeST/rtl/atari7800.vh | 11 + Atari - 7800_TeST/rtl/audio.sv | 93 ++ Atari - 7800_TeST/rtl/audio_xformer.sv | 24 + Atari - 7800_TeST/rtl/build_id.tcl | 35 + Atari - 7800_TeST/rtl/build_id.v | 2 + Atari - 7800_TeST/rtl/cart_top.sv | 257 ++++ Atari - 7800_TeST/rtl/cpu.sv | 1250 +++++++++++++++++ Atari - 7800_TeST/rtl/cpu_wrapper.sv | 65 + Atari - 7800_TeST/rtl/defender_rom.v | 164 +++ Atari - 7800_TeST/rtl/dma_ctrl.sv | 403 ++++++ Atari - 7800_TeST/rtl/hq2x.sv | 454 ++++++ Atari - 7800_TeST/rtl/line_ram.sv | 261 ++++ Atari - 7800_TeST/rtl/maria.sv | 178 +++ Atari - 7800_TeST/rtl/memory_map.sv | 232 +++ Atari - 7800_TeST/rtl/mist_io.sv | 532 +++++++ Atari - 7800_TeST/rtl/osd.sv | 179 +++ Atari - 7800_TeST/rtl/pll.v | 376 +++++ Atari - 7800_TeST/rtl/ram2k.v | 177 +++ Atari - 7800_TeST/rtl/riot.vh | 26 + Atari - 7800_TeST/rtl/rom/7800ntsc.hex | 257 ++++ Atari - 7800_TeST/rtl/rom/7800ntsc.rom | Bin 0 -> 4096 bytes Atari - 7800_TeST/rtl/rom/7800pal.hex | 1025 ++++++++++++++ Atari - 7800_TeST/rtl/rom/7800pal.rom | Bin 0 -> 16384 bytes .../rtl/rom/Defender (1981) (Atari).a26 | Bin 0 -> 4096 bytes Atari - 7800_TeST/rtl/rom/Defender.hex | 257 ++++ Atari - 7800_TeST/rtl/rom/Joust.a78 | Bin 0 -> 32896 bytes Atari - 7800_TeST/rtl/scandoubler.sv | 195 +++ Atari - 7800_TeST/rtl/sigma_delta_dac.sv | 33 + Atari - 7800_TeST/rtl/tia.vh | 81 ++ Atari - 7800_TeST/rtl/timing_ctrl.sv | 361 +++++ Atari - 7800_TeST/rtl/uv_to_vga.sv | 218 +++ Atari - 7800_TeST/rtl/video_mixer.sv | 242 ++++ 43 files changed, 9062 insertions(+) create mode 100644 Atari - 7800_TeST/Atari7800.qpf create mode 100644 Atari - 7800_TeST/Atari7800.qsf create mode 100644 Atari - 7800_TeST/Atari7800.qws create mode 100644 Atari - 7800_TeST/Atari7800.srf create mode 100644 Atari - 7800_TeST/Snapshot/Atari7800.rbf create mode 100644 Atari - 7800_TeST/clean.bat create mode 100644 Atari - 7800_TeST/rtl/ALU.sv create mode 100644 Atari - 7800_TeST/rtl/Atari7800.sv create mode 100644 Atari - 7800_TeST/rtl/BIOS_ROM.v create mode 100644 Atari - 7800_TeST/rtl/RIOT.sv create mode 100644 Atari - 7800_TeST/rtl/TIA.sv create mode 100644 Atari - 7800_TeST/rtl/atari7800.vh create mode 100644 Atari - 7800_TeST/rtl/audio.sv create mode 100644 Atari - 7800_TeST/rtl/audio_xformer.sv create mode 100644 Atari - 7800_TeST/rtl/build_id.tcl create mode 100644 Atari - 7800_TeST/rtl/build_id.v create mode 100644 Atari - 7800_TeST/rtl/cart_top.sv create mode 100644 Atari - 7800_TeST/rtl/cpu.sv create mode 100644 Atari - 7800_TeST/rtl/cpu_wrapper.sv create mode 100644 Atari - 7800_TeST/rtl/defender_rom.v create mode 100644 Atari - 7800_TeST/rtl/dma_ctrl.sv create mode 100644 Atari - 7800_TeST/rtl/hq2x.sv create mode 100644 Atari - 7800_TeST/rtl/line_ram.sv create mode 100644 Atari - 7800_TeST/rtl/maria.sv create mode 100644 Atari - 7800_TeST/rtl/memory_map.sv create mode 100644 Atari - 7800_TeST/rtl/mist_io.sv create mode 100644 Atari - 7800_TeST/rtl/osd.sv create mode 100644 Atari - 7800_TeST/rtl/pll.v create mode 100644 Atari - 7800_TeST/rtl/ram2k.v create mode 100644 Atari - 7800_TeST/rtl/riot.vh create mode 100644 Atari - 7800_TeST/rtl/rom/7800ntsc.hex create mode 100644 Atari - 7800_TeST/rtl/rom/7800ntsc.rom create mode 100644 Atari - 7800_TeST/rtl/rom/7800pal.hex create mode 100644 Atari - 7800_TeST/rtl/rom/7800pal.rom create mode 100644 Atari - 7800_TeST/rtl/rom/Defender (1981) (Atari).a26 create mode 100644 Atari - 7800_TeST/rtl/rom/Defender.hex create mode 100644 Atari - 7800_TeST/rtl/rom/Joust.a78 create mode 100644 Atari - 7800_TeST/rtl/scandoubler.sv create mode 100644 Atari - 7800_TeST/rtl/sigma_delta_dac.sv create mode 100644 Atari - 7800_TeST/rtl/tia.vh create mode 100644 Atari - 7800_TeST/rtl/timing_ctrl.sv create mode 100644 Atari - 7800_TeST/rtl/uv_to_vga.sv create mode 100644 Atari - 7800_TeST/rtl/video_mixer.sv diff --git a/Atari - 7800_TeST/Atari7800.qpf b/Atari - 7800_TeST/Atari7800.qpf new file mode 100644 index 00000000..086d0dc1 --- /dev/null +++ b/Atari - 7800_TeST/Atari7800.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 23:59:05 March 16, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "23:59:05 March 16, 2017" + +# Revisions + +PROJECT_REVISION = "Atari7800" diff --git a/Atari - 7800_TeST/Atari7800.qsf b/Atari - 7800_TeST/Atari7800.qsf new file mode 100644 index 00000000..679890ef --- /dev/null +++ b/Atari - 7800_TeST/Atari7800.qsf @@ -0,0 +1,231 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Web Edition +# Date created = 14:33:15 July 17, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Atari7800_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 "23:59:05 MARCH 16, 2017" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY Output_Files +set_global_assignment -name VERILOG_INCLUDE_FILE rtl/atari7800.vh +set_global_assignment -name VERILOG_INCLUDE_FILE rtl/tia.vh +set_global_assignment -name VERILOG_INCLUDE_FILE rtl/riot.vh +set_global_assignment -name SYSTEMVERILOG_FILE rtl/cart_top.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Atari7800.sv +set_global_assignment -name VERILOG_FILE rtl/BIOS_ROM.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/uv_to_vga.sv +set_global_assignment -name VERILOG_FILE rtl/ram2k.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/maria.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/TIA.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/RIOT.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu_wrapper.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/line_ram.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/timing_ctrl.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory_map.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/dma_ctrl.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/audio.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/audio_xformer.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ALU.sv +set_global_assignment -name VERILOG_FILE rtl/pll.v +set_global_assignment -name VERILOG_FILE rtl/defender_rom.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sigma_delta_dac.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/osd.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/mist_io.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/scandoubler.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_7 -to LED +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_90 -to SPI_SS4 +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 PIN_31 -to UART_RX +set_location_assignment PIN_46 -to UART_TX + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP +set_global_assignment -name TOP_LEVEL_ENTITY cart_top + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name 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(cart_top) + + # 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(cart_top) +# -------------------- +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Atari - 7800_TeST/Atari7800.qws b/Atari - 7800_TeST/Atari7800.qws new file mode 100644 index 0000000000000000000000000000000000000000..f178369c99c36ac667d04882d4e8a6d7fcc8fd14 GIT binary patch literal 2082 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 z%0D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�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ÐGW9m&ZD_7CXmrdsSt@Q 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
  • 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 L#{c~88y5aIIOf78 literal 0 HcmV?d00001 diff --git a/Atari - 7800_TeST/clean.bat b/Atari - 7800_TeST/clean.bat new file mode 100644 index 00000000..b3b7c3b5 --- /dev/null +++ b/Atari - 7800_TeST/clean.bat @@ -0,0 +1,37 @@ +@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 /s new_rtl_netlist +del /s old_rtl_netlist + +pause diff --git a/Atari - 7800_TeST/rtl/ALU.sv b/Atari - 7800_TeST/rtl/ALU.sv new file mode 100644 index 00000000..0a5abe18 --- /dev/null +++ b/Atari - 7800_TeST/rtl/ALU.sv @@ -0,0 +1,110 @@ +/* + * ALU. + * + * AI and BI are 8 bit inputs. Result in OUT. + * CI is Carry In. + * CO is Carry Out. + * + * op[3:0] is defined as follows: + * + * 0011 AI + BI + * 0111 AI - BI + * 1011 AI + AI + * 1100 AI | BI + * 1101 AI & BI + * 1110 AI ^ BI + * 1111 AI + * + */ + `timescale 1ns / 1ps + + +module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY ); + input clk; + input right; + input [3:0] op; // operation + input [7:0] AI; + input [7:0] BI; + input CI; + input BCD; // BCD style carry + output [7:0] OUT; + output CO; + output V; + output Z; + output N; + output HC; + input RDY; + +reg [7:0] OUT; +reg CO; +wire V; +wire Z; +reg N; +reg HC; + +reg AI7; +reg BI7; +reg [8:0] temp_logic; +reg [7:0] temp_BI; +reg [4:0] temp_l; +reg [4:0] temp_h; +wire [8:0] temp = { temp_h, temp_l[3:0] }; +wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI; + +// calculate the logic operations. The 'case' can be done in 1 LUT per +// bit. The 'right' shift is a simple mux that can be implemented by +// F5MUX. +always @* begin + case( op[1:0] ) + 2'b00: temp_logic = AI | BI; + 2'b01: temp_logic = AI & BI; + 2'b10: temp_logic = AI ^ BI; + 2'b11: temp_logic = AI; + endcase + + if( right ) + temp_logic = { AI[0], CI, AI[7:1] }; +end + +// Add logic result to BI input. This only makes sense when logic = AI. +// This stage can be done in 1 LUT per bit, using carry chain logic. +always @* begin + case( op[3:2] ) + 2'b00: temp_BI = BI; // A+B + 2'b01: temp_BI = ~BI; // A-B + 2'b10: temp_BI = temp_logic; // A+A + 2'b11: temp_BI = 0; // A+0 + endcase +end + +// HC9 is the half carry bit when doing BCD add +wire HC9 = BCD & (temp_l[3:1] >= 3'd5); + +// CO9 is the carry-out bit when doing BCD add +wire CO9 = BCD & (temp_h[3:1] >= 3'd5); + +// combined half carry bit +wire temp_HC = temp_l[4] | HC9; + +// perform the addition as 2 separate nibble, so we get +// access to the half carry flag +always @* begin + temp_l = temp_logic[3:0] + temp_BI[3:0] + adder_CI; + temp_h = temp_logic[8:4] + temp_BI[7:4] + temp_HC; +end + +// calculate the flags +always @(posedge clk) + if( RDY ) begin + AI7 <= AI[7]; + BI7 <= temp_BI[7]; + OUT <= temp[7:0]; + CO <= temp[8] | CO9; + N <= temp[7]; + HC <= temp_HC; + end + +assign V = AI7 ^ BI7 ^ CO ^ N; +assign Z = ~|OUT; + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/Atari7800.sv b/Atari - 7800_TeST/rtl/Atari7800.sv new file mode 100644 index 00000000..a7e9036c --- /dev/null +++ b/Atari - 7800_TeST/rtl/Atari7800.sv @@ -0,0 +1,444 @@ +`timescale 1ns / 1ps +`include "atari7800.vh" + + + +module Atari7800( + input logic clock_25, + input logic sysclk_7_143, + input logic clock_divider_locked, + + input logic reset, + output logic [3:0] RED, GREEN, BLUE, + output logic HSync, VSync, + + output logic [15:0] aud_signal_out, + + input logic [7:0] cart_DB_out, + output logic [15:0] AB, + output logic RW, + output logic pclk_0, + + output logic [7:0] ld, + + // Tia inputs + input logic [3:0] idump, + input logic [1:0] ilatch, + + output logic tia_en, + + // Riot inputs + input logic [7:0] PAin, PBin, + output logic [7:0] PAout, PBout +); + + assign ld[0] = lock_ctrl; + + ////////////// + // Signals // + //////////// + + // Clock Signals + + logic pclk_2, tia_clk, sel_slow_clock; + + + // VGA Signals + logic [9:0] vga_row, vga_col; + logic tia_hsync, tia_vsync, vga_hsync, vga_vsync; + + (* keep = "true" *) logic tia_hsync_kept; + (* keep = "true" *) logic tia_vsync_kept; + (* keep = "true" *) logic vga_hsync_kept; + (* keep = "true" *) logic vga_vsync_kept; + + assign tia_hsync_kept = ~tia_hsync; + assign tia_vsync_kept = ~tia_vsync; + assign vga_hsync_kept = vga_hsync; + assign vga_vsync_kept = vga_vsync; + + // MARIA Signals + logic m_int_b, maria_RDY; + logic maria_rw; + logic halt_b, maria_drive_AB; + logic [7:0] uv_display, uv_maria, uv_tia; + logic [15:0] maria_AB_out; + + + + // TIA Signals + logic hblank_tia, vblank_tia, aud0, aud1, tia_RDY; + logic [3:0] audv0, audv1; + logic [7:0] tia_db_out; + + // RIOT Signals + logic riot_RS_b; + + // 6502 Signals + logic RDY, IRQ_n, CPU_NMI; + logic [7:0] core_DB_out; + logic [15:0] core_AB_out; + + logic cpu_reset, core_halt_b, core_latch_data; + logic [2:0] cpu_reset_counter; + + assign IRQ_n = 1'b1; + + //ctrl Signals + logic maria_en, lock_ctrl, bios_en_b; + logic [1:0] ctrl_writes; + + // Buses + // AB and RW defined in port declaration + logic [7:0] read_DB, write_DB; + + logic [7:0] tia_DB_out, riot_DB_out, maria_DB_out, + ram0_DB_out, ram1_DB_out, bios_DB_out; + + `chipselect CS_maria_buf, CS_core_buf, CS_buf, CS; + + logic memclk; + assign memclk = (~halt_b & maria_drive_AB) ? sysclk_7_143 : pclk_0; + + /*always_ff @(posedge sysclk_7_143, posedge reset) begin + if (reset) begin + CS_maria_buf <= `CS_NONE; + CS_core_buf <= `CS_NONE; + end else begin + CS_maria_buf <= CS; + CS_core_buf <= CS; + end + end + + assign CS_buf = maria_drive_AB ? CS_maria_buf : CS_core_buf;*/ + + always_ff @(posedge memclk, posedge reset) + if (reset) + CS_buf <= `CS_NONE; + else + CS_buf <= CS; + + + //CS LOGIC + logic ram0_cs, ram1_cs, bios_cs, tia_cs, riot_cs, riot_ram_cs; + + always_comb begin + ram0_cs = 1'b0; + ram1_cs = 1'b0; + bios_cs = 1'b0; + tia_cs = 1'b0; + riot_cs = 1'b0; + riot_ram_cs = 1'b0; + casex (CS) + `CS_RAM0: ram0_cs = 1'b1; + `CS_RAM1: ram1_cs = 1'b1; + `CS_BIOS: bios_cs = 1'b1; + `CS_TIA: tia_cs = 1'b1; + `CS_RIOT_IO: riot_cs = 1'b1; + `CS_RIOT_RAM: begin riot_cs = 1'b1; riot_ram_cs = 1'b1; end + endcase + end + + + always_comb begin + casex (CS_buf) + `CS_RAM0: read_DB = ram0_DB_out; + `CS_RAM1: read_DB = ram1_DB_out; + `CS_RIOT_IO, + `CS_RIOT_RAM: read_DB = riot_DB_out; + `CS_TIA: read_DB = tia_DB_out; + `CS_BIOS: read_DB = bios_DB_out; + `CS_MARIA: read_DB = maria_DB_out; + `CS_CART: read_DB = cart_DB_out; + // Otherwise, nothing is driving the data bus. THIS SHOULD NEVER HAPPEN + default: read_DB = 8'h46; + endcase + + write_DB = core_DB_out; + + AB = (maria_drive_AB) ? maria_AB_out : core_AB_out; + end + /* + (* ram_style = "distributed" *) + reg [7:0] ram0 [2047:0]; + (* ram_style = "distributed" *) + reg [7:0] ram1 [2047:0]; + integer cnt; + always_ff @(posedge memclk) begin + if (reset) begin + for (cnt = 0; cnt < 2048;cnt = cnt + 1) begin + ram0[cnt] <= 8'b0; + ram1[cnt] <= 8'b0; + end + end + else if(ram0_cs) + if (RW) + ram0_DB_out <= ram0[AB[10:0]]; + else + ram0[AB[10:0]] <= write_DB; + else if (ram1_cs) + if (RW) + ram1_DB_out <= ram1[AB[10:0]]; + else + ram1[AB[10:0]] <= write_DB; + end */ + + ram2k ram0_inst( + .clock(memclk), + //.ena(~ram0_cs_b), + .clken(ram0_cs), + .wren(~RW), + .address(AB[10:0]), + .data(write_DB), + .q(ram0_DB_out) + ); + + ram2k ram1_inst( + .clock(memclk), + //.ena(~ram1_cs_b), + .clken(ram1_cs), + .wren(~RW), + .address(AB[10:0]), + .data(write_DB), + .q(ram1_DB_out) + ); + + //assign bios_cs_b = ~(AB[15] & ~bios_en_b); + + + BIOS_ROM BIOS_ROM( + .clock(memclk), + .clken(bios_cs), + .address(AB[11:0]), + .q(bios_DB_out) + ); + + assign pclk_2 = ~pclk_0; +// console_pll console_pll ( +// .inclk0(CLOCK_PLL), +// .c0(clock_100), +// .c1(clock_25), // 25 MHz +// .c2(sysclk_7_143), // 7.143 MHz. Divide to 1.79 MHz +// .locked(clock_divider_locked) +// ); + + assign VSync = vga_vsync; + assign HSync = vga_hsync; + + // VGA + uv_to_vga vga_out( + .clk(clock_25), .reset(reset), + .uv_in(uv_display), + .row(vga_row), .col(vga_col), + .RED(RED), .GREEN(GREEN), .BLUE(BLUE), + .HSync(vga_hsync), .VSync(vga_vsync), + .tia_en(tia_en), + .tia_hblank(hblank_tia), + .tia_vblank(vblank_tia), + .tia_clk(tia_clk) + ); + + // VIDEO + always_comb case ({maria_en, tia_en}) + 2'b00: uv_display = uv_maria; + 2'b01: uv_display = uv_tia; + 2'b10: uv_display = uv_maria; + 2'b11: uv_display = uv_tia; + default: uv_display = uv_maria; + endcase + + // MARIA + maria maria_inst( + .AB_in(AB), + .AB_out(maria_AB_out), + .drive_AB(maria_drive_AB), + .read_DB_in(read_DB), + .write_DB_in(write_DB), + .DB_out(maria_DB_out), + .bios_en(~bios_en_b), + .reset(reset), + .sysclk(sysclk_7_143), + .pclk_2(pclk_2), + .sel_slow_clock(sel_slow_clock), + .core_latch_data(core_latch_data), + .tia_en(tia_en), + .tia_clk(tia_clk), + .pclk_0(pclk_0), + .CS(CS), + //.ram0_b(ram0_cs_b), + //.ram1_b(ram1_cs_b), + //.p6532_b(riot_cs_b), + //.tia_b(tia_cs_b), + //.riot_ram_b(riot_RS_b), + .RW(RW), + .enable(maria_en), + .vga_row(vga_row), + .vga_col(vga_col), + .UV_out(uv_maria), + .int_b(m_int_b), + .halt_b(halt_b), + .ready(maria_RDY) + ); + + // TIA + TIA tia_inst(.A({(AB[5] & tia_en), AB[4:0]}), // Address bus input + .Din(write_DB), // Data bus input + .Dout(tia_DB_out), // Data bus output + .CS_n({2'b0,~tia_cs}), // Active low chip select input + .CS(tia_cs), // Chip select input + .R_W_n(RW), // Active low read/write input + .RDY(tia_RDY), // CPU ready output + .MASTERCLK(tia_clk), // 3.58 Mhz pixel clock input + .CLK2(pclk_0), // 1.19 Mhz bus clock input + .idump_in(idump), // Dumped I/O + .Ilatch(ilatch), // Latched I/O + .HSYNC(tia_hsync), // Video horizontal sync output + .HBLANK(hblank_tia), // Video horizontal blank output + .VSYNC(tia_vsync), // Video vertical sync output + .VBLANK(vblank_tia), // Video vertical sync output + .COLOROUT(uv_tia), // Indexed color output + .RES_n(~reset), // Active low reset input + .AUD0(aud0), //audio pin 0 + .AUD1(aud1), //audio pin 1 + .audv0(audv0), //audio volume for use with external xformer module + .audv1(audv1) //audio volume for use with external xformer module + ); + + audio_xformer audio_xform(.AUD0(aud0), .AUD1(aud1), .AUDV0(audv0), + .AUDV1(audv1), .AUD_SIGNAL(aud_signal_out)); + + //RIOT + RIOT riot_inst(.A(AB[6:0]), // Address bus input + .Din(write_DB), // Data bus input + .Dout(riot_DB_out), // Data bus output + .CS(riot_cs), // Chip select input + .CS_n(~riot_cs), // Active low chip select input + .R_W_n(RW), // Active high read, active low write input + .RS_n(~riot_ram_cs), // Active low rom select input + .RES_n(~reset), // Active low reset input + .IRQ_n(), // Active low interrupt output + .CLK(pclk_0), // Clock input + .PAin(PAin), // 8 bit port A input + .PAout(PAout), // 8 bit port A output + .PBin(PBin), // 8 bit port B input + .PBout(PBout)); // 8 bit port B output + + //6502 + assign cpu_reset = cpu_reset_counter != 3'b111; + + always_ff @(posedge pclk_0, posedge reset) begin + if (reset) begin + cpu_reset_counter <= 3'b0; + end else begin + if (cpu_reset_counter != 3'b111) + cpu_reset_counter <= cpu_reset_counter + 3'b001; + end + end + + + assign RDY = maria_en ? maria_RDY : ((tia_en) ? tia_RDY : clock_divider_locked); + + assign core_halt_b = (ctrl_writes == 2'd2) ? halt_b : 1'b1; + + /// DEBUG /////////////////////////////////////////// + `ifndef SIM + + (* keep = "true" *) + logic [15:0] pc_temp; + + assign ld[1] = pc_reached_230a; + assign ld[2] = pc_reached_26bc; + //assign ld[3] = pc_reached_fbad; + assign ld[4] = pc_reached_fbbd; + assign ld[5] = pc_reached_faaf; + + + assign ld[6] = tia_en; + assign ld[7] = maria_en; + + logic pc_reached_230a; // Beginning of RAM code + logic pc_reached_26bc; // Exit BIOS + logic pc_reached_fbad; // waiting for VSYNC + logic pc_reached_fbbd; // done waiting for VSYNC + logic pc_reached_faaf; // NMI handler + + always_ff @(posedge sysclk_7_143, posedge reset) begin + if (reset) begin + pc_reached_230a <= 1'b0; + pc_reached_26bc <= 1'b0; + pc_reached_fbad <= 1'b0; + pc_reached_fbbd <= 1'b0; + pc_reached_faaf <= 1'b0; + end else begin + if (pc_temp == 16'h230a) + pc_reached_230a <= 1'b1; + if (pc_temp == 16'h23ee) + pc_reached_26bc <= 1'b1; + if (pc_temp == 16'hfbad) + pc_reached_fbad <= 1'b1; + if (pc_temp == 16'hfbbd) + pc_reached_fbbd <= 1'b1; + if (pc_temp == 16'hfaaf) + pc_reached_faaf <= 1'b1; + end + end + `endif + ////////////////////////////////////////////////////// + + assign CPU_NMI = (lock_ctrl) ? (~m_int_b) : (~m_int_b & ~bios_en_b); + + cpu_wrapper cpu_inst(.clk(pclk_0), + .core_latch_data(core_latch_data), + .sysclk(sysclk_7_143), + .reset(cpu_reset), + .AB(core_AB_out), + .DB_IN(read_DB), + .DB_OUT(core_DB_out), + .RD(RW), + .IRQ(~IRQ_n), + .NMI(CPU_NMI), + .RDY(RDY), + .halt_b(core_halt_b), + .pc_temp(pc_temp)); + + + + ctrl_reg ctrl(.clk(pclk_0), + .lock_in(write_DB[0]), + .maria_en_in(write_DB[1]), + .bios_en_in(write_DB[2]), + .tia_en_in(write_DB[3]), + .latch_b(RW | ~tia_cs | lock_ctrl), + .rst(reset), + .lock_out(lock_ctrl), + .maria_en_out(maria_en), + .bios_en_out(bios_en_b), + .tia_en_out(tia_en), + .writes(ctrl_writes)); + + +endmodule + +module ctrl_reg(input logic clk, lock_in, maria_en_in, bios_en_in, tia_en_in, latch_b, rst, + output logic lock_out, maria_en_out, bios_en_out, tia_en_out, + output logic [1:0] writes); + + + always_ff @(posedge clk, posedge rst) begin + if (rst) begin + lock_out <= 0; + maria_en_out <= 0; + bios_en_out <= 0; + tia_en_out <= 0; + writes <= 0; + end + else if (~latch_b) begin + lock_out <= lock_in; + maria_en_out <= maria_en_in; + bios_en_out <= bios_en_in; + tia_en_out <= tia_en_in; + if (writes < 2'd2) + writes <= writes + 1; + end + end +endmodule diff --git a/Atari - 7800_TeST/rtl/BIOS_ROM.v b/Atari - 7800_TeST/rtl/BIOS_ROM.v new file mode 100644 index 00000000..197fe978 --- /dev/null +++ b/Atari - 7800_TeST/rtl/BIOS_ROM.v @@ -0,0 +1,169 @@ +// megafunction wizard: %ROM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: BIOS_ROM.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module BIOS_ROM ( + address, + clken, + clock, + q); + + input [11:0] address; + input clken; + input clock; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clken; + 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), + .clocken0 (clken), + .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), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_a ({8{1'b1}}), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_a (1'b0), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.clock_enable_input_a = "NORMAL", + altsyncram_component.clock_enable_output_a = "NORMAL", +`ifdef NO_PLI + altsyncram_component.init_file = "../rtl/rom/7800ntsc.rif" +`else + altsyncram_component.init_file = "../rtl/rom/7800ntsc.hex" +`endif +, + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 4096, + altsyncram_component.operation_mode = "ROM", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.widthad_a = 12, + 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: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1" +// Retrieval info: PRIVATE: Clken NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "../rtl/rom/7800ntsc.hex" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +// 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 "12" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "NORMAL" +// Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/rom/7800ntsc.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 "4096" +// 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 "12" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]" +// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC "clken" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL BIOS_ROM_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Atari - 7800_TeST/rtl/RIOT.sv b/Atari - 7800_TeST/rtl/RIOT.sv new file mode 100644 index 00000000..917c7079 --- /dev/null +++ b/Atari - 7800_TeST/rtl/RIOT.sv @@ -0,0 +1,174 @@ +/* Atari on an FPGA +Masters of Engineering Project +Cornell University, 2007 +Daniel Beer + RIOT.v +Redesign of the MOS 6532 chip. Provides RAM, I/O and timers to the Atari. +*/ +`timescale 1ns / 1ps + +`include "riot.vh" +module RIOT(A, // Address bus input + Din, // Data bus input + Dout, // Data bus output + CS, // Chip select input + CS_n, // Active low chip select input + R_W_n, // Active low read/write input + RS_n, // Active low rom select input + RES_n, // Active low reset input + IRQ_n, // Active low interrupt output + CLK, // Clock input + PAin, // 8 bit port A input + PAout, // 8 bit port A output + PBin, // 8 bit port B input + PBout);// 8 bit port B output + input [6:0] A; + input [7:0] Din; + output [7:0] Dout; + input CS, CS_n, R_W_n, RS_n, RES_n, CLK; + output IRQ_n; + input [7:0] PAin, PBin; + output [7:0] PAout, PBout; // Output register + reg [7:0] Dout; // RAM allocation + reg [7:0] RAM[127:0]; // I/O registers + reg [7:0] DRA, DRB; // Data registers + reg [7:0] DDRA, DDRB; // Data direction registers + wire PA7; + reg R_PA7; + assign PA7 = (PAin[7] & ~DDRA[7]) | (DRA[7] & DDRA[7]); + assign PAout = DRA & DDRA; + assign PBout = DRB & DDRB; + // Timer registers + reg [8:0] Timer; + reg [9:0] Prescaler; + reg [1:0] Timer_Mode; + reg Timer_Int_Flag, PA7_Int_Flag, Timer_Int_Enable, PA7_Int_Enable, PA7_Int_Mode; // Timer prescaler constants + wire [9:0] PRESCALER_VALS[3:0]; + assign PRESCALER_VALS[0] = 10'd0; + assign PRESCALER_VALS[1] = 10'd7; + assign PRESCALER_VALS[2] = 10'd63; + assign PRESCALER_VALS[3] = 10'd1023; + // Interrupt + assign IRQ_n = ~(Timer_Int_Flag & Timer_Int_Enable | PA7_Int_Flag & PA7_Int_Enable); + // Operation decoding + wire [6:0] op; + reg [6:0] R_op; + assign op = {RS_n, R_W_n, A[4:0]}; + // Registered data in + reg [7:0] R_Din; + integer cnt; + // Software operations + always @(posedge CLK) + begin + // Reset operation + if (~RES_n) begin + DRA <= 8'b0; + DDRA <= 8'b0; + DRB <= 8'b00010100; + DDRB <= 8'b00010100; + Timer_Int_Flag <= 1'b0; + PA7_Int_Flag <= 1'b0; + PA7_Int_Enable <= 1'b0; + PA7_Int_Mode <= 1'b0; + // Fill RAM with 0s + for (cnt = 0; cnt < 128; cnt = cnt + 1) + RAM[cnt] <= 8'b0; + R_PA7 <= 1'b0; + R_op <= `NOP; + R_Din <= 8'b0; + end + // If the chip is enabled, execute an operation + else if (CS & ~CS_n) begin + // Register inputs for use later + R_PA7 <= PA7; + R_op <= op; + R_Din <= Din; + // Update the timer interrupt flag + casex (op) + `WRITE_TIMER: Timer_Int_Flag <= 1'b0; + `READ_TIMER: Timer_Int_Flag <= 1'b0; + default: if (Timer == 9'b111111111) Timer_Int_Flag <= 1'b1; + endcase + // Update the port A interrupt flag + casex (op) + `READ_INT_FLAG: PA7_Int_Flag <= 1'b0; + default: PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode); + endcase + // Process the current operation + casex(op) // RAM access + `READ_RAM: Dout <= RAM[A]; + `WRITE_RAM: RAM[A] <= Din; + // Port A data access + `READ_DRA : Dout <= (PAin & ~DDRA) | (DRA & DDRA); + `WRITE_DRA: DRA <= Din; + // Port A direction register access + `READ_DDRA: Dout <= DDRA; + `WRITE_DDRA: DDRA <= Din; + // Port B data access + `READ_DRB: Dout <= (PBin & ~DDRB) | (DRB & DDRB); + `WRITE_DRB: DRB <= Din; + // Port B direction register access + `READ_DDRB: Dout <= DDRB; + `WRITE_DDRB: DDRB <= Din; + // Timer access + `READ_TIMER: Dout <= Timer[7:0]; + // Status register access + `READ_INT_FLAG: Dout <= {Timer_Int_Flag, PA7_Int_Flag, 6'b0}; + // Enable the port A interrupt + `WRITE_EDGE_DETECT: begin + PA7_Int_Mode <= A[0]; PA7_Int_Enable <= A[1]; + end + endcase + end + // Even if the chip is not enabled, update background functions + else begin + // Update the timer interrupt + if (Timer == 9'b111111111) + Timer_Int_Flag <= 1'b1; + // Update the port A interrupt + R_PA7 <= PA7; + PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode); + // Set the operation to a NOP + R_op <=`NOP; + end + end + // Update the timer at the negative edge of the clock + always @(negedge CLK)begin + // Reset operation + if (~RES_n) begin + Timer <= 9'b0; + Timer_Mode <= 2'b0; + Prescaler <= 10'b0; + Timer_Int_Enable <= 1'b0; + end + // Otherwise, process timer operations + else + casex + (R_op) + // Write value to the timer and update the prescaler based on the address + `WRITE_TIMER:begin + Timer <= {1'b0, R_Din}; + Timer_Mode <= R_op[1:0]; + Prescaler <= PRESCALER_VALS[R_op[1:0]]; + Timer_Int_Enable <= R_op[3]; + end + // Otherwise decrement the prescaler and if necessary the timer. + // The prescaler holds a variable number of counts that must be + // run before the timer is decremented + default:if (Timer != 9'b100000000) begin + if (Prescaler != 10'b0) + Prescaler <= Prescaler - 10'b1; + else begin + if (Timer == 9'b0) + begin + Prescaler <= 10'b0; + Timer_Mode <= 2'b0; + end + else + Prescaler <= PRESCALER_VALS[Timer_Mode]; + Timer <= Timer - 9'b1; + end + end + endcase + end +endmodule diff --git a/Atari - 7800_TeST/rtl/TIA.sv b/Atari - 7800_TeST/rtl/TIA.sv new file mode 100644 index 00000000..61852f62 --- /dev/null +++ b/Atari - 7800_TeST/rtl/TIA.sv @@ -0,0 +1,477 @@ +/* Atari on an FPGA + Masters of Engineering Project + Cornell University, 2007 + Daniel Beer + TIA.v + Redesign of the Atari TIA chip. Provides the Atari with video generation, + sound generation and I/O. + */ + `timescale 1ns / 1ps + +`include "tia.vh" +module TIA(A, // Address bus input + Din, // Data bus input + Dout, // Data bus output + CS_n, // Active low chip select input + CS, // Chip select input + R_W_n, // Active low read/write input + RDY, // CPU ready output + MASTERCLK, // 3.58 Mhz pixel clock input + CLK2, // 1.19 Mhz bus clock input + idump_in, // Dumped I/O + Ilatch, // Latched I/O + HSYNC, // Video horizontal sync output + HBLANK, // Video horizontal blank output + VSYNC, // Video vertical sync output + VBLANK, // Video vertical sync output + COLOROUT, // Indexed color output + RES_n, // Active low reset input + AUD0, //audio pin 0 + AUD1, //audio pin 1 + audv0, //audio volume for use with external xformer module + audv1); //audio volume for use with external xformer module + input [5:0] A; + input [7:0] Din; + output [7:0] Dout; + input [2:0] CS_n; + input CS; + input R_W_n; + output RDY; + input MASTERCLK; + input CLK2; + input [1:0] Ilatch; + input [3:0] idump_in; + output HSYNC, HBLANK; + output VSYNC, VBLANK; + output [7:0] COLOROUT; + input RES_n; + output AUD0, AUD1; + output reg [3:0] audv0, audv1; + // Data output register + reg [7:0] Dout; + // Video control signal registers + wire HSYNC; + reg VSYNC, VBLANK; + // Horizontal pixel counter + reg [7:0] hCount; + reg [3:0] hCountReset; + reg clk_30; + reg [7:0] clk_30_count; + + wire [3:0] Idump; + + // Pixel counter update + always @(posedge MASTERCLK) + begin + // Reset operation + if (~RES_n) begin + hCount <= 8'd0; + hCountReset[3:1] <= 3'd0; + clk_30 <= 0; + clk_30_count <= 0; + latchedInputs <= 2'b11; + end + else begin + if (inputLatchReset) + latchedInputs <= 2'b11; + else + latchedInputs <= latchedInputs & Ilatch; + + if (clk_30_count == 57) begin + clk_30 <= ~clk_30; + clk_30_count <= 0; + end else begin + clk_30_count <= clk_30_count + 1; + end + // Increment the count and reset if necessary + if ((hCountReset[3]) ||(hCount == 8'd227)) + hCount <= 8'd0; + else + hCount <= hCount + 8'd1; + // Software resets are delayed by three cycles + hCountReset[3:1] <= hCountReset[2:0]; + end + end + assign HSYNC = (hCount >= 8'd20) && (hCount < 8'd36); + assign HBLANK = (hCount < 8'd68); + // Screen object registers + // These registers are set by the software and used to generate pixels + reg [7:0] player0Pos, player1Pos, missile0Pos, missile1Pos, ballPos; + reg [4:0] player0Size, player1Size; + reg [7:0] player0Color, player1Color, ballColor, pfColor, bgColor; + reg [3:0] player0Motion, player1Motion, missile0Motion, missile1Motion, + ballMotion; + reg missile0Enable, missile1Enable, ballEnable, R_ballEnable; + reg [1:0] ballSize; + reg [19:0] pfGraphic; + reg [7:0] player0Graphic, player1Graphic; + reg [7:0] R_player0Graphic, R_player1Graphic; + reg pfReflect, player0Reflect, player1Reflect; + reg prioCtrl; + reg pfColorCtrl; + reg [14:0] collisionLatch; + reg missile0Lock, missile1Lock; + reg player0VertDelay, player1VertDelay, ballVertDelay; + reg [3:0] audc0, audc1; + reg [4:0] audf0, audf1; + // Pixel number calculation + wire [7:0] pixelNum; + + + //audio control + audio audio_ctrl(.AUDC0(audc0), + .AUDC1(audc1), + .AUDF0(audf0), + .AUDF1(audf1), + .CLK_30(clk_30), //30khz clock + .AUD0(AUD0), + .AUD1(AUD1)); + + assign pixelNum = (hCount >= 8'd68) ? (hCount - 8'd68) : 8'd227; + + // Pixel tests. For each pixel and screen object, a test is done based on the + // screen objects register to determine if the screen object should show on that + // pixel. The results of all the tests are fed into logic to pick which displayed + // object has priority and color the pixel the color of that object. + // Playfield pixel test + wire [5:0] pfPixelNum; + wire pfPixelOn, pfLeftPixelVal, pfRightPixelVal; + assign pfPixelNum = pixelNum[7:2]; + assign pfLeftPixelVal = pfGraphic[pfPixelNum]; + assign pfRightPixelVal = (pfReflect == 1'b0)? pfGraphic[pfPixelNum - 6'd20]: + pfGraphic[6'd39 - pfPixelNum]; + assign pfPixelOn = (pfPixelNum < 6'd20)? pfLeftPixelVal : pfRightPixelVal; + // Player 0 sprite pixel test + wire pl0PixelOn; + wire [7:0] pl0Mask, pl0MaskDel; + assign pl0MaskDel = (player0VertDelay)? R_player0Graphic : player0Graphic; + assign pl0Mask = (!player0Reflect)? pl0MaskDel : {pl0MaskDel[0], pl0MaskDel[1], + pl0MaskDel[2], pl0MaskDel[3], + pl0MaskDel[4], pl0MaskDel[5], + pl0MaskDel[6], pl0MaskDel[7]}; + objPixelOn player0_test(pixelNum, player0Pos, player0Size[2:0], pl0Mask, pl0PixelOn); + // Player 1 sprite pixel test + wire pl1PixelOn; + wire [7:0] pl1Mask, pl1MaskDel; + assign pl1MaskDel = (player1VertDelay)? R_player1Graphic : player1Graphic; + assign pl1Mask = (!player1Reflect)? pl1MaskDel : {pl1MaskDel[0], pl1MaskDel[1], + pl1MaskDel[2], pl1MaskDel[3], + pl1MaskDel[4], pl1MaskDel[5], + pl1MaskDel[6], pl1MaskDel[7]}; + objPixelOn player1_test(pixelNum, player1Pos, player1Size[2:0], pl1Mask, pl1PixelOn); + // Missile 0 pixel test + wire mis0PixelOn, mis0PixelOut; + wire [7:0] mis0ActualPos; + reg [7:0] mis0Mask; + always @(player0Size) + begin + case(player0Size[4:3]) + 2'd0: mis0Mask <= 8'h01; + 2'd1: mis0Mask <= 8'h03; + 2'd2: mis0Mask <= 8'h0F; + 2'd3: mis0Mask <= 8'hFF; + endcase + end + assign mis0ActualPos = (missile0Lock)? player0Pos : missile0Pos; + objPixelOn missile0_test(pixelNum, mis0ActualPos, player0Size[2:0], mis0Mask, mis0PixelOut); + assign mis0PixelOn = mis0PixelOut && missile0Enable; + // Missile 1 pixel test + wire mis1PixelOn, mis1PixelOut; + wire [7:0] mis1ActualPos; + reg [7:0] mis1Mask; + always @(player1Size) + begin + case(player1Size[4:3]) + 2'd0: mis1Mask <= 8'h01; + 2'd1: mis1Mask <= 8'h03; + 2'd2: mis1Mask <= 8'h0F; + 2'd3: mis1Mask <= 8'hFF; + endcase + end + assign mis1ActualPos = (missile1Lock)? player1Pos : missile1Pos; + objPixelOn missile1_test(pixelNum, mis1ActualPos, player1Size[2:0], mis1Mask, mis1PixelOut); + assign mis1PixelOn = mis1PixelOut && missile1Enable; + // Ball pixel test + wire ballPixelOut, ballPixelOn, ballEnableDel; + reg [7:0] ballMask; + always @(ballSize) + begin + case(ballSize) + 2'd0: ballMask <= 8'h01; + 2'd1: ballMask <= 8'h03; + 2'd2: ballMask <= 8'h0F; + 2'd3: ballMask <= 8'hFF; + endcase + end + objPixelOn ball_test(pixelNum, ballPos, 3'd0, ballMask, ballPixelOut); + assign ballEnableDel = ((ballVertDelay)? R_ballEnable : ballEnable); + assign ballPixelOn = ballPixelOut && ballEnableDel; + // Playfield color selection + // The programmer can select a unique color for the playfield or have it match + // the player's sprites colors + reg [7:0] pfActualColor; + always @(pfColorCtrl, pfColor, player0Color, player1Color, pfPixelNum) + begin + if (pfColorCtrl) + begin + if (pfPixelNum < 6'd20) + pfActualColor <= player0Color; + else + pfActualColor <= player1Color; + end + else + pfActualColor <= pfColor; + end + // Final pixel color selection + reg [7:0] pixelColor; + assign COLOROUT = (HBLANK)? 8'b0 : pixelColor; + // This combinational logic uses a priority encoder like structure to select + // the highest priority screen object and color the pixel. + always @(prioCtrl, pfPixelOn, pl0PixelOn, pl1PixelOn, mis0PixelOn, mis1PixelOn, + ballPixelOn, pfActualColor, player0Color, player1Color, bgColor) + begin + // Show the playfield behind the players + if (!prioCtrl) + begin + if (pl0PixelOn || mis0PixelOn) + pixelColor <= player0Color; + else if (pl1PixelOn || mis1PixelOn) + pixelColor <= player1Color; + else if (pfPixelOn) + pixelColor <= pfActualColor; + else + pixelColor <= bgColor; + end + // Otherwise, show the playfield in front of the players + else begin + if (pfPixelOn) + pixelColor <= pfActualColor; + else if (pl0PixelOn || mis0PixelOn) + pixelColor <= player0Color; + else if (pl1PixelOn || mis1PixelOn) + pixelColor <= player1Color; + else + pixelColor <= bgColor; + end + end + // Collision register and latching update + wire [14:0] collisions; + reg collisionLatchReset; + assign collisions = {pl0PixelOn && pl1PixelOn, mis0PixelOn && mis1PixelOn, + ballPixelOn && pfPixelOn, + mis1PixelOn && pfPixelOn, mis1PixelOn && ballPixelOn, + mis0PixelOn && pfPixelOn, mis0PixelOn && ballPixelOn, + pl1PixelOn && pfPixelOn, pl1PixelOn && ballPixelOn, + pl0PixelOn && pfPixelOn, pl0PixelOn && ballPixelOn, + mis1PixelOn && pl0PixelOn, mis1PixelOn && pl1PixelOn, + mis0PixelOn && pl1PixelOn, mis0PixelOn && pl0PixelOn}; + always @(posedge MASTERCLK, posedge collisionLatchReset) + begin + if (collisionLatchReset) + collisionLatch <= 15'b000000000000000; + else + collisionLatch <= collisionLatch | collisions; + end + // WSYNC logic + // When a WSYNC is signalled by the programmer, the CPU ready line is lowered + // until the end of a scanline + reg wSync, wSyncReset; + always @(hCount, wSyncReset) + begin + if (hCount == 8'd0) + wSync <= 1'b0; + else if (wSyncReset && hCount > 8'd2) + wSync <= 1'b1; + end + assign RDY = ~wSync; + // Latched input registers and update + wire [1:0] latchedInputsValue; + reg inputLatchEnabled; + reg inputLatchReset; + reg [1:0] latchedInputs; + + /*always_ff @(Ilatch, inputLatchReset) + begin + if (inputLatchReset) + latchedInputs <= 2'b11; + else + latchedInputs <= latchedInputs & Ilatch; + end*/ + + assign latchedInputsValue = (inputLatchEnabled)? latchedInputs : Ilatch; + // Dumped input registers update + reg inputDumpEnabled; + assign Idump = (inputDumpEnabled)? 4'b0000 : idump_in; + // Software operations + always @(posedge CLK2) + begin + // Reset operation + if (~RES_n) begin + inputLatchReset <= 1'b0; + collisionLatchReset <= 1'b0; + hCountReset[0] <= 1'b0; + wSyncReset <= 1'b0; + Dout <= 8'b00000000; + end + // If the chip is enabled, execute an operation + else if (CS) begin + // Software reset signals + inputLatchReset <= ({R_W_n, A[5:0]} == `VBLANK && Din[6] && !inputLatchEnabled); + collisionLatchReset <= ({R_W_n, A[5:0]} == `CXCLR); + hCountReset[0] <= ({R_W_n, A[5:0]} == `RSYNC); + wSyncReset <= ({R_W_n, A[5:0]} == `WSYNC) && !wSync; + case({R_W_n, A[5:0]}) + // Collision latch reads + `CXM0P, `CXM0P_7800: Dout <= {collisionLatch[1:0],6'b000000}; + `CXM1P, `CXM1P_7800: Dout <= {collisionLatch[3:2],6'b000000}; + `CXP0FB, `CXP0FB_7800: Dout <= {collisionLatch[5:4],6'b000000}; + `CXP1FB, `CXP1FB_7800: Dout <= {collisionLatch[7:6],6'b000000}; + `CXM0FB, `CXM0FB_7800: Dout <= {collisionLatch[9:8],6'b000000}; + `CXM1FB, `CXM1FB_7800: Dout <= {collisionLatch[11:10],6'b000000}; + `CXBLPF, `CXBLPF_7800: Dout <= {collisionLatch[12],7'b0000000}; + `CXPPMM, `CXPPMM_7800: Dout <= {collisionLatch[14:13],6'b000000}; + // I/O reads + `INPT0, `INPT0_7800: Dout <= {Idump[0], 7'b0000000}; + `INPT1, `INPT1_7800: Dout <= {Idump[1], 7'b0000000}; + `INPT2, `INPT2_7800: Dout <= {Idump[2], 7'b0000000}; + `INPT3, `INPT3_7800: Dout <= {Idump[3], 7'b0000000}; + `INPT4, `INPT4_7800: Dout <= {latchedInputsValue[0], 7'b0000000}; + `INPT5, `INPT5_7800: Dout <= {latchedInputsValue[1], 7'b0000000}; + // Video signals + `VSYNC: VSYNC <= Din[1]; + `VBLANK: begin + inputLatchEnabled <= Din[6]; + inputDumpEnabled <= Din[7]; + VBLANK <= Din[1]; + end + `WSYNC:; + `RSYNC:; + // Screen object register access + `NUSIZ0: player0Size <= {Din[5:4],Din[2:0]}; + `NUSIZ1: player1Size <= {Din[5:4],Din[2:0]}; + `COLUP0: player0Color <= Din; + `COLUP1: player1Color <= Din; + `COLUPF: pfColor <= Din; + `COLUBK: bgColor <= Din; + `CTRLPF: begin + pfReflect <= Din[0]; + pfColorCtrl <= Din[1]; + prioCtrl <= Din[2]; + ballSize <= Din[5:4]; + end + `REFP0: player0Reflect <= Din[3]; + `REFP1: player1Reflect <= Din[3]; + `PF0: pfGraphic[3:0] <= Din[7:4]; + `PF1: pfGraphic[11:4] <= {Din[0], Din[1], Din[2], Din[3], + Din[4], Din[5], Din[6], Din[7]}; + `PF2: pfGraphic[19:12] <= Din[7:0]; + `RESP0: player0Pos <= pixelNum; + `RESP1: player1Pos <= pixelNum; + `RESM0: missile0Pos <= pixelNum; + `RESM1: missile1Pos <= pixelNum; + `RESBL: ballPos <= pixelNum; + // Audio controls + `AUDC0: audc0 <= Din[3:0]; + `AUDC1: audc1 <= Din[3:0]; + `AUDF0: audf0 <= Din[4:0]; + `AUDF1: audf1 <= Din[4:0]; + `AUDV0: audv0 <= Din[3:0]; + `AUDV1: audv1 <= Din[3:0]; + // Screen object register access + `GRP0: begin + player0Graphic <= {Din[0], Din[1], Din[2], Din[3], + Din[4], Din[5], Din[6], Din[7]}; + R_player1Graphic <= player1Graphic; + end + `GRP1: begin + player1Graphic <= {Din[0], Din[1], Din[2], Din[3], + Din[4], Din[5], Din[6], Din[7]}; + R_player0Graphic <= player0Graphic; + R_ballEnable <= ballEnable; + end + `ENAM0: missile0Enable <= Din[1]; + `ENAM1: missile1Enable <= Din[1]; + `ENABL: ballEnable <= Din[1]; + `HMP0: player0Motion <= Din[7:4]; + `HMP1: player1Motion <= Din[7:4]; + `HMM0: missile0Motion <= Din[7:4]; + `HMM1: missile1Motion <= Din[7:4]; + `HMBL: ballMotion <= Din[7:4]; + `VDELP0: player0VertDelay <= Din[0]; + `VDELP1: player1VertDelay <= Din[0]; + `VDELBL: ballVertDelay <= Din[0]; + `RESMP0: missile0Lock <= Din[1]; + `RESMP1: missile1Lock <= Din[1]; + // Strobed line that initiates an object move + `HMOVE: begin + player0Pos <= player0Pos - {{4{player0Motion[3]}}, + player0Motion[3:0]}; + player1Pos <= player1Pos - {{4{player1Motion[3]}}, + player1Motion[3:0]}; + missile0Pos <= missile0Pos - {{4{missile0Motion[3]}}, + missile0Motion[3:0]}; + missile1Pos <= missile1Pos - {{4{missile1Motion[3]}}, + missile1Motion[3:0]}; + ballPos <= ballPos - {{4{ballMotion[3]}},ballMotion[3:0]}; + end + // Motion register clear + `HMCLR: begin + player0Motion <= Din[7:4]; + player1Motion <= Din[7:4]; + missile0Motion <= Din[7:4]; + missile1Motion <= Din[7:4]; + ballMotion <= Din[7:4]; + end + `CXCLR:; + default: Dout <= 8'b00000000; + endcase + end + // If the chip is not enabled, do nothing + else begin + inputLatchReset <= 1'b0; + collisionLatchReset <= 1'b0; + hCountReset[0] <= 1'b0; + wSyncReset <= 1'b0; + Dout <= 8'b00000000; + end + end +endmodule +// objPixelOn module +// Checks the pixel number against a stretched and possibly duplicated version of the +// object. +module objPixelOn(pixelNum, objPos, objSize, objMask, pixelOn); + input [7:0] pixelNum, objPos, objMask; + input [2:0] objSize; + output pixelOn; + wire [7:0] objIndex; + wire [8:0] objByteIndex; + wire objMaskOn, objPosOn; + reg objSizeOn; + reg [2:0] objMaskSel; + assign objIndex = pixelNum - objPos - 8'd1; + assign objByteIndex = 9'b1 << (objIndex[7:3]); + always @(objSize, objByteIndex) + begin + case (objSize) + 3'd0: objSizeOn <= (objByteIndex & 9'b00000001) != 0; + 3'd1: objSizeOn <= (objByteIndex & 9'b00000101) != 0; + 3'd2: objSizeOn <= (objByteIndex & 9'b00010001) != 0; + 3'd3: objSizeOn <= (objByteIndex & 9'b00010101) != 0; + 3'd4: objSizeOn <= (objByteIndex & 9'b10000001) != 0; + 3'd5: objSizeOn <= (objByteIndex & 9'b00000011) != 0; + 3'd6: objSizeOn <= (objByteIndex & 9'b10010001) != 0; + 3'd7: objSizeOn <= (objByteIndex & 9'b00001111) != 0; + endcase + end + always @(objSize, objIndex) + begin + case (objSize) + 3'd5: objMaskSel <= objIndex[3:1]; + 3'd7: objMaskSel <= objIndex[4:2]; + default: objMaskSel <= objIndex[2:0]; + endcase + end + assign objMaskOn = objMask[objMaskSel]; + assign objPosOn = (pixelNum > objPos) && ({1'b0, pixelNum} <= {1'b0, objPos} + 9'd72); + assign pixelOn = objSizeOn && objMaskOn && objPosOn; +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/atari7800.vh b/Atari - 7800_TeST/rtl/atari7800.vh new file mode 100644 index 00000000..d1d73a75 --- /dev/null +++ b/Atari - 7800_TeST/rtl/atari7800.vh @@ -0,0 +1,11 @@ +`define CS_NONE 'h0 +`define CS_RAM0 'h1 +`define CS_RAM1 'h2 +`define CS_RIOT_IO 'h3 +`define CS_RIOT_RAM 'h4 +`define CS_TIA 'h5 +`define CS_BIOS 'h6 +`define CS_MARIA 'h7 +`define CS_CART 'h8 + +`define chipselect logic[3:0] \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/audio.sv b/Atari - 7800_TeST/rtl/audio.sv new file mode 100644 index 00000000..e0786a27 --- /dev/null +++ b/Atari - 7800_TeST/rtl/audio.sv @@ -0,0 +1,93 @@ +`timescale 1ns / 1ps + +module audio(input logic [3:0] AUDC0, AUDC1, + input logic [4:0] AUDF0, AUDF1, + input logic CLK_30, //30khz clock + output logic AUD0,AUD1 + ); + + logic [4:0] counter0, counter1 = 5'b0; + integer rep0,rep1,ind0,ind1 = 0; + logic [1:0] pattern45 = 2'b10; + logic pattern0b = 1'b1; + logic [14:0] pattern1 = 15'b111100010011010; + logic [30:0] pattern6a = 31'b1111111111111111110000000000000; + logic [30:0] pattern79 = 31'b1111100011011101010000100101100; + logic [5:0] patterncd = 6'b111000; + logic [92:0] patterne = 93'b111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000; + logic [92:0] patternf = 93'b111111111100000111000000011110000000000111111000111111000011111111100000011111000000111100000; + logic [464:0] pattern2 = 465'b111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000111111111111100000000000000000000000000000001111111111111111111111111111111000000000000000000111111111111100000000000000000011111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000001111111111111111110000000000000000000000000000000111111111111111111111111111111100000000000001111111111111111110000000000000; + logic [464:0] pattern3 = 465'b111111000000100011100111110001111111000111100011001100000111111111000100000111011001111111111100000100000111010011111111111100000100111110010111111111111000000100111110110111111111100000011100110000100111111000000000010000110111101111110000000000110000110100001111100000000011100011110101111111100000111110000011110101111111100001100000000111000101111111000011000000011111011101111111000010000111111110010001111000000010001111111000110111111000000110011110000011100; + logic [510:0] pattern8 = 511'b1111111110000011110111110001011100110010000010010100111011010001111001111100110110001010100100011100011011010101110001001100010001000000001000010001100001001110010101011000011011110100110111001000101000010101101001111110110010010010110111111001001101010011001100000001100011001010001101001011111110100010110001110101100101100111100011111011101000001101011011011101100000101101011111010101010000001010010101111001011101110000001110011101001001111010111010100010010000110011100001011110110110011010000111011110000; + + always_comb begin + case (AUDC0) + 4'h0,4'hb: rep0 = 1; + 4'h1: rep0 = 15; + 4'h2,4'h3: rep0 = 465; + 4'h4,4'h5: rep0 = 2; + 4'h6,4'h7,4'h9,4'ha: rep0 = 31; + 4'h8: rep0 = 511; + 4'hc,4'hd: rep0 = 6; + 4'he,4'hf: rep0 = 93; + default: rep0 = 1; + endcase + case (AUDC1) + 4'h0,4'hb: rep1 = 1; + 4'h1: rep1 = 15; + 4'h2,4'h3: rep1 = 465; + 4'h4,4'h5: rep1 = 2; + 4'h6,4'h7,4'h9,4'ha: rep1 = 31; + 4'h8: rep1 = 511; + 4'hc,4'hd: rep1 = 6; + 4'he,4'hf: rep1 = 93; + default: rep0 = 1; + endcase + end + + always_ff @(posedge CLK_30) begin //divide the clk by the frequency value + if (counter0 == AUDF0) begin + case (AUDC0) + 4'h0,4'hb: AUD0 <= pattern0b; + 4'h1: AUD0 <= pattern1[ind0]; + 4'h2: AUD0 <= pattern2[ind0]; + 4'h3: AUD0 <= pattern3[ind0]; + 4'h4,4'h5: AUD0 <= pattern45[ind0]; + 4'h6,4'ha: AUD0 <= pattern6a[ind0]; + 4'h7,4'h9: AUD0 <= pattern79[ind0]; + 4'h8: AUD0 <= pattern8[ind0]; + 4'hc,4'hd: AUD0 <= patterncd[ind0]; + 4'he: AUD0 <= patterne[ind0]; + 4'hf: AUD0 <= patternf[ind0]; + default: AUD0 <= 1'bx; + endcase + ind0 <= (ind0 + 1) % rep0; + counter0 <= 0; + end + else + counter0 <= counter0 + 1; + + if (counter1 == AUDF1) begin + case (AUDC1) + 4'h0,4'hb: AUD1 <= pattern0b; + 4'h1: AUD1 <= pattern1[ind1]; + 4'h2: AUD1 <= pattern2[ind1]; + 4'h3: AUD1 <= pattern3[ind1]; + 4'h4,4'h5: AUD1 <= pattern45[ind1]; + 4'h6,4'ha: AUD1 <= pattern6a[ind1]; + 4'h7,4'h9: AUD1 <= pattern79[ind1]; + 4'h8: AUD1 <= pattern8[ind1]; + 4'hc,4'hd: AUD1 <= patterncd[ind1]; + 4'he: AUD1 <= patterne[ind1]; + 4'hf: AUD1 <= patternf[ind1]; + default: AUD1 <= 1'bx; + endcase + ind1 <= (ind1 + 1) % rep1; + counter1 <= 0; + end + else + counter1 <= counter1 + 1; + end + + +endmodule diff --git a/Atari - 7800_TeST/rtl/audio_xformer.sv b/Atari - 7800_TeST/rtl/audio_xformer.sv new file mode 100644 index 00000000..2ccac83a --- /dev/null +++ b/Atari - 7800_TeST/rtl/audio_xformer.sv @@ -0,0 +1,24 @@ +`timescale 1ns / 1ps + +module audio_xformer(input logic AUD0, AUD1, + input logic [3:0] AUDV0, AUDV1, + output logic [15:0] AUD_SIGNAL); + + logic [15:0] audio0,audio1; + + + assign AUD_SIGNAL = audio0 + audio1; + + always_comb begin + case (AUD0) + 1: audio0 = 16'h3FF * AUDV0; + 0: audio0 = 16'hFC00 * AUDV0; + endcase + case (AUD1) + 1: audio1 = 16'h3FF * AUDV1; + 0: audio1 = 16'hFC00 * AUDV1; + endcase + end + + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/build_id.tcl b/Atari - 7800_TeST/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Atari - 7800_TeST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/build_id.v b/Atari - 7800_TeST/rtl/build_id.v new file mode 100644 index 00000000..3192af89 --- /dev/null +++ b/Atari - 7800_TeST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "180630" +`define BUILD_TIME "212824" diff --git a/Atari - 7800_TeST/rtl/cart_top.sv b/Atari - 7800_TeST/rtl/cart_top.sv new file mode 100644 index 00000000..222f220f --- /dev/null +++ b/Atari - 7800_TeST/rtl/cart_top.sv @@ -0,0 +1,257 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 11/02/2015 11:36:06 AM +// Design Name: +// Module Name: cart_top +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + +`include "atari7800.vh" + +`define INPUT_CYCLES 256 +`define INPUT_CYCLES_NBITS 9 + +module cart_top( + 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, +// output UART_TX,//uses for Tape Record +// input UART_RX,//uses for Tape Play + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input SPI_SS4, + input CONF_DATA0, + + output logic [7:0] ld, + + input logic [7:0] sw, + input logic PB_UP,PB_DOWN,PB_LEFT,PB_RIGHT,PB_CENTER, + + + inout logic [6:0] ctrl_0_fmc, ctrl_1_fmc + ); + +`include "rtl\build_id.v" +assign LED = 1; +localparam CONF_STR = { + "ATARI7800;;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v0.0.",`BUILD_DATE + }; + + + + wire clk25, clk7p143, clk6p25; + wire locked; + + pll pll ( + .inclk0(CLOCK_27), + .c0(clk25), + .c1(clk7p143), + .c2(clk6p25), + .locked(locked) + ); + wire scandoubler_disable; + wire ypbpr; + wire ps2_kbd_clk, ps2_kbd_data; + wire [31:0] status; + wire [1:0] buttons; + wire [1:0] switches; + wire [3:0] r, g, b; + wire hs, vs, hb, vb; + wire blankn = ~(hb | vb); + + + logic [7:0] cart_data_out; + logic [15:0] AB; + logic RW; + logic pclk_0; + reg [`INPUT_CYCLES_NBITS-1:0] paddleA0_ctr = {`INPUT_CYCLES_NBITS{1'b0}}; + reg [`INPUT_CYCLES_NBITS-1:0] paddleB0_ctr = {`INPUT_CYCLES_NBITS{1'b0}}; + reg [`INPUT_CYCLES_NBITS-1:0] paddleA1_ctr = {`INPUT_CYCLES_NBITS{1'b0}}; + reg [`INPUT_CYCLES_NBITS-1:0] paddleB1_ctr = {`INPUT_CYCLES_NBITS{1'b0}}; + + always_ff @(posedge pclk_0) begin + if (~ctrl_0_fmc[6]) + paddleA0_ctr <= 0; + else if (paddleA0_ctr < `INPUT_CYCLES) + paddleA0_ctr <= paddleA0_ctr + 1; + + if (~ctrl_0_fmc[4]) + paddleB0_ctr <= 0; + else if (paddleB0_ctr < `INPUT_CYCLES) + paddleB0_ctr <= paddleB0_ctr + 1; + + if (~ctrl_1_fmc[6]) + paddleA1_ctr <= 0; + else if (paddleA1_ctr < `INPUT_CYCLES) + paddleA1_ctr <= paddleA1_ctr + 1; + + if (~ctrl_1_fmc[4]) + paddleB1_ctr <= 0; + else if (paddleB1_ctr < `INPUT_CYCLES) + paddleB1_ctr <= paddleB1_ctr + 1; + end + + + logic [3:0] idump; + logic [1:0] ilatch; + logic [7:0] PAin, PBin, PAout, PBout; + logic [15:0] audio; + + + logic right_0_b, left_0_b, down_0_b, up_0_b, fire_0_b, paddle_A_0, paddle_B_0; + logic right_1_b, left_1_b, down_1_b, up_1_b, fire_1_b, paddle_A_1, paddle_B_1; + logic player1_2bmode, player2_2bmode; + + assign player1_2bmode = ~PBout[2] & ~tia_en; + assign player2_2bmode = ~PBout[4] & ~tia_en; + + assign {right_0_b, left_0_b, down_0_b, up_0_b} = ctrl_0_fmc[3:0]; + assign {right_1_b, left_1_b, down_1_b, up_1_b} = ctrl_1_fmc[3:0]; + + assign paddle_B_0 = paddleB0_ctr == `INPUT_CYCLES; + assign paddle_B_1 = paddleB1_ctr == `INPUT_CYCLES; + assign paddle_A_0 = paddleA0_ctr == `INPUT_CYCLES; + assign paddle_A_1 = paddleA1_ctr == `INPUT_CYCLES; + + assign fire_0_b = (~paddle_A_0 & ~paddle_B_0); + assign fire_1_b = (~paddle_A_1 & ~paddle_B_1); + logic tia_en; + + assign PAin[7:4] = {right_0_b, left_0_b, down_0_b, up_0_b}; + assign PAin[3:0] = {right_1_b, left_1_b, down_1_b, up_1_b}; + + assign PBin[7] = sw[1]; // RDiff + assign PBin[6] = sw[0]; // LDiff + assign PBin[5] = 1'b0; // Unused + assign PBin[4] = 1'b0; + assign PBin[3] = ~PB_DOWN; // Pause + assign PBin[2] = 1'b0; // 2 Button mode + assign PBin[1] = ~PB_LEFT; // Select + assign PBin[0] = ~PB_UP; // Reset + + + assign ilatch[0] = fire_0_b; + assign ilatch[1] = fire_1_b; + + assign idump = {paddle_A_0, paddle_B_0, paddle_A_1, paddle_B_1}; + + logic [7:0] def_dout; + assign cart_data_out = def_dout; + + defender_rom defender_rom ( + .clock(pclk_0), + .address(AB[11:0]), + .q(def_dout) + ); + + Atari7800 console( + .clock_25(clk25), + .sysclk_7_143(clk7p143), + .clock_divider_locked(locked), + .reset((buttons[1] || status[0] || status[6])), + .RED(r), + .GREEN(g), + .BLUE(b), + .HSync(hs), + .VSync(vs), + .aud_signal_out(audio), + + .cart_DB_out(cart_data_out), + .AB(AB), + .RW(RW), + .pclk_0(pclk_0), + .ld(ld), + .tia_en(tia_en), + + .idump(idump), + .ilatch(ilatch), + .PAin(PAin), + .PBin(PBin), + .PAout(PAout), + .PBout(PBout) + ); + +sigma_delta_dac #(.MSBI(15)) sigma_delta_dac ( + .DACout(AUDIO_L), + .DACin(audio), + .CLK(clk25), + .RESET() +); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io +( + .conf_str(CONF_STR), + .clk_sys(clk25), + .SPI_SCK(SPI_SCK), + .CONF_DATA0(CONF_DATA0), + .SPI_SS2(SPI_SS2), + .SPI_DO(SPI_DO), + .SPI_DI(SPI_DI), + .buttons(buttons), + .switches(switches), + .scandoubler_disable(scandoubler_disable), + .ypbpr(ypbpr), + .status(status), + .ps2_kbd_clk(ps2_kbd_clk), + .ps2_kbd_data(ps2_kbd_data) +); + +video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(0)) video_mixer +( + .clk_sys(clk25), + .ce_pix(clk6p25), + .ce_pix_actual(clk6p25), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .scandoubler_disable(1),//scandoubler_disable), + .hq2x(status[4:3]==1), + .ypbpr(ypbpr), + .ypbpr_full(1), + .R({r,r[1:0]}), + .G({g,g[1:0]}), + .B({b,b[1:0]}), +// .R(blankn ? {r,r[1:0]} : "000000"), +// .G(blankn ? {g,g[1:0]} : "000000"), +// .B(blankn ? {b,b[1:0]} : "000000"), + .mono(0), + .HSync(hs), + .VSync(vs), + .line_start(0), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS) +); + + +assign AUDIO_R = AUDIO_L; + +endmodule diff --git a/Atari - 7800_TeST/rtl/cpu.sv b/Atari - 7800_TeST/rtl/cpu.sv new file mode 100644 index 00000000..64ff3cd8 --- /dev/null +++ b/Atari - 7800_TeST/rtl/cpu.sv @@ -0,0 +1,1250 @@ +/* + * verilog model of 6502 CPU. + * + * (C) Arlet Ottens, + * + * Feel free to use this code in any project (commercial or not), as long as you + * keep this message, and the copyright notice. This code is provided "as is", + * without any warranties of any kind. + * + */ + +/* + * Note that not all 6502 interface signals are supported (yet). The goal + * is to create an Acorn Atom model, and the Atom didn't use all signals on + * the main board. + * + * The data bus is implemented as separate read/write buses. Combine them + * on the output pads if external memory is required. + */ + `timescale 1ns / 1ps +`include "atari7800.vh" + + + + + +module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY, pc_temp, res); + +input clk; // CPU clock +input reset; // reset signal +output reg [15:0] AB; // address bus +input [7:0] DI; // data in, read bus +output [7:0] DO; // data out, write bus +output WE; // write enable +input IRQ; // interrupt request +input NMI; // non-maskable interrupt request +input RDY; // Ready signal. Pauses CPU when RDY=0 + +output [15:0] pc_temp; +output reg res; + +assign pc_temp = PC_temp; + +/* + * internal signals + */ + +reg [15:0] PC; // Program Counter +reg [7:0] ABL; // Address Bus Register LSB +reg [7:0] ABH; // Address Bus Register MSB +wire [7:0] ADD; // Adder Hold Register (registered in ALU) + +reg [7:0] DIHOLD; // Hold for Data In +reg DIHOLD_valid; // +wire [7:0] DIMUX; // + +reg [7:0] IRHOLD; // Hold for Instruction register +reg IRHOLD_valid; // Valid instruction in IRHOLD + +reg [7:0] AXYS[3:0]; // A, X, Y and S register file + +wire [7:0] AA; +wire [7:0] XX; +wire [7:0] YY; +wire [7:0] SS; +assign YY = AXYS[3]; +assign XX = AXYS[2]; +assign SS = AXYS[1]; +assign AA = AXYS[0]; + +(* keep = "true" *) +wire [15:0] pc_temp_kept; + +assign pc_temp_kept = PC_temp; + +reg C = 0; // carry flag (init at zero to avoid X's in ALU sim) +reg Z = 0; // zero flag +reg I = 0; // interrupt flag +reg D = 0; // decimal flag +reg V = 0; // overflow flag +reg N = 0; // negative flag +wire AZ; // ALU Zero flag +wire AV; // ALU overflow flag +wire AN; // ALU negative flag +wire HC; // ALU half carry + +reg [7:0] AI; // ALU Input A +reg [7:0] BI; // ALU Input B +wire [7:0] DI; // Data In +wire [7:0] IR; // Instruction register +reg [7:0] DO; // Data Out +reg WE; // Write Enable +reg CI; // Carry In +wire CO; // Carry Out +wire [7:0] PCH = PC[15:8]; +wire [7:0] PCL = PC[7:0]; + +reg NMI_edge = 0; // captured NMI edge + +reg [1:0] regsel; // Select A, X, Y or S register +wire [7:0] regfile = AXYS[regsel]; // Selected register output + +parameter + SEL_A = 2'd0, + SEL_S = 2'd1, + SEL_X = 2'd2, + SEL_Y = 2'd3; + +/* + * define some signals for watching in simulator output + */ + + +`ifdef SIM +wire [7:0] A = AXYS[SEL_A]; // Accumulator +wire [7:0] X = AXYS[SEL_X]; // X register +wire [7:0] Y = AXYS[SEL_Y]; // Y register +wire [7:0] S = AXYS[SEL_S]; // Stack pointer +`endif + +wire [7:0] P = { N, V, 2'b11, D, I, Z, C }; + +/* + * instruction decoder/sequencer + */ + +reg [5:0] state; + +/* + * control signals + */ + +reg PC_inc; // Increment PC +reg [15:0] PC_temp; // intermediate value of PC + +reg [1:0] src_reg; // source register index +reg [1:0] dst_reg; // destination register index + +reg index_y; // if set, then Y is index reg rather than X +reg load_reg; // loading a register (A, X, Y, S) in this instruction +reg inc; // increment +reg write_back; // set if memory is read/modified/written +reg load_only; // LDA/LDX/LDY instruction +reg store; // doing store (STA/STX/STY) +reg adc_sbc; // doing ADC/SBC +reg compare; // doing CMP/CPY/CPX +reg shift; // doing shift/rotate instruction +reg rotate; // doing rotate (no shift) +reg backwards; // backwards branch +reg cond_true; // branch condition is true +reg [2:0] cond_code; // condition code bits from instruction +reg shift_right; // Instruction ALU shift/rotate right +reg alu_shift_right; // Current cycle shift right enable +reg [3:0] op; // Main ALU operation for instruction +reg [3:0] alu_op; // Current cycle ALU operation +reg adc_bcd; // ALU should do BCD style carry +reg adj_bcd; // results should be BCD adjusted + +/* + * some flip flops to remember we're doing special instructions. These + * get loaded at the DECODE state, and used later + */ +reg bit_ins; // doing BIT instruction +reg plp; // doing PLP instruction +reg php; // doing PHP instruction +reg clc; // clear carry +reg sec; // set carry +reg cld; // clear decimal +reg sed; // set decimal +reg cli; // clear interrupt +reg sei; // set interrupt +reg clv; // clear overflow +reg brk; // doing BRK + +//reg res; // in reset + +/* + * ALU operations + */ + +parameter + OP_OR = 4'b1100, + OP_AND = 4'b1101, + OP_EOR = 4'b1110, + OP_ADD = 4'b0011, + OP_SUB = 4'b0111, + OP_ROL = 4'b1011, + OP_A = 4'b1111; + +/* + * Microcode state machine. Basically, every addressing mode has its own + * path through the state machine. Additional information, such as the + * operation, source and destination registers are decoded in parallel, and + * kept in separate flops. + */ + +parameter + ABS0 = 6'd0, // ABS - fetch LSB + ABS1 = 6'd1, // ABS - fetch MSB + ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X) + ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry) + ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed) + BRA0 = 6'd5, // Branch - fetch offset and send to ALU (+PC[7:0]) + BRA1 = 6'd6, // Branch - fetch opcode, and send PC[15:8] to ALU + BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed) + BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1) + BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1) + BRK2 = 6'd10, // BRK/IRQ - push P, send S to ALU (-1) + BRK3 = 6'd11, // BRK/IRQ - write S, and fetch @ fffe + DECODE = 6'd12, // IR is valid, decode instruction, and write prev reg + FETCH = 6'd13, // fetch next opcode, and perform prev ALU op + INDX0 = 6'd14, // (ZP,X) - fetch ZP address, and send to ALU (+X) + INDX1 = 6'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1 + INDX2 = 6'd16, // (ZP,X) - fetch MSB at ZP+X+1 + INDX3 = 6'd17, // (ZP,X) - fetch data + INDY0 = 6'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1) + INDY1 = 6'd19, // (ZP),Y - fetch at ZP+1, and send LSB to ALU (+Y) + INDY2 = 6'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry) + INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed) + JMP0 = 6'd22, // JMP - fetch PCL and hold + JMP1 = 6'd23, // JMP - fetch PCH + JMPI0 = 6'd24, // JMP IND - fetch LSB and send to ALU for delay (+0) + JMPI1 = 6'd25, // JMP IND - fetch MSB, proceed with JMP0 state + JSR0 = 6'd26, // JSR - push PCH, save LSB, send S to ALU (-1) + JSR1 = 6'd27, // JSR - push PCL, send S to ALU (-1) + JSR2 = 6'd28, // JSR - write S + JSR3 = 6'd29, // JSR - fetch MSB + PULL0 = 6'd30, // PLP/PLA - save next op in IRHOLD, send S to ALU (+1) + PULL1 = 6'd31, // PLP/PLA - fetch data from stack, write S + PULL2 = 6'd32, // PLP/PLA - prefetch op, but don't increment PC + PUSH0 = 6'd33, // PHP/PHA - send A to ALU (+0) + PUSH1 = 6'd34, // PHP/PHA - write A/P, send S to ALU (-1) + READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift) + REG = 6'd36, // Read register for reg-reg transfers + RTI0 = 6'd37, // RTI - send S to ALU (+1) + RTI1 = 6'd38, // RTI - read P from stack + RTI2 = 6'd39, // RTI - read PCL from stack + RTI3 = 6'd40, // RTI - read PCH from stack + RTI4 = 6'd41, // RTI - read PCH from stack + RTS0 = 6'd42, // RTS - send S to ALU (+1) + RTS1 = 6'd43, // RTS - read PCL from stack + RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH + RTS3 = 6'd45, // RTS - load PC and increment + WRITE = 6'd46, // Write memory for read/modify/write + ZP0 = 6'd47, // Z-page - fetch ZP address + ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X) + ZPX1 = 6'd49; // ZP, X - load from memory + +`ifdef SIM + +/* + * easy to read names in simulator output + */ +reg [8*6-1:0] statename; + +always @* + case( state ) + DECODE: statename = "DECODE"; + REG: statename = "REG"; + ZP0: statename = "ZP0"; + ZPX0: statename = "ZPX0"; + ZPX1: statename = "ZPX1"; + ABS0: statename = "ABS0"; + ABS1: statename = "ABS1"; + ABSX0: statename = "ABSX0"; + ABSX1: statename = "ABSX1"; + ABSX2: statename = "ABSX2"; + INDX0: statename = "INDX0"; + INDX1: statename = "INDX1"; + INDX2: statename = "INDX2"; + INDX3: statename = "INDX3"; + INDY0: statename = "INDY0"; + INDY1: statename = "INDY1"; + INDY2: statename = "INDY2"; + INDY3: statename = "INDY3"; + READ: statename = "READ"; + WRITE: statename = "WRITE"; + FETCH: statename = "FETCH"; + PUSH0: statename = "PUSH0"; + PUSH1: statename = "PUSH1"; + PULL0: statename = "PULL0"; + PULL1: statename = "PULL1"; + PULL2: statename = "PULL2"; + JSR0: statename = "JSR0"; + JSR1: statename = "JSR1"; + JSR2: statename = "JSR2"; + JSR3: statename = "JSR3"; + RTI0: statename = "RTI0"; + RTI1: statename = "RTI1"; + RTI2: statename = "RTI2"; + RTI3: statename = "RTI3"; + RTI4: statename = "RTI4"; + RTS0: statename = "RTS0"; + RTS1: statename = "RTS1"; + RTS2: statename = "RTS2"; + RTS3: statename = "RTS3"; + BRK0: statename = "BRK0"; + BRK1: statename = "BRK1"; + BRK2: statename = "BRK2"; + BRK3: statename = "BRK3"; + BRA0: statename = "BRA0"; + BRA1: statename = "BRA1"; + BRA2: statename = "BRA2"; + JMP0: statename = "JMP0"; + JMP1: statename = "JMP1"; + JMPI0: statename = "JMPI0"; + JMPI1: statename = "JMPI1"; + endcase + +//always @( PC ) +// $display( "%t, PC:%04x IR:%02x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d P:%02x", $time, PC, IR, A, X, Y, S, C, Z, V, N, P ); + +`endif + + + +/* + * Program Counter Increment/Load. First calculate the base value in + * PC_temp. + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_temp = { ABH, ABL }; + else + PC_temp = PC; + + + JMP1, + JMPI1, + JSR3, + RTS3, + RTI4: PC_temp = { DIMUX, ADD }; + + BRA1: PC_temp = { ABH, ADD }; + + BRA2: PC_temp = { ADD, PCL }; + + BRK2: PC_temp = res ? 16'hfffc : + NMI_edge ? 16'hfffa : 16'hfffe; + + default: PC_temp = PC; + endcase + +/* + * Determine wether we need PC_temp, or PC_temp + 1 + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_inc = 0; + else + PC_inc = 1; + + ABS0, + ABSX0, + FETCH, + BRA0, + BRA2, + BRK3, + JMPI1, + JMP1, + RTI4, + RTS3: PC_inc = 1; + + BRA1: PC_inc = CO ^~ backwards; + + default: PC_inc = 0; + endcase + +/* + * Set new PC + */ +always @(posedge clk) + if( RDY ) + PC <= PC_temp + PC_inc; + +/* + * Address Generator + */ + +parameter + ZEROPAGE = 8'h00, + STACKPAGE = 8'h01; + +always @* + case( state ) + ABSX1, + INDX3, + INDY2, + JMP1, + JMPI1, + RTI4, + ABS1: AB = { DIMUX, ADD }; + + BRA2, + INDY3, + ABSX2: AB = { ADD, ABL }; + + BRA1: AB = { ABH, ADD }; + + JSR0, + PUSH1, + RTS0, + RTI0, + BRK0: AB = { STACKPAGE, regfile }; + + BRK1, + JSR1, + PULL1, + RTS1, + RTS2, + RTI1, + RTI2, + RTI3, + BRK2: AB = { STACKPAGE, ADD }; + + INDY1, + INDX1, + ZPX1, + INDX2: AB = { ZEROPAGE, ADD }; + + ZP0, + INDY0: AB = { ZEROPAGE, DIMUX }; + + REG, + READ, + WRITE: AB = { ABH, ABL }; + + default: AB = PC; + endcase + +/* + * ABH/ABL pair is used for registering previous address bus state. + * This can be used to keep the current address, freeing up the original + * source of the address, such as the ALU or DI. + */ +always @(posedge clk) + if( state != PUSH0 && state != PUSH1 && RDY && + state != PULL0 && state != PULL1 && state != PULL2 ) + begin + ABL <= AB[7:0]; + ABH <= AB[15:8]; + end + +/* + * Data Out MUX + */ +always @* + case( state ) + WRITE: DO = ADD; + + JSR0, + BRK0: DO = PCH; + + JSR1, + BRK1: DO = PCL; + + PUSH1: DO = php ? P : ADD; + + BRK2: DO = (IRQ | NMI_edge) ? (P & 8'b1110_1111) : P; + + default: DO = regfile; + endcase + +/* + * Write Enable Generator + */ + +always @* + case( state ) + BRK0, // writing to stack or memory + BRK1, + BRK2, + JSR0, + JSR1, + PUSH1, + WRITE: WE = 1; + + INDX3, // only if doing a STA, STX or STY + INDY3, + ABSX2, + ABS1, + ZPX1, + ZP0: WE = store; + + default: WE = 0; + endcase + +/* + * register file, contains A, X, Y and S (stack pointer) registers. At each + * cycle only 1 of those registers needs to be accessed, so they combined + * in a small memory, saving resources. + */ + +reg write_register; // set when register file is written + +always @* + case( state ) + DECODE: write_register = load_reg & ~plp; + + PULL1, + RTS2, + RTI3, + BRK3, + JSR0, + JSR2 : write_register = 1; + + default: write_register = 0; + endcase + +/* + * BCD adjust logic + */ + +always @(posedge clk) + adj_bcd <= adc_sbc & (D | sed); // '1' when doing a BCD instruction + +reg [3:0] ADJL; +reg [3:0] ADJH; + +// adjustment term to be added to ADD[3:0] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// HC : half carry bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, HC} ) + 3'b0xx: ADJL = 4'd0; // no BCD instruction + 3'b100: ADJL = 4'd10; // SBC, and digital borrow + 3'b101: ADJL = 4'd0; // SBC, but no borrow + 3'b110: ADJL = 4'd0; // ADC, but no carry + 3'b111: ADJL = 4'd6; // ADC, and decimal/digital carry + endcase +end + +// adjustment term to be added to ADD[7:4] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// CO : carry out bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, CO} ) + 3'b0xx: ADJH = 4'd0; // no BCD instruction + 3'b100: ADJH = 4'd10; // SBC, and digital borrow + 3'b101: ADJH = 4'd0; // SBC, but no borrow + 3'b110: ADJH = 4'd0; // ADC, but no carry + 3'b111: ADJH = 4'd6; // ADC, and decimal/digital carry + endcase +end + +/* + * write to a register. Usually this is the (BCD corrected) output of the + * ALU, but in case of the JSR0 we use the S register to temporarily store + * the PCL. This is possible, because the S register itself is stored in + * the ALU during those cycles. + */ +always @(posedge clk) + if( write_register & RDY ) + AXYS[regsel] <= (state == JSR0) ? DIMUX : { ADD[7:4] + ADJH, ADD[3:0] + ADJL }; + +/* + * register select logic. This determines which of the A, X, Y or + * S registers will be accessed. + */ + +always @* + case( state ) + INDY1, + INDX0, + ZPX0, + ABSX0 : regsel = index_y ? SEL_Y : SEL_X; + + + DECODE : regsel = dst_reg; + + BRK0, + BRK3, + JSR0, + JSR2, + PULL0, + PULL1, + PUSH1, + RTI0, + RTI3, + RTS0, + RTS2 : regsel = SEL_S; + + default: regsel = src_reg; + endcase + +/* + * ALU + */ + +ALU ALU( .clk(clk), + .op(alu_op), + .right(alu_shift_right), + .AI(AI), + .BI(BI), + .CI(CI), + .BCD(adc_bcd & (state == FETCH)), + .CO(CO), + .OUT(ADD), + .V(AV), + .Z(AZ), + .N(AN), + .HC(HC), + .RDY(RDY) ); + +/* + * Select current ALU operation + */ + +always @* + case( state ) + READ: alu_op = op; + + BRA1: alu_op = backwards ? OP_SUB : OP_ADD; + + FETCH, + REG : alu_op = op; + + DECODE, + ABS1: alu_op = 1'bx; + + PUSH1, + BRK0, + BRK1, + BRK2, + JSR0, + JSR1: alu_op = OP_SUB; + + default: alu_op = OP_ADD; + endcase + +/* + * Determine shift right signal to ALU + */ + +always @* + if( state == FETCH || state == REG || state == READ ) + alu_shift_right = shift_right; + else + alu_shift_right = 0; + +/* + * Sign extend branch offset. + */ + +always @(posedge clk) + if( RDY ) + backwards <= DIMUX[7]; + +/* + * ALU A Input MUX + */ + +always @* + case( state ) + JSR1, + RTS1, + RTI1, + RTI2, + BRK1, + BRK2, + INDX1: AI = ADD; + + REG, + ZPX0, + INDX0, + ABSX0, + RTI0, + RTS0, + JSR0, + JSR2, + BRK0, + PULL0, + INDY1, + PUSH0, + PUSH1: AI = regfile; + + BRA0, + READ: AI = DIMUX; + + BRA1: AI = ABH; // don't use PCH in case we're + + FETCH: AI = load_only ? 0 : regfile; + + DECODE, + ABS1: AI = 8'hxx; // don't care + + default: AI = 0; + endcase + + +/* + * ALU B Input mux + */ + +always @* + case( state ) + BRA1, + RTS1, + RTI0, + RTI1, + RTI2, + INDX1, + READ, + REG, + JSR0, + JSR1, + JSR2, + BRK0, + BRK1, + BRK2, + PUSH0, + PUSH1, + PULL0, + RTS0: BI = 8'h00; + + BRA0: BI = PCL; + + DECODE, + ABS1: BI = 8'hxx; + + default: BI = DIMUX; + endcase + +/* + * ALU CI (carry in) mux + */ + +always @* + case( state ) + INDY2, + BRA1, + ABSX1: CI = CO; + + DECODE, + ABS1: CI = 1'bx; + + READ, + REG: CI = rotate ? C : + shift ? 0 : inc; + + FETCH: CI = rotate ? C : + compare ? 1 : + (shift | load_only) ? 0 : C; + + PULL0, + RTI0, + RTI1, + RTI2, + RTS0, + RTS1, + INDY0, + INDX1: CI = 1; + + default: CI = 0; + endcase + +/* + * Processor Status Register update + * + */ + +/* + * Update C flag when doing ADC/SBC, shift/rotate, compare + */ +always @(posedge clk ) + if( shift && state == WRITE ) + C <= CO; + else if( state == RTI2 ) + C <= DIMUX[0]; + else if( ~write_back && state == DECODE ) begin + if( adc_sbc | shift | compare ) + C <= CO; + else if( plp ) + C <= ADD[0]; + else begin + if( sec ) C <= 1; + if( clc ) C <= 0; + end + end + +/* + * Update Z, N flags when writing A, X, Y, Memory, or when doing compare + */ + +always @(posedge clk) + if( state == WRITE ) + Z <= AZ; + else if( state == RTI2 ) + Z <= DIMUX[1]; + else if( state == DECODE ) begin + if( plp ) + Z <= ADD[1]; + else if( (load_reg & (regsel != SEL_S)) | compare | bit_ins ) + Z <= AZ; + end + +always @(posedge clk) + if( state == WRITE ) + N <= AN; + else if( state == RTI2 ) + N <= DIMUX[7]; + else if( state == DECODE ) begin + if( plp ) + N <= ADD[7]; + else if( (load_reg & (regsel != SEL_S)) | compare ) + N <= AN; + end else if( state == FETCH && bit_ins ) + N <= DIMUX[7]; + +/* + * Update I flag + */ + +always @(posedge clk) + if( state == BRK3 ) + I <= 1; + else if( state == RTI2 ) + I <= DIMUX[2]; + else if( state == REG ) begin + if( sei ) I <= 1; + if( cli ) I <= 0; + end else if( state == DECODE ) + if( plp ) I <= ADD[2]; + +/* + * Update D flag + */ +always @(posedge clk ) + if( state == RTI2 ) + D <= DIMUX[3]; + else if( state == DECODE ) begin + if( sed ) D <= 1; + if( cld ) D <= 0; + if( plp ) D <= ADD[3]; + end + +/* + * Update V flag + */ +always @(posedge clk ) + if( state == RTI2 ) + V <= DIMUX[6]; + else if( state == DECODE ) begin + if( adc_sbc ) V <= AV; + if( clv ) V <= 0; + if( plp ) V <= ADD[6]; + end else if( state == FETCH && bit_ins ) + V <= DIMUX[6]; + +/* + * Instruction decoder + */ + +/* + * IR register/mux. Hold previous DI value in IRHOLD in PULL0 and PUSH0 + * states. In these states, the IR has been prefetched, and there is no + * time to read the IR again before the next decode. + */ + +reg RDY1 = 1; + +always @(posedge clk ) + RDY1 <= RDY; + +always @(posedge clk ) + if( ~RDY && RDY1 ) + DIHOLD <= DI; + +always @(posedge clk ) + if( reset ) + IRHOLD_valid <= 0; + else if( RDY ) begin + if( state == PULL0 || state == PUSH0 ) begin + IRHOLD <= DIMUX; + IRHOLD_valid <= 1; + end else if( state == DECODE ) + IRHOLD_valid <= 0; + end + +assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 : + IRHOLD_valid ? IRHOLD : DIMUX; + +assign DIMUX = ~RDY1 ? DIHOLD : DI; + +/* + * Microcode state machine + */ +always @(posedge clk or posedge reset) + if( reset ) + state <= BRK0; + else if( RDY ) case( state ) + DECODE : + casex ( IR ) + 8'b0000_0000: state <= BRK0; + 8'b0010_0000: state <= JSR0; + 8'b0010_1100: state <= ABS0; // BIT abs + 8'b0100_0000: state <= RTI0; // + 8'b0100_1100: state <= JMP0; + 8'b0110_0000: state <= RTS0; + 8'b0110_1100: state <= JMPI0; + 8'b0x00_1000: state <= PUSH0; + 8'b0x10_1000: state <= PULL0; + 8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI + 8'b1xx0_00x0: state <= FETCH; // IMM + 8'b1xx0_1100: state <= ABS0; // X/Y abs + 8'b1xxx_1000: state <= REG; // DEY, TYA, ... + 8'bxxx0_0001: state <= INDX0; + 8'bxxx0_01xx: state <= ZP0; + 8'bxxx0_1001: state <= FETCH; // IMM + 8'bxxx0_1101: state <= ABS0; // even E column + 8'bxxx0_1110: state <= ABS0; // even E column + 8'bxxx1_0000: state <= BRA0; // odd 0 column + 8'bxxx1_0001: state <= INDY0; // odd 1 column + 8'bxxx1_01xx: state <= ZPX0; // odd 4,5,6,7 columns + 8'bxxx1_1001: state <= ABSX0; // odd 9 column + 8'bxxx1_11xx: state <= ABSX0; // odd C, D, E, F columns + 8'bxxxx_1010: state <= REG; // A, TXA, ... NOP + endcase + + ZP0 : state <= write_back ? READ : FETCH; + + ZPX0 : state <= ZPX1; + ZPX1 : state <= write_back ? READ : FETCH; + + ABS0 : state <= ABS1; + ABS1 : state <= write_back ? READ : FETCH; + + ABSX0 : state <= ABSX1; + ABSX1 : state <= (CO | store | write_back) ? ABSX2 : FETCH; + ABSX2 : state <= write_back ? READ : FETCH; + + INDX0 : state <= INDX1; + INDX1 : state <= INDX2; + INDX2 : state <= INDX3; + INDX3 : state <= FETCH; + + INDY0 : state <= INDY1; + INDY1 : state <= INDY2; + INDY2 : state <= (CO | store) ? INDY3 : FETCH; + INDY3 : state <= FETCH; + + READ : state <= WRITE; + WRITE : state <= FETCH; + FETCH : state <= DECODE; + + REG : state <= DECODE; + + PUSH0 : state <= PUSH1; + PUSH1 : state <= DECODE; + + PULL0 : state <= PULL1; + PULL1 : state <= PULL2; + PULL2 : state <= DECODE; + + JSR0 : state <= JSR1; + JSR1 : state <= JSR2; + JSR2 : state <= JSR3; + JSR3 : state <= FETCH; + + RTI0 : state <= RTI1; + RTI1 : state <= RTI2; + RTI2 : state <= RTI3; + RTI3 : state <= RTI4; + RTI4 : state <= DECODE; + + RTS0 : state <= RTS1; + RTS1 : state <= RTS2; + RTS2 : state <= RTS3; + RTS3 : state <= FETCH; + + BRA0 : state <= cond_true ? BRA1 : DECODE; + BRA1 : state <= (CO ^ backwards) ? BRA2 : DECODE; + BRA2 : state <= DECODE; + + JMP0 : state <= JMP1; + JMP1 : state <= DECODE; + + JMPI0 : state <= JMPI1; + JMPI1 : state <= JMP0; + + BRK0 : state <= BRK1; + BRK1 : state <= BRK2; + BRK2 : state <= BRK3; + BRK3 : state <= JMP0; + + endcase + +/* + * Additional control signals + */ + +always @(posedge clk) + if( reset ) + res <= 1; + else if( state == DECODE ) + res <= 0; + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xx01010, // ASLA, ROLA, LSRA, RORA + 8'b0xxxxx01, // ORA, AND, EOR, ADC + 8'b100x10x0, // DEY, TYA, TXA, TXS + 8'b1010xxx0, // LDA/LDX/LDY + 8'b10111010, // TSX + 8'b1011x1x0, // LDX/LDY + 8'b11001010, // DEX + 8'b1x1xxx01, // LDA, SBC + 8'bxxx01000: // DEY, TAY, INY, INX + load_reg <= 1; + + default: load_reg <= 0; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1110_1000, // INX + 8'b1100_1010, // DEX + 8'b101x_xx10: // LDX, TAX, TSX + dst_reg <= SEL_X; + + 8'b0x00_1000, // PHP, PHA + 8'b1001_1010: // TXS + dst_reg <= SEL_S; + + 8'b1x00_1000, // DEY, DEX + 8'b101x_x100, // LDY + 8'b1010_x000: // LDY #imm, TAY + dst_reg <= SEL_Y; + + default: dst_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1011_1010: // TSX + src_reg <= SEL_S; + + 8'b100x_x110, // STX + 8'b100x_1x10, // TXA, TXS + 8'b1110_xx00, // INX, CPX + 8'b1100_1010: // DEX + src_reg <= SEL_X; + + 8'b100x_x100, // STY + 8'b1001_1000, // TYA + 8'b1100_xx00, // CPY + 8'b1x00_1000: // DEY, INY + src_reg <= SEL_Y; + + default: src_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'bxxx1_0001, // INDY + 8'b10x1_x110, // LDX/STX zpg/abs, Y + 8'bxxxx_1001: // abs, Y + index_y <= 1; + + default: index_y <= 0; + endcase + + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b100x_x1x0, // STX, STY + 8'b100x_xx01: // STA + store <= 1; + + default: store <= 0; + + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xxx_x110, // ASL, ROL, LSR, ROR + 8'b11xx_x110: // DEC/INC + write_back <= 1; + + default: write_back <= 0; + endcase + + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b101x_xxxx: // LDA, LDX, LDY + load_only <= 1; + default: load_only <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b111x_x110, // INC + 8'b11x0_1000: // INX, INY + inc <= 1; + + default: inc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'bx11x_xx01: // SBC, ADC + adc_sbc <= 1; + + default: adc_sbc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'b011x_xx01: // ADC + adc_bcd <= (D | sed); + + default: adc_bcd <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx) + 8'b0xxx_1010: // ASL, ROL, LSR, ROR (acc) + shift <= 1; + + default: shift <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b11x0_0x00, // CPX, CPY (imm/zp) + 8'b11x0_1100, // CPX, CPY (abs) + 8'b110x_xx01: // CMP + compare <= 1; + + default: compare <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b01xx_xx10: // ROR, LSR + shift_right <= 1; + + default: shift_right <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0x1x_1010, // ROL A, ROR A + 8'b0x1x_x110: // ROR, ROL + rotate <= 1; + + default: rotate <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b00xx_xx10: // ROL, ASL + op <= OP_ROL; + + 8'b0010_x100: // BIT zp/abs + op <= OP_AND; + + 8'b01xx_xx10: // ROR, LSR + op <= OP_A; + + 8'b1000_1000, // DEY + 8'b1100_1010, // DEX + 8'b110x_x110, // DEC + 8'b11xx_xx01, // CMP, SBC + 8'b11x0_0x00, // CPX, CPY (imm, zpg) + 8'b11x0_1100: op <= OP_SUB; + + 8'b010x_xx01, // EOR + 8'b00xx_xx01: // ORA, AND + op <= { 2'b11, IR[6:5] }; + + default: op <= OP_ADD; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0010_x100: // BIT zp/abs + bit_ins <= 1; + + default: bit_ins <= 0; + endcase + +/* + * special instructions + */ +always @(posedge clk ) + if( state == DECODE && RDY ) begin + php <= (IR == 8'h08); + clc <= (IR == 8'h18); + plp <= (IR == 8'h28); + sec <= (IR == 8'h38); + cli <= (IR == 8'h58); + sei <= (IR == 8'h78); + clv <= (IR == 8'hb8); + cld <= (IR == 8'hd8); + sed <= (IR == 8'hf8); + brk <= (IR == 8'h00); + end + +always @(posedge clk) + if( RDY ) + cond_code <= IR[7:5]; + +always @* + case( cond_code ) + 3'b000: cond_true = ~N; + 3'b001: cond_true = N; + 3'b010: cond_true = ~V; + 3'b011: cond_true = V; + 3'b100: cond_true = ~C; + 3'b101: cond_true = C; + 3'b110: cond_true = ~Z; + 3'b111: cond_true = Z; + endcase + + +reg NMI_1 = 0; // delayed NMI signal + +always @(posedge clk) + NMI_1 <= NMI; + +always @(posedge clk ) + if( NMI_edge && state == BRK3 ) + NMI_edge <= 0; + else if( NMI & ~NMI_1 ) + NMI_edge <= 1; + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/cpu_wrapper.sv b/Atari - 7800_TeST/rtl/cpu_wrapper.sv new file mode 100644 index 00000000..4e1f5e7c --- /dev/null +++ b/Atari - 7800_TeST/rtl/cpu_wrapper.sv @@ -0,0 +1,65 @@ +`timescale 1ns / 1ps + + +module cpu_wrapper( clk, sysclk, reset, AB, DB_IN, DB_OUT, RD, IRQ, NMI, RDY, halt_b, pc_temp, core_latch_data); + +input clk; // CPU clock +input sysclk; // MARIA Clock +input reset; // reset signal +output [15:0] AB; // address bus +input [7:0] DB_IN; // data in, +output [7:0] DB_OUT; // data_out, +output RD; // read enable +input IRQ; // interrupt request +input NMI; // non-maskable interrupt request +input RDY; // Ready signal. Pauses CPU when RDY=0 +input halt_b; +input core_latch_data; + +output [15:0] pc_temp; + +logic res; +logic rdy_in; +logic WE_OUT; +logic WE, holding; +logic [7:0] DB_hold, DB_into_cpu; + +cpu core(.clk(clk), .reset(reset),.AB(AB),.DI(DB_hold),.DO(DB_OUT),.WE(WE_OUT),.IRQ(IRQ),.NMI(NMI),.RDY(rdy_in), .pc_temp(pc_temp), .res(res)); + +assign RD = ~(WE & ~res & ~reset); +assign WE = WE_OUT & rdy_in; //& ~core_latch_data; +//assign rdy_in = RDY & halt_b; +assign DB_hold = (holding) ? DB_hold : DB_IN; + +//assign DB_into_cpu = (core_latch_data) ? DB_IN : DB_hold; +//assign DB_into_cpu = DB_hold; + + +/*always_ff @(posedge sysclk) begin + if (core_latch_data & rdy_in) begin + DB_hold <= DB_IN; + end +end*/ + +/*always_ff @(posedge clk) begin + if (rdy_in) + DB_hold <= DB_IN; +end*/ + +/*always_ff @(posedge clk, posedge reset) + if (reset) + holding <= 1'b0; + else + holding <= ~rdy_in;*/ + +assign holding = ~rdy_in; + +always_ff @(negedge clk, posedge reset) + if (reset) + rdy_in <= 1'b1; + else if (halt_b & RDY) + rdy_in <= 1'b1; + else + rdy_in <= 1'b0; + +endmodule: cpu_wrapper \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/defender_rom.v b/Atari - 7800_TeST/rtl/defender_rom.v new file mode 100644 index 00000000..0ed1d560 --- /dev/null +++ b/Atari - 7800_TeST/rtl/defender_rom.v @@ -0,0 +1,164 @@ +// megafunction wizard: %ROM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: defender_rom.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module defender_rom ( + address, + clock, + q); + + input [11:0] address; + input clock; + 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), + .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_a ({8{1'b1}}), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_a (1'b0), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", +`ifdef NO_PLI + altsyncram_component.init_file = "../rtl/rom/Defender.rif" +`else + altsyncram_component.init_file = "../rtl/rom/Defender.hex" +`endif +, + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 4096, + altsyncram_component.operation_mode = "ROM", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.widthad_a = 12, + 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: 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 "../rtl/rom/Defender.hex" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +// 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 "12" +// 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 "../rtl/rom/Defender.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 "4096" +// 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 "12" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..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 12 0 address 0 0 12 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 defender_rom.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL defender_rom_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Atari - 7800_TeST/rtl/dma_ctrl.sv b/Atari - 7800_TeST/rtl/dma_ctrl.sv new file mode 100644 index 00000000..18b4ff8d --- /dev/null +++ b/Atari - 7800_TeST/rtl/dma_ctrl.sv @@ -0,0 +1,403 @@ +`timescale 1ns / 1ps + +module dma_ctrl( + output logic [15:0] AddrB, + output logic drive_AB, + input logic [7:0] DataB, + // from memory map + input logic [15:0] ZP, + + output logic palette_w, input_w, pixels_w, + output logic wm_w, + + input logic zp_dma_start, dp_dma_start, dp_dma_kill, + output logic zp_dma_done, dp_dma_done, dp_dma_done_dli, + + input logic character_width, + input logic [7:0] char_base, + + input logic sysclk, reset, last_line +); + logic [15:0] DP; + logic [15:0] DP_saved; + logic [15:0] PP; + logic [15:0] ZP_saved, ZP_saved_next; + logic [15:0] CHAR_PTR; + logic [1:0] char_ptr_cycles; + logic char_bytes_fetched; + logic [4:0] WIDTH; + logic [3:0] OFFSET; + + logic INDIRECT_MODE; + + // control regs + logic DLIen, DLIen_prev, A12en, A11en; + + // states + enum logic [1:0] {waiting = 2'b00, zp_dma = 2'b01, dp_dma = 2'b10} state; + enum logic [2:0] {drive_zp_addr = 3'b000, w_offset = 3'b001, w_DPH = 3'b010 ,w_DPL = 3'b100} zp_state; + enum logic [3:0] {drive_dp_addr = 4'h00, + w_PPL = 4'h01, + w_PALETTE_WIDTH = 4'h02, + w_PPH = 4'h03, + w_PALETTE_WIDTH_2 = 4'h04, + w_INPUT = 4'h05, + drive_pp_addr = 4'h06, + w_PIXELS = 4'h07, + w_PIXELS_slow = 4'h08, + drive_char_addr = 4'h09, + w_CHAR_PTR = 4'ha, + w_CHAR_PIXELS = 4'hb, + drive_next_zp_addr = 4'hc, + w_next_offset = 4'hd, + w_next_DPL = 4'he, + w_next_DPH = 4'hf} dp_state; + + logic five_byte_mode, null_width, null_data, zero_offset; + + logic PP_in_cart; + assign PP_in_cart = |(PP_plus_offset[15:14]); + + logic [7:0] CB_plus_offset; + assign CB_plus_offset = char_base + {4'b0, OFFSET}; + + logic CB_in_cart; + assign CB_in_cart = |(CB_plus_offset[7:6]); + + assign null_width = (DataB[4:0] == 5'b0); + assign null_data = (DataB == 8'b0); + assign zero_offset = (OFFSET == 4'b0); + + assign drive_AB = (state != waiting); + + assign ZP_saved_next = ZP_saved + 1; + + logic [15:0] PP_plus_offset; + assign PP_plus_offset = PP + {4'b0, OFFSET, 8'b0}; + + always_comb begin + AddrB = 'h1234; + wm_w = 0; + palette_w = 0; + input_w = 0; + pixels_w = 0; + case (state) + zp_dma: begin + AddrB = ZP_saved; + end + dp_dma: begin + AddrB = 16'hx; + case (dp_state) + drive_dp_addr: begin + AddrB = DP_saved; + end + + w_PPL: begin + AddrB = DP_saved; + end + + w_PALETTE_WIDTH: begin + AddrB = DP_saved; + if (~null_data) begin + wm_w = null_width; + palette_w = ~null_width; + end + end + + w_PPH: begin + AddrB = DP_saved; + end + + w_PALETTE_WIDTH_2: begin + AddrB = DP_saved; + palette_w = 1; + end + + w_INPUT: begin + AddrB = DP_saved; + input_w = 1; + end + + drive_pp_addr: begin + AddrB = PP_plus_offset; + end + + w_PIXELS: begin + AddrB = PP + 1; + pixels_w = 1; + end + + w_PIXELS_slow: begin + if (char_ptr_cycles == 2'b11) begin + pixels_w = 1; + AddrB = PP + 1; + end else begin + AddrB = PP; + end + end + + drive_char_addr: begin + AddrB = PP; + end + + w_CHAR_PTR: begin + AddrB = {CB_plus_offset, DataB}; + end + + w_CHAR_PIXELS: begin + if (char_ptr_cycles == 2'b11) begin + pixels_w = 1; + if (~char_bytes_fetched & character_width) begin + AddrB = CHAR_PTR + 1; + end else begin + AddrB = PP; + end + end else begin + AddrB = CHAR_PTR; + end + end + + drive_next_zp_addr: begin + AddrB = ZP_saved; + end + w_next_offset: begin + AddrB = ZP_saved; + end + w_next_DPL: begin + AddrB = ZP_saved; + end + w_next_DPH: begin + AddrB = ZP_saved; + end + endcase + end + endcase + end + + always_ff @(posedge sysclk, posedge reset) begin + if (reset) begin + state <= waiting; + zp_state <= drive_zp_addr; + dp_state <= drive_dp_addr; + zp_dma_done <= 0; + dp_dma_done <= 0; + dp_dma_done_dli <= 0; + five_byte_mode <= 0; + INDIRECT_MODE <= 0; + end else begin + case (state) + waiting: begin + if (zp_dma_start) begin + state <= zp_dma; + ZP_saved <= ZP; + end else if (dp_dma_start) begin + state <= dp_dma; + DP_saved <= DP; + end + zp_dma_done <= 0; + dp_dma_done <= 0; + dp_dma_done_dli <= 0; + end + //////////////////////////////////////////////////////////// + zp_dma: begin + case (zp_state) + drive_zp_addr: begin // Read zp + zp_state <= w_offset; + // AddrB = ZP_saved; + ZP_saved <= ZP_saved_next; + end + w_offset: begin //write cbits and offset + zp_state <= w_DPH; + {DLIen,A12en,A11en} <= DataB[7:5]; + OFFSET <= DataB[3:0]; + // AddrB = ZP_saved_next; + ZP_saved <= ZP_saved_next; + end + w_DPH: begin //Write DPH + zp_state <= w_DPL; + DP[15:8] <= DataB; + // AddrB = ZP_saved; + ZP_saved <= ZP_saved_next; + end + w_DPL: begin //Write DPL + zp_state <= drive_zp_addr; + state <= waiting; + DP[7:0] <= DataB; + DP_saved <= {DP[15:8], DataB}; + zp_dma_done <= 1'b1; + dp_dma_done_dli <= DLIen; + end + endcase // case (zp_state) + end // case: zp_dma + + ////////////////////////////////////////////////////////////// + dp_dma: begin + if (dp_dma_kill) begin + dp_state <= drive_dp_addr; + state <= waiting; + dp_dma_done <= 1'b1; + end else case (dp_state) + drive_dp_addr: begin //read from dp + dp_state <= w_PPL; + // AddrB = DP_saved; + DP_saved <= DP_saved+1; + five_byte_mode <= 0; + INDIRECT_MODE <= 0; + end + w_PPL: begin //Write PPL + dp_state <= w_PALETTE_WIDTH; + PP[7:0] <= DataB; + // AddrB = DP_saved; + DP_saved <= DP_saved+1; + end + w_PALETTE_WIDTH: + // Write palette/width or determine 5b + // mode or find end of DP list + if (null_data) begin //Found end of DP list + if (last_line) begin // Found end of frame + dp_state <= drive_dp_addr; + state <= waiting; + dp_dma_done <= 1; + dp_dma_done_dli <= 1'b0; + end else if (zero_offset) begin // Found end of zone, but not end of frame + dp_state <= drive_next_zp_addr; + state <= dp_dma; + end else begin // Not at end of zone or frame. Get ready for next line in zone. + state <= waiting; + dp_state <= drive_dp_addr; + OFFSET <= OFFSET - 1; + dp_dma_done <= 1; + end + end else begin + // Write palette and width or determine its 5b mode + dp_state <= w_PPH; + five_byte_mode <= null_width; + INDIRECT_MODE <= null_width & DataB[5]; + // wm_w <= null_width; + // ind_w <= null_width; + // palette_w <= ~null_width; + WIDTH <= DataB[4:0]; + // AddrB <= DP; + DP_saved <= DP_saved+1; + end + w_PPH: begin //Write PPH + dp_state <= (five_byte_mode) ? w_PALETTE_WIDTH_2 : w_INPUT; + PP[15:8] <= DataB; + // AddrB <= DP; + DP_saved <= DP_saved+1; + end + w_PALETTE_WIDTH_2: begin //Write palette and width for realzies + dp_state <= w_INPUT; + // palette_w <= 1; + WIDTH <= DataB[4:0]; + // AddrB <= DP; + DP_saved <= DP_saved+1; + end + w_INPUT: begin //write INPUT + if (INDIRECT_MODE) begin + dp_state <= drive_char_addr; + end else begin + if ((A12en & PP_plus_offset[12]) | (A11en & PP_plus_offset[11])) + dp_state <= drive_dp_addr; + else + dp_state <= drive_pp_addr; + end + // palette_w <= 0; + // AddrB <= DP; + // input_w <= 1; + end + drive_pp_addr: begin //read from pp + if (PP_in_cart) begin + dp_state <= w_PIXELS_slow; + char_ptr_cycles <= 2'b00; + end else begin + dp_state <= w_PIXELS; + end + WIDTH <= WIDTH+1; + PP <= PP_plus_offset; + end + w_PIXELS: begin //Write Pixel data + PP <= PP + 1; + WIDTH <= WIDTH + 1; + dp_state <= (WIDTH == 5'b0) ? drive_dp_addr : w_PIXELS; + end + w_PIXELS_slow: begin + // Similar to w_CHAR_PIXELS in that we wait 4 cycles, + // but similar to w_PIXELS otherwise + if (char_ptr_cycles == 2'b11) begin + // Data is ready on the data bus + WIDTH <= WIDTH + 1; + PP <= PP + 1; + dp_state <= (WIDTH == 5'b0) ? drive_dp_addr: w_PIXELS_slow; + char_ptr_cycles <= 2'b00; + end else begin + char_ptr_cycles <= char_ptr_cycles + 1; + end + end + drive_char_addr: begin // read character pointer from pp + dp_state <= w_CHAR_PTR; + WIDTH <= WIDTH + 1; + PP <= PP + 1; + end + w_CHAR_PTR: begin + dp_state <= w_CHAR_PIXELS; + CHAR_PTR <= {CB_plus_offset, DataB}; + char_bytes_fetched <= 2'b0; + char_ptr_cycles <= (CB_in_cart) ? 2'b00 : 2'b11; + end + + w_CHAR_PIXELS: begin + if (char_ptr_cycles == 2'b11) begin + if (~char_bytes_fetched & character_width) begin + dp_state <= w_CHAR_PIXELS; + char_bytes_fetched <= 1'b1; + CHAR_PTR <= CHAR_PTR + 1; + end else begin + if (WIDTH == 5'b0) begin + dp_state <= drive_dp_addr; + end else begin + dp_state <= w_CHAR_PTR; + WIDTH <= WIDTH + 1; + PP <= PP + 1; + end + end + end else begin + char_ptr_cycles <= char_ptr_cycles + 1; + end + end + + ///////////////////////////////////////////////// + //Loading next zp when OFFSET has been decremented to 0 + drive_next_zp_addr: begin //Read zp + dp_state <= w_next_offset; + // AddrB <= ZP_saved; + ZP_saved <= ZP_saved_next; + end + w_next_offset: begin //write cbits and offset + dp_state <= w_next_DPH; + DLIen_prev <= DLIen; + {DLIen,A12en,A11en} <= DataB[7:5]; + OFFSET <= DataB[3:0]; + // AddrB <= ZP_saved; + ZP_saved <= ZP_saved_next; + end + w_next_DPH: begin //Write DPH + dp_state <= w_next_DPL; + DP[15:8] <= DataB; + // AddrB <= ZP_saved; + ZP_saved <= ZP_saved_next; + end + w_next_DPL: begin //Write DPH + dp_state <= drive_dp_addr; + state <= waiting; + DP[7:0] <= DataB; + DP_saved <= {DP[15:8], DataB}; + dp_dma_done <= 1; + dp_dma_done_dli <= DLIen; + end + endcase // case (dp_state) + end // case: dp_dma + endcase + end + end // always_ff @ +endmodule // dma_ctrl \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/hq2x.sv b/Atari - 7800_TeST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Atari - 7800_TeST/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/Atari - 7800_TeST/rtl/line_ram.sv b/Atari - 7800_TeST/rtl/line_ram.sv new file mode 100644 index 00000000..9b9b6f88 --- /dev/null +++ b/Atari - 7800_TeST/rtl/line_ram.sv @@ -0,0 +1,261 @@ +`timescale 1ns / 1ps + +// Graphics Mode Definitions +`define GM_160A 3'b000 +`define GM_160B 3'b100 +`define GM_320A 3'b011 +`define GM_320B 3'b110 +`define GM_320C 3'b111 +`define GM_320D 3'b010 + +module line_ram( + input logic SYSCLK, RESET, + output logic [7:0] PLAYBACK, + // Databus inputs + input logic [7:0] INPUT_ADDR, + input logic [2:0] PALETTE, + input logic [7:0] PIXELS, + input logic WM, + // Write enable for databus inputs + input logic PALETTE_W, INPUT_W, PIXELS_W, WM_W, + // Memory mapped registers + input logic [24:0][7:0] COLOR_MAP, + input logic [1:0] READ_MODE, + input logic KANGAROO_MODE, BORDER_CONTROL, + input logic COLOR_KILL, + input logic LRAM_SWAP, + // VGA Control signal + input logic [8:0] LRAM_OUT_COL +); + + logic [159:0][4:0] lram_in, lram_out; + logic rm_in, rm_out; + + logic [7:0] input_addr; + logic [2:0] palette; + logic wm; + + logic [2:0] display_mode; + assign display_mode = {wm, READ_MODE}; + + logic [2:0] playback_palette; + logic [1:0] playback_color; + logic [4:0] playback_cell; + logic [8:0] playback_ix; + logic [7:0] lram_ix; + + assign playback_ix = (LRAM_OUT_COL < 9'd320) ? LRAM_OUT_COL : 9'd0; + + always_comb begin + if (playback_color == 2'b0) begin + PLAYBACK = COLOR_MAP[0]; + end else begin + PLAYBACK = COLOR_MAP[3 * playback_palette + playback_color]; + end + end + + logic [4:0] cell1, cell2, cell3, cell4; + logic [4:0] pcell1, pcell2, pcell3, pcell4; + + assign cell1 = lram_in[input_addr]; + assign cell2 = lram_in[input_addr+1]; + assign cell3 = lram_in[input_addr+2]; + assign cell4 = lram_in[input_addr+3]; + + assign pcell1 = lram_in[input_addr-4]; + assign pcell2 = lram_in[input_addr-3]; + assign pcell3 = lram_in[input_addr-2]; + assign pcell4 = lram_in[input_addr-1]; + + // Assign playback_color and playback_palette based on + // lram_in and playback_ix and display_mode + always_comb begin + lram_ix = playback_ix[8:1]; // 2 pixels per lram cell + playback_cell = lram_out[lram_ix]; + playback_palette = playback_cell[4:2]; // Default to 160A/B + playback_color = playback_cell[1:0]; + casex (rm_out) + 2'b0x: begin + // 160A is read as four double-pixels per byte: + // + // + // + // + // 160B is read as two double-pixels per byte: + // + // + // In both cases, the lineram cells are stored in + // exactly the order specified above. They can be + // read directly. + playback_palette = playback_cell[4:2]; + playback_color = playback_cell[1:0]; + end + 2'b10: begin + // 320B is read as four pixels per byte: + // + // + // + // + // 320B is stored as two cells per byte (wm=1): + // [P2 D3 D2 D7 D6] + // [P2 D1 D0 D5 D4] + // + // 320D is read as eight pixels per byte: + // + // + // + // + // + // + // + // + // 320D is stored as four cells per byte (wm=0): + // [P2 P1 P0 D7 D6] + // [P2 P1 P0 D5 D4] + // [P2 P1 P0 D3 D2] + // [P2 P1 P0 D1 D0] + // + // In both cases, the palette is always + // For a given pair of pixels, the color selectors + // are, from left to right, and + // Example: Either D7,D3:D6,D2 (320B) or D7,P1:D6,P0 (320D) + playback_palette = {playback_cell[4], 2'b0}; + if (playback_ix[0]) begin + // Right pixel + playback_color = {playback_cell[0], playback_cell[2]}; + end else begin + // Left pixel + playback_color = {playback_cell[1], playback_cell[3]}; + end + end + 2'b11: begin + // 320A is read as eight pixels per byte: + // + // + // + // + // + // + // + // + // 320A is stored as four cells per byte (wm=0): + // [P2 P1 P0 D7 D6] + // [P2 P1 P0 D5 D4] + // [P2 P1 P0 D3 D2] + // [P2 P1 P0 D1 D0] + // + // 320C is read as four pixels per byte: + // + // + // + // + // 320C is stored as two cells per byte (wm=1): + // [P2 D3 D2 D7 D6] + // [P2 D1 D0 D5 D4] + // + // In both cases, the palette is always + // For a given pair of pixels, the color selectors + // are, from left to right, and + playback_palette = playback_cell[4:2]; + if (playback_ix[0]) begin + // Right pixel + playback_color = {playback_cell[0], 1'b0}; + end else begin + // Left pixel + playback_color = {playback_cell[1], 1'b0}; + end + end + endcase + end + + always_ff @(posedge SYSCLK, posedge RESET) begin + if (RESET) begin + input_addr <= 8'b0; + palette <= 3'b0; + wm <= 1'b0; + lram_in <= 800'd0; + lram_out <= 800'd0; + end else begin + input_addr <= INPUT_W ? INPUT_ADDR : input_addr; + palette <= PALETTE_W ? PALETTE : palette; + wm <= WM_W ? WM : wm; + if (LRAM_SWAP) begin + lram_in <= 800'd0; // All background color + lram_out <= lram_in; + rm_out <= rm_in; + end + if (PIXELS_W) begin + // Load PIXELS byte into lram_in + rm_in <= READ_MODE; + case (wm) + 1'b0: begin + // "When wm = 0, each byte specifies four pixel cells + // of the lineram" + // This encompasses: + // 160A: + // [P2 P1 P0 D7 D6] + // [P2 P1 P0 D5 D4] + // [P2 P1 P0 D3 D2] + // [P2 P1 P0 D1 D0] + // 320A: + // [P2 P1 P0 D7 0] + // [P2 P1 P0 D6 0] + // [P2 P1 P0 D5 0] + // [P2 P1 P0 D4 0] + // [P2 P1 P0 D3 0] + // [P2 P1 P0 D2 0] + // [P2 P1 P0 D1 0] + // [P2 P1 P0 D0 0] + // 320D: + // [P2 0 0 D7 P1] + // [P2 0 0 D6 P0] + // [P2 0 0 D5 P1] + // [P2 0 0 D4 P0] + // [P2 0 0 D3 P1] + // [P2 0 0 D2 P0] + // [P2 0 0 D1 P1] + // [P2 0 0 D0 P0] + // These can all be written into the cells using + // the same format and read out differently. + input_addr <= input_addr + 4; + if (|PIXELS[7:6]) + lram_in[input_addr+0] <= {palette, PIXELS[7:6]}; + if (|PIXELS[5:4]) + lram_in[input_addr+1] <= {palette, PIXELS[5:4]}; + if (|PIXELS[3:2]) + lram_in[input_addr+2] <= {palette, PIXELS[3:2]}; + if (|PIXELS[1:0]) + lram_in[input_addr+3] <= {palette, PIXELS[1:0]}; + end + 1'b1: begin + // "When wm = 1, each byte specifies two cells within the lineram." + // This encompasses: + // 160B: + // [P2 D3 D2 D7 D6] + // [P2 D1 D0 D5 D4] + // 320B: + // [P2 0 0 D7 D3] + // [P2 0 0 D6 D2] + // [P2 0 0 D5 D1] + // [P2 0 0 D4 D0] + // 320C: + // [P2 D3 D2 D7 0] + // [P2 D3 D2 D6 0] + // [P2 D1 D0 D5 0] + // [P2 D1 D0 D4 0] + // Again, these can be written into the cells in + // the same format and read out differently. Note: + // transparency may not be correct in 320B mode here + // since the color bits are different than 160B and 320C. + input_addr <= input_addr + 2; + if (|PIXELS[7:6]) + lram_in[input_addr+0] <= {palette[2], PIXELS[3:2], PIXELS[7:6]}; + if (|PIXELS[5:4]) + lram_in[input_addr+1] <= {palette[2], PIXELS[1:0], PIXELS[5:4]}; + end + endcase + end + end + end + +endmodule diff --git a/Atari - 7800_TeST/rtl/maria.sv b/Atari - 7800_TeST/rtl/maria.sv new file mode 100644 index 00000000..2f30002d --- /dev/null +++ b/Atari - 7800_TeST/rtl/maria.sv @@ -0,0 +1,178 @@ +`timescale 1ns / 1ps +`include "atari7800.vh" + + +module maria( + // Busses ("tristate") + input logic [15:0] AB_in, + output logic [15:0] AB_out, + output logic drive_AB, + + input logic [7:0] read_DB_in, + input logic [7:0] write_DB_in, + output logic [7:0] DB_out, + // inout wire [15:0] AB, + // inout wire [ 7:0] DB, + //inout wire [7:0] DB, + //inout wire [15:0] AB, + + // Clocking + input logic reset, + input logic sysclk, pclk_2, + output logic tia_clk, pclk_0, sel_slow_clock, + + // Memory Map Select lines + output `chipselect CS, + input logic bios_en, + input logic tia_en, + //output logic ram0_b, ram1_b, p6532_b, tia_b, + //output logic riot_ram_b, + + // Maria configuration + input logic RW, enable, + + // VGA Interface + input logic [9:0] vga_row, vga_col, + output logic [7:0] UV_out, + + // Outputs to 6502 + output logic int_b, halt_b, ready, core_latch_data +); + + // Bus interface + // Defined as ports. + //logic drive_AB; + //logic [15:0] AB_in, AB_out; + //logic drive_DB; + //logic [7:0] DB_in, DB_out; + //assign DB = drive_DB ? DB_out : 'bz; + //assign AB = drive_AB ? AB_out : 'bz; + //assign DB_in = DB; + //assign AB_in = AB; + + // For testing DMA. + //assign DB_in = DB; + //assign AB = AB_out; + //assign AB_in = AB_out; + + //// Memory Mapped Registers + // Control register format: + // {CK, DM1, DM0, CW, BC, KM, RM1, RM0} + // CK: Color Kill + // {DM1, DM0}: DMA Control. 0: Test A. 1: Test B. + // 2: Normal DMA. 3: No DMA. + // CW: Character Width (For indirect mode). 0=>2bytes. 1=>1byte. + // BC: Border Control: 0=>Background Color. 1=>Black Border. + // KM: Kangaroo Mode: 0=>Transparency, 1=>No transparency + // {RM1, RM0}: Read mode. + logic [7:0] ctrl; + logic [24:0][7:0] color_map; + logic [7:0] char_base; + logic [15:0] ZP; + + //// Signals from memory_map to timing_ctrl + logic deassert_ready, zp_written; + + // Write enables for internal Display List registers + logic palette_w, input_w, pixels_w, wm_w; + + //// Control signals between timing_ctrl and dma_ctrl + logic zp_dma_start, dp_dma_start; + logic zp_dma_done, dp_dma_done; + // When dp_dma_done is asserted, use this signal to specify + // whether timing_ctrl needs to raise a display list interrupt + logic dp_dma_done_dli; + // If a DMA is taking too long (too many objects,) kill it + logic dp_dma_kill; + // Next-line ZP DMA not needed at end of DP DMA + logic last_line; + + //// Control signals between timing_ctrl and line_ram + logic lram_swap; + + logic VBLANK; + + line_ram line_ram_inst( + .SYSCLK(sysclk), .RESET(reset), + .PLAYBACK(UV_out), + // Databus inputs + .INPUT_ADDR(read_DB_in), .PALETTE(read_DB_in[7:5]), .PIXELS(read_DB_in), + .WM(read_DB_in[7]), + // Write enable for databus inputs + .PALETTE_W(palette_w), .INPUT_W(input_w), .PIXELS_W(pixels_w), + .WM_W(wm_w), + // Memory mapped registers + .COLOR_MAP(color_map), + .READ_MODE(ctrl[1:0]), + .KANGAROO_MODE(ctrl[2]), + .BORDER_CONTROL(ctrl[3]), + .COLOR_KILL(ctrl[7]), + // Control signals from timing_ctrl + .LRAM_SWAP(lram_swap), + .LRAM_OUT_COL(vga_col[9:1]) + ); + + timing_ctrl timing_ctrl_inst( + // Enabled only if men is asserted and display mode is 10 + .enable(enable & ctrl[6] & ~ctrl[5]), + // Clocking + .sysclk(sysclk), .reset(reset), .pclk_2(pclk_2), + .pclk_0(pclk_0), .tia_clk(tia_clk), + // Signals needed to slow pclk_0 + .sel_slow_clock(sel_slow_clock), + // Outputs to 6502 + .halt_b(halt_b), .int_b(int_b), .ready(ready), .core_latch_data(core_latch_data), + .VBLANK(VBLANK), + // Signals to/from dma_ctrl + .zp_dma_start(zp_dma_start), .dp_dma_start(dp_dma_start), + .zp_dma_done(zp_dma_done), .dp_dma_done(dp_dma_done), + .dp_dma_done_dli(dp_dma_done_dli), + .dp_dma_kill(dp_dma_kill), .last_line(last_line), + // Signals to/from line_ram + .lram_swap(lram_swap), + // Signals to/from VGA + .vga_row(vga_row), .vga_col(vga_col), + // Signals from memory map + .deassert_ready(deassert_ready), + .zp_written(zp_written) + ); + + memory_map memory_map_inst( + .maria_en(enable), + .tia_en(tia_en), + .AB(AB_in), + .DB_in(write_DB_in), .DB_out(DB_out), + //.drive_DB(drive_DB), + .halt_b(halt_b), .we_b(RW), + //.tia_b(tia_b), .p6532_b(p6532_b), + //.ram0_b(ram0_b), .ram1_b(ram1_b), + //.riot_ram_b(riot_ram_b), + .cs(CS), .bios_en(bios_en), + .drive_AB(drive_AB), + .ctrl(ctrl), + .color_map(color_map), + .status_read({VBLANK, 7'b0}), + .char_base(char_base), + .ZP(ZP), + .sel_slow_clock(sel_slow_clock), + .deassert_ready(deassert_ready), + .zp_written(zp_written), + .sysclock(sysclk), .reset_b(~reset), + .pclk_0(pclk_0), .pclk_2(pclk_2) + ); + + dma_ctrl dma_ctrl_inst ( + .AddrB(AB_out), .drive_AB(drive_AB), + .DataB(read_DB_in), .ZP(ZP), + .palette_w(palette_w), .input_w(input_w), .pixels_w(pixels_w), + .wm_w(wm_w), + .zp_dma_start(zp_dma_start), .dp_dma_start(dp_dma_start), + .dp_dma_kill(dp_dma_kill), + .zp_dma_done(zp_dma_done), .dp_dma_done(dp_dma_done), + .dp_dma_done_dli(dp_dma_done_dli), + .sysclk(sysclk), .reset(reset), + .last_line(last_line), + .character_width(ctrl[4]), .char_base(char_base) + ); + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/memory_map.sv b/Atari - 7800_TeST/rtl/memory_map.sv new file mode 100644 index 00000000..2c993781 --- /dev/null +++ b/Atari - 7800_TeST/rtl/memory_map.sv @@ -0,0 +1,232 @@ +`timescale 1ns / 1ps + +`include "atari7800.vh" + +module memory_map ( + input logic maria_en, + input logic tia_en, + input logic [15:0] AB, + input logic [7:0] DB_in, + output logic [7:0] DB_out, + input logic halt_b, we_b, + + output `chipselect cs, + input logic bios_en, + input logic drive_AB, + + output logic [7:0] ctrl, + output logic [24:0][7:0] color_map, + input logic [7:0] status_read, + output logic [7:0] char_base, + output logic [15:0] ZP, + + // whether to slow pclk_0 for slow memory accesses + output logic sel_slow_clock, + + // when wait_sync is written to, ready is deasserted + output logic deassert_ready, zp_written, + + input logic sysclock, reset_b, pclk_0, pclk_2 +); + + logic [3:0] signals_out; + + // Internal Memory Mapped Registers + logic [7:0] ZPH, ZPL; + logic [7:0] wait_sync; + + logic [7:0] read_addr_found, write_addr_found; + + (* KEEP = "true" *) + logic [7:0] ctrl_kept; + + assign sel_slow_clock = (drive_AB) ? 1'b0 : ((tia_en) ? 1'b1 : ((cs == `CS_TIA) || (cs == `CS_RIOT_IO) || (cs == `CS_RIOT_RAM))); + + assign ZP = {ZPH, ZPL}; + logic [1:0] zp_byte_written; + + assign zp_written = &zp_byte_written; + + always_comb begin + // Generate Chip Select (cs) Signal + cs = `CS_CART; + + if (~tia_en) casex (AB) + // RIOT RAM: "Do Not Use" in 7800 mode. + 16'b0000_010x_1xxx_xxxx: cs = `CS_RIOT_RAM; + 16'b0000_0010_1xxx_xxxx: cs = `CS_RIOT_IO; + + // 1800-1FFF: 2K RAM. + 16'b0001_1xxx_xxxx_xxxx: cs = `CS_RAM1; + + // 0040-00FF: Zero Page (Local variable space) + // 0140-01FF: Stack + 16'b0000_000x_01xx_xxxx, + 16'b0000_000x_1xxx_xxxx, + + // 2000-27FF: 2K RAM. Zero Page and Stack mirrored from here. + 16'b001x_xxxx_xxxx_xxxx: cs = `CS_RAM0; + + // TIA Registers: + // 0000-001F, 0100-001F, 0200-021F, 0300-031F + // All mirrors are ranges of the same registers + 16'b0000_00xx_000x_xxxx: cs = `CS_TIA; + + // MARIA Registers: + // 0020-003F, 0120-003F, 0220-023F, 0320-033F + // All ranges are mirrors of the same registers + 16'b0000_00xx_001x_xxxx: cs = `CS_MARIA; + + endcase else casex (AB) + 16'bxxx0_xx0x_1xxx_xxxx: cs = `CS_RIOT_RAM; + 16'bxxx0_xx1x_1xxx_xxxx: cs = `CS_RIOT_IO; + 16'bxxx0_xxxx_0xxx_xxxx: cs = `CS_TIA; + endcase + + if (bios_en & AB[15]) + cs = `CS_BIOS; + + // If MARIA is selected, handle memory mapped registers + if (cs == `CS_MARIA) begin + if (we_b) begin + read_addr_found = AB[7:0]; + write_addr_found = 8'h0; + end + else begin + write_addr_found = AB[7:0]; + read_addr_found = 8'h0; + end + end else begin + read_addr_found = 8'h0; + write_addr_found = 8'h0; + end + + /* + //Find write addresses on bus to latch data on next tick + casex ({AB, we_b}) + {16'b0000_00xx_001x_xxxx,1'b0}: wr_addr_found = AB[7:0]; + default: wr_addr_found = 8'b0; + endcase + + casex ({AB, we_b}) + {16'b0000_00xx_001x_xxxx,1'b1}: read_addr_found = AB[7:0]; + default: read_addr_found = 8'b0; + endcase + */ + + + end // always_comb + + always_ff @(posedge pclk_0, negedge reset_b) begin + if (~reset_b) begin + ctrl <= {1'b0, 2'b10, 1'b0, 1'b0, 1'b0, 2'b00}; // 8'b0 + ctrl_kept <= 8'b0; + //color_map <= 200'b0; + //////// TESTING COLOR MAP ///////// + // Background + color_map[0] <= 8'h0c; + // Palette 0 + color_map[3:1] <= {8'h32, 8'h55, 8'h55}; + // Palette 1 + color_map[6:4] <= {8'h83, 8'h55, 8'h55}; + // Palette 2 + color_map[9:7] <= {8'h1c, 8'h55, 8'h55}; + // Palette 3 + color_map[12:10] <= {8'h25, 8'h55, 8'h55}; + // Palette 4 + color_map[15:13] <= {8'hda, 8'h55, 8'h55}; + + color_map[24:16] <= 'b0; + + wait_sync <= 8'b0; + char_base <= 8'b0; + {ZPH,ZPL} <= {8'h18, 8'h20}; + zp_byte_written <= 2'b0; + end + + else begin + ctrl_kept <= ctrl; + deassert_ready <= 1'b0; + //Handle writes to mem mapped regs + case(write_addr_found) + 8'h20: color_map[0] <= DB_in; + 8'h21: color_map[1] <= DB_in; + 8'h22: color_map[2] <= DB_in; + 8'h23: color_map[3] <= DB_in; + 8'h24: begin + wait_sync <= DB_in; + deassert_ready <= 1'b1; + end + 8'h25: color_map[4] <= DB_in; + 8'h26: color_map[5] <= DB_in; + 8'h27: color_map[6] <= DB_in; + //8'h28: status_read <= DB_in; Read only + 8'h29: color_map[7] <= DB_in; + 8'h2a: color_map[8] <= DB_in; + 8'h2b: color_map[9] <= DB_in; + 8'h2c: begin + ZPH <= DB_in; + zp_byte_written[1] <= 1'b1; + end + 8'h2d: color_map[10] <= DB_in; + 8'h2e: color_map[11] <= DB_in; + 8'h2f: color_map[12] <= DB_in; + 8'h30: begin + ZPL <= DB_in; + zp_byte_written[0] <= 1'b1; + end + 8'h31: color_map[13] <= DB_in; + 8'h32: color_map[14] <= DB_in; + 8'h33: color_map[15] <= DB_in; + 8'h34: char_base <= DB_in; + 8'h35: color_map[16] <= DB_in; + 8'h36: color_map[17] <= DB_in; + 8'h37: color_map[18] <= DB_in; + //8'h38: NOT USED + 8'h39: color_map[19] <= DB_in; + 8'h3a: color_map[20] <= DB_in; + 8'h3b: color_map[21] <= DB_in; + 8'h3c: ctrl <= DB_in; + 8'h3d: color_map[22] <= DB_in; + 8'h3e: color_map[23] <= DB_in; + 8'h3f: color_map[24] <= DB_in; + default: ; + endcase // case (wr_addr_found) + + case(read_addr_found) + 8'h20: DB_out <= color_map[0]; + 8'h21: DB_out <= color_map[1]; + 8'h22: DB_out <= color_map[2]; + 8'h23: DB_out <= color_map[3]; + 8'h25: DB_out <= color_map[4]; + 8'h26: DB_out <= color_map[5]; + 8'h27: DB_out <= color_map[6]; + 8'h28: DB_out <= status_read; + 8'h29: DB_out <= color_map[7]; + 8'h2a: DB_out <= color_map[8]; + 8'h2b: DB_out <= color_map[9]; + 8'h2c: DB_out <= ZPH; + 8'h2d: DB_out <= color_map[10]; + 8'h2e: DB_out <= color_map[11]; + 8'h2f: DB_out <= color_map[12]; + 8'h30: DB_out <= ZPL; + 8'h31: DB_out <= color_map[13]; + 8'h32: DB_out <= color_map[14]; + 8'h33: DB_out <= color_map[15]; + 8'h34: DB_out <= char_base; + 8'h35: DB_out <= color_map[16]; + 8'h36: DB_out <= color_map[17]; + 8'h37: DB_out <= color_map[18]; + //8'h38: NOT USED + 8'h39: DB_out <= color_map[19]; + 8'h3a: DB_out <= color_map[20]; + 8'h3b: DB_out <= color_map[21]; + 8'h3c: DB_out <= ctrl; + 8'h3d: DB_out <= color_map[22]; + 8'h3e: DB_out <= color_map[23]; + 8'h3f: DB_out <= color_map[24]; + default: DB_out <= 8'hbe; + endcase // case (wr_addr_found) + end // else: !if(~reset_b) + end // always_ff @ +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/mist_io.sv b/Atari - 7800_TeST/rtl/mist_io.sv new file mode 100644 index 00000000..ab9ef8ad --- /dev/null +++ b/Atari - 7800_TeST/rtl/mist_io.sv @@ -0,0 +1,532 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + + // ARM -> FPGA download + input ioctl_force_erase, + output reg ioctl_download = 0, // signal indicating an active download + output reg ioctl_erasing = 0, // signal indicating an active erase + output reg [7:0] ioctl_index, // menu index used to upload the file + output reg ioctl_wr = 0, + output reg [24:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [7:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [24:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [24:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + case(ioctl_index) + 0: addr <= 'h080000; // BOOT ROM + 'h01: addr <= 'h000100; // ROM file + 'h41: addr <= 'h000100; // COM file + 'h81: addr <= 'h000000; // C00 file + 'hC1: addr <= 'h010000; // EDD file + default: addr <= 'h100000; // FDD file + endcase + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +reg [24:0] erase_mask; +wire [24:0] next_erase = (ioctl_addr + 1'd1) & erase_mask; + +always@(posedge clk_sys) begin + reg rclkD, rclkD2; + reg old_force = 0; + reg [5:0] erase_clk_div; + reg [24:0] end_addr; + reg erase_trigger = 0; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wr <= 0; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wr <= 1; + end + + if(ioctl_download) begin + old_force <= 0; + ioctl_erasing <= 0; + erase_trigger <= (ioctl_index == 1); + end else begin + + old_force <= ioctl_force_erase; + + // start erasing + if(erase_trigger) begin + erase_trigger <= 0; + erase_mask <= 'hFFFF; + end_addr <= 'h0100; + erase_clk_div <= 1; + ioctl_erasing <= 1; + end else if((ioctl_force_erase & ~old_force)) begin + erase_trigger <= 0; + ioctl_addr <= 'h1FFFFFF; + erase_mask <= 'h1FFFFFF; + end_addr <= 'h0050000; + erase_clk_div <= 1; + ioctl_erasing <= 1; + end else if(ioctl_erasing) begin + erase_clk_div <= erase_clk_div + 1'd1; + if(!erase_clk_div) begin + if(next_erase == end_addr) ioctl_erasing <= 0; + else begin + ioctl_addr <= next_erase; + ioctl_dout <= 0; + ioctl_wr <= 1; + end + end + end + end +end + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/osd.sv b/Atari - 7800_TeST/rtl/osd.sv new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Atari - 7800_TeST/rtl/osd.sv @@ -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/Atari - 7800_TeST/rtl/pll.v b/Atari - 7800_TeST/rtl/pll.v new file mode 100644 index 00000000..e38a7e4c --- /dev/null +++ b/Atari - 7800_TeST/rtl/pll.v @@ -0,0 +1,376 @@ +// 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.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + c2, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output c2; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire7 = 1'h0; + wire [2:2] sub_wire4 = sub_wire0[2:2]; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire c2 = sub_wire4; + wire sub_wire5 = inclk0; + wire [1:0] sub_wire6 = {sub_wire7, sub_wire5}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire6), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 27, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 25, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 189, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 50, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 108, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 25, + altpll_component.clk2_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "27" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "189" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "108" +// 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 "25.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "7.142857" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "6.250000" +// 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 "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 "25" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "50" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "25" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "7.14300000" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "6.25000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: 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 "27" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "25" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "189" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "108" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "25" +// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.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/Atari - 7800_TeST/rtl/ram2k.v b/Atari - 7800_TeST/rtl/ram2k.v new file mode 100644 index 00000000..a57abe06 --- /dev/null +++ b/Atari - 7800_TeST/rtl/ram2k.v @@ -0,0 +1,177 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: ram2k.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module ram2k ( + address, + clken, + clock, + data, + wren, + q); + + input [10:0] address; + input clken; + input clock; + input [7:0] data; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clken; + 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), + .clocken0 (clken), + .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), + .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 = "NORMAL", + altsyncram_component.clock_enable_output_a = "NORMAL", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2048, + 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 = 11, + 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 "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1" +// Retrieval info: PRIVATE: Clken NUMERIC "1" +// 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 "2048" +// 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 "11" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "NORMAL" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "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 "11" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" +// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC "clken" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: 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 11 0 address 0 0 11 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @clocken0 0 0 0 0 clken 0 0 0 0 +// Retrieval info: CONNECT: @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 ram2k.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram2k_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Atari - 7800_TeST/rtl/riot.vh b/Atari - 7800_TeST/rtl/riot.vh new file mode 100644 index 00000000..74090777 --- /dev/null +++ b/Atari - 7800_TeST/rtl/riot.vh @@ -0,0 +1,26 @@ +/* Atari on an FPGA +Masters of Engineering Project +Cornell University, 2007 +Daniel Beer + RIOT.h +Header file that contains useful definitions for the RIOT module. +*/ +`define READ_RAM 7'b01xxxxx +`define WRITE_RAM 7'b00xxxxx +`define READ_DRA 7'b11xx000 +`define WRITE_DRA 7'b10xx000 +`define READ_DDRA 7'b11xx001 +`define WRITE_DDRA 7'b10xx001 +`define READ_DRB 7'b11xx010 +`define WRITE_DRB 7'b10xx010 +`define READ_DDRB 7'b11xx011 +`define WRITE_DDRB 7'b10xx011 +`define WRITE_TIMER 7'b101x1xx +`define READ_TIMER 7'b11xx1x0 +`define READ_INT_FLAG 7'b11xx1x1 +`define WRITE_EDGE_DETECT 7'b100x1x0 +`define NOP 7'b0100000 +`define TM_1 2'b00 +`define TM_8 2'b01 +`define TM_64 2'b10 +`define TM_1024 2'b11 \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/rom/7800ntsc.hex b/Atari - 7800_TeST/rtl/rom/7800ntsc.hex new file mode 100644 index 00000000..3bec21bc --- /dev/null +++ b/Atari - 7800_TeST/rtl/rom/7800ntsc.hex @@ -0,0 +1,257 @@ +:10000000486CF400FFFFFFFFFFFFFFFFFFFFFFFF54 +:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 +:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 +:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF +:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF +:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF +:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF +:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF +:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F +:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F +:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F +:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F +:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F +:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F +:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F +:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F +:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F +:1001F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F +:10020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:10021000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:10022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:1002B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:1002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:1002D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:1002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:1002F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:10030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:1003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:1003D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:1003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:1003F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:100400004CC2264CC226A9168501A0FFA27FBD00C2 +:10041000FED980FDD0EA88CA10F4ADFCFF2DFDFFA7 +:10042000C9FFF0DCADFCFF0DFDFFF0D4ADF8FF0916 +:10043000FEC9FFD0CEADF8FF49F029F0D0C5ADF927 +:10044000FF290BC903D0BCADF9FF29F085EE8D065D +:1004500024C94090AEE901CDFDFFB0A7203625A903 +:100460000085F0201B24A9168501A2008A9D001892 +:10047000CAD0FA48A07FB900FF99001888C0F8D008 +:10048000F5A92E8D0924A9248D0A24201B24682077 +:10049000FF2348EE0624AD0624C9FFD0EE201B241E +:1004A000201224201224A9368D0924A9248D0A247F +:1004B000CE0624201B246820FF2348CE0624AD0648 +:1004C00024C5EEB0EEA960853CA277BD00185D5052 +:1004D000185D88189D001ACA10F1AD001A29078D01 +:1004E000001AA900A2049D001A9D0020A277BD0059 +:1004F00020DD001AD006CA10F54CB9264CC226A23F +:10050000007D00187D00FFA8B9D52D9D0018E8D00A +:10051000F060A2003E0018E8D0FA6008C6F0100CA7 +:10052000A9028501A5F030FCA91685012860C765E0 +:10053000ABCAEEF78309E1D0926762B672558E912D +:10054000DCC581BE782059B7E63D0645AFC8083105 +:1005500038D1FB7384A917FC3487A394FA90B8EDC3 +:10056000CE3B5B0A43D9F35382B30D6D5A609D5164 +:10057000A7B91110BCE47F8041E7E3F6562635ECBD +:10058000D6DF0C7FF49EAC5246EFCFBFA23FA41340 +:1005900015974A1CB0428CB105588018772B023E43 +:1005A000A8491A6ACB6E0B8AEBF14F14798BD89F4E +:1005B0009B5719F82A2D760EE82E4BF90703DE9388 +:1005C000167ED4E5B2F07D7ADAD2A1CC1DE05E23AE +:1005D000A095221E3685FE1F39AA8996AD0F2FC021 +:1005E00047275D24EAC3A5F5215F1B408FAE742524 +:1005F000DDC17CCDA670D7337B2C75BB8699BD54ED +:100600009A6C6332484C8DBA5C61C44E293712C66D +:10061000989CD5696BE2044DE9C2883ADB640144D9 +:100620006FB5F23028FD50713CB46668C9D3CA83F7 +:10063000C7ABF76509EEA27786E486E5BD80FF9D2E +:1006400001199D0020CA10F4A90285012084FB2015 +:100650007B25C6F2A27786E4BDD5FE9D0119CA109E +:10066000F7A5E185E320E125C6F2A5E08D7225A27C +:1006700077BD00189D0020CA10F760203926A4E538 +:10068000C884E1981865E248AAA9008D71269D00EA +:1006900018CAD0FA8D0018C88C6E268C74268C7CF3 +:1006A000268C8126A200CE6E26CE7426CE7C26CE47 +:1006B0008126C6E1301BA4E1B900203DD925F0090F +:1006C000BD62268D7226206A26E8E00830E84CA438 +:1006D000256885E1A90185E0600102040810204039 +:1006E00080203926A5E338E5E485E085E1A2008E87 +:1006F00000188E8F268EAC26CA8EA9268E8C268E4A +:1007000092268E9A268E9F26A207EEA926EE8C268A +:10071000EE9226EE9A26EE9F26C6E13017BD62269F +:100720008D90268DAD2620A6269003208826CA10FF +:10073000EC4C0826A5E385E160A6E4E886E2A0008B +:100740008C0019B962268D5526C8B962268D5926A6 +:10075000A6E218BD00192A9D0019CA10F6C007307C +:10076000E260191A1B1C1D1E1F21A4E218B90018F3 +:100770007900199900188810F4900CB900176900D5 +:10078000990017884C792660A4E238B90018F9005E +:10079000199900188810F4B00CB90017E9009900F5 +:1007A00017884C972660A000B90018D90019F001ED +:1007B00060C4E2F0FBC84CA826A21686019AF86C29 +:1007C000FCFFA9028501A27FBDD4F79D8004CA1059 +:1007D000F74C8004A900AA85019503E8E02AD0F926 +:1007E0008502A904EA3023A204CA10FD9A8D1001E3 +:1007F00020CB0420CB048511851B851C850FEA8541 +:1008000002A900EA300424033009A90285098D12E7 +:10081000F1D01E2402300CA90285068D18F18D60DE +:10082000F4D00E852CA908851B20CB04EA240230C5 +:10083000D9A9FD85086CFCFFEAFFFFFFFFFFFFFF62 +:10084000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 +:10085000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 +:10086000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 +:10087000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 +:10088000A91D850178D8A9028501A9FB85F5A912C2 +:1008900085F4A97F853CA9008520A205BD1DF9A08E +:1008A00000990020D90020D027990021D90021D01B +:1008B0001F88D0EDCA10E5A9438D8020C580D00BDC +:1008C0008D8021CD8001D0034C38F9A0044C80F8F4 +:1008D0008D0018CD0018D00AA0014C80F8A0024C61 +:1008E00080F8A0034C80F8A90085F085F2A0078469 +:1008F000F4B923F985F1B92BF985F3A205BD1DF9EA +:10090000A00091F0D1F0D0D091F2D1F2D0CF88D028 +:10091000F1CA10E9C6F4A4F410D74C17FB00FF5538 +:10092000AA690F222324252627222318191A1B1C03 +:100930001D1E1FA0004C80F8A9AAF0F710F5300387 +:100940004C33F9D0034C33F985AAC5AAD0E5A900E8 +:10095000D0E130DF10034C33F9F0034C33F9C90018 +:10096000D0D190CFB0034C33F9C901B0C690034C3D +:1009700033F9A255E056F0BB8EAA01ECAA01D0B320 +:10098000A4AAC0ABF0AD8C5501CC5501D0A5CA9A34 +:10099000E868C9AAD0558A48EC5501D04E98C9AA32 +:1009A000D049AABD0001A8C055D040B500C5AAD005 +:1009B0003AC9AAD03649FF990000C555D02DD900B3 +:1009C00001D028DDAB20D023A92085F1A9CC85F06A +:1009D0008146C5CCD01591F0CD2121D00EA9EE8550 +:1009E000F0A9F985F16CF0004CEBF94C33F9A955FD +:1009F000186955EAB0F510F3F0F1C9AAD0ED6955C0 +:100A0000EA90E830E6D0E4E955B0E010DEF0DCC969 +:100A1000ABD0D818E9AA90D330D1D0CFA9FFAAE89B +:100A2000D036CAF0331031E0FFD02DA8C8D02988C5 +:100A3000F026C8D02385F0E6F0D01DC4F0D019C64A +:100A4000F0F015C5F0D011A9AA182A2A2AC952D047 +:100A5000076A6A6AC9AAF0034C33F90A90FA0AB025 +:100A6000F70AC950D0F249054A90ED4AB0EA4AC99E +:100A70000AD0E5A955091BC95FD0DD2955291BC935 +:100A800011D0D50955491BC94ED0CD2091FA4C58EB +:100A9000FABAE052D0C268C98DD0BD68C9FAD0B8E0 +:100AA000A9F848A9E648604C58FA8A48A943853C09 +:100AB000A20FA5EF852224F3500610028524852479 +:100AC000852438E910C910B002E90F8522CA10EC5C +:100AD000A240863C29F0090E8527A5EF29F00906DA +:100AE000852529F01869409002690F09038526C6FB +:100AF000F11019A5F369609011A5EF186910900223 +:100B0000690F85EFA5F285F1A90085F3A90285F0AB +:100B100068AA68404C14FBA2FF9AA900AA9501E8B4 +:100B2000E02CD0F9A9028501A2008620BD00F49D29 +:100B30000023BD00F59D0024BD00F69D0025BD00ED +:100B4000F79D0026BD00F89D0027BDBEFB9D00223D +:100B5000E000302ABD4BFC9D841FBDC6FC9D84195E +:100B6000BD3DFD9D841ABDB4FD9D841BBD18FE9D39 +:100B7000841CBD57FE9D841DBD96FE9D841ECAD05B +:100B8000AB4C0623ADF9FF2904F032A90385F185AA +:100B9000F2A94985EFA9668525A9568526A92E853E +:100BA00027A9AA85F4A9FA85F5242830FC24281061 +:100BB000FCA9848530A91F852CA943853C60841F2E +:100BC00019BB00008440191FBB0000851C194A0096 +:100BD00000891C194A00008D1C19480000911B193E +:100BE0004600009619194200009D17193E0000A604 +:100BF00017193E0000AF2C1C00AF2C1C500000AF9A +:100C00002C1D00AF2C1D500000AF2D19280000C274 +:100C10002D19280000D52D19280000E82D192800CD +:100C200000AF2D1A280000C22D1A280000D52D1A59 +:100C3000280000E82D1A280000AF2D1B280000C254 +:100C40002D1B280000D52D1B2800000F22060F2287 +:100C5000000F22000F220003220085220D0522131F +:100C600005221905221F05222505222B0522310FF9 +:100C7000220001223700224B022237002251022299 +:100C80003700225702223700225D022237002263FA +:100C900002223700226902223700226F0222370027 +:100CA000227502223700227B022237002281022293 +:100CB000370022870122410F22000F22000F22005D +:100CC0000F22000F2200007C7F8F80FC7F8FC01FCF +:100CD00087F87E0FE07F81FC07FF807F807FF81F11 +:100CE000FFF0007F8003FFFE1F0000007F800000F8 +:100CF0003E00000C003FFFFFFFF000C000003FFF80 +:100D0000FF0003FC00003F003FFFFFFFF003F00087 +:100D1000003FFFFFFC03FC0000FFC00003FF0000DA +:100D20000FFC00003FF003FFC3FC0003FFF00003D3 +:100D3000FF00003FFF00003FF0003FC3FC007C7F4E +:100D40008F807C7F8F801F87F87E0FF07F83FC0170 +:100D5000FF807F807FE01FFFF8007F8007FFFE1F7E +:100D6000F000007F800003FE000FF3FC0003FF0093 +:100D700000FF3FC0003FF000FFC3FC003FC0FF008A +:100D800003FF0003FC0FF0003FF03FFC03FC00FFFB +:100D9000003FC003FF000FF003FC003FF0FFC00363 +:100DA000FC03FFFFFFF003FF003FFFFFFF003FF0EA +:100DB0003FF003FC007C7F8F807C7F8F801F87F853 +:100DC0007E07F07F83F800FFC07F80FFC01FFFFC1D +:100DD000007F800FFFFE1FFC00007F80000FFE0FD2 +:100DE000FFFFFFFC03FF00FFFFFFFFC03FF00FFC12 +:100DF00003FC3FF00003FF03FF03FF00003FF03F51 +:100E0000F003FF03FCFFC00000FFC3FF0FFC000066 +:100E10000FFC3FF000FFC3FC007C7F8F807C7F8F46 +:100E2000800F87F87C07F07F83F8007FC07F80FF0A +:100E3000801FFFFE007F801FFFFE1FFF00007F80DE +:100E4000003FFE5555555555555555555555555514 +:100E500055555555555555007C7F8F807C7F8F802B +:100E60000FC7F8FC03F07F83F0003FE07F81FF00B5 +:100E700001FFFE007F801FFFE01FFFC0007F80009A +:100E8000FFFEAAAAAAAAAAAAAAAAAAAAAAAAAAAA19 +:100E9000AAAAAAAAAAAA007C7F8F807C7F8F800F33 +:100EA000C7F8FC03F87F87F0001FE07F81FE000099 +:100EB0001FFF007F803FFE001FFFE0007F8001FFDB +:100EC000FE55555555555555555555555555555529 +:100ED000555555555509CAC9C6B412081B605881E5 +:100EE0004B8601D8BFD925A07BDC3279843B7CBC02 +:100EF0002FE2E2FA8D0A003BC5ECAF2D8ACD0693B6 +:100F00006AA5144677C46AB25336EF8CCE0CA26839 +:100F100071D373E8F76D06B520EF23470C5155C820 +:100F2000FEF458C43F20A76738B076E2C4D8056302 +:100F3000F83C583B2D22CC88B3718F1D800A87BDA9 +:100F4000A15923E970E2D3EC4668804239EAFFFFF9 +:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFF474385 +:100FF00043284329313938342DF700F084F833F988 +:00000001FF diff --git a/Atari - 7800_TeST/rtl/rom/7800ntsc.rom b/Atari - 7800_TeST/rtl/rom/7800ntsc.rom new file mode 100644 index 0000000000000000000000000000000000000000..c91490c2acc2c1aaab3b88ac5b53f4b1e8632e13 GIT binary patch literal 4096 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 Co9Ti8 literal 0 HcmV?d00001 diff --git a/Atari - 7800_TeST/rtl/rom/7800pal.hex b/Atari - 7800_TeST/rtl/rom/7800pal.hex new file mode 100644 index 00000000..97141817 --- /dev/null +++ b/Atari - 7800_TeST/rtl/rom/7800pal.hex @@ -0,0 +1,1025 @@ +:1000000003FC0003FC0003FC0003FC0003FC0003F2 +:10001000FC0003FC0003FC0003FC0003FC0003FCE9 +:100020000003FC0003FC0003FC0003FC0003FC00D5 +:1000300003FC0003FC0003FC0003FC0003FC0003C2 +:10004000FC0003FC0003FC0000F00000F00000F0E6 +:100050000000F00000F00000F00000F00000F000F0 +:1000600000F00000F00000F00000F00000000000D0 +:100070002300001000000800002000000000000025 +:100080000000000000000000000000000000000070 +:100090000000000000000000000000000000000060 +:1000A0000000000000000000000000000000000050 +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:100100000FAA000FAA000FAA000FAB000FAF000F3D +:10011000B6000FAA000F6A000FAB000FAD000FADC5 +:10012000000FB5000FEA000FDA000FE9000FE90039 +:100130000FEA000FF5000FB9000FEB000FFA000FE8 +:10014000E9000FE9000FEA000FFF000FFF000FFFAB +:10015000000FFF000FFF000FFE000FBF000FFF009A +:100160000FFF000FFF000FFF000FFF000000000057 +:1001700010000008000810402304000000000000E8 +:10018000000000000000000000000000000000006F +:10019000000000000000000000000000000000005F +:1001A000000000000000000000000000000000004F +:1001B000000000000000000000000000000000003F +:1001C000000000000000000000000000000000002F +:1001D000000000000000000000000000000000001F +:1001E000000000000000000000000000000000000F +:1001F00000000000000000000000000000000000FF +:100200000FF6000FA5000FA5000FA5000FAF000F00 +:10021000BF000FD5000DA5000F99000E9D000FB572 +:10022000000FB7000FA5000FA5000FA9000FA90030 +:100230000FA5000FB9000FAD000FA5000FA9000F0B +:10024000A6000FAA000F95000FAA000FAA000FAA80 +:10025000000FAA000FAA000FA6C00FDE000FBA0001 +:100260000EAA000FAA000FAA000FAA0000010000AA +:10027000109000200808104000000000000000005E +:10028000000000000000000000000000000000006E +:10029000000000000000000000000000000000005E +:1002A000000000000000000000000000000000004E +:1002B000000000000000000000000000000000003E +:1002C000000000000000000000000000000000002E +:1002D000000000000000000000000000000000001E +:1002E000000000000000000000000000000000000E +:1002F00000000000000000000000000000000000FE +:100300003F55803E95403E95803E95403EA5403EFF +:10031000BD403EFD403F56403E95403EA5C03EB5E7 +:10032000403ED6803F99403F69403EA5403E9540C3 +:100330003E95403EA5403EED403E95C03EA5403F27 +:10034000A5403EA5403E95403E96803E96803E9616 +:10035000803E96803E95C03E9FC03E75803FD680D1 +:100360003B96803E96803E96803E9680002000041C +:100370001440012910010448004000000000000062 +:10038000000000000000000000000000000000006D +:10039000000000000000000000000000000000005D +:1003A000000000000000000000000000000000004D +:1003B0000000000000010004000000000000000038 +:1003C000000000000000000000000000000000002D +:1003D00000000000400000000000000000000000DD +:1003E000000000000000000000000000000000000D +:1003F00000000000000000000000000000000000FD +:100400003F75403F99403E95403E65403E95403E99 +:1004100055403EF6403FF5403E55403E95403E57E4 +:10042000C03ED6803EA5403FA5403F99403E654036 +:100430003E55403E95403E95803E55C03E55403F1E +:1004400095403ED5403E55403E95403E55403E5538 +:10045000803E55C03A55803AD7403A954039D5400C +:100460002E55403E55403E55403E55400038801088 +:10047000948080515003490000010003F000F00017 +:10048000F000F003F003F003F000F00FF00FF00EB7 +:10049000F00FF00FF003F003F003F00FF00FF00F88 +:1004A000F00FF00FF00FF00FF00FF0000000000061 +:1004B0000000000420010004800200000000000091 +:1004C000000000000002000000000000000000002A +:1004D00000020008400000000000000002000000D0 +:1004E000000000000000000000000000000000000C +:1004F00000000000000000000000000000000000FC +:10050000FD6D50FD5550FE6550FE5550FE5550FE98 +:100510009550FE9550FBD550FFD9D0FE5550FE9515 +:10052000D0FE9FD0FE6550FF9550FF9550FED650EF +:10053000FE9550FA6550FF5550FF5DD0FE5570FE98 +:10054000A550FFD550FF7550FA6560FA9560FA55D1 +:1005500060FA5D70FA76F0FA5960FE5560FF5560FA +:10056000FA5560FA5560FA5D60F9B56002258005BC +:10057000690426994000620001040803F00FF00BA3 +:10058000F00EF00FB00FEC0FF803FC2FFC3FFC3F18 +:10059000FC3FBC0FFC03FC03FC03FC3FFC3FFC3FA7 +:1005A000FC3FFC3FFC3FFC3FFC3FFC000000000523 +:1005B0002004080000202003804200080000000002 +:1005C00000000000800200080000000000000000A1 +:1005D0008002040B00000000200008010000000061 +:1005E0000800000000000000000000000000000003 +:1005F00000000000000000000000000000000000FB +:10060000FD6D50FF5570FF5550FA5550FA9550FA50 +:100610005550FA5550F95550FF6550FF9550F95512 +:1006200050F96750FAD550FA9950FAD550F6E5507E +:10063000FA9590FE9650FA9550FB65D0F99770FAAE +:100640009550FF5550FFF550F9D550FD5550F955CF +:1006500050F95570FA56D0F95550F95550FA555091 +:10066000F95550F95750F95A50FA59500A570002A3 +:1006700075800155100202180600C20FFC0FFC0F16 +:10068000FC0FF00FF80FFF0FFC0FFF3FD83BD83ED9 +:10069000A83EA83EA83E983FA83FD83EA83EA83E08 +:1006A000A83EA83EA83EE83DA83EA80000003001B4 +:1006B000400910C0082FE002800E000A002C000044 +:1006C0000000E0028002000A002C00000000E002AE +:1006D0008002C00A000104041000A002400280024F +:1006E000000000000000000000000000000000000A +:1006F00000000000000000000000000000000000FA +:10070000F95D50F5D550FD55D0F95550FA5550FAD0 +:100710006550F96550F59550F95550FD5D50FD96C1 +:1007200050FA5550FAF750FA9550F9D650FAB5509C +:10073000F99D50F69550FB9550FFD550F97570FA1C +:1007400055D0FA9550FBD950FDD550FF5550F9556D +:1007500090F96570F95550F95550F95950F96550AF +:10076000FA5650F95590F96650FE6D5000B580006C +:1007700096600075600108888000800EE83FBC3FED +:10078000AC3EA83BA83EF40FBF0FAFFBFBFBFBFA50 +:10079000FBFA5BFA5BFA97FA9BFBDBFA5BFA5BF915 +:1007A0005BFA5FFB58FAABF69FFA6F00000100019D +:1007B00040006220303AB0EA800AC04A802A002A0B +:1007C000C002A00E800EC00A002A000EA002A00ADD +:1007D000840E800AAC01040A90021000A003880075 +:1007E0000000000000000000000000000000000009 +:1007F00000000000000000000000000000000000F9 +:10080000F97550F9D550F75550F65750FA5550F93B +:100810005550FA5550F95550FA5550FA5550FA5569 +:1008200050FA5950FAFF50FE9D50FB9550F97590C3 +:10083000FA5D50F99560FA9550FD9550FA7550FAA9 +:100840009D50FA5570FA9550FAE550FB5590FD55BC +:1008500050F95550F99550FA5650F95650F95990AB +:10086000F995D0FA55D0F96750F9AD50006480047D +:100870005D281015622050000052002F983ABB3EB0 +:10088000AF3E973FA43ED63FB63EB4FAF6FAFDF926 +:10089000FEFD7EF996FE56F956F956F956F95AF9C3 +:1008A00074FD5CF954F976F97FF95E02000980065F +:1008B000C8111000000A802A803A800EB00AB03AAF +:1008C000A83AB00A800A800A803AB0AAB03A803AC0 +:1008D000C00AB00AA00254096006100A12002000E3 +:1008E0008000000000000000000000000000000088 +:1008F00000000000000000000000000000000000F8 +:10090000FA5550FFD570F76570FE6570FD5D50FAC1 +:100910005550FA9550FA5550F96550FA5550FAD598 +:1009200050F95550FE7D50FE5F70FB5750FAD55080 +:10093000FA9D60FA55D0FA5950FA9550FAFD50FADE +:100940005D50FA5750FA5550FFD550FB9550EE596F +:1009500050F95950F95550F95590F95550F95570CD +:10096000F956D0F956D0F96F50F9B650004400004E +:10097000E5000246400062C00010003EB4FE5CFE8E +:1009800057FF943DD63E753E9E3E94E955E97EE67E +:100990007CFD7CEB5CED96FB55E956E956E5DEF90E +:1009A0007CEA5CE9D5E9FFE976EA56024001601588 +:1009B000A0888000400A803A80AA800AAC4AA80A2F +:1009C000ACAA803A800A800AB00AA8EA80AA84EA1F +:1009D000800AA80AB000540150019804600208007F +:1009E000000AA00AA00AA00AA0000000000000005F +:1009F00000000000000000000000000000000000F7 +:100A0000FE9540FF5570FF55F0FE55F0FE95D0FD68 +:100A10005570FE5550FE5550FE5570FD5550FD5514 +:100A200050FF5550FE9570FE9FF0FE57D0FED5D07A +:100A3000FA7D50FE55D0FE5570FA5590FED550FA0D +:100A4000BF50FD9750FE95D0FF5560FB5660ED55A9 +:100A500060B95560F95550F95550F95550F955B0F0 +:100A6000F957D0F95B50FA6D50FE5550010800025D +:100A70004404011410810410818008FE56FD54FDC9 +:100A800055FE55FBD5F9F5FA7DF95BE955E556A913 +:100A90005CFD5CEF5CEAD6EF55EDD6E776E5FCE968 +:100AA0007CE554EBFEE5D5E956E95601800B4002A2 +:100AB00040311800010A800A803AB03AA80AB00E04 +:100AC000B03A802A800A800AA00AB03AC03A80AAC6 +:100AD000B03AB00A80006403420250001000800067 +:100AE000003AA82FA82AF82ABC000000003C3C3C91 +:100AF0003C3C3C3C3C3C3C3C3C00080808080000BA +:100B00003E55403E95403D65403E95C03E57C03EF7 +:100B100057403ED5403DA5403E95403E65403E5540 +:100B2000403E95403E65403E57C03E97C03ED5C0D2 +:100B30003EB5403E55C03E95403D55403D5D403E32 +:100B400075403A5FC03E55C03A95403E55403E56CE +:100B5000402E55403A55D03A55403A55C03A55C0C6 +:100B60003A5B403A55403E55803E554000080008EB +:100B70000800040404060042100800FB553AD53969 +:100B8000753E5DEA54F954FA54F955EB75E956E5AA +:100B900054EA54EF58EBD4E574EBD6EBFEE5FCE5F4 +:100BA0005DED56EB56E956E956EDD6008006500548 +:100BB0004C014381300EC0028002A02AC02A004AA4 +:100BC000800AC0EA803AB00AAC0E800A8402A00E05 +:100BD000A02A000A00061405D0240000800000802E +:100BE00000AAAAAAAAAAAAAAAA383C2C28383B3842 +:100BF000F83BFBFBFBFBF7FFF708101000000000C1 +:100C00003EA5403E55403E55403E97403E5F403EEB +:100C10005F403F55403F95403E65403E55403E67F2 +:100C2000403E55403E95003E55403E55C03F65C054 +:100C30003EB9403EA7C03E95403EA5403E55403E91 +:100C400097403E5D403E65C03E55803E56403E5515 +:100C5000403E55402E55403E55403E55C03E56C044 +:100C60003E55403E55403E55803E95800008000070 +:100C700008002004C00000000000203A96396439C2 +:100C8000543A543954395439543A54F5F6F5DEF59A +:100C900056F954FD58FBD4F9F4F95EF7FEF976F9EC +:100CA00055FFD6F956F956FB56FFF6000001000431 +:100CB00050091000000200028000E000002C000A31 +:100CC000000E0002802FE00A0002C0028000E00057 +:100CD000002C000A00051025041A22280088202074 +:100CE000003954395439543954AAAAAAAAE535F519 +:100CF000ECE5F5DDE5D415D6D524B6020C0C0000E4 +:100D00000E95000EA5000E65000E95000E9D000EBE +:100D1000BC000EBD000E96000EA5000E95000D97AE +:100D2000000E9D000E95000E95000E95000E5500CC +:100D30000F55000EA7000E95000E55000E55000E23 +:100D400095000E95000E97000EF5000EE5000EF5CD +:100D5000000EF5000EF5000EF7000EF7000EF50080 +:100D60000EF5000EF5000FF5000FF5000000000075 +:100D70000800004000081000001000395439540EDB +:100D8000543A943A503E903D603E583954397C393B +:100D900074395839583B5839F8395C39D439543F8B +:100DA00054395439543E543FD83FF80000000010E5 +:100DB000800408000002000080000000000000081D +:100DC000004200038020200B00020400800000008D +:100DD0000000000800060017009A00A820E00000AC +:100DE000080E500E500E500E5075757575D5F5DD08 +:100DF000E7F5D5DDD7D4D5D5DD180488020200008B +:100E00000FA9000F95000F95000FA5000FA5000F6B +:100E1000B5000FF5000FF5000FE9000FA5000FA5B5 +:100E2000000FAD000FA5000FA5000FA5000F950046 +:100E30000FA5000FFE000FE5000FE5000FD5000F16 +:100E4000D5000FD5000FD5000F96000F96000F9616 +:100E5000000F96000F96000F96000FE6000FD600C9 +:100E60000FD6000FD6000F96000FD600000000002E +:100E700000000008000004300C00000A500A500D69 +:100E8000500D500E500E500F500D503A5C3A543ADF +:100E90005C3A6C3A6C395C3AE83A7C3A583E583ADB +:100EA000583A580A580F5C0FDB3B5800000000000E +:100EB000004080200302000000000000000000004D +:100EC0000002000480010008400200000000000051 +:100ED0000000000000070020000000248028080017 +:100EE0000002400240024002403C282828E6E4D6A6 +:100EF000E5D6DDE5E4D51535DD201E020000000C49 +:100F000003F80003E80003E80003E80003E8000337 +:100F1000E80003D80003E80003E80003E80003E862 +:100F20000003E80003F80003E80003E80003F8000A +:100F300003F80003F80003FC0003FC0003F80003BF +:100F4000F80003F80003F80000E00000E00000E013 +:100F50000000E00000E00000E00000E00000E00031 +:100F600000E00000E00000E00000E0000000000001 +:100F7000000000000000040000200002800080004B +:100F800080028000800200028003400EB00EA00D9F +:100F9000A00EA00EA00EA00EA00EB00EA00EA00ED1 +:100FA000A00EA002A000A002A00EA0000000000061 +:100FB00000000042000000000000000000000000EF +:100FC00000000004000100004000000000000000DC +:100FD00000000000000400000000000000002020CD +:100FE000000240024002400240343434343434348D +:100FF00034343834383404043400202020204000B5 +:10100000A9148D8302A90085388D820220B5F4AD24 +:101010008402291F854018691F8541A236BD00D072 +:101020009D0021CA10F7A9018583868220B5FF2083 +:101030003AF42065FCA901857BA2FF9AE8867C86AC +:101040007D20D0F420A6F120DBF420A5FA20E8F4DE +:10105000A57629FE8576A57BC904F00DA57638E531 +:1010600077C90290F7A5768577E67DD002E67C20E9 +:101070002BD620BED12007FAA57BC905F076C9037F +:10108000F048C902F07AC901F006C904F04ED0C098 +:10109000A5B93007A2FF86FECA86FFA5BF2908F0C2 +:1010A00013AD800205FF25FE85FE3826FFC9F0D06E +:1010B000034CA2D2A57CD00B205AD120EFF920CB33 +:1010C000D19016C902D0F74CE1D1A57CC904D00358 +:1010D0004C09D220F3F720CBD14C50D020C5FFA62D +:1010E00055E8E00CB00B8655AAD0F120CBD14C507E +:1010F000D04C0ED220F3F7206ED120D8D14C50D056 +:10110000A57CC907F0CA2021D2205AD1A20A8A1888 +:101110006583A82037FAA20BA90F186582A820378B +:10112000FA20B1F9A9FF85988599A20CA016A5828D +:101130003012C8A582F008C902D002C8C8C8C820A9 +:1011400037FAC8E82037FAA50C100CA5093008A515 +:10115000BF4AB0034C50D04CFBD1A209A0092037A4 +:10116000FA88CA10F9A90E85F1A90785F360A5BF11 +:101170002908F02DA906857BA9008519851A857C8B +:10118000857D242830FC242810FCE67DD004E67CF4 +:10119000302220BED12908F009A905857BA9408508 +:1011A0003C60AD800249FFD00FA50C250D10092031 +:1011B000D8D190CEA960D002A940853CD0B6AE82ED +:1011C000028A45BE25BE85BF86BE60A5BC102CAD7B +:1011D000800229F049F0D012A5BF4AB01E4AB00AD9 +:1011E00060A9008555A9044C37D0A91085FAA9003B +:1011F000855285538554A9024C37D0203AF4204FAC +:10120000F420B1F9A9054C37D0A9014C37D0A90079 +:1012100085528553855420B1F9204FF4A9034C37EA +:10122000D0AD800229F049F0D028AD82022902F029 +:1012300005A90085FA60C6FA1061A21086FA20712D +:10124000D2D058A90085832063D2D04FA9FF8582D0 +:10125000D03EC6FA1045A21086FA0AB0140AB01B96 +:101260000AB022A682E001F032E8BD9ED28582104B +:101270001FA583C903F024E6831015A583C900F0D8 +:101280001AC683100BA682E0FFF010BD9CD28582A7 +:10129000A900857C857D20B5FFA91160FF020002B1 +:1012A0001101A208A0B2948CBD16FD9DD71AADE81D +:1012B000F39D2E19CA10EFA5762903D00CA5764808 +:1012C0004A8576204DDA68857620A5FAA9728DD1F7 +:1012D00018A9DE8D3719A94A8DE01A2024FA202B8F +:1012E000D620BED120CBD190CE488A489848D8A5E8 +:1012F00078D031AD9E1A100D297F8D9E1A20CDF128 +:10130000E6764C24D3AD0120186D00208D0020908E +:1013100008AD9E1A09808D9E1A20BCFA20CDF1E6F8 +:10132000762076FA68A868AA6840A679B57EF001AA +:1013300060A68BBD5918100549FF1869018555BD78 +:101340009B18100549FF1869011865558555A909AD +:10135000E5558555A679B5BA3003203ED5A5BDA67D +:1013600079F0040A0A0A0A0A48B003208FD3680AEF +:1013700048B0032087D3680A48B006204DD520B76F +:10138000D5680AB01F9057B5C138E5554C94D3B510 +:10139000C118655595C1A48B4A4A4A29FE1869B5FA +:1013A00099461960A582C901300DA57E057FD00739 +:1013B000A5BD3DA7D6F005A91120B7F1A5790A0A68 +:1013C000A8A90099E900204DD520B7D5A679B5B8D0 +:1013D0003007B5DBD0074C92D4A90095DB60A9118A +:1013E000205EF1A5790A0AA8A94F99E900A679B566 +:1013F000C14A4A4A4AA8A68BBD38188556BD591815 +:101400004A66564A66564A66564A6656BD7A1885F0 +:1014100057BD9B184A66574A66574A66574A6657E9 +:10142000B91DFE100AA6561014C5569010B008A695 +:1014300056300AC556B006204DD54C55D4B9DDFD01 +:101440000A0A0AA68B187D38189D3818BD591879D4 +:10145000FDFD9D591898186910A8B91DFE100AA61F +:10146000571014C5579010B008A657300AC557B08A +:101470000620B7D54CCCD3B9DDFD0A0A0AA68B18D5 +:101480007D7A189D7A18BD9B1879FDFD9D9B184C9F +:10149000CCD3A582C901100AA203B5A83014CA1082 +:1014A000F960A679F002A202B5A83006E8B5A83026 +:1014B0000160A479B9C1004A4A4A4AA8A90695A878 +:1014C000A9EC95DF8655A68BBDBC18A6551879BD2D +:1014D000FDC99F9002E99F9DC018A68BBDE018A68C +:1014E000551879CDFDC9BF9002E9BF9DE418A68BC0 +:1014F000BD0419A6559D0819A68BBD2519A6559D95 +:101500002919B9DDFDA68B187D5918A6559D5D18C2 +:10151000A68BBD3818A6559D3C18B9EDFDA68B18B5 +:101520007D9B18A6559D9F18A68BBD7A18A6559D24 +:101530007E18A90E206BF1A679A90195DB60A6792A +:10154000B57ED008A902957EA92C958060A68BBD9A +:1015500038181D5918F05FBD38180A8556BD59183E +:101560002A8555BD38181865568556BD591810037B +:10157000FE591865558555A679BD921A38E5569DD0 +:10158000921AA68BBD3818E5559D3818BD5918E933 +:10159000009D5918A90085F8BD5918F00E18690169 +:1015A000D014BD3818C9E0900DB007BD3818C92057 +:1015B000B004A90185F860A68BBD7A181D9B18F0B0 +:1015C00069BD7A180A8556BD9B182A8555BD7A18BB +:1015D0001865568556BD9B181003FE9B18655585EA +:1015E00055A679BD941A38E5569D941AA68BBD7AF6 +:1015F00018E5559D7A18BD9B18E9009D9B18BD9B69 +:1016000018F00E186901D022BD7A18C9E0901BB0FD +:1016100007BD7A18C920B012A5F8F00EA9009D38B0 +:10162000189D59189D7A189D9B1860AD800285BD44 +:10163000A2012068D6CA10FAA5B885BCA57BC9034B +:10164000D025A9FF85B885B985BA85BBA576290CB3 +:10165000D015A5764A2901AAA97F95B820AEF82908 +:1016600007AABDA9D685BD60B40C1019A5C03DA3BD +:10167000D6D01C8A0AA8B9090049FF95B8B9080054 +:1016800049FF95BA60A5C01DA3D68D820285C0947E +:10169000B8A9FF95BAA5BD3D14D8DDA5D6D0E5A95A +:1016A0007FD0DF0410D00D01107FBFEFF7FBFEFFEE +:1016B000EEA679B57EF01F100160D680C901F05505 +:1016C000C902D0034C16D8C904D0034C98D8C9031A +:1016D000D0034CBBD860A5FCF0FB20FBD630F6C590 +:1016E00079D0F2AAA904957EA9FF85FCA90095529C +:1016F000A90D8D121BA9002070F160A200B546D57E +:101700004A900CF002B00BE8E005D0F1A9FF60A907 +:101710000160A90060A48BB9A4003010A905A47BC6 +:10172000C005D003A5760A205AFAA679B580C979F2 +:10173000F00BC951F011C929F062901060A582C95F +:1017400001100320E5DF60A9FF85AE60A57BC90518 +:10175000D010B5B835BA1020AD800249FF3D14D87D +:10176000D016B580C901B00FA58B186918AA20380A +:10177000F9F005A679F68060A90220B7F1A9032047 +:1017800070F1A5790A0AAABDF8FC95EABDF9FC95A5 +:10179000EBA679A90195DBA900957E60A5A530038C +:1017A000F68060A57BC903F016A582C901D00BA500 +:1017B00054C901B003F68060A202D65220C3DFA94B +:1017C000022070F1A68BA9009D59189D9B189D3889 +:1017D000189D7A188D131BA582C9013007A479B909 +:1017E00012D81002A9509DBC18186DFCF39D8A19DF +:1017F000A9509DE018186D03F49DB619A679B5C1DE +:101800004A4A4A29FE1869B5A68B9D4619A923950F +:10181000A4603070F00FB580C929F005C901F01B34 +:1018200060A9012070F1A68BA9FF95A4A9009D389D +:10183000189D59189D7A189D9B1860A91818658BDA +:10184000AA20AEF84A690D9DA41820AEF84A691086 +:101850009DC8182038F9F005A679F6806020AEF80A +:10186000C932B022A91818658BAAA9A3958CADE935 +:10187000F39D2E19A9052070F1A679A903A67995E3 +:101880007EA9DE958060A9032070F1A923A6559555 +:101890008CA679A900957E60AD121BEE121BC920A3 +:1018A000F012C92ED0034C7BD82CF7F9F002491F57 +:1018B000205AFA60A68BA9FF95A460B580C9B6F03E +:1018C0004BC9A6D0034CA3D9C9A1D0034C6DD9C92B +:1018D00071F015C961F02CC901D00C20A6F120DBF4 +:1018E000F420B8FF4C09D260A9FF85AE85AF8A49C4 +:1018F00001A8A9FFD97E00F0EE957EA582D0E84C24 +:10190000A3D960A20220E5DF208BDF6020AEF1A921 +:101910001120B7F1A679A482A554C001F002B552F6 +:10192000C9019011C000D03A8A4901AAB552C90133 +:10193000B0B54C42DAC0FFF01EC001D01E8A49018A +:10194000AAB57EC901D01BA58B4908A8B9A400C9B6 +:1019500023F00FA9FF957EA964D002A9A4A67995CA +:101960008060A679A901957EA92C958060A679A5AD +:10197000FC3029F01620FBD6AA1021AD131BD00491 +:10198000A6791018A9FF85AE85AF6020E5DFA20219 +:1019900020E5DFA682E002D00286FC6020E5DFA21F +:1019A0000310ED8A4901AA8579F002A908858BA95F +:1019B000FFA20795A4CA10FBA90085FBA95085E4E6 +:1019C000A99285E585E620A6F1A017B68CB9001886 +:1019D000998C008A990018BE2E19B95219992E199E +:1019E0008A995219BED71AB9FB1A99D71A8A99FB44 +:1019F0001ABE4118B9CA199941188A99CA19BE83E1 +:101A000018B9EA199983188A99EA19BE2018B94AAF +:101A10001A9920188A994A1ABE6218B96A1A9962E4 +:101A2000188A996A1ABEA418B90A1A99A4188A9928 +:101A30000A1ABEC818B92A1A99C8188A992A1A887F +:101A40001089A679A901957EA999958060A020B9F1 +:101A50008C001031C9FFF02D980A65764A2903D011 +:101A600024B98C00290FAAB92E19DDEEF3D00FE0AE +:101A700003B004A679D6C5A9FF998C003007187D5C +:101A800089DA992E198810C7600102030201020049 +:101A9000A5FD3002C6FDA220B58C3016BCC6DDB94E +:101AA0008C00300B865884594CB8DAA658A4598853 +:101AB00010EDCAE01810E160BD721938F97219B062 +:101AC0000449FF6901C992900FE019F00BC019F0A9 +:101AD0000738E9A049FF6901C90AB05C8555BD9E78 +:101AE0001938F99E19B00449FF6901C9AE9006E999 +:101AF000C049FF6901C90EB03F8556186555855725 +:101B0000B58C290F855AB98C00290F855B845EA896 +:101B1000B9F7DDA45A79F7DDC557301AB9E7DDA466 +:101B20005B1879E7DDC555900DB9EFDDA45A18793A +:101B3000EFDDC556B022A45EC028F00CB016E02838 +:101B4000F03AE0259036B008E0259030B000A02BA8 +:101B5000CA4CB8DA884CB8DAA920A482C001300295 +:101B6000A91E8555A45EE020F015E018F04FC018BE +:101B7000F031A658A45920D1DC4CB2DA4CABDAA52E +:101B80007FD0F9A582C902F004C01CB0EFA22720C3 +:101B900014DCC018D024A582C902F007A57ED0DCD1 +:101BA0004C8BDDA57ED0D5E01C900AA582C901F042 +:101BB000CBE45590C7A02B20C5DB4CB8DAA57ED06E +:101BC000BBA22BD0F2865DA5C14A4A4A4AAABDBD36 +:101BD000FD186DBC188D9A19BDCDFD6DE0188DC630 +:101BE00019BD1FDE6DBC188D9B19BD2FDE6DE01871 +:101BF0008DC719BDFFDD6DBC188D9C19BD0FDE6D45 +:101C0000E0188DC819AD8A198D9D19ADB6198DC909 +:101C100019A65D60865DA5C24A4A4A4AAABDBDFDB5 +:101C2000186DC4188D9619BDCDFD6DE8188DC219BB +:101C3000BD1FDE6DC4188D9719BD2FDE6DE8188DA0 +:101C4000C319BDFFDD6DC4188D9819BD0FDE6DE899 +:101C5000188DC419AD92198D9919ADBE198DC5197C +:101C6000A65D60865DB58C0980958C290F855BC962 +:101C700006B020C904B025C903B041690A48A90AC1 +:101C800020B7F1A90B20B7F1A90C20B7F16820709B +:101C9000F1A65DA45BB9E6F39D2E1960AA38E902AE +:101CA000209AF8E004D008A5E7C9049002C6E78AA4 +:101CB00018690248690220B7F16810D2A55DA20038 +:101CC000C920D001E8A903957EA9DE9580A9051059 +:101CD000BD2063DCA55B855AA6592063DCA65BA406 +:101CE0005820F2DCA65AA45920F2DCC0189024A691 +:101CF0005860C4551019C01C100DC018D010E00356 +:101D0000D005A9118D131BA579857A203FDE60A926 +:101D10000110F6B98C0038E991301F855CA9508517 +:101D2000E4A583F010C9039009A5402903D003203E +:101D30003BDD203BDD203BDDA65860A217B58CC9FA +:101D4000FFF004CA10F760B9EC189DEC18B9A4189C +:101D50009DA418B90D199D0D19B9C8189DC818B9B9 +:101D600072199D7219B99E199D9E19B9D71A1869D1 +:101D7000019DD71AA55C958C290FA8B9F6F39D2E65 +:101D80001920F5F8A679F6C5A45960A5FD1048AD4F +:101D90005918C9806A48AD38186A48AD6118C980B9 +:101DA0006A8D5918AD40186A8D3818688D401868CA +:101DB0008D6118AD9B18C9806A48AD7A186A48AD24 +:101DC000A318C9806A8D9B18AD82186A8D7A18682D +:101DD0008D8218688DA318A90185FD4CABDA171800 +:101DE0001818191919191D02040503020401010329 +:101DF00006080602030101030609060203020101A7 +:101E0000000001010203040505060505040302059F +:101E100007090B0C0D0E0E0D0B0907060504040532 +:101E20000403020101000001020304050506050583 +:101E30000404050607090B0D0E0E0D0C0B0907A572 +:101E40007BC905D0102056DEA582C901D007A902A2 +:101E5000857A2056DE6086628463A57A0A0AA8F82D +:101E600018BDADFD794900994900BDB5FD7948001F +:101E70009948009024A582C901D006A57AC902D04C +:101E800017D8A900209AF8A67AF652200DDFA904E7 +:101E90002070F1A57A0A0AA838A900F879470099B4 +:101EA0004700A900794600994600D820B7DEA6620F +:101EB000A4636086628463A57A0A0AAA0A0A856412 +:101EC0008A1869048561B5464A4A4A4AD01F2003E8 +:101ED000DFB546290FD0202003DFE8E46130E7A911 +:101EE00001C6642005DF60B5464A4A4A4A186901BE +:101EF0002005DFB546290F1869012005DFE8E461F8 +:101F000030E560A900A46499141BE66460A67A8A8F +:101F10000A0A0A0A186908A8A90099141BC8846447 +:101F200099141BC899141BC899141BC899141BA693 +:101F30007AB552F00FC9059002A904AAA90B200591 +:101F4000DFCAD0F860A2008664B5424A4A4A4AD045 +:101F50001A2081DFB542290FD01B2081DFE8E00481 +:101F600030E74C80DFB5424A4A4A4A18690C208360 +:101F7000DFB542290F18690C2083DFE8E00430E563 +:101F800060A900A46499441BE66460A000A58230A7 +:101F90000DA008C901F007A00020A5DFA00420A51E +:101FA000DF2045DF60A200B94600D5429014F00C56 +:101FB0009542C8E8B94600E00490F560C8E8E0043E +:101FC00090E560A582C901D008A902857A200DDFBD +:101FD00060A900857A200DDFA582100160A9018526 +:101FE0007A200DDF60A57BC905D0F98A186912A88F +:101FF0008AC902B004A2221002A2234C37FA0000C0 +:1020000000A8A8A8A808A8A820A8A8000000000068 +:1020100000000000000000000000000000000000C0 +:1020200000000000000000000000000000000000B0 +:102030000000000000000000000000000000003F61 +:10204000F03FF003FFFFF0003FC000FFFFFF00FF85 +:10205000C0FFC0FFFFFFC0FFF03FFFFF0003FFFF17 +:10206000F0000000000000411541411545504410AA +:1020700010154411011545411040405555111005EA +:1020800051040400551045500401544101015441CC +:102090000401105500401544101015441154040556 +:1020A000510440404015441010551544044015405B +:1020B00040404045510400401544101000055000B8 +:1020C0000000000000000000000000000000000010 +:1020D0000000000041150141044115455150200AFE +:1020E00000020200A8002A8200008008A000002848 +:1020F00000288200FFFFFFFFFFFFFFFFFFFFFFFF42 +:1021000000882080080808882088080C000000004B +:1021100000000000000000000000000000000000BF +:1021200000000000000000000000000000000000AF +:102130000000000000000000000000000000003F60 +:10214000F03FF003FFFFF0003FC000FFFFFF00FF84 +:10215000C3FFC0FFFFFFC0FFF03FFFFFC003FFFF53 +:10216000F0000000000000451045511004004450EC +:10217000101004510110041115404040401110048A +:1021800001140400411144000401005501010045FF +:10219000040444410040100550101004500404048D +:1021A00001544040401005501040104404401000BD +:1021B000404040441114004010055010001004002D +:1021C000545515455001040404110440055154416F +:1021D000100400005510455154451004010488288E +:1021E00082888888820080820000202A88000082FD +:1021F00000820200FFFFFFFFFFFFFFFFFFFFFFFF67 +:10220000008820800808088820880838000000001E +:1022100000000000000000000000000000000000BE +:1022200000000000000000000000000000000000AE +:102230000000000000000000000000000000003569 +:10224000703570035555700035C000D5555700D511 +:10225000CFD5C0D55555C0D570355555C00355554A +:102260007000000100000055104411100540455059 +:102270001015054111150411104040545404154522 +:10228000415004004115454005410041054150546D +:102290000404444100541004105415054050040532 +:1022A0004104444054100410544010444455150057 +:1022B0004040404411540055100410540011440093 +:1022C000100110401001540405511440040104454C +:1022D00010040000411044110455100541048220EF +:1022E000822888220002802000002AA208000082A2 +:1022F00000820200FFFFFFFFFFFFFFFFFFFFFFFF66 +:102300000088208008A808882088A8A8000000006D +:1023100000000000000000000000000000000000BD +:1023200000000000000000000000000000000000AD +:102330000000000000000000000000000000003568 +:10234000703570035555700035C000D5555700D510 +:10235000CF5700D55555C0D57035555570035555D7 +:1023600070000000000000511044111004004510DE +:102370001010041145100411104040404011104449 +:1023800001040400411444000411004114510041AF +:1023900004044441004110041145100411000404D8 +:1023A00001045140411004114540104514411000F2 +:1023B0004040404411440041100411450011040004 +:1023C00010551545500104040411504004010454F3 +:1023D00015000000411044110451100401048280D2 +:1023E0008A088822A802002008080A8008020082C1 +:1023F00000820000FFFFFFFFFFFFFFFFFFFFFFFF67 +:10240000008820A82888A8A808A888E8000000005C +:10241000000000000000400551010101544040014E +:1024200050400551010101544040015455444115AB +:1024300040554404404550055010154404AAAAB51F +:10244000703570A80035702AB5C2AAD5555708D581 +:10245000CF5402D5C2D5C2D542B5555570AA003564 +:1024600072AAA800000000411544111545504411FE +:10247000551545510115454105055455551115454D +:1024800051545540551045500551001410115455E4 +:102490005544045500551001410115455154554509 +:1024A0005050404055100141015515440455154503 +:1024B0005445544551040055100141010011440098 +:1024C000504110441001040404110440040104416B +:1024D0001040000014150410504115455150228041 +:1024E0002208882202080020022880000A8A00822E +:1024F00000820000FFFFFFFFFFFFFFFFFFFFFFFF66 +:10250000008820080888808008888828000000004B +:1025100000000000000040040101010100404000F3 +:1025200040400401010101004040010044444100D9 +:1025300040404404404400041044100404000035AA +:10254000F03D7000003D700035C000D5C00000D7E0 +:10255000CF5C00D5C0D5C035C03570157000003DCA +:1025600070000000000000000000000000000000FB +:10257000000000000000000000000000000000005B +:10258000000000000000000000000000000000004B +:10259000000000000000000000000000000000003B +:1025A000000000000000000000000000000000002B +:1025B0000000000000000000000000000010040007 +:1025C0001055154550005055414154400551545542 +:1025D000154000000000000000000000000008801E +:1025E0002088882202080020028228A808A08022D1 +:1025F00000820200FFFFFFFFFFFFFFFFFFFFFFFF63 +:1026000000A8A0A8A880A8A8A8A8A8080000000062 +:1026100000000000000040040101010100404000F2 +:1026200040400401010101004040010044444500D4 +:10263000404044044044000411011004040AAAB7B5 +:10264000FFFF70BFFFFF702AB5C2AAD7C00008DF26 +:10265000FFDF02D5C2D5C2B5C2B570BD70BFFFFFE6 +:1026600072AA8000200000000000000000000000AE +:10267000000000000000000000000000000000005A +:10268000000000000000000000000000000000004A +:10269000000000000000000000000000000000003A +:1026A000000000000000000000000000000000002A +:1026B00000000000000000000000000000055000C5 +:1026C000000000000000000000000000000000000A +:1026D000000000000000000000000000000000807A +:1026E000208888220200008002022288A880802A96 +:1026F00000820200FFFFFFFFFFFFFFFFFFFFFFFF62 +:1027000000000000000000000000000800000000C1 +:1027100000000000000040040101010100404000F1 +:1027200040400401010101004040010044444500D3 +:1027300040414404404400041101100404000035E9 +:10274000555570355555700035C000DFFFFF00D579 +:102750005555C0D5C0D5C035C035703570355555C7 +:1027600070000000000000000000000000000000F9 +:102770000000000000000000000000000000000059 +:102780000000000000000000000000000000000049 +:102790000000000000000000000000000000000039 +:1027A0000000000000000000000000000000000029 +:1027B0000000000000000000000000000000000019 +:1027C0000000000000000000000000000000000009 +:1027D0000000000000000000000000000000008079 +:1027E00020282020A8002A800082208A0820800A31 +:1027F000A8820200FFFFFFFFFFFFFFFFFFFFFFFFB9 +:1028000000000000000000000000000000000000C8 +:10281000000000000000554401551551545540007A +:1028200040554401551551545540015440445115EB +:102830004040055440455004110115455400AAB5C7 +:10284000555570B55555702AB5C002D5555708D5A0 +:102850005555C2D5C2D5C2B5C0B570B570B55555C0 +:1028600072A800000000000000000000000000004E +:102870000000000000000000000000000000000058 +:102880000000000000000000000000000000000048 +:102890000000000000000000000000000000000038 +:1028A0000000000000000000000000000000000028 +:1028B0000000000000000000000000000000000018 +:1028C0000000000000000000000000000000000008 +:1028D0000000000000000000000000000000008078 +:1028E000200000000000AA00008220820820800250 +:1028F00002820200FFFFFFFFFFFFFFFFFFFFFFFF5E +:102900000000000000000000000000005454545477 +:10291000045454105454404401011011004100006B +:102920004040440101101100410000044044511096 +:102930000040440444440004110110041000003518 +:10294000555570355555700035C000D5555700D5D3 +:102950005555C0D5C0D5C035C035703570355555C5 +:1029600070000000000000000000000000000000F7 +:102970000000000000000000000000000000000057 +:102980000000000000000000000000000000000047 +:102990000000000000000000000000000000000037 +:1029A0000000000000000000000000000000000027 +:1029B0000000000000000000000000000000000017 +:1029C0000000000000000000000000000000000007 +:1029D0000000000000000000000000000000008077 +:1029E00080000000000080000088088208220002A9 +:1029F00000820200FFFFFFFFFFFFFFFFFFFFFFFF5F +:102A0000000000000000000000000000441040042E +:102A1000040444104404404401011011004100002A +:102A200040404401011011004100000440444110A5 +:102A300000404404444400041101100410000AB58D +:102A4000703570B5700002AAB5C002D5C00008D5B7 +:102A5000C0D5C2D5C0D5C2B5C0B5703D70B5700087 +:102A60000A80000000C0000000000000000000001C +:102A70000000000000000000000000000000000056 +:102A80000000000000000000000000000000000046 +:102A90000000000000000000000000000000000036 +:102AA0000000000000000000000000000000000026 +:102AB0000000000000000000000000000000000016 +:102AC0000000000000000000000000000000000006 +:102AD0000000000000000000000000000000008076 +:102AE000800000000002000000A008820828000208 +:102AF00000800200FFFFFFFFFFFFFFFFFFFFFFFF60 +:102B0000000000000000000000000000441040042D +:102B100054044410445455440155101154550001B7 +:102B2000405544015510115455000154404441157D +:102B30004055455455455005510115455000003547 +:102B4000F03D7035F000000035C000D7C00000D760 +:102B5000C0F5C0D7C0F5C035C035F03F7035F000C6 +:102B60000000000000000000000000000000000065 +:102B70000000000000000000000000000000000055 +:102B80000000000000000000000000000000000045 +:102B90000000000000000000000000000000000035 +:102BA0000000000000000000000000000000000025 +:102BB0000000000000000000000000000000000015 +:102BC0000000000000000000000000000000000005 +:102BD000000000000000000000000000000008826B +:102BE0000000000000020020002002820008008295 +:102BF00000800200FFFFFFFFFFFFFFFFFFFFFFFF5F +:102C00000000000000000000000000004410541408 +:102C1000445454045444000000000000000000002C +:102C200000000000000000000000000000000000A4 +:102C3000000000000000000000000000000000B7DD +:102C4000FFFF7AB7FFFFA8FFFDFFFADFFFFFA8DF56 +:102C5000FFFDEADFFFFDEAFDFAB7FFF57AB7FFFFF8 +:102C6000A8000000000000000000000000000000BC +:102C70000000000000000000000000000000000054 +:102C80000000000000000000000000000000000044 +:102C90000000000000000000000000000000000034 +:102CA0000000000000000000000000000000000024 +:102CB0000000000000000000000000000000000014 +:102CC0000000000000000000000000000000000004 +:102CD000000000000000000000000000000002886A +:102CE0000000000000020020000000000000202280 +:102CF00000820208FFFFFFFFFFFFFFFFFFFFFFFF54 +:102D00000000000000000000000000004410040467 +:102D10004440400444440000000000000000000063 +:102D200000000000000000000000000000000000A3 +:102D3000000000000000000000000000000000355E +:102D400055557035555700D5555570D5555700D543 +:102D50005555C0D55555C0D5703555557035555755 +:102D60000000000000000000000000000000000063 +:102D70000000000000000000000000000000000053 +:102D80000000000000000000000000000000000043 +:102D90000000000000000000000000000000000033 +:102DA0000000000000000000000000000000000023 +:102DB0000000000000000000000000000000000013 +:102DC0000000000000000000000000000000000003 +:102DD000000000000000000000000000000000A053 +:102DE0000000000000008080000000000000200AB9 +:102DF00000820202FFFFFFFFFFFFFFFFFFFFFFFF59 +:102E00000000000000000000000000005450545476 +:102E100040545454545400000000000000000000CE +:102E200000000000000000000000000000000000A2 +:102E3000000000000000000000000000000000355D +:102E400055557035555700D5555570D5555700D542 +:102E50005555C0D55555C0D570355555C035555704 +:102E60000000000000000000000000000000000062 +:102E70000000000000000000000000000000000052 +:102E80000000000000000000000000000000000042 +:102E90000000000000000000000000000000000032 +:102EA0000000000000000000000000000000000022 +:102EB0000000000000000000000000000000000012 +:102EC0000000000000000000000000000000000002 +:102ED00000000000000000000000000000000020D2 +:102EE0000000000000008280000000000000200AB6 +:102EF00000800202FFFFFFFFFFFFFFFFFFFFFFFF5A +:102F000000000000000000000000000000000000C1 +:102F100000000000000000000000000000000000B1 +:102F200000000000000000000000000000000000A1 +:102F3000000000000000000000000000000000355C +:102F400055557035555700D5555570D5555700D541 +:102F50005555C0D55555C0D57035555700355557C1 +:102F60000000000000004000000000000000000021 +:102F70000000000000000000000000000000000051 +:102F80000000000000000000000000000000000041 +:102F90000000000000000000000000000000000031 +:102FA0000000000000000000000000000000000021 +:102FB0000000000000000000000000000000000011 +:102FC0000000000000000000000000000000000001 +:102FD00000000000000000000000000000000008E9 +:102FE00000000000000028000000000000000802AF +:102FF00000800002FFFFFFFFFFFFFFFFFFFFFFFF5B +:103000004041424446480A090807060504030201F4 +:10301000FF4D03020102032098FEBC0D241F1D1B5F +:103020001A18171514131211100F0E0D2C860A857D +:103030000806900402FF06040105020301060405C8 +:103040000203040103254501010203040608080CDC +:103050000F0FFF861F181F9514FF080008000800B7 +:10306000FE075F88034909070907FE0B8A09430722 +:10307000230F0307234B515A030F12131314141574 +:10308000161617FF03050784060504820302010CC8 +:103090000D0E0F101112131415161718191A1B1CE8 +:1030A0001D1E1FFF82FE075309FF54100E0D0E0C4C +:1030B0000E0F2E10130C0805030221A007050301B3 +:1030C000FF07210102030405060708FE080905079A +:1030D0002A8C07000500030001FF1A122D9BFEBC7D +:1030E0000400040004008A000400040004008504B5 +:1030F00000040004FF04062692010203FE0C1112D4 +:1031000018031B1D2D010336460205004703035318 +:103110005A030562060905636603056C66046F00C1 +:103120000303710203050575080405760806057793 +:10313000070803788402038FA40104A7A80604AA41 +:10314000A80604AB030203B3BB0403C1C30803CD49 +:10315000D10303DADD090100E00501F5F806A2015B +:10316000D5CDF006CA10F92070F1604820B7F1689B +:10317000A201B4CD3011CA10F9C910B009A201D50D +:10318000CD9004CA10F96095CD0A0AA8B9FEF09551 +:10319000CFC8E8E8E00690F4B9FEF0CACA30E79D6F +:1031A0008A1A95D510F5A20120C1F1CA10FAA920FA +:1031B00085CAA99085CB60A201D5CDF004CA10F9CB +:1031C000608A2901AAA0FF94CDC8941960A57BC983 +:1031D00005D0B3A5A53008290F186904205EF1A217 +:1031E000018A48B5CD300320F0F168AACA10F26018 +:1031F000B4CFB900F0C9FFF0C8C9FEF035C9FDF081 +:103200003AC980B021291F9515D6D5D012BD8A1A8A +:1032100095D5B900F0C940B006C920B02AF6CFE86C +:10322000E8E00690CB60297F9D8A1A95D5F6CF4CB1 +:10323000F0F1C8B900F095CF4CF0F1C8B900F048F2 +:1032400020C1F1684C70F18A2901A8B9CD000A0AA1 +:1032500085658A4A186565A8B9FEF095CF4C1FF2BE +:10326000A5762906D00D20AEF8C906B00618691259 +:103270002070F1E6CBD010A99085CBC6CAA5CAC9EB +:1032800005B004A90585CAC6C91010A5CA85C9A577 +:10329000CC490185CC18690F2070F160A220B58C53 +:1032A0001004CA10F960290FA818BD20187DEC1869 +:1032B0009DEC18BD41187DA418C99F9010E019F02D +:1032C0000CBD41183005A9004CCDF2A99F9DA41852 +:1032D0001879F9F39D721918BD62187D0D199D0DAD +:1032E00019BD83187DC818C9BF900CBD831830055F +:1032F000A9004CF7F2A9BF9DC818187900F49D9E4B +:1033000019C003B09DB58C30998A0A65764A3DC2D2 +:10331000F3D08FBDAAF33039C0019024F011A8BDBD +:103320002E196902D9DBF33069B9DAF34C92F3A8AC +:10333000BD2E196901D9DFF33058B9DEF34C92F391 +:10334000A8BD2E196901D9E3F33047B9E2F34C92D5 +:10335000F3297FC001902AF014A8BD2E19E903D9E2 +:10336000DAF3102EB9DBF338E9034C92F3A8BD2E43 +:1033700019E902D9DEF3101AB9DFF338E9024C92E9 +:10338000F3A8BD2E19E900D9E2F31006B9E3F3382A +:10339000E9019D2E194CA2F2A205B5A63008F6DD72 +:1033A000D004A9FF95A6CA10F160008001810282B5 +:1033B00000800181028200800181028200800181FF +:1033C0000282010300010300010300010300030066 +:1033D000010300010300010300010024486C7B8B02 +:1033E0009BABEDF1F5F9F9AB6CD5F9ABFED5FDB3BF +:1033F00078DFFDB3FEDFED7B00020305030203006F +:103400000D0A08090D0C00A9FFA217958CCA10FB24 +:10341000A479B6C5CAA932958CBDAAF3297FA8B9EB +:10342000DAF39D2E1920CFF820F5F8CA10E7A22074 +:10343000BD16FD9DD71ACA10F760A20BA9009546CC +:10344000CA10FB60A90085428543854485456020FC +:10345000A6F1A907AA95B0CA10FBA483B9B1F48557 +:1034600084C898A20395850ACA10FAA903855285D3 +:1034700053A9068554A9FF85C385C485FDA9008588 +:10348000C585C68579858B85C185C285FB85FCA9E7 +:1034900001857EA9208589858AA5821009A9FF85D5 +:1034A0007FA939858060A901857FA97A858085817A +:1034B00060406080DFA900A88555A21F86569155FF +:1034C00088D0FBCAE017D0F4A2BE9541CAD0FB60F9 +:1034D000A20FBDF6FC95E8CA10F860A223A9FF95DB +:1034E0008C9D0018CA10F860A23FBDBAFC9D981AC6 +:1034F000CA10F7242810FCA91A852CA9008D971A48 +:103500008578A9E08534A940853C6060A5A5300395 +:103510004CC0F5C9FFD0F4A583F0F0A582C90130F5 +:1035200008A57E257FD0E4F006A679B57ED0DCA57F +:10353000762902D0D6A679B5C5F0D0A4E4F002C6AB +:10354000E4C6E6D0C6E6E6C000F004D5C7B0BCA528 +:10355000E538E906C914900285E5A5E585E6A915D3 +:1035600085E320AEF84A69108DE118AE2FFDA582E3 +:10357000C901D004A0081005A5790A0AA8B9470016 +:10358000C902B010A5E5301120AEF88555A5E54A71 +:10359000C555B005E8A014D002A02584A58EF01A68 +:1035A00020AEF84A9009A9A38DBD18A9FF3007A93C +:1035B000FC8DBD18A9018D5A18A9008D3918F0226B +:1035C000A576C9FE9034A583C901F01620AEF8C9CE +:1035D000AAB019C955B019ADE118C9ABB01CC90AD8 +:1035E0009018A9008D9C188D7B18F00EA9FF300251 +:1035F000A9018D9C18A9008D7B18AD5A18186DBDB6 +:1036000018C9A39013C9FDB00FA9FF85A5A908206B +:10361000B7F1A90920B7F160A201B5A63005CA101B +:10362000F93059C6E3D055A92085E3A90695A6A986 +:10363000EC95DDAD8B19C99F9002E99F9DBE18AD39 +:10364000B719C9BF9002E9BF9DE218A9009D0619EC +:103650009D2719A5A5C914F03D20AEF8291FA8B9CA +:1036600063F79D5B18B983F79D3A18B9A3F79D9D41 +:1036700018B9C3F79D7C18A90D2070F1A5764A4AA8 +:103680002903A4A5C014F0070A1869E14C92F618A2 +:1036900069E98D471960A900855785588559A58224 +:1036A000C9013018A57E257FF008A57ED00AA000AC +:1036B000100C20AEF80A90F6A0081002A48BB98A6C +:1036C0001938ED8B19B006E65749FF69018555B9E0 +:1036D000B61938EDB719B006E65849FF69018556A5 +:1036E0004A855A4A4A18655AC555B007E659A8A5E9 +:1036F0005584554A4A8556A5554A4A855A4A1865F9 +:103700005A855BA5554A855A4A4A18655AA000C58C +:10371000569006A002A900F002A55518655BC55693 +:103720009001C88455A459F007A90738E555855577 +:10373000A458F007A90F38E5558555A457F007A9F7 +:103740001F38E5558555A5E74A855B20AEF8A45B93 +:10375000395EF7C5E7B0F4655538E55B4C5CF603B8 +:1037600007070F0000010203030404040404030319 +:1037700002010000FFFEFDFCFCFBFBFBFBFBFCFC75 +:10378000FDFEFF00DBAD6E18A30B4A604A0BA318C9 +:103790006EADDB00265493E95EF6B7A1B7F65EE99D +:1037A000935426070606050403020100FEFDFCFBF8 +:1037B000FAF9F9F9F9F9FAFBFCFDFE00010203043C +:1037C00005060600DE78D2F3E4AE5E00A3531D0EBC +:1037D0002F89230123892F0E1D53A3005EAEE4F32E +:1037E000D278DE0123892F0E1D53A3005EAEE4F3D1 +:1037F000D278DEA679B5898D911A4A8D901AB5C511 +:10380000D065A5A5C9FFD05FA57E257FC902B057A9 +:10381000A582D007A48BB9A400304CC6FB1048A9E0 +:103820002585FBF6C3B5C3186902658395C5A483D6 +:10383000B992F8D5C5B00295C595C72065FCA90118 +:10384000209AF8A95085E4A683BD96F8A67938F5A4 +:10385000C3F5C3F5C385E585E6A90985E7A92885EC +:10386000E320AEF12007F420B1D6202AD3A582C9E7 +:1038700001300C20FAF920B1D6202AD320FAF92001 +:103880009CF22098F32090DA204DDA200CF520608D +:10389000F260080C0E1000A7958FA8B98500A479D6 +:1038A00018798900C5849002A58499890060A44094 +:1038B000B9002118A441790021A440990021C640F3 +:1038C0001004A0368440C6411004A0368441602014 +:1038D000AEF84A9010A9BF9DC81820AEF8C999B09B +:1038E000F99DA41860A99F9DA41820AEF8C9BFB087 +:1038F000F99DC8186020AEF82A900FED901A9D200F +:1039000018A9FFE9009D4118B00C6D901A9D201870 +:10391000A9002A9D411820AEF82A900FED911A9D1A +:103920006218A9FFE9009D8318B00C6D911A9D6281 +:1039300018A9002A9D8318608655A900855A855BC1 +:10394000BDA4186DAFF98556E99F9004E65A8556D7 +:10395000BDA418EDAFF9B004E65A699F8557BDC8FC +:10396000186DB0F98558E9BF9004E65B8558BDC86D +:1039700018EDB0F9B004E65B69BF8559A220B58C9B +:103980003027A900BCA418C4562AC4576900455A58 +:103990006A9016A900BCC818C4582AC459690045C1 +:1039A0005B6A9005E455F00160CA10D2A000601077 +:1039B0001A20EFF92045DFA582C901D019A9028597 +:1039C0007A20B3DE200DDFA900857A20B3DEA901BD +:1039D000857A20B3DE60A900857A20B3DE200DDF72 +:1039E000A582300AA901857A20B3DE200DDF60A20E +:1039F00037A9009D141BCA10FA60A5794901857981 +:103A0000F002A908858B6020AEF84A90054A900222 +:103A1000E6F64A90054A9002E6F7A57BC905F0163E +:103A2000C903F012A5764AB00DE660A5602CF7F93F +:103A3000D002491F85F260B939FD9D2E19B973FD79 +:103A40009DA418B990FD9DC818B956FD9DD71AA917 +:103A500007C0169002A923958C60290F1D37FD48D9 +:103A60004A29071D37FDE000F002A20495EB689596 +:103A7000EAA90095E960A21FBDF6FC9520CABDF633 +:103A8000FC9520CABDF6FC9520CACAE010B0E9B585 +:103A9000E89520CAB5E89520CAB5E89520CACA10AD +:103AA000EEE8862060A90185F9A5F9F00E2428101A +:103AB000F8242810F42076FA20BCFA60A904A20B9E +:103AC000956ACA10FBA223B58CF049C9FFF04529BD +:103AD0000FC906D045BDC81849FF290F8569BDC863 +:103AE000184A4A4A4AA8B96A001879A2FC8565B9F9 +:103AF000AEFC8566B96A006904996A00A000A9FE57 +:103B00009165C8A97F9165C8A56909C09165C8BDBF +:103B1000A4189165CA10B04CABFBBDC81849FF2969 +:103B20000F8569BDC8184A4A4A4AA8B96A00187977 +:103B3000A2FC8565B9AEFC8566B96A006904996A1C +:103B400000C8C00C9003A00018B96A0079A2FC85D7 +:103B500067B9AEFC8568B96A006904996A00A0007B +:103B6000BD2E1991659167C8BDD71A91659167C837 +:103B7000B58CC90718D006A56969D1D004A56969B3 +:103B8000B1916569109167C8BDA41891659167C925 +:103B9000979081E019F011C9F0B008E99F9DA41831 +:103BA0004C1AFB699F9DA4184C14FBA000A5751826 +:103BB0006DADFC8565ADB9FC8566A9449165C8A964 +:103BC000609165C8A91B9165C8A9789165C8A93994 +:103BD0009165A582C901D019C8A9349165C8A960A9 +:103BE0009165C8A91B9165C8A9909165C8A939912B +:103BF00065A000A574186DACFC8565ADB8FC856644 +:103C0000A9149165C8A9609165C8A91B9165C8A947 +:103C1000109165C8A9079165C8A9249165C8A960D4 +:103C20009165C8A91B9165C8A9309165C8A965911E +:103C300065A5751869058575A682E001D005186926 +:103C4000058575A57418690A8574A20BA001B56A6B +:103C5000187DA2FC8565BDAEFC8566A9009165CA8C +:103C600010EC85F960A20BBDA2FC8565BDAEFC859C +:103C70006620AEF82903186963A0009165C8BD9657 +:103C8000FC9165C8A9E0916520AEF84A6910A003CF +:103C90009165CA10D2607F9F7F7FBF7FDF7F7FFFEC +:103CA0009FDF008000800080008000800080222252 +:103CB000232324242525262627270F1A960B1A9618 +:103CC0000F1A96071A964F27804F27004F26804FCE +:103CD00026004F25804F25004F24804F24004F237E +:103CE000804F23004F22804F22008F1A960F1A9682 +:103CF0000F1A960F1A960000FDF500009D95008A98 +:103D00007146000F07E5000A060400D7D4D1003938 +:103D1000242100B6B3B09DBDDDFD9DBDDDFD9DBD83 +:103D2000DDFD9DBDDDFD9DBDDDFD9DBDDDFD1E5EA1 +:103D30007F7F7F7F7F7F3EF0903D43474B4F5357C0 +:103D4000595DBC676ED47C84909EA91621312CB538 +:103D5000B5B5B5B5BDCD5A5C5C5C5C5C5E5C5A6863 +:103D6000797276787472756D757574751E1E3E1E47 +:103D70003E1E3E061E2D3D4C5C6C74842306205076 +:103D80007C38373C2941413F4150505030703070B1 +:103D90007272727272727272720013131313505035 +:103DA00050507676686831382C31313131005020EE +:103DB00000000000000100000510020000030405DF +:103DC000060606050403020100000001020E0D0CA8 +:103DD0000A0908060504050608090A0C0D00020375 +:103DE000040504030200FEFDFCFBFCFDFE070605C6 +:103DF0000200FEFBFAF9FAFBFE00020506000000D5 +:103E0000000000000000FFFFFFFFFFFFFF000000B9 +:103E10000000FFFFFFFFFFFFFF00000000000B1886 +:103E20001F201F180B00F5E8E1E0E1E8F533301939 +:103E30000B00F5E7D0CDD0E7F5000B19300040F0CE +:103E40001FBB00008F270078D8A9028501A2FF9A26 +:103E5000A97F853CA9008520A27FBD51FF9D8004DC +:103E6000CA10F7A2ADBDA3FE9DFF22CAD0F7A900DC +:103E7000AA9501E8E02CD0F9A9028501A9FFA23F8B +:103E80009D00209D0021CA10F7A209BD3DFE9D00A6 +:103E900027CA10F7E8A050BD07279D0A27E888D059 +:103EA000F64C0723A91385014CC8FFA9168501A06C +:103EB000FFA27FBD00FED980FDD0E988CA10F4AD15 +:103EC000FCFF2DFDFFC9FFF0DBADFCFF0DFDFFF09A +:103ED000D3ADF8FF09FEC9FFD067ADF8FF49F0295F +:103EE000F0D05EADF9FF290BC903D055ADF9FF291C +:103EF000F0C940904CE901CDFDFFB045ADEA1B494A +:103F0000FF8DEA1BA8A205BDFAFFDDFADFD008CAC3 +:103F100010F5CCEA1BD02AA902850120A423A927E9 +:103F2000852CA9078530A9438578853CA20120A46A +:103F300023CA10FAA960853CA21686019AF86CFC87 +:103F4000FFA90285014C8004242830FC242810FCA1 +:103F500060A900AA85019503E8E02AD0F98502A9A5 +:103F600004EA3023A204CA10FD9A8D100120CB046C +:103F700020CB048511851B851C850FEA8502A900CD +:103F8000EA300424033009A90285098D12F1D01EFC +:103F90002402300CA90285068D18F18D60F4D00E34 +:103FA000852CA908851B20CB04EA240230D9A9FD61 +:103FB00085086CFCFF2044F4A5821002A9000A0ABF +:103FC0001865838555A901602048FF242830FCA985 +:103FD0009EA000A2002428300785248524CAD0F59D +:103FE000E078B004A998A02B85308C01204C00D03B +:103FF00000000000000000000000E9D247FE29D3C5 +:00000001FF diff --git a/Atari - 7800_TeST/rtl/rom/7800pal.rom b/Atari - 7800_TeST/rtl/rom/7800pal.rom new file mode 100644 index 0000000000000000000000000000000000000000..51d0d12f95f955fdcb66e72b003d62659af4669c GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/Atari - 7800_TeST/rtl/rom/Defender (1981) (Atari).a26 b/Atari - 7800_TeST/rtl/rom/Defender (1981) (Atari).a26 new file mode 100644 index 0000000000000000000000000000000000000000..d9843f2b7e1015cc405a9cf8632e20a2d755b489 GIT binary patch literal 4096 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 +// Copyright (c) 2017 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/Atari - 7800_TeST/rtl/sigma_delta_dac.sv b/Atari - 7800_TeST/rtl/sigma_delta_dac.sv new file mode 100644 index 00000000..29daea6e --- /dev/null +++ b/Atari - 7800_TeST/rtl/sigma_delta_dac.sv @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module sigma_delta_dac #(parameter MSBI=0) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= 1; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= ~SigmaLatch[MSBI+2]; + end +end + +endmodule diff --git a/Atari - 7800_TeST/rtl/tia.vh b/Atari - 7800_TeST/rtl/tia.vh new file mode 100644 index 00000000..04c8510a --- /dev/null +++ b/Atari - 7800_TeST/rtl/tia.vh @@ -0,0 +1,81 @@ +/* Atari on an FPGA +Masters of Engineering Project +Cornell University, 2007 +Daniel Beer + TIA.h +Header file that contains useful definitions for the TIA module. +*/ +`define CXM0P 7'h70 +`define CXM1P 7'h71 +`define CXP0FB 7'h72 +`define CXP1FB 7'h73 +`define CXM0FB 7'h74 +`define CXM1FB 7'h75 +`define CXBLPF 7'h76 +`define CXPPMM 7'h77 +`define INPT0 7'h78 +`define INPT1 7'h79 +`define INPT2 7'h7A +`define INPT3 7'h7B +`define INPT4 7'h7C +`define INPT5 7'h7D +`define VSYNC 7'h00 +`define VBLANK 7'h01 +`define WSYNC 7'h02 +`define RSYNC 7'h03 +`define NUSIZ0 7'h04 +`define NUSIZ1 7'h05 +`define COLUP0 7'h06 +`define COLUP1 7'h07 +`define COLUPF 7'h08 +`define COLUBK 7'h09 +`define CTRLPF 7'h0A +`define REFP0 7'h0B +`define REFP1 7'h0C +`define PF0 7'h0D +`define PF1 7'h0E +`define PF2 7'h0F +`define RESP0 7'h10 +`define RESP1 7'h11 +`define RESM0 7'h12 +`define RESM1 7'h13 +`define RESBL 7'h14 +`define AUDC0 7'h15 +`define AUDC1 7'h16 +`define AUDF0 7'h17 +`define AUDF1 7'h18 +`define AUDV0 7'h19 +`define AUDV1 7'h1A +`define GRP0 7'h1B +`define GRP1 7'h1C +`define ENAM0 7'h1D +`define ENAM1 7'h1E +`define ENABL 7'h1F +`define HMP0 7'h20 +`define HMP1 7'h21 +`define HMM0 7'h22 +`define HMM1 7'h23 +`define HMBL 7'h24 +`define VDELP0 7'h25 +`define VDELP1 7'h26 +`define VDELBL 7'h27 +`define RESMP0 7'h28 +`define RESMP1 7'h29 +`define HMOVE 7'h2A +`define HMCLR 7'h2B +`define CXCLR 7'h2C + +`define CXM0P_7800 7'h40 +`define CXM1P_7800 7'h41 +`define CXP0FB_7800 7'h42 +`define CXP1FB_7800 7'h43 +`define CXM0FB_7800 7'h44 +`define CXM1FB_7800 7'h45 +`define CXBLPF_7800 7'h46 +`define CXPPMM_7800 7'h47 +`define INPT0_7800 7'h48 +`define INPT1_7800 7'h49 +`define INPT2_7800 7'h4A +`define INPT3_7800 7'h4B +`define INPT4_7800 7'h4C +`define INPT5_7800 7'h4D \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/timing_ctrl.sv b/Atari - 7800_TeST/rtl/timing_ctrl.sv new file mode 100644 index 00000000..b40e1aef --- /dev/null +++ b/Atari - 7800_TeST/rtl/timing_ctrl.sv @@ -0,0 +1,361 @@ +`timescale 1ns / 1ps + +// Number of sysclk cycles needed for the halt signal to take on the CPU +`define DMA_STARTUP_CYCLES 9 + +// Number of sysclk cycles that the cpu gets at the start of a line +`define START_OF_LINE_CYCLES 24 + +// At which column we terminate DP DMA +`define DP_DMA_KILL_COL 435 + +// Column to start the ZP DMA, given that about 29 cycles are needed +// and there are 452 columns total. Plus some slack cycles. +// 9 for startup, 7 for access, 13 for shutdown +`define ZP_READY_COL 420 + +// VGA Row to start the ZP DMA. Rows 0-1 are the first visible line, +// rows 523-524 are the virst invisible line, rows 521-522 are buffering +// for the first invisible line, so ZP needs to be fetched by row 521. +`define ZP_READY_ROW 520 + +`define VGA_VISIBLE_COLS 640 + +`define NTSC_SCANLINE_COUNT 242 + +`define COOLDOWN_CYCLES 1 + +//`define OVERCLOCK + + + +module timing_ctrl ( + input logic enable, + + // Clocking + input logic sysclk, reset, pclk_2, + output logic pclk_0, tia_clk, + input logic sel_slow_clock, + + // Outputs to 6502 + output logic halt_b, int_b, ready, core_latch_data, + output logic VBLANK, + + // Signals to/from dma_ctrl + output logic zp_dma_start, dp_dma_start, + input logic zp_dma_done, dp_dma_done, + input logic dp_dma_done_dli, + output logic dp_dma_kill, + output logic last_line, + + // Signals to/from line_ram + output logic lram_swap, + + // VGA Status + input logic [9:0] vga_row, vga_col, + + // Signals from memory map + input logic deassert_ready, zp_written +); + + // Output buffers + logic [5:0] int_b_sr; + assign int_b = &int_b_sr; + + // Current NTSC row and col + logic [8:0] row, col; + + logic [9:0] vga_row_prev, vga_row_prev_prev; + + // Each ntsc line is two vga lines. Asserted => we are on second one + logic second_vga_line; + + // vga_row has changed in the last cycle + logic vga_line_delta; + + // Clock division + `ifndef OVERCLOCK + logic fast_ctr; + `endif + + logic [1:0] slow_ctr; + logic fast_clk, slow_clk; + + logic ready_for_lswap, ready_for_lswap_prev; + + // Ready to move to ZP_DMA_STARTUP + logic zp_ready; + + // interrupt on next cycle + logic dli_next, raise_dli; + + logic [4:0] startup_ctr; + logic cooldown_count; + + enum logic [31:0] { + VWAIT = 'h0, // Waiting for VSYNC to complete before starting ZP DMA + HWAIT = 'h1, // Waiting for HSYNC to complete before starting DP DMA + ZP_DMA_STARTUP = 'h2, // Waiting for HALT to reach CPU before starting ZP DMA + ZP_DMA = 'h3, // Waiting for DMA CTRL to finish ZP DMA + START_OF_LINE = 'h4, // Waiting for first 7 CPU cycles of line before DP DMA + DP_DMA_STARTUP = 'h5, // Waiting for HALT to reach CPU before starting DP DMA + DP_DMA = 'h6, // Waiting for DMA CTRL to finish DP DMA + DP_DMA_WAITSWAP = 'h7, // Done with DP DMA, but not ready to swap linerams yet + VWAIT_COOLDOWN = 'h8, + HWAIT_COOLDOWN = 'h9 + } state; + + assign vga_line_delta = vga_row_prev_prev != vga_row_prev; + + // In general, we are on the second row if the row number is odd (vga_row[0]) + // However, above 512 (521/522, 523/524) we are on the second row if the row + // number is even. + assign second_vga_line = vga_row[9] ^ vga_row[0]; + + assign dp_dma_kill = ((enable) & + (state == DP_DMA) & + (second_vga_line) & + (col == `DP_DMA_KILL_COL)); + + assign zp_ready = ((enable) & (vga_row == `ZP_READY_ROW) & + (col == `ZP_READY_COL)); + + assign last_line = (row == (`NTSC_SCANLINE_COUNT - 1)); + + assign VBLANK = (row >= 9'd241); + + assign pclk_0 = sel_slow_clock ? slow_clk : fast_clk; + + assign ready_for_lswap = ((enable) & second_vga_line & + (vga_col > `VGA_VISIBLE_COLS)); + assign lram_swap = (ready_for_lswap & + (((state == DP_DMA) & (dp_dma_done | dp_dma_kill)) || + (state == DP_DMA_WAITSWAP))); + + + always @(posedge sysclk, posedge reset) begin + if (reset) begin + state <= VWAIT; + row <= 9'b0; + col <= 9'b0; + vga_row_prev <= 10'd0; + fast_clk <= 1'b0; + cooldown_count <= 1'b0; + slow_clk <= 1'b0; + `ifndef OVERCLOCK + fast_ctr <= 1'b0; + `endif + slow_ctr <= 2'b0; + int_b_sr <= 6'b111111; + raise_dli <= 1'b0; + startup_ctr <= 4'd0; + dli_next <= 1'b0; + halt_b <= 1'b1; + zp_dma_start <= 1'b0; + dp_dma_start <= 1'b0; + core_latch_data <= 1'b0; + ready_for_lswap_prev <= 1'b0; + ready <= 1'b1; + tia_clk <= 1'b0; + end else begin + // Clock generation + tia_clk <= ~tia_clk; + core_latch_data <= 1'b0; + if (sel_slow_clock) begin + `ifndef OVERCLOCK + fast_ctr <= 1'b0; + `endif + + fast_clk <= 1'b1; + if (slow_ctr == 2'd2) begin + slow_ctr <= 2'b0; + slow_clk <= ~slow_clk; + if (slow_clk == 1'b0) + core_latch_data <= 1'b1; + end + else + slow_ctr <= slow_ctr + 2'b01; + end + else begin + slow_ctr <= 2'b00; + slow_clk <= 1'b1; + `ifdef OVERCLOCK + fast_clk <= ~fast_clk; + `else + fast_ctr <= ~fast_ctr; + if (fast_ctr) begin + fast_clk <= ~fast_clk; + if (fast_clk == 1'b0) + core_latch_data <= 1'b1; + end + `endif + end + + // Interrupt generation + int_b_sr <= {int_b_sr[4:0], ~(dli_next & enable)}; + //int_b_reg <= ~(dli_next & enable); + + vga_row_prev <= vga_row; + vga_row_prev_prev <= vga_row_prev; + ready_for_lswap_prev <= ready_for_lswap; + + // Column counting + if (vga_line_delta & ~second_vga_line) // Just changed to first line + col <= 0; + else + col <= col + 1; + + // Row counting + if (vga_line_delta & ~second_vga_line) begin + if (vga_row == 10'd521) + row <= 0; + else + row <= row + 1; + end + + // Ready signal + if (enable & deassert_ready) + ready <= 1'b0; + else if (ready_for_lswap & ~ready_for_lswap_prev) + ready <= 1'b1; + + // Next state logic + case (state) + VWAIT: begin + if (zp_ready & zp_written) begin + halt_b <= 1'b0; + raise_dli <= 1'b0; + dli_next <= 1'b0; + state <= ZP_DMA_STARTUP; + startup_ctr <= 1; + end + end + HWAIT: begin + if (~enable) begin + state <= VWAIT_COOLDOWN; + halt_b <= 1'b0; + raise_dli <= 1'b0; + dli_next <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (vga_line_delta) begin + state <= START_OF_LINE; + startup_ctr <= 1; + end + end + ZP_DMA_STARTUP: begin + startup_ctr <= startup_ctr + 1; + if (~enable) begin + state <= VWAIT_COOLDOWN; + raise_dli <= 1'b0; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (startup_ctr == `DMA_STARTUP_CYCLES) begin + zp_dma_start <= 1'b1; + state <= ZP_DMA; + end + end + ZP_DMA: begin + zp_dma_start <= 1'b0; + if (~enable) begin + state <= VWAIT_COOLDOWN; + raise_dli <= 1'b0; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (zp_dma_done) begin + state <= HWAIT_COOLDOWN; + raise_dli <= dp_dma_done_dli; + raise_dli <= 1'b0; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end + end + START_OF_LINE: begin + startup_ctr <= startup_ctr + 1; + if (~enable) begin + state <= VWAIT_COOLDOWN; + raise_dli <= 1'b0; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (startup_ctr == `START_OF_LINE_CYCLES) begin + halt_b <= 1'b0; + state <= DP_DMA_STARTUP; + startup_ctr <= 1; + end + end + DP_DMA_STARTUP: begin + startup_ctr <= startup_ctr + 1; + if (~enable) begin + state <= VWAIT_COOLDOWN; + raise_dli <= 1'b0; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (startup_ctr == `DMA_STARTUP_CYCLES) begin + dp_dma_start <= 1'b1; + raise_dli <= 1'b0; + state <= DP_DMA; + end + end + DP_DMA: begin + dp_dma_start <= 1'b0; + if (~enable) begin + state <= VWAIT_COOLDOWN; + halt_b <= 1'b0; + cooldown_count <= `COOLDOWN_CYCLES; + end else if (dp_dma_done | dp_dma_kill) begin + halt_b <= 1'b0; + raise_dli <= dp_dma_done_dli; + cooldown_count <= `COOLDOWN_CYCLES; + if (ready_for_lswap) begin + state <= last_line ? VWAIT_COOLDOWN : HWAIT_COOLDOWN; + end else begin + state <= DP_DMA_WAITSWAP; + end + end + end + DP_DMA_WAITSWAP: begin + if (~enable) begin + state <= VWAIT_COOLDOWN; + end else if (cooldown_count == 0) begin + if ((sel_slow_clock && slow_ctr != 2'b10) || + (~sel_slow_clock && fast_clk == 1'b1)) begin + halt_b <= 1'b1; + raise_dli <= 1'b0; + dli_next <= raise_dli; + end + end else begin + cooldown_count <= cooldown_count - 1; + end + if (ready_for_lswap) begin + state <= last_line ? VWAIT_COOLDOWN : HWAIT_COOLDOWN; + end + end + VWAIT_COOLDOWN: begin + if (cooldown_count == 0) begin + if ((sel_slow_clock && slow_ctr != 2'b10) || + (~sel_slow_clock && fast_clk == 1'b1)) begin + halt_b <= 1'b1; + raise_dli <= 1'b0; + dli_next <= raise_dli; + state <= VWAIT; + end + end else begin + cooldown_count <= cooldown_count - 1; + end + end + HWAIT_COOLDOWN: begin + if (cooldown_count == 0) begin + if ((sel_slow_clock && slow_ctr != 2'b10) || + (~sel_slow_clock && fast_clk == 1'b1)) begin + halt_b <= 1'b1; + raise_dli <= 1'b0; + dli_next <= raise_dli; + state <= HWAIT; + end + end else begin + cooldown_count <= cooldown_count - 1; + end + end + endcase + end + end +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/uv_to_vga.sv b/Atari - 7800_TeST/rtl/uv_to_vga.sv new file mode 100644 index 00000000..f890e5aa --- /dev/null +++ b/Atari - 7800_TeST/rtl/uv_to_vga.sv @@ -0,0 +1,218 @@ +`timescale 1ns / 1ps +/** Line buffer to VGA Interface + * + * input lbuffer is the line buffer. + * For column c, 0 <= c < 640, where 0 is left and 639 is right, + * lbuffer[c][0] is RED, where 4'hF is the most intense red and + * 4'h0 is the least intense red. + * lbuffer[c][1] is GREEN and lbuffer[c][2] is BLUE. + * + * output line_number indicates the current row, where the top + * of the screen is 0 and 479 is the bottom of the screen. Other + * values indicate that no line is currently being drawn. + * + * clk should be hooked up to a 25MHz clock (or 25.175 if available.) + * reset should be hooked up to system reset. + * RED, GREEN, BLUE, HSync, and VSync should be hooked up to the + * appropriate VGA pins. + **/ + +//`define FRAMEBUF + +module uv_to_vga ( + input logic clk, reset, + input logic [7:0] uv_in, + + output logic [9:0] row, col, + output logic [3:0] RED, GREEN, BLUE, + output logic HSync, VSync, + + input logic tia_en, tia_clk, + input logic tia_hblank, + input logic tia_vblank +); + + + + logic col_clear, row_clear; + logic col_enable, row_enable; + + // Chrominance-Luminance palettes (represented as rgb) + logic [255:0][3:0] red_palette, green_palette, blue_palette; + + logic [7:0] rbuf, gbuf, bbuf; + logic [7:0] uv; + + logic visible, tia_visible; + assign visible = (row < 10'd480) & (col < 10'd640); + + `ifdef FRAMEBUF + assign tia_visible = (row >= 10'd48) & (row <10'd432) & (col < 10'd640); + + logic [9:0] tia_row, tia_col; + assign tia_row = row - 10'd48; + assign tia_col = col; + + logic [7:0] fbuf_uv1, fbuf_uv2; + (* keep = "true" *) logic [7:0] fbuf_uv1_kept, fbuf_uv2_kept; + assign fbuf_uv1_kept = fbuf_uv1; + assign fbuf_uv2_kept = fbuf_uv2; + + logic [14:0] buf_w_addr, buf_r_addr; + (* keep = "true" *) logic [14:0] buf_w_addr_kept; + (* keep = "true" *) logic [14:0] buf_r_addr_kept; + assign buf_w_addr = tia_write_row*14'd160+tia_write_col; + assign buf_r_addr = tia_row[8:1]*14'd160+tia_col[9:2]; + assign buf_w_addr_kept = buf_w_addr; + assign buf_r_addr_kept = buf_r_addr; + logic write_buf1; + + Frame_Buf frame_buffer1( + .clka(tia_clk), // input wire clka + .ena(~tia_vblank & ~tia_hblank & write_buf1), // input wire ena + .wea(write_buf1), // input wire [0 : 0] wea + .addra(buf_w_addr), // input wire [14 : 0] addra + .dina(uv_in), // input wire [7 : 0] dina + .clkb(clk), // input wire clkb + .enb(tia_visible), // input wire enb + .addrb(buf_r_addr), // input wire [14 : 0] addrb + .doutb(fbuf_uv1) // output wire [7 : 0] doutb + ); + + Frame_Buf frame_buffer2( + .clka(tia_clk), // input wire clka + .ena(~tia_vblank & ~tia_hblank & ~write_buf1), // input wire ena + .wea(~write_buf1), // input wire [0 : 0] wea + .addra(buf_w_addr), // input wire [14 : 0] addra + .dina(uv_in), // input wire [7 : 0] dina + .clkb(clk), // input wire clkb + .enb(tia_visible), // input wire enb + .addrb(buf_r_addr), // input wire [14 : 0] addrb + .doutb(fbuf_uv2) // output wire [7 : 0] doutb + ); + + logic [7:0] tia_write_row; + logic [7:0] tia_write_col; + (* keep = "true" *) logic [7:0] tia_write_row_kept; + (* keep = "true" *) logic [7:0] tia_write_col_kept; + assign tia_write_row_kept = tia_write_row; + assign tia_write_col_kept = tia_write_col; + + logic tia_hblank_buf, tia_vblank_buf; + + always_ff @(posedge tia_clk, posedge reset) begin + if (reset) begin + tia_write_row <= 0; + tia_write_col <= 0; + tia_hblank_buf <= 0; + tia_vblank_buf <= 0; + end else begin + tia_hblank_buf <= tia_hblank; + tia_vblank_buf <= tia_vblank; + if (~tia_vblank_buf & tia_vblank) + write_buf1 <= ~write_buf1; + if (tia_hblank) begin + tia_write_col <= 8'b0; + if (~tia_hblank_buf & ~tia_vblank) begin + tia_write_row <= tia_write_row + 1; + end + end else begin + tia_write_col <= tia_write_col + 1; + end + + if (tia_vblank) + tia_write_row <= 8'd0; + end + end + + logic [7:0] uv_from_fbuf; + assign uv_from_fbuf = (write_buf1) ? fbuf_uv2 : fbuf_uv1; + assign uv = tia_en ? (tia_visible ? uv_from_fbuf : 8'd0) : (visible ? uv_in : 8'd0); + `else + assign uv = uv_in; + `endif + + + assign RED = rbuf; + assign GREEN = gbuf; + assign BLUE = bbuf; + // UV Palette data found at: http://atariage.com/forums/topic/209210-complete-ntsc-pal-color-palettes/ + // These three assign statements generated by Atari7800/palettes.py + assign red_palette = {4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0}; + assign rbuf = red_palette[uv]; + + assign green_palette = {4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h1, 4'h0, 4'h0, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h0, 4'h0, 4'h0, 4'h0, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'he, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0}; + assign gbuf = green_palette[uv]; + + assign blue_palette = {4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'ha, 4'h9, 4'h8, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'hf, 4'hf, 4'hf, 4'hf, 4'hd, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h4, 4'h3, 4'h2, 4'h1, 4'hf, 4'he, 4'hc, 4'hb, 4'ha, 4'h9, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'hb, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'ha, 4'h9, 4'h8, 4'h7, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'hf, 4'hf, 4'he, 4'hd, 4'hc, 4'hb, 4'ha, 4'h8, 4'h7, 4'h6, 4'h5, 4'h4, 4'h3, 4'h2, 4'h1, 4'h0}; + assign bbuf = blue_palette[uv]; + + + // Row counter counts from 0 to 520 + // count of 0 - 479 is display time (row == line_number here) + // count of 480 - 489 is front porch + // count of 490 - 491 is VS=0 pulse width + // count of 492 - 525 is back porch + + always @(posedge clk, posedge reset) + if (reset) begin + row <= 10'd519; + end else if (row_clear) + row <= 10'd0; + else + row <= row + row_enable; + + assign row_clear = (row == 10'd524) & row_enable; + assign row_enable = (col == 10'd799); + assign VSync = (row < 10'd490) | (row > 10'd491); + + // Col counter counts from 0 to 799 + // count of 0 - 639 is display time + // count of 640 - 655 is front porch + // count of 656 - 751 is HS=0 pulse width + // count of 752 - 799 is back porch + + always @(posedge clk)//, reset) + if (reset | col_clear) + col <= 10'd0; + else + col <= col + col_enable; + + /*logic [7:0] tia_buf_col; + logic write_buf1; + logic [7:0][159:0] tia_buf1; + logic [7:0][159:0] tia_buf2; + integer i; + + always @(posedge tia_hblank) + write_buf1 <= ~write_buf1; + + always @(posedge tia_clk, posedge reset) begin + if (reset) begin + tia_buf_col <= 7'b0; + tia_buf1 <= 1280'b0; + tia_buf2 <= 1280'b0; + end else if (tia_en & tia_vsync_delta) begin + tia_buf_col <= 7'b0; + for (i=0;i<160;i=i+1) begin + tia_buf1[i] <= 8'b0; + tia_buf2[i] <= 8'b0; + end + end else if (tia_hblank) + tia_buf_col <= 8'd160; + else if (tia_buf_col == 8'd227) + tia_buf_col <= 8'd0; + else begin + tia_buf_col <= tia_buf_col + 1; + if (write_buf1) + tia_buf1[tia_buf_col] <= uv_in; + else + tia_buf2[tia_buf_col] <= uv_in; + end + end*/ + + assign col_clear = row_enable; + assign col_enable = 1'b1; + assign HSync = (col < 10'd656) | (col > 10'd751); + +endmodule \ No newline at end of file diff --git a/Atari - 7800_TeST/rtl/video_mixer.sv b/Atari - 7800_TeST/rtl/video_mixer.sv new file mode 100644 index 00000000..ec953e53 --- /dev/null +++ b/Atari - 7800_TeST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd7, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule