mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-26 16:43:21 +00:00
Add Gauntlet Code WIP
This commit is contained in:
30
Arcade_MiST/Atari Gauntlet Hardware/Gauntlet_MiST.qpf
Normal file
30
Arcade_MiST/Atari Gauntlet Hardware/Gauntlet_MiST.qpf
Normal file
@@ -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 = 18:28:29 January 01, 2020
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "13.1"
|
||||
DATE = "18:28:29 January 01, 2020"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "Gauntlet_MiST"
|
||||
259
Arcade_MiST/Atari Gauntlet Hardware/Gauntlet_MiST.qsf
Normal file
259
Arcade_MiST/Atari Gauntlet Hardware/Gauntlet_MiST.qsf
Normal file
@@ -0,0 +1,259 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# 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 = 15:32:36 April 12, 2020
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# 1) The default values for assignments are stored in the file:
|
||||
# Gauntlet_MiST_assignment_defaults.qdf
|
||||
# If this file doesn't exist, see file:
|
||||
# assignment_defaults.qdf
|
||||
#
|
||||
# 2) Altera recommends that you do not modify this file. This
|
||||
# file is updated automatically by the Quartus II software
|
||||
# and any changes you make may be lost or overwritten.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
|
||||
# Project-Wide Assignments
|
||||
# ========================
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:22:13 JUNE 04, 2019"
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
||||
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name SMART_RECOMPILE ON
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
set_location_assignment PIN_7 -to LED
|
||||
set_location_assignment PIN_54 -to CLOCK_27
|
||||
set_location_assignment PIN_144 -to VGA_R[5]
|
||||
set_location_assignment PIN_143 -to VGA_R[4]
|
||||
set_location_assignment PIN_142 -to VGA_R[3]
|
||||
set_location_assignment PIN_141 -to VGA_R[2]
|
||||
set_location_assignment PIN_137 -to VGA_R[1]
|
||||
set_location_assignment PIN_135 -to VGA_R[0]
|
||||
set_location_assignment PIN_133 -to VGA_B[5]
|
||||
set_location_assignment PIN_132 -to VGA_B[4]
|
||||
set_location_assignment PIN_125 -to VGA_B[3]
|
||||
set_location_assignment PIN_121 -to VGA_B[2]
|
||||
set_location_assignment PIN_120 -to VGA_B[1]
|
||||
set_location_assignment PIN_115 -to VGA_B[0]
|
||||
set_location_assignment PIN_114 -to VGA_G[5]
|
||||
set_location_assignment PIN_113 -to VGA_G[4]
|
||||
set_location_assignment PIN_112 -to VGA_G[3]
|
||||
set_location_assignment PIN_111 -to VGA_G[2]
|
||||
set_location_assignment PIN_110 -to VGA_G[1]
|
||||
set_location_assignment PIN_106 -to VGA_G[0]
|
||||
set_location_assignment PIN_136 -to VGA_VS
|
||||
set_location_assignment PIN_119 -to VGA_HS
|
||||
set_location_assignment PIN_65 -to AUDIO_L
|
||||
set_location_assignment PIN_80 -to AUDIO_R
|
||||
set_location_assignment PIN_105 -to SPI_DO
|
||||
set_location_assignment PIN_88 -to SPI_DI
|
||||
set_location_assignment PIN_126 -to SPI_SCK
|
||||
set_location_assignment PIN_127 -to SPI_SS2
|
||||
set_location_assignment PIN_91 -to SPI_SS3
|
||||
set_location_assignment PIN_13 -to CONF_DATA0
|
||||
set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component"
|
||||
set_location_assignment PIN_49 -to SDRAM_A[0]
|
||||
set_location_assignment PIN_44 -to SDRAM_A[1]
|
||||
set_location_assignment PIN_42 -to SDRAM_A[2]
|
||||
set_location_assignment PIN_39 -to SDRAM_A[3]
|
||||
set_location_assignment PIN_4 -to SDRAM_A[4]
|
||||
set_location_assignment PIN_6 -to SDRAM_A[5]
|
||||
set_location_assignment PIN_8 -to SDRAM_A[6]
|
||||
set_location_assignment PIN_10 -to SDRAM_A[7]
|
||||
set_location_assignment PIN_11 -to SDRAM_A[8]
|
||||
set_location_assignment PIN_28 -to SDRAM_A[9]
|
||||
set_location_assignment PIN_50 -to SDRAM_A[10]
|
||||
set_location_assignment PIN_30 -to SDRAM_A[11]
|
||||
set_location_assignment PIN_32 -to SDRAM_A[12]
|
||||
set_location_assignment PIN_83 -to SDRAM_DQ[0]
|
||||
set_location_assignment PIN_79 -to SDRAM_DQ[1]
|
||||
set_location_assignment PIN_77 -to SDRAM_DQ[2]
|
||||
set_location_assignment PIN_76 -to SDRAM_DQ[3]
|
||||
set_location_assignment PIN_72 -to SDRAM_DQ[4]
|
||||
set_location_assignment PIN_71 -to SDRAM_DQ[5]
|
||||
set_location_assignment PIN_69 -to SDRAM_DQ[6]
|
||||
set_location_assignment PIN_68 -to SDRAM_DQ[7]
|
||||
set_location_assignment PIN_86 -to SDRAM_DQ[8]
|
||||
set_location_assignment PIN_87 -to SDRAM_DQ[9]
|
||||
set_location_assignment PIN_98 -to SDRAM_DQ[10]
|
||||
set_location_assignment PIN_99 -to SDRAM_DQ[11]
|
||||
set_location_assignment PIN_100 -to SDRAM_DQ[12]
|
||||
set_location_assignment PIN_101 -to SDRAM_DQ[13]
|
||||
set_location_assignment PIN_103 -to SDRAM_DQ[14]
|
||||
set_location_assignment PIN_104 -to SDRAM_DQ[15]
|
||||
set_location_assignment PIN_58 -to SDRAM_BA[0]
|
||||
set_location_assignment PIN_51 -to SDRAM_BA[1]
|
||||
set_location_assignment PIN_85 -to SDRAM_DQMH
|
||||
set_location_assignment PIN_67 -to SDRAM_DQML
|
||||
set_location_assignment PIN_60 -to SDRAM_nRAS
|
||||
set_location_assignment PIN_64 -to SDRAM_nCAS
|
||||
set_location_assignment PIN_66 -to SDRAM_nWE
|
||||
set_location_assignment PIN_59 -to SDRAM_nCS
|
||||
set_location_assignment PIN_33 -to SDRAM_CKE
|
||||
set_location_assignment PIN_43 -to SDRAM_CLK
|
||||
|
||||
# Classic Timing Assignments
|
||||
# ==========================
|
||||
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
|
||||
set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON
|
||||
|
||||
# Analysis & Synthesis Assignments
|
||||
# ================================
|
||||
set_global_assignment -name FAMILY "Cyclone III"
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY Gauntlet_MiST
|
||||
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
|
||||
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
|
||||
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
|
||||
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
set_global_assignment -name DEVICE EP3C25E144C8
|
||||
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
|
||||
set_global_assignment -name ENABLE_NCE_PIN OFF
|
||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
|
||||
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
||||
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
|
||||
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
|
||||
# Assembler Assignments
|
||||
# =====================
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
|
||||
# SignalTap II Assignments
|
||||
# ========================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/trop.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
|
||||
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
|
||||
|
||||
# Advanced I/O Timing Assignments
|
||||
# ===============================
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
|
||||
|
||||
# ---------------------------
|
||||
# start ENTITY(Gauntlet_MiST)
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
|
||||
# start DESIGN_PARTITION(Top)
|
||||
# ---------------------------
|
||||
|
||||
# Incremental Compilation Assignments
|
||||
# ===================================
|
||||
|
||||
# end DESIGN_PARTITION(Top)
|
||||
# -------------------------
|
||||
|
||||
# end ENTITY(Gauntlet_MiST)
|
||||
# -------------------------
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*]
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*]
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gauntlet_MiST.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/GAUNTLET.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/MAIN.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/spram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/VIDEO.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/AUDIO.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/SLAPSTIC.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/VRAMS.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/SLAGS.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/PFHS.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/MOHLB.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/SYNGEN.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/GPC.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/CRAMS.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/POKEY.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/TMS5220.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/LS299.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/LINEBUF.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/ROM_6P.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/PROM_5L.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/PROM_5E.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/PROM_4R.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/EEP_14A.vhd
|
||||
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/CPU/68000/tg68last/TG68K.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/CPU/T65/T65.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/Sound/jt51/jt51.qip
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
15
Arcade_MiST/Atari Gauntlet Hardware/clean.bat
Normal file
15
Arcade_MiST/Atari Gauntlet Hardware/clean.bat
Normal file
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
del /s *.bak
|
||||
del /s *.orig
|
||||
del /s *.rej
|
||||
rmdir /s /q db
|
||||
rmdir /s /q incremental_db
|
||||
rmdir /s /q output
|
||||
rmdir /s /q simulation
|
||||
rmdir /s /q greybox_tmp
|
||||
del PLLJ_PLLSPE_INFO.txt
|
||||
del *.qws
|
||||
del *.ppf
|
||||
del *.qip
|
||||
del *.ddb
|
||||
pause
|
||||
BIN
Arcade_MiST/Atari Gauntlet Hardware/doc/Gauntlet_FPGA-master.zip
Normal file
BIN
Arcade_MiST/Atari Gauntlet Hardware/doc/Gauntlet_FPGA-master.zip
Normal file
Binary file not shown.
Binary file not shown.
BIN
Arcade_MiST/Atari Gauntlet Hardware/doc/gauntlet.zip
Normal file
BIN
Arcade_MiST/Atari Gauntlet Hardware/doc/gauntlet.zip
Normal file
Binary file not shown.
589
Arcade_MiST/Atari Gauntlet Hardware/doc/readme.md
Normal file
589
Arcade_MiST/Atari Gauntlet Hardware/doc/readme.md
Normal file
@@ -0,0 +1,589 @@
|
||||
# Atari Gauntlet FPGA Arcade
|
||||
|
||||
## Hardware
|
||||
Initially all screen shots here were generated from test bench output of what the video signal would look like if it was displayed on a monitor. The testbench dumps the output video values for each frame in a .ppm (portable pixmap) text file which can then be directly viewed by a suitable viewer (eg FastStone Image Viewer). The .ppm file format consists of one line with the pixmap magic value P3, next line is the X and Y resolution and max number of colors, followed by hopefully at least X*Y lines of RGB color triplets like so:
|
||||
|
||||
<pre>
|
||||
P3
|
||||
336 240 15
|
||||
15 15 15
|
||||
0 0 0
|
||||
15 15 15
|
||||
12 11 15
|
||||
10 9 15
|
||||
...
|
||||
</pre>
|
||||
To start with, the Video section of the arcade game was implemented and debugged (sheets 8 though 16 in the schematic). Because there was no CPU to run the game, for simulation purposes the video RAMs are initialized with data dumped from MAME so as to produce the relevant game screens.
|
||||
|
||||
Progress has been made and the game has been successfully run on a Pipistrello FPGA board with a custom add-on board which has a 2Mx16 SRAM chip rated at 10ns access time. This is needed because there is no space inside the FPGA to store all the game ROMs.
|
||||
|
||||
## Platform Information
|
||||
|
||||
The following collection of information serves as notes used during debugging.
|
||||
|
||||
### Video Output
|
||||
|
||||
The game has a resolution of 336x240 pixels.
|
||||
|
||||
The video output is generated in `IRGB` format before being converted to `RGB` (sheet 16) so the total number of colors are 4 bits per color, plus a common 4 bit intensity for all colors for a total of 16 bits or 65536 colors.
|
||||
|
||||
The game uses the typical three layer video layout, `Text`, `Sprites` and `Background` with `Text` having the highest display priority (obscures sprites and playfield), `Sprites` having medium priority (only obscures background) and `Background` having the lowest priority. The schematic refers to the text layer as `AL` which seems to stand for Alphanumerics, the sprite layer is `MO` for Motion Objects and the background is `PF` for Play Field.
|
||||
|
||||
### Video Memory Layout
|
||||
|
||||
Table below borrowed from MAME source code. The video uses a total of 24KB RAM for the VRAM (video RAM) organized as three sections of 4Kb x 16 bits:
|
||||
<pre>
|
||||
Playfield
|
||||
PF 900000-901FFF R/W xxxxxxxx xxxxxxxx Playfield RAM (64x64 tiles)
|
||||
R/W x------- -------- (Horizontal flip)
|
||||
R/W -xxx---- -------- (Palette select)
|
||||
R/W ----xxxx xxxxxxxx (Tile index)
|
||||
|
||||
Motion Objects
|
||||
MO 902000-9027FF R/W xxxxxxxx xxxxxxxx Motion object RAM TILE
|
||||
R/W -xxxxxxx xxxxxxxx (Tile index)
|
||||
MO 902800-902FFF R/W xxxxxxxx xxxxxxxx Motion object RAM XPOS
|
||||
R/W xxxxxxxx x------- (X position)
|
||||
R/W -------- ----xxxx (Palette select)
|
||||
MO 903000-9037FF R/W xxxxxxxx xxxxxxxx Motion object RAM YPOS
|
||||
R/W xxxxxxxx x------- (Y position)
|
||||
R/W -------- -x------ (Horizontal flip)
|
||||
R/W -------- --xxx--- (Number of X tiles - 1)
|
||||
R/W -------- -----xxx (Number of Y tiles - 1)
|
||||
MO 903800-903FFF R/W xxxxxxxx xxxxxxxx Motion object RAM LINK
|
||||
R/W ------xx xxxxxxxx (Link to next object)
|
||||
Spare Video
|
||||
SP 904000-904FFF R/W xxxxxxxx xxxxxxxx Spare video RAM
|
||||
|
||||
Alphanumerics
|
||||
AL 905000-905ED3 R/W xxxxxxxx xxxxxxxx Alphanumerics RAM (64x32 tiles)
|
||||
R/W x------- -------- (Opaque/transparent)
|
||||
R/W -xxxxx-- -------- (Palette select)
|
||||
R/W ------xx xxxxxxxx (Tile index)
|
||||
905F6E R/W xxxxxxxx x-----xx Playfield Y scroll/tile bank select
|
||||
R/W xxxxxxxx x------- (Playfield Y scroll)
|
||||
R/W -------- ------xx (Playfield tile bank select)
|
||||
AL 905F80-905FBF R/W xxxxxxxx xxxxxxxx
|
||||
AL 905FC0-905FFF R/W xxxxxxxx xxxxxxxx
|
||||
</pre>
|
||||
Additionally 2KB RAM are used for the CRAM (color palette RAM):
|
||||
<pre>
|
||||
AL 910000-9101FF R/W xxxxxxxx xxxxxxxx Alphanumerics palette RAM (256 entries)
|
||||
MO 910200-9103FF R/W xxxxxxxx xxxxxxxx Motion object palette RAM (256 entries)
|
||||
PL 910400-9105FF R/W xxxxxxxx xxxxxxxx Playfield palette RAM (256 entries)
|
||||
EX 910600-9107FF R/W xxxxxxxx xxxxxxxx Extra palette RAM (256 entries)
|
||||
R/W xxxx---- -------- (Intensity)
|
||||
R/W ----xxxx -------- (Red)
|
||||
R/W -------- xxxx---- (Green)
|
||||
R/W -------- ----xxxx (Blue)
|
||||
</pre>
|
||||
|
||||
There are 42 visible text lines across and 30 down, each text character requires a word
|
||||
Top line starts at 905000 - 905053, remaining 22 words not visible on screen
|
||||
Next line starts at 905080 - 9050D3, remaining 22 words not visible on screen
|
||||
etc...
|
||||
Bottom line starts at 905E80 - 905ED3, remaining 22 words not visible on screen
|
||||
|
||||
### Special Memory Locations
|
||||
|
||||
There are two special memory locations at 930000 and 905F6E that control overall MO and PF horizontal and vertical offset (scroll)
|
||||
|
||||
- 930000 = PF and MO horizontal scroll. Increasing values scrolls the playfield left. Any write to memory range 930XXX will work. The bottom 9 bits of the `WORD` written to 930000 will be latched by signal `/HSCRLD` into a 9 bit register formed by chips `9S` `6M` `7M` as well as latched into the internal register of custom chip `12K`, the `PFHS` (Play Field Horizontal Scroller). At game startup this is initialized to 0005.
|
||||
|
||||
- 905F6E = PF and MO vertical scroll. Increasing values scroll playfield up. This memory location is scanned each video frame and the top 9 bits are loaded into presettable counters `5J`,`5F`,`4F` when both `/VSYNC` and `/PFHST` are active (start of each video frame). The counters counts up from that value for each horizontal line. This effectively pushes an offset into VPOS via the adders `5D`, `5E`. Lowest 2 bits are also loaded into a counter at each start of frame and count up modulo 4 into a 2:4 decoder which selects graphic ROM chip selects `GCS0`..`GCS3`
|
||||
|
||||
### Sprite Format
|
||||
Sprites are stored at memory range 902000-903FFF. A single sprite is defined by four words: a tile, xpos, ypos and link value stored at the same offset in four different memory regions (some additional attributes are also stored, see detailed memory map above).
|
||||
|
||||
The sprites form a linked list via the LINK memory region 903800-903FFF
|
||||
|
||||
The link to the next sprite is obtained by doubling the current LINK offset and adding it to LINK memory base 903800.
|
||||
|
||||
For example at game startup the initial screen has the sprite link list shown below based on initial sprite offset 0046. Doubling the offset, we get 8C and adding it to LINK base memory 903800 we get 90388C, then as per the table below each memory has a LINK offset pointing to the next sprite LINK address. Note that many tiles in the link list do not contain a visible sprite (value 0800) yet they are still part of the linked list, perhaps simply waiting for a valid sprite value to be stored at those addresses and the sprite then becomes visible.
|
||||
<pre>
|
||||
Memory 90388C 90389C 9038AA 9038B8 903978 90397A 90397C 90398C 903A1C 903A2C 903C38 903C3A 903C3C 903C7A 903D18 903D1A
|
||||
Sprite 097E 0990 08FC 0AFC 1D42 1D48 1D52 1648 096C 0990 0800 0800 0800 09AB 0800 0800
|
||||
Memory 903D1C 903D1E 903D20 903D58 903D5A 903D5C 903D5E 903D60 903D7A 903D98 903D9A 903D9C 903D9E 903DA0 903DD8 903DDA
|
||||
Sprite 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800
|
||||
Memory 903DDC 903DDE 903DE0 903E18 903E1A 903E1C 903E1E 903E20 903E58 903E5A 903E5C 903E5E 903E60 903E98 903E9A 903E9C
|
||||
Sprite 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800
|
||||
Memory 903E9E 903EA0 903ED8 903EDA 903EDC 903EDE 903EE0 903F18 903F1A 903F1C 903F1E 903F20 903F58 903F5A 903F5C 903F5E
|
||||
Sprite 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800
|
||||
Memory 903F60 903F98 903F9A 903F9C 903F9E 903FA0 903FD8 903FDA 903FDC 903FDE 903FE0 903FFA 903800
|
||||
Sprite 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 0800 09E1 0000
|
||||
</pre>
|
||||
|
||||
The sprite link list does not appear to be circular, so the LINK register must be somehow initialized with the offset of the first sprite in the link list at the start of each horizontal scanline. It appears that the first memory location (index=0) does not contain a LINK to a valid sprite during gameplay so once that memory location is reached, the LINK register remains zeroed until it is loaded again with a valid index.
|
||||
|
||||
Memory region 905F80-905FFF seems to control sprite visibility as follows
|
||||
905F80 enables sprites on first 8 lines of screen 1..8
|
||||
905F82 enables sprites on next 8 lines of screen 9..16
|
||||
...
|
||||
905FB8 enables sprites on next 8 lines of screen 321..328
|
||||
905FBA enables sprites on last 8 lines of screen 329..336
|
||||
|
||||
To be determined
|
||||
905FC0
|
||||
..
|
||||
905FFE
|
||||
|
||||
At each location, the word's top 6 bits seem to be unused and the word's bottom 10 bits (when doubled) is a pointer to a sprite offset (typically the first sprite in a linked list).
|
||||
|
||||
So for every word in the memory range 905F80-905FBA, if the word's bottom 10 bits point to a valid sprite, then if that sprite or any other sprites linked from it have y coordinates that fall within the screen range of 8 lines covered by that memory location, those portions of those sprites are visible on those lines on the screen.
|
||||
|
||||
From simulation, this memory range is scanned during each horizontal line, data from MO VRAM ends up on VRD then loaded on LINK register latch `8F`, `8J` on rising `RCLK` when `/LINK` signal is low.
|
||||
|
||||
## It's Alive!!!
|
||||
After the initial translation of the schematic to RTL, the simulation produces the frame of video on the left but it's not the expected output as can be seen on the right from MAME:
|
||||
[](images/SIM00.png)
|
||||
[](images/MAME02.png)
|
||||
|
||||
### Debugging the alphanumerics:
|
||||
The top right corner under the Gauntlet logo, where the first text line should read "LEVEL 1", the L begins to be drawn but instead of drawing an L shape the display shows the 2 pixels of the top of the L replicated for all 8 lines after. All text characters exhibit this same behaviour.
|
||||
|
||||
Pixel data goes to GPC `APIX1`, `APIX0` from shifters `7P`, `7N` fed by `ROM 6P` driven by `VRD` bus through latches `4P`, `7R` on `4H` rising clock. `ROM 6P` address is `VRD9..0` registered, plus unregistered signals `4V`, `2V`, `1V`, `/4H`, address changes every 4 cycles.
|
||||
|
||||
Turns out `4V`, `2V`, `1V` were not being driven so `ROM 6P` was not being addressed properly and was not outputting enough new data to form proper characters. Connecting the additional signals properly produces a much more recognizable picture:
|
||||
[](images/SIM03.png)
|
||||
|
||||
Additionally GPC `I_D` bus connect order was wrong, so the colors were also reversed. Fixing that shows colors in the correct order:
|
||||
[](images/SIM04.png)
|
||||
|
||||
### Playfield debugging
|
||||
The playfield shows pink stripes instead of the expected maze. Forcing the AL ROMs to return zero, makes the text on the right of the screen disappear. This reveals additional playfield that would normally be hidden under the text. Since AL was fixed earlier, the AL ROMs will be left disabled while troubleshooting the PF issue.
|
||||
|
||||
Adding debug code to the simulator to dump selected busses to a log file and debugging the GP bus address (ROM addresses), data out of ROMs and into SLAGS, reveals several mistakes such as unconnected signals, SLAGS selectors S0 S1 to the shifters were reversed, etc, so progressively the playfield becomes more and more visible.
|
||||
[](images/SIM10.png)
|
||||
[](images/SIM11.png)
|
||||
[](images/SIM12.png)
|
||||
|
||||
The raw data from the correctly functioning SLAGS can be seen below. This is an example of what the `SLAGS` `MO` shifter output dumped into a .ppm file looks like before it is turned into an index into the color palette.
|
||||
[](images/SLAGS_MO.png)
|
||||
|
||||
And this is the corresponding `PF` shifters output. Since these values are intercepted straight from the SLAGS outputs before they hit the color palette, each value is written into the .ppm file three times (R=G=B) so as to form a grayscale image.
|
||||
[](images/SLAGS_PF.png)
|
||||
|
||||
### CRAM Debugging
|
||||
PF is now looking much better but the colors are wrong. Suspecting CRAM, palette indexing.
|
||||
[](images/SIM13.png)
|
||||
|
||||
CRAM is addressed by the 10 bit bus CRA from GPC. The top two bits of address selects CPAL as follows:
|
||||
|
||||
- 0 = AL
|
||||
- 1 = MO
|
||||
- 2 = PF
|
||||
- 3 = Extra
|
||||
|
||||
Top two bits have value of 2 so they correctly access PF CPAL, lower byte is an index into the PF CPAL.
|
||||
|
||||
From MAME it is apparent that for the initial screen, the game only uses CPAL indexes 280-29F for PF as below. This CPAL section shows what each index value is used for, X is don't care/unused, F is floor tile, the rest are different types of wall pieces.
|
||||
<pre>
|
||||
280: 0000 6631 9631 C631 F631 F643 F654 F876 -- X X X X X X F X
|
||||
288: 8333 7223 A324 F334 C334 C445 E445 F445 -- wallshade F F F F F F F
|
||||
290: F410 F010 F110 F322 B520 4531 F531 F731 -- X X X wallright X X walldown wallleft
|
||||
298: FC63 F840 FD84 F335 F246 F158 F26A F37B -- walltop X X X X X X X
|
||||
</pre>
|
||||
|
||||
Examination in the simulator shows the following discrepancies:
|
||||
|
||||
- wallshade color index expected 288 observed 257
|
||||
- wallright color index expected 293 observed 24C
|
||||
- walldown color index expected 296 observed 249
|
||||
- wallleft color index expected 297 observed 248
|
||||
- walltop color index expected 298 observed 247
|
||||
|
||||
It appears that the pattern is the original value lower byte + x20 xor 0xff. This incorrect data comes from the GPC (Graphic Priority Control) chip `12M` which in turn receives it from PFHS (Play Field Horizontal Scroll) chip `12K`. Since many of the custom chips in this schematic are based on earlier Atari arcade versions implemented with discrete components, checking schematic `SP-277` for the Atari System 1 where this `PFHS` implementation is based on, shows there is a small 64 bit `74F189` RAM chip inside the `PFHS`. A mistake made was in assuming that the data that goes into the RAM chip comes out exactly the same, but upon reading the RAM datasheet it turns out the data coming out of RAM is the **complement** of the data going in! After inverting the outputs from the `PFHS` RAM chip the PF now shows correct colors:
|
||||
[](images/SIM14.png)
|
||||
|
||||
### Debugging Motion Objects
|
||||
Sprites do not show on screen at all. When there are sprites on the screen, it seems `/VMATCH` asserts during sprite presence but, horizontal match doesn't so the `MATCH` signal is never asserted. It seems the VHDL implementation of `6S` F/F with both set and preset was incorrect, output `6S9` is never preset by `/VERTDL`, also `6S6` output is **inverted**, not just straight through. After inverting output `6S6` and fixing the async preset of F/F `6S` sprites now show (corrupted) on the top part of screen and they seem to repeat instead of just showing once. Further research shows that `MOHLB` (Motion Object Horizontal Line Buffer) had miscellaneous logic issues that needed correcting.
|
||||
|
||||
### More CRAM debugging
|
||||
Just when the colors appeared to be OK, it became apparent that sprites like 0863 (ghost) show up with wrong colors. Investigating why an incorrect color palette is selected leads to discovering that CRA5, CRA7 outputs from 8U page 15 are stuck low because they were left unconnected and were not being driven. After connecting them to the appropriate drivers the colors now look correct. Below left is what it looked like before, right is what it looks like after the fix.
|
||||
[](images/SIM16.png)
|
||||
|
||||
### Debugging Motion Objects Overlap
|
||||
Problem with sprite overlap, when sprites (like the ghosts) are overlapping, some minor corruption is visible, for example the shadow of the top ghost's arm is not obscuring the ghost underneath. Suspecting GPC (Graphic Priority Control) problem.
|
||||
|
||||
Left: how it looks, Right: how it should look.
|
||||
[](images/SIM17.png)
|
||||
|
||||
In other places there is visible corruption where extra pixels appear.
|
||||
[](images/SIM20.png)
|
||||
|
||||
As opposed to how it looks in MAME
|
||||
[](images/MAME01.png)
|
||||
|
||||
Sprite tuples for two ghosts to replicate issue
|
||||
GH1 GH2
|
||||
0890 0890
|
||||
0202 0002
|
||||
F392 F392
|
||||
0001 0000
|
||||
|
||||
CRAM address comes from 12M GPC Graphic Priority Control output. This is not a `GPC` problem, need to check `MOHLB`
|
||||
Exclude PF without recompiling simulation with following command:
|
||||
isim force add {/tb\_fpga\_gauntlet/uut/gauntlet\_inst/video\_inst/p\_12M/i\_p} 80 -radix hex
|
||||
|
||||
<pre>
|
||||
MPX to IRGB Sprite value mapping
|
||||
D7 -> 8FFF Ghost arm light gray
|
||||
D8 -> 6FFF Ghost arm medium gray
|
||||
D9 -> 6FFF Ghost arm medium gray
|
||||
DA -> 5EEF Ghost arm darker gray
|
||||
DE -> 8C63 Ghost shadow brown
|
||||
FF -> Seethrough
|
||||
</pre>
|
||||
|
||||
`MOSR` bus input to `MOHLB` for ghost sprite, FF means transparent otherwise top 4 bits are D (1101) and select the palette, bottom 4 bits select the sprite color within the selected palette. Squinting, you can almost see the ghost pattern in the data below
|
||||
<pre>
|
||||
FF FF FF FF DE FF FF FF FF FF FF FF FF FF FF FF FF FF FF DE FF FF FF FF
|
||||
FF FF FF DE DE FF FF FF FF FF FF FF FF FF FF FF FF FF FF DE DE FF FF FF
|
||||
FF FF FF DE DE FF FF FF FF FF FF FF FF FF FF FF FF FF FF DE DE FF FF FF
|
||||
FF D9 FF DE DE FF FF FF FF FF FF FF FF FF FF FF D9 FF FF DE DE FF FF FF
|
||||
D8 D9 FF DE DE FF FF FF FF FF FF DE DE DE FF FF D8 D9 FF DE DE FF FF FF
|
||||
D7 D9 D9 DE DE DE FF FF FF FF DE DE DE DE DE D8 D7 D9 FF DE DE FF FF FF
|
||||
D7 D9 FF DE DE DE DE FF FF FF DE DE DE DE DE FF D7 DA DE DE DE FF FF FF
|
||||
D7 D8 FF FF DE DE DE DE D8 D7 DA DE DE DE DE FF D8 DA DE DE FF FF FF FF
|
||||
D7 D8 DA FF FF DE DE D8 D7 D7 D9 DA DE DE DE DE D8 DA DE FF FF FF FF FF
|
||||
D8 D7 D9 DA FF FF DE D7 D7 D7 D8 DA DE DE DE D8 D9 DA FF FF FF FF FF FF
|
||||
FF D8 D7 D8 D9 DA FF D7 D7 D7 D8 DA DE DE D9 D9 DA FF FF FF FF FF FF FF
|
||||
FF FF D8 D7 D8 D9 D9 D7 D7 D7 D9 DA DA D9 DA DA FF FF FF FF FF FF FF FF
|
||||
FF FF FF D8 D7 D7 D8 D7 D7 D7 DA DA DA DA DA DE FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF D8 D7 D7 D7 D7 D9 DA DA DA DA DE DE FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF D9 D7 D7 D7 D7 D9 D9 DA DE DE DE FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF D8 D7 D7 D7 D8 D9 DA DE DE DE FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF D8 D7 D7 D7 D8 D9 DA DE DE DE FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF D7 D7 D7 D7 D8 D9 DA DE DE FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF D7 D7 D7 D7 D8 D9 DA DE DE FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF D8 D7 D7 D7 D8 D9 DA FF FF FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF FF D8 D7 D8 D9 DA DE FF FF FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF FF D8 D7 D9 D9 DA FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF FF FF D7 D9 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
FF FF FF FF FF FF FF FF D8 D9 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
</pre>
|
||||
|
||||
Since `MPX` output of MO Horizontal Line Buffer is not as expected, problem may be with `MOHLB`.
|
||||
|
||||
Simplistic way of how `MOHLB` works:
|
||||
There are two 512B RAMs that alternately buffer a **single video line** of sprites. Focusing on just one of those buffers, if two sprites overlap, the first sprite in the linked list is written to the buffer, then the next sprite in the linked list is written to the buffer, etc. If the sprites overlap and the current value of the sprite is visible (not FF) then it overwrites the memory location (covers the pixel of the sprite below) but if the current value of the sprite is transparent (FF), then it is not written to RAM so the pixel of the sprite below remains unchanged and shows through.
|
||||
|
||||
<pre>
|
||||
Higher Sprite Data (new data to RAM) : D7 D9 FF DE DE DE DE FF FF FF DE DE DE DE DE FF D7 DA DE DE DE FF FF FF FF
|
||||
Lower Sprite Data (existing data in RAM): FF FF FF FF D7 D9 FF DE DE DE DE FF FF FF DE DE DE DE DE FF D7 DA DE DE DE
|
||||
Expected RAM Data : D7 D9 FF DE DE DE DE DE DE DE DE DE DE DE DE DE D7 DA DE DE DE DA DE DE DE
|
||||
Observed RAM Data : D7 D9 FF DE D7 D9 DE DE DE DE DE DE DE DE DE DE D7 DA DE DE DE DA DE DE DE
|
||||
</pre>
|
||||
|
||||
It seems the `MOHLB` works as designed, but the data presented to it is causing it to incorrectly overwrite earlier buffered data when it shouldn't. This feels like it's a side effect of forcing sprites to appear on screen by loading sprite offset 0 with sprite data. Possibly a side effect of the issue below so putting this on ice for now until problem below is resolved.
|
||||
|
||||
### Debugging Motion Objects LINK register
|
||||
Sprites only show when sprite LINK value at offset 0 (memory 903800) points to a valid sprite, otherwise no sprites show at all.
|
||||
|
||||
Visible sprites at game start:
|
||||
<pre>
|
||||
Ypos 15..7
|
||||
HFlip 6
|
||||
Xpos 15..7 XTiles 5..3
|
||||
Sprite bits 14..0 Palette 3..0 YTiles 2..0 Link 9..0 (offset x2 + 902000)
|
||||
90208C=097E Food1 90288C=2E01 90308C=E812 90388C=004E
|
||||
90209C=0999 Chest 90289C=6E01 90309C=E812 903978=00BE
|
||||
90218C=1648 Hero 90298C=2E0F 90318C=C812 90397C=00C6
|
||||
90221C=096C Food2 902A1C=6E01 90321C=B812
|
||||
Must latch in Must latch in Must latch in Must latch in
|
||||
3C3K on rising 4N 3N on rising 5C 5K on rising 8F 8J on rising
|
||||
PICTDL HORZDL VERTDL /LINK
|
||||
|
||||
The latch signals come from MC1, MC0 decoded by 1:4 active low selector 8T. MC1, MC0 are generated by 1H, 2H, 4H, MATCH
|
||||
3 /LINK
|
||||
2 VERTDL
|
||||
1 HORZDL
|
||||
0 PICTDL
|
||||
</pre>
|
||||
|
||||
The problem as observed from simulation is this:
|
||||
If the word at 903800 contains 0400 (as per MAME simulation of game), the LINK register is loaded with the bottom 10 bits (all zero) from that memory location and therefore when it is used as a pointer into the MO VRAM, it points to offset 0 (memory 903800) so it is loaded again with zero and so on, so the LINK register is always zeroed and never finds any sprites to display.
|
||||
|
||||
If however as a test, the word at memory location 903800 is initialized with a value that points to an actual sprite's offset, then that value is loaded into the LINK register and the LINK register is used as an index into the MO VRAM LINK area to retrieve the next word which is used as an index to the next sprite and so on. ISE simulator confirms this, by loading the VRAM with an exact dump of the memory from MAME, then changing location 903800 from 0400 to 0046 (so it points to the first sprite offset) then the simulation indeed proceeds to display all sprites on the screen as expected. Note that this is a hack to force the display of sprites and not normal game behaviour.
|
||||
|
||||
To further examine the VRAM addressing, a dump of the VRD bus is sent to a log file together with the address accessed. Analysis of the log shows that at video frame 1, line 1 time offset 574515ns the screen vertical offset appears on the bus (905F6E=0080) and in the simulator it is verified that it is indeed loaded into counters `5J`, `5F`, `4F` as expected.
|
||||
|
||||
A little later at 576755ns memory location 905F80 is accessed. From experiments with MAME it is apparent that during game play the memory region 905F80 onwards stores sprite index values for sprites that should appear on the screen and this is where the LINK register should be loaded from initially. Further in the log, address 905F80 appears on the `VRD` bus and has value 0046 which is the value of the index to the first valid sprite but instead of being loaded into the `LINK` register `8F`, `8J` on the rising edge of the master clock when `/LINK` is low, the simulator shows that the enable signal `/LINK` goes low just as the master clock rises, and therefore misses loading the value on the VRD bus into the LINK register. By the time the master clock rises again, the `VRD` bus has changed value. There are two possibilities, either the VRD bus is early and should be delayed or the `/LINK` signal is late and should arrive about a half a master clock earlier.
|
||||
|
||||
The `/LINK` signal is generated by chip `8T` when both `MC1` `MC0` are high and gate signal is low. All those signals come from register `6U` which registers them on the rising master clock. Before reaching `6U` the signals come from the outputs of GAL `7U` which is not clocked.
|
||||
|
||||
Further experiments in ISIM indicate that forcibly initializing the `LINK` register to 046 at the start of each horizontal line, makes the sprites appear as expected. The LINK register must be initialized not earlier than H counter = 004 and possibly as late as H counter = 1A0. Initializing LINK earlier than 004 does not display all sprites (skips the first sprite in linked list) and initializing `LINK` as late as 1A0 makes the leftmost sprites on screen appear but leaves no time for the rightmost sprites to be displayed. Once `LINK` is initialized with 046 it follows through the sprite link list from index to index until it reaches index 0 and remains there (since the game does not place sprites at index 0 and its link index points to back to itself = 0 ).
|
||||
|
||||
During the game's initial startup screen, sprites should be visible during lines 42-62 (3187125 ns), 103-126 (7081365 ns) and 138-157 (9315765 ns)
|
||||
|
||||
Gut feel at this stage is that everything works as designed and the fault may be due to `SYNGEN`. The Sync Generator custom chip is based on the discrete chip implementation from schematic SP-277 for Atari System I. The GAL chips `136032.102.e5` and `136032.103.f7` may contain equations that while suitable for System I, may have been changed or tweaked in the `SYNGEN` for Gauntlet.
|
||||
|
||||
Further analysing the schematic and trying to understand how sprites function, of particular note is signal `/NXL` generated by `SYNGEN`. This signal comes from GAL `136032.103.f7` which monitors the H horizontal counters and resets them when a particular count is reached, therefore when `/NXL` pulses low, it resets the H counters to zero (start of new horizontal video line). It is not totally clear how the signals `/NXL` and `/NXL*` from schematic `SP-277` correspond with Gauntlet schema `SP-284` in regards to how many master clock cycles one is delayed with respect to the other.
|
||||
|
||||
Furthermore on sheet 9 of Gauntlet schema, the address selector chip `7S` has a direct override controlled by `/NXL` which causes the `VAS1` line to go low when `/NXL` is pulsed low once at the start of each horizontal line.
|
||||
|
||||
<pre>
|
||||
VRAM addressing
|
||||
|
||||
VAS1* VAS0* VRAM_ADDR
|
||||
0 0 PF 900000-901FFF
|
||||
0 1 MO 902000-903FFF
|
||||
1 0 AL 904000-905FFF
|
||||
1 1 - No VRAM selected
|
||||
|
||||
VAS1 VAS0 VRAM_ADDR_BUS
|
||||
0 0 from PF V and H counters
|
||||
0 1 from MC1/MC0 and LINK register
|
||||
1 0 from V and H counters
|
||||
1 1 from CPU address bus
|
||||
</pre>
|
||||
|
||||
Since `VAS1` and `VAS0` directly control which one of four buses is selected to make up the video RAM address lines, this seems like a very good candidate to force a particular address on the `VRAM` bus to cause `LINK` register initialization. Of note is that a delayed and inverted version of `/NXL` disables the address selector that controls the top 6 bits of of the `VRAM` address allowing the pullups to pull high forcing a particular range of addresses for one master clock cycle.
|
||||
|
||||
So when `/NXL` is low it forces `VAS1` to be low, limiting the `VRAM` address selection to only two out of the four available busses. `VAS0` is then used to select one of those two buses. `VAS0` comes directly from `VAS0*` delayed one master clock and `VAS0*` is created from `1H`, `2H`, `4H` and `/NXL` by GAL `7U`, but we see from the equations of `7U` GAL that one of the terms is "`/NXL` AND `1H`", but because `/NXL` is always low when `1H` is low (they are in sync) then `/NXL` has no chance of affecting the result of that logical AND. This doesn't seem correct and in fact points to the root cause of this entire sprite problem which has taken many hours of simulation and head scratching. The `/NXL` signal is delayed one master clock cycle inside `SYNGEN` before it comes out, then delayed again by the `5T` register. This turns out to be one delay too many and by eliminating the delay inside `SYNGEN` the portion of the `/NXL` low signal lines up with the part where `1H` is high, so essentially `/NXL` can now mask `1H` and influence the output `VAS0*` which directly affects the VRAM address selection.
|
||||
|
||||
ISIM testing now shows that removing the `/NXL` delay inside `SYNGEN` makes the sprites appear without having to force `LINK` register loading!!! So as suspected timing of the `/NXL` signal was at the root of the problem.
|
||||
|
||||
Below is the initial screen at game startup from simulation. The reason the playfield on the left hand side looks a little different from MAME is because I forgot to initialize the playfield horizontal scroll register to 005 as MAME does, so the playfield is scrolled right 5 pixels compared to the MAME reference picture.
|
||||
[](images/SIM21.png)
|
||||
Same screen from MAME for reference.
|
||||
[](images/MAME02.png)
|
||||
|
||||
Another simulation of a later game screen with lots of sprites visible. Again the playfield horizontal scroll register in the simulation has a slightly different value from MAME so the screen is shifted right by some number of pixels.
|
||||
[](images/SIM22.png)
|
||||
|
||||
Compared to the same MAME screen for reference.
|
||||
[](images/MAME01.png)
|
||||
|
||||
## Debugging Commands
|
||||
|
||||
In MAME debug mode use ***w@930000=0005*** to write new horizontal scroll offsets, or ***w@905F6E=00CB*** for vertical scroll offsets
|
||||
|
||||
In ISIM to write to 930000 without recompiling simulation we can place a value on `VBD` then pulse `/HSCRLD` with the following commands. .
|
||||
|
||||
**restart;
|
||||
isim force add {/tb\_fpga\_gauntlet/uut/gauntlet\_inst/video\_inst/bus\_VBD} CB -radix hex -time 3 us -cancel 5 us;
|
||||
isim force add {/tb\_fpga\_gauntlet/uut/gauntlet\_inst/video\_inst/s\_HSCRLDn} 0 -radix bin -time 3 us -cancel 4 us;
|
||||
run 18ms;**
|
||||
|
||||
MAME debug commands to follow the sprite link list from an initial index and dump the values. Set temp0 to initial index of interest then repeat the next two command as many times as necessary
|
||||
|
||||
**temp0=0046**
|
||||
|
||||
**temp1=w@(902000+temp0\*2); temp2=w@(902800+temp0\*2); temp3=w@(903000+temp0\*2); temp4=w@(903800+temp0\*2); temp0=w@(903800+temp0\*2)&3ff**
|
||||
|
||||
**printf "\n%04X TILE=%04X\n%04X XPOS=%d, PSEL=%d\n%04X YPOS=%d, HSIZ=%d, VSIZ=%d\n%04X LINK=%04X (%04X)",temp1,temp1&7fff,temp2,temp2>>7,temp2&15,temp3,temp3>>7,(temp3>>3)&7,temp3&7,temp4,temp4&3ff,903800+(temp4&3ff)\*2**
|
||||
|
||||
### Misc
|
||||
|
||||
Flow of data with no CPU active should be
|
||||
<pre>
|
||||
+-->[VRAMS]--vrd bus-->[VROM]--ab bus-->[SLAGS]--MOSR/PFSR bus-->[PFHS]--pfx bus-->[GPC]--cra bus-->[CRAMS]--RGBI out bus-->[Video Out]
|
||||
|
|
||||
|
|
||||
+--vra--+-(3 --) [ma12..1 CPU address]
|
||||
|-(2 AL) [HV counters]<------------------------------- [SYNGEN]<--------------[CLOCK]
|
||||
|-(1 MO) [mc1,mc0,lnk9..0 from vrd on /link signal]
|
||||
+-(0 PF) [pfv from counters, pfh from PFHS]
|
||||
^
|
||||
|
|
||||
+---[VS1* VS0* selectors from 7U PROM]
|
||||
</pre>
|
||||
|
||||
When no RAMs are selected the bus `VRD` floats
|
||||
|
||||
## Sound Section
|
||||
<pre>
|
||||
========================================================================
|
||||
SOUND CPU
|
||||
========================================================================
|
||||
0000-0FFF R/W xxxxxxxx Program RAM
|
||||
4000-FFFF R xxxxxxxx Program ROM
|
||||
|
||||
1000 W xxxxxxxx Sound response write
|
||||
1010 R xxxxxxxx Sound command read
|
||||
1020 R ----xxxx Coin inputs
|
||||
R ----x--- (Coin 1)
|
||||
R -----x-- (Coin 2)
|
||||
R ------x- (Coin 3)
|
||||
R -------x (Coin 4)
|
||||
1020 W xxxxxxxx Mixer control
|
||||
W xxx----- (TMS5220 volume)
|
||||
W ---xx--- (POKEY volume)
|
||||
W -----xxx (YM2151 volume)
|
||||
1030 R xxxx---- Sound status read
|
||||
R x------- (Sound command buffer full)
|
||||
R -x------ (Sound response buffer full)
|
||||
R --x----- (TMS5220 ready)
|
||||
R ---x---- (Self test)
|
||||
|
||||
1030 W x------- YM2151 reset
|
||||
1031 W x------- TMS5220 data strobe
|
||||
1032 W x------- TMS5220 reset
|
||||
1033 W x------- TMS5220 frequency
|
||||
1800-180F R/W xxxxxxxx POKEY communications
|
||||
1810-1811 R/W xxxxxxxx YM2151 communications
|
||||
1820 W xxxxxxxx TMS5220 data latch
|
||||
1830 R/W -------- IRQ acknowledge
|
||||
========================================================================
|
||||
Interrupts:
|
||||
IRQ = timed interrupt
|
||||
NMI = latch on sound command
|
||||
========================================================================
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
List of sounds:
|
||||
0 Reset all sounds
|
||||
1 Silent (Volume off)
|
||||
2 Noisy (Volume on)
|
||||
3 Silences sounds
|
||||
4 Music Chip Test (YM)
|
||||
5 Effects Chip Test (Pokey)
|
||||
6 Silences sounds
|
||||
7 Silences sounds
|
||||
8 Speech Chip Test (TMS)
|
||||
|
||||
YM sounds
|
||||
09-65 Misc Effects
|
||||
47/48 start/stop alarm sound
|
||||
49/50 start/stop alarm sound
|
||||
51/52 start/stop alarm sound
|
||||
53/54 start/stop alarm sound
|
||||
66/67 start/stop long music
|
||||
68-71 long music different tempos
|
||||
72 fade out music 68-71
|
||||
73 melody
|
||||
Pokey sounds
|
||||
74-80 effects
|
||||
TMS sounds
|
||||
81-220 Speech Sounds
|
||||
|
||||
221 pokey vol off
|
||||
222 pokey vol low
|
||||
223 pokey vol med
|
||||
224 pokey vol high
|
||||
225
|
||||
</pre>
|
||||
|
||||
Set DIP switch to service mode and advance to sound test, then from MAINCPU, write sound command as
|
||||
w@803170=51
|
||||
|
||||
From MAINCPU, sound CPU reset should be
|
||||
w@80312E=1
|
||||
w@80312E=0
|
||||
|
||||
breakpoint 5787 reads 1010, x contains the sound to play
|
||||
|
||||
When AUDIOCPU is unused and it is reset then 1030=00 so from reset address 599e the condition doesn't match and CPU is stuck in infinite loop at 59A5
|
||||
When AUDIOCPU is used it is reset then 1030=80 so from reset address 599e the condition matches and it jumps to 4002, where it initializes stack and continues running
|
||||
|
||||
IRQ FFFE 4187
|
||||
RST FFFC 599E
|
||||
NMI FFFA 5729
|
||||
|
||||
bp 4187,1,{printf "IRQ"; g}
|
||||
bp 599E,1,{printf "RST"; g}
|
||||
bp 5729,1,{printf "NMI"; g}
|
||||
bp 578a,1,{printf "X=%x",X; g}
|
||||
|
||||
Skip RAM and ROM checks, jmp 40a3
|
||||
audiocpu.md@402c=ea40a34c
|
||||
|
||||
breakpoint after NMI on read of snd command
|
||||
bp 578a
|
||||
watchpoint on YM access
|
||||
wps 1810,2,rw,1,{printf "%X %X",wpaddr,wpdata; g}
|
||||
|
||||
NMI disable
|
||||
audiocpu.mb@fffa=9c
|
||||
|
||||
SYNGEN 7M16 in , H1 = 3M58 H2=1M78
|
||||
IRQ 17.15ms
|
||||
|
||||
## Main CPU Section
|
||||
After an 8 month break from this project, spring, summer and autumn has come and gone, it is now cold and dark, time to get some work done :) Used the TG68K softcore from MiSTer as the base for the main CPU core. Initial problem was that the softcore doesn't match the pins of the real 68K CPU, for example `/AS` is completely missing and also the timing of the `R/W` and `/UDS`, `/LDS` signals coming out of the softcore is very wide so the whole timing doesn't match a real 68K bus access. After some research, the way others deal with that is to implement a wrapper around the softcore with a state machine to create or activate the signals in such a way that it more closely resembles a 68K in timing.
|
||||
|
||||
With a first draft wrapper, initial success was observed in simulation as the CPU comes out of reset, fetches `SP` from address 000000 and `PC` from address 000004 then continues execution. Additinally success is observed jumping into and returning from subroutines, meaning the correct data is pushed into and popped off the stack (RAM). Also interrupts work as expected which should not be surprising since the stack is functional.
|
||||
|
||||
### Memory.. unused
|
||||
An interesting observation, even though the schematic sheet 3 shows RAMs attached to the CPU at address 800000, they do not appear to be used. Instead the stack is initialized with 904F00 which falls in the `SPARE` video memory area which seems to be used as the CPU RAM. Tracking down a picture of a Gauntlet board, it shows places 11A, 11B, 12A, 12B fitted with empty sockets.
|
||||
|
||||
### CPU simulation
|
||||
Observations from MAME indicate that on game powerup it is not until frame 77 that a picture starts to appear. This is far too long to simulate as it takes about 90 seconds per frame to simulate. Poking around MAME debugger it seems a good starting point is address 040000, which produces a stable game with first video picture appearing at frame 35, a saving of 42 frames (1 hour of simulation).
|
||||
|
||||
This is an animation of the first 2 seconds (120 frames) produced by running the simulation in ISIM for about 3 hours.
|
||||
[](images/gauntlet_anim1.gif)
|
||||
|
||||
### What memory test?
|
||||
Poking around in the debugger I discovered a bug in the original game ROMs. At game power on, as well as performing ROM checksums to ensure that the ROMs are valid, the game also performs a RAM "test", or at least it tries to.
|
||||
|
||||
At address 0636 is the start of a number of calls to subroutine 0A2C which is called with registers A1 and A2 initialized to the following memory ranges:
|
||||
<pre>
|
||||
904000-904FFE Spare video RAM
|
||||
910000-9107FE Palette RAM
|
||||
900000-901FFE Playfield RAM
|
||||
905000-905FFE Alphanumerics RAM
|
||||
902000-903FFE Motion object RAM
|
||||
</pre>
|
||||
|
||||
The idea is that the subroutine at 0A2C will go through every memory word in the range and fill the word first with 1's (8000, C000, E000, ..., FFFC, FFFE, FFFF) then with 0's (FFFF, 7FFF, 3FFF, ..., 0003, 0001, 0000) comparing that the data read from RAM is as expected.
|
||||
|
||||
The problem is that in the loop that compares the current address in A0 with the end address in A2, someone inserted a write to address 803100 (watchdog reset), so this messes up the carry flag and the branch back to 0B04 is never taken.
|
||||
|
||||
<pre>
|
||||
000B1C: B1CA cmpa.l A2, A0
|
||||
000B1E: 33C0 0080 3100 move.w D0, $803100.l
|
||||
000B24: 65DE bcs $b04
|
||||
</pre>
|
||||
|
||||
This means that only the first word in each memory region is tested before the loop falls through. If you were to swap around the instructions at 0B1C and 0B1E the bug would be fixed and the entire RAM range would be tested.
|
||||
|
||||
### Oh MAME, how could you...
|
||||
|
||||
I don't have access to a real Gauntlet arcade board, so I used MAME as my reference. Imagine my surprise after I got the game going and it appeared to function fine, when I went into the game "service mode" and I see this. Some of the sprite squares on the right hand side are cut off, while in MAME they appear whole.
|
||||
|
||||
[](images/sprites1.png)
|
||||
|
||||
Immediate assumption was "MAME is correct" so there's a bug in my implementation whereupon I proceed to embarc on a very lengthy debug session in ISIM. The problem with simulations is that they're very very slow, so anything one can do to skip unnecessary game run time in simulation can shave literally hours of simulation time. Normally the game takes 12 seconds from bootup to come up and advance 9 test screens to get to the relevant sprite test screen. It takes 2-3 hours to simulate 2 seconds of game run time. Slight problem...
|
||||
|
||||
The most efficient way to deal with this is spend 10-20 minutes in MAME debug mode and find a suitable patch to the ROMs that causes the game to boot up and just jump to the relevant code that displays the sprites. Then the simulation time is cut to 5 minutes as it only needs to render the first 2 or 3 frames of video. This is exactly the process here, the game ROM was patched with the following code that executes straight from reset.
|
||||
|
||||
<pre>
|
||||
0005E2: move #$2700, SR ; disable interrupts
|
||||
0005E6: movea.w #$5A36, a3 ; set parameter
|
||||
0005EA: movea.w #$5A32, a4 ; set parameter
|
||||
0005EE: jmp $1BD6.w ; jump to relevant sprite code
|
||||
</pre>
|
||||
|
||||
The real game ROMs are not in fact touched, instead a small script is run every time MAME debug mode is entered that apply this patch over the ROM memory.
|
||||
|
||||
<pre>
|
||||
maincpu.md@5E6=367C5A36
|
||||
maincpu.md@5EA=387C5A32
|
||||
maincpu.md@5EE=4EF81BD6
|
||||
</pre>
|
||||
|
||||
Armed with this ROM patch the investigation began and sure enough the simulator produced the relevant video frame in only a few minutes.
|
||||
|
||||
[](images/sprites2.png)
|
||||
|
||||
Then it was a matter of following the signals backwards starting from the video output. After identifying the video line signal where the part of the sprites was missing, that data comes out of the color palette RAMs, which are driven by the Graphics Priority Chip `GPC` which apparently also outputs incomplete data. So the `GPC` is not at fault, tracing backwards, the `GPC` is driven by the two line buffers inside the Motion Object Horizonal Line Buffer chip `MOHLB`. Because the line buffers, buffer the video signal and output it one video line later, this introduces a delay, so in the simulation traces one must look to the time period of the previous video line to find the relevant data stored in the line buffers. Turns out this data is also incomplete, so the "fault" lies before the `MOHLB` which is driven by the outputs of the video ROMs.
|
||||
|
||||
So the next step is to check what is driving the address bus of the video ROMs. This is where things become complicated, see sheet 10 of the schematic. There is a fairly complex piece of circuitry that involves horizontal and vertical sprite address coordinate latches that also add offsets to those coordinates via adders and generate "match" signals when a sprite position matches the current H and V position of the video counters rendering the picture. Additionally there is also circuitry on page 14 which is also related in terms of timing and control signals. Long story short, after many hours in the simulator trying to understand how sprites are rendered to the video screen, it became apparent that the "problem" was in fact on page 14.
|
||||
|
||||
There is a PROM chip 4R and a countdown counter 5R. The PROM chip address is driven with bits 8 though 4 of the sprite horizontal position, as well as three bits representing one of the 8 possible sprite sizes. Based on the sprite horizontal position and size, the output of the PROM loads countdown counter 5R with a certain value when signal `/NEWMO` is aserted (New Motion Object aka sprite). The counter then counts down and generates signal `/END` which terminates the display of the sprite on screen.
|
||||
|
||||
It was now clear in the simulation that while the first few sprites on the screen were being drawn correctly, the last two sprites (large squares) were being terminated prematurely by the `/END` signal. Inspecting the contents of the 4R PROM, it has a repeating pattern of 1,3,5,7,9,B,D,F for most of its first half and zeroes for most of the last half. Each of those values represent one of the eight possible sprite sizes, except for the least significant bit, which when set indicates that a sprite is present and must be displayed. The other top three bits are loaded into the 5R countdown counter. Each set of 8 bytes in the PROM represent a 16 pixel horizontal line offset (because only bits 8 though 4 of sprites H position drive the PROM address, so bits 3 to 0 = 16 values are not evaluated). This means that as we move from address 0 in the PROM towards higher values, this represents lower H sprite coordinates (left of the screen) moving towards higher H coordinates (right of screen).
|
||||
|
||||
As we arrive to the middle of the PROM (almost all the way right of the screen), the repeating pattern of of 1,3,5,7,9,B,D,F, changes to to 1,3,5,7,7,7,7,7 and then 1,3,3,3,3,3,3,3 meaning that the counter value for larger sprites is artificially reduced causing them to be cut off before being fully displayed because the 5R countdown counter is loaded with a smaller value and asserts /END earlier. Then most of the last half of the PROM has zeroes meaning that no sprites will ever be displayed after a certain H coordinate (too far right / off screen).
|
||||
|
||||
So after wasting many hours analyzing this, it turns out there is nothing wrong, the FPGA implementation functions correctly and it is in fact MAME that is wrong, even though it seems to display "more correct" video output. As a test I filled the PROM entirely with the 1,3,5,7,9,B,D,F pattern and run a simulation since I knew now that would cause all sprites to be fully displayed regardless of H screen coordinate value. The simulation proved it:
|
||||
|
||||
[](images/sprites3.png)
|
||||
|
||||
Finally thanks to Colin Davies, who was kind enough to hook up his real Gauntlet arcade PCB and run a test for me, the following picture shows that the real arcade game also displays cut off sprites on the right hand side, so yeah... MAME is wrong.
|
||||
|
||||
[](images/sprites4.png)
|
||||
|
||||
Just for completeness though, it's worth pointing out that during gameplay, the rightmost 1/4 of the screen is always taken up by text display with player stats, so no sprites will even be visible in that region of the screen, therefore this will never be a problem.
|
||||
18
Arcade_MiST/Atari Gauntlet Hardware/readme.md
Normal file
18
Arcade_MiST/Atari Gauntlet Hardware/readme.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Atari Gauntlet FPGA Arcade
|
||||
|
||||
## About
|
||||
This is an FPGA implementation of Atari's arcade game "Gauntlet" from 1985, based on the SP-284 schematic circuit diagram.
|
||||
|
||||
[](doc/images/MAME00.png)
|
||||
[](doc/images/MAME01.png)
|
||||
|
||||
Here is a youtube video of the current status, click on picture below:
|
||||
[](https://www.youtube.com/watch?v=7A2k7wLUSUU)
|
||||
|
||||
The game is mostly functional right now, can coin up and start game, known problems are as follows:
|
||||
|
||||
* The TMS5220 speech synth is not implemented
|
||||
* Audio mixing is not ideal, sound quality needs improvement.
|
||||
* Game EPROM is implemented as RAM so game settings are lost on power off.
|
||||
* Some game ROMs are stored external to FPGA, multiplexing may need improvement.
|
||||
* Only player 1 controls are connected (minor).
|
||||
510
Arcade_MiST/Atari Gauntlet Hardware/rtl/AUDIO.vhd
Normal file
510
Arcade_MiST/Atari Gauntlet Hardware/rtl/AUDIO.vhd
Normal file
@@ -0,0 +1,510 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity AUDIO is
|
||||
port(
|
||||
I_MCKR : in std_logic; -- 7.14MHz
|
||||
|
||||
I_1H : in std_logic; -- 3.58MHz
|
||||
I_2H : in std_logic; -- 1.79MHz
|
||||
I_32V : in std_logic;
|
||||
I_VBLANKn : in std_logic;
|
||||
|
||||
I_SNDNMIn : in std_logic;
|
||||
I_SNDINTn : in std_logic;
|
||||
I_SNDRESn : in std_logic;
|
||||
|
||||
I_SELFTESTn : in std_logic;
|
||||
I_COIN : in std_logic_vector( 3 downto 0); -- 1L, 2, 3, 4R
|
||||
|
||||
I_SBD : in std_logic_vector( 7 downto 0);
|
||||
O_SBD : out std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
O_WR68K : out std_logic;
|
||||
O_RD68K : out std_logic;
|
||||
|
||||
O_CCTR1n : out std_logic;
|
||||
O_CCTR2n : out std_logic;
|
||||
O_AUDIO_L : out std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
O_AUDIO_R : out std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
|
||||
-- ROMs are external
|
||||
O_AP_EN : out std_logic;
|
||||
O_AP_AD : out std_logic_vector(15 downto 0) := (others=>'1');
|
||||
I_AP_DI : in std_logic_vector( 7 downto 0)
|
||||
);
|
||||
end AUDIO;
|
||||
|
||||
architecture RTL of AUDIO is
|
||||
signal
|
||||
sl_COINn,
|
||||
sl_MIXn,
|
||||
sl_MIXn_last,
|
||||
sl_MUSICn,
|
||||
sl_POKEYn,
|
||||
sl_RD68kn,
|
||||
sl_SBR_Wn,
|
||||
sl_SBW_Rn,
|
||||
sl_SIORDn,
|
||||
sl_SIOWRn,
|
||||
sl_SIRQACKn,
|
||||
sl_SNDIRQn,
|
||||
sl_SPHRDYn,
|
||||
sl_SPHRESn,
|
||||
sl_SPHWRRn,
|
||||
sl_SPHWRn,
|
||||
sl_SQUEAKn,
|
||||
sl_SRDn,
|
||||
sl_SWRn,
|
||||
sl_VOICEn,
|
||||
sl_VOICEn_last,
|
||||
sl_WR68kn,
|
||||
sl_YAMRESn,
|
||||
sl_POKEY_cs
|
||||
: std_logic := '0';
|
||||
signal
|
||||
sl_SYNC,
|
||||
sl_MCKF,
|
||||
sl_PHI2,
|
||||
sl_CPU_ena,
|
||||
sl_13L4,
|
||||
sl_13L5,
|
||||
sl_14L4,
|
||||
sl_14P4,
|
||||
sl_14P5,
|
||||
sl_14P6,
|
||||
sl_14P7,
|
||||
sl_1H_last,
|
||||
sl_32V_last,
|
||||
sl_B02,
|
||||
sl_YAMRES,
|
||||
sl_ROM_CS,
|
||||
sl_RAM_16M_cs,
|
||||
sl_RAM_16N_cs,
|
||||
sl_ROM_16R_cs,
|
||||
sl_ROM_16S_cs
|
||||
: std_logic := '1';
|
||||
signal
|
||||
sl_SWR
|
||||
: std_logic_vector( 0 downto 0) := (others => '0');
|
||||
signal
|
||||
slv_YM_vol,
|
||||
slv_PM_vol,
|
||||
slv_SM_vol
|
||||
: std_logic_vector( 2 downto 0) := (others => '0');
|
||||
signal
|
||||
sph_ctr
|
||||
: std_logic_vector( 3 downto 0) := (others => '0');
|
||||
signal
|
||||
slv_12P,
|
||||
slv_IO,
|
||||
slv_16R_ROM_data,
|
||||
slv_16S_ROM_data,
|
||||
slv_16N_RAM_data,
|
||||
slv_16M_RAM_data,
|
||||
slv_SBDI,
|
||||
slv_SBDO,
|
||||
slv_TMS_data,
|
||||
slv_YM_data,
|
||||
slv_POKEY_data
|
||||
: std_logic_vector( 7 downto 0) := (others => '0');
|
||||
signal
|
||||
s_TMS_out,
|
||||
s_POK_out
|
||||
: signed( 7 downto 0) := (others => '0');
|
||||
signal
|
||||
s_audio_TMS,
|
||||
s_audio_POK,
|
||||
s_audio_YML,
|
||||
s_audio_YMR
|
||||
: signed(11 downto 0) := (others => '0');
|
||||
signal
|
||||
s_chan_l,
|
||||
s_chan_r
|
||||
: signed(13 downto 0) := (others => '0');
|
||||
signal
|
||||
s_YML_out,
|
||||
s_YMR_out
|
||||
: std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal
|
||||
slv_SBA
|
||||
: std_logic_vector(23 downto 0) := (others => '0');
|
||||
|
||||
COMPONENT jt51
|
||||
PORT
|
||||
(
|
||||
rst : IN STD_LOGIC;
|
||||
clk : IN STD_LOGIC;
|
||||
cen : IN STD_LOGIC;
|
||||
cen_p1 : IN STD_LOGIC;
|
||||
cs_n : IN STD_LOGIC;
|
||||
wr_n : IN STD_LOGIC;
|
||||
a0 : IN STD_LOGIC;
|
||||
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
ct1 : OUT STD_LOGIC;
|
||||
ct2 : OUT STD_LOGIC;
|
||||
irq_n : OUT STD_LOGIC;
|
||||
sample : OUT STD_LOGIC;
|
||||
left : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
||||
right : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
||||
xleft : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
||||
xright : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
||||
dacleft : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
||||
dacright : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
begin
|
||||
O_RD68K <= sl_RD68Kn;
|
||||
|
||||
-- Delay CPU enable to create an artificial PHI2 clock enable, PHI1 is not used
|
||||
p_cpuena : process
|
||||
begin
|
||||
wait until falling_edge(I_MCKR);
|
||||
-- use 1H and 2H to create a short clock enable for the 7MHz master clock
|
||||
sl_CPU_ena <= I_1H and (not I_2H);
|
||||
sl_PHI2 <= sl_CPU_ena;
|
||||
end process;
|
||||
|
||||
sl_MCKF <= not I_MCKR;
|
||||
|
||||
O_WR68K <= sl_WR68kn;
|
||||
-------------
|
||||
-- sheet 5 --
|
||||
-------------
|
||||
u_15_16L : entity work.T65
|
||||
port map (
|
||||
MODE => "00", -- "00" => 6502, "01" => 65C02, "10" => 65C816
|
||||
Enable => sl_CPU_ena, -- clock enable to run at 1.7MHz
|
||||
Abort_n => '1',
|
||||
CLK => I_MCKR, -- in, system clock 7MHz
|
||||
IRQ_n => sl_SNDIRQn, -- in, active low irq
|
||||
NMI_n => I_SNDNMIn, -- in, active low nmi
|
||||
RES_n => I_SNDRESn, -- in, active low reset
|
||||
RDY => '1', -- in, ready
|
||||
SO_n => '1', -- in, set overflow
|
||||
DI => slv_SBDI, -- in, data
|
||||
|
||||
A => slv_SBA, -- out, address
|
||||
DO => slv_SBDO, -- out, data
|
||||
R_W_n => sl_SBR_Wn, -- out, read /write
|
||||
SYNC => sl_SYNC -- out, sync
|
||||
);
|
||||
|
||||
O_SBD <= slv_SBDO;
|
||||
O_AP_EN <= (sl_CPU_ena or sl_PHI2) and sl_ROM_CS and sl_SBR_Wn; -- when reading from ROM range
|
||||
O_AP_AD <= slv_SBA(15 downto 0);
|
||||
|
||||
-- 15P, 16K, 16L are just buffers
|
||||
p_cpubus : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_PHI2 = '1' then
|
||||
-- CPU input data bus mux
|
||||
if sl_SBR_Wn = '1' and sl_ROM_CS = '1' then slv_SBDI <= I_AP_DI; -- @4000-FFFF
|
||||
elsif sl_SRDn = '0' and sl_RAM_16M_CS = '1' then slv_SBDI <= slv_16M_RAM_data; -- @0000-07FF
|
||||
elsif sl_SRDn = '0' and sl_RAM_16N_CS = '1' then slv_SBDI <= slv_16N_RAM_data; -- @0800-0FFF
|
||||
elsif sl_SBR_Wn = '1' and sl_POKEYn = '0' then slv_SBDI <= slv_POKEY_data; -- @1800
|
||||
elsif sl_SBR_Wn = '1' and sl_MUSICn = '0' then slv_SBDI <= slv_YM_data; -- @1810
|
||||
elsif sl_SBR_Wn = '1' and sl_RD68Kn = '0' then slv_SBDI <= I_SBD; -- @1010
|
||||
elsif sl_SBR_Wn = '1' and (sl_COINn = '0' or sl_SIORDn = '0') then slv_SBDI <= slv_12P; -- @1020, @1030
|
||||
else slv_SBDI <= (others=>'Z'); -- FIXME
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_16N : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_SBA(10 downto 0),
|
||||
clock => sl_MCKF,-- and sl_RAM_16N_CS,
|
||||
data => slv_SBDO,
|
||||
wren => sl_SWR(0),
|
||||
q => slv_16N_RAM_data
|
||||
);
|
||||
|
||||
p_16M : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_SBA(10 downto 0),
|
||||
clock => sl_MCKF,-- and sl_RAM_16M_CS,
|
||||
data => slv_SBDO,
|
||||
wren => sl_SWR(0),
|
||||
q => slv_16M_RAM_data
|
||||
);
|
||||
|
||||
|
||||
-- Xilinx Block RAMs are active high, so inverted from schematic
|
||||
sl_ROM_16S_CS <= not sl_14L4; -- @8000-FFFF
|
||||
sl_ROM_16R_CS <= not sl_13L5; -- @4000-7FFF
|
||||
sl_RAM_16N_CS <= not sl_14P5; -- @0800-0FFF
|
||||
sl_RAM_16M_CS <= not sl_14P4; -- @0000-07FF
|
||||
sl_ROM_CS <= sl_ROM_16S_CS or sl_ROM_16R_CS;
|
||||
|
||||
-- Address Decoding
|
||||
|
||||
-- 14L
|
||||
sl_14L4 <= ( not slv_SBA(15)); -- @8000-FFFF
|
||||
|
||||
-- 13L
|
||||
sl_13L5 <= ( slv_SBA(15)) or ( not slv_SBA(14)); -- Y1 @4000-7FFF
|
||||
sl_13L4 <= ( slv_SBA(15)) or ( slv_SBA(14)); -- Y0 @0000-3FFF
|
||||
|
||||
-- 14P
|
||||
sl_14P7 <= sl_13L4 or ( not slv_SBA(12)) or ( not slv_SBA(11)); -- Y3 @1800-1FFF
|
||||
sl_14P6 <= sl_13L4 or ( not slv_SBA(12)) or ( slv_SBA(11)); -- Y2 @1000-17FF
|
||||
sl_14P5 <= sl_13L4 or ( slv_SBA(12)) or ( not slv_SBA(11)); -- Y1 @0800-0FFF
|
||||
sl_14P4 <= sl_13L4 or ( slv_SBA(12)) or ( slv_SBA(11)); -- Y0 @0000-07FF
|
||||
|
||||
sl_SIRQACKn <= sl_14P7 or ( not slv_SBA(5)) or ( not slv_SBA(4)); -- Y3 @1830
|
||||
sl_VOICEn <= sl_14P7 or ( not slv_SBA(5)) or ( slv_SBA(4)); -- Y2 @1820
|
||||
sl_MUSICn <= sl_14P7 or ( slv_SBA(5)) or ( not slv_SBA(4)); -- Y1 @1810
|
||||
sl_POKEYn <= sl_14P7 or ( slv_SBA(5)) or ( slv_SBA(4)); -- Y0 @1800
|
||||
|
||||
sl_POKEY_cs <= not sl_POKEYn;
|
||||
|
||||
-- 12R
|
||||
sl_SIORDn <= (not sl_B02) or sl_14P6 or ( not slv_SBA(5)) or ( not slv_SBA(4) or ( not sl_SBR_Wn )); -- Y7 @1030 RD
|
||||
sl_SIOWRn <= (not sl_B02) or sl_14P6 or ( not slv_SBA(5)) or ( not slv_SBA(4) or ( sl_SBR_Wn )); -- Y6 @1030 WR
|
||||
sl_COINn <= (not sl_B02) or sl_14P6 or ( not slv_SBA(5)) or ( slv_SBA(4) or ( not sl_SBR_Wn )); -- Y5 @1020 RD
|
||||
sl_MIXn <= (not sl_B02) or sl_14P6 or ( not slv_SBA(5)) or ( slv_SBA(4) or ( sl_SBR_Wn )); -- Y4 @1020 WR
|
||||
sl_RD68Kn <= (not sl_B02) or sl_14P6 or ( slv_SBA(5)) or ( not slv_SBA(4) or ( not sl_SBR_Wn )); -- Y3 @1010 RD
|
||||
-- sl_12R13 <= (not sl_B02) or sl_14P6 or ( slv_SBA(5)) or ( not slv_SBA(4) or ( sl_SBR_Wn )); -- Y2
|
||||
-- sl_12R14 <= (not sl_B02) or sl_14P6 or ( slv_SBA(5)) or ( slv_SBA(4) or ( not sl_SBR_Wn )); -- Y1
|
||||
sl_WR68Kn <= (not sl_B02) or sl_14P6 or ( slv_SBA(5)) or ( slv_SBA(4) or ( sl_SBR_Wn )); -- Y0 @1000 WR
|
||||
|
||||
-- 14M F/F
|
||||
p_14M : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
sl_32V_last <= I_32V;
|
||||
if sl_SIRQACKn = '0' then
|
||||
sl_SNDIRQn <= '1';
|
||||
elsif sl_32V_last = '0' and I_32V = '1' then
|
||||
sl_SNDIRQn <= not I_VBLANKn;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 16T/U simplified addressable latch
|
||||
p_16T_U : process
|
||||
begin
|
||||
wait until rising_edge(sl_MCKF);
|
||||
if I_SNDRESn = '0' then
|
||||
sl_YAMRESn <= '0';
|
||||
sl_SPHWRRn <= '0';
|
||||
sl_SPHRESn <= '0';
|
||||
sl_SQUEAKn <= '0';
|
||||
O_CCTR1n <= '0';
|
||||
O_CCTR2n <= '0';
|
||||
else
|
||||
if sl_SIOWRn = '0' then
|
||||
case slv_SBA(2 downto 0) is
|
||||
when "000" => sl_YAMRESn <= slv_SBDO(7); -- @1030
|
||||
when "001" => sl_SPHWRRn <= slv_SBDO(7); -- @1031
|
||||
when "010" => sl_SPHRESn <= slv_SBDO(7); -- @1032
|
||||
when "011" => sl_SQUEAKn <= slv_SBDO(7); -- @1033
|
||||
when "100" => O_CCTR1n <= not slv_SBDO(7); -- @1034 (inverted by Q17)
|
||||
when "101" => O_CCTR2n <= not slv_SBDO(7); -- @1035 (inverted by Q18)
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- gate 14N
|
||||
sl_SPHWRn <= sl_SPHWRRn and sl_SPHRESn;
|
||||
|
||||
-- gates 12S
|
||||
sl_SWRn <= not (sl_B02 and sl_SBW_Rn);
|
||||
sl_SRDn <= not (sl_B02 and sl_SBR_Wn);
|
||||
sl_SWR(0) <= not sl_SWRn; -- inverted for Xilinx Block RAM
|
||||
sl_SBW_Rn <= not sl_SBR_Wn;
|
||||
sl_B02 <= sl_PHI2;
|
||||
|
||||
-------------
|
||||
-- sheet 6 --
|
||||
-------------
|
||||
|
||||
-- 14S counter is clocked by 1H = 3.5795MHz and provides TMS5220 clock
|
||||
-- when SQUEAK is 0 counter is preset with 5, else 7 then counts up to F before being preset again
|
||||
-- divide by 11 gives 325.4KHz, divide by 9 gives 397.7KHz
|
||||
p_14S : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if I_1H = '0' then
|
||||
if sph_ctr = "1111" then
|
||||
sph_ctr <= "01" & sl_SQUEAKn & '1';
|
||||
else
|
||||
sph_ctr <= sph_ctr + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 13P
|
||||
p_13P : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
sl_VOICEn_last <= sl_VOICEn;
|
||||
if sl_VOICEn_last = '0' and sl_VOICEn = '1' then
|
||||
slv_TMS_data <= slv_SBDO;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 15S latch - 3 bit volume control
|
||||
p_15S : process(I_SNDRESn, I_MCKR)
|
||||
begin
|
||||
if I_SNDRESn = '0' then
|
||||
slv_SM_vol <= "000";
|
||||
slv_PM_vol <= "000";
|
||||
slv_YM_vol <= "000";
|
||||
elsif rising_edge(I_MCKR) then
|
||||
sl_MIXn_last <= sl_MIXn;
|
||||
if sl_MIXn_last = '0' and sl_MIXn = '1' then
|
||||
slv_SM_vol <= slv_SBDO(7 downto 5);
|
||||
slv_PM_vol <= slv_SBDO(4 downto 3) & slv_SBDO(3); -- PM0 and PM1 are connected together by R132
|
||||
slv_YM_vol <= slv_SBDO(2 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sl_YAMRES <= not sl_YAMRESn;
|
||||
|
||||
-- YM2151 sound
|
||||
u_15R : JT51
|
||||
port map(
|
||||
-- inputs
|
||||
rst => sl_YAMRES, -- active high reset
|
||||
clk => I_1H, -- FIXME
|
||||
cen => '1',
|
||||
cen_p1 => I_2H,
|
||||
a0 => slv_SBA(0),
|
||||
wr_n => sl_SWRn,
|
||||
cs_n => sl_MUSICn,
|
||||
din => slv_SBDO,
|
||||
|
||||
-- outputs
|
||||
dout => slv_YM_data,
|
||||
irq_n => open,
|
||||
|
||||
ct1 => open,
|
||||
ct2 => open,
|
||||
|
||||
-- Low resolution outputs (same as real chip)
|
||||
sample => open, -- marks new output sample
|
||||
left => open, -- std_logic_vector(15 downto 0)
|
||||
right => open, -- std_logic_vector(15 downto 0)
|
||||
|
||||
-- Full resolution outputs
|
||||
xleft => s_YML_out, -- std_logic_vector(15 downto 0)
|
||||
xright => s_YMR_out, -- std_logic_vector(15 downto 0)
|
||||
dacleft => open,
|
||||
dacright => open
|
||||
);
|
||||
|
||||
-- -- YM3012 DAC - not used becase YM2151 core outputs parallel sound data
|
||||
-- u_15T : entity work.YM3012
|
||||
-- generic map (signed_data => false)
|
||||
-- port map (
|
||||
-- PHI0 => clk,
|
||||
-- ICL => reset,
|
||||
-- SDATA => ym_sd,
|
||||
-- SAM1 => ym_sam1,
|
||||
-- SAM2 => ym_sam2,
|
||||
-- CH1 => open,
|
||||
-- Ch2 => open
|
||||
-- );
|
||||
|
||||
-- POKEY sound (Atari custom chip 137430-001)
|
||||
u_15L : entity work.POKEY
|
||||
port map (
|
||||
ADDR => slv_SBA(3 downto 0),
|
||||
DIN => slv_SBDO,
|
||||
DOUT => slv_POKEY_data,
|
||||
DOUT_OE_L => open,
|
||||
RW_L => sl_SBR_Wn,
|
||||
CS => sl_POKEY_cs,
|
||||
CS_L => '0',
|
||||
|
||||
AUDIO_OUT => s_POK_out,
|
||||
|
||||
PIN => x"00",
|
||||
ENA => sl_CPU_ena,
|
||||
CLK => I_MCKR
|
||||
);
|
||||
|
||||
-- TMS5220 Voice Synthesis
|
||||
u_13R : entity work.TMS5220
|
||||
port map (
|
||||
I_OSC => sph_ctr(2),
|
||||
I_WSn => sl_SPHWRn,
|
||||
I_RSn => sl_SPHRESn,
|
||||
I_DATA => '1',
|
||||
I_TEST => '1',
|
||||
I_DBUS => slv_TMS_data,
|
||||
|
||||
O_DBUS => open,
|
||||
O_RDYn => sl_SPHRDYn,
|
||||
O_INTn => open,
|
||||
O_M0 => open,
|
||||
O_M1 => open,
|
||||
O_ADD8 => open,
|
||||
O_ADD4 => open,
|
||||
O_ADD2 => open,
|
||||
O_ADD1 => open,
|
||||
O_ROMCLK => open,
|
||||
O_T11 => open,
|
||||
O_IO => open,
|
||||
O_PRMOUT => open,
|
||||
O_SPKR => s_TMS_out
|
||||
);
|
||||
|
||||
-- FIXME this mixing isn't ideal, sound volume ends up too low
|
||||
-- Pokey sounds OK, but YM seems a bit distorted, try and do better
|
||||
p_volmux : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
|
||||
-- volume control applied to signed outputs
|
||||
s_audio_TMS <= signed('0' & slv_SM_vol) * signed(s_TMS_out);
|
||||
s_audio_POK <= signed('0' & slv_PM_vol) * signed(s_POK_out);
|
||||
s_audio_YML <= signed('0' & slv_YM_vol) * signed(s_YML_out(15 downto 8));
|
||||
s_audio_YMR <= signed('0' & slv_YM_vol) * signed(s_YMR_out(15 downto 8));
|
||||
|
||||
-- sign extend to 14 bits and add all outputs together as signed integers
|
||||
s_chan_l <= signed(s_audio_YML(11) & s_audio_YML(11) & s_audio_YML)
|
||||
+ ( signed(s_audio_POK(11) & s_audio_POK(11) & s_audio_POK)
|
||||
+ signed(s_audio_TMS(11) & s_audio_TMS(11) & s_audio_TMS) );
|
||||
s_chan_r <= signed(s_audio_YMR(11) & s_audio_YMR(11) & s_audio_YMR)
|
||||
+ ( signed(s_audio_POK(11) & s_audio_POK(11) & s_audio_POK)
|
||||
+ signed(s_audio_TMS(11) & s_audio_TMS(11) & s_audio_TMS) );
|
||||
|
||||
-- convert output back to unsigned for DAC usage
|
||||
O_AUDIO_L <= std_logic_vector(not s_chan_l(13) & s_chan_l(12 downto 6));
|
||||
O_AUDIO_R <= std_logic_vector(not s_chan_r(13) & s_chan_r(12 downto 6));
|
||||
end process;
|
||||
|
||||
-------------
|
||||
-- sheet 7 --
|
||||
-------------
|
||||
|
||||
-- 12P buffer
|
||||
slv_12P <= (not I_SNDNMIn) & (not I_SNDINTn) & sl_SPHRDYn & I_SELFTESTn & I_COIN;
|
||||
end RTL;
|
||||
81
Arcade_MiST/Atari Gauntlet Hardware/rtl/CRAMS.vhd
Normal file
81
Arcade_MiST/Atari Gauntlet Hardware/rtl/CRAMS.vhd
Normal file
@@ -0,0 +1,81 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity CRAMS is
|
||||
port(
|
||||
I_MCKR : in std_logic;
|
||||
I_UDSn : in std_logic;
|
||||
I_LDSn : in std_logic;
|
||||
I_CRAMn : in std_logic;
|
||||
I_BR_Wn : in std_logic;
|
||||
I_CRA : in std_logic_vector( 9 downto 0);
|
||||
I_DB : in std_logic_vector(15 downto 0);
|
||||
O_DB : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end CRAMS;
|
||||
|
||||
architecture RTL of CRAMS is
|
||||
signal
|
||||
sl_CRAM_CS,
|
||||
sl_CRAMWRn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_CRAM_WE
|
||||
: std_logic_vector(1 downto 0) := (others=>'0');
|
||||
begin
|
||||
------------------------
|
||||
-- sheet 15 Color RAM --
|
||||
------------------------
|
||||
|
||||
-- 9L, 9M, 10L, 10M RAM
|
||||
p_9L_10L : entity work.spram--Lo
|
||||
generic map (
|
||||
widthad_a => 10,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => I_CRA(9 downto 0),
|
||||
clock => I_MCKR,-- and sl_CRAM_CS,
|
||||
data => I_DB(7 downto 0),
|
||||
wren => slv_CRAM_WE(0),
|
||||
q => O_DB(7 downto 0)
|
||||
);
|
||||
|
||||
p_9M_10M : entity work.spram--Hi
|
||||
generic map (
|
||||
widthad_a => 10,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => I_CRA(9 downto 0),
|
||||
clock => I_MCKR,-- and sl_CRAM_CS,
|
||||
data => I_DB(15 downto 8),
|
||||
wren => slv_CRAM_WE(1),
|
||||
q => O_DB(15 downto 8)
|
||||
);
|
||||
|
||||
|
||||
|
||||
slv_CRAM_WE <= not (
|
||||
(((not I_CRAMn) and I_UDSn) or sl_CRAMWRn) &
|
||||
(((not I_CRAMn) and I_LDSn) or sl_CRAMWRn)
|
||||
);
|
||||
|
||||
-- gates 7W, 11P
|
||||
sl_CRAM_CS <= not (I_UDSn and I_LDSn and (not I_CRAMn));
|
||||
|
||||
-- gate 7X
|
||||
sl_CRAMWRn <= I_CRAMn or I_BR_Wn;
|
||||
end RTL;
|
||||
229
Arcade_MiST/Atari Gauntlet Hardware/rtl/GAUNTLET.vhd
Normal file
229
Arcade_MiST/Atari Gauntlet Hardware/rtl/GAUNTLET.vhd
Normal file
@@ -0,0 +1,229 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
|
||||
-- From: https://en.wikipedia.org/wiki/Gauntlet_(1985_video_game)
|
||||
-- Developer: Atari Games
|
||||
-- Publishers: Atari Games, U.S. Gold
|
||||
-- Designer: Ed Logg
|
||||
-- Platform: Arcade
|
||||
-- Release: October 1985
|
||||
-- Genres: Hack and slash, dungeon crawl
|
||||
-- Mode: Single-player, 4-player multiplayer
|
||||
-- Cabinet: Custom upright
|
||||
-- Arcade system: Atari Gauntlet
|
||||
-- CPU: Motorola 68010 @ 7.15909 MHz, MOS Technology 6502 @ 1.789772 MHz
|
||||
-- Sound: Yamaha YM2151 @ 3.579545, Atari POKEY @ 1.789772 MHz, Texas Instruments TMS5220@ 650.826 kHz
|
||||
-- Display: Raster, 336x240 resolution
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
--pragma translate_off
|
||||
use ieee.std_logic_textio.all;
|
||||
use std.textio.all;
|
||||
--pragma translate_on
|
||||
|
||||
entity GAUNTLET is
|
||||
port(
|
||||
-- System Clock
|
||||
I_CLK_14M : in std_logic;
|
||||
I_CLK_7M : in std_logic;
|
||||
|
||||
-- Active high reset
|
||||
I_RESET : in std_logic;
|
||||
|
||||
-- Player controls, active low
|
||||
I_P1 : in std_logic_vector(7 downto 0);
|
||||
I_P2 : in std_logic_vector(7 downto 0);
|
||||
I_P3 : in std_logic_vector(7 downto 0);
|
||||
I_P4 : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- System inputs
|
||||
I_SYS : in std_logic_vector(4 downto 0);
|
||||
|
||||
O_LEDS : out std_logic_vector(4 downto 1);
|
||||
|
||||
-- Audio out
|
||||
O_AUDIO_L : out std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
O_AUDIO_R : out std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
|
||||
-- Monitor output
|
||||
O_VIDEO_I : out std_logic_vector(3 downto 0);
|
||||
O_VIDEO_R : out std_logic_vector(3 downto 0);
|
||||
O_VIDEO_G : out std_logic_vector(3 downto 0);
|
||||
O_VIDEO_B : out std_logic_vector(3 downto 0);
|
||||
O_HSYNC : out std_logic;
|
||||
O_VSYNC : out std_logic;
|
||||
O_CSYNC : out std_logic;
|
||||
|
||||
-- GFX ROMs
|
||||
O_GP_EN : out std_logic := '0';
|
||||
O_GP_ADDR : out std_logic_vector(15 downto 0) := (others=>'0');
|
||||
I_GP_DATA : in std_logic_vector(31 downto 0) := (others=>'0');
|
||||
-- Main Program ROMs
|
||||
O_MP_EN : out std_logic := '0';
|
||||
O_MP_ADDR : out std_logic_vector(18 downto 0) := (others=>'0');
|
||||
I_MP_DATA : in std_logic_vector(15 downto 0) := (others=>'0');
|
||||
-- Audio Program ROMs
|
||||
O_AP_EN : out std_logic := '0';
|
||||
O_AP_ADDR : out std_logic_vector(15 downto 0) := (others=>'0');
|
||||
I_AP_DATA : in std_logic_vector( 7 downto 0) := (others=>'0')
|
||||
);
|
||||
end GAUNTLET;
|
||||
|
||||
architecture RTL of GAUNTLET is
|
||||
signal
|
||||
sl_1H,
|
||||
sl_2H,
|
||||
sl_32V,
|
||||
sl_R_Wn,
|
||||
sl_LDSn,
|
||||
sl_UDSn,
|
||||
sl_VCPU,
|
||||
sl_SNDNMIn,
|
||||
sl_SNDINTn,
|
||||
sl_SNDRESn,
|
||||
sl_CRAMn,
|
||||
sl_VBUSn,
|
||||
sl_VRAMn,
|
||||
sl_MBUSn,
|
||||
sl_VRDTACK,
|
||||
sl_VBLANKn,
|
||||
sl_VBKACKn,
|
||||
sl_VBKINTn,
|
||||
sl_HSCRLDn
|
||||
: std_logic := '1';
|
||||
signal sl_WR68K : std_logic := '0';
|
||||
signal sl_RD68K : std_logic := '0';
|
||||
signal
|
||||
slv_SBDI,
|
||||
slv_SBDO
|
||||
: std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_addr
|
||||
: std_logic_vector(14 downto 1) := (others=>'0');
|
||||
signal
|
||||
slv_vdata,
|
||||
slv_data
|
||||
: std_logic_vector(15 downto 0) := (others=>'0');
|
||||
begin
|
||||
u_main : entity work.MAIN
|
||||
port map (
|
||||
I_MCKR => I_CLK_7M,
|
||||
I_XCKR => I_CLK_14M,
|
||||
I_RESET => I_RESET,
|
||||
I_VBLANKn => sl_VBLANKn,
|
||||
I_VBKINTn => sl_VBKINTn,
|
||||
I_VCPU => sl_VCPU,
|
||||
I_WR68K => sl_WR68K,
|
||||
I_RD68K => sl_RD68K,
|
||||
I_SBD => slv_SBDO,
|
||||
I_DATA => slv_vdata,
|
||||
|
||||
I_SELFTESTn => I_SYS(4),
|
||||
I_P1 => I_P1,
|
||||
I_P2 => I_P2,
|
||||
I_P3 => I_P3,
|
||||
I_P4 => I_P4,
|
||||
|
||||
O_HSCRLDn => sl_HSCRLDn,
|
||||
O_SNDNMIn => sl_SNDNMIn,
|
||||
O_SNDINTn => sl_SNDINTn,
|
||||
O_SNDRESn => sl_SNDRESn,
|
||||
O_CRAMn => sl_CRAMn,
|
||||
O_VRAMn => sl_VRAMn,
|
||||
O_VBUSn => sl_VBUSn,
|
||||
O_VRDTACK => sl_VRDTACK,
|
||||
O_VBKACKn => sl_VBKACKn,
|
||||
O_R_Wn => sl_R_Wn,
|
||||
O_LDSn => sl_LDSn,
|
||||
O_UDSn => sl_UDSn,
|
||||
|
||||
O_LEDS => O_LEDS,
|
||||
O_SBD => slv_SBDI,
|
||||
O_ADDR => slv_addr,
|
||||
O_DATA => slv_data,
|
||||
|
||||
-- external CPU ROMs
|
||||
O_MP_EN => O_MP_EN,
|
||||
O_MP_ADDR => O_MP_ADDR,
|
||||
I_MP_DATA => I_MP_DATA
|
||||
);
|
||||
|
||||
u_video : entity work.VIDEO
|
||||
port map (
|
||||
I_MCKR => I_CLK_7M,
|
||||
I_ADDR => slv_addr,
|
||||
I_DATA => slv_data,
|
||||
I_HSCRLDn => sl_HSCRLDn,
|
||||
I_CRAMn => sl_CRAMn,
|
||||
I_VRAMn => sl_VRAMn,
|
||||
I_VBUSn => sl_VBUSn,
|
||||
I_VRDTACK => sl_VRDTACK,
|
||||
I_VBKACKn => sl_VBKACKn,
|
||||
I_R_Wn => sl_R_Wn,
|
||||
I_LDSn => sl_LDSn,
|
||||
I_UDSn => sl_UDSn,
|
||||
O_VCPU => sl_VCPU,
|
||||
O_1H => sl_1H,
|
||||
O_2H => sl_2H,
|
||||
O_32V => sl_32V,
|
||||
O_VBKINTn => sl_VBKINTn,
|
||||
O_VBLANKn => sl_VBLANKn,
|
||||
O_DATA => slv_vdata,
|
||||
O_I => O_VIDEO_I,
|
||||
O_R => O_VIDEO_R,
|
||||
O_G => O_VIDEO_G,
|
||||
O_B => O_VIDEO_B,
|
||||
O_HSYNC => O_HSYNC,
|
||||
O_VSYNC => O_VSYNC,
|
||||
O_CSYNC => O_CSYNC,
|
||||
|
||||
-- external GFX ROMs
|
||||
O_GP_EN => O_GP_EN,
|
||||
O_GP_ADDR => O_GP_ADDR,
|
||||
I_GP_DATA => I_GP_DATA
|
||||
);
|
||||
|
||||
u_audio : entity work.AUDIO
|
||||
port map (
|
||||
I_MCKR => I_CLK_7M,
|
||||
|
||||
I_1H => sl_1H,
|
||||
I_2H => sl_2H,
|
||||
I_32V => sl_32V,
|
||||
I_VBLANKn => sl_VBLANKn,
|
||||
|
||||
I_SNDNMIn => sl_SNDNMIn,
|
||||
I_SNDINTn => sl_SNDINTn,
|
||||
I_SNDRESn => sl_SNDRESn,
|
||||
|
||||
I_SELFTESTn => I_SYS(4),
|
||||
I_COIN => I_SYS(3 downto 0), -- 1L, 2, 3, 4R
|
||||
|
||||
I_SBD => slv_SBDI,
|
||||
O_SBD => slv_SBDO,
|
||||
O_WR68K => sl_WR68K,
|
||||
O_RD68K => sl_RD68K,
|
||||
|
||||
O_CCTR1n => open, -- coin counter open collector active low
|
||||
O_CCTR2n => open, -- coin counter open collector active low
|
||||
O_AUDIO_L => O_AUDIO_L,
|
||||
O_AUDIO_R => O_AUDIO_R,
|
||||
|
||||
-- external audio ROMs
|
||||
O_AP_EN => O_AP_EN,
|
||||
O_AP_AD => O_AP_ADDR,
|
||||
I_AP_DI => I_AP_DATA
|
||||
);
|
||||
|
||||
end RTL;
|
||||
141
Arcade_MiST/Atari Gauntlet Hardware/rtl/GPC.vhd
Normal file
141
Arcade_MiST/Atari Gauntlet Hardware/rtl/GPC.vhd
Normal file
@@ -0,0 +1,141 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- Graphic Priority Control (Atari custom chip 137419-101)
|
||||
-- This GPC was derived from System I SP-277 schematic
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity GPC is
|
||||
port(
|
||||
I_CK : in std_logic; -- MCKR
|
||||
I_PFM : in std_logic; -- PFSC/MO
|
||||
I_4H : in std_logic; -- 4H
|
||||
I_SEL : in std_logic; -- /CRAM
|
||||
I_AL : in std_logic_vector(1 downto 0); -- APIX
|
||||
I_MA : in std_logic_vector(1 downto 0); -- MA9, MA10
|
||||
I_D : in std_logic_vector(3 downto 0); -- VRD
|
||||
I_P : in std_logic_vector(7 downto 0); -- PFX
|
||||
I_M : in std_logic_vector(7 downto 0); -- MPX
|
||||
|
||||
O_CA : out std_logic_vector(9 downto 0) -- CRA
|
||||
);
|
||||
end GPC;
|
||||
|
||||
architecture RTL of GPC is
|
||||
signal
|
||||
sl_gate,
|
||||
sl_3C6,
|
||||
sl_3F2,
|
||||
sl_1C12,
|
||||
sl_4HD,
|
||||
sl_3H
|
||||
: std_logic := '1';
|
||||
signal
|
||||
PROM_3E_data,
|
||||
slv_CRAS,
|
||||
slv_hcnt
|
||||
: std_logic_vector(1 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_ALC
|
||||
: std_logic_vector(2 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_3H
|
||||
: std_logic_vector(3 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_9D
|
||||
: std_logic_vector(7 downto 0) := (others=>'1');
|
||||
begin
|
||||
-- 8D tristate buffers
|
||||
O_CA <= I_MA & "ZZZZZZZZ" when I_SEL = '0' else slv_CRAS & slv_9D;
|
||||
|
||||
-- gate 3C output 6 (PFX7..3)
|
||||
sl_3C6 <= (not (I_P(7) or I_P(6) or I_P(5) or I_P(4) or I_P(3)));
|
||||
|
||||
-- gate 1C output 12 (MPX3..1)
|
||||
sl_1C12 <= (not (I_M(3) and I_M(2) and I_M(1)));
|
||||
|
||||
-- when any of these are high, PROM output is all low
|
||||
sl_gate <= not (sl_3F2 or I_AL(1) or I_AL(0));
|
||||
|
||||
-- These equations describe the PROM 3E contents,
|
||||
-- top 2 data bits are the same as bottom 2 data bits as can be seen in PROM dump
|
||||
PROM_3E_data(1) <= sl_gate and ((sl_3C6 and I_PFM) or (not I_M(7)) or (I_M(0) and (not sl_1C12)) );
|
||||
PROM_3E_data(0) <= sl_gate and not ((sl_3C6 and I_PFM) or (((not I_M(7)) or (I_M(0))) and (not sl_1C12)) );
|
||||
|
||||
-- Graphic Priority Control selection
|
||||
-- 3C9 3C7 4C7 4C9 7C7 7C9 6C7 6C9 case
|
||||
-- GND GND GND ALC2 ALC1 ALC0 APIX1 APIX0 0
|
||||
-- GND /MPX6 /MPX5 /MPX4 /MPX3 /MPX2 /MPX1 /MPX0 1
|
||||
-- PFX7 PFX6 PFX5 PFX4 PFX3 PFX2 PFX1 PFX0 2
|
||||
-- PFX3 PFX2 PFX1 PFX0 /MPX3 /MPX2 /MPX1 /MPX0 3
|
||||
|
||||
-- 9D latch
|
||||
p_9D : process
|
||||
begin
|
||||
wait until falling_edge(I_CK);
|
||||
if I_SEL = '1' then
|
||||
-- 3C, 4C, 7C, 6C dual 4:1 muxes
|
||||
case PROM_3E_data is
|
||||
when "00" => slv_9D <= "000" & slv_ALC & I_AL;
|
||||
when "01" => slv_9D <= '0' & not I_M(6 downto 0);
|
||||
when "10" => slv_9D <= I_P;
|
||||
when "11" => slv_9D <= I_P(3 downto 0) & not I_M(3 downto 0);
|
||||
when others => slv_9D <= "11111111";
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 3H latch
|
||||
p_3H : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
if (sl_3H='1') and (I_4H='0') then
|
||||
slv_3H <= I_D;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- recreate part of the horizontal counter to generate the 3H signal
|
||||
p_hcnt : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
sl_4HD <= I_4H;
|
||||
if (sl_4HD='0' and I_4H='1') then
|
||||
slv_hcnt<="01";
|
||||
else
|
||||
slv_hcnt <= slv_hcnt + 1;
|
||||
end if;
|
||||
end process;
|
||||
sl_3H <= slv_hcnt(1) and slv_hcnt(0);
|
||||
|
||||
-- The old circuit built with discrete chips is gated by "/H03 = 1H nand 2H;" but LSI chip does not
|
||||
-- have 1H, 2H or /H03 coming in so here we bring H03 from outside the chip
|
||||
-- 3F latch
|
||||
p_3F : process
|
||||
begin
|
||||
wait until falling_edge(I_CK);
|
||||
if sl_3H='1' then
|
||||
sl_3F2 <= slv_3H(3);
|
||||
slv_ALC <= slv_3H(2 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 1B, 5B latch
|
||||
p_1B_5B : process
|
||||
begin
|
||||
wait until falling_edge(I_CK);
|
||||
slv_CRAS <= PROM_3E_data;
|
||||
end process;
|
||||
end RTL;
|
||||
309
Arcade_MiST/Atari Gauntlet Hardware/rtl/Gauntlet_MiST.sv
Normal file
309
Arcade_MiST/Atari Gauntlet Hardware/rtl/Gauntlet_MiST.sv
Normal file
@@ -0,0 +1,309 @@
|
||||
module Gauntlet_MiST(
|
||||
output LED,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output AUDIO_L,
|
||||
output AUDIO_R,
|
||||
input SPI_SCK,
|
||||
inout SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SS2,
|
||||
input SPI_SS3,
|
||||
input SPI_SS4,
|
||||
input CONF_DATA0,
|
||||
input CLOCK_27,
|
||||
|
||||
output [12:0] SDRAM_A,
|
||||
inout [15:0] SDRAM_DQ,
|
||||
output SDRAM_DQML,
|
||||
output SDRAM_DQMH,
|
||||
output SDRAM_nWE,
|
||||
output SDRAM_nCAS,
|
||||
output SDRAM_nRAS,
|
||||
output SDRAM_nCS,
|
||||
output [1:0] SDRAM_BA,
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE
|
||||
);
|
||||
|
||||
`include "rtl/build_id.v"
|
||||
|
||||
localparam CONF_STR = {
|
||||
"GAUNTLET;ROM;",
|
||||
"O2,Rotate Controls,Off,On;",
|
||||
"O34,Scanlines,Off,25%,50%,75%;",
|
||||
"O5,Blending,Off,On;",
|
||||
"O7,Service,Off,On;",
|
||||
"T0,Reset;",
|
||||
"V,v1.0.",`BUILD_DATE
|
||||
};
|
||||
|
||||
wire rotate = status[2];
|
||||
wire [1:0] scanlines = status[4:3];
|
||||
wire blend = status[5];
|
||||
wire joyswap = status[6];
|
||||
wire service = status[7];
|
||||
reg oneplayer;
|
||||
|
||||
|
||||
|
||||
assign LED = ~ioctl_downl;
|
||||
assign SDRAM_CLK = clk_sd;
|
||||
assign SDRAM_CKE = 1;
|
||||
|
||||
wire clk_sys, clk_14, clk_7, clk_sd;
|
||||
wire pll_locked;
|
||||
pll_mist pll(
|
||||
.inclk0(CLOCK_27),
|
||||
.areset(0),
|
||||
.c0(clk_sd),//64
|
||||
.c1(clk_sys),//28
|
||||
.c2(clk_14),//14
|
||||
.c3(clk_7),//7
|
||||
.locked(pll_locked)
|
||||
);
|
||||
|
||||
wire [31:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
wire [7:0] joystick_0;
|
||||
wire [7:0] joystick_1;
|
||||
wire scandoublerD;
|
||||
wire ypbpr;
|
||||
wire no_csync;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
user_io #(
|
||||
.STRLEN(($size(CONF_STR)>>3)),
|
||||
.ROM_DIRECT_UPLOAD(1'b1))
|
||||
user_io(
|
||||
.clk_sys (clk_sys ),
|
||||
.conf_str (CONF_STR ),
|
||||
.SPI_CLK (SPI_SCK ),
|
||||
.SPI_SS_IO (CONF_DATA0 ),
|
||||
.SPI_MISO (SPI_DO ),
|
||||
.SPI_MOSI (SPI_DI ),
|
||||
.buttons (buttons ),
|
||||
.switches (switches ),
|
||||
.scandoubler_disable (scandoublerD ),
|
||||
.ypbpr (ypbpr ),
|
||||
.no_csync (no_csync ),
|
||||
.key_strobe (key_strobe ),
|
||||
.key_pressed (key_pressed ),
|
||||
.key_code (key_code ),
|
||||
.joystick_0 (joystick_0 ),
|
||||
.joystick_1 (joystick_1 ),
|
||||
.status (status )
|
||||
);
|
||||
|
||||
wire [18:0] rom_addr;
|
||||
wire [15:0] rom_do;
|
||||
|
||||
wire [15:0] snd_addr;
|
||||
wire [15:0] snd_do;
|
||||
|
||||
wire [15:0] sp_addr;
|
||||
wire [31:0] sp_do;
|
||||
wire [24:0] sp_ioctl_addr = ioctl_addr - 20'h34000;
|
||||
wire [24:0] snd_ioctl_addr = ioctl_addr - 18'h28000;
|
||||
|
||||
/* ROM structure
|
||||
00000-27FFF CPU1 160k Program
|
||||
28000-33FFF CPU2 48k Sound
|
||||
34000-73FFF GFX2 256k
|
||||
|
||||
for now
|
||||
*/
|
||||
|
||||
wire ioctl_downl;
|
||||
wire [7:0] ioctl_index;
|
||||
wire ioctl_wr;
|
||||
wire [24:0] ioctl_addr;
|
||||
wire [7:0] ioctl_dout;
|
||||
|
||||
data_io #(.ROM_DIRECT_UPLOAD(1'b1)) data_io(
|
||||
.clk_sys ( clk_sys ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS2 ( SPI_SS2 ),
|
||||
.SPI_SS4 ( SPI_SS4 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
.SPI_DO ( SPI_DO ),
|
||||
.ioctl_download( ioctl_downl ),
|
||||
.ioctl_index ( ioctl_index ),
|
||||
.ioctl_wr ( ioctl_wr ),
|
||||
.ioctl_addr ( ioctl_addr ),
|
||||
.ioctl_dout ( ioctl_dout )
|
||||
);
|
||||
|
||||
|
||||
reg port1_req, port2_req;
|
||||
sdram sdram(
|
||||
.*,
|
||||
.init_n ( pll_locked ),
|
||||
.clk ( clk_sd ),
|
||||
|
||||
// port1 used for main + sound CPU
|
||||
.port1_req ( port1_req ),
|
||||
.port1_ack ( ),
|
||||
.port1_a ( ioctl_addr[23:1] ),
|
||||
.port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ),
|
||||
.port1_we ( ioctl_downl ),
|
||||
.port1_d ( {ioctl_dout, ioctl_dout} ),
|
||||
.port1_q ( ),
|
||||
|
||||
.cpu1_addr ( ioctl_downl ? 18'h3ffff : {rom_addr[18:0]} ),
|
||||
.cpu1_q ( rom_do ),
|
||||
.cpu2_addr ( ioctl_downl ? 18'h3ffff : snd_ioctl_addr ),
|
||||
.cpu2_q ( snd_do ),
|
||||
|
||||
// port2 for sprite graphics
|
||||
.port2_req ( port2_req ),
|
||||
.port2_ack ( ),
|
||||
.port2_a ( {sp_ioctl_addr[23:16], sp_ioctl_addr[13:0], sp_ioctl_addr[15]} ), // merge sprite roms to 32-bit wide words
|
||||
.port2_ds ( {sp_ioctl_addr[14], ~sp_ioctl_addr[14]} ),
|
||||
.port2_we ( ioctl_downl ),
|
||||
.port2_d ( {ioctl_dout, ioctl_dout} ),
|
||||
.port2_q ( ),
|
||||
|
||||
.sp_addr ( ioctl_downl ? 15'h7fff : sp_addr ),
|
||||
.sp_q ( sp_do )
|
||||
);
|
||||
|
||||
|
||||
// ROM download controller
|
||||
always @(posedge clk_sys) begin
|
||||
reg ioctl_wr_last = 0;
|
||||
|
||||
ioctl_wr_last <= ioctl_wr;
|
||||
if (ioctl_downl) begin
|
||||
if (~ioctl_wr_last && ioctl_wr) begin
|
||||
port1_req <= ~port1_req;
|
||||
port2_req <= ~port2_req;
|
||||
end
|
||||
end
|
||||
// async clock domain crossing here (clk_snd -> clk_sys)
|
||||
end
|
||||
|
||||
// reset signal generation
|
||||
reg reset = 1;
|
||||
reg rom_loaded = 0;
|
||||
always @(posedge clk_sys) begin
|
||||
reg ioctl_downlD;
|
||||
reg [15:0] reset_count;
|
||||
ioctl_downlD <= ioctl_downl;
|
||||
|
||||
if (status[0] | buttons[1]/* ~rom_loaded*/)reset_count <= 16'hffff;
|
||||
else if (reset_count != 0) reset_count <= reset_count - 1'd1;
|
||||
|
||||
if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1;
|
||||
reset <= reset_count != 16'h0000;
|
||||
|
||||
end
|
||||
|
||||
wire [7:0] audiol, audior;
|
||||
wire hs, vs, cs;
|
||||
wire blankn;
|
||||
wire [3:0] g,b,r;
|
||||
|
||||
GAUNTLET GAUNTLET(
|
||||
.I_CLK_14M(clk_14),
|
||||
.I_CLK_7M(clk_7),
|
||||
.I_RESET(reset),
|
||||
.I_P1({m_up,m_down,m_left,m_right,1'b1,1'b1,m_fireA,m_one_player}),
|
||||
.I_P2(8'hFF),
|
||||
.I_P3(8'hFF),
|
||||
.I_P4(8'hFF),
|
||||
.I_SYS({~service,m_coin1,m_coin2,1'b1,1'b1}),
|
||||
.O_LEDS(),
|
||||
.O_AUDIO_L(audiol),
|
||||
.O_AUDIO_R(audior),
|
||||
.O_VIDEO_I(),
|
||||
.O_VIDEO_R(r),
|
||||
.O_VIDEO_G(g),
|
||||
.O_VIDEO_B(b),
|
||||
.O_HSYNC(hs),
|
||||
.O_VSYNC(vs),
|
||||
.O_CSYNC(blankn),
|
||||
// GFX ROMs
|
||||
.O_GP_EN(),
|
||||
.O_GP_ADDR(sp_addr),
|
||||
.I_GP_DATA(sp_do),
|
||||
// Main Program ROMs
|
||||
.O_MP_EN(),
|
||||
.O_MP_ADDR(rom_addr),
|
||||
.I_MP_DATA(rom_do),
|
||||
// Audio Program ROMs
|
||||
.O_AP_EN(),
|
||||
.O_AP_ADDR(snd_addr),
|
||||
.I_AP_DATA(snd_addr[0] ? snd_do[15:8] : snd_do[7:0])
|
||||
);
|
||||
|
||||
mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(11)) mist_video(
|
||||
.clk_sys ( clk_sys ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS3 ( SPI_SS3 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
.R ( blankn ? r : 0 ),
|
||||
.G ( blankn ? g : 0 ),
|
||||
.B ( blankn ? b : 0 ),
|
||||
.HSync ( hs ),
|
||||
.VSync ( vs ),
|
||||
.VGA_R ( VGA_R ),
|
||||
.VGA_G ( VGA_G ),
|
||||
.VGA_B ( VGA_B ),
|
||||
.VGA_VS ( VGA_VS ),
|
||||
.VGA_HS ( VGA_HS ),
|
||||
.rotate ( { 2'b10, rotate } ),
|
||||
.ce_divider ( 1'b1 ),
|
||||
.scandoubler_disable( scandoublerD ),
|
||||
.scanlines ( scanlines ),
|
||||
.blend ( blend ),
|
||||
.ypbpr ( ypbpr ),
|
||||
.no_csync ( no_csync )
|
||||
);
|
||||
|
||||
|
||||
dac #(
|
||||
.C_bits(8))
|
||||
dacl(
|
||||
.clk_i(clk_sys),
|
||||
.res_n_i(1),
|
||||
.dac_i(audiol),
|
||||
.dac_o(AUDIO_L)
|
||||
);
|
||||
|
||||
dac #(
|
||||
.C_bits(8))
|
||||
dacr(
|
||||
.clk_i(clk_sys),
|
||||
.res_n_i(1),
|
||||
.dac_i(audior),
|
||||
.dac_o(AUDIO_R)
|
||||
);
|
||||
|
||||
wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF;
|
||||
wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F;
|
||||
wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
|
||||
|
||||
arcade_inputs inputs (
|
||||
.clk ( clk_sys ),
|
||||
.key_strobe ( key_strobe ),
|
||||
.key_pressed ( key_pressed ),
|
||||
.key_code ( key_code ),
|
||||
.joystick_0 ( joystick_0 ),
|
||||
.joystick_1 ( joystick_1 ),
|
||||
.rotate ( rotate ),
|
||||
.orientation ( 2'b10 ),
|
||||
.joyswap ( joyswap ),
|
||||
.oneplayer ( oneplayer ),
|
||||
.controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
|
||||
.player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
|
||||
.player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
99
Arcade_MiST/Atari Gauntlet Hardware/rtl/LINEBUF.vhd
Normal file
99
Arcade_MiST/Atari Gauntlet Hardware/rtl/LINEBUF.vhd
Normal file
@@ -0,0 +1,99 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- Line Buffer used in Motion Object Horizontal Line Buffer module
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity LINEBUF is
|
||||
port(
|
||||
I_MCKR : in std_logic;
|
||||
I_BUFCLRn : in std_logic;
|
||||
I_LDn : in std_logic;
|
||||
I_FLBn : in std_logic;
|
||||
I_CSn : in std_logic;
|
||||
|
||||
I_HPOS : in std_logic_vector(8 downto 0);
|
||||
I_MOSR : in std_logic_vector(7 downto 0);
|
||||
|
||||
O_MPX : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end LINEBUF;
|
||||
|
||||
architecture RTL of LINEBUF is
|
||||
-- type RAM_ARRAY is array (0 to 511) of std_logic_vector(7 downto 0);
|
||||
-- signal RAM : RAM_ARRAY := ((others=>(others=>'1')));
|
||||
-- attribute ram_style : string;
|
||||
-- attribute ram_style of RAM : signal is "block";
|
||||
|
||||
signal
|
||||
sl_CLRn,
|
||||
sl_LDn,
|
||||
sl_CSn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_LBD
|
||||
: std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_LB
|
||||
: std_logic_vector( 8 downto 0) := (others=>'1');
|
||||
begin
|
||||
sl_CLRn <= I_FLBn or I_BUFCLRn;
|
||||
sl_LDn <= I_FLBn or I_LDn;
|
||||
sl_CSn <= (not I_FLBn) and I_CSn;
|
||||
|
||||
-- 3T, 3R, 3W, 3U, 3S, 3X counters
|
||||
p_ctrs : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_CLRn = '0' then
|
||||
slv_LB <= (others=>'0');
|
||||
elsif sl_LDn = '0' then
|
||||
slv_LB <= I_HPOS;
|
||||
else
|
||||
slv_LB <= slv_LB + 1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 1X, 1W, 2X, 2W RAM
|
||||
-- p_rams : process
|
||||
-- begin
|
||||
-- -- MCKR connected to /WE so RAM is written when MCKR is low
|
||||
-- wait until falling_edge(I_MCKR);
|
||||
-- if sl_CSn = '0' then
|
||||
-- RAM(to_integer(unsigned(slv_LB))) <= slv_LBD;
|
||||
-- -- 4W, 5W latches
|
||||
-- O_MPX <= RAM(to_integer(unsigned(slv_LB)));
|
||||
-- else
|
||||
-- O_MPX <= (others=>'1');
|
||||
-- end if;
|
||||
-- end process;
|
||||
|
||||
buff : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 9,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_LB,
|
||||
clock => I_MCKR,
|
||||
data => slv_LBD,
|
||||
wren => not sl_CSn,--?
|
||||
q => O_MPX
|
||||
);
|
||||
|
||||
|
||||
-- LBD bus mux, 4X, 5X or pullups RN1, RN2
|
||||
slv_LBD <= I_MOSR when I_FLBn = '0' else (others=>'1');
|
||||
end RTL;
|
||||
50
Arcade_MiST/Atari Gauntlet Hardware/rtl/LS299.vhd
Normal file
50
Arcade_MiST/Atari Gauntlet Hardware/rtl/LS299.vhd
Normal file
@@ -0,0 +1,50 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
-- simplified 74LS299 shifter as used in SLAGS
|
||||
entity LS299 is
|
||||
port(
|
||||
I_CK : in std_logic; -- Clock
|
||||
I_DATA : in std_logic_vector(7 downto 0); -- parallel input
|
||||
I_SEL : in std_logic_vector(1 downto 0); -- S1 S0
|
||||
I_SL : in std_logic; -- SL shift left input
|
||||
I_SR : in std_logic; -- SR shift right input
|
||||
O_SL : out std_logic; -- QA shift left output
|
||||
O_SR : out std_logic -- QH shift right output
|
||||
);
|
||||
end LS299;
|
||||
|
||||
architecture RTL of LS299 is
|
||||
signal slv_shifter : std_logic_vector(7 downto 0) := (others=>'0');
|
||||
begin
|
||||
O_SR <= slv_shifter(7);
|
||||
O_SL <= slv_shifter(0);
|
||||
|
||||
-- LS299 shifter
|
||||
-- datasheet labels shifter inputs ABCDEFGH corresponding to D7..D0 as connected to circuit
|
||||
-- so because the bit order is reversed, then shift left/right directions are also reversed
|
||||
p_shift : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
case I_SEL is
|
||||
when "11" => slv_shifter <= I_DATA; -- load
|
||||
when "10" => slv_shifter <= I_SL & slv_shifter(7 downto 1); -- left >HGFEDCB
|
||||
when "01" => slv_shifter <= slv_shifter(6 downto 0) & I_SR ; -- right GFEDCBA<
|
||||
when "00" => -- hold
|
||||
when others => null;
|
||||
end case;
|
||||
end process;
|
||||
end RTL;
|
||||
625
Arcade_MiST/Atari Gauntlet Hardware/rtl/MAIN.vhd
Normal file
625
Arcade_MiST/Atari Gauntlet Hardware/rtl/MAIN.vhd
Normal file
@@ -0,0 +1,625 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity MAIN is
|
||||
port(
|
||||
I_MCKR : in std_logic; -- 7MHz
|
||||
I_XCKR : in std_logic;
|
||||
I_RESET : in std_logic; -- active high
|
||||
I_VBLANKn : in std_logic;
|
||||
I_VBKINTn : in std_logic;
|
||||
I_VCPU : in std_logic;
|
||||
I_WR68K : in std_logic;
|
||||
I_RD68K : in std_logic;
|
||||
I_SBD : in std_logic_vector( 7 downto 0);
|
||||
I_DATA : in std_logic_vector(15 downto 0);
|
||||
|
||||
-- active low player inputs
|
||||
I_SELFTESTn : in std_logic;
|
||||
I_P1 : in std_logic_vector( 7 downto 0); -- U, D, L, R, -, -, F, S
|
||||
I_P2 : in std_logic_vector( 7 downto 0); -- U, D, L, R, -, -, F, S
|
||||
I_P3 : in std_logic_vector( 7 downto 0); -- U, D, L, R, -, -, F, S
|
||||
I_P4 : in std_logic_vector( 7 downto 0); -- U, D, L, R, -, -, F, S
|
||||
|
||||
O_HSCRLDn : out std_logic;
|
||||
O_SNDNMIn : out std_logic;
|
||||
O_SNDINTn : out std_logic;
|
||||
O_SNDRESn : out std_logic;
|
||||
O_CRAMn : out std_logic;
|
||||
O_VRAMn : out std_logic;
|
||||
O_VBUSn : out std_logic;
|
||||
O_VRDTACK : out std_logic;
|
||||
O_VBKACKn : out std_logic;
|
||||
O_R_Wn : out std_logic;
|
||||
O_LDSn : out std_logic;
|
||||
O_UDSn : out std_logic;
|
||||
|
||||
O_LEDS : out std_logic_vector( 4 downto 1) := (others=>'0');
|
||||
O_SBD : out std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
O_ADDR : out std_logic_vector(14 downto 1) := (others=>'0');
|
||||
O_DATA : out std_logic_vector(15 downto 0) := (others=>'0');
|
||||
|
||||
-- external program ROMs
|
||||
O_MP_EN : out std_logic;
|
||||
O_MP_ADDR : out std_logic_vector(18 downto 0) := (others=>'0');
|
||||
I_MP_DATA : in std_logic_vector(15 downto 0) := (others=>'0')
|
||||
);
|
||||
end MAIN;
|
||||
|
||||
architecture RTL of MAIN is
|
||||
signal
|
||||
sl_13L_Y0,
|
||||
-- sl_13L_Y1,
|
||||
sl_13L_Y2,
|
||||
sl_13L_Y3,
|
||||
sl_8T_Y0,
|
||||
sl_8T_Y1,
|
||||
-- sl_8T_Y2,
|
||||
sl_8T_Y3,
|
||||
sl_13M_Y0,
|
||||
sl_13M_Y1,
|
||||
sl_13M_Y2,
|
||||
sl_13M_Y3,
|
||||
sl_14K_Y0,
|
||||
-- sl_14K_Y1,
|
||||
sl_14K_Y2,
|
||||
-- sl_14K_Y3,
|
||||
sl_14K_Y4,
|
||||
sl_14K_Y5,
|
||||
-- sl_14K_Y6,
|
||||
sl_14K_Y7,
|
||||
sl_14D_Y0,
|
||||
sl_14D_Y1,
|
||||
sl_14D_Y2,
|
||||
sl_14D_Y3,
|
||||
sl_14D_Y4,
|
||||
-- sl_14D_Y5,
|
||||
-- sl_14D_Y6,
|
||||
sl_14D_Y7,
|
||||
sl_10D_Y0,
|
||||
-- sl_10D_Y1,
|
||||
-- sl_10D_Y2,
|
||||
sl_10D_Y3,
|
||||
sl_10D_Y4,
|
||||
-- sl_10D_Y5,
|
||||
-- sl_10D_Y6,
|
||||
-- sl_10D_Y7,
|
||||
sl_13N9,
|
||||
|
||||
sl_BAS,
|
||||
sl_VCPU,
|
||||
sl_SNDRDn,
|
||||
sl_SNDWRn,
|
||||
sl_SNDWRn_last,
|
||||
sl_VBLANKn_last,
|
||||
sl_VCPU_last,
|
||||
sl_WR68K_last,
|
||||
sl_WLn_last,
|
||||
sl_SNDINTn,
|
||||
sl_SNDBUF,
|
||||
sl_SNDRESn,
|
||||
sl_13Na_clr,
|
||||
sl_UNLOCKn,
|
||||
sl_LATCHn,
|
||||
sl_WDOGn,
|
||||
sl_INPUTn,
|
||||
|
||||
sl_VPA,
|
||||
sl_RCO,
|
||||
|
||||
sl_PL4n,
|
||||
sl_PL3n,
|
||||
sl_PL2n,
|
||||
sl_PL1n,
|
||||
|
||||
sl_EEP_OEn,
|
||||
sl_EEP_CEn,
|
||||
sl_SLAPSTK,
|
||||
sl_BS0,
|
||||
sl_BS1,
|
||||
sl_ASn,
|
||||
sl_ROM,
|
||||
sl_SYSRESn,
|
||||
-- sl_CPU_HALT,
|
||||
sl_CPU_RESET,
|
||||
sl_ROM_H_Ln,
|
||||
|
||||
sl_R_Wn,
|
||||
-- sl_BR_Wn,
|
||||
sl_BW_Rn,
|
||||
sl_DTACKn,
|
||||
sl_drive,
|
||||
sl_LDSn,
|
||||
sl_UDSn,
|
||||
sl_CRAMn,
|
||||
sl_VBUSn,
|
||||
sl_VRAMn,
|
||||
sl_VRAMn_last,
|
||||
sl_MBUSn,
|
||||
sl_VBKACKn,
|
||||
sl_HSCRLDn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
sl_68KBUF,
|
||||
sl_VRDTACK
|
||||
: std_logic := '0';
|
||||
signal
|
||||
sl_WH,
|
||||
sl_WL,
|
||||
sl_WHn,
|
||||
sl_WLn
|
||||
: std_logic := '0';
|
||||
signal
|
||||
slv_BS,
|
||||
slv_RAMn,
|
||||
slv_RAM
|
||||
: std_logic_vector( 1 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_FC,
|
||||
slv_ROMEN,
|
||||
slv_IPL
|
||||
: std_logic_vector( 2 downto 0) := (others=>'1');
|
||||
signal
|
||||
ctr_11N,
|
||||
ctr_11R
|
||||
: std_logic_vector( 3 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_SBDI,
|
||||
slv_14F,
|
||||
slv_EEP_14A,
|
||||
slv_11A_data,
|
||||
slv_11B_data,
|
||||
slv_12A_data,
|
||||
slv_12B_data
|
||||
: std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_cpu_di,
|
||||
slv_cpu_do,
|
||||
slv_VRAM_PF,
|
||||
slv_VRAM_MO,
|
||||
slv_VRAM_AL,
|
||||
slv_CRAM,
|
||||
VID_D
|
||||
: std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal
|
||||
VID_A : std_logic_vector(18 downto 0) := (others=>'0');
|
||||
|
||||
signal
|
||||
slv_cpu_ad
|
||||
: std_logic_vector(23 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
O_ADDR <= slv_cpu_ad(14 downto 1);
|
||||
O_DATA <= slv_cpu_do;
|
||||
O_HSCRLDn <= sl_HSCRLDn;
|
||||
O_SNDNMIn <= not sl_68KBUF;
|
||||
O_SNDINTn <= not sl_SNDBUF;
|
||||
O_CRAMn <= sl_CRAMn;
|
||||
O_VRAMn <= sl_VRAMn;
|
||||
O_VBUSn <= sl_VBUSn;
|
||||
O_VRDTACK <= sl_VRDTACK;
|
||||
O_VBKACKn <= sl_VBKACKn;
|
||||
O_R_Wn <= sl_R_Wn;
|
||||
O_LDSn <= sl_LDSn;
|
||||
O_UDSn <= sl_UDSn;
|
||||
sl_VCPU <= I_VCPU;
|
||||
|
||||
----------------------------
|
||||
-- sheet 2
|
||||
----------------------------
|
||||
|
||||
-- reset circuit
|
||||
-- counter counts VBLANK intervals from 8 up to 15
|
||||
-- the system resets if it reaches 0 without being preset by watchdog back to 8
|
||||
p_11R : process(I_RESET, I_MCKR)
|
||||
begin
|
||||
if I_RESET = '1' then
|
||||
ctr_11R <= "0000";
|
||||
elsif rising_edge(I_MCKR) then
|
||||
sl_VBLANKn_last<=I_VBLANKn;
|
||||
if sl_WDOGn = '0' then
|
||||
ctr_11R <= "1000";
|
||||
elsif sl_VBLANKn_last='1' and I_VBLANKn='0' then
|
||||
ctr_11R <= ctr_11R + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sl_SYSRESn <= ctr_11R(3);
|
||||
-- sl_CPU_HALT <= ctr_11R(3); -- softcore CPU doesn't have HALT
|
||||
sl_CPU_RESET <= sl_SYSRESn;
|
||||
|
||||
-- Xilinx BRAMs have positive logic
|
||||
sl_WH <= not sl_WHn;
|
||||
sl_WL <= not sl_WLn;
|
||||
|
||||
-- gates 12N, 14L
|
||||
sl_WHn <= sl_UDSn or sl_R_Wn;
|
||||
sl_WLn <= sl_LDSn or sl_R_Wn;
|
||||
-- sl_BR_Wn <= sl_R_Wn;
|
||||
sl_BW_Rn <= not sl_R_Wn;
|
||||
sl_BAS <= not sl_ASn;
|
||||
|
||||
-- VRDTACK signal generation
|
||||
p_12Ja : process
|
||||
begin
|
||||
wait until rising_edge(I_XCKR);
|
||||
sl_VCPU_last <= sl_VCPU;
|
||||
sl_VRAMn_last <= sl_VRAMn;
|
||||
if sl_BAS = '0' then
|
||||
sl_VRDTACK <= '0';
|
||||
elsif sl_VCPU_last = '0' and sl_VCPU = '1' then
|
||||
sl_VRDTACK <= not sl_VRAMn_last;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 11J gate
|
||||
sl_VPA <= not (sl_BAS and slv_FC(2) and slv_FC(1) and slv_FC(0) );
|
||||
|
||||
-- 11S gate
|
||||
sl_DTACKn <= not (sl_VRDTACK or sl_RCO);
|
||||
|
||||
-- interrupt priority
|
||||
slv_IPL(2) <= I_VBKINTn and sl_SNDINTn; -- the open collectors make an AND gate
|
||||
slv_IPL(1) <= sl_SNDINTn;
|
||||
slv_IPL(0) <= '1';
|
||||
|
||||
sl_RCO <= ctr_11N(3) and ctr_11N(2) and ctr_11N(1) and ctr_11N(0) and sl_VPA;
|
||||
|
||||
-- busk ACK delay
|
||||
p_11N : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
-- clear
|
||||
if sl_BAS = '0' or sl_VRAMn = '0' then
|
||||
ctr_11N <= (others=>'0');
|
||||
-- load
|
||||
elsif ctr_11N(3) = '0' then
|
||||
ctr_11N <= '1' & '1' & sl_EEP_CEn & '1';
|
||||
-- count
|
||||
elsif sl_VPA = '1' and sl_DTACKn = '1' then
|
||||
ctr_11N <= ctr_11N + 1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 13L 2:4 decoder
|
||||
sl_13L_Y3 <= sl_ASn or ( not slv_cpu_ad(23) ) or ( not slv_cpu_ad(20) );
|
||||
sl_13L_Y2 <= sl_ASn or ( not slv_cpu_ad(23) ) or ( slv_cpu_ad(20) );
|
||||
-- sl_13L_Y1 <= sl_ASn or ( slv_cpu_ad(23) ) or ( not slv_cpu_ad(20) ); -- unused
|
||||
sl_13L_Y0 <= sl_ASn or ( slv_cpu_ad(23) ) or ( slv_cpu_ad(20) );
|
||||
|
||||
sl_VBUSn <= sl_13L_Y3;
|
||||
sl_MBUSn <= sl_13L_Y2;
|
||||
sl_ROM <= sl_13L_Y0 or sl_BW_Rn;
|
||||
|
||||
-- 8T 2:4 decoder, gate 7X
|
||||
sl_8T_Y3 <= sl_VBUSn or ( not slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) );
|
||||
-- sl_8T_Y2 <= sl_VBUSn or ( not slv_cpu_ad(17) ) or ( slv_cpu_ad(16) ); -- unused
|
||||
sl_8T_Y1 <= sl_VBUSn or ( slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) );
|
||||
sl_8T_Y0 <= sl_VBUSn or ( slv_cpu_ad(17) ) or ( slv_cpu_ad(16) );
|
||||
|
||||
sl_HSCRLDn <= sl_8T_Y3 or sl_WLn;
|
||||
sl_CRAMn <= sl_8T_Y1;
|
||||
sl_VRAMn <= sl_8T_Y0;
|
||||
|
||||
-- 13M 2:4 decoder
|
||||
sl_13M_Y3 <= sl_MBUSn or ( not slv_cpu_ad(13) ) or ( not slv_cpu_ad(12) );
|
||||
sl_13M_Y2 <= sl_MBUSn or ( not slv_cpu_ad(13) ) or ( slv_cpu_ad(12) );
|
||||
sl_13M_Y1 <= sl_MBUSn or ( slv_cpu_ad(13) ) or ( not slv_cpu_ad(12) );
|
||||
sl_13M_Y0 <= sl_MBUSn or ( slv_cpu_ad(13) ) or ( slv_cpu_ad(12) );
|
||||
|
||||
sl_EEP_CEn <= sl_13M_Y2;
|
||||
slv_RAMn(1) <= sl_13M_Y1;
|
||||
slv_RAMn(0) <= sl_13M_Y0;
|
||||
|
||||
-- Xilinx BRAMS positive logic
|
||||
slv_RAM(1) <= not slv_RAMn(1);
|
||||
slv_RAM(0) <= not slv_RAMn(0);
|
||||
|
||||
-- 14K 3:8 decoder
|
||||
sl_14K_Y7 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( not slv_cpu_ad( 6) ) or ( not slv_cpu_ad( 5) ) or ( not slv_cpu_ad( 4) );
|
||||
-- sl_14K_Y6 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( not slv_cpu_ad( 6) ) or ( not slv_cpu_ad( 5) ) or ( slv_cpu_ad( 4) ); -- unused
|
||||
sl_14K_Y5 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( not slv_cpu_ad( 6) ) or ( slv_cpu_ad( 5) ) or ( not slv_cpu_ad( 4) );
|
||||
sl_14K_Y4 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( not slv_cpu_ad( 6) ) or ( slv_cpu_ad( 5) ) or ( slv_cpu_ad( 4) );
|
||||
-- sl_14K_Y3 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( slv_cpu_ad( 6) ) or ( not slv_cpu_ad( 5) ) or ( not slv_cpu_ad( 4) ); -- unused
|
||||
sl_14K_Y2 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( slv_cpu_ad( 6) ) or ( not slv_cpu_ad( 5) ) or ( slv_cpu_ad( 4) );
|
||||
-- sl_14K_Y1 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( slv_cpu_ad( 6) ) or ( slv_cpu_ad( 5) ) or ( not slv_cpu_ad( 4) ); -- unused
|
||||
sl_14K_Y0 <= sl_13M_Y3 or sl_WLn or (not slv_cpu_ad(8)) or ( slv_cpu_ad( 6) ) or ( slv_cpu_ad( 5) ) or ( slv_cpu_ad( 4) );
|
||||
|
||||
sl_SNDWRn <= sl_14K_Y7;
|
||||
sl_UNLOCKn <= sl_14K_Y5;
|
||||
sl_VBKACKn <= sl_14K_Y4;
|
||||
sl_LATCHn <= sl_14K_Y2;
|
||||
sl_WDOGn <= sl_14K_Y0;
|
||||
|
||||
-- 14D 3:8 decoder
|
||||
sl_14D_Y7 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( not slv_cpu_ad( 3) ) or ( not slv_cpu_ad( 2) ) or ( not slv_cpu_ad( 1) );
|
||||
-- sl_14D_Y6 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( not slv_cpu_ad( 3) ) or ( not slv_cpu_ad( 2) ) or ( slv_cpu_ad( 1) ); -- unused
|
||||
-- sl_14D_Y5 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( not slv_cpu_ad( 3) ) or ( slv_cpu_ad( 2) ) or ( not slv_cpu_ad( 1) ); -- unused
|
||||
sl_14D_Y4 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( not slv_cpu_ad( 3) ) or ( slv_cpu_ad( 2) ) or ( slv_cpu_ad( 1) );
|
||||
sl_14D_Y3 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( slv_cpu_ad( 3) ) or ( not slv_cpu_ad( 2) ) or ( not slv_cpu_ad( 1) );
|
||||
sl_14D_Y2 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( slv_cpu_ad( 3) ) or ( not slv_cpu_ad( 2) ) or ( slv_cpu_ad( 1) );
|
||||
sl_14D_Y1 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( slv_cpu_ad( 3) ) or ( slv_cpu_ad( 2) ) or ( not slv_cpu_ad( 1) );
|
||||
sl_14D_Y0 <= sl_13M_Y3 or (not sl_R_Wn) or slv_cpu_ad(8) or ( slv_cpu_ad( 3) ) or ( slv_cpu_ad( 2) ) or ( slv_cpu_ad( 1) );
|
||||
|
||||
sl_SNDRDn <= sl_14D_Y7;
|
||||
sl_INPUTn <= sl_14D_Y4;
|
||||
sl_PL4n <= sl_14D_Y3;
|
||||
sl_PL3n <= sl_14D_Y2;
|
||||
sl_PL2n <= sl_14D_Y1;
|
||||
sl_PL1n <= sl_14D_Y0;
|
||||
|
||||
-- 10D 3:8 decoder
|
||||
-- sl_10D_Y7 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( not slv_cpu_ad(18) ) or ( not slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) );
|
||||
-- sl_10D_Y6 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( not slv_cpu_ad(18) ) or ( not slv_cpu_ad(17) ) or ( slv_cpu_ad(16) );
|
||||
-- sl_10D_Y5 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( not slv_cpu_ad(18) ) or ( slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) ); -- unused
|
||||
sl_10D_Y4 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( not slv_cpu_ad(18) ) or ( slv_cpu_ad(17) ) or ( slv_cpu_ad(16) );
|
||||
sl_10D_Y3 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( slv_cpu_ad(18) ) or ( not slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) );
|
||||
-- sl_10D_Y2 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( slv_cpu_ad(18) ) or ( not slv_cpu_ad(17) ) or ( slv_cpu_ad(16) ); -- unused
|
||||
-- sl_10D_Y1 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( slv_cpu_ad(18) ) or ( slv_cpu_ad(17) ) or ( not slv_cpu_ad(16) ); -- unused
|
||||
sl_10D_Y0 <= slv_cpu_ad(23) or slv_cpu_ad(22) or ( slv_cpu_ad(18) ) or ( slv_cpu_ad(17) ) or ( slv_cpu_ad(16) );
|
||||
|
||||
-- slv_ROMEN(4)<= sl_10D_Y7;
|
||||
-- slv_ROMEN(3)<= sl_10D_Y6;
|
||||
-- slv_ROMEN(2)<= sl_10D_Y5;
|
||||
slv_ROMEN(1)<= sl_10D_Y4;
|
||||
sl_SLAPSTK <= sl_10D_Y3;
|
||||
slv_ROMEN(0)<= sl_10D_Y0;
|
||||
|
||||
-- Wrapper around 68010 soft core
|
||||
u_12E : entity work.TG68K
|
||||
port map (
|
||||
-- ins
|
||||
CLK => I_MCKR, -- CLK 7.1591MHz
|
||||
RST => sl_CPU_RESET, -- RESET active low
|
||||
-- HALT in sync with reset
|
||||
|
||||
-- BR tied high
|
||||
-- BGACK tied high
|
||||
-- BERR tied high
|
||||
clkena_ext => '1',
|
||||
IPL => slv_IPL, -- IPL
|
||||
DTACK => sl_DTACKn, -- DTACK active low
|
||||
VPA => sl_VPA, -- VPA active low
|
||||
DI => slv_cpu_di, -- DATA in
|
||||
|
||||
-- outs
|
||||
AS => sl_ASn, -- AS
|
||||
UDS => sl_UDSn, -- UDS
|
||||
LDS => sl_LDSn, -- LDS
|
||||
WR => sl_R_Wn, -- R/W
|
||||
-- E not connected
|
||||
-- VMA not connected
|
||||
-- BG not connected
|
||||
FC => slv_FC, -- FC2..0
|
||||
ADDR => slv_cpu_ad, -- ADDR
|
||||
DO => slv_cpu_do, -- DATA out
|
||||
|
||||
--
|
||||
cpusel => "01", -- CPU type selector 00->68000 01->68010 11->68020
|
||||
nRSTout => open -- reset out (not used);
|
||||
);
|
||||
|
||||
u_11A : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_cpu_ad(11 downto 1),
|
||||
clock => I_XCKR and not slv_RAM(0),
|
||||
data => slv_cpu_do(15 downto 8),
|
||||
wren => sl_WH,
|
||||
q => slv_11A_data
|
||||
);
|
||||
|
||||
u_11B : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_cpu_ad(11 downto 1),
|
||||
clock => I_XCKR and not slv_RAM(0),
|
||||
data => slv_cpu_do( 7 downto 0),
|
||||
wren => sl_WL,
|
||||
q => slv_11B_data
|
||||
);
|
||||
|
||||
u_12A : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_cpu_ad(11 downto 1),
|
||||
clock => I_XCKR and not slv_RAM(1),
|
||||
data => slv_cpu_do(15 downto 8),
|
||||
wren => sl_WH,
|
||||
q => slv_12A_data
|
||||
);
|
||||
|
||||
u_12B : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 11,
|
||||
width_a => 8)
|
||||
port map (
|
||||
address => slv_cpu_ad(11 downto 1),
|
||||
clock => I_XCKR and not slv_RAM(1),
|
||||
data => slv_cpu_do( 7 downto 0),
|
||||
wren => sl_WL,
|
||||
q => slv_12B_data
|
||||
);
|
||||
|
||||
|
||||
-- gate 14L, buffer 13C
|
||||
sl_ROM_H_Ln <= not slv_cpu_ad(15);
|
||||
|
||||
p_12Jb : process
|
||||
begin
|
||||
wait until rising_edge(I_XCKR);
|
||||
if I_RD68K = '0' then
|
||||
sl_68KBUF <= '0';
|
||||
elsif sl_SNDWRn_last = '0' and sl_SNDWRn = '1' then
|
||||
sl_68KBUF <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_13Na : process(I_MCKR, sl_UNLOCKn)
|
||||
begin
|
||||
if sl_UNLOCKn = '0' then
|
||||
sl_13N9 <= '1';
|
||||
elsif rising_edge(I_MCKR) then
|
||||
sl_WLn_last <= sl_WLn;
|
||||
if sl_SYSRESn = '0' then
|
||||
sl_13N9 <= '0';
|
||||
elsif sl_WLn_last = '0' and sl_WLn = '1' then
|
||||
sl_13N9 <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Sound Board data latch out
|
||||
p_13J : process
|
||||
begin
|
||||
wait until rising_edge(I_XCKR);
|
||||
sl_SNDWRn_last <= sl_SNDWRn;
|
||||
if sl_SNDWRn_last = '0' and sl_SNDWRn = '1' then
|
||||
O_SBD <= slv_cpu_do(7 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Sound Board data latch in
|
||||
p_14J : process
|
||||
begin
|
||||
wait until rising_edge(I_XCKR);
|
||||
sl_WR68K_last <= I_WR68K;
|
||||
if sl_WR68K_last = '0' and I_WR68K = '1' then
|
||||
slv_SBDI <= I_SBD;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_13Nb : process
|
||||
begin
|
||||
wait until rising_edge(I_XCKR);
|
||||
if sl_13Na_clr = '0' then
|
||||
sl_SNDBUF <= '0';
|
||||
elsif sl_WR68K_last = '0' and I_WR68K = '1' then
|
||||
sl_SNDBUF <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sl_13Na_clr <= sl_SNDRDn and sl_SNDRESn;
|
||||
sl_SNDINTn <= not sl_SNDBUF;
|
||||
sl_EEP_OEn <= sl_13N9 and sl_SYSRESn;
|
||||
O_SNDRESn <= sl_SNDRESn;
|
||||
|
||||
-- 14A simplified addressable latch
|
||||
p_14A : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_SYSRESn = '0' then
|
||||
sl_SNDRESn <= '0';
|
||||
O_LEDS <= (others=>'0');
|
||||
else
|
||||
if sl_LATCHn = '0' then
|
||||
case slv_cpu_ad(3 downto 1) is
|
||||
when "000" => O_LEDS(1) <= slv_cpu_do(0);
|
||||
when "001" => O_LEDS(2) <= slv_cpu_do(0);
|
||||
when "010" => O_LEDS(3) <= slv_cpu_do(0);
|
||||
when "011" => O_LEDS(4) <= slv_cpu_do(0);
|
||||
when "111" => sl_SNDRESn <= slv_cpu_do(0);
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 12C and 12D bidirectional buffers not required because we have separate in/out busses to CPU
|
||||
|
||||
----------------------------
|
||||
-- sheet 4
|
||||
----------------------------
|
||||
|
||||
p_10C : entity work.SLAPSTIC
|
||||
port map (
|
||||
I_CK => I_MCKR,
|
||||
I_ASn => sl_ASn,
|
||||
I_CSn => sl_SLAPSTK,
|
||||
I_A => slv_cpu_ad(14 downto 1),
|
||||
O_BS => slv_BS
|
||||
);
|
||||
|
||||
p_EEP_14A : entity work.EEP_14A
|
||||
port map (
|
||||
CLK => I_XCKR,
|
||||
WEn => sl_WLn,
|
||||
CEn => sl_EEP_CEn,
|
||||
OEn => sl_EEP_OEn,
|
||||
AD => slv_cpu_ad( 9 downto 1),
|
||||
DI => slv_cpu_do( 7 downto 0),
|
||||
DO => slv_EEP_14A
|
||||
);
|
||||
|
||||
-- address bus and enable for externally located program ROMs 7A, 7B, 9A, 9B, 10A, 10B
|
||||
-- top 4 address bits map each ROM into external memory space
|
||||
O_MP_EN <=
|
||||
not (sl_ASn or sl_ROM);
|
||||
O_MP_ADDR <=
|
||||
x"4" & sl_ROM_H_Ln & slv_cpu_ad(14 downto 1) when sl_ROM='0' and slv_ROMEN(1)='0' else -- /ROM1 7A/B
|
||||
x"5" & sl_ROM_H_Ln & slv_cpu_ad(14 downto 1) when sl_ROM='0' and slv_ROMEN(0)='0' else -- /ROM0 9A/B
|
||||
x"6" & '0' & slv_BS( 1 downto 0) & slv_cpu_ad(12 downto 1) when sl_ROM='0' and sl_SLAPSTK ='0' else -- SLAP 10A/B
|
||||
(others=>'0');
|
||||
|
||||
----------------------------
|
||||
-- sheet 7
|
||||
----------------------------
|
||||
-- buffer 14F
|
||||
slv_14F <= '0' & I_VBLANKn & sl_68KBUF & sl_SNDBUF & I_SELFTESTn & "000";
|
||||
|
||||
-- CPU data bus input
|
||||
-- ROM=0 SLAPSTK=0 x16 data from 10A, 10B ROMs
|
||||
-- ROM=0 /ROM0=0 x16 data from 9A, 9B ROMs
|
||||
-- ROM=0 /ROM1=0 x16 data from 7A, 7B ROMs
|
||||
-- ROM=0 /ROM2=0 x16 data from 6A, 6B ROMs
|
||||
-- ROM=0 /ROM3=0 x16 data from 5A, 5B ROMs
|
||||
-- ROM=0 /ROM4=0 x16 data from 3A, 3B ROMs
|
||||
-- MBUS=0 R/W=1 RAM0=0 x16 data from 11A, 11B RAMs
|
||||
-- MBUS=0 R/W=1 RAM1=0 x16 data from 12A, 12B RAMs
|
||||
-- VBUS=0 R/W=1 x16 data from 9E, 10E VBD bus
|
||||
|
||||
-- MBUS=0 EEPROM=0 /WL=1 x8 data from 13/14A EEPROM
|
||||
-- MBUS=0 /SNDRD=0 x8 data from 14J sound latch
|
||||
-- MBUS=0 R/W=1 /PL1=0 x8 data from 14AB
|
||||
-- MBUS=0 R/W=1 /PL2=0 x8 data from 14B
|
||||
-- MBUS=0 R/W=1 /PL3=0 x8 data from 14C
|
||||
-- MBUS=0 R/W=1 /PL4=0 x8 data from 14E
|
||||
-- MBUS=0 R/W=1 /INPUT=0 x8 data from 14F
|
||||
|
||||
-- CPU input data bus mux
|
||||
slv_cpu_di <=
|
||||
I_MP_DATA when sl_ROM='0' else -- ROMs 10A/B, 9A/B, 7A/B
|
||||
slv_11A_data & slv_11B_data when sl_R_Wn='1' and slv_RAM(0)='1' else -- RAMs 11A/B
|
||||
slv_12A_data & slv_12B_data when sl_R_Wn='1' and slv_RAM(1)='1' else -- RAMs 12A/B
|
||||
I_DATA when sl_R_Wn='1' and sl_VBUSn ='0' else -- 9E, 10E VID BUS
|
||||
x"00" & slv_EEP_14A when sl_R_Wn='1' and sl_EEP_CEn='0' and sl_EEP_OEn='0' else -- EEPROM
|
||||
x"00" & slv_SBDI when sl_SNDRDn ='0' else -- 14J sound latch
|
||||
x"00" & I_P1 when sl_PL1n ='0' else -- 14AB
|
||||
x"00" & I_P2 when sl_PL2n ='0' else -- 14B
|
||||
x"00" & I_P3 when sl_PL3n ='0' else -- 14C
|
||||
x"00" & I_P4 when sl_PL4n ='0' else -- 14E
|
||||
x"00" & slv_14F when sl_INPUTn ='0' else -- 14F
|
||||
(others=>'0');
|
||||
end RTL;
|
||||
87
Arcade_MiST/Atari Gauntlet Hardware/rtl/MOHLB.vhd
Normal file
87
Arcade_MiST/Atari Gauntlet Hardware/rtl/MOHLB.vhd
Normal file
@@ -0,0 +1,87 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- Motion Object Horizontal Line Buffer
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity MOHLB is
|
||||
port(
|
||||
I_MCKR : in std_logic;
|
||||
I_LMPDn : in std_logic;
|
||||
I_LDABn : in std_logic;
|
||||
I_BUFCLRn : in std_logic;
|
||||
|
||||
I_HPOS : in std_logic_vector(8 downto 0);
|
||||
I_MOSR : in std_logic_vector(7 downto 0);
|
||||
|
||||
O_MPX : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end MOHLB;
|
||||
|
||||
architecture RTL of MOHLB is
|
||||
signal
|
||||
sl_FLBAn,
|
||||
sl_FLBBn,
|
||||
sl_2_3X8
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_MPXA,
|
||||
slv_MPXB
|
||||
: std_logic_vector( 7 downto 0) := (others=>'1');
|
||||
begin
|
||||
----------------------------------------
|
||||
-- sheet 13 Motion Object Line Buffer --
|
||||
----------------------------------------
|
||||
|
||||
-- 5S latch
|
||||
p_5S : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
sl_FLBBn <= (not sl_FLBBn) xor I_BUFCLRn;
|
||||
end process;
|
||||
|
||||
sl_FLBAn <= not sl_FLBBn;
|
||||
|
||||
-- gates 2/3X
|
||||
sl_2_3X8 <= ( not I_LMPDn ) or ( I_MOSR(3) and I_MOSR(2) and I_MOSR(1) and I_MOSR(0) );
|
||||
|
||||
-- Line Buffer A
|
||||
u_LBA : entity work.LINEBUF
|
||||
port map (
|
||||
I_MCKR => I_MCKR,
|
||||
I_BUFCLRn => I_BUFCLRn,
|
||||
I_LDn => I_LDABn,
|
||||
I_FLBn => sl_FLBAn,
|
||||
I_CSn => sl_2_3X8,
|
||||
I_HPOS => I_HPOS,
|
||||
I_MOSR => I_MOSR,
|
||||
O_MPX => slv_MPXA
|
||||
);
|
||||
|
||||
-- Line Buffer B
|
||||
u_LBB : entity work.LINEBUF
|
||||
port map (
|
||||
I_MCKR => I_MCKR,
|
||||
I_BUFCLRn => I_BUFCLRn,
|
||||
I_LDn => I_LDABn,
|
||||
I_FLBn => sl_FLBBn,
|
||||
I_CSn => sl_2_3X8,
|
||||
I_HPOS => I_HPOS,
|
||||
I_MOSR => I_MOSR,
|
||||
O_MPX => slv_MPXB
|
||||
);
|
||||
|
||||
-- MPX bus mux
|
||||
O_MPX <= slv_MPXA when sl_FLBBn = '0' else slv_MPXB;
|
||||
end RTL;
|
||||
123
Arcade_MiST/Atari Gauntlet Hardware/rtl/PFHS.vhd
Normal file
123
Arcade_MiST/Atari Gauntlet Hardware/rtl/PFHS.vhd
Normal file
@@ -0,0 +1,123 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- Play Field Horizontal Scroll (Atari custom chip 137419-104)
|
||||
-- This PFHS was derived from System I SP-277 schematic
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity PFHS is
|
||||
port(
|
||||
I_CK : in std_logic; -- MCKR
|
||||
I_ST : in std_logic; -- PFHST
|
||||
I_4H : in std_logic; -- 4H
|
||||
I_H03 : in std_logic; -- H03
|
||||
I_HS : in std_logic; -- HSCRLD
|
||||
I_SPC : in std_logic; -- PFSPC
|
||||
I_D : in std_logic_vector(8 downto 0); -- VBD
|
||||
I_PS : in std_logic_vector(7 downto 0); -- PFSR
|
||||
|
||||
O_PFM : out std_logic; -- PFSC/MO
|
||||
O_PFH : out std_logic_vector(5 downto 0); -- PF8H..PH256H
|
||||
O_XP : out std_logic_vector(7 downto 0) -- PFX
|
||||
);
|
||||
end PFHS;
|
||||
|
||||
architecture RTL of PFHS is
|
||||
type RAM_ARRAY is array (0 to 7) of std_logic_vector(7 downto 0);
|
||||
signal
|
||||
sl_4H_last,
|
||||
sl_HS_last,
|
||||
sl_SPC_last
|
||||
: std_logic := '1';
|
||||
signal
|
||||
RAM_4M_5M_addr
|
||||
: std_logic_vector(2 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_8E_9B
|
||||
: std_logic_vector(5 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_4D
|
||||
: std_logic_vector(7 downto 0) := (others=>'1');
|
||||
signal
|
||||
slv_10F,
|
||||
slv_11E
|
||||
: std_logic_vector(8 downto 0) := (others=>'1');
|
||||
begin
|
||||
O_PFH <= slv_8E_9B;
|
||||
O_XP <= slv_4D;
|
||||
|
||||
-- 10F and 1B latches
|
||||
p_10F_1B : process
|
||||
begin
|
||||
-- until rising edge I_HS in schema
|
||||
wait until rising_edge(I_CK);
|
||||
if (I_HS = '0') then
|
||||
slv_10F <= I_D;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 11E latch
|
||||
p_11E : process
|
||||
begin
|
||||
-- until rising edge I_SPC in schema
|
||||
wait until rising_edge(I_CK);
|
||||
if (I_SPC = '0') then
|
||||
slv_11E <= I_D;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 12E 8:1 mux
|
||||
O_PFM <= slv_11E(to_integer(unsigned(slv_4D(2 downto 0))));
|
||||
|
||||
-- two 74LS189 16x4 bit RAMs, arranged as one 16x8 RAM
|
||||
-- but only 3 address lines used, so really one 8x8 RAM
|
||||
-- IMPORTANT: data out is the COMPLEMENT of data in!!!
|
||||
p_4M_5M : process
|
||||
variable RAM : RAM_ARRAY;
|
||||
attribute ram_style : string;
|
||||
attribute ram_style of RAM : variable is "distributed";
|
||||
begin
|
||||
wait until falling_edge(I_CK);
|
||||
slv_4D <= RAM(to_integer(unsigned(RAM_4M_5M_addr))); -- 4D latch
|
||||
RAM(to_integer(unsigned(RAM_4M_5M_addr))) := not I_PS;
|
||||
end process;
|
||||
|
||||
-- 6D counter
|
||||
p_6D : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
if I_ST = '0' or RAM_4M_5M_addr = "111" then
|
||||
RAM_4M_5M_addr <= slv_10F(2 downto 0);
|
||||
else
|
||||
RAM_4M_5M_addr <= RAM_4M_5M_addr + 1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 8E, 9B counters
|
||||
p_8E_9B : process
|
||||
begin
|
||||
-- until rising edge I_4H in schema, we use H03 to detect rising edge
|
||||
wait until rising_edge(I_CK);
|
||||
if I_H03 = '1' and I_4H = '0' then
|
||||
if I_ST = '0' then
|
||||
slv_8E_9B <= slv_10F(8 downto 3);
|
||||
else
|
||||
slv_8E_9B <= slv_8E_9B + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end RTL;
|
||||
560
Arcade_MiST/Atari Gauntlet Hardware/rtl/POKEY.vhd
Normal file
560
Arcade_MiST/Atari Gauntlet Hardware/rtl/POKEY.vhd
Normal file
@@ -0,0 +1,560 @@
|
||||
--
|
||||
-- Copyright (c) MikeJ - May 2004
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- You are responsible for any legal issues arising from your use of this code.
|
||||
--
|
||||
-- The latest version of this file can be found at: www.fpgaarcade.com
|
||||
--
|
||||
-- Email support@fpgaarcade.com
|
||||
--
|
||||
-- Revision list
|
||||
--
|
||||
-- version 002 return 00 on allpot when fast scan completed to fix self test
|
||||
-- version 001 initial release (this version should be considered Beta
|
||||
-- it seems to make all the right sort of sounds however ... )
|
||||
--
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity POKEY is
|
||||
port (
|
||||
ADDR : in std_logic_vector(3 downto 0);
|
||||
DIN : in std_logic_vector(7 downto 0);
|
||||
DOUT : out std_logic_vector(7 downto 0);
|
||||
DOUT_OE_L : out std_logic;
|
||||
RW_L : in std_logic;
|
||||
CS : in std_logic; -- used as enable
|
||||
CS_L : in std_logic;
|
||||
--
|
||||
AUDIO_OUT : out signed(7 downto 0);
|
||||
--
|
||||
PIN : in std_logic_vector(7 downto 0);
|
||||
ENA : in std_logic;
|
||||
CLK : in std_logic -- note 6 Mhz
|
||||
);
|
||||
end;
|
||||
|
||||
architecture RTL of POKEY is
|
||||
type array_8x8 is array (0 to 7) of std_logic_vector(7 downto 0);
|
||||
type array_4x8 is array (1 to 4) of std_logic_vector(7 downto 0);
|
||||
type array_4x4 is array (1 to 4) of std_logic_vector(3 downto 0);
|
||||
type array_4x9 is array (1 to 4) of std_logic_vector(8 downto 0);
|
||||
type array_2x17 is array (1 to 2) of std_logic_vector(16 downto 0);
|
||||
type bool_4 is array (1 to 4) of boolean;
|
||||
|
||||
signal we : std_logic :='0';
|
||||
signal oe : std_logic :='0';
|
||||
--
|
||||
signal ena_64k_15k : std_logic :='0';
|
||||
signal cnt_64k : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal ena_64k : std_logic :='0';
|
||||
signal cnt_15k : std_logic_vector(6 downto 0) := (others => '0');
|
||||
signal ena_15k : std_logic :='0';
|
||||
--
|
||||
signal poly4 : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal poly5 : std_logic_vector(4 downto 0) := (others => '0');
|
||||
signal poly9 : std_logic_vector(8 downto 0) := (others => '0');
|
||||
signal poly17 : std_logic_vector(16 downto 0) := (others => '0');
|
||||
signal poly_17_9 : std_logic :='0';
|
||||
|
||||
-- registers
|
||||
signal audf : array_4x8 := (others => (others => '0'));
|
||||
signal audc : array_4x8 := (others => (others => '0'));
|
||||
signal audctl : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal stimer : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal skres : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal potgo : std_logic :='0';
|
||||
signal serout : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal irqen : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal skctls : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal reset : std_logic :='0';
|
||||
--
|
||||
signal kbcode : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal random : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal serin : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal irqst : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal skstat : std_logic_vector(7 downto 0) := (others => '0');
|
||||
--
|
||||
signal pot_fin : std_logic :='0';
|
||||
signal pot_cnt : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal pot_val : array_8x8 := (others => (others => '0'));
|
||||
signal pin_reg : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal pin_reg_gated : std_logic_vector(7 downto 0) := (others => '0');
|
||||
--
|
||||
signal chan_ena : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal tone_gen_div : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal tone_gen_cnt : array_4x8 := (others => (others => '0'));
|
||||
signal tone_gen_div_mux : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal tone_gen_zero : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal tone_gen_zero_t : array_4x8 := (others => (others => '0'));
|
||||
signal chan_done_load : std_logic_vector(4 downto 1) := (others => '0');
|
||||
--
|
||||
signal poly_sel : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal poly_sel_hp : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal poly_sel_hp_t1 : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal poly_sel_hp_reg : std_logic_vector(4 downto 1) := (others => '0');
|
||||
signal tone_gen_final : std_logic_vector(4 downto 1) := (others => '0');
|
||||
begin
|
||||
|
||||
p_we : process(RW_L, CS_L, CS, ENA)
|
||||
begin
|
||||
we <= (not CS_L) and CS and (not RW_L) and ENA;
|
||||
end process;
|
||||
|
||||
p_oe : process(RW_L, CS_L, CS)
|
||||
begin
|
||||
oe <= (not CS_L) and CS and RW_L;
|
||||
end process;
|
||||
DOUT_OE_L <= not oe;
|
||||
|
||||
p_ipreg : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
pin_reg <= PIN;
|
||||
end process;
|
||||
|
||||
p_dividers : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
ena_64k <= '0';
|
||||
if cnt_64k = "00000" then
|
||||
cnt_64k <= "11011"; -- 28 - 1
|
||||
ena_64k <= '1';
|
||||
else
|
||||
cnt_64k <= cnt_64k - "1";
|
||||
end if;
|
||||
|
||||
ena_15k <= '0';
|
||||
if cnt_15k = "0000000" then
|
||||
cnt_15k <= "1110001"; -- 114 - 1
|
||||
ena_15k <= '1';
|
||||
else
|
||||
cnt_15k <= cnt_15k - "1";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_ena_64k_15k : process(ena_64k, ena_15k, audctl)
|
||||
begin
|
||||
if (audctl(0) = '1') then
|
||||
ena_64k_15k <= ena_15k;
|
||||
else
|
||||
ena_64k_15k <= ena_64k;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_poly : process
|
||||
variable poly9_zero : std_logic;
|
||||
variable poly17_zero : std_logic;
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
poly4 <= poly4(2 downto 0) & not (poly4(3) xor poly4(2));
|
||||
poly5 <= poly5(3 downto 0) & not (poly5(4) xor poly4(2)); -- used inverted
|
||||
|
||||
-- not correct
|
||||
poly9_zero := '0';
|
||||
if (poly9 = "000000000") then poly9_zero := '1'; end if;
|
||||
poly9 <= poly9(7 downto 0) & (poly9(8) xor poly9(3) xor poly9_zero);
|
||||
|
||||
poly17_zero := '0';
|
||||
if (poly17 = "00000000000000000") then poly17_zero := '1'; end if;
|
||||
poly17 <= poly17(15 downto 0) & (poly17(16) xor poly17(2) xor poly17_zero);
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_random_mux : process(audctl, poly9, poly17)
|
||||
begin
|
||||
-- bit unnecessary this ....
|
||||
for i in 0 to 7 loop
|
||||
if (audctl(7) = '1') then -- 9 bit poly
|
||||
random(i) <= poly9(8-i);
|
||||
else
|
||||
random(i) <= poly17(16-i);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
if (audctl(7) = '1') then
|
||||
poly_17_9 <= poly9(8);
|
||||
else
|
||||
poly_17_9 <= poly17(16);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_wdata : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
potgo <= '0';
|
||||
|
||||
--if (reset = '1') then
|
||||
-- no idea what the reset state is
|
||||
--audf <= (others => (others => '0'));
|
||||
--audc <= (others => (others => '0'));
|
||||
--audctl <= x"00";
|
||||
--else
|
||||
if (we = '1') then
|
||||
case ADDR is
|
||||
when x"0" => audf(1) <= DIN;
|
||||
when x"1" => audc(1) <= DIN;
|
||||
when x"2" => audf(2) <= DIN;
|
||||
when x"3" => audc(2) <= DIN;
|
||||
when x"4" => audf(3) <= DIN;
|
||||
when x"5" => audc(3) <= DIN;
|
||||
when x"6" => audf(4) <= DIN;
|
||||
when x"7" => audc(4) <= DIN;
|
||||
when x"8" => audctl <= DIN;
|
||||
when x"9" => stimer <= DIN;
|
||||
when x"A" => skres <= DIN;
|
||||
when x"B" => potgo <= '1';
|
||||
--when x"C" =>
|
||||
when x"D" => serout <= DIN;
|
||||
when x"E" => irqen <= DIN;
|
||||
when x"F" => skctls <= DIN;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
--end if;
|
||||
end process;
|
||||
|
||||
p_reset : process(skctls)
|
||||
begin
|
||||
-- chip in reset if bits 1..0 of skctls are both zero
|
||||
reset <= '0';
|
||||
if (skctls(1 downto 0) = "00") then
|
||||
reset <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_rdata : process(oe, ADDR, pot_val, pin_reg_gated, kbcode, random, serin, irqst, skstat)
|
||||
begin
|
||||
DOUT <= x"00";
|
||||
if (oe = '1') then -- keep things quiet
|
||||
case ADDR IS
|
||||
when x"0" => DOUT <= pot_val(0); -- pot 0
|
||||
when x"1" => DOUT <= pot_val(1); -- pot 1
|
||||
when x"2" => DOUT <= pot_val(2); -- pot 2
|
||||
when x"3" => DOUT <= pot_val(3); -- pot 3
|
||||
when x"4" => DOUT <= pot_val(4); -- pot 4
|
||||
when x"5" => DOUT <= pot_val(5); -- pot 5
|
||||
when x"6" => DOUT <= pot_val(6); -- pot 6
|
||||
when x"7" => DOUT <= pot_val(7); -- pot 7
|
||||
when x"8" => DOUT <= pin_reg_gated;-- allpot
|
||||
when x"9" => DOUT <= kbcode;
|
||||
when x"A" => DOUT <= random;
|
||||
when x"B" => DOUT <= x"FF";
|
||||
when x"C" => DOUT <= x"FF";
|
||||
when x"D" => DOUT <= serin;
|
||||
when x"E" => DOUT <= irqst;
|
||||
when x"F" => DOUT <= skstat;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- POT ANALOGUE IN UNTESTED !!
|
||||
p_pot_cnt : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (potgo = '1') then
|
||||
pot_cnt <= x"00";
|
||||
elsif ((ena_15k = '1') or (skctls(2) = '1')) and (ENA = '1') then -- fast scan mode
|
||||
pot_cnt <= pot_cnt + "1";
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_pot_comp : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (reset = '1') then
|
||||
pot_fin <= '1';
|
||||
else
|
||||
if (potgo = '1') then
|
||||
pot_fin <= '0';
|
||||
elsif (pot_cnt = x"E4") then -- 228
|
||||
pot_fin <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_pot_val : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
for i in 0 to 7 loop
|
||||
if (pot_fin = '0') and (pin_reg(i) = '0') then
|
||||
-- continue latching counter value until input reaches ViH threshold
|
||||
pot_val(i) <= pot_cnt;
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
-- dump transistors
|
||||
--PIN <= x"00" when (pot_fin = '1') else (others => 'Z');
|
||||
p_in_gate : process(pin_reg, reset) -- dump transistor fakeup
|
||||
begin
|
||||
pin_reg_gated <= pin_reg;
|
||||
-- I think the datasheet lies about dump transistors being disabled
|
||||
-- in fast scan mode, as the self test fails ....
|
||||
if (reset = '1') or (pot_fin = '1') then --and (skctls(2) = '0'))
|
||||
pin_reg_gated <= x"00";
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_tone_cnt_ena : process(audctl, ena_64k_15k, tone_gen_div)
|
||||
variable chan_ena1, chan_ena3 : std_ulogic;
|
||||
begin
|
||||
|
||||
if (audctl(6) = '1') then
|
||||
chan_ena1 := '1'; -- 1.5 MHz,
|
||||
else
|
||||
chan_ena1 := ena_64k_15k;
|
||||
end if;
|
||||
chan_ena(1) <= chan_ena1;
|
||||
|
||||
if (audctl(4) = '1') then -- chan 1/2 joined
|
||||
chan_ena(2) <= chan_ena1;
|
||||
else
|
||||
chan_ena(2) <= ena_64k_15k;
|
||||
end if;
|
||||
|
||||
if (audctl(5) = '1') then
|
||||
chan_ena3 := '1'; -- 1.5 MHz,
|
||||
else
|
||||
chan_ena3 := ena_64k_15k; -- 64 KHz
|
||||
end if;
|
||||
chan_ena(3) <= chan_ena3;
|
||||
|
||||
if (audctl(3) = '1') then -- chan 3/4 joined
|
||||
chan_ena(4) <= chan_ena3;
|
||||
else
|
||||
chan_ena(4) <= ena_64k_15k; -- 64 KHz
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_tone_generator_zero : process(tone_gen_cnt, chan_ena)
|
||||
begin
|
||||
for i in 1 to 4 loop
|
||||
if (tone_gen_cnt(i) = "00000000") and (chan_ena(i) = '1') then
|
||||
tone_gen_zero(i) <= '1';
|
||||
else
|
||||
tone_gen_zero(i) <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
p_tone_generators : process
|
||||
variable chan_load : std_logic_vector(4 downto 1);
|
||||
variable chan_dec : std_logic_vector(4 downto 1);
|
||||
begin
|
||||
-- quite tricky this .. but I think it does the correct stuff
|
||||
-- bet this is not how is was done originally !
|
||||
--
|
||||
-- nasty frig to easily get exact chip behaviour in high speed mode
|
||||
-- fout = fin / 2(audf + n) when n=4 or 7 in 16 bit mode
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
tone_gen_div <= "0000";
|
||||
|
||||
if (audctl(4) = '1') then -- chan 1/2 joined
|
||||
chan_load(1) := '0';
|
||||
chan_load(2) := '0';
|
||||
if (tone_gen_zero_t(1)(5) = '1') and (tone_gen_zero_t(2)(5) = '1') and (chan_done_load(1) = '0') then
|
||||
chan_load(1) := '1';
|
||||
chan_load(2) := '1';
|
||||
end if;
|
||||
chan_dec(1) := '1';
|
||||
chan_dec(2) := tone_gen_zero(1);
|
||||
else
|
||||
chan_load(1) := tone_gen_zero_t(1)(2) and not chan_done_load(1);
|
||||
chan_load(2) := tone_gen_zero_t(2)(2) and not chan_done_load(2);
|
||||
|
||||
chan_dec(1) := '1';
|
||||
chan_dec(2) := '1';
|
||||
end if;
|
||||
|
||||
if (audctl(3) = '1') then -- chan 1/2 joined
|
||||
chan_load(3) := '0';
|
||||
chan_load(4) := '0';
|
||||
if (tone_gen_zero_t(3)(5) = '1') and (tone_gen_zero_t(4)(5) = '1') and (chan_done_load(3) = '0') then
|
||||
chan_load(3) := '1';
|
||||
chan_load(4) := '1';
|
||||
end if;
|
||||
chan_dec(3) := '1';
|
||||
chan_dec(4) := tone_gen_zero(3);
|
||||
else
|
||||
chan_load(3) := tone_gen_zero_t(3)(2) and not chan_done_load(3);
|
||||
chan_load(4) := tone_gen_zero_t(4)(2) and not chan_done_load(4);
|
||||
|
||||
chan_dec(3) := '1';
|
||||
chan_dec(4) := '1';
|
||||
end if;
|
||||
|
||||
for i in 1 to 4 loop
|
||||
|
||||
if (chan_load(i) = '1') then
|
||||
chan_done_load(i) <= '1';
|
||||
tone_gen_div(i) <= '1';
|
||||
tone_gen_cnt(i) <= audf(i);
|
||||
elsif (chan_dec(i) = '1') and (chan_ena(i) = '1') then
|
||||
chan_done_load(i) <= '0';
|
||||
tone_gen_cnt(i) <= tone_gen_cnt(i) - "1";
|
||||
end if;
|
||||
|
||||
tone_gen_div(i) <= chan_load(i);
|
||||
tone_gen_zero_t(i)(7 downto 0) <= tone_gen_zero_t(i)(6 downto 0) & tone_gen_zero(i);
|
||||
end loop;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_tone_generator_mux : process(audctl, tone_gen_div)
|
||||
begin
|
||||
if (audctl(4) = '1') then -- chan 1/2 joined
|
||||
tone_gen_div_mux(1) <= tone_gen_div(1); -- do they both waggle
|
||||
tone_gen_div_mux(2) <= tone_gen_div(2); -- or do I mute chan 1?
|
||||
else
|
||||
tone_gen_div_mux(1) <= tone_gen_div(1);
|
||||
tone_gen_div_mux(2) <= tone_gen_div(2);
|
||||
end if;
|
||||
|
||||
if (audctl(3) = '1') then -- chan 3/4 joined
|
||||
tone_gen_div_mux(3) <= tone_gen_div(3); -- ditto
|
||||
tone_gen_div_mux(4) <= tone_gen_div(4);
|
||||
else
|
||||
tone_gen_div_mux(3) <= tone_gen_div(3);
|
||||
tone_gen_div_mux(4) <= tone_gen_div(4);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_poly_gating : process(audc, poly4, poly5, poly_17_9, tone_gen_div_mux)
|
||||
variable filter_a : std_logic_vector(4 downto 1);
|
||||
variable filter_b : std_logic_vector(4 downto 1);
|
||||
begin
|
||||
for i in 1 to 4 loop
|
||||
if (audc(i)(7) = '0') then
|
||||
filter_a(i) := poly5(4) and tone_gen_div_mux(i);-- 5 bit poly
|
||||
else
|
||||
filter_a(i) := tone_gen_div_mux(i);
|
||||
end if;
|
||||
|
||||
if (audc(i)(6) = '0') then
|
||||
filter_b(i) := poly_17_9 and filter_a(i);-- 17 bit poly
|
||||
else
|
||||
filter_b(i) := poly4(3) and filter_a(i);-- 4 bit poly
|
||||
end if;
|
||||
|
||||
if (audc(i)(5) = '0') then
|
||||
poly_sel(i) <= filter_b(i);
|
||||
else
|
||||
poly_sel(i) <= filter_a(i);
|
||||
end if;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
p_high_pass_filters : process(audctl, poly_sel, poly_sel_hp_reg)
|
||||
begin
|
||||
poly_sel_hp <= poly_sel;
|
||||
|
||||
if (audctl(2) = '1') then
|
||||
poly_sel_hp(1) <= poly_sel(1) xor poly_sel_hp_reg(1);
|
||||
end if;
|
||||
|
||||
if (audctl(1) = '1') then
|
||||
poly_sel_hp(2) <= poly_sel(2) xor poly_sel_hp_reg(2);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_audio_out : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
for i in 1 to 4 loop
|
||||
-- filter reg
|
||||
if (tone_gen_div(3) = '1') then -- tone gen 1 clocked by gen 3
|
||||
poly_sel_hp_reg(1) <= poly_sel(1);
|
||||
end if;
|
||||
|
||||
if (tone_gen_div(4) = '1') then -- tone gen 2 clocked by gen 4
|
||||
poly_sel_hp_reg(2) <= poly_sel(2);
|
||||
end if;
|
||||
|
||||
poly_sel_hp_t1 <= poly_sel_hp;
|
||||
|
||||
if (poly_sel_hp(i) = '1') and (poly_sel_hp_t1(i) = '0') then -- rising edge
|
||||
tone_gen_final(i) <= not tone_gen_final(i);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_op_mixer : process
|
||||
variable vol : array_4x4;
|
||||
variable sum12 : std_logic_vector(4 downto 0);
|
||||
variable sum34 : std_logic_vector(4 downto 0);
|
||||
variable sum : std_logic_vector(5 downto 0);
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
for i in 1 to 4 loop
|
||||
if (audc(i)(4) = '1') then -- vol only
|
||||
vol(i) := audc(i)(3 downto 0);
|
||||
else
|
||||
if (tone_gen_final(i) = '1') then
|
||||
vol(i) := audc(i)(3 downto 0);
|
||||
else
|
||||
vol(i) := "0000";
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
sum12 := ('0' & vol(1)) + ('0' & vol(2));
|
||||
sum34 := ('0' & vol(3)) + ('0' & vol(4));
|
||||
sum := ('0' & sum12) + ('0' & sum34);
|
||||
|
||||
if (reset = '1') then
|
||||
AUDIO_OUT <= (others=>'0');
|
||||
else
|
||||
if (sum(5) = '1') then
|
||||
-- clip to max
|
||||
AUDIO_OUT <= x"7F";
|
||||
else
|
||||
-- signed output
|
||||
AUDIO_OUT <= signed((sum(4 downto 0) & "000") - x"80");
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- keyboard / serial etc to do
|
||||
end architecture RTL;
|
||||
135
Arcade_MiST/Atari Gauntlet Hardware/rtl/SLAGS.vhd
Normal file
135
Arcade_MiST/Atari Gauntlet Hardware/rtl/SLAGS.vhd
Normal file
@@ -0,0 +1,135 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- Storage/Logic Array Graphics Shifter (Atari custom chip 137415-101)
|
||||
-- This SLAGS was derived from Marble Madness SP-276 schematic
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity SLAGS is
|
||||
port(
|
||||
I_PHIN : in std_logic; -- RCLOCK
|
||||
I_A : in std_logic_vector(7 downto 0);
|
||||
I_B : in std_logic_vector(7 downto 0);
|
||||
I_HLDAn : in std_logic; -- /HOLDA
|
||||
I_HLDBn : in std_logic; -- /HOLDB
|
||||
I_FLP : in std_logic; -- MGHF
|
||||
I_MO_PFn : in std_logic; -- MO/ /PF
|
||||
I_LDn : in std_logic; -- /GLD
|
||||
O_PFDA : out std_logic; -- PFSR Play Field Shift Register
|
||||
O_PFDB : out std_logic; -- PFSR Play Field Shift Register
|
||||
O_MODA : out std_logic; -- MOSR Motion Object Shift Register
|
||||
O_MODB : out std_logic -- MOSR Motion Object Shift Register
|
||||
);
|
||||
end SLAGS;
|
||||
|
||||
architecture RTL of SLAGS is
|
||||
signal
|
||||
sl_MOFDA,
|
||||
sl_MOSDA,
|
||||
sl_MOFDB,
|
||||
sl_MOSDB,
|
||||
sl_PFFDA,
|
||||
sl_PFSDA,
|
||||
sl_PFFDB,
|
||||
sl_PFSDB,
|
||||
|
||||
sl_LDMOn,
|
||||
sl_LDPFn,
|
||||
sl_MOFLP,
|
||||
sl_MO_HLDAn,
|
||||
sl_MO_HLDBn,
|
||||
sl_PFFLP,
|
||||
sl_PF_HLDAn,
|
||||
sl_PF_HLDBn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_1B_4B,
|
||||
slv_1A_5B,
|
||||
sel_MOSA,
|
||||
sel_MOSB,
|
||||
sel_PFSA,
|
||||
sel_PFSB,
|
||||
slv_2A,
|
||||
slv_2B,
|
||||
slv_3A,
|
||||
slv_3B
|
||||
: std_logic_vector(1 downto 0) := (others=>'1');
|
||||
begin
|
||||
-- gates 6B, 12A - shifter controls MO /PF
|
||||
sl_LDPFn <= I_LDn or ( I_MO_PFn);
|
||||
sl_LDMOn <= I_LDn or (not I_MO_PFn);
|
||||
|
||||
-- latch 8B
|
||||
p_8B : process
|
||||
begin
|
||||
wait until rising_edge(I_PHIN);
|
||||
if sl_LDPFn = '0' then
|
||||
sl_PFFLP <= I_FLP;
|
||||
sl_PF_HLDAn <= I_HLDAn;
|
||||
sl_PF_HLDBn <= I_HLDBn;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- latch 11A
|
||||
p_11A : process
|
||||
begin
|
||||
wait until rising_edge(I_PHIN);
|
||||
if sl_LDMOn = '0' then
|
||||
sl_MOFLP <= I_FLP;
|
||||
sl_MO_HLDAn <= I_HLDAn;
|
||||
sl_MO_HLDBn <= I_HLDBn;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- shift register select signals
|
||||
sel_MOSB(0) <= not (sl_LDMOn and not (sl_MO_HLDBn and (not sl_MOFLP)));
|
||||
sel_MOSB(1) <= not (sl_LDMOn and not (sl_MO_HLDBn and ( sl_MOFLP)));
|
||||
|
||||
sel_MOSA(0) <= not (sl_LDMOn and not (sl_MO_HLDAn and (not sl_MOFLP)));
|
||||
sel_MOSA(1) <= not (sl_LDMOn and not (sl_MO_HLDAn and ( sl_MOFLP)));
|
||||
|
||||
sel_PFSB(0) <= not (sl_LDPFn and not (sl_PF_HLDBn and (not sl_PFFLP)));
|
||||
sel_PFSB(1) <= not (sl_LDPFn and not (sl_PF_HLDBn and ( sl_PFFLP)));
|
||||
|
||||
sel_PFSA(0) <= not (sl_LDPFn and not (sl_PF_HLDAn and (not sl_PFFLP)));
|
||||
sel_PFSA(1) <= not (sl_LDPFn and not (sl_PF_HLDAn and ( sl_PFFLP)));
|
||||
|
||||
-- LS299 shifters
|
||||
u_MOSB : entity work.LS299 port map ( I_CK=>I_PHIN, I_DATA=>I_B, I_SL=>'0', I_SR=>'0', I_SEL=>sel_MOSB, O_SL=>sl_MOFDB, O_SR=>sl_MOSDB );
|
||||
u_MOSA : entity work.LS299 port map ( I_CK=>I_PHIN, I_DATA=>I_A, I_SL=>'0', I_SR=>'0', I_SEL=>sel_MOSA, O_SL=>sl_MOFDA, O_SR=>sl_MOSDA );
|
||||
u_PFSB : entity work.LS299 port map ( I_CK=>I_PHIN, I_DATA=>I_B, I_SL=>'0', I_SR=>'0', I_SEL=>sel_PFSB, O_SL=>sl_PFFDB, O_SR=>sl_PFSDB );
|
||||
u_PFSA : entity work.LS299 port map ( I_CK=>I_PHIN, I_DATA=>I_A, I_SL=>'0', I_SR=>'0', I_SEL=>sel_PFSA, O_SL=>sl_PFFDA, O_SR=>sl_PFSDA );
|
||||
|
||||
-- selectors 1A, 1B, 4B, 5B 0=A 1=B
|
||||
-- selects left or right shifter outputs based on FLP
|
||||
slv_1B_4B <= sl_PFFDB & sl_PFFDA when sl_PFFLP = '1' else sl_PFSDB & sl_PFSDA;
|
||||
slv_1A_5B <= sl_MOFDB & sl_MOFDA when sl_MOFLP = '1' else sl_MOSDB & sl_MOSDA;
|
||||
|
||||
-- latches 2A, 2B, 3A, 3B
|
||||
-- 2 clock cycle delay line
|
||||
p_2A_2B_3A_3B : process
|
||||
begin
|
||||
wait until rising_edge(I_PHIN);
|
||||
slv_3B <= slv_1B_4B;
|
||||
slv_3A <= slv_3B;
|
||||
slv_2B <= slv_1A_5B;
|
||||
slv_2A <= slv_2B;
|
||||
end process;
|
||||
|
||||
-- outputs
|
||||
O_MODB <= slv_2A(1);
|
||||
O_MODA <= slv_2A(0);
|
||||
O_PFDB <= slv_3A(1);
|
||||
O_PFDA <= slv_3A(0);
|
||||
end RTL;
|
||||
780
Arcade_MiST/Atari Gauntlet Hardware/rtl/SLAPSTIC.vhd
Normal file
780
Arcade_MiST/Atari Gauntlet Hardware/rtl/SLAPSTIC.vhd
Normal file
@@ -0,0 +1,780 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- SLAPSTIC 137412-104 GAUNTLET
|
||||
-- This SLAPSTIC was translated from MAME "slapstic.cpp" source code pretty much verbatim :)
|
||||
-- The original MAME C++ code is left in as comments
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity SLAPSTIC is
|
||||
generic (
|
||||
chip_type : integer range 100 to 118 := 104 -- see generate statements below to select correct type
|
||||
);
|
||||
port(
|
||||
I_CK : in std_logic;
|
||||
I_ASn : in std_logic;
|
||||
I_CSn : in std_logic;
|
||||
I_A : in std_logic_vector(13 downto 0);
|
||||
O_BS : out std_logic_vector( 1 downto 0)
|
||||
);
|
||||
end SLAPSTIC;
|
||||
|
||||
architecture RTL of SLAPSTIC is
|
||||
signal slv_BS : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
|
||||
type slap_sm is (DIS, ENA, ALT1, ALT2, ALT3, BIT1, BIT2, BIT3, ADD1, ADD2, ADD3);
|
||||
signal state : slap_sm;
|
||||
signal sl_ASn_last : std_logic:='0';
|
||||
signal additive : std_logic:='0';
|
||||
signal bitwise : std_logic:='0';
|
||||
|
||||
signal addr : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal ini_bank : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
signal cur_bank : std_logic_vector( 1 downto 0) := (others=>'1');
|
||||
signal alt_bank : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
signal bit_bank : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
signal bit_xor : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
signal add_bank : std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
|
||||
signal val_bank0 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bank1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bank2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bank3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
|
||||
signal mask_alt1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_alt2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_alt3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_alt4 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_alt1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_alt2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_alt3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_alt4 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
|
||||
signal altshift : natural range 0 to 3 := 0;
|
||||
|
||||
signal mask_bit1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_bit2c0 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_bit2s0 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_bit2c1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_bit2s1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_bit3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit2c0 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit2s0 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit2c1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit2s1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_bit3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
|
||||
signal mask_add1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_add2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_add3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_addp1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal mask_addp2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_add1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_add2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_add3 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_addp1 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal val_addp2 : std_logic_vector(15 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
--/* slapstic 137412-101: Empire Strikes Back/Tetris (NOT confirmed) */
|
||||
--static const struct slapstic_data slapstic101 =
|
||||
--{
|
||||
gen_101 : if chip_type = 101 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0080"; -- { 0x0080,0x0090,0x00a0,0x00b0 },/* bank select values */
|
||||
val_bank1 <= x"0090";
|
||||
val_bank2 <= x"00A0";
|
||||
val_bank3 <= x"00B0";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"FFFF"; -- { 0x007f,UNKNOWN }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"1FFF"; val_alt2 <= x"1DFF"; -- { 0x1fff,0x1dff }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"1FFC"; val_alt3 <= x"1B5C"; -- { 0x1ffc,0x1b5c }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"1FCF"; val_alt4 <= x"0080"; -- { 0x1fcf,0x0080 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"1FF0"; val_bit1 <= x"1540"; -- { 0x1ff0,0x1540 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"1FF3"; val_bit2c0 <= x"1540"; -- { 0x1ff3,0x1540 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"1FF3"; val_bit2s0 <= x"1541"; -- { 0x1ff3,0x1541 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"1FF3"; val_bit2c1 <= x"1542"; -- { 0x1ff3,0x1542 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"1FF3"; val_bit2s1 <= x"1543"; -- { 0x1ff3,0x1543 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"1FF8"; val_bit3 <= x"1550"; -- { 0x1ff8,0x1550 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-103: Marble Madness (confirmed) */
|
||||
--static const struct slapstic_data slapstic103 =
|
||||
--{
|
||||
gen_103 : if chip_type = 103 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0040"; -- { 0x0040,0x0050,0x0060,0x0070 },/* bank select values */
|
||||
val_bank1 <= x"0050";
|
||||
val_bank2 <= x"0060";
|
||||
val_bank3 <= x"0070";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"002D"; -- { 0x007f,0x002d }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3D14"; -- { 0x3fff,0x3d14 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"3D24"; -- { 0x3ffc,0x3d24 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FCF"; val_alt4 <= x"0040"; -- { 0x3fcf,0x0040 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"34C0"; -- { 0x3ff0,0x34c0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"34C0"; -- { 0x3ff3,0x34c0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"34C1"; -- { 0x3ff3,0x34c1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"34C2"; -- { 0x3ff3,0x34c2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"34C3"; -- { 0x3ff3,0x34c3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"34D0"; -- { 0x3ff8,0x34d0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-104: Gauntlet (confirmed) */
|
||||
--static const struct slapstic_data slapstic104 =
|
||||
--{
|
||||
gen_104 : if chip_type = 104 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0020"; -- { 0x0020,0x0028,0x0030,0x0038 },/* bank select values */
|
||||
val_bank1 <= x"0028";
|
||||
val_bank2 <= x"0030";
|
||||
val_bank3 <= x"0038";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0069"; -- { 0x007f,0x0069 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3735"; -- { 0x3fff,0x3735 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"3764"; -- { 0x3ffc,0x3764 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FE7"; val_alt4 <= x"0020"; -- { 0x3fe7,0x0020 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"3D90"; -- { 0x3ff0,0x3d90 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"3D90"; -- { 0x3ff3,0x3d90 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"3D91"; -- { 0x3ff3,0x3d91 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"3D92"; -- { 0x3ff3,0x3d92 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"3D93"; -- { 0x3ff3,0x3d93 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"3DA0"; -- { 0x3ff8,0x3da0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-105: Indiana Jones/Paperboy (confirmed) */
|
||||
--static const struct slapstic_data slapstic105 =
|
||||
--{
|
||||
gen_105 : if chip_type = 105 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0010"; -- { 0x0010,0x0014,0x0018,0x001c },/* bank select values */
|
||||
val_bank1 <= x"0014";
|
||||
val_bank2 <= x"0018";
|
||||
val_bank3 <= x"001C";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"003D"; -- { 0x007f,0x003d }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"0092"; -- { 0x3fff,0x0092 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"00A4"; -- { 0x3ffc,0x00a4 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF3"; val_alt4 <= x"0010"; -- { 0x3ff3,0x0010 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"35B0"; -- { 0x3ff0,0x35b0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"35B0"; -- { 0x3ff3,0x35b0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"35B1"; -- { 0x3ff3,0x35b1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"35B2"; -- { 0x3ff3,0x35b2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"35B3"; -- { 0x3ff3,0x35b3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"35C0"; -- { 0x3ff8,0x35c0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-106: Gauntlet II (confirmed) */
|
||||
--static const struct slapstic_data slapstic106 =
|
||||
--{
|
||||
gen_106 : if chip_type = 106 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0008"; -- { 0x0008,0x000a,0x000c,0x000e },/* bank select values */
|
||||
val_bank1 <= x"000A";
|
||||
val_bank2 <= x"000C";
|
||||
val_bank3 <= x"000E";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"002B"; -- { 0x007f,0x002b }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"0052"; -- { 0x3fff,0x0052 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"0064"; -- { 0x3ffc,0x0064 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF9"; val_alt4 <= x"0008"; -- { 0x3ff9,0x0008 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"3DA0"; -- { 0x3ff0,0x3da0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"3DA0"; -- { 0x3ff3,0x3da0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"3DA1"; -- { 0x3ff3,0x3da1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"3DA2"; -- { 0x3ff3,0x3da2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"3DA3"; -- { 0x3ff3,0x3da3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"3DB0"; -- { 0x3ff8,0x3db0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-107: Peter Packrat/Xybots/2p Gauntlet/720 (confirmed) */
|
||||
--static const struct slapstic_data slapstic107 =
|
||||
--{
|
||||
gen_107 : if chip_type = 107 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0018"; -- { 0x0018,0x001a,0x001c,0x001e },/* bank select values */
|
||||
val_bank1 <= x"001A";
|
||||
val_bank2 <= x"001C";
|
||||
val_bank3 <= x"001E";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"006B"; -- { 0x007f,0x006b }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3D52"; -- { 0x3fff,0x3d52 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"3D64"; -- { 0x3ffc,0x3d64 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF9"; val_alt4 <= x"0018"; -- { 0x3ff9,0x0018 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"00A0"; -- { 0x3ff0,0x00a0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"00A0"; -- { 0x3ff3,0x00a0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"00A1"; -- { 0x3ff3,0x00a1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"00A2"; -- { 0x3ff3,0x00a2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"00A3"; -- { 0x3ff3,0x00a3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"00B0"; -- { 0x3ff8,0x00b0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-108: Road Runner/Super Sprint (confirmed) */
|
||||
--static const struct slapstic_data slapstic108 =
|
||||
--{
|
||||
gen_108 : if chip_type = 108 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0028"; -- { 0x0028,0x002a,0x002c,0x002e },/* bank select values */
|
||||
val_bank1 <= x"002A";
|
||||
val_bank2 <= x"002C";
|
||||
val_bank3 <= x"002E";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"001F"; -- { 0x007f,0x001f }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3772"; -- { 0x3fff,0x3772 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"3764"; -- { 0x3ffc,0x3764 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF9"; val_alt4 <= x"0028"; -- { 0x3ff9,0x0028 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"0060"; -- { 0x3ff0,0x0060 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"0060"; -- { 0x3ff3,0x0060 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"0061"; -- { 0x3ff3,0x0061 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"0062"; -- { 0x3ff3,0x0062 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"0063"; -- { 0x3ff3,0x0063 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"0070"; -- { 0x3ff8,0x0070 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-109: Championship Sprint/Road Blasters (confirmed) */
|
||||
--static const struct slapstic_data slapstic109 =
|
||||
--{
|
||||
gen_109 : if chip_type = 109 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0008"; -- { 0x0008,0x000a,0x000c,0x000e },/* bank select values */
|
||||
val_bank1 <= x"000A";
|
||||
val_bank2 <= x"000C";
|
||||
val_bank3 <= x"000E";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"002B"; -- { 0x007f,0x002b }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"0052"; -- { 0x3fff,0x0052 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"0064"; -- { 0x3ffc,0x0064 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF9"; val_alt4 <= x"0008"; -- { 0x3ff9,0x0008 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"3DA0"; -- { 0x3ff0,0x3da0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"3DA0"; -- { 0x3ff3,0x3da0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"3DA1"; -- { 0x3ff3,0x3da1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"3DA2"; -- { 0x3ff3,0x3da2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"3DA3"; -- { 0x3ff3,0x3da3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"3DB0"; -- { 0x3ff8,0x3db0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/* slapstic 137412-110: Road Blasters/APB (confirmed) */
|
||||
--static const struct slapstic_data slapstic110 =
|
||||
--{
|
||||
gen_110 : if chip_type = 110 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 3, /* starting bank */
|
||||
val_bank0 <= x"0040"; -- { 0x0040,0x0050,0x0060,0x0070 },/* bank select values */
|
||||
val_bank1 <= x"0050";
|
||||
val_bank2 <= x"0060";
|
||||
val_bank3 <= x"0070";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"002D"; -- { 0x007f,0x002d }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3D14"; -- { 0x3fff,0x3d14 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3FFC"; val_alt3 <= x"3D24"; -- { 0x3ffc,0x3d24 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FCF"; val_alt4 <= x"0040"; -- { 0x3fcf,0x0040 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
|
||||
bitwise <= '1'; -- /* bitwise banking */
|
||||
mask_bit1 <= x"3FF0"; val_bit1 <= x"34C0"; -- { 0x3ff0,0x34c0 }, /* 1st mask/value in sequence */
|
||||
mask_bit2c0 <= x"3FF3"; val_bit2c0 <= x"34C0"; -- { 0x3ff3,0x34c0 }, /* clear bit 0 value */
|
||||
mask_bit2s0 <= x"3FF3"; val_bit2s0 <= x"34C1"; -- { 0x3ff3,0x34c1 }, /* set bit 0 value */
|
||||
mask_bit2c1 <= x"3FF3"; val_bit2c1 <= x"34C2"; -- { 0x3ff3,0x34c2 }, /* clear bit 1 value */
|
||||
mask_bit2s1 <= x"3FF3"; val_bit2s1 <= x"34C3"; -- { 0x3ff3,0x34c3 }, /* set bit 1 value */
|
||||
mask_bit3 <= x"3FF8"; val_bit3 <= x"34D0"; -- { 0x3ff8,0x34d0 }, /* final mask/value in sequence */
|
||||
-- /* additive banking */
|
||||
additive <= '0'; -- NO_ADDITIVE
|
||||
end generate; --};
|
||||
|
||||
|
||||
--/*************************************
|
||||
-- *
|
||||
-- * Slapstic-2 definitions
|
||||
-- *
|
||||
-- *************************************/
|
||||
|
||||
--/* slapstic 137412-111: Pit Fighter (confirmed) */
|
||||
--static const struct slapstic_data slapstic111 =
|
||||
--{
|
||||
gen_111 : if chip_type = 111 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0042"; -- { 0x0042,0x0052,0x0062,0x0072 },/* bank select values */
|
||||
val_bank1 <= x"0052";
|
||||
val_bank2 <= x"0062";
|
||||
val_bank3 <= x"0072";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"000A"; -- { 0x007f,0x000a }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"28A4"; -- { 0x3fff,0x28a4 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"0784"; val_alt3 <= x"0080"; -- { 0x0784,0x0080 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FCF"; val_alt4 <= x"0042"; -- { 0x3fcf,0x0042 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"00A1"; -- { 0x3fff,0x00a1 }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"00A2"; -- { 0x3fff,0x00a2 }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3C4F"; val_addp1 <= x"284D"; -- { 0x3c4f,0x284d }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3A5F"; val_addp2 <= x"285D"; -- { 0x3a5f,0x285d }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FF8"; val_add3 <= x"2800"; -- { 0x3ff8,0x2800 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-112: Pit Fighter (Japan) (confirmed) */
|
||||
--static const struct slapstic_data slapstic112 =
|
||||
--{
|
||||
gen_112 : if chip_type = 112 generate -- /* basic banking */
|
||||
ini_bank <= "11"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"002C"; -- { 0x002c,0x003c,0x006c,0x007c },/* bank select values */
|
||||
val_bank1 <= x"003C";
|
||||
val_bank2 <= x"006C";
|
||||
val_bank3 <= x"007C";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0014"; -- { 0x007f,0x0014 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"29A0"; -- { 0x3fff,0x29a0 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"0073"; val_alt3 <= x"0010"; -- { 0x0073,0x0010 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FAF"; val_alt4 <= x"002C"; -- { 0x3faf,0x002c }, /* 4th mask/value in sequence */
|
||||
altshift <= 2; -- 2, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"2DCE"; -- { 0x3fff,0x2dce }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"2DCF"; -- { 0x3fff,0x2dcf }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3DEF"; val_addp1 <= x"15E2"; -- { 0x3def,0x15e2 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3FBF"; val_addp2 <= x"15A2"; -- { 0x3fbf,0x15a2 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFC"; val_add3 <= x"1450"; -- { 0x3ffc,0x1450 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-113: Unknown (Europe) (confirmed) */
|
||||
--static const struct slapstic_data slapstic113 =
|
||||
--{
|
||||
gen_113 : if chip_type = 113 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0008"; -- { 0x0008,0x0018,0x0028,0x0038 },/* bank select values */
|
||||
val_bank1 <= x"0018";
|
||||
val_bank2 <= x"0028";
|
||||
val_bank3 <= x"0038";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0059"; -- { 0x007f,0x0059 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"11A5"; -- { 0x3fff,0x11a5 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"0860"; val_alt3 <= x"0800"; -- { 0x0860,0x0800 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FCF"; val_alt4 <= x"0008"; -- { 0x3fcf,0x0008 }, /* 4th mask/value in sequence */
|
||||
altshift <= 3; -- 3, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"049B"; -- { 0x3fff,0x049b }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"049C"; -- { 0x3fff,0x049c }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3FCF"; val_addp1 <= x"3EC7"; -- { 0x3fcf,0x3ec7 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3EDF"; val_addp2 <= x"3ED7"; -- { 0x3edf,0x3ed7 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFF"; val_add3 <= x"3FB2"; -- { 0x3fff,0x3fb2 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-114: Pit Fighter (rev 9) (confirmed) */
|
||||
--static const struct slapstic_data slapstic114 =
|
||||
--{
|
||||
gen_114 : if chip_type = 114 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0040"; -- { 0x0040,0x0048,0x0050,0x0058 },/* bank select values */
|
||||
val_bank1 <= x"0048";
|
||||
val_bank2 <= x"0050";
|
||||
val_bank3 <= x"0058";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0016"; -- { 0x007f,0x0016 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"24DE"; -- { 0x3fff,0x24de }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3871"; val_alt3 <= x"0000"; -- { 0x3871,0x0000 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FE7"; val_alt4 <= x"0040"; -- { 0x3fe7,0x0040 }, /* 4th mask/value in sequence */
|
||||
altshift <= 1; -- 1, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"0AB7"; -- { 0x3fff,0x0ab7 }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"0AB8"; -- { 0x3fff,0x0ab8 }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3F63"; val_addp1 <= x"0D40"; -- { 0x3f63,0x0d40 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3FD9"; val_addp2 <= x"0DC8"; -- { 0x3fd9,0x0dc8 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFF"; val_add3 <= x"0AB0"; -- { 0x3fff,0x0ab0 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-115: Race Drivin' DSK board (confirmed) */
|
||||
--static const struct slapstic_data slapstic115 =
|
||||
--{
|
||||
gen_115 : if chip_type = 115 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0020"; -- { 0x0020,0x0022,0x0024,0x0026 },/* bank select values */
|
||||
val_bank1 <= x"0022";
|
||||
val_bank2 <= x"0024";
|
||||
val_bank3 <= x"0026";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0054"; -- { 0x007f,0x0054 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3E01"; -- { 0x3fff,0x3e01 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"3879"; val_alt3 <= x"0029"; -- { 0x3879,0x0029 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FF9"; val_alt4 <= x"0020"; -- { 0x3ff9,0x0020 }, /* 4th mask/value in sequence */
|
||||
altshift <= 1; -- 1, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"2591"; -- { 0x3fff,0x2591 }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"2592"; -- { 0x3fff,0x2592 }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3FE6"; val_addp1 <= x"3402"; -- { 0x3fe6,0x3402 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3FB4"; val_addp2 <= x"3410"; -- { 0x3fb4,0x3410 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFF"; val_add3 <= x"34A2"; -- { 0x3fff,0x34a2 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-116: Hydra (confirmed) */
|
||||
--static const struct slapstic_data slapstic116 =
|
||||
--{
|
||||
gen_116 : if chip_type = 116 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0044"; -- { 0x0044,0x004c,0x0054,0x005c },/* bank select values */
|
||||
val_bank1 <= x"004C";
|
||||
val_bank2 <= x"0054";
|
||||
val_bank3 <= x"005C";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0069"; -- { 0x007f,0x0069 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"2BAB"; -- { 0x3fff,0x2bab }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"387C"; val_alt3 <= x"0808"; -- { 0x387c,0x0808 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FE7"; val_alt4 <= x"0044"; -- { 0x3fe7,0x0044 }, /* 4th mask/value in sequence */
|
||||
altshift <= 0; -- 0, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"3F7C"; -- { 0x3fff,0x3f7c }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"3F7D"; -- { 0x3fff,0x3f7d }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3DB2"; val_addp1 <= x"3C12"; -- { 0x3db2,0x3c12 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3FE3"; val_addp2 <= x"3E43"; -- { 0x3fe3,0x3e43 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFF"; val_add3 <= x"2BA8"; -- { 0x3fff,0x2ba8 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-117: Race Drivin' main board (confirmed) */
|
||||
--static const struct slapstic_data slapstic117 =
|
||||
--{
|
||||
gen_117 : if chip_type = 117 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0008"; -- { 0x0008,0x001a,0x002c,0x003e },/* bank select values */
|
||||
val_bank1 <= x"001A";
|
||||
val_bank2 <= x"002C";
|
||||
val_bank3 <= x"003E";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"007D"; -- { 0x007f,0x007d }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"3580"; -- { 0x3fff,0x3580 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"0079"; val_alt3 <= x"0020"; -- { 0x0079,0x0020 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3FC9"; val_alt4 <= x"0008"; -- { 0x3fc9,0x0008 }, /* 4th mask/value in sequence */
|
||||
altshift <= 1; -- 1, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"0676"; -- { 0x3fff,0x0676 }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"0677"; -- { 0x3fff,0x0677 }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3E62"; val_addp1 <= x"1A42"; -- { 0x3e62,0x1a42 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3E35"; val_addp2 <= x"1A11"; -- { 0x3e35,0x1a11 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FFF"; val_add3 <= x"1A42"; -- { 0x3fff,0x1a42 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
|
||||
|
||||
--/* slapstic 137412-118: Rampart/Vindicators II (confirmed) */
|
||||
--static const struct slapstic_data slapstic118 =
|
||||
--{
|
||||
gen_118 : if chip_type = 118 generate -- /* basic banking */
|
||||
ini_bank <= "00"; -- 0, /* starting bank */
|
||||
val_bank0 <= x"0014"; -- { 0x0014,0x0034,0x0054,0x0074 },/* bank select values */
|
||||
val_bank1 <= x"0034";
|
||||
val_bank2 <= x"0054";
|
||||
val_bank3 <= x"0074";
|
||||
-- /* alternate banking */
|
||||
mask_alt1 <= x"007F"; val_alt1 <= x"0002"; -- { 0x007f,0x0002 }, /* 1st mask/value in sequence */
|
||||
mask_alt2 <= x"3FFF"; val_alt2 <= x"1950"; -- { 0x3fff,0x1950 }, /* 2nd mask/value in sequence */
|
||||
mask_alt3 <= x"0067"; val_alt3 <= x"0020"; -- { 0x0067,0x0020 }, /* 3rd mask/value in sequence */
|
||||
mask_alt4 <= x"3F9F"; val_alt4 <= x"0014"; -- { 0x3f9f,0x0014 }, /* 4th mask/value in sequence */
|
||||
altshift <= 3; -- 3, /* shift to get bank from 3rd */
|
||||
-- /* bitwise banking */
|
||||
bitwise <= '0'; -- NO_BITWISE,
|
||||
|
||||
additive <= '1'; -- /* additive banking */
|
||||
mask_add1 <= x"3FFF"; val_add1 <= x"1958"; -- { 0x3fff,0x1958 }, /* 1st mask/value in sequence */
|
||||
mask_add2 <= x"3FFF"; val_add2 <= x"1959"; -- { 0x3fff,0x1959 }, /* 2nd mask/value in sequence */
|
||||
mask_addp1 <= x"3F73"; val_addp1 <= x"3052"; -- { 0x3f73,0x3052 }, /* +1 mask/value */
|
||||
mask_addp2 <= x"3F67"; val_addp2 <= x"3042"; -- { 0x3f67,0x3042 }, /* +2 mask/value */
|
||||
mask_add3 <= x"3FF8"; val_add3 <= x"30E0"; -- { 0x3ff8,0x30e0 } /* final mask/value in sequence */
|
||||
end generate; --};
|
||||
|
||||
slv_BS <= cur_bank;
|
||||
O_BS <= slv_BS;
|
||||
|
||||
-- expand address to 16 bits for easier representation in hex
|
||||
addr <= "00" & I_A;
|
||||
|
||||
p_slap : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
sl_ASn_last <= I_ASn; -- detect /AS transition
|
||||
if I_CSn = '0' then
|
||||
if sl_ASn_last = '0' and I_ASn = '1' then
|
||||
-- /* reset is universal */
|
||||
if addr = x"0000" then -- if (offset == 0x0000)
|
||||
-- {
|
||||
state <= ENA; -- state = ENABLED;
|
||||
-- }
|
||||
-- /* otherwise, use the state machine */
|
||||
else -- else
|
||||
-- {
|
||||
case state is -- switch (state)
|
||||
-- {
|
||||
-- /* DISABLED state: everything is ignored except a reset */
|
||||
when DIS => -- case DISABLED:
|
||||
-- break;
|
||||
-- /* ENABLED state: the chip has been activated and is ready for a bankswitch */
|
||||
when ENA => -- case ENABLED:
|
||||
-- /* check for request to enter bitwise state */
|
||||
if bitwise = '1' and (addr and mask_bit1) = val_bit1 then -- if (MATCHES_MASK_VALUE(offset, slapstic.bit1))
|
||||
-- {
|
||||
state <= BIT1; -- state = BITWISE1;
|
||||
-- }
|
||||
-- /* check for request to enter additive state */
|
||||
elsif additive = '1' and (addr and mask_add1) = val_add1 then -- else if (MATCHES_MASK_VALUE(offset, slapstic.add1))
|
||||
-- {
|
||||
state <= ADD1; -- state = ADDITIVE1;
|
||||
-- }
|
||||
-- /* check for request to enter alternate state */
|
||||
elsif (addr and mask_alt1) = val_alt1 then -- else if (MATCHES_MASK_VALUE(offset, slapstic.alt1))
|
||||
-- {
|
||||
state <= ALT1; -- state = ALTERNATE1;
|
||||
-- }
|
||||
-- /* special kludge for catching the second alternate address if */
|
||||
-- /* the first one was missed (since it's usually an opcode fetch) */
|
||||
elsif (addr and mask_alt2) = val_alt2 then -- else if (MATCHES_MASK_VALUE(offset, slapstic.alt2))
|
||||
-- {
|
||||
state <= ALT2; -- state = alt2_kludge(space, offset);
|
||||
-- }
|
||||
-- /* check for standard bankswitches */
|
||||
elsif addr = val_bank0 then -- else if (offset == slapstic.bank[0])
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= "00"; -- current_bank = 0;
|
||||
-- }
|
||||
elsif addr = val_bank1 then -- else if (offset == slapstic.bank[1])
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= "01"; -- current_bank = 1;
|
||||
-- }
|
||||
elsif addr = val_bank2 then -- else if (offset == slapstic.bank[2])
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= "10"; -- current_bank = 2;
|
||||
-- }
|
||||
elsif addr = val_bank3 then -- else if (offset == slapstic.bank[3])
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= "11"; -- current_bank = 3;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ALTERNATE1 state: look for alternate2 offset, or else fall back to ENABLED */
|
||||
when ALT1 => -- case ALTERNATE1:
|
||||
if (addr and mask_alt2) = val_alt2 then -- if (MATCHES_MASK_VALUE(offset, slapstic.alt2))
|
||||
-- {
|
||||
state <= ALT2; -- state = ALTERNATE2;
|
||||
-- }
|
||||
else -- else
|
||||
-- {
|
||||
state <= ENA; -- state = ENABLED;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ALTERNATE2 state: look for altbank offset, or else fall back to ENABLED */
|
||||
when ALT2 => -- case ALTERNATE2:
|
||||
if (addr and mask_alt3) = val_alt3 then -- if (MATCHES_MASK_VALUE(offset, slapstic.alt3))
|
||||
-- {
|
||||
state <= ALT3; -- state = ALTERNATE3;
|
||||
alt_bank <= addr(altshift+1) & addr(altshift); -- alt_bank = (offset >> slapstic.altshift) & 3;
|
||||
-- }
|
||||
else -- else
|
||||
-- {
|
||||
state <= ENA; -- state = ENABLED;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ALTERNATE3 state: wait for the final value to finish the transaction */
|
||||
when ALT3 => -- case ALTERNATE3:
|
||||
if (addr and mask_alt4) = val_alt4 then -- if (MATCHES_MASK_VALUE(offset, slapstic.alt4))
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= alt_bank; -- current_bank = alt_bank;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* BITWISE1 state: waiting for a bank to enter the BITWISE state */
|
||||
when BIT1 => -- case BITWISE1:
|
||||
-- if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
|
||||
if (addr = val_bank0) or (addr = val_bank1) or -- offset == slapstic.bank[2] || offset == slapstic.bank[3])
|
||||
(addr = val_bank2) or (addr = val_bank3) then
|
||||
-- {
|
||||
state <= BIT2; -- state = BITWISE2;
|
||||
bit_bank <= cur_bank; -- bit_bank = current_bank;
|
||||
bit_xor <= "00"; -- bit_xor = 0;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* BITWISE2 state: watch for twiddling and the escape mechanism */
|
||||
when BIT2 => -- case BITWISE2:
|
||||
-- /* check for clear bit 0 case */
|
||||
if ( (addr(15 downto 2) & (addr(1 downto 0) xor bit_xor) ) -- if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2c0))
|
||||
and mask_bit2c0) = val_bit2c0 then
|
||||
-- {
|
||||
bit_bank <= bit_bank and "10"; -- bit_bank &= ~1;
|
||||
bit_xor <= bit_xor xor "11"; -- bit_xor ^= 3;
|
||||
-- }
|
||||
--
|
||||
-- /* check for set bit 0 case */
|
||||
elsif ( (addr(15 downto 2) & (addr(1 downto 0) xor bit_xor) ) -- else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2s0))
|
||||
and mask_bit2s0) = val_bit2s0 then
|
||||
-- {
|
||||
bit_bank <= bit_bank or "01"; -- bit_bank |= 1;
|
||||
bit_xor <= bit_xor xor "11"; -- bit_xor ^= 3;
|
||||
-- }
|
||||
-- /* check for clear bit 1 case */
|
||||
elsif ( (addr(15 downto 2) & (addr(1 downto 0) xor bit_xor) ) -- else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2c1))
|
||||
and mask_bit2c1) = val_bit2c1 then
|
||||
-- {
|
||||
bit_bank <= bit_bank and "01"; -- bit_bank &= ~2;
|
||||
bit_xor <= bit_xor xor "11"; -- bit_xor ^= 3;
|
||||
-- }
|
||||
-- /* check for set bit 1 case */
|
||||
elsif ( (addr(15 downto 2) & (addr(1 downto 0) xor bit_xor) ) -- else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2s1))
|
||||
and mask_bit2s1) = val_bit2s1 then
|
||||
-- {
|
||||
bit_bank <= bit_bank or "10"; -- bit_bank |= 2;
|
||||
bit_xor <= bit_xor xor "11"; -- bit_xor ^= 3;
|
||||
-- }
|
||||
-- /* check for escape case */
|
||||
elsif (addr and mask_bit3) = val_bit3 then -- else if (MATCHES_MASK_VALUE(offset, slapstic.bit3))
|
||||
-- {
|
||||
state <= BIT3; -- state = BITWISE3;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* BITWISE3 state: waiting for a bank to seal the deal */
|
||||
when BIT3 => -- case BITWISE3:
|
||||
-- if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
|
||||
if (addr = val_bank0) or (addr = val_bank1) or -- offset == slapstic.bank[2] || offset == slapstic.bank[3])
|
||||
(addr = val_bank2) or (addr = val_bank3) then
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= bit_bank; -- current_bank = bit_bank;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ADDITIVE1 state: look for add2 offset, or else fall back to ENABLED */
|
||||
when ADD1 => -- case ADDITIVE1:
|
||||
if (addr and mask_add2) = val_add2 then -- if (MATCHES_MASK_VALUE(offset, slapstic.add2))
|
||||
-- {
|
||||
state <= ADD2; -- state = ADDITIVE2;
|
||||
add_bank <= cur_bank; -- add_bank = current_bank;
|
||||
-- }
|
||||
else -- else
|
||||
-- {
|
||||
state <= ENA; -- state = ENABLED;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ADDITIVE2 state: watch for twiddling and the escape mechanism */
|
||||
when ADD2 => -- case ADDITIVE2:
|
||||
if ((addr and mask_addp1) = val_addp1) and -- there is a case where we add 3 (both +1 and +2 cases matched) so since we don't execute sequentially
|
||||
((addr and mask_addp2) = val_addp2) then -- like a CPU runing a C program but in parallel, we have to add one more test for that specific case
|
||||
add_bank <= add_bank + 3;
|
||||
-- /* check for add 1 case -- can intermix */
|
||||
elsif (addr and mask_addp1) = val_addp1 then -- if (MATCHES_MASK_VALUE(offset, slapstic.addplus1))
|
||||
-- {
|
||||
add_bank <= add_bank + 1; -- add_bank = (add_bank + 1) & 3;
|
||||
-- }
|
||||
-- /* check for add 2 case -- can intermix */
|
||||
elsif (addr and mask_addp2) = val_addp2 then -- if (MATCHES_MASK_VALUE(offset, slapstic.addplus2))
|
||||
-- {
|
||||
add_bank <= add_bank + 2; -- add_bank = (add_bank + 2) & 3;
|
||||
-- }
|
||||
-- /* check for escape case -- can intermix with the above */
|
||||
elsif (addr and mask_add3) = val_add3 then -- if (MATCHES_MASK_VALUE(offset, slapstic.add3))
|
||||
-- {
|
||||
state <= ADD3; -- state = ADDITIVE3;
|
||||
end if; -- }
|
||||
-- break;
|
||||
-- /* ADDITIVE3 state: waiting for a bank to seal the deal */
|
||||
when ADD3 => -- case ADDITIVE3:
|
||||
-- if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
|
||||
if (addr = val_bank0) or (addr = val_bank1) or -- offset == slapstic.bank[2] || offset == slapstic.bank[3])
|
||||
(addr = val_bank2) or (addr = val_bank3) then
|
||||
-- {
|
||||
state <= DIS; -- state = DISABLED;
|
||||
cur_bank <= add_bank; -- current_bank = add_bank;
|
||||
end if; -- }
|
||||
when others => null; -- break;
|
||||
end case; -- }
|
||||
end if; -- }
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end RTL;
|
||||
211
Arcade_MiST/Atari Gauntlet Hardware/rtl/SYNGEN.vhd
Normal file
211
Arcade_MiST/Atari Gauntlet Hardware/rtl/SYNGEN.vhd
Normal file
@@ -0,0 +1,211 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- System Clock and Sync Generator (Atari custom chip 137419-103)
|
||||
-- This SYNGEN was derived from System I SP-277 schematic
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity SYNGEN is
|
||||
port(
|
||||
I_CK : in std_logic; -- 7.159MHz clock
|
||||
|
||||
O_C0 : out std_logic := '0';
|
||||
O_C1 : out std_logic := '0';
|
||||
O_C2 : out std_logic := '0';
|
||||
O_LMPDn : out std_logic := '0';
|
||||
O_HBKn : out std_logic;
|
||||
O_VIDBn : out std_logic; -- VIDBLANK
|
||||
O_VRESn : out std_logic;
|
||||
|
||||
O_HSYNCn : out std_logic;
|
||||
O_VSYNCn : out std_logic;
|
||||
O_PFHSTn : out std_logic;
|
||||
O_BUFCLRn : out std_logic;
|
||||
|
||||
O_VBLKn : out std_logic; -- VBLANK
|
||||
O_VSCK : out std_logic;
|
||||
O_CK0n : out std_logic; -- pin 4 RCLOCK
|
||||
O_CK0 : out std_logic; -- pin 29 FCLOCK
|
||||
O_2HDLn : out std_logic;
|
||||
O_4HDLn : out std_logic;
|
||||
O_4HDDn : out std_logic;
|
||||
O_NXLn : out std_logic;
|
||||
O_V : out std_logic_vector(7 downto 0);
|
||||
O_H : out std_logic_vector(8 downto 0)
|
||||
);
|
||||
end SYNGEN;
|
||||
|
||||
architecture RTL of SYNGEN is
|
||||
signal
|
||||
sl_2HDLn,
|
||||
sl_3A5,
|
||||
sl_4HDDn,
|
||||
sl_o13
|
||||
: std_logic := '0';
|
||||
signal
|
||||
sl_VBLANKn,
|
||||
sl_4HDLn,
|
||||
sl_C0,
|
||||
sl_C1,
|
||||
sl_C2,
|
||||
sl_HBLANKn,
|
||||
sl_HSYNCn,
|
||||
sl_LMPDn,
|
||||
sl_NXLn,
|
||||
sl_VRESn,
|
||||
sl_o11,
|
||||
sl_o12,
|
||||
sl_o14,
|
||||
sl_o15,
|
||||
sl_o16,
|
||||
sl_o17,
|
||||
sl_o18,
|
||||
sl_o19
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_5E_data
|
||||
: std_logic_vector( 3 downto 0) := (others => '1');
|
||||
signal
|
||||
slv_5E_addr
|
||||
: std_logic_vector( 7 downto 0) := (others => '1');
|
||||
signal
|
||||
slv_vcnt
|
||||
: std_logic_vector( 7 downto 0) := x"EF"; --(others => '1');
|
||||
signal
|
||||
slv_hcnt
|
||||
: std_logic_vector( 8 downto 0) := (others => '0');
|
||||
begin
|
||||
O_2HDLn <= sl_2HDLn;
|
||||
O_4HDDn <= sl_4HDDn;
|
||||
O_4HDLn <= sl_4HDLn;
|
||||
O_BUFCLRn <= not sl_o11;
|
||||
O_C0 <= sl_C0;
|
||||
O_C1 <= sl_C1;
|
||||
O_C2 <= sl_C2;
|
||||
O_CK0 <= I_CK;
|
||||
O_CK0n <= not I_CK;
|
||||
O_H <= slv_hcnt;
|
||||
O_HBKn <= sl_HBLANKn; -- From SP-313 this is /HBLANK
|
||||
O_HSYNCn <= sl_HSYNCn;
|
||||
O_LMPDn <= sl_LMPDn;
|
||||
O_NXLn <= not sl_o19;
|
||||
O_PFHSTn <= not sl_o12;
|
||||
O_V <= slv_vcnt;
|
||||
O_VBLKn <= sl_VBLANKn;
|
||||
O_VIDBn <= sl_VBLANKn and sl_HBLANKn;
|
||||
O_VRESn <= sl_VRESn;
|
||||
O_VSCK <= sl_VBLANKn and sl_o13;
|
||||
O_VSYNCn <= slv_5E_data(1);
|
||||
|
||||
p_7A_7D_7E : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
|
||||
-- 7D
|
||||
sl_2HDLn <= not slv_hcnt(1); -- 2H delayed x1 inverted
|
||||
sl_4HDLn <= not slv_hcnt(2); -- 4H delayed x1 inverted
|
||||
sl_4HDDn <= sl_4HDLn; -- 4H delayed x2
|
||||
|
||||
-- 7E
|
||||
sl_NXLn <= not sl_o19;
|
||||
sl_C2 <= sl_o18;
|
||||
sl_C1 <= sl_o17;
|
||||
sl_C0 <= sl_o16;
|
||||
sl_LMPDn <= not sl_o15;
|
||||
sl_HBLANKn <= not sl_o14;
|
||||
sl_HSYNCn <= not sl_o13;
|
||||
end process;
|
||||
|
||||
slv_5E_addr <= sl_3A5 & (slv_vcnt(7) and slv_vcnt(6)) & slv_vcnt(5 downto 0);
|
||||
|
||||
-- 82S129 256x4 TTL BIPOLAR PROM (Atari chip 136032.102)
|
||||
u_PROM_5E : entity work.PROM_5E
|
||||
port map (
|
||||
CLK => I_CK,
|
||||
ADDR => slv_5E_addr,
|
||||
DATA => slv_5E_data
|
||||
);
|
||||
|
||||
-- counters 4E, 5D, 6E, 6F
|
||||
p_h_v_count : process
|
||||
begin
|
||||
wait until rising_edge(I_CK);
|
||||
if sl_NXLn = '0' then
|
||||
slv_hcnt <= (others=>'0');
|
||||
if slv_5E_data(0) = '0' then
|
||||
slv_vcnt <= (others=>'1');
|
||||
else
|
||||
slv_vcnt <= slv_vcnt + 1;
|
||||
end if;
|
||||
sl_VRESn <= slv_5E_data(0); -- F/F 3A output 9
|
||||
sl_3A5 <= slv_5E_data(2); -- F/F 3A output 5
|
||||
sl_VBLANKn <= not slv_5E_data(3); -- F/F 5B output 5
|
||||
else
|
||||
slv_hcnt <= slv_hcnt + 1;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Equations for PLA chip 7F Signetics 82S153 aka PLS153A (Atari custom chip 136032.103)
|
||||
-- /o19 = /i1 & i2 & i3 & i7 & i8 & i9
|
||||
-- o18 = i1 & /i2
|
||||
-- o17 = i1 & /i2 & /i3 +
|
||||
-- /i1 & i2 & /i3 +
|
||||
-- i1 & /i2 & i3
|
||||
-- o16 = /i2 +
|
||||
-- i1 & i2 & /i3 +
|
||||
-- /i1 & i2 & i3
|
||||
-- /o15 = i3 & /i4 & /i5 & /i6 & /i7 & /i8 & /i9 +
|
||||
-- i2 & /i3 & /i4 & /i5 & /i6 & /i7 & /i8 & /i9 +
|
||||
-- /i2 & /i3 & i4 & /i5 & /i6 & /i7 & /i8 & /i9
|
||||
-- /o14 = /i4 & /i5 & /i6 & /i7 & /i8 & /i9 +
|
||||
-- i4 & i5 & /i6 & i7 & /i8 & i9 +
|
||||
-- i6 & i7 & /i8 & i9 +
|
||||
-- i8 & i9
|
||||
-- o13 = /i4 & i5 & /i6 & /i7 & i8 & i9 +
|
||||
-- /i5 & /i6 & /i7 & i8 & i9 +
|
||||
-- i4 & i5 & i6 & i7 & /i8 & i9
|
||||
-- /o12 = i4 & i5 & i6 & /i7 & i8 & i9
|
||||
-- /o11 = /i1 & i2 & i3 & /i4 & /i5 & /i6 & /i7 & /i8 & /i9
|
||||
|
||||
sl_o19 <= ((not slv_hcnt(0)) and slv_hcnt(1) and slv_hcnt(2) and slv_hcnt(6) and slv_hcnt(7) and slv_hcnt(8));
|
||||
|
||||
sl_o18 <= slv_hcnt(0) and (not slv_hcnt(1)) ;
|
||||
|
||||
sl_o17 <= ( slv_hcnt(0) and (not slv_hcnt(1)) and (not slv_hcnt(2))) or
|
||||
((not slv_hcnt(0)) and slv_hcnt(1) and (not slv_hcnt(2))) or
|
||||
( slv_hcnt(0) and (not slv_hcnt(1)) and slv_hcnt(2));
|
||||
|
||||
sl_o16 <= (not slv_hcnt(1)) or
|
||||
( slv_hcnt(0) and slv_hcnt(1) and (not slv_hcnt(2))) or
|
||||
( (not slv_hcnt(0)) and slv_hcnt(1) and slv_hcnt(2));
|
||||
|
||||
sl_o15 <= (( slv_hcnt(2) and (not slv_hcnt(3)) and (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and (not slv_hcnt(7)) and (not slv_hcnt(8))) or
|
||||
( slv_hcnt(1) and (not slv_hcnt(2)) and (not slv_hcnt(3)) and (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and (not slv_hcnt(7)) and (not slv_hcnt(8))) or
|
||||
(( not slv_hcnt(1)) and (not slv_hcnt(2)) and slv_hcnt(3) and (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and (not slv_hcnt(7)) and (not slv_hcnt(8))));
|
||||
|
||||
sl_o14 <= (((not slv_hcnt(3)) and (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and (not slv_hcnt(7)) and (not slv_hcnt(8))) or
|
||||
( slv_hcnt(3) and slv_hcnt(4) and (not slv_hcnt(5)) and slv_hcnt(6) and (not slv_hcnt(7)) and slv_hcnt(8)) or
|
||||
( slv_hcnt(5) and slv_hcnt(6) and (not slv_hcnt(7)) and slv_hcnt(8)) or
|
||||
( slv_hcnt(7) and slv_hcnt(8)));
|
||||
|
||||
sl_o13 <= ( (not slv_hcnt(3)) and slv_hcnt(4) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and slv_hcnt(7) and slv_hcnt(8)) or
|
||||
( (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and slv_hcnt(7) and slv_hcnt(8)) or
|
||||
( slv_hcnt(3) and slv_hcnt(4) and slv_hcnt(5) and slv_hcnt(6) and (not slv_hcnt(7)) and slv_hcnt(8));
|
||||
|
||||
sl_o12 <= ( slv_hcnt(3) and slv_hcnt(4) and slv_hcnt(5) and (not slv_hcnt(6)) and slv_hcnt(7) and slv_hcnt(8));
|
||||
|
||||
sl_o11 <= ((not slv_hcnt(0)) and slv_hcnt(1) and slv_hcnt(2) and (not slv_hcnt(3)) and (not slv_hcnt(4)) and (not slv_hcnt(5)) and (not slv_hcnt(6)) and (not slv_hcnt(7)) and (not slv_hcnt(8)));
|
||||
end RTL;
|
||||
74
Arcade_MiST/Atari Gauntlet Hardware/rtl/TMS5220.vhd
Normal file
74
Arcade_MiST/Atari Gauntlet Hardware/rtl/TMS5220.vhd
Normal file
@@ -0,0 +1,74 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity TMS5220 is
|
||||
port (
|
||||
-- inputs
|
||||
I_OSC : in std_logic; -- pin 6 typ 640KHz
|
||||
I_WSn : in std_logic; -- pin 27 Write Select
|
||||
I_RSn : in std_logic; -- pin 28 Read Select
|
||||
I_DATA : in std_logic; -- pin 21 Serial Data In (alt function)
|
||||
I_TEST : in std_logic; -- pin 20 Test use only
|
||||
I_DBUS : in std_logic_vector(7 downto 0); -- pins 1,26,24,22,19,12,13,14
|
||||
-- outputs
|
||||
O_DBUS : out std_logic_vector(7 downto 0); -- pins 1,26,24,22,19,12,13,14
|
||||
O_RDYn : out std_logic; -- pin 18 Transfer cycle complete
|
||||
O_INTn : out std_logic; -- pin 17 Interrupt
|
||||
|
||||
O_M0 : out std_logic; -- pin 15 VSM command bit 0
|
||||
O_M1 : out std_logic; -- pin 16 VSM command bit 1
|
||||
O_ADD8 : out std_logic; -- pin 21 VSM Addr (alt function)
|
||||
O_ADD4 : out std_logic; -- pin 23 VSM Addr
|
||||
O_ADD2 : out std_logic; -- pin 25 VSM Addr
|
||||
O_ADD1 : out std_logic; -- pin 2 VSM Addr
|
||||
O_ROMCLK : out std_logic; -- pin 3 VSM clock
|
||||
|
||||
O_T11 : out std_logic; -- pin 7 Sync
|
||||
O_IO : out std_logic; -- pin 9 Serial Data Out
|
||||
O_PRMOUT : out std_logic; -- pin 10 Test use only
|
||||
O_SPKR : out signed(7 downto 0) -- pin 8 Audio Output
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture RTL of TMS5220 is
|
||||
signal rdy : std_logic := '0';
|
||||
signal int_n : std_logic := '1';
|
||||
signal dbus : std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
-- FIXME implement TMS5220 core
|
||||
|
||||
O_DBUS <= dbus;
|
||||
O_RDYn <= rdy;
|
||||
O_INTn <= int_n;
|
||||
|
||||
O_SPKR <= (others=>'0'); -- speaker out
|
||||
|
||||
-- VSM memory bus driver (not implemented)
|
||||
O_M0 <= '0';
|
||||
O_M1 <= '0';
|
||||
O_ADD8 <= '0';
|
||||
O_ADD4 <= '0';
|
||||
O_ADD2 <= '0';
|
||||
O_ADD1 <= '0';
|
||||
O_ROMCLK <= '0';
|
||||
|
||||
O_T11 <= '0'; -- sync
|
||||
O_IO <= '0'; -- serial out
|
||||
O_PRMOUT <= '0'; -- test use
|
||||
|
||||
end architecture;
|
||||
936
Arcade_MiST/Atari Gauntlet Hardware/rtl/VIDEO.vhd
Normal file
936
Arcade_MiST/Atari Gauntlet Hardware/rtl/VIDEO.vhd
Normal file
@@ -0,0 +1,936 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity VIDEO is
|
||||
port(
|
||||
I_MCKR : in std_logic; -- MCKR 7.159 MHz
|
||||
I_ADDR : in std_logic_vector(14 downto 1);
|
||||
I_DATA : in std_logic_vector(15 downto 0);
|
||||
I_HSCRLDn : in std_logic;
|
||||
I_CRAMn : in std_logic;
|
||||
I_VRAMn : in std_logic;
|
||||
I_VBUSn : in std_logic;
|
||||
I_VRDTACK : in std_logic;
|
||||
I_VBKACKn : in std_logic;
|
||||
I_R_Wn : in std_logic;
|
||||
I_LDSn : in std_logic;
|
||||
I_UDSn : in std_logic;
|
||||
O_VCPU : out std_logic;
|
||||
O_VBKINTn : out std_logic;
|
||||
O_VBLANKn : out std_logic;
|
||||
O_1H : out std_logic;
|
||||
O_2H : out std_logic;
|
||||
O_32V : out std_logic;
|
||||
O_DATA : out std_logic_vector(15 downto 0);
|
||||
O_I : out std_logic_vector( 3 downto 0);
|
||||
O_R : out std_logic_vector( 3 downto 0);
|
||||
O_G : out std_logic_vector( 3 downto 0);
|
||||
O_B : out std_logic_vector( 3 downto 0);
|
||||
O_HSYNC : out std_logic;
|
||||
O_VSYNC : out std_logic;
|
||||
O_CSYNC : out std_logic;
|
||||
-- external GFX ROMs
|
||||
O_GP_EN : out std_logic;
|
||||
O_GP_ADDR : out std_logic_vector(15 downto 0);
|
||||
I_GP_DATA : in std_logic_vector(31 downto 0)
|
||||
);
|
||||
end VIDEO;
|
||||
|
||||
architecture RTL of VIDEO is
|
||||
signal
|
||||
sl_MATCH,
|
||||
sl_VRDTACK,
|
||||
sl_VBUS,
|
||||
sl_1H,
|
||||
sl_2H,
|
||||
sl_4H,
|
||||
-- sl_4HD3,
|
||||
sl_6S6,
|
||||
sl_6T8,
|
||||
sl_6X6,
|
||||
-- sl_6X8,
|
||||
sl_6X8_en,
|
||||
sl_7S7,
|
||||
sl_9D12,
|
||||
sl_9D4,
|
||||
sl_9D7,
|
||||
sl_9D9,
|
||||
sl_ALC3,
|
||||
sl_ALC3D,
|
||||
sl_ALC4,
|
||||
sl_ALC4D,
|
||||
sl_CRA5,
|
||||
sl_CRA7,
|
||||
sl_H03,
|
||||
sl_HFLP,
|
||||
-- sl_HORZDL,
|
||||
sl_MREFL,
|
||||
sl_NXL,
|
||||
sl_NXLDL,
|
||||
sl_VCPU,
|
||||
-- sl_VERTDL,
|
||||
sl_VRAMWE
|
||||
-- sl_PICTDL
|
||||
: std_logic := '0';
|
||||
signal
|
||||
sl_GP_EN,
|
||||
sl_GP_ADDR14,
|
||||
sl_MCKF,
|
||||
sl_HSCRLDn,
|
||||
sl_VRAMn,
|
||||
sl_LDSn,
|
||||
sl_UDSn,
|
||||
sl_BR_Wn,
|
||||
sl_BW_Rn,
|
||||
sl_4HD3_en,
|
||||
sl_4HD3n,
|
||||
sl_4HDDn,
|
||||
sl_4HDLn,
|
||||
sl_4Hn,
|
||||
sl_6S9,
|
||||
sl_BUFCLRn,
|
||||
sl_ENDn,
|
||||
sl_FLBAn,
|
||||
sl_FLBBn,
|
||||
sl_G8T,
|
||||
sl_GLD,
|
||||
sl_GLDn,
|
||||
sl_HORZDLn,
|
||||
sl_HORZDLn_tap,
|
||||
sl_HSYNCn,
|
||||
sl_LDABn,
|
||||
sl_LINKn,
|
||||
sl_LMPDn,
|
||||
sl_MATCHDL,
|
||||
sl_MC0,
|
||||
sl_MC1,
|
||||
sl_MFLP,
|
||||
sl_MO_PFn,
|
||||
sl_NEWMOn,
|
||||
sl_NXLn,
|
||||
sl_NXLn_star,
|
||||
sl_PFHSTn,
|
||||
-- sl_PICTDLn,
|
||||
sl_PICTDLn_tap,
|
||||
sl_VBKACKn,
|
||||
sl_VBLANKn,
|
||||
sl_VBLANKn_en,
|
||||
sl_VERTDLn,
|
||||
sl_VERTDLn_tap,
|
||||
sl_VIDBLANKn,
|
||||
sl_VMATCHn,
|
||||
sl_VSYNCn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
slv_VAS,
|
||||
slv_VAS_star
|
||||
: std_logic_vector( 1 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_HSIZ,
|
||||
slv_VSIZ
|
||||
: std_logic_vector( 2 downto 0) := (others=>'0');
|
||||
signal
|
||||
sl_I,
|
||||
sl_R,
|
||||
sl_G,
|
||||
sl_B,
|
||||
slv_4E,
|
||||
slv_PSEL,
|
||||
slv_ctr_5R,
|
||||
slv_sum_6L,
|
||||
slv_shift_7N,
|
||||
slv_shift_7P,
|
||||
slv_4R_data
|
||||
: std_logic_vector( 3 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_PFSR
|
||||
: std_logic_vector( 6 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_ctr_4L_4M,
|
||||
slv_MPIC,
|
||||
slv_V,
|
||||
slv_MPX,
|
||||
slv_PFX,
|
||||
slv_MOSR,
|
||||
slv_ROM_6P,
|
||||
slv_PROM_5L
|
||||
: std_logic_vector( 7 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_PFH
|
||||
: std_logic_vector( 8 downto 3) := (others=>'0');
|
||||
signal
|
||||
slv_H,
|
||||
slv_adder_a,
|
||||
slv_XPOS,
|
||||
slv_YPOS,
|
||||
slv_HPOS,
|
||||
slv_sum_5D_5E
|
||||
: std_logic_vector( 8 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_sum,
|
||||
slv_CRA,
|
||||
slv_LINK,
|
||||
slv_GPC_CA
|
||||
: std_logic_vector( 9 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_PFV,
|
||||
slv_VRAM,
|
||||
slv_VRA
|
||||
: std_logic_vector(11 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_ROM_6P_addr
|
||||
: std_logic_vector(13 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_MA
|
||||
: std_logic_vector(14 downto 1) := (others=>'0');
|
||||
signal
|
||||
slv_CRAM,
|
||||
slv_4C_4K,
|
||||
slv_TILE,
|
||||
slv_VBD,
|
||||
slv_VRD
|
||||
: std_logic_vector(15 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_GP_ADDR
|
||||
: std_logic_vector(17 downto 0) := (others=>'0');
|
||||
signal
|
||||
slv_GP_DATA : std_logic_vector(31 downto 0) := (others=>'0');
|
||||
|
||||
begin
|
||||
O_I <= sl_I;
|
||||
O_R <= sl_R;
|
||||
O_G <= sl_G;
|
||||
O_B <= sl_B;
|
||||
|
||||
O_1H <= slv_H(0);
|
||||
O_2H <= slv_H(1);
|
||||
O_32V <= slv_V(5);
|
||||
|
||||
O_DATA <= slv_VBD;
|
||||
O_VCPU <= sl_VCPU;
|
||||
O_VBLANKn <= sl_VBLANKn;
|
||||
|
||||
O_HSYNC <= sl_HSYNCn;
|
||||
O_VSYNC <= sl_VSYNCn;
|
||||
O_CSYNC <= sl_HSYNCn and sl_VSYNCn;
|
||||
|
||||
O_GP_ADDR <= slv_GP_ADDR(15) & sl_GP_ADDR14 & slv_GP_ADDR(13 downto 0);
|
||||
O_GP_EN <= sl_GP_EN;
|
||||
|
||||
sl_MCKF <= not I_MCKR;
|
||||
|
||||
-----------------------------
|
||||
-- sheet 2 control signals --
|
||||
-----------------------------
|
||||
|
||||
slv_MA <= I_ADDR;
|
||||
sl_VBUS <= I_VBUSn;
|
||||
sl_VRDTACK <= I_VRDTACK;
|
||||
sl_VBKACKn <= I_VBKACKn;
|
||||
sl_HSCRLDn <= I_HSCRLDn;
|
||||
sl_VRAMn <= I_VRAMn;
|
||||
sl_UDSn <= I_UDSn;
|
||||
sl_LDSn <= I_LDSn;
|
||||
sl_BR_Wn <= I_R_Wn;
|
||||
sl_BW_Rn <= not I_R_Wn;
|
||||
|
||||
-----------------------
|
||||
-- sheet 8 RAM banks --
|
||||
-----------------------
|
||||
-- at adress 900000-905FFF
|
||||
u_VRAMS : entity work.VRAMS
|
||||
port map (
|
||||
I_CK => sl_MCKF,
|
||||
I_VRAMWE => sl_VRAMWE,
|
||||
I_SELB => sl_9D4,
|
||||
I_SELA => sl_9D7,
|
||||
I_UDSn => sl_9D9,
|
||||
I_LDSn => sl_9D12,
|
||||
I_VRA => slv_VRA,
|
||||
I_VRD => slv_VBD,
|
||||
O_VRD => slv_VRD
|
||||
);
|
||||
|
||||
------------------------------------------
|
||||
-- sheet 9 VRAM addr and data bus muxes --
|
||||
------------------------------------------
|
||||
|
||||
-- 903800-903FFF R/W ------xx xxxxxxxx (Link to next object)
|
||||
-- 8F, 8J latches sheet 9
|
||||
-- D transfered to Q on the rising edge of clock if enable /G is low
|
||||
p_8F_8J : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_LINKn = '0' then
|
||||
slv_LINK <= slv_VRD(9 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
slv_VRA <= slv_VRAM when sl_NXLDL = '0' else "111111" & slv_VRAM( 5 downto 0); -- pullups RN7
|
||||
|
||||
-- 8C, 8E, 8D selectors create video RAM address high
|
||||
-- 7L, 8L, 8K selectors create video RAM address low
|
||||
slv_VRAM <=
|
||||
slv_MA(12 downto 1) when slv_VAS = "11" else -- c3
|
||||
'1' & slv_V(7 downto 3) & slv_H(8 downto 3) when slv_VAS = "10" else -- c2
|
||||
sl_MC1 & sl_MC0 & slv_LINK(9 downto 0) when slv_VAS = "01" else -- c1
|
||||
slv_PFH(8 downto 3) & slv_PFV(8 downto 3) when slv_VAS = "00"; -- c0
|
||||
|
||||
-- 7S latch
|
||||
p_7S : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
sl_NXLDL <= sl_NXL;
|
||||
slv_VAS(1) <= slv_VAS_star(1) and sl_NXLn;
|
||||
sl_7S7 <= slv_VAS_star(1);
|
||||
slv_VAS(0) <= slv_VAS_star(0);
|
||||
sl_VCPU <= slv_VAS_star(0) and slv_VAS_star(1);
|
||||
end process;
|
||||
|
||||
-- 9D selector SEL 0=A 1=B
|
||||
sl_9D4 <= slv_MA(14) when sl_VCPU = '1' else sl_7S7;
|
||||
sl_9D7 <= slv_MA(13) when sl_VCPU = '1' else slv_VAS(0);
|
||||
sl_9D9 <= sl_UDSn when sl_VCPU = '1' else '0';
|
||||
sl_9D12 <= sl_LDSn when sl_VCPU = '1' else '0';
|
||||
|
||||
-- gate 11J -- inverted for Xilinx Block RAMs
|
||||
-- The FCLOCK is connected to the BRAM clock input to achieve the intended result, or else we
|
||||
-- have timing problem as WE and FCLOCK become active simultaneously and WE signal is missed
|
||||
sl_VRAMWE <= sl_VCPU and sl_VRDTACK and sl_BW_Rn; -- and sl_MCKF
|
||||
|
||||
-- 9E, 10E transceivers to/from 68K data bus
|
||||
-- 9K, 10K transceivers to/from CRAM
|
||||
-- DIR 0=B->A 1=A->B
|
||||
-- VBD is driven by either
|
||||
-- 68K data bus
|
||||
-- CRAM data bus
|
||||
-- VRAM data bus
|
||||
-- else it holds its value (latches 9J,10J)
|
||||
slv_VBD <=
|
||||
I_DATA when sl_BW_Rn = '1' and sl_VBUS = '0' else -- VBUS write access from 68K
|
||||
slv_CRAM when sl_BW_Rn = '0' and I_CRAMn = '0' else -- CRAM read access
|
||||
slv_VRD when sl_BW_Rn = '0' and sl_VRAMn = '0' else -- VRAM read access
|
||||
(others=>'0'); -- else floating
|
||||
|
||||
----------------------------
|
||||
-- sheet 10
|
||||
----------------------------
|
||||
|
||||
-- 902000-9027FF R/W -xxxxxxx xxxxxxxx (Tile index / Sprite)
|
||||
-- 3C, 3K latch sheet 10
|
||||
p_3C_3K : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_PICTDLn_tap = '0' then
|
||||
slv_TILE <= sl_MREFL & slv_VRD(14 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 903000-9037FF R/W xxxxxxxx x------- (Y position)
|
||||
-- R/W -------- -x------ (Horizontal flip)
|
||||
-- R/W -------- --xxx--- (Number of X tiles - 1)
|
||||
-- R/W -------- -----xxx (Number of Y tiles - 1)
|
||||
-- 5C, 5K latches sheet 10
|
||||
p_5C_5K : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_VERTDLn_tap = '0' then
|
||||
slv_YPOS <= slv_VRD(15 downto 7);
|
||||
sl_MFLP <= slv_VRD(6);
|
||||
slv_HSIZ <= slv_VRD( 5 downto 3);
|
||||
slv_VSIZ <= slv_VRD( 2 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- adders 5D, 5E
|
||||
slv_sum_5D_5E <= (slv_PFV(8 downto 0) + slv_YPOS) + (x"00" & sl_VBLANKn);
|
||||
|
||||
-- 4E latch
|
||||
p_4E : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_H03 = '1' and sl_4H = '0' then
|
||||
if sl_NEWMOn = '0' then
|
||||
slv_4E <= slv_sum_5D_5E(2 downto 0) & sl_MATCH;
|
||||
sl_MREFL <= sl_MFLP;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 3C, 3J, and 3D, 4K tristate outputs are muxed here
|
||||
-- when MO/PF is active selects 3D, 4K outputs
|
||||
-- when /4HDL is active selects 3C, 3J outputs
|
||||
sl_HFLP <= slv_TILE(15) when sl_4HDLn = '0' else slv_4C_4K(15);
|
||||
|
||||
-- 3F selector is external because all ROMs are also external, address bits 17:15 below would decode to GCS0..5
|
||||
slv_GP_ADDR(17 downto 3) <= slv_TILE(14 downto 8) & slv_MPIC when sl_4HDLn = '0' else '0' & slv_PFV(11 downto 10) & slv_4C_4K(11 downto 0);
|
||||
|
||||
-- 3E mux, SEL 0=A, 1=B
|
||||
slv_GP_ADDR(2) <= slv_4E(3) when sl_4HDLn = '0' else slv_PFV(2);
|
||||
slv_GP_ADDR(1) <= slv_4E(2) when sl_4HDLn = '0' else slv_PFV(1);
|
||||
slv_GP_ADDR(0) <= slv_4E(1) when sl_4HDLn = '0' else slv_PFV(0);
|
||||
sl_GP_EN <= slv_4E(0) when sl_4HDLn = '0' else '1';
|
||||
|
||||
-- bit 14 inverted as per XOR gate 4J, slv_GP_ADDR(17 downto 16) not decoded (ROMS at GCS2..5 not fitted)
|
||||
sl_GP_ADDR14 <= (not slv_GP_ADDR(14));
|
||||
|
||||
-- adder 6L
|
||||
slv_sum_6L <= ( ('1' & slv_VSIZ(2 downto 0)) + ( '1' & slv_sum_5D_5E(5 downto 3)) ) + ( "0001");
|
||||
|
||||
-- NAND gate 6T
|
||||
sl_VMATCHn <= not (slv_sum_5D_5E(8) and slv_sum_5D_5E(7) and slv_sum_5D_5E(6) and slv_sum_6L(3));
|
||||
|
||||
-- PROM 5L is 82S147 512x8 TTL BIPOLAR PROM (Atari chip 136037.102)
|
||||
-- Top 2 address bits tied low so only 128x8 used
|
||||
u_5L : entity work.PROM_5L
|
||||
port map (
|
||||
CLK => I_MCKR,
|
||||
ADDR(6) => sl_MFLP,
|
||||
ADDR(5) => slv_HSIZ(2),
|
||||
ADDR(4) => slv_HSIZ(1),
|
||||
ADDR(3) => slv_HSIZ(0),
|
||||
ADDR(2) => slv_sum_6L(2),
|
||||
ADDR(1) => slv_sum_6L(1),
|
||||
ADDR(0) => slv_sum_6L(0),
|
||||
DATA => slv_PROM_5L
|
||||
);
|
||||
|
||||
-- 4L, 4M counters
|
||||
p_4L_4M : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_H03 = '1' and sl_4H = '0' then
|
||||
if sl_NEWMOn = '0' then
|
||||
slv_ctr_4L_4M <= slv_PROM_5L;
|
||||
elsif sl_MREFL = '0' then
|
||||
slv_ctr_4L_4M <= slv_ctr_4L_4M + 1;
|
||||
else
|
||||
slv_ctr_4L_4M <= slv_ctr_4L_4M - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 3L, 3M adders
|
||||
slv_MPIC <= slv_TILE(7 downto 0) + slv_ctr_4L_4M;
|
||||
|
||||
-- 5J, 5F, 4F counters
|
||||
p_5J_5F_4F : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_H03 = '1' and sl_4H = '0' then
|
||||
if sl_VSYNCn = '0' and sl_PFHSTn = '0' then
|
||||
slv_PFV <= slv_VRD( 1 downto 0) & '0' & slv_VRD(15 downto 7);
|
||||
elsif sl_PFHSTn = '0' and sl_VBLANKn = '1' then
|
||||
slv_PFV <= slv_PFV + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 4C, 4K latch
|
||||
p_4C_4K : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_H03 = '1' and sl_4Hn = '0' then
|
||||
slv_4C_4K <= slv_VRD;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sl_4HD3_en <= sl_4hn or sl_4hdln or sl_4hddn or (not sl_4hd3n);
|
||||
|
||||
-- 4D latch
|
||||
p_4D : process
|
||||
begin
|
||||
-- rising edge sl_4HD3 in schema
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_4HD3_en = '0' then
|
||||
slv_PFSR(6 downto 4) <= not slv_4C_4K(14 downto 12);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- remember that MO/PF is /4HDL inverted
|
||||
sl_MO_PFn <= not sl_4HDLn;
|
||||
|
||||
--------------------------------------------------
|
||||
-- sheet 11 - plane 0 and plane 1 ROMs and SLAG --
|
||||
-- sheet 12 - plane 2 and plane 3 ROMs and SLAG --
|
||||
-- ROMs total 256KB and are stored outside the FPGA
|
||||
--------------------------------------------------
|
||||
|
||||
-- 1K Storage/Logic Array Graphics Shifter
|
||||
u_1K : entity work.SLAGS
|
||||
port map (
|
||||
I_PHIN => I_MCKR,
|
||||
I_A => slv_GP_DATA( 7 downto 0),
|
||||
I_B => slv_GP_DATA(15 downto 8),
|
||||
I_HLDAn => '1',
|
||||
I_HLDBn => '1',
|
||||
I_FLP => sl_HFLP,
|
||||
I_MO_PFn => sl_MO_PFn,
|
||||
I_LDn => sl_GLDn,
|
||||
|
||||
O_PFDA => slv_PFSR(0),
|
||||
O_PFDB => slv_PFSR(1),
|
||||
O_MODA => slv_MOSR(0),
|
||||
O_MODB => slv_MOSR(1)
|
||||
);
|
||||
|
||||
-- 2K Storage/Logic Array Graphics Shifter
|
||||
u_2K : entity work.SLAGS
|
||||
port map (
|
||||
I_PHIN => I_MCKR,
|
||||
I_A => slv_GP_DATA(23 downto 16),
|
||||
I_B => slv_GP_DATA(31 downto 24),
|
||||
I_HLDAn => '1',
|
||||
I_HLDBn => '1',
|
||||
I_FLP => sl_HFLP,
|
||||
I_MO_PFn => sl_MO_PFn,
|
||||
I_LDn => sl_GLDn,
|
||||
|
||||
O_PFDA => slv_PFSR(2),
|
||||
O_PFDB => slv_PFSR(3),
|
||||
O_MODA => slv_MOSR(2),
|
||||
O_MODB => slv_MOSR(3)
|
||||
);
|
||||
|
||||
-- Pullups RN3, RN4, RN5, RN6
|
||||
slv_GP_DATA <= I_GP_DATA when sl_GP_EN = '1' else (others=>'1');
|
||||
|
||||
--------------------------------
|
||||
-- sheet 13 Play Field Scroll --
|
||||
--------------------------------
|
||||
|
||||
-- 12K Play Field Horizontal Scroll
|
||||
u_12K : entity work.PFHS
|
||||
port map (
|
||||
I_CK => I_MCKR,
|
||||
I_ST => sl_PFHSTn,
|
||||
I_4H => sl_4H,
|
||||
I_H03 => sl_H03,
|
||||
I_HS => sl_HSCRLDn,
|
||||
I_SPC => '1',
|
||||
I_D => slv_VBD(8 downto 0),
|
||||
I_PS(7) => slv_PFSR(6),
|
||||
I_PS(6 downto 0) => slv_PFSR(6 downto 0),
|
||||
|
||||
O_PFM => open,
|
||||
O_PFH => slv_PFH(8 downto 3),
|
||||
O_XP => slv_PFX
|
||||
);
|
||||
|
||||
-- Motion Object Horizontal Line Buffer
|
||||
u_MOHLB : entity work.MOHLB
|
||||
port map (
|
||||
I_MCKR => I_MCKR,
|
||||
I_LMPDn => sl_LMPDn,
|
||||
I_LDABn => sl_LDABn,
|
||||
I_BUFCLRn => sl_BUFCLRn,
|
||||
|
||||
I_HPOS => slv_HPOS,
|
||||
I_MOSR => slv_MOSR,
|
||||
|
||||
O_MPX => slv_MPX
|
||||
);
|
||||
|
||||
----------------------------
|
||||
-- sheet 14
|
||||
----------------------------
|
||||
|
||||
-- 902800-903000 R/W xxxxxxxx x------- (X position)
|
||||
-- R/W -------- ----xxxx (Palette select)
|
||||
-- 4N, 3N latches sheet 14
|
||||
p_4N_3N : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_HORZDLn_tap = '0' then
|
||||
slv_XPOS <= slv_VRD(15 downto 7);
|
||||
slv_PSEL <= slv_VRD(3 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 9S, 6M, 7M latches (Playfield X scroll at address 930000)
|
||||
p_9S_6M_7M : process
|
||||
begin
|
||||
-- rising edge sl_HSCRLDn in schema
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_HSCRLDn = '0' then
|
||||
slv_adder_a <= not slv_VBD(8 downto 0); -- /PF256LD .. /PF1LD
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- 5N, 5P adders and gates 4T
|
||||
slv_HPOS <= slv_XPOS + (slv_adder_a + "000000001"); -- add 2's complement to XPOS
|
||||
|
||||
-- 3P latch
|
||||
p_3P : process
|
||||
begin
|
||||
-- rising edge sl_LDABn in schema
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_LDABn = '0' then
|
||||
slv_MOSR(7 downto 4) <= not slv_PSEL;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- PROM 4R is 74S287 (256x4) TTL PROM "136037-103"
|
||||
u_4R : entity work.PROM_4R
|
||||
port map (
|
||||
CLK => sl_MCKF,
|
||||
ADDR(7 downto 3) => slv_HPOS(8 downto 4),
|
||||
ADDR(2 downto 0) => slv_HSIZ(2 downto 0),
|
||||
DATA => slv_4R_data
|
||||
);
|
||||
|
||||
-- 5R counter
|
||||
p_5R : process
|
||||
begin
|
||||
-- rising edge sl_4HD3 in schema
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_4HD3_en = '0' then
|
||||
if sl_NEWMOn = '0' then
|
||||
slv_ctr_5R <= '0' & slv_4R_data(3 downto 1);
|
||||
else
|
||||
slv_ctr_5R <= slv_ctr_5R - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sl_ENDn <= slv_ctr_5R(3) or slv_ctr_5R(2) or slv_ctr_5R(1) or slv_ctr_5R(0);
|
||||
|
||||
-- 6S F/F with async set/reset
|
||||
p_6S6 : process(sl_NXLn, I_MCKR)
|
||||
begin
|
||||
if sl_NXLn = '0' then
|
||||
sl_6S6 <= '0';
|
||||
elsif rising_edge(I_MCKR) then
|
||||
if sl_VERTDLn = '0' then
|
||||
sl_6S6 <= not sl_VMATCHn;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_6S9 : process(sl_VERTDLn, I_MCKR)
|
||||
begin
|
||||
if sl_VERTDLn = '0' then
|
||||
sl_6S9 <= '1';
|
||||
elsif rising_edge(I_MCKR) then
|
||||
if sl_HORZDLn = '0' then
|
||||
sl_6S9 <= slv_4R_data(0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- gate 4U
|
||||
sl_MATCH <= sl_6S6 and sl_6S9;
|
||||
|
||||
sl_2H <= slv_H(1);
|
||||
sl_1H <= slv_H(0);
|
||||
|
||||
-- gate 7T
|
||||
sl_H03 <= sl_2H and sl_1H;
|
||||
|
||||
-- 6U latch with 7U PROM equations
|
||||
p_6U : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
-- 82S147 512x8 TTL BIPOLAR PROM (Atari chip 136037.101)
|
||||
-- These equations replace the 7U PROM
|
||||
-- Minterms Sum of Products
|
||||
-- D7 = A5 A1' + A5 A0 + A5 A2 + A6 A4 A3 A2' A1 A0' + A6 A5
|
||||
-- D6 = A0' + A1 + A2 + A5
|
||||
-- D5 = A1' A0 + A1 A0' + A5 A3 A2' A0 + A7 A4' A3 A2 A0 + A7 A5 A3 A0
|
||||
-- D4 = A3' + A1' A0 + A1 A0' + A2 A0 + A5' A4 A2' A1' + A5 A0
|
||||
-- D3 = A1' A0 + A1 A0' + A3 A2 + A5 A3 + A3' A0 + A4' A3 A1'
|
||||
-- D2 = A2' + A0' + A1 + A8
|
||||
-- D1 = A1' A0 + A2' A1 A0' + A7' A2 A0 + A4' A3 A2 A0 + A5 A3 A0
|
||||
-- D0 = A1' + A2' A0 + A7 A0
|
||||
sl_NEWMOn <= (sl_NEWMOn and (sl_4H or (not sl_2H) or sl_1H)) or
|
||||
(sl_ENDn and sl_MATCHDL and sl_MATCH and (not sl_4H) and sl_2H and (not sl_1H)) or
|
||||
(sl_ENDn and sl_NEWMOn);
|
||||
|
||||
sl_LDABn <= sl_NEWMOn or sl_4H or sl_2H or (not sl_1H);
|
||||
|
||||
sl_G8T <= (sl_2H xor sl_1H) or
|
||||
( (sl_NEWMOn and sl_MATCH) and ( ((not sl_4H) and sl_1H) or (sl_NXLn and sl_1H) ) ) or
|
||||
(sl_NXLn and (not sl_MATCHDL) and sl_MATCH and sl_4H and sl_1H);
|
||||
|
||||
sl_MC1 <= (sl_2H xor sl_1H) or
|
||||
(not sl_MATCH) or
|
||||
(sl_1H and (sl_4H or sl_NEWMOn)) or
|
||||
((not sl_NEWMOn) and sl_MATCHDL and (not sl_4H) and (not sl_2H));
|
||||
|
||||
sl_MC0 <= (sl_2H xor sl_1H) or
|
||||
(sl_MATCH and (sl_NEWMOn or sl_4H)) or
|
||||
((not sl_MATCH) and sl_1H) or
|
||||
((not sl_MATCHDL) and sl_MATCH and (not sl_2H));
|
||||
|
||||
sl_BUFCLRn <= sl_LMPDn or (not sl_4H) or sl_2H or (not sl_1H);
|
||||
end process;
|
||||
|
||||
slv_VAS_star(1) <=
|
||||
((not sl_2H) and sl_1H) or
|
||||
((not sl_4H) and sl_2H and (not sl_1H)) or
|
||||
((not sl_NXLn) and sl_4H and sl_1H) or
|
||||
((not sl_MATCHDL) and sl_MATCH and sl_4H and sl_1H) or
|
||||
(sl_NEWMOn and sl_MATCH and sl_1H);
|
||||
slv_VAS_star(0) <=
|
||||
(not sl_2H) or
|
||||
((not sl_4H) and sl_1H) or
|
||||
(sl_NXLn and sl_1H);
|
||||
|
||||
-- 8T selector
|
||||
-- here we use the tap signals as master clock gates so that we can capture the
|
||||
-- data we want at the same time as falling edge of the corresponding non tap signals
|
||||
sl_LINKn <= sl_G8T or (not sl_MC1) or (not sl_MC0); -- 3
|
||||
sl_VERTDLn_tap <= sl_G8T or (not sl_MC1) or ( sl_MC0); -- 2
|
||||
sl_HORZDLn_tap <= sl_G8T or ( sl_MC1) or (not sl_MC0); -- 1
|
||||
sl_PICTDLn_tap <= sl_G8T or ( sl_MC1) or ( sl_MC0); -- 0
|
||||
|
||||
-- 5S, 5T latches
|
||||
p_5S_5T : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
-- Q outputs of 5S
|
||||
sl_VERTDLn <= sl_VERTDLn_tap; -- 2
|
||||
sl_HORZDLn <= sl_HORZDLn_tap; -- 1
|
||||
-- sl_PICTDLn <= sl_PICTDLn_tap; -- 0
|
||||
sl_FLBBn <= (sl_FLBAn xor sl_BUFCLRn);
|
||||
|
||||
-- Q outputs of 5T
|
||||
sl_4H <= sl_4HD3n;
|
||||
sl_4HD3n <= sl_4HDDn;
|
||||
sl_NXLn <= sl_NXLn_star;
|
||||
sl_GLD <= sl_H03;
|
||||
end process;
|
||||
|
||||
-- /Q outputs of 5S
|
||||
-- sl_VERTDL <= not sl_VERTDLn;
|
||||
-- sl_HORZDL <= not sl_HORZDLn;
|
||||
-- sl_PICTDL <= not sl_PICTDLn;
|
||||
sl_FLBAn <= not sl_FLBBn;
|
||||
|
||||
-- /Q outputs of 5T
|
||||
sl_4Hn <= not sl_4H;
|
||||
-- sl_4HD3 <= not sl_4HD3n;
|
||||
sl_NXL <= not sl_NXLn;
|
||||
sl_GLDn <= not sl_GLD;
|
||||
|
||||
-- 14M F/F
|
||||
p_14M : process(sl_VBKACKn, I_MCKR)
|
||||
begin
|
||||
if sl_VBKACKn = '0' then
|
||||
O_VBKINTn <= '1';
|
||||
elsif rising_edge(I_MCKR) then
|
||||
sl_VBLANKn_en <= sl_VBLANKn;
|
||||
if sl_VBLANKn = '0' and sl_VBLANKn_en = '1' then
|
||||
O_VBKINTn <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
u_8P : entity work.SYNGEN
|
||||
port map (
|
||||
I_CK => I_MCKR,
|
||||
|
||||
O_C0 => open, -- UNUSED
|
||||
O_C1 => open, -- UNUSED
|
||||
O_C2 => open, -- UNUSED
|
||||
O_LMPDn => sl_LMPDn,
|
||||
O_HBKn => open, -- UNUSED
|
||||
O_VIDBn => sl_VIDBLANKn,
|
||||
O_VRESn => open, -- UNUSED
|
||||
|
||||
O_HSYNCn => sl_HSYNCn,
|
||||
O_VSYNCn => sl_VSYNCn,
|
||||
O_PFHSTn => sl_PFHSTn,
|
||||
O_BUFCLRn => open, -- UNUSED this /BUFCLR replaced by signal from PROM 7U
|
||||
|
||||
O_VBLKn => sl_VBLANKn,
|
||||
O_VSCK => open, -- UNUSED
|
||||
O_CK0n => open, -- same as MCKF
|
||||
O_CK0 => open, -- same as MCKR
|
||||
O_2HDLn => open, -- UNUSED
|
||||
O_4HDLn => sl_4HDLn,
|
||||
O_4HDDn => sl_4HDDn,
|
||||
O_NXLn => sl_NXLn_star,
|
||||
O_V => slv_V,
|
||||
O_H => slv_H
|
||||
);
|
||||
|
||||
-- clock generation, 14.31818 MHz xtal drives F/F
|
||||
-- F/F divides xtal by 2 and generates:
|
||||
-- MCKR (Master Clock Rising - 7.1591MHz)
|
||||
-- MCKF (Master Clock Falling - inverted MCKR)
|
||||
-- other clocks are copies of master clock
|
||||
-- RCLOCK same as MCKR
|
||||
-- FCLOCK same as MCKF
|
||||
-- LBCKR same as MCKR
|
||||
-- LBCKF same as MCKF
|
||||
|
||||
----------------------------
|
||||
-- sheet 15
|
||||
----------------------------
|
||||
|
||||
-- gates 6T, 9R
|
||||
sl_6T8 <= not ((not slv_MPX(0)) and slv_MPX(1) and slv_MPX(2) and slv_MPX(3));
|
||||
|
||||
-- Graphic Priority Control
|
||||
u_12M : entity work.GPC
|
||||
port map (
|
||||
I_CK => I_MCKR,
|
||||
I_PFM => '0',
|
||||
I_4H => sl_4H,
|
||||
I_SEL => I_CRAMn,
|
||||
|
||||
-- AL serialised data
|
||||
I_AL(1) => slv_shift_7P(3), -- APIX1
|
||||
I_AL(0) => slv_shift_7N(3), -- APIX0
|
||||
I_MA => slv_MA(10 downto 9),
|
||||
|
||||
-- I_D controls color for alphanumerics
|
||||
I_D(3) => slv_VRD(15), -- to PROM MSB inside GPC
|
||||
I_D(2) => slv_VRD(12), -- to ALC2 inside GPC
|
||||
I_D(1) => slv_VRD(11), -- to ALC1 inside GPC
|
||||
I_D(0) => slv_VRD(10), -- to ALC0 inside GPC
|
||||
|
||||
-- PF data
|
||||
I_P(7) => sl_6T8,
|
||||
I_P(6 downto 0) => slv_PFX(6 downto 0),
|
||||
|
||||
-- MO data
|
||||
I_M(7) => sl_6T8,
|
||||
I_M(6 downto 0) => slv_MPX(6 downto 0),
|
||||
|
||||
O_CA => slv_GPC_CA
|
||||
);
|
||||
|
||||
-- at address 910000-9107FF
|
||||
u_CRAMS : entity work.CRAMS
|
||||
port map (
|
||||
I_MCKR => I_MCKR,
|
||||
I_UDSn => sl_UDSn,
|
||||
I_LDSn => sl_LDSn,
|
||||
I_CRAMn => I_CRAMn,
|
||||
I_BR_Wn => sl_BR_Wn,
|
||||
I_CRA => slv_CRA,
|
||||
I_DB => slv_VBD,
|
||||
O_DB => slv_CRAM
|
||||
);
|
||||
|
||||
|
||||
-- 9N, 10N latch color palette output
|
||||
p_9N_10N : process
|
||||
begin
|
||||
wait until falling_edge(I_MCKR);
|
||||
if I_CRAMn='1' then
|
||||
if sl_VIDBLANKn = '0' then
|
||||
sl_I <= (others=>'0');
|
||||
sl_R <= (others=>'0');
|
||||
sl_G <= (others=>'0');
|
||||
sl_B <= (others=>'0');
|
||||
else
|
||||
-- UDS
|
||||
sl_I <= slv_CRAM(15 downto 12); -- INT
|
||||
sl_R <= slv_CRAM(11 downto 8); -- RED
|
||||
-- LDS
|
||||
sl_G <= slv_CRAM( 7 downto 4); -- GRN
|
||||
sl_B <= slv_CRAM( 3 downto 0); -- BLU
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
slv_CRA(9 downto 8) <= slv_GPC_CA(9 downto 8);
|
||||
|
||||
-- 8M tristate buffer A>Y
|
||||
slv_CRA(7 downto 0) <= slv_MA(8 downto 1) when I_CRAMn = '0' else sl_CRA7 & slv_GPC_CA(6) & sl_CRA5 & slv_GPC_CA(4 downto 0);
|
||||
|
||||
-- 8U dual 4:1 mux
|
||||
sl_CRA7 <=
|
||||
slv_GPC_CA(7) when slv_GPC_CA(9 downto 8) = "11" else
|
||||
slv_GPC_CA(7) when slv_GPC_CA(9 downto 8) = "10" else
|
||||
sl_6X6 when slv_GPC_CA(9 downto 8) = "01" else
|
||||
sl_ALC4D when slv_GPC_CA(9 downto 8) = "00";
|
||||
|
||||
-- 8U dual 4:1 mux
|
||||
sl_CRA5 <=
|
||||
slv_GPC_CA(5) when slv_GPC_CA(9 downto 8) = "11" else
|
||||
slv_GPC_CA(5) when slv_GPC_CA(9 downto 8) = "10" else
|
||||
slv_GPC_CA(5) when slv_GPC_CA(9 downto 8) = "01" else
|
||||
sl_ALC3D when slv_GPC_CA(9 downto 8) = "00";
|
||||
|
||||
-- 6X F/F
|
||||
p_6X : process
|
||||
begin
|
||||
wait until falling_edge(I_MCKR);
|
||||
sl_6X6 <= not slv_MPX(7);
|
||||
-- sl_6X8 <= not sl_4H;
|
||||
end process;
|
||||
|
||||
sl_6X8_en <= (not sl_4hn) or sl_4hdln or sl_4hddn or sl_4hd3n;
|
||||
|
||||
-- 6W F/F
|
||||
p_6W : process
|
||||
begin
|
||||
wait until falling_edge(I_MCKR);
|
||||
if sl_6X8_en = '0' then
|
||||
sl_ALC4D <= sl_ALC4;
|
||||
sl_ALC3D <= sl_ALC3;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Alphanumerics are handled by 4P, 7R, 6P, 7P, 7N and fed into GPC
|
||||
|
||||
p_4P_7R : process
|
||||
begin
|
||||
wait until rising_edge(I_MCKR);
|
||||
if sl_H03 = '1' and sl_4H = '0' then
|
||||
-- 4P latch
|
||||
sl_ALC4 <= slv_VRD(14);
|
||||
sl_ALC3 <= slv_VRD(13);
|
||||
slv_ROM_6P_addr(13 downto 10) <= slv_VRD( 9 downto 6);
|
||||
|
||||
-- 7R latch
|
||||
slv_ROM_6P_addr( 9 downto 4) <= slv_VRD( 5 downto 0);
|
||||
sl_MATCHDL <= sl_MATCH;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- unlatched low address bus
|
||||
slv_ROM_6P_addr(3 downto 0) <= slv_V(2 downto 0) & sl_4Hn;
|
||||
|
||||
-- 6P ROM
|
||||
u_6P : entity work.ROM_6P
|
||||
port map (
|
||||
CLK => I_MCKR,
|
||||
ADDR => slv_ROM_6P_addr,
|
||||
DATA => slv_ROM_6P
|
||||
);
|
||||
|
||||
-- 7P, 7N shifters S1 S0 11=load 10=shift left 01=shift right 00=inhibit
|
||||
p_7P_7N : process
|
||||
begin
|
||||
wait until falling_edge(I_MCKR);
|
||||
if sl_H03 = '1'then -- load
|
||||
slv_shift_7P <= slv_ROM_6P(7 downto 4);
|
||||
slv_shift_7N <= slv_ROM_6P(3 downto 0);
|
||||
elsif sl_H03 = '0' then -- shift msb
|
||||
slv_shift_7P <= slv_shift_7P(2 downto 0) & '0'; --msb is APIX1
|
||||
slv_shift_7N <= slv_shift_7N(2 downto 0) & '0'; --msb is APIX0
|
||||
-- else inhibit
|
||||
end if;
|
||||
end process;
|
||||
end RTL;
|
||||
228
Arcade_MiST/Atari Gauntlet Hardware/rtl/VRAMS.vhd
Normal file
228
Arcade_MiST/Atari Gauntlet Hardware/rtl/VRAMS.vhd
Normal file
@@ -0,0 +1,228 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity VRAMS is
|
||||
port(
|
||||
I_CK : in std_logic;
|
||||
I_VRAMWE : in std_logic;
|
||||
I_SELB : in std_logic;
|
||||
I_SELA : in std_logic;
|
||||
I_UDSn : in std_logic;
|
||||
I_LDSn : in std_logic;
|
||||
I_VRA : in std_logic_vector(11 downto 0);
|
||||
I_VRD : in std_logic_vector(15 downto 0);
|
||||
O_VRD : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end VRAMS;
|
||||
|
||||
architecture RTL of VRAMS is
|
||||
signal
|
||||
sl_PF_HI,
|
||||
sl_MO_HI,
|
||||
sl_AL_HI,
|
||||
sl_PF_LO,
|
||||
sl_MO_LO,
|
||||
sl_AL_LO,
|
||||
sl_PF_CSn,
|
||||
sl_MO_CSn,
|
||||
sl_AL_CSn
|
||||
: std_logic := '1';
|
||||
signal
|
||||
sl_VRAMWE
|
||||
: std_logic := '0';
|
||||
signal
|
||||
slv_PF,
|
||||
slv_MO,
|
||||
slv_AL
|
||||
: std_logic_vector(15 downto 0) := (others=>'0');
|
||||
begin
|
||||
-------------------------
|
||||
-- sheet 9 RAM decoder --
|
||||
-------------------------
|
||||
-- 9C decoders
|
||||
sl_PF_CSn <= ( I_SELB ) or ( I_SELA );
|
||||
sl_MO_CSn <= ( I_SELB ) or ( not I_SELA );
|
||||
sl_AL_CSn <= ( not I_SELB ) or ( I_SELA );
|
||||
|
||||
-- Xilinx Block RAM chip selects
|
||||
sl_PF_HI <= not (I_UDSn or sl_PF_CSn);
|
||||
sl_MO_HI <= not (I_UDSn or sl_MO_CSn);
|
||||
sl_AL_HI <= not (I_UDSn or sl_AL_CSn);
|
||||
|
||||
sl_PF_LO <= not (I_LDSn or sl_PF_CSn);
|
||||
sl_MO_LO <= not (I_LDSn or sl_MO_CSn);
|
||||
sl_AL_LO <= not (I_LDSn or sl_AL_CSn);
|
||||
|
||||
-----------------------
|
||||
-- sheet 8 RAM banks --
|
||||
-----------------------
|
||||
sl_VRAMWE <= I_VRAMWE;
|
||||
|
||||
O_VRD <=
|
||||
slv_PF when sl_PF_CSn = '0' else
|
||||
slv_MO when sl_MO_CSn = '0' else
|
||||
slv_AL when sl_AL_CSn = '0' else
|
||||
-- slv_AL when sl_AL_CSn = '0' and (I_VRA < x"800" or I_VRA > x"F69") else -- disables reads from alphanumerics range 905000-905BB0
|
||||
(others=>'Z'); -- floating
|
||||
|
||||
-- PF video RAMs 6D, 7D, 6J, 7J
|
||||
p_7J_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_PF_LO,
|
||||
data => I_VRD(3 downto 0),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_PF(3 downto 0)
|
||||
);
|
||||
|
||||
p_6J_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_PF_LO,
|
||||
data => I_VRD(7 downto 4),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_PF(7 downto 4)
|
||||
);
|
||||
|
||||
p_7D_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_PF_HI,
|
||||
data => I_VRD(11 downto 8),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_PF(11 downto 8)
|
||||
);
|
||||
|
||||
p_6D_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_PF_HI,
|
||||
data => I_VRD(15 downto 12),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_PF(15 downto 12)
|
||||
);
|
||||
|
||||
-- MO video RAMs 6C, 7C, 6F, 7F
|
||||
p_7F_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_MO_LO,
|
||||
data => I_VRD(3 downto 0),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_MO(3 downto 0)
|
||||
);
|
||||
|
||||
p_6F_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_MO_LO,
|
||||
data => I_VRD(7 downto 4),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_MO(7 downto 4)
|
||||
);
|
||||
|
||||
p_7C_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_MO_HI,
|
||||
data => I_VRD(11 downto 8),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_MO(11 downto 8)
|
||||
);
|
||||
|
||||
p_6C_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_MO_HI,
|
||||
data => I_VRD(15 downto 12),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_MO(15 downto 12)
|
||||
);
|
||||
|
||||
-- AL video RAMs 6E, 7E, 6K, 7K
|
||||
p_7K_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_AL_LO,
|
||||
data => I_VRD(3 downto 0),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_AL(3 downto 0)
|
||||
);
|
||||
|
||||
p_6K_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_AL_LO,
|
||||
data => I_VRD(7 downto 4),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_AL(7 downto 4)
|
||||
);
|
||||
|
||||
p_7E_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_AL_HI,
|
||||
data => I_VRD(11 downto 8),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_AL(11 downto 8)
|
||||
);
|
||||
|
||||
p_6E_RAM : entity work.spram
|
||||
generic map (
|
||||
widthad_a => 12,
|
||||
width_a => 4)
|
||||
port map (
|
||||
address => I_VRA,
|
||||
clock => I_CK,-- and sl_AL_HI,
|
||||
data => I_VRD(15 downto 12),
|
||||
wren => sl_VRAMWE,
|
||||
q => slv_AL(15 downto 12)
|
||||
);
|
||||
|
||||
end RTL;
|
||||
35
Arcade_MiST/Atari Gauntlet Hardware/rtl/build_id.tcl
Normal file
35
Arcade_MiST/Atari Gauntlet Hardware/rtl/build_id.tcl
Normal file
@@ -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
|
||||
461
Arcade_MiST/Atari Gauntlet Hardware/rtl/pll_mist.vhd
Normal file
461
Arcade_MiST/Atari Gauntlet Hardware/rtl/pll_mist.vhd
Normal file
@@ -0,0 +1,461 @@
|
||||
-- megafunction wizard: %ALTPLL%
|
||||
-- GENERATION: STANDARD
|
||||
-- VERSION: WM1.0
|
||||
-- MODULE: altpll
|
||||
|
||||
-- ============================================================
|
||||
-- File Name: pll_mist.vhd
|
||||
-- Megafunction Name(s):
|
||||
-- altpll
|
||||
--
|
||||
-- Simulation Library Files(s):
|
||||
-- altera_mf
|
||||
-- ============================================================
|
||||
-- ************************************************************
|
||||
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
--
|
||||
-- 13.1.0 Build 162 10/23/2013 SJ Web Edition
|
||||
-- ************************************************************
|
||||
|
||||
|
||||
--Copyright (C) 1991-2013 Altera Corporation
|
||||
--Your use of Altera Corporation's design tools, logic functions
|
||||
--and other software and tools, and its AMPP partner logic
|
||||
--functions, and any output files from any of the foregoing
|
||||
--(including device programming or simulation files), and any
|
||||
--associated documentation or information are expressly subject
|
||||
--to the terms and conditions of the Altera Program License
|
||||
--Subscription Agreement, Altera MegaCore Function License
|
||||
--Agreement, or other applicable license agreement, including,
|
||||
--without limitation, that your use is for the sole purpose of
|
||||
--programming logic devices manufactured by Altera and sold by
|
||||
--Altera or its authorized distributors. Please refer to the
|
||||
--applicable agreement for further details.
|
||||
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY pll_mist IS
|
||||
PORT
|
||||
(
|
||||
areset : IN STD_LOGIC := '0';
|
||||
inclk0 : IN STD_LOGIC := '0';
|
||||
c0 : OUT STD_LOGIC ;
|
||||
c1 : OUT STD_LOGIC ;
|
||||
c2 : OUT STD_LOGIC ;
|
||||
c3 : OUT STD_LOGIC ;
|
||||
locked : OUT STD_LOGIC
|
||||
);
|
||||
END pll_mist;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF pll_mist IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
|
||||
SIGNAL sub_wire1 : STD_LOGIC ;
|
||||
SIGNAL sub_wire2 : STD_LOGIC ;
|
||||
SIGNAL sub_wire3 : STD_LOGIC ;
|
||||
SIGNAL sub_wire4 : STD_LOGIC ;
|
||||
SIGNAL sub_wire5 : STD_LOGIC ;
|
||||
SIGNAL sub_wire6 : STD_LOGIC ;
|
||||
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (1 DOWNTO 0);
|
||||
SIGNAL sub_wire8_bv : BIT_VECTOR (0 DOWNTO 0);
|
||||
SIGNAL sub_wire8 : STD_LOGIC_VECTOR (0 DOWNTO 0);
|
||||
|
||||
|
||||
|
||||
COMPONENT altpll
|
||||
GENERIC (
|
||||
bandwidth_type : STRING;
|
||||
clk0_divide_by : NATURAL;
|
||||
clk0_duty_cycle : NATURAL;
|
||||
clk0_multiply_by : NATURAL;
|
||||
clk0_phase_shift : STRING;
|
||||
clk1_divide_by : NATURAL;
|
||||
clk1_duty_cycle : NATURAL;
|
||||
clk1_multiply_by : NATURAL;
|
||||
clk1_phase_shift : STRING;
|
||||
clk2_divide_by : NATURAL;
|
||||
clk2_duty_cycle : NATURAL;
|
||||
clk2_multiply_by : NATURAL;
|
||||
clk2_phase_shift : STRING;
|
||||
clk3_divide_by : NATURAL;
|
||||
clk3_duty_cycle : NATURAL;
|
||||
clk3_multiply_by : NATURAL;
|
||||
clk3_phase_shift : STRING;
|
||||
compensate_clock : STRING;
|
||||
inclk0_input_frequency : NATURAL;
|
||||
intended_device_family : STRING;
|
||||
lpm_hint : STRING;
|
||||
lpm_type : STRING;
|
||||
operation_mode : STRING;
|
||||
pll_type : STRING;
|
||||
port_activeclock : STRING;
|
||||
port_areset : STRING;
|
||||
port_clkbad0 : STRING;
|
||||
port_clkbad1 : STRING;
|
||||
port_clkloss : STRING;
|
||||
port_clkswitch : STRING;
|
||||
port_configupdate : STRING;
|
||||
port_fbin : STRING;
|
||||
port_inclk0 : STRING;
|
||||
port_inclk1 : STRING;
|
||||
port_locked : STRING;
|
||||
port_pfdena : STRING;
|
||||
port_phasecounterselect : STRING;
|
||||
port_phasedone : STRING;
|
||||
port_phasestep : STRING;
|
||||
port_phaseupdown : STRING;
|
||||
port_pllena : STRING;
|
||||
port_scanaclr : STRING;
|
||||
port_scanclk : STRING;
|
||||
port_scanclkena : STRING;
|
||||
port_scandata : STRING;
|
||||
port_scandataout : STRING;
|
||||
port_scandone : STRING;
|
||||
port_scanread : STRING;
|
||||
port_scanwrite : STRING;
|
||||
port_clk0 : STRING;
|
||||
port_clk1 : STRING;
|
||||
port_clk2 : STRING;
|
||||
port_clk3 : STRING;
|
||||
port_clk4 : STRING;
|
||||
port_clk5 : STRING;
|
||||
port_clkena0 : STRING;
|
||||
port_clkena1 : STRING;
|
||||
port_clkena2 : STRING;
|
||||
port_clkena3 : STRING;
|
||||
port_clkena4 : STRING;
|
||||
port_clkena5 : STRING;
|
||||
port_extclk0 : STRING;
|
||||
port_extclk1 : STRING;
|
||||
port_extclk2 : STRING;
|
||||
port_extclk3 : STRING;
|
||||
self_reset_on_loss_lock : STRING;
|
||||
width_clock : NATURAL
|
||||
);
|
||||
PORT (
|
||||
areset : IN STD_LOGIC ;
|
||||
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
|
||||
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
|
||||
locked : OUT STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
sub_wire8_bv(0 DOWNTO 0) <= "0";
|
||||
sub_wire8 <= To_stdlogicvector(sub_wire8_bv);
|
||||
sub_wire5 <= sub_wire0(2);
|
||||
sub_wire4 <= sub_wire0(0);
|
||||
sub_wire2 <= sub_wire0(3);
|
||||
sub_wire1 <= sub_wire0(1);
|
||||
c1 <= sub_wire1;
|
||||
c3 <= sub_wire2;
|
||||
locked <= sub_wire3;
|
||||
c0 <= sub_wire4;
|
||||
c2 <= sub_wire5;
|
||||
sub_wire6 <= inclk0;
|
||||
sub_wire7 <= sub_wire8(0 DOWNTO 0) & sub_wire6;
|
||||
|
||||
altpll_component : altpll
|
||||
GENERIC MAP (
|
||||
bandwidth_type => "AUTO",
|
||||
clk0_divide_by => 35,
|
||||
clk0_duty_cycle => 50,
|
||||
clk0_multiply_by => 83,
|
||||
clk0_phase_shift => "0",
|
||||
clk1_divide_by => 80,
|
||||
clk1_duty_cycle => 50,
|
||||
clk1_multiply_by => 83,
|
||||
clk1_phase_shift => "0",
|
||||
clk2_divide_by => 160,
|
||||
clk2_duty_cycle => 50,
|
||||
clk2_multiply_by => 83,
|
||||
clk2_phase_shift => "0",
|
||||
clk3_divide_by => 320,
|
||||
clk3_duty_cycle => 50,
|
||||
clk3_multiply_by => 83,
|
||||
clk3_phase_shift => "0",
|
||||
compensate_clock => "CLK0",
|
||||
inclk0_input_frequency => 37037,
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_hint => "CBX_MODULE_PREFIX=pll_mist",
|
||||
lpm_type => "altpll",
|
||||
operation_mode => "NORMAL",
|
||||
pll_type => "AUTO",
|
||||
port_activeclock => "PORT_UNUSED",
|
||||
port_areset => "PORT_USED",
|
||||
port_clkbad0 => "PORT_UNUSED",
|
||||
port_clkbad1 => "PORT_UNUSED",
|
||||
port_clkloss => "PORT_UNUSED",
|
||||
port_clkswitch => "PORT_UNUSED",
|
||||
port_configupdate => "PORT_UNUSED",
|
||||
port_fbin => "PORT_UNUSED",
|
||||
port_inclk0 => "PORT_USED",
|
||||
port_inclk1 => "PORT_UNUSED",
|
||||
port_locked => "PORT_USED",
|
||||
port_pfdena => "PORT_UNUSED",
|
||||
port_phasecounterselect => "PORT_UNUSED",
|
||||
port_phasedone => "PORT_UNUSED",
|
||||
port_phasestep => "PORT_UNUSED",
|
||||
port_phaseupdown => "PORT_UNUSED",
|
||||
port_pllena => "PORT_UNUSED",
|
||||
port_scanaclr => "PORT_UNUSED",
|
||||
port_scanclk => "PORT_UNUSED",
|
||||
port_scanclkena => "PORT_UNUSED",
|
||||
port_scandata => "PORT_UNUSED",
|
||||
port_scandataout => "PORT_UNUSED",
|
||||
port_scandone => "PORT_UNUSED",
|
||||
port_scanread => "PORT_UNUSED",
|
||||
port_scanwrite => "PORT_UNUSED",
|
||||
port_clk0 => "PORT_USED",
|
||||
port_clk1 => "PORT_USED",
|
||||
port_clk2 => "PORT_USED",
|
||||
port_clk3 => "PORT_USED",
|
||||
port_clk4 => "PORT_UNUSED",
|
||||
port_clk5 => "PORT_UNUSED",
|
||||
port_clkena0 => "PORT_UNUSED",
|
||||
port_clkena1 => "PORT_UNUSED",
|
||||
port_clkena2 => "PORT_UNUSED",
|
||||
port_clkena3 => "PORT_UNUSED",
|
||||
port_clkena4 => "PORT_UNUSED",
|
||||
port_clkena5 => "PORT_UNUSED",
|
||||
port_extclk0 => "PORT_UNUSED",
|
||||
port_extclk1 => "PORT_UNUSED",
|
||||
port_extclk2 => "PORT_UNUSED",
|
||||
port_extclk3 => "PORT_UNUSED",
|
||||
self_reset_on_loss_lock => "OFF",
|
||||
width_clock => 5
|
||||
)
|
||||
PORT MAP (
|
||||
areset => areset,
|
||||
inclk => sub_wire7,
|
||||
clk => sub_wire0,
|
||||
locked => sub_wire3
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
|
||||
-- ============================================================
|
||||
-- CNX file retrieval info
|
||||
-- ============================================================
|
||||
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
|
||||
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
|
||||
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
|
||||
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
|
||||
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
|
||||
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
|
||||
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "35"
|
||||
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "80"
|
||||
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "160"
|
||||
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "320"
|
||||
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
|
||||
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
|
||||
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "64.028572"
|
||||
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "28.012501"
|
||||
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "14.006250"
|
||||
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "7.003125"
|
||||
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
|
||||
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
|
||||
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
|
||||
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
|
||||
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
|
||||
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
|
||||
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
|
||||
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
|
||||
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
|
||||
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
|
||||
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
|
||||
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
|
||||
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
|
||||
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
|
||||
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
|
||||
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
|
||||
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
|
||||
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
|
||||
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
|
||||
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
|
||||
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
|
||||
-- Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
|
||||
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "83"
|
||||
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "83"
|
||||
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "83"
|
||||
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "83"
|
||||
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "64.00000000"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "28.00000000"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "14.00000000"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "7.00000000"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "0"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT3 STRING "MHz"
|
||||
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
|
||||
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
|
||||
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
|
||||
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
|
||||
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "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: PHASE_SHIFT_UNIT3 STRING "deg"
|
||||
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
|
||||
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
|
||||
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_mist.mif"
|
||||
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
|
||||
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
|
||||
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
|
||||
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
|
||||
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
|
||||
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
|
||||
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
|
||||
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
|
||||
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
|
||||
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
|
||||
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
|
||||
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
|
||||
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
|
||||
-- Retrieval info: PRIVATE: STICKY_CLK3 STRING "1"
|
||||
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
|
||||
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
|
||||
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
|
||||
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
|
||||
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
|
||||
-- Retrieval info: PRIVATE: USE_CLK3 STRING "1"
|
||||
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
|
||||
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
|
||||
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
|
||||
-- Retrieval info: PRIVATE: USE_CLKENA3 STRING "0"
|
||||
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
|
||||
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
|
||||
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
|
||||
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "35"
|
||||
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "83"
|
||||
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "80"
|
||||
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "83"
|
||||
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
|
||||
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "160"
|
||||
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
|
||||
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "83"
|
||||
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
|
||||
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "320"
|
||||
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
|
||||
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "83"
|
||||
-- Retrieval info: CONSTANT: CLK3_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_USED"
|
||||
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
|
||||
-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
|
||||
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
|
||||
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
|
||||
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
|
||||
-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
|
||||
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
|
||||
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
|
||||
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
|
||||
-- Retrieval info: USED_PORT: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
|
||||
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
|
||||
-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
|
||||
-- Retrieval info: CONNECT: @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: c3 0 0 0 0 @clk 0 0 1 3
|
||||
-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.vhd TRUE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.ppf TRUE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.inc FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.cmp FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.bsf FALSE
|
||||
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_inst.vhd FALSE
|
||||
-- Retrieval info: LIB_FILE: altera_mf
|
||||
-- Retrieval info: CBX_MODULE_PREFIX: ON
|
||||
72
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/EEP_14A.vhd
Normal file
72
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/EEP_14A.vhd
Normal file
@@ -0,0 +1,72 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity EEP_14A is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
WEn : in std_logic;
|
||||
CEn : in std_logic;
|
||||
OEn : in std_logic;
|
||||
AD : in std_logic_vector(8 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
-- EEPROM as RAM
|
||||
architecture RTL of EEP_14A is
|
||||
type RAM_ARRAY is array (0 to 511) of std_logic_vector(7 downto 0);
|
||||
-- signal RAM : RAM_ARRAY:=(others=>(others=>'0'));
|
||||
-- initial RAM contents
|
||||
signal RAM : RAM_ARRAY := (
|
||||
x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"03", -- 0x0000
|
||||
x"FC",x"14",x"00",x"EB",x"FF",x"00",x"00",x"17",x"03",x"00",x"00",x"00",x"00",x"14",x"FF",x"00", -- 0x0010
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"03",x"FC",x"14", -- 0x0020
|
||||
x"00",x"EB",x"FF",x"00",x"00",x"17",x"03",x"00",x"00",x"00",x"00",x"14",x"8C",x"51",x"B2",x"00", -- 0x0030
|
||||
x"1F",x"1F",x"00",x"90",x"FC",x"4E",x"22",x"00",x"00",x"90",x"00",x"D2",x"9A",x"B4",x"00",x"B7", -- 0x0040
|
||||
x"00",x"2E",x"9A",x"03",x"00",x"00",x"00",x"03",x"00",x"00",x"FC",x"EE",x"38",x"00",x"95",x"1F", -- 0x0050
|
||||
x"40",x"1F",x"24",x"EC",x"00",x"1D",x"B0",x"1F",x"7A",x"C5",x"81",x"CF",x"00",x"0D",x"1C",x"20", -- 0x0060
|
||||
x"45",x"F8",x"96",x"00",x"1A",x"90",x"54",x"B0",x"96",x"91",x"67",x"00",x"CC",x"1F",x"40",x"0C", -- 0x0070
|
||||
x"04",x"86",x"00",x"1D",x"B0",x"19",x"36",x"FD",x"35",x"74",x"00",x"73",x"1C",x"20",x"0C",x"F7", -- 0x0080
|
||||
x"AE",x"00",x"1A",x"90",x"91",x"42",x"1B",x"B6",x"97",x"00",x"55",x"04",x"26",x"B2",x"C5",x"00", -- 0x0090
|
||||
x"00",x"00",x"C6",x"00",x"03",x"EF",x"36",x"97",x"00",x"31",x"7F",x"FF",x"00",x"B1",x"00",x"00", -- 0x00A0
|
||||
x"00",x"90",x"49",x"68",x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x00B0
|
||||
x"00",x"00",x"00",x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x00C0
|
||||
x"00",x"00",x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x00D0
|
||||
x"00",x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x00E0
|
||||
x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"FF", -- 0x00F0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"FF",x"00", -- 0x0100
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"FF",x"00",x"00", -- 0x0110
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"FF",x"00",x"00",x"00", -- 0x0120
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0130
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0140
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0150
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0160
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0170
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0180
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x0190
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x01A0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x01B0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x01C0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", -- 0x01D0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"FF", -- 0x01E0
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00" -- 0x01F0
|
||||
);
|
||||
|
||||
-- attribute ram_style : string;
|
||||
-- attribute ram_style of RAM : signal is "block";
|
||||
begin
|
||||
mem_proc : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
DO <= (others=>'Z');
|
||||
if CEn = '0' then
|
||||
if OEn = '0' then
|
||||
DO <= RAM(to_integer(unsigned(AD)));
|
||||
elsif WEn = '0' then
|
||||
RAM(to_integer(unsigned(AD))) <= DI;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end RTL;
|
||||
41
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_4R.vhd
Normal file
41
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_4R.vhd
Normal file
@@ -0,0 +1,41 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity PROM_4R is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
ADDR : in std_logic_vector(7 downto 0);
|
||||
DATA : out std_logic_vector(3 downto 0) := (others=>'0')
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture RTL of PROM_4R is
|
||||
type ROM_ARRAY is array (0 to 255) of std_logic_vector(3 downto 0);
|
||||
signal ROM : ROM_ARRAY := (
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0000
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0010
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0020
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0030
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0040
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F", -- 0x0050
|
||||
x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"B",x"B", -- 0x0060
|
||||
x"1",x"3",x"5",x"7",x"7",x"7",x"7",x"7",x"1",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0070
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x0080
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x0090
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x00A0
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x00B0
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x00C0
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0",x"0", -- 0x00D0
|
||||
x"0",x"0",x"0",x"0",x"0",x"0",x"D",x"F",x"0",x"0",x"0",x"0",x"9",x"B",x"D",x"F", -- 0x00E0
|
||||
x"0",x"0",x"5",x"7",x"9",x"B",x"D",x"F",x"1",x"3",x"5",x"7",x"9",x"B",x"D",x"F" -- 0x00F0
|
||||
);
|
||||
attribute ram_style : string;
|
||||
-- attribute ram_style of ROM : signal is "distributed";
|
||||
begin
|
||||
mem_proc : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
DATA <= ROM(to_integer(unsigned(ADDR)));
|
||||
end process;
|
||||
end RTL;
|
||||
41
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_5E.vhd
Normal file
41
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_5E.vhd
Normal file
@@ -0,0 +1,41 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity PROM_5E is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
ADDR : in std_logic_vector(7 downto 0);
|
||||
DATA : out std_logic_vector(3 downto 0) := (others=>'1')
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture RTL of PROM_5E is
|
||||
type ROM_ARRAY is array (0 to 255) of std_logic_vector(3 downto 0);
|
||||
signal ROM : ROM_ARRAY := (
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0000
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0010
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0020
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0030
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0040
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3", -- 0x0050
|
||||
x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"3",x"B", -- 0x0060
|
||||
x"B",x"B",x"B",x"9",x"9",x"9",x"9",x"B",x"B",x"B",x"B",x"B",x"B",x"B",x"B",x"F", -- 0x0070
|
||||
x"F",x"F",x"F",x"F",x"F",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x0080
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x0090
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00A0
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00B0
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00C0
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00D0
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E", -- 0x00E0
|
||||
x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"E",x"3" -- 0x00F0
|
||||
);
|
||||
attribute ram_style : string;
|
||||
-- attribute ram_style of ROM : signal is "distributed";
|
||||
begin
|
||||
mem_proc : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
DATA <= ROM(to_integer(unsigned(ADDR)));
|
||||
end process;
|
||||
end RTL;
|
||||
33
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_5L.vhd
Normal file
33
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/PROM_5L.vhd
Normal file
@@ -0,0 +1,33 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity PROM_5L is
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
ADDR : in std_logic_vector(6 downto 0);
|
||||
DATA : out std_logic_vector(7 downto 0) := (others=>'0')
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture RTL of PROM_5L is
|
||||
type ROM_ARRAY is array (0 to 127) of std_logic_vector(7 downto 0);
|
||||
signal ROM : ROM_ARRAY := (
|
||||
x"00",x"01",x"02",x"03",x"04",x"05",x"06",x"07",x"00",x"02",x"04",x"06",x"08",x"0A",x"0C",x"0E", -- 0x0000
|
||||
x"00",x"03",x"06",x"09",x"0C",x"0F",x"12",x"15",x"00",x"04",x"08",x"0C",x"10",x"14",x"18",x"1C", -- 0x0010
|
||||
x"00",x"05",x"0A",x"0F",x"14",x"19",x"1E",x"23",x"00",x"06",x"0C",x"12",x"18",x"1E",x"24",x"2A", -- 0x0020
|
||||
x"00",x"07",x"0E",x"15",x"1C",x"23",x"2A",x"31",x"00",x"08",x"10",x"18",x"20",x"28",x"30",x"38", -- 0x0030
|
||||
x"00",x"01",x"02",x"03",x"04",x"05",x"06",x"07",x"01",x"03",x"05",x"07",x"09",x"0B",x"0D",x"0F", -- 0x0040
|
||||
x"02",x"05",x"08",x"0B",x"0E",x"11",x"14",x"17",x"03",x"07",x"0B",x"0F",x"13",x"17",x"1B",x"1F", -- 0x0050
|
||||
x"04",x"09",x"0E",x"13",x"18",x"1D",x"22",x"27",x"05",x"0B",x"11",x"17",x"1D",x"23",x"29",x"2F", -- 0x0060
|
||||
x"06",x"0D",x"14",x"1B",x"22",x"29",x"30",x"37",x"07",x"0F",x"17",x"1F",x"27",x"2F",x"37",x"3F" -- 0x0070
|
||||
);
|
||||
attribute ram_style : string;
|
||||
-- attribute ram_style of ROM : signal is "distributed";
|
||||
begin
|
||||
mem_proc : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
DATA <= ROM(to_integer(unsigned(ADDR)));
|
||||
end process;
|
||||
end RTL;
|
||||
538
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/ROM_6P.vhd
Normal file
538
Arcade_MiST/Atari Gauntlet Hardware/rtl/rom/ROM_6P.vhd
Normal file
@@ -0,0 +1,538 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all,ieee.numeric_std.all;
|
||||
|
||||
entity ROM_6P is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector(13 downto 0);
|
||||
data : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture prom of ROM_6P is
|
||||
type rom is array(0 to 8191) of std_logic_vector(7 downto 0);
|
||||
signal rom_data: rom := (
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"FF",X"EE",X"EE",X"EE",X"FF",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"00",X"00",
|
||||
X"FF",X"CC",X"FF",X"EE",X"EE",X"EE",X"FF",X"CC",X"EE",X"EE",X"FF",X"EE",X"FF",X"CC",X"00",X"00",
|
||||
X"77",X"CC",X"FF",X"EE",X"FF",X"EE",X"EE",X"00",X"FF",X"EE",X"FF",X"EE",X"77",X"CC",X"00",X"00",
|
||||
X"FF",X"CC",X"FF",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"FF",X"EE",X"FF",X"CC",X"00",X"00",
|
||||
X"FF",X"EE",X"FF",X"EE",X"EE",X"00",X"FF",X"CC",X"EE",X"00",X"FF",X"EE",X"FF",X"EE",X"00",X"00",
|
||||
X"FF",X"EE",X"FF",X"EE",X"EE",X"00",X"FF",X"CC",X"EE",X"00",X"EE",X"00",X"EE",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"FF",X"EE",X"FF",X"EE",X"EE",X"00",X"EE",X"EE",X"FF",X"EE",X"77",X"EE",X"00",X"00",
|
||||
X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"FF",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"00",X"00",
|
||||
X"33",X"CC",X"33",X"CC",X"33",X"CC",X"33",X"CC",X"33",X"CC",X"33",X"CC",X"33",X"CC",X"00",X"00",
|
||||
X"00",X"EE",X"00",X"EE",X"00",X"EE",X"66",X"EE",X"66",X"EE",X"77",X"EE",X"33",X"CC",X"00",X"00",
|
||||
X"EE",X"EE",X"EE",X"EE",X"FF",X"CC",X"FF",X"88",X"FF",X"CC",X"EE",X"EE",X"EE",X"EE",X"00",X"00",
|
||||
X"EE",X"00",X"EE",X"00",X"EE",X"00",X"EE",X"00",X"EE",X"00",X"FF",X"EE",X"FF",X"EE",X"00",X"00",
|
||||
X"EE",X"EE",X"FE",X"EE",X"FF",X"EE",X"FF",X"EE",X"FF",X"EE",X"FD",X"E6",X"DD",X"66",X"00",X"00",
|
||||
X"EE",X"66",X"FF",X"66",X"FF",X"EE",X"FF",X"EE",X"FF",X"EE",X"DD",X"EE",X"CC",X"EE",X"00",X"00",
|
||||
X"77",X"CC",X"FF",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"FF",X"EE",X"77",X"CC",X"00",X"00",
|
||||
X"FF",X"CC",X"FF",X"EE",X"EE",X"EE",X"FF",X"CC",X"EE",X"00",X"EE",X"00",X"EE",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"FF",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"FF",X"EE",X"77",X"CC",X"00",X"EE",
|
||||
X"FF",X"CC",X"FF",X"EE",X"EE",X"EE",X"FF",X"C8",X"FF",X"CC",X"EE",X"EE",X"EE",X"EE",X"00",X"00",
|
||||
X"77",X"EE",X"FF",X"EE",X"EE",X"00",X"FF",X"EE",X"00",X"EE",X"FF",X"EE",X"FF",X"CC",X"00",X"00",
|
||||
X"FF",X"EE",X"FF",X"EE",X"33",X"88",X"33",X"88",X"33",X"88",X"33",X"88",X"33",X"88",X"00",X"00",
|
||||
X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"FF",X"EE",X"FF",X"EE",X"77",X"CC",X"00",X"00",
|
||||
X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"66",X"CC",X"77",X"CC",X"33",X"88",X"33",X"88",X"00",X"00",
|
||||
X"DD",X"66",X"FD",X"E6",X"FF",X"EE",X"FF",X"EE",X"FF",X"EE",X"FE",X"EE",X"EE",X"EE",X"00",X"00",
|
||||
X"EC",X"E6",X"FE",X"EE",X"F7",X"EC",X"73",X"C8",X"F7",X"EC",X"FE",X"EE",X"EC",X"E6",X"00",X"00",
|
||||
X"EE",X"EE",X"EE",X"EE",X"EE",X"EE",X"77",X"CC",X"33",X"88",X"33",X"88",X"33",X"88",X"00",X"00",
|
||||
X"FF",X"EE",X"FF",X"EE",X"11",X"EE",X"77",X"CC",X"FF",X"00",X"FF",X"EE",X"FF",X"EE",X"00",X"00",
|
||||
X"08",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"11",X"00",X"33",X"00",X"77",X"00",X"FF",X"11",X"FF",X"33",X"FF",X"77",X"FF",X"FF",X"FF",
|
||||
X"88",X"00",X"CC",X"00",X"EE",X"00",X"FF",X"00",X"FF",X"88",X"FF",X"CC",X"FF",X"EE",X"FF",X"FF",
|
||||
X"FF",X"FF",X"77",X"FF",X"33",X"FF",X"11",X"FF",X"00",X"FF",X"00",X"77",X"00",X"33",X"00",X"11",
|
||||
X"FF",X"FF",X"FF",X"EE",X"FF",X"CC",X"FF",X"88",X"FF",X"00",X"EE",X"00",X"CC",X"00",X"88",X"00",
|
||||
X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",X"F0",
|
||||
X"33",X"00",X"33",X"00",X"33",X"00",X"11",X"00",X"11",X"00",X"00",X"00",X"33",X"00",X"00",X"00",
|
||||
X"00",X"00",X"22",X"88",X"22",X"88",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"22",X"88",X"22",X"88",X"FF",X"EE",X"22",X"88",X"FF",X"EE",X"22",X"88",X"22",X"88",X"00",X"00",
|
||||
X"11",X"00",X"F7",X"EC",X"D9",X"00",X"F7",X"EC",X"11",X"62",X"F7",X"EC",X"11",X"00",X"00",X"00",
|
||||
X"E4",X"22",X"AA",X"44",X"E4",X"88",X"11",X"00",X"22",X"E4",X"44",X"AA",X"88",X"E4",X"00",X"00",
|
||||
X"72",X"00",X"55",X"00",X"22",X"00",X"75",X"00",X"98",X"AA",X"C8",X"C4",X"77",X"AA",X"00",X"00",
|
||||
X"11",X"88",X"10",X"88",X"00",X"88",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"88",X"11",X"00",X"22",X"00",X"22",X"00",X"22",X"00",X"11",X"00",X"00",X"88",X"00",X"00",
|
||||
X"11",X"00",X"00",X"88",X"00",X"44",X"00",X"44",X"00",X"44",X"00",X"88",X"11",X"00",X"00",X"00",
|
||||
X"00",X"00",X"11",X"00",X"55",X"44",X"22",X"88",X"22",X"88",X"55",X"44",X"11",X"00",X"00",X"00",
|
||||
X"00",X"00",X"11",X"00",X"11",X"00",X"77",X"CC",X"11",X"00",X"11",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"11",X"88",X"00",X"88",X"11",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"77",X"CC",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"33",X"00",X"33",X"00",X"00",X"00",
|
||||
X"00",X"11",X"00",X"32",X"00",X"64",X"00",X"C8",X"11",X"80",X"32",X"00",X"64",X"00",X"C8",X"00",
|
||||
X"33",X"88",X"66",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"66",X"CC",X"33",X"88",X"00",X"00",
|
||||
X"11",X"88",X"33",X"88",X"77",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"77",X"EE",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"00",X"EE",X"33",X"CC",X"77",X"88",X"EE",X"00",X"FF",X"EE",X"00",X"00",
|
||||
X"77",X"EE",X"00",X"CC",X"11",X"88",X"33",X"CC",X"00",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"11",X"CC",X"33",X"CC",X"66",X"CC",X"CC",X"CC",X"FF",X"EE",X"00",X"CC",X"00",X"CC",X"00",X"00",
|
||||
X"FF",X"CC",X"CC",X"00",X"FF",X"CC",X"00",X"66",X"00",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"33",X"CC",X"66",X"00",X"CC",X"00",X"FF",X"CC",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"FF",X"EE",X"CC",X"66",X"00",X"CC",X"11",X"88",X"33",X"00",X"33",X"00",X"33",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"CC",X"66",X"77",X"EE",X"00",X"66",X"00",X"CC",X"77",X"88",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"11",X"88",X"11",X"88",X"00",X"00",X"11",X"88",X"11",X"88",X"00",X"00",
|
||||
X"11",X"00",X"33",X"00",X"77",X"EE",X"FF",X"EE",X"77",X"EE",X"33",X"00",X"11",X"00",X"00",X"00",
|
||||
X"00",X"44",X"00",X"88",X"11",X"00",X"22",X"00",X"11",X"00",X"00",X"88",X"00",X"44",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"77",X"CC",X"00",X"00",X"77",X"CC",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"22",X"00",X"11",X"00",X"00",X"88",X"00",X"44",X"00",X"88",X"11",X"00",X"22",X"00",X"00",X"00",
|
||||
X"33",X"CC",X"66",X"66",X"66",X"66",X"00",X"CC",X"11",X"88",X"11",X"88",X"00",X"00",X"11",X"88",
|
||||
X"33",X"CC",X"44",X"22",X"99",X"99",X"AA",X"11",X"AA",X"11",X"99",X"99",X"44",X"22",X"33",X"CC",
|
||||
X"33",X"88",X"66",X"CC",X"CC",X"66",X"CC",X"66",X"FF",X"EE",X"CC",X"66",X"CC",X"66",X"00",X"00",
|
||||
X"FF",X"CC",X"CC",X"66",X"CC",X"66",X"FF",X"CC",X"CC",X"66",X"CC",X"66",X"FF",X"CC",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"CC",X"00",X"CC",X"00",X"CC",X"00",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"FF",X"88",X"CC",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"CC",X"FF",X"88",X"00",X"00",
|
||||
X"FF",X"EE",X"CC",X"00",X"CC",X"00",X"FF",X"88",X"CC",X"00",X"CC",X"00",X"FF",X"EE",X"00",X"00",
|
||||
X"FF",X"EE",X"CC",X"00",X"CC",X"00",X"FF",X"88",X"CC",X"00",X"CC",X"00",X"CC",X"00",X"00",X"00",
|
||||
X"33",X"EE",X"66",X"00",X"CC",X"00",X"CC",X"EE",X"CC",X"66",X"66",X"66",X"33",X"EE",X"00",X"00",
|
||||
X"CC",X"66",X"CC",X"66",X"CC",X"66",X"FF",X"EE",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"00",X"00",
|
||||
X"77",X"EE",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"77",X"EE",X"00",X"00",
|
||||
X"00",X"66",X"00",X"66",X"00",X"66",X"00",X"66",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"CC",X"66",X"CC",X"CC",X"DD",X"88",X"FF",X"00",X"FF",X"88",X"CC",X"CC",X"CC",X"66",X"00",X"00",
|
||||
X"66",X"00",X"66",X"00",X"66",X"00",X"66",X"00",X"66",X"00",X"66",X"00",X"77",X"EE",X"00",X"00",
|
||||
X"CC",X"66",X"EE",X"EE",X"FF",X"EE",X"FF",X"EE",X"DD",X"66",X"CC",X"66",X"CC",X"66",X"00",X"00",
|
||||
X"CC",X"66",X"EE",X"66",X"FF",X"66",X"FF",X"EE",X"DD",X"EE",X"CC",X"EE",X"CC",X"66",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"FF",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"FF",X"CC",X"CC",X"00",X"CC",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"DD",X"EE",X"CC",X"CC",X"77",X"AA",X"00",X"00",
|
||||
X"FF",X"CC",X"CC",X"66",X"CC",X"66",X"CC",X"CC",X"FF",X"88",X"DD",X"CC",X"CC",X"EE",X"00",X"00",
|
||||
X"77",X"88",X"CC",X"C4",X"CC",X"00",X"77",X"CC",X"00",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"77",X"EE",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"00",X"00",
|
||||
X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"CC",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"CC",X"66",X"CC",X"66",X"CC",X"66",X"EE",X"EE",X"77",X"CC",X"33",X"88",X"11",X"00",X"00",X"00",
|
||||
X"CC",X"66",X"CC",X"66",X"DD",X"66",X"FF",X"EE",X"FF",X"EE",X"EE",X"EE",X"CC",X"66",X"00",X"00",
|
||||
X"CC",X"66",X"EE",X"EE",X"77",X"CC",X"33",X"88",X"77",X"CC",X"EE",X"EE",X"CC",X"66",X"00",X"00",
|
||||
X"66",X"66",X"66",X"66",X"66",X"66",X"33",X"CC",X"11",X"88",X"11",X"88",X"11",X"88",X"00",X"00",
|
||||
X"FF",X"EE",X"00",X"EE",X"11",X"CC",X"33",X"88",X"77",X"00",X"EE",X"00",X"FF",X"EE",X"00",X"00",
|
||||
X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",
|
||||
X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",
|
||||
X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",
|
||||
X"0F",X"0F",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"0F",X"0F",
|
||||
X"44",X"00",X"44",X"44",X"44",X"88",X"55",X"66",X"22",X"99",X"44",X"22",X"00",X"44",X"00",X"FF",
|
||||
X"00",X"00",X"00",X"00",X"33",X"EE",X"66",X"66",X"66",X"66",X"66",X"EE",X"33",X"66",X"00",X"00",
|
||||
X"66",X"00",X"66",X"00",X"77",X"CC",X"66",X"66",X"66",X"66",X"66",X"66",X"77",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"33",X"CC",X"66",X"66",X"66",X"00",X"66",X"66",X"33",X"CC",X"00",X"00",
|
||||
X"00",X"66",X"00",X"66",X"33",X"EE",X"66",X"66",X"66",X"66",X"66",X"66",X"33",X"EE",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"33",X"CC",X"66",X"66",X"77",X"EE",X"66",X"00",X"33",X"CC",X"00",X"00",
|
||||
X"11",X"CC",X"33",X"66",X"33",X"00",X"77",X"CC",X"33",X"00",X"33",X"00",X"33",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"33",X"EE",X"66",X"66",X"66",X"66",X"33",X"EE",X"00",X"66",X"33",X"CC",
|
||||
X"66",X"00",X"66",X"00",X"77",X"CC",X"66",X"66",X"66",X"66",X"66",X"66",X"66",X"66",X"00",X"00",
|
||||
X"11",X"88",X"00",X"00",X"33",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"33",X"CC",X"00",X"00",
|
||||
X"00",X"CC",X"00",X"00",X"11",X"CC",X"00",X"CC",X"00",X"CC",X"00",X"CC",X"44",X"CC",X"33",X"88",
|
||||
X"66",X"00",X"66",X"66",X"66",X"CC",X"77",X"88",X"77",X"88",X"66",X"CC",X"66",X"66",X"00",X"00",
|
||||
X"33",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"11",X"88",X"33",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"FF",X"CC",X"DD",X"66",X"DD",X"66",X"DD",X"66",X"DD",X"66",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"77",X"CC",X"66",X"66",X"66",X"66",X"66",X"66",X"66",X"66",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"33",X"CC",X"66",X"66",X"66",X"66",X"66",X"66",X"33",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"77",X"CC",X"66",X"66",X"66",X"66",X"77",X"CC",X"66",X"00",X"66",X"00",
|
||||
X"00",X"00",X"00",X"00",X"77",X"CC",X"CC",X"CC",X"CC",X"CC",X"77",X"CC",X"00",X"CC",X"00",X"EE",
|
||||
X"00",X"00",X"00",X"00",X"77",X"CC",X"76",X"62",X"66",X"00",X"66",X"00",X"66",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"73",X"CC",X"66",X"00",X"73",X"EC",X"00",X"66",X"77",X"EC",X"00",X"00",
|
||||
X"11",X"88",X"11",X"88",X"77",X"EE",X"11",X"88",X"11",X"88",X"11",X"88",X"00",X"EE",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"66",X"66",X"66",X"66",X"66",X"66",X"66",X"EE",X"33",X"66",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"66",X"66",X"66",X"66",X"66",X"66",X"33",X"CC",X"11",X"88",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"DD",X"66",X"DD",X"66",X"DD",X"66",X"DD",X"66",X"76",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"CC",X"CC",X"77",X"88",X"33",X"00",X"77",X"88",X"CC",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"66",X"66",X"66",X"66",X"66",X"66",X"33",X"EE",X"00",X"66",X"33",X"CC",
|
||||
X"00",X"00",X"00",X"00",X"77",X"EE",X"00",X"CC",X"11",X"88",X"33",X"00",X"77",X"EE",X"00",X"00",
|
||||
X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",
|
||||
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",
|
||||
X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"01",
|
||||
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
|
||||
X"00",X"72",X"00",X"F6",X"10",X"BA",X"77",X"FE",X"72",X"32",X"E4",X"32",X"C8",X"32",X"00",X"00",
|
||||
X"F7",X"88",X"C4",X"88",X"F7",X"EC",X"C4",X"62",X"C4",X"62",X"C4",X"E4",X"F7",X"C8",X"00",X"00",
|
||||
X"31",X"EE",X"72",X"00",X"E4",X"00",X"C4",X"00",X"E4",X"00",X"72",X"00",X"31",X"EE",X"00",X"00",
|
||||
X"F7",X"C8",X"C4",X"E4",X"C4",X"72",X"C4",X"32",X"C4",X"72",X"C4",X"E4",X"F7",X"C8",X"00",X"00",
|
||||
X"F7",X"88",X"C4",X"00",X"F7",X"00",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"F7",X"EE",X"00",X"00",
|
||||
X"F7",X"EE",X"C4",X"00",X"F7",X"88",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"00",X"00",
|
||||
X"31",X"EE",X"72",X"00",X"E4",X"00",X"C4",X"00",X"E4",X"66",X"72",X"62",X"31",X"EC",X"00",X"00",
|
||||
X"C4",X"62",X"C4",X"62",X"F7",X"EE",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"00",X"00",
|
||||
X"73",X"EE",X"10",X"88",X"10",X"88",X"10",X"88",X"10",X"88",X"10",X"88",X"73",X"EE",X"00",X"00",
|
||||
X"00",X"62",X"00",X"62",X"00",X"62",X"00",X"62",X"00",X"62",X"C4",X"62",X"73",X"EC",X"00",X"00",
|
||||
X"D4",X"88",X"F5",X"80",X"F6",X"00",X"F5",X"80",X"D4",X"C8",X"C4",X"E4",X"C4",X"62",X"00",X"00",
|
||||
X"C4",X"00",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"C4",X"00",X"F7",X"EE",X"00",X"00",
|
||||
X"E4",X"62",X"F6",X"E6",X"D5",X"EA",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"00",X"00",
|
||||
X"C4",X"62",X"E6",X"62",X"F7",X"62",X"D5",X"EA",X"C4",X"EE",X"C4",X"66",X"C4",X"22",X"00",X"00",
|
||||
X"31",X"CC",X"62",X"62",X"C4",X"31",X"C4",X"31",X"C4",X"31",X"62",X"62",X"31",X"CC",X"00",X"00",
|
||||
X"F7",X"88",X"C4",X"C4",X"C4",X"62",X"C4",X"62",X"C4",X"C4",X"F7",X"88",X"C4",X"00",X"00",X"00",
|
||||
X"31",X"CC",X"62",X"62",X"C4",X"31",X"C4",X"31",X"C4",X"F5",X"62",X"62",X"31",X"F9",X"00",X"00",
|
||||
X"F7",X"88",X"C4",X"C4",X"C4",X"62",X"C4",X"62",X"C4",X"C4",X"F7",X"88",X"C4",X"E6",X"00",X"00",
|
||||
X"73",X"88",X"C4",X"00",X"73",X"C8",X"00",X"64",X"00",X"62",X"00",X"64",X"F7",X"C8",X"00",X"00",
|
||||
X"F7",X"FF",X"10",X"88",X"10",X"88",X"10",X"88",X"10",X"88",X"10",X"88",X"10",X"88",X"00",X"00",
|
||||
X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"73",X"CC",X"00",X"00",
|
||||
X"C4",X"31",X"C4",X"72",X"C4",X"E4",X"D4",X"C8",X"F5",X"80",X"F6",X"00",X"E4",X"00",X"00",X"00",
|
||||
X"C4",X"62",X"C4",X"62",X"C4",X"62",X"C4",X"62",X"D5",X"EA",X"F6",X"E6",X"E4",X"62",X"00",X"00",
|
||||
X"E4",X"31",X"72",X"72",X"31",X"E4",X"10",X"C8",X"31",X"E4",X"72",X"72",X"E4",X"31",X"00",X"00",
|
||||
X"E4",X"31",X"72",X"72",X"31",X"E4",X"10",X"C8",X"31",X"80",X"72",X"00",X"E4",X"00",X"00",X"00",
|
||||
X"FF",X"EE",X"00",X"E4",X"10",X"C8",X"31",X"80",X"72",X"00",X"E4",X"00",X"FF",X"EE",X"00",X"00",
|
||||
X"00",X"01",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"22",X"00",X"31",X"00",X"72",X"00",X"31",X"80",X"10",X"C8",X"11",X"80",X"00",X"C8",X"00",X"44",
|
||||
X"11",X"00",X"33",X"88",X"77",X"CC",X"FF",X"EE",X"77",X"CC",X"33",X"88",X"11",X"00",X"00",X"00",
|
||||
X"FF",X"EE",X"88",X"22",X"BB",X"AA",X"BB",X"AA",X"BB",X"AA",X"88",X"22",X"FF",X"EE",X"00",X"00",
|
||||
X"FA",X"FA",X"F5",X"F5",X"FA",X"FA",X"F5",X"F5",X"FA",X"FA",X"F5",X"F5",X"FA",X"FA",X"F5",X"F5",
|
||||
X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",X"0F",
|
||||
X"03",X"0C",X"02",X"04",X"03",X"0C",X"01",X"08",X"01",X"08",X"01",X"0E",X"01",X"08",X"01",X"0E",
|
||||
X"00",X"11",X"00",X"32",X"00",X"64",X"04",X"C8",X"13",X"80",X"21",X"00",X"42",X"08",X"84",X"00",
|
||||
X"11",X"84",X"11",X"84",X"11",X"84",X"32",X"C2",X"74",X"E1",X"74",X"E1",X"32",X"C3",X"03",X"0E",
|
||||
X"00",X"00",X"99",X"77",X"99",X"44",X"FF",X"77",X"99",X"44",X"99",X"44",X"99",X"77",X"00",X"00",
|
||||
X"00",X"00",X"9B",X"99",X"22",X"55",X"22",X"55",X"33",X"DD",X"22",X"55",X"AA",X"55",X"00",X"00",
|
||||
X"00",X"00",X"11",X"FF",X"00",X"44",X"00",X"44",X"00",X"44",X"00",X"44",X"EE",X"44",X"00",X"00",
|
||||
X"00",X"00",X"44",X"88",X"44",X"88",X"77",X"88",X"44",X"88",X"44",X"88",X"44",X"88",X"00",X"00",
|
||||
X"00",X"00",X"F7",X"33",X"88",X"44",X"F6",X"44",X"11",X"44",X"11",X"44",X"EE",X"33",X"00",X"00",
|
||||
X"00",X"00",X"9B",X"9D",X"22",X"55",X"22",X"55",X"22",X"55",X"22",X"55",X"9B",X"9D",X"00",X"00",
|
||||
X"00",X"00",X"EC",X"FF",X"22",X"88",X"E4",X"EE",X"88",X"88",X"44",X"88",X"22",X"FF",X"00",X"00",
|
||||
X"00",X"00",X"88",X"9B",X"88",X"AA",X"88",X"AA",X"AA",X"BB",X"AA",X"AA",X"55",X"22",X"00",X"00",
|
||||
X"00",X"00",X"99",X"EC",X"55",X"22",X"55",X"E4",X"DD",X"88",X"55",X"44",X"55",X"22",X"00",X"00",
|
||||
X"00",X"00",X"FE",X"45",X"99",X"55",X"FA",X"55",X"CC",X"55",X"AA",X"55",X"99",X"45",X"00",X"00",
|
||||
X"00",X"00",X"CE",X"FE",X"22",X"99",X"22",X"FA",X"22",X"CC",X"22",X"AA",X"CE",X"99",X"00",X"00",
|
||||
X"00",X"00",X"88",X"99",X"88",X"AA",X"88",X"AA",X"88",X"BB",X"55",X"22",X"22",X"22",X"00",X"00",
|
||||
X"00",X"00",X"99",X"00",X"55",X"00",X"55",X"00",X"DD",X"00",X"55",X"00",X"55",X"EE",X"00",X"00",
|
||||
X"00",X"00",X"88",X"44",X"99",X"44",X"AA",X"22",X"CC",X"11",X"AA",X"11",X"99",X"11",X"00",X"00",
|
||||
X"00",X"00",X"55",X"EC",X"55",X"22",X"99",X"E4",X"11",X"88",X"11",X"44",X"11",X"22",X"00",X"00",
|
||||
X"00",X"00",X"BB",X"CC",X"AA",X"00",X"BB",X"88",X"AA",X"00",X"AA",X"00",X"BB",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"88",X"AA",X"88",X"AA",X"88",X"AA",X"AA",X"AA",X"AA",X"AA",X"55",X"22",X"00",X"00",
|
||||
X"00",X"00",X"FF",X"33",X"11",X"44",X"22",X"44",X"44",X"77",X"88",X"44",X"FF",X"44",X"00",X"00",
|
||||
X"00",X"00",X"33",X"D9",X"AA",X"55",X"BA",X"D9",X"BB",X"11",X"AA",X"99",X"AA",X"55",X"00",X"00",
|
||||
X"00",X"00",X"CC",X"00",X"26",X"00",X"22",X"00",X"22",X"00",X"26",X"00",X"CC",X"00",X"00",X"00",
|
||||
X"00",X"00",X"FF",X"44",X"88",X"44",X"EE",X"44",X"88",X"44",X"88",X"44",X"FF",X"77",X"00",X"00",
|
||||
X"00",X"00",X"33",X"CC",X"22",X"00",X"33",X"88",X"22",X"00",X"22",X"00",X"AA",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"70",X"10",X"F7",X"31",X"FC",X"73",X"C8",X"73",X"90",X"73",X"80",X"73",X"F0",
|
||||
X"00",X"00",X"F0",X"00",X"FF",X"F0",X"F7",X"F7",X"F6",X"71",X"EC",X"31",X"C0",X"73",X"F0",X"73",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"F0",X"FF",X"FF",X"FF",X"B9",X"F9",X"FB",X"B1",X"FB",X"F1",X"FB",
|
||||
X"00",X"00",X"00",X"00",X"B0",X"E0",X"FB",X"FC",X"B8",X"EC",X"90",X"EC",X"90",X"EC",X"90",X"EC",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"C0",X"FF",X"FC",X"F6",X"F7",X"F6",X"73",X"F6",X"31",X"F6",X"31",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"F0",X"FF",X"FF",X"E6",X"F6",X"EA",X"F6",X"F9",X"F6",X"D8",X"F6",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"70",X"FF",X"FF",X"76",X"F6",X"64",X"F6",X"C8",X"F6",X"80",X"F6",
|
||||
X"00",X"00",X"00",X"00",X"B0",X"F0",X"FB",X"FF",X"B0",X"FC",X"10",X"EC",X"10",X"EC",X"10",X"FC",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"F0",X"FF",X"FF",X"F0",X"F3",X"20",X"73",X"72",X"73",X"F6",X"73",
|
||||
X"00",X"00",X"00",X"00",X"F0",X"E0",X"FF",X"EC",X"F0",X"EC",X"90",X"C8",X"B1",X"80",X"B0",X"00",
|
||||
X"73",X"FF",X"73",X"F0",X"73",X"80",X"73",X"F8",X"31",X"FF",X"10",X"FF",X"00",X"F0",X"00",X"00",
|
||||
X"FF",X"F7",X"F3",X"F6",X"73",X"F6",X"F3",X"F6",X"FF",X"F6",X"FF",X"F6",X"F3",X"F6",X"73",X"F6",
|
||||
X"FF",X"FB",X"F1",X"FB",X"31",X"FB",X"31",X"FB",X"31",X"FB",X"31",X"F9",X"31",X"D8",X"73",X"80",
|
||||
X"90",X"EC",X"90",X"EC",X"90",X"EC",X"90",X"EC",X"F9",X"FC",X"FE",X"FF",X"EC",X"F6",X"C0",X"60",
|
||||
X"F6",X"31",X"F6",X"31",X"F6",X"31",X"F6",X"B1",X"FE",X"F9",X"F7",X"F9",X"F7",X"B0",X"F6",X"00",
|
||||
X"C8",X"F6",X"C8",X"F6",X"C8",X"F6",X"C8",X"F6",X"C8",X"F6",X"C8",X"F6",X"C0",X"F0",X"00",X"00",
|
||||
X"00",X"F6",X"00",X"F6",X"00",X"F6",X"00",X"F6",X"30",X"F6",X"31",X"FF",X"30",X"F0",X"00",X"00",
|
||||
X"10",X"FF",X"30",X"FD",X"72",X"FD",X"F6",X"FC",X"FC",X"FC",X"FC",X"FF",X"D0",X"F0",X"00",X"00",
|
||||
X"EC",X"73",X"C8",X"73",X"90",X"F7",X"31",X"FB",X"F3",X"F3",X"FF",X"F3",X"F0",X"73",X"00",X"73",
|
||||
X"80",X"00",X"80",X"00",X"80",X"00",X"80",X"00",X"80",X"00",X"B0",X"00",X"F2",X"00",X"F6",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"10",X"00",X"31",X"00",X"31",X"00",X"30",
|
||||
X"73",X"E4",X"73",X"C0",X"73",X"80",X"F6",X"00",X"EC",X"00",X"C8",X"00",X"80",X"00",X"00",X"00",
|
||||
X"72",X"00",X"60",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"10",X"00",X"10",X"00",X"10",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"EC",X"00",X"C8",X"00",X"80",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"73",X"00",X"73",X"00",X"73",X"00",X"F6",X"10",X"EC",X"31",X"C8",X"31",X"80",X"30",X"00",
|
||||
X"EC",X"00",X"C8",X"00",X"80",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"66",X"33",X"77",X"77",X"33",X"EE",X"11",X"CC",X"33",X"EE",X"77",X"77",X"66",X"33",X"00",X"00",
|
||||
X"00",X"00",X"00",X"77",X"00",X"FF",X"77",X"88",X"77",X"88",X"00",X"FF",X"00",X"77",X"00",X"00",
|
||||
X"66",X"11",X"77",X"11",X"77",X"99",X"55",X"DD",X"44",X"FF",X"44",X"77",X"44",X"33",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
|
||||
X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",
|
||||
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",
|
||||
X"08",X"00",X"08",X"00",X"08",X"00",X"08",X"00",X"08",X"00",X"08",X"00",X"08",X"00",X"08",X"00",
|
||||
X"00",X"00",X"22",X"FF",X"11",X"00",X"00",X"88",X"99",X"44",X"CC",X"AA",X"AA",X"88",X"99",X"00",
|
||||
X"00",X"00",X"33",X"88",X"77",X"CC",X"44",X"44",X"22",X"44",X"77",X"CC",X"77",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"77",X"FF",X"77",X"FF",X"44",X"44",X"44",X"44",X"77",X"CC",X"33",X"88",X"00",X"00",
|
||||
X"00",X"00",X"33",X"88",X"77",X"CC",X"44",X"44",X"44",X"44",X"66",X"CC",X"22",X"88",X"00",X"00",
|
||||
X"00",X"00",X"33",X"88",X"77",X"CC",X"44",X"44",X"44",X"44",X"77",X"FF",X"77",X"FF",X"00",X"00",
|
||||
X"00",X"00",X"33",X"88",X"77",X"CC",X"55",X"44",X"55",X"44",X"55",X"CC",X"11",X"88",X"00",X"00",
|
||||
X"00",X"00",X"00",X"88",X"77",X"EE",X"77",X"FF",X"00",X"99",X"00",X"BB",X"00",X"22",X"00",X"00",
|
||||
X"00",X"00",X"11",X"88",X"BB",X"CC",X"AA",X"44",X"AA",X"44",X"FF",X"CC",X"77",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"77",X"FF",X"77",X"FF",X"00",X"44",X"00",X"44",X"77",X"CC",X"77",X"88",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"44",X"44",X"77",X"DD",X"77",X"DD",X"44",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"44",X"00",X"88",X"00",X"88",X"44",X"FF",X"DD",X"77",X"DD",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"77",X"FF",X"77",X"FF",X"11",X"88",X"33",X"CC",X"66",X"66",X"44",X"22",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"44",X"11",X"77",X"FF",X"77",X"FF",X"44",X"00",X"00",X"00",X"00",X"00",
|
||||
X"77",X"CC",X"77",X"CC",X"00",X"44",X"77",X"CC",X"00",X"44",X"77",X"CC",X"77",X"88",X"00",X"00",
|
||||
X"00",X"00",X"77",X"CC",X"77",X"CC",X"00",X"44",X"00",X"44",X"77",X"CC",X"77",X"88",X"00",X"00",
|
||||
X"00",X"00",X"33",X"88",X"77",X"CC",X"44",X"44",X"44",X"44",X"77",X"CC",X"33",X"88",X"00",X"00",
|
||||
X"00",X"00",X"FF",X"CC",X"FF",X"CC",X"22",X"44",X"22",X"44",X"33",X"CC",X"11",X"88",X"00",X"00",
|
||||
X"11",X"88",X"33",X"CC",X"22",X"44",X"22",X"44",X"FF",X"CC",X"FF",X"CC",X"88",X"00",X"00",X"00",
|
||||
X"00",X"00",X"77",X"CC",X"77",X"CC",X"00",X"C4",X"00",X"44",X"00",X"44",X"00",X"C8",X"00",X"00",
|
||||
X"00",X"00",X"54",X"C8",X"55",X"CC",X"55",X"44",X"55",X"44",X"77",X"44",X"72",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"44",X"00",X"44",X"33",X"FF",X"77",X"FF",X"44",X"44",X"44",X"44",X"00",X"00",
|
||||
X"00",X"00",X"33",X"CC",X"77",X"CC",X"44",X"00",X"22",X"00",X"77",X"CC",X"77",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"11",X"CC",X"33",X"CC",X"66",X"00",X"66",X"00",X"33",X"CC",X"11",X"CC",X"00",X"00",
|
||||
X"33",X"CC",X"77",X"CC",X"44",X"00",X"73",X"CC",X"44",X"00",X"77",X"CC",X"33",X"CC",X"00",X"00",
|
||||
X"44",X"44",X"66",X"CC",X"33",X"88",X"33",X"88",X"66",X"CC",X"44",X"44",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"11",X"CC",X"BB",X"CC",X"AA",X"00",X"AA",X"00",X"FF",X"CC",X"77",X"CC",X"00",X"00",
|
||||
X"00",X"00",X"44",X"44",X"66",X"44",X"77",X"44",X"55",X"CC",X"44",X"CC",X"44",X"44",X"00",X"00",
|
||||
X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",
|
||||
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",
|
||||
X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"FF",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"08",X"00",
|
||||
X"00",X"07",X"00",X"7B",X"01",X"F6",X"12",X"ED",X"13",X"CE",X"13",X"CA",X"13",X"8C",X"13",X"8C",
|
||||
X"0F",X"08",X"FF",X"84",X"3D",X"CA",X"12",X"ED",X"01",X"EF",X"01",X"E7",X"00",X"6F",X"00",X"6F",
|
||||
X"13",X"8C",X"13",X"8C",X"13",X"CA",X"13",X"CE",X"12",X"ED",X"01",X"F6",X"00",X"7B",X"00",X"07",
|
||||
X"00",X"6F",X"00",X"6F",X"01",X"E7",X"01",X"EF",X"12",X"ED",X"3D",X"CA",X"FF",X"84",X"0F",X"08",
|
||||
X"00",X"00",X"00",X"00",X"00",X"01",X"00",X"13",X"00",X"37",X"00",X"07",X"00",X"01",X"00",X"01",
|
||||
X"06",X"00",X"4E",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",
|
||||
X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"16",X"00",X"7F",X"00",X"0F",
|
||||
X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"ED",X"08",X"FF",X"8C",X"0F",X"0C",
|
||||
X"00",X"07",X"00",X"7F",X"01",X"ED",X"13",X"CA",X"13",X"8C",X"01",X"08",X"00",X"00",X"00",X"01",
|
||||
X"0F",X"00",X"FE",X"08",X"3F",X"8C",X"13",X"CE",X"12",X"CE",X"13",X"CE",X"37",X"8C",X"7F",X"08",
|
||||
X"00",X"16",X"00",X"7B",X"01",X"F6",X"12",X"CF",X"13",X"8C",X"13",X"CB",X"13",X"FF",X"03",X"0F",
|
||||
X"ED",X"00",X"CA",X"00",X"0C",X"06",X"00",X"4E",X"00",X"4E",X"0F",X"C6",X"FF",X"CE",X"0F",X"0E",
|
||||
X"00",X"07",X"00",X"7F",X"01",X"ED",X"13",X"CA",X"13",X"8C",X"01",X"08",X"00",X"01",X"00",X"13",
|
||||
X"0F",X"00",X"FF",X"08",X"3D",X"8C",X"12",X"CE",X"01",X"CE",X"01",X"CE",X"1F",X"8C",X"FF",X"08",
|
||||
X"00",X"01",X"00",X"00",X"01",X"08",X"13",X"8C",X"13",X"8C",X"01",X"CF",X"00",X"7F",X"00",X"07",
|
||||
X"1F",X"8C",X"01",X"CE",X"00",X"6F",X"00",X"6F",X"01",X"E7",X"1E",X"CE",X"FF",X"8C",X"0F",X"08",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"01",X"00",X"13",X"00",X"37",X"00",X"6F",X"01",X"CE",
|
||||
X"03",X"08",X"37",X"08",X"7F",X"08",X"FF",X"08",X"BF",X"08",X"3F",X"08",X"37",X"08",X"37",X"08",
|
||||
X"13",X"8C",X"37",X"0F",X"37",X"FF",X"07",X"0F",X"00",X"00",X"00",X"00",X"00",X"01",X"00",X"01",
|
||||
X"37",X"08",X"3F",X"0C",X"FF",X"8C",X"3F",X"0C",X"37",X"08",X"7B",X"84",X"FF",X"CE",X"0F",X"0E",
|
||||
X"03",X"0F",X"13",X"FF",X"13",X"8F",X"13",X"8C",X"13",X"8C",X"13",X"8F",X"13",X"FB",X"13",X"ED",
|
||||
X"0F",X"0C",X"FF",X"8C",X"1E",X"8C",X"01",X"8C",X"00",X"0C",X"0E",X"00",X"FE",X"08",X"3F",X"8C",
|
||||
X"01",X"0C",X"00",X"00",X"03",X"08",X"13",X"8C",X"13",X"CA",X"01",X"ED",X"00",X"7F",X"00",X"07",
|
||||
X"13",X"CA",X"10",X"CE",X"01",X"CE",X"01",X"CE",X"13",X"CA",X"3F",X"84",X"EF",X"08",X"0E",X"00",
|
||||
X"00",X"07",X"00",X"7F",X"01",X"CF",X"12",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8F",X"13",X"FB",
|
||||
X"0F",X"00",X"FF",X"08",X"1F",X"8C",X"01",X"CA",X"01",X"CE",X"00",X"0C",X"0F",X"00",X"FF",X"08",
|
||||
X"13",X"ED",X"13",X"8E",X"13",X"8C",X"13",X"8C",X"12",X"CA",X"01",X"ED",X"00",X"7F",X"00",X"07",
|
||||
X"1F",X"8C",X"10",X"CE",X"01",X"CE",X"01",X"CE",X"03",X"CA",X"1F",X"8C",X"FF",X"08",X"0F",X"00",
|
||||
X"03",X"0F",X"13",X"FF",X"13",X"87",X"13",X"08",X"13",X"08",X"03",X"00",X"00",X"00",X"00",X"01",
|
||||
X"0F",X"0F",X"FF",X"EF",X"0F",X"6F",X"01",X"E7",X"12",X"CE",X"35",X"8C",X"7B",X"08",X"E7",X"00",
|
||||
X"00",X"01",X"00",X"12",X"00",X"13",X"00",X"13",X"00",X"13",X"00",X"13",X"00",X"13",X"00",X"03",
|
||||
X"CE",X"00",X"CA",X"00",X"8C",X"00",X"8C",X"00",X"8C",X"00",X"8C",X"00",X"8C",X"00",X"0C",X"00",
|
||||
X"00",X"07",X"00",X"7B",X"01",X"E7",X"01",X"CF",X"01",X"CE",X"01",X"ED",X"00",X"7F",X"00",X"37",
|
||||
X"0F",X"08",X"FF",X"84",X"3D",X"CA",X"12",X"CE",X"01",X"CE",X"01",X"CE",X"1E",X"CA",X"FF",X"84",
|
||||
X"00",X"7A",X"01",X"C7",X"12",X"8C",X"13",X"8C",X"13",X"CA",X"12",X"ED",X"01",X"F7",X"00",X"0F",
|
||||
X"F7",X"8C",X"3D",X"CE",X"03",X"E7",X"00",X"6F",X"00",X"6F",X"1E",X"ED",X"FF",X"CA",X"0F",X"0C",
|
||||
X"00",X"07",X"00",X"7F",X"01",X"CF",X"12",X"8E",X"13",X"8C",X"13",X"8C",X"13",X"C8",X"01",X"CF",
|
||||
X"0F",X"00",X"FF",X"08",X"3D",X"8C",X"12",X"CA",X"01",X"CE",X"01",X"CE",X"03",X"CE",X"3D",X"CE",
|
||||
X"00",X"7F",X"00",X"07",X"01",X"08",X"13",X"8C",X"12",X"8C",X"01",X"CF",X"00",X"7F",X"00",X"07",
|
||||
X"FE",X"CE",X"0F",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CA",X"1F",X"8C",X"FF",X"08",X"0F",X"00",
|
||||
X"00",X"0F",X"00",X"7F",X"00",X"35",X"00",X"36",X"00",X"6B",X"00",X"6D",X"00",X"4E",X"01",X"C6",
|
||||
X"0E",X"00",X"CE",X"00",X"ED",X"00",X"EF",X"00",X"E7",X"00",X"7E",X"08",X"7F",X"08",X"73",X"08",
|
||||
X"01",X"CB",X"01",X"FF",X"12",X"8F",X"13",X"84",X"13",X"08",X"35",X"84",X"37",X"CE",X"07",X"0E",
|
||||
X"3F",X"84",X"FF",X"8C",X"3D",X"8C",X"13",X"CA",X"13",X"CE",X"12",X"ED",X"37",X"EF",X"07",X"0F",
|
||||
X"07",X"0F",X"37",X"FF",X"12",X"ED",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CF",X"01",X"FF",
|
||||
X"01",X"CF",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"12",X"ED",X"37",X"FF",X"07",X"0F",
|
||||
X"3D",X"CA",X"03",X"ED",X"00",X"6F",X"00",X"6F",X"00",X"6F",X"0F",X"ED",X"FF",X"CA",X"0F",X"0C",
|
||||
X"0F",X"0E",X"FF",X"C6",X"3D",X"CE",X"12",X"CE",X"01",X"C6",X"00",X"0E",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"02",X"00",X"27",X"00",X"6F",X"1E",X"CF",X"FF",X"8E",X"0F",X"0C",
|
||||
X"07",X"0F",X"37",X"FF",X"12",X"ED",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",
|
||||
X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"12",X"ED",X"37",X"FF",X"07",X"0F",
|
||||
X"0F",X"0F",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"03",X"03",X"27",X"00",X"6B",X"00",X"EF",X"00",
|
||||
X"6B",X"00",X"27",X"00",X"03",X"00",X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"0F",X"0F",
|
||||
X"6B",X"00",X"27",X"00",X"03",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"08",X"00",X"08",X"00",
|
||||
X"07",X"0F",X"37",X"EF",X"12",X"ED",X"01",X"CE",X"01",X"CE",X"1E",X"ED",X"FF",X"EF",X"0F",X"0F",
|
||||
X"0F",X"0F",X"7F",X"EF",X"35",X"CA",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"1F",X"8C",X"FF",X"8C",
|
||||
X"1F",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"35",X"CA",X"7F",X"EF",X"0F",X"0F",
|
||||
X"00",X"0F",X"00",X"7F",X"00",X"16",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",
|
||||
X"0F",X"0C",X"FF",X"8C",X"ED",X"08",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",
|
||||
X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"ED",X"00",X"FF",X"8C",X"0F",X"0C",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"0F",X"0F",X"7F",X"EF",X"35",X"CA",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",
|
||||
X"00",X"00",X"00",X"00",X"03",X"08",X"13",X"8C",X"13",X"CA",X"01",X"ED",X"00",X"7F",X"00",X"07",
|
||||
X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"35",X"8C",X"7B",X"84",X"FE",X"08",X"0F",X"00",
|
||||
X"0F",X"0F",X"3F",X"EF",X"12",X"CA",X"13",X"84",X"36",X"08",X"6D",X"00",X"CA",X"00",X"CE",X"00",
|
||||
X"ED",X"00",X"E7",X"00",X"7E",X"08",X"7B",X"08",X"37",X"84",X"35",X"CA",X"7F",X"EF",X"0F",X"0F",
|
||||
X"08",X"00",X"08",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"06",X"00",X"4E",X"00",X"4E",X"0F",X"C6",X"FF",X"CE",X"0F",X"0E",
|
||||
X"0F",X"08",X"7F",X"8C",X"37",X"CA",X"37",X"CE",X"36",X"ED",X"27",X"EF",X"27",X"F6",X"27",X"7F",
|
||||
X"00",X"0F",X"01",X"EF",X"12",X"CE",X"13",X"CE",X"35",X"CE",X"36",X"CE",X"6B",X"CE",X"6D",X"CE",
|
||||
X"27",X"7B",X"27",X"37",X"27",X"35",X"27",X"13",X"27",X"12",X"7A",X"09",X"7F",X"08",X"0F",X"08",
|
||||
X"C7",X"CE",X"C9",X"CE",X"8D",X"CE",X"81",X"CE",X"09",X"CE",X"12",X"ED",X"13",X"EF",X"03",X"0F",
|
||||
X"07",X"0E",X"37",X"ED",X"12",X"EF",X"01",X"FE",X"01",X"FB",X"01",X"BF",X"01",X"BD",X"01",X"9F",
|
||||
X"07",X"0F",X"37",X"EF",X"03",X"CA",X"09",X"8C",X"09",X"8C",X"85",X"8C",X"8D",X"8C",X"CB",X"8C",
|
||||
X"01",X"9E",X"01",X"8D",X"01",X"8D",X"01",X"8C",X"01",X"8C",X"12",X"CA",X"37",X"EF",X"07",X"0F",
|
||||
X"CF",X"8C",X"ED",X"8C",X"E7",X"8C",X"7E",X"8C",X"7B",X"8C",X"37",X"8C",X"35",X"8C",X"03",X"0C",
|
||||
X"0F",X"08",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"08",X"00",X"08",X"00",
|
||||
X"06",X"6F",X"6F",X"6F",X"37",X"E7",X"35",X"ED",X"12",X"CF",X"3D",X"ED",X"FF",X"E7",X"0F",X"0F",
|
||||
X"00",X"07",X"01",X"7B",X"12",X"ED",X"13",X"CA",X"13",X"CA",X"13",X"ED",X"01",X"FF",X"00",X"7B",
|
||||
X"0F",X"0E",X"FF",X"C6",X"3D",X"CE",X"12",X"CE",X"01",X"C6",X"08",X"0E",X"86",X"00",X"ED",X"08",
|
||||
X"00",X"16",X"00",X"01",X"03",X"08",X"13",X"84",X"13",X"CA",X"13",X"ED",X"13",X"F7",X"03",X"0F",
|
||||
X"FF",X"84",X"7B",X"CE",X"16",X"EF",X"01",X"E7",X"01",X"E7",X"1E",X"ED",X"FF",X"86",X"0F",X"08",
|
||||
X"03",X"0F",X"13",X"FF",X"13",X"96",X"13",X"09",X"03",X"01",X"00",X"01",X"00",X"01",X"00",X"01",
|
||||
X"0F",X"0F",X"FF",X"EF",X"ED",X"6B",X"CE",X"27",X"CE",X"03",X"CE",X"00",X"CE",X"00",X"CE",X"00",
|
||||
X"0F",X"0F",X"3F",X"EF",X"12",X"CA",X"01",X"8C",X"01",X"8C",X"01",X"8C",X"01",X"8C",X"01",X"8C",
|
||||
X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"CE",X"01",X"ED",X"01",X"F6",X"00",X"7B",X"00",X"07",
|
||||
X"01",X"8C",X"01",X"8C",X"01",X"8C",X"01",X"8C",X"12",X"8C",X"3D",X"84",X"FE",X"08",X"0F",X"00",
|
||||
X"0F",X"0F",X"7F",X"EF",X"35",X"CA",X"13",X"CA",X"12",X"CE",X"01",X"CE",X"01",X"ED",X"01",X"E7",
|
||||
X"07",X"0F",X"37",X"EF",X"12",X"CA",X"13",X"8C",X"13",X"84",X"13",X"08",X"35",X"08",X"36",X"08",
|
||||
X"00",X"6F",X"00",X"7E",X"00",X"7B",X"00",X"37",X"00",X"37",X"00",X"35",X"00",X"13",X"00",X"03",
|
||||
X"27",X"00",X"6B",X"00",X"6D",X"00",X"4E",X"00",X"C6",X"00",X"CA",X"00",X"8C",X"00",X"0C",X"00",
|
||||
X"0F",X"0B",X"7F",X"BF",X"7B",X"B5",X"37",X"1B",X"37",X"1B",X"37",X"1B",X"37",X"97",X"35",X"BD",
|
||||
X"0C",X"0F",X"CF",X"EF",X"CB",X"E5",X"8C",X"4E",X"8D",X"C6",X"8D",X"CE",X"CB",X"CA",X"DA",X"8C",
|
||||
X"13",X"BF",X"13",X"AF",X"13",X"EB",X"12",X"EF",X"01",X"ED",X"01",X"CE",X"01",X"CE",X"01",X"0E",
|
||||
X"DF",X"8C",X"DF",X"84",X"FD",X"08",X"F7",X"08",X"7E",X"08",X"6F",X"00",X"6F",X"00",X"0F",X"00",
|
||||
X"07",X"0F",X"37",X"EF",X"12",X"CE",X"01",X"ED",X"00",X"6F",X"00",X"7B",X"00",X"37",X"00",X"35",
|
||||
X"03",X"0F",X"13",X"EF",X"01",X"C6",X"12",X"8C",X"35",X"08",X"6B",X"00",X"C6",X"00",X"CA",X"00",
|
||||
X"00",X"13",X"00",X"35",X"00",X"6B",X"01",X"C6",X"12",X"8C",X"35",X"86",X"7F",X"EF",X"0F",X"0F",
|
||||
X"CE",X"00",X"ED",X"00",X"6F",X"00",X"7B",X"08",X"37",X"84",X"35",X"CA",X"7F",X"EF",X"0F",X"0F",
|
||||
X"03",X"0F",X"13",X"EF",X"01",X"C6",X"01",X"CA",X"12",X"8C",X"1B",X"84",X"B5",X"08",X"FA",X"08",
|
||||
X"00",X"13",X"00",X"12",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"12",X"00",X"37",X"00",X"07",
|
||||
X"EF",X"00",X"ED",X"00",X"CE",X"00",X"CE",X"00",X"CE",X"00",X"ED",X"00",X"FF",X"08",X"0F",X"08",
|
||||
X"0F",X"0E",X"FF",X"CE",X"0F",X"CE",X"01",X"CE",X"13",X"CA",X"37",X"84",X"7E",X"08",X"ED",X"00",
|
||||
X"00",X"13",X"00",X"37",X"00",X"7E",X"01",X"ED",X"12",X"CA",X"13",X"8F",X"13",X"FF",X"03",X"0F",
|
||||
X"CA",X"00",X"84",X"00",X"08",X"06",X"00",X"4E",X"00",X"4E",X"0F",X"C6",X"FF",X"CE",X"0F",X"0E",
|
||||
X"00",X"07",X"00",X"7F",X"01",X"ED",X"13",X"CA",X"13",X"8C",X"01",X"08",X"00",X"00",X"00",X"00",
|
||||
X"0F",X"00",X"FF",X"08",X"3D",X"8C",X"12",X"CE",X"12",X"CE",X"13",X"CA",X"37",X"84",X"7E",X"08",
|
||||
X"00",X"01",X"00",X"13",X"00",X"13",X"00",X"01",X"00",X"01",X"00",X"13",X"00",X"13",X"00",X"01",
|
||||
X"ED",X"00",X"CA",X"00",X"8C",X"00",X"08",X"00",X"08",X"00",X"8C",X"00",X"8C",X"00",X"08",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"01",X"0C",X"12",X"CA",X"13",X"CE",X"12",X"CA",X"01",X"0C",
|
||||
X"00",X"00",X"01",X"08",X"13",X"8C",X"13",X"8C",X"01",X"8C",X"01",X"8C",X"13",X"84",X"13",X"08",
|
||||
X"01",X"08",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",X"13",X"8C",
|
||||
X"13",X"8C",X"13",X"8C",X"12",X"8C",X"01",X"84",X"01",X"08",X"13",X"8C",X"13",X"8C",X"01",X"08",
|
||||
X"00",X"0E",X"07",X"4E",X"27",X"4F",X"27",X"F7",X"7B",X"ED",X"FE",X"4E",X"2F",X"4E",X"27",X"4E",
|
||||
X"27",X"4E",X"27",X"4F",X"27",X"F7",X"7B",X"ED",X"FE",X"4E",X"2F",X"4E",X"27",X"0E",X"07",X"00",
|
||||
X"01",X"0C",X"01",X"8C",X"74",X"F1",X"10",X"C0",X"01",X"0C",X"03",X"0E",X"02",X"02",X"66",X"33",
|
||||
X"01",X"0C",X"03",X"8E",X"74",X"F1",X"10",X"C0",X"01",X"84",X"12",X"C2",X"30",X"E0",X"01",X"04",
|
||||
X"0E",X"0E",X"0E",X"0E",X"0F",X"0E",X"27",X"8C",X"52",X"48",X"E1",X"E0",X"B4",X"A4",X"43",X"48",
|
||||
X"07",X"0C",X"0F",X"0E",X"3E",X"8E",X"5A",X"4A",X"79",X"C2",X"C3",X"68",X"D3",X"68",X"61",X"C0",
|
||||
X"07",X"0C",X"0F",X"86",X"78",X"C2",X"5E",X"8F",X"7E",X"CF",X"78",X"C3",X"69",X"C3",X"38",X"83",
|
||||
X"30",X"80",X"73",X"C8",X"97",X"2C",X"B5",X"A4",X"F6",X"EC",X"37",X"8C",X"43",X"48",X"33",X"88",
|
||||
X"C0",X"30",X"F4",X"F2",X"F7",X"FE",X"D7",X"BE",X"F7",X"FE",X"73",X"EC",X"63",X"6C",X"30",X"C0",
|
||||
X"09",X"02",X"1E",X"0E",X"28",X"C6",X"5A",X"CA",X"39",X"82",X"7A",X"42",X"24",X"84",X"03",X"08",
|
||||
X"30",X"80",X"73",X"C8",X"F7",X"EC",X"F7",X"EC",X"F7",X"EC",X"73",X"C8",X"30",X"80",X"00",X"00",
|
||||
X"60",X"C0",X"E4",X"E4",X"FE",X"EE",X"FF",X"EE",X"F7",X"EC",X"73",X"C8",X"31",X"80",X"10",X"00",
|
||||
X"E8",X"00",X"FB",X"C0",X"FB",X"FE",X"FB",X"E8",X"FB",X"80",X"F8",X"00",X"C8",X"00",X"C8",X"00",
|
||||
X"31",X"80",X"62",X"C8",X"62",X"C8",X"31",X"80",X"77",X"CC",X"31",X"00",X"31",X"00",X"31",X"00",
|
||||
X"24",X"48",X"24",X"48",X"F7",X"FE",X"E5",X"7F",X"F7",X"FE",X"24",X"48",X"24",X"48",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"08",X"FF",X"84",X"FF",X"CA",X"3D",X"ED",X"03",X"E7",X"00",X"6B",
|
||||
X"00",X"27",X"00",X"27",X"00",X"6B",X"03",X"E7",X"3D",X"ED",X"FF",X"CA",X"FF",X"84",X"0F",X"08",
|
||||
X"00",X"00",X"00",X"00",X"01",X"0F",X"12",X"FF",X"35",X"FF",X"7B",X"CB",X"7E",X"0C",X"6D",X"00",
|
||||
X"4E",X"00",X"4E",X"00",X"6D",X"00",X"7E",X"0C",X"7B",X"CB",X"35",X"FF",X"12",X"FF",X"01",X"0F",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"03",X"00",X"13",X"08",X"1F",X"8C",
|
||||
X"FF",X"CE",X"FF",X"EF",X"0F",X"0F",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"0C",X"00",X"4E",X"00",X"4E",X"00",X"6D",X"0F",
|
||||
X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"4E",X"00",X"4E",X"00",X"0C",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"08",X"13",X"8C",X"13",X"CE",X"01",X"E7",X"00",X"6B",X"08",X"27",
|
||||
X"08",X"27",X"8C",X"27",X"CF",X"6F",X"FE",X"ED",X"7F",X"CE",X"37",X"8C",X"03",X"08",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"08",X"7F",X"84",X"7F",X"CA",X"6D",X"ED",X"4E",X"6F",X"4E",X"7A",
|
||||
X"4E",X"37",X"4E",X"35",X"4E",X"12",X"4E",X"01",X"6D",X"08",X"7F",X"8C",X"0F",X"0C",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"08",X"13",X"8C",X"13",X"CE",X"01",X"E7",X"08",X"6B",X"8C",X"27",
|
||||
X"8C",X"27",X"8C",X"27",X"8C",X"6B",X"CF",X"E7",X"7F",X"CE",X"37",X"8C",X"03",X"08",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"08",X"13",X"8C",X"37",X"8C",X"6F",X"08",X"4E",X"00",X"4E",X"01",
|
||||
X"4E",X"01",X"4E",X"01",X"4E",X"01",X"6D",X"13",X"7E",X"3F",X"37",X"EF",X"13",X"CE",X"01",X"0C",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"08",X"00",X"8C",X"00",X"CE",X"00",X"6F",X"00",X"37",X"08",
|
||||
X"13",X"8C",X"0F",X"CE",X"FF",X"EF",X"FF",X"EF",X"0F",X"0F",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"0E",X"00",X"6F",X"00",X"7F",X"00",X"5F",X"00",X"4F",X"00",X"4E",X"0C",X"4E",
|
||||
X"4E",X"4E",X"6D",X"4F",X"7F",X"FF",X"7F",X"FF",X"6D",X"4F",X"4E",X"0E",X"0C",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"0F",X"FF",X"EF",X"FF",X"EF",X"CB",X"2F",X"C6",X"27",X"4E",X"27",
|
||||
X"4E",X"27",X"4E",X"27",X"CE",X"27",X"C8",X"6B",X"8D",X"EF",X"09",X"0F",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"0C",X"13",X"8D",X"37",X"8D",X"7E",X"09",X"6D",X"00",X"4E",X"00",
|
||||
X"4E",X"00",X"4E",X"00",X"6F",X"01",X"37",X"3D",X"35",X"FF",X"12",X"FE",X"01",X"0F",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"08",X"FF",X"84",X"FF",X"CE",X"87",X"6F",X"8C",X"27",X"8C",X"27",
|
||||
X"8C",X"27",X"8C",X"27",X"8C",X"27",X"8D",X"6F",X"1B",X"CE",X"13",X"84",X"01",X"08",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"0F",X"12",X"FF",X"37",X"FF",X"7E",X"1F",X"6D",X"12",X"4E",X"01",
|
||||
X"4E",X"01",X"4E",X"01",X"4F",X"01",X"6F",X"3D",X"37",X"FF",X"12",X"EF",X"01",X"0E",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"03",X"0F",X"13",X"EF",X"01",X"6B",X"00",X"27",X"00",X"27",X"08",X"27",
|
||||
X"84",X"27",X"CA",X"27",X"ED",X"27",X"7E",X"2F",X"37",X"A7",X"13",X"EF",X"01",X"EF",X"00",X"0F",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"0F",X"0E",X"7F",X"ED",
|
||||
X"7F",X"FF",X"0F",X"3D",X"00",X"03",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"03",X"0C",X"37",X"CA",X"7F",X"ED",X"ED",X"6F",X"CE",X"2F",
|
||||
X"8C",X"27",X"8C",X"27",X"8C",X"6B",X"CB",X"E7",X"F7",X"ED",X"7B",X"CA",X"07",X"0C",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"03",X"0C",X"35",X"CA",X"7B",X"ED",X"7E",X"3E",X"6D",X"13",X"4E",X"12",
|
||||
X"4E",X"12",X"4E",X"13",X"4E",X"35",X"6C",X"37",X"6F",X"7B",X"7B",X"EF",X"35",X"CE",X"03",X"0C",
|
||||
X"00",X"00",X"00",X"00",X"07",X"08",X"7F",X"84",X"FF",X"CE",X"CB",X"6F",X"08",X"2F",X"08",X"27",
|
||||
X"08",X"27",X"08",X"27",X"84",X"6B",X"8F",X"E7",X"FF",X"CE",X"FF",X"84",X"0F",X"08",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"08",X"12",X"8C",X"37",X"8D",X"6F",X"1B",X"4E",X"13",X"4E",X"13",
|
||||
X"4E",X"13",X"4E",X"13",X"4E",X"13",X"6F",X"1E",X"37",X"FF",X"12",X"FF",X"01",X"0F",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"08",X"00",X"87",X"03",X"FE",X"2F",X"3D",X"EB",X"03",X"E7",
|
||||
X"16",X"EF",X"F7",X"EF",X"FF",X"CB",X"ED",X"0C",X"0E",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"0E",X"00",X"6D",X"0C",X"7F",X"CB",X"6D",X"F7",X"4E",X"3E",X"0C",X"27",X"00",X"27",
|
||||
X"00",X"27",X"0C",X"27",X"4F",X"7B",X"7D",X"FF",X"7F",X"FE",X"7F",X"87",X"6D",X"08",X"0E",X"00",
|
||||
X"00",X"00",X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"FF",X"EF",X"8F",X"6B",X"8C",X"27",
|
||||
X"00",X"00",X"0C",X"00",X"4E",X"00",X"6D",X"0F",X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"4E",X"01",
|
||||
X"4E",X"01",X"4E",X"01",X"4E",X"12",X"4E",X"13",X"6F",X"3F",X"7B",X"FE",X"35",X"ED",X"03",X"0E",
|
||||
X"00",X"27",X"00",X"27",X"00",X"6B",X"01",X"E7",X"12",X"ED",X"13",X"EF",X"03",X"0F",X"00",X"00",
|
||||
X"4E",X"00",X"4E",X"00",X"4E",X"00",X"6C",X"00",X"6F",X"00",X"3F",X"08",X"17",X"8C",X"03",X"08",
|
||||
X"00",X"00",X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"FF",X"EF",X"0F",X"6B",X"00",X"27",
|
||||
X"00",X"00",X"0C",X"00",X"4E",X"00",X"6D",X"0F",X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"4E",X"00",
|
||||
X"8C",X"27",X"CA",X"27",X"EF",X"27",X"0F",X"27",X"00",X"27",X"00",X"6B",X"01",X"EF",X"01",X"0F",
|
||||
X"4E",X"01",X"4E",X"12",X"4E",X"37",X"4E",X"07",X"4E",X"00",X"6D",X"00",X"7F",X"08",X"0F",X"08",
|
||||
X"0C",X"01",X"00",X"12",X"00",X"37",X"00",X"07",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"4E",X"00",X"4E",X"03",X"4E",X"27",X"6D",X"6B",X"7F",X"EF",X"7F",X"EF",X"6D",X"6B",X"0E",X"07",
|
||||
X"8C",X"03",X"8C",X"27",X"8F",X"6B",X"FF",X"EF",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"0C",X"01",X"4E",X"01",X"6D",X"0F",X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"4E",X"00",X"0C",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"03",X"00",X"27",X"00",X"27",X"0F",X"6B",
|
||||
X"FF",X"EF",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"27",X"00",X"03",X"00",X"00",X"00",X"00",
|
||||
X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"4E",X"00",X"4C",X"00",X"0C",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"00",X"00",X"00",X"00",X"01",X"0C",X"13",X"8C",X"37",X"8C",X"7E",X"08",X"6D",X"00",X"4E",X"00",
|
||||
X"4E",X"00",X"6D",X"00",X"7E",X"0F",X"7B",X"FF",X"35",X"FF",X"03",X"0F",X"00",X"00",X"00",X"00",
|
||||
X"CE",X"03",X"EB",X"03",X"3D",X"2F",X"12",X"EB",X"01",X"E7",X"00",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"0C",X"3D",X"4F",X"F7",X"7D",X"FE",X"7F",X"CB",X"7E",X"0C",X"6D",X"00",X"4E",X"00",X"0C",X"00",
|
||||
X"00",X"03",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"4E",X"00",X"4E",X"00",X"4E",X"00",X"4E",X"00",X"6D",X"08",X"7F",X"8C",X"0F",X"0C",X"00",X"00",
|
||||
X"00",X"03",X"0F",X"2F",X"FF",X"EF",X"1E",X"EF",X"7B",X"EF",X"FF",X"CA",X"FE",X"0C",X"CB",X"00",
|
||||
X"0C",X"00",X"CB",X"00",X"F6",X"0C",X"3D",X"CA",X"FF",X"EF",X"FF",X"EF",X"0F",X"2F",X"00",X"03",
|
||||
X"0E",X"00",X"6D",X"0F",X"7F",X"FF",X"6D",X"0F",X"0E",X"01",X"00",X"16",X"01",X"7B",X"12",X"FF",
|
||||
X"01",X"F6",X"00",X"35",X"0E",X"01",X"6D",X"0F",X"7F",X"FF",X"7F",X"FF",X"6D",X"0F",X"0E",X"00",
|
||||
X"00",X"00",X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"1E",X"EF",X"7B",X"ED",X"FF",X"86",
|
||||
X"ED",X"08",X"86",X"03",X"08",X"27",X"0F",X"2F",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"00",X"00",X"0C",X"00",X"4E",X"00",X"6D",X"0F",X"7F",X"FF",X"6D",X"0F",X"4E",X"01",X"0C",X"16",
|
||||
X"01",X"7B",X"16",X"FF",X"7B",X"ED",X"7F",X"87",X"7F",X"FF",X"0F",X"0F",X"00",X"00",X"00",X"00",
|
||||
X"0C",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"01",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"4E",X"02",X"4E",X"2F",X"6D",X"E7",X"7E",X"CE",X"7B",X"CB",X"7F",X"FF",X"6D",X"F7",X"0F",X"0F",
|
||||
X"00",X"00",X"00",X"00",X"03",X"0C",X"37",X"CA",X"7F",X"CE",X"F6",X"E5",X"ED",X"6B",X"CE",X"27",
|
||||
X"CA",X"27",X"8C",X"27",X"84",X"6B",X"09",X"E7",X"1A",X"ED",X"13",X"EF",X"03",X"0F",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"0C",X"7F",X"8C",X"7B",X"84",X"7E",X"09",X"6D",X"01",X"4E",X"12",
|
||||
X"4E",X"13",X"4E",X"35",X"4E",X"37",X"6D",X"7B",X"7A",X"F6",X"37",X"EF",X"35",X"CE",X"03",X"0C",
|
||||
X"00",X"00",X"00",X"00",X"01",X"0F",X"01",X"EF",X"00",X"6B",X"00",X"27",X"00",X"27",X"0F",X"6B",
|
||||
X"FF",X"EF",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"27",X"00",X"6B",X"01",X"EF",X"01",X"0F",
|
||||
X"00",X"03",X"00",X"03",X"00",X"27",X"0F",X"6B",X"FF",X"EF",X"0F",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"03",X"0F",X"35",X"FF",X"7B",X"FF",X"7E",X"0F",X"6D",X"00",
|
||||
X"4E",X"00",X"4E",X"00",X"6D",X"00",X"7A",X"0F",X"35",X"FF",X"03",X"0F",X"00",X"00",X"00",X"00",
|
||||
X"00",X"03",X"00",X"27",X"01",X"6B",X"1E",X"EF",X"F7",X"EF",X"FF",X"E3",X"CB",X"2F",X"0C",X"03",
|
||||
X"00",X"00",X"0C",X"03",X"CB",X"2F",X"F7",X"EB",X"1E",X"EF",X"01",X"6B",X"00",X"27",X"00",X"03",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"07",X"03",X"7B",X"3D",X"FF",X"7F",X"ED",
|
||||
X"7E",X"0E",X"3D",X"ED",X"03",X"7B",X"00",X"07",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"07",X"0F",X"6B",X"F7",X"EF",X"FF",X"EF",X"CB",X"6B",X"0C",X"06",X"87",X"6B",X"FF",X"EF",
|
||||
X"FF",X"EF",X"C3",X"6B",X"0C",X"06",X"87",X"06",X"FE",X"6B",X"7B",X"EF",X"07",X"6B",X"00",X"07",
|
||||
X"00",X"00",X"00",X"00",X"00",X"0F",X"0F",X"F7",X"7F",X"FF",X"7F",X"CB",X"1E",X"FF",X"01",X"1F",
|
||||
X"0F",X"F7",X"7F",X"FF",X"7F",X"CB",X"1E",X"FF",X"01",X"3D",X"00",X"03",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"03",X"00",X"27",X"00",X"6B",X"03",X"EF",X"3D",X"EF",X"F7",X"A7",X"EF",X"0B",
|
||||
X"CA",X"00",X"E5",X"00",X"3E",X"0B",X"13",X"A7",X"01",X"EB",X"00",X"6F",X"00",X"27",X"00",X"03",
|
||||
X"0C",X"00",X"4E",X"00",X"6D",X"00",X"7E",X"08",X"7D",X"84",X"4F",X"CA",X"4E",X"6D",X"0C",X"37",
|
||||
X"0C",X"3F",X"4F",X"F7",X"7D",X"ED",X"7F",X"8E",X"7E",X"08",X"6D",X"00",X"4E",X"00",X"0C",X"00",
|
||||
X"CA",X"00",X"84",X"00",X"CB",X"03",X"F6",X"2F",X"3D",X"EB",X"03",X"E7",X"00",X"2F",X"00",X"03",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"0C",X"00",X"4E",X"03",X"6D",X"3D",
|
||||
X"7F",X"FF",X"7F",X"FF",X"6D",X"3D",X"4E",X"03",X"0C",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"8C",X"27",X"CE",X"27",X"E7",X"27",X"7B",X"2F",X"35",X"EF",X"12",X"EF",X"01",X"0F",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"00",X"7E",X"08",X"7F",X"8C",X"5E",X"CE",X"4F",X"E7",X"4E",X"7B",
|
||||
X"4E",X"35",X"4E",X"12",X"4E",X"01",X"4E",X"00",X"6D",X"08",X"7F",X"8C",X"0F",X"0C",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"01",X"08",X"13",X"8C",X"13",X"CE",X"01",X"E7",X"00",X"6B",X"00",X"27",
|
||||
X"08",X"27",X"8C",X"27",X"CF",X"6B",X"F6",X"E7",X"7B",X"CE",X"35",X"8C",X"03",X"08",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"06",X"06",X"6F",X"6F",
|
||||
X"6F",X"7F",X"06",X"35",X"00",X"12",X"00",X"01",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"07",X"00",X"7A",X"08",X"7F",X"08",X"7A",X"08",X"07",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0C",X"0C",X"CF",X"CE",X"7B",X"CE",X"07",X"0C",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"0F",X"0E",X"FF",X"EF",X"FF",X"EF",X"0F",X"0E",X"00",X"00",X"00",X"00",
|
||||
X"00",X"00",X"00",X"00",X"06",X"07",X"6F",X"7B",X"6F",X"F7",X"06",X"0F",X"00",X"00",X"00",X"00",
|
||||
X"27",X"00",X"3E",X"0E",X"FF",X"CE",X"3D",X"0E",X"1F",X"87",X"FF",X"EF",X"1E",X"8F",X"01",X"8C",
|
||||
X"13",X"08",X"1F",X"87",X"7F",X"FF",X"1E",X"8F",X"07",X"CB",X"37",X"FF",X"07",X"C7",X"00",X"4E",
|
||||
X"00",X"00",X"88",X"44",X"8E",X"40",X"03",X"C3",X"03",X"E3",X"03",X"C3",X"8E",X"40",X"88",X"44",
|
||||
X"00",X"00",X"00",X"44",X"42",X"42",X"69",X"C3",X"70",X"E3",X"69",X"C3",X"42",X"42",X"00",X"44",
|
||||
X"60",X"07",X"B4",X"0F",X"69",X"8F",X"5A",X"0C",X"69",X"8F",X"B4",X"0F",X"60",X"07",X"00",X"00",
|
||||
X"61",X"0E",X"F0",X"87",X"96",X"4F",X"5F",X"C3",X"96",X"4F",X"F0",X"87",X"61",X"0E",X"00",X"00",
|
||||
X"0F",X"0E",X"71",X"CB",X"F1",X"4B",X"B4",X"C3",X"F1",X"E9",X"71",X"4B",X"0F",X"0E",X"0F",X"08",
|
||||
X"10",X"C0",X"53",X"2C",X"BF",X"B6",X"BE",X"FE",X"BF",X"B6",X"53",X"2C",X"10",X"C0",X"00",X"00",
|
||||
X"10",X"F0",X"71",X"FE",X"F7",X"6C",X"B7",X"EC",X"B7",X"EC",X"F7",X"6C",X"71",X"FE",X"10",X"F0",
|
||||
X"03",X"0F",X"24",X"82",X"7A",X"4A",X"39",X"A1",X"58",X"CA",X"24",X"C6",X"03",X"0F",X"00",X"00",
|
||||
X"31",X"80",X"33",X"88",X"33",X"88",X"33",X"88",X"73",X"C8",X"77",X"CC",X"55",X"44",X"00",X"00",
|
||||
X"10",X"EC",X"31",X"FE",X"73",X"FC",X"F7",X"C8",X"73",X"FC",X"31",X"FE",X"10",X"EC",X"00",X"00",
|
||||
X"FF",X"FF",X"F0",X"F0",X"31",X"FE",X"31",X"EE",X"10",X"EC",X"00",X"E4",X"00",X"C4",X"00",X"40",
|
||||
X"00",X"00",X"11",X"60",X"F1",X"F6",X"FF",X"99",X"11",X"F6",X"11",X"60",X"00",X"00",X"00",X"00",
|
||||
X"00",X"31",X"00",X"72",X"00",X"E4",X"34",X"C8",X"13",X"00",X"43",X"80",X"84",X"08",X"08",X"00");
|
||||
begin
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if addr(13) = '1' then
|
||||
data <= (others=>'0');
|
||||
else
|
||||
data <= rom_data(to_integer(unsigned(addr)));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end architecture;
|
||||
351
Arcade_MiST/Atari Gauntlet Hardware/rtl/sdram.sv
Normal file
351
Arcade_MiST/Atari Gauntlet Hardware/rtl/sdram.sv
Normal file
@@ -0,0 +1,351 @@
|
||||
//
|
||||
// sdram.v
|
||||
//
|
||||
// sdram controller implementation for the MiST board
|
||||
// https://github.com/mist-devel/mist-board
|
||||
//
|
||||
// Copyright (c) 2013 Till Harbaum <till@harbaum.org>
|
||||
// Copyright (c) 2019 Gyorgy Szombathelyi
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module sdram (
|
||||
|
||||
// interface to the MT48LC16M16 chip
|
||||
inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
|
||||
output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
|
||||
output reg SDRAM_DQML, // two byte masks
|
||||
output reg SDRAM_DQMH, // two byte masks
|
||||
output reg [1:0] SDRAM_BA, // two banks
|
||||
output SDRAM_nCS, // a single chip select
|
||||
output SDRAM_nWE, // write enable
|
||||
output SDRAM_nRAS, // row address select
|
||||
output SDRAM_nCAS, // columns address select
|
||||
|
||||
// cpu/chipset interface
|
||||
input init_n, // init signal after FPGA config to initialize RAM
|
||||
input clk, // sdram clock
|
||||
|
||||
input port1_req,
|
||||
output reg port1_ack,
|
||||
input port1_we,
|
||||
input [23:1] port1_a,
|
||||
input [1:0] port1_ds,
|
||||
input [15:0] port1_d,
|
||||
output reg [15:0] port1_q,
|
||||
|
||||
input [19:1] cpu1_addr,
|
||||
output reg [15:0] cpu1_q,
|
||||
input [19:1] cpu2_addr,
|
||||
output reg [15:0] cpu2_q,
|
||||
|
||||
input port2_req,
|
||||
output reg port2_ack,
|
||||
input port2_we,
|
||||
input [23:1] port2_a,
|
||||
input [1:0] port2_ds,
|
||||
input [15:0] port2_d,
|
||||
output reg [31:0] port2_q,
|
||||
|
||||
input [17:2] sp_addr,
|
||||
output reg [31:0] sp_q
|
||||
);
|
||||
|
||||
parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate
|
||||
|
||||
localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz
|
||||
localparam BURST_LENGTH = 3'b001; // 000=1, 001=2, 010=4, 011=8
|
||||
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
|
||||
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
// 64ms/8192 rows = 7.8us
|
||||
localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------------ cycle state machine ------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
SDRAM state machine for 2 bank interleaved access
|
||||
1 word burst, CL2
|
||||
cmd issued registered
|
||||
0 RAS0 cas1 - data0 read burst terminated
|
||||
1 ras0
|
||||
2 data1 returned
|
||||
3 CAS0 data1 returned
|
||||
4 RAS1 cas0
|
||||
5 ras1
|
||||
6 CAS1 data0 returned
|
||||
*/
|
||||
|
||||
localparam STATE_RAS0 = 3'd0; // first state in cycle
|
||||
localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns)
|
||||
localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3
|
||||
localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6
|
||||
localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7
|
||||
localparam STATE_READ1 = 3'd3;
|
||||
localparam STATE_DS1b = 3'd0;
|
||||
localparam STATE_READ1b = 3'd4;
|
||||
localparam STATE_LAST = 3'd6;
|
||||
|
||||
reg [2:0] t;
|
||||
|
||||
always @(posedge clk) begin
|
||||
t <= t + 1'd1;
|
||||
if (t == STATE_LAST) t <= STATE_RAS0;
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// --------------------------- startup/reset ---------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// wait 1ms (32 8Mhz cycles) after FPGA config is done before going
|
||||
// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
|
||||
reg [4:0] reset;
|
||||
reg init = 1'b1;
|
||||
always @(posedge clk, negedge init_n) begin
|
||||
if(!init_n) begin
|
||||
reset <= 5'h1f;
|
||||
init <= 1'b1;
|
||||
end else begin
|
||||
if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1;
|
||||
init <= !(reset == 0);
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------ generate ram control signals ---------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// all possible commands
|
||||
localparam CMD_INHIBIT = 4'b1111;
|
||||
localparam CMD_NOP = 4'b0111;
|
||||
localparam CMD_ACTIVE = 4'b0011;
|
||||
localparam CMD_READ = 4'b0101;
|
||||
localparam CMD_WRITE = 4'b0100;
|
||||
localparam CMD_BURST_TERMINATE = 4'b0110;
|
||||
localparam CMD_PRECHARGE = 4'b0010;
|
||||
localparam CMD_AUTO_REFRESH = 4'b0001;
|
||||
localparam CMD_LOAD_MODE = 4'b0000;
|
||||
|
||||
reg [3:0] sd_cmd; // current command sent to sd ram
|
||||
reg [15:0] sd_din; // Fast Input register latching incoming SDRAM data
|
||||
|
||||
// drive control signals according to current command
|
||||
assign SDRAM_nCS = sd_cmd[3];
|
||||
assign SDRAM_nRAS = sd_cmd[2];
|
||||
assign SDRAM_nCAS = sd_cmd[1];
|
||||
assign SDRAM_nWE = sd_cmd[0];
|
||||
|
||||
reg [24:1] addr_latch[2];
|
||||
reg [24:1] addr_latch_next[2];
|
||||
reg [19:1] addr_last[2];
|
||||
reg [17:2] addr_last2[2];
|
||||
reg [15:0] din_latch[2];
|
||||
reg [1:0] oe_latch;
|
||||
reg [1:0] we_latch;
|
||||
reg [1:0] ds[2];
|
||||
|
||||
reg port1_state;
|
||||
reg port2_state;
|
||||
|
||||
localparam PORT_NONE = 2'd0;
|
||||
localparam PORT_CPU1 = 2'd1;
|
||||
localparam PORT_CPU2 = 2'd2;
|
||||
localparam PORT_SP = 2'd1;
|
||||
localparam PORT_REQ = 2'd3;
|
||||
|
||||
reg [1:0] next_port[2];
|
||||
reg [1:0] port[2];
|
||||
|
||||
reg refresh;
|
||||
reg [11:0] refresh_cnt;
|
||||
reg need_refresh;
|
||||
|
||||
// PORT1: bank 0,1
|
||||
always @(*) begin
|
||||
if (refresh) begin
|
||||
next_port[0] = PORT_NONE;
|
||||
addr_latch_next[0] = addr_latch[1];
|
||||
end else if (port1_req ^ port1_state) begin
|
||||
next_port[0] = PORT_REQ;
|
||||
addr_latch_next[0] = { 1'b0, port1_a };
|
||||
end else if (cpu1_addr != addr_last[PORT_CPU1]) begin
|
||||
next_port[0] = PORT_CPU1;
|
||||
addr_latch_next[0] = { 5'd0, cpu1_addr };
|
||||
end else if (cpu2_addr != addr_last[PORT_CPU2]) begin
|
||||
next_port[0] = PORT_CPU2;
|
||||
addr_latch_next[0] = { 5'd0, cpu2_addr };
|
||||
end else begin
|
||||
next_port[0] = PORT_NONE;
|
||||
addr_latch_next[0] = addr_latch[0];
|
||||
end
|
||||
end
|
||||
|
||||
// PORT1: bank 2,3
|
||||
always @(*) begin
|
||||
if (port2_req ^ port2_state) begin
|
||||
next_port[1] = PORT_REQ;
|
||||
addr_latch_next[1] = { 1'b1, port2_a };
|
||||
end else if (sp_addr != addr_last2[PORT_SP]) begin
|
||||
next_port[1] = PORT_SP;
|
||||
addr_latch_next[1] = { 1'b1, 6'd0, sp_addr, 1'b0 };
|
||||
end else begin
|
||||
next_port[1] = PORT_NONE;
|
||||
addr_latch_next[1] = addr_latch[1];
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
// permanently latch ram data to reduce delays
|
||||
sd_din <= SDRAM_DQ;
|
||||
SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
|
||||
{ SDRAM_DQMH, SDRAM_DQML } <= 2'b11;
|
||||
sd_cmd <= CMD_NOP; // default: idle
|
||||
refresh_cnt <= refresh_cnt + 1'd1;
|
||||
need_refresh <= (refresh_cnt >= RFRSH_CYCLES);
|
||||
|
||||
if(init) begin
|
||||
// initialization takes place at the end of the reset phase
|
||||
if(t == STATE_RAS0) begin
|
||||
|
||||
if(reset == 15) begin
|
||||
sd_cmd <= CMD_PRECHARGE;
|
||||
SDRAM_A[10] <= 1'b1; // precharge all banks
|
||||
end
|
||||
|
||||
if(reset == 10 || reset == 8) begin
|
||||
sd_cmd <= CMD_AUTO_REFRESH;
|
||||
end
|
||||
|
||||
if(reset == 2) begin
|
||||
sd_cmd <= CMD_LOAD_MODE;
|
||||
SDRAM_A <= MODE;
|
||||
SDRAM_BA <= 2'b00;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
// RAS phase
|
||||
// bank 0,1
|
||||
if(t == STATE_RAS0) begin
|
||||
addr_latch[0] <= addr_latch_next[0];
|
||||
port[0] <= next_port[0];
|
||||
{ oe_latch[0], we_latch[0] } <= 2'b00;
|
||||
|
||||
if (next_port[0] != PORT_NONE) begin
|
||||
sd_cmd <= CMD_ACTIVE;
|
||||
SDRAM_A <= addr_latch_next[0][22:10];
|
||||
SDRAM_BA <= addr_latch_next[0][24:23];
|
||||
addr_last[next_port[0]] <= addr_latch_next[0][19:1];
|
||||
if (next_port[0] == PORT_REQ) begin
|
||||
{ oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we };
|
||||
ds[0] <= port1_ds;
|
||||
din_latch[0] <= port1_d;
|
||||
port1_state <= port1_req;
|
||||
end else begin
|
||||
{ oe_latch[0], we_latch[0] } <= 2'b10;
|
||||
ds[0] <= 2'b11;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// bank 2,3
|
||||
if(t == STATE_RAS1) begin
|
||||
refresh <= 0;
|
||||
addr_latch[1] <= addr_latch_next[1];
|
||||
{ oe_latch[1], we_latch[1] } <= 2'b00;
|
||||
port[1] <= next_port[1];
|
||||
|
||||
if (next_port[1] != PORT_NONE) begin
|
||||
sd_cmd <= CMD_ACTIVE;
|
||||
SDRAM_A <= addr_latch_next[1][22:10];
|
||||
SDRAM_BA <= addr_latch_next[1][24:23];
|
||||
addr_last2[next_port[1]] <= addr_latch_next[1][16:2];
|
||||
if (next_port[1] == PORT_REQ) begin
|
||||
{ oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we };
|
||||
ds[1] <= port2_ds;
|
||||
din_latch[1] <= port2_d;
|
||||
port2_state <= port2_req;
|
||||
end else begin
|
||||
{ oe_latch[1], we_latch[1] } <= 2'b10;
|
||||
ds[1] <= 2'b11;
|
||||
end
|
||||
end else if (need_refresh && !oe_latch[0] & !we_latch[0]) begin
|
||||
refresh <= 1;
|
||||
refresh_cnt <= 0;
|
||||
sd_cmd <= CMD_AUTO_REFRESH;
|
||||
end
|
||||
end
|
||||
|
||||
// CAS phase
|
||||
if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin
|
||||
sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ;
|
||||
{ SDRAM_DQMH, SDRAM_DQML } <= ~ds[0];
|
||||
if (we_latch[0]) begin
|
||||
SDRAM_DQ <= din_latch[0];
|
||||
port1_ack <= port1_req;
|
||||
end
|
||||
SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge
|
||||
SDRAM_BA <= addr_latch[0][24:23];
|
||||
end
|
||||
|
||||
if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin
|
||||
sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ;
|
||||
{ SDRAM_DQMH, SDRAM_DQML } <= ~ds[1];
|
||||
if (we_latch[1]) begin
|
||||
SDRAM_DQ <= din_latch[1];
|
||||
port2_ack <= port2_req;
|
||||
end
|
||||
SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge
|
||||
SDRAM_BA <= addr_latch[1][24:23];
|
||||
end
|
||||
|
||||
// Data returned
|
||||
if(t == STATE_READ0 && oe_latch[0]) begin
|
||||
case(port[0])
|
||||
PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end
|
||||
PORT_CPU1: begin cpu1_q <= sd_din; end
|
||||
PORT_CPU2: begin cpu2_q <= sd_din; end
|
||||
default: ;
|
||||
endcase;
|
||||
end
|
||||
|
||||
if(t == STATE_READ1 && oe_latch[1]) begin
|
||||
case(port[1])
|
||||
PORT_REQ: port2_q[15:0] <= sd_din;
|
||||
PORT_SP : sp_q[15:0] <= sd_din;
|
||||
default: ;
|
||||
endcase;
|
||||
end
|
||||
|
||||
//set DQM two cycles before the 2nd word in the burst
|
||||
if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1];
|
||||
|
||||
if(t == STATE_READ1b && oe_latch[1]) begin
|
||||
case(port[1])
|
||||
PORT_REQ: begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end
|
||||
PORT_SP : begin sp_q[31:16] <= sd_din; end
|
||||
default: ;
|
||||
endcase;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
91
Arcade_MiST/Atari Gauntlet Hardware/rtl/spram.vhd
Normal file
91
Arcade_MiST/Atari Gauntlet Hardware/rtl/spram.vhd
Normal file
@@ -0,0 +1,91 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY spram IS
|
||||
GENERIC
|
||||
(
|
||||
init_file : string := "";
|
||||
--numwords_a : natural;
|
||||
widthad_a : natural;
|
||||
width_a : natural := 8;
|
||||
outdata_reg_a : string := "UNREGISTERED"
|
||||
);
|
||||
PORT
|
||||
(
|
||||
address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
clock : IN STD_LOGIC ;
|
||||
data : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
wren : IN STD_LOGIC ;
|
||||
q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END spram;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF spram IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
|
||||
|
||||
|
||||
COMPONENT altsyncram
|
||||
GENERIC (
|
||||
clock_enable_input_a : STRING;
|
||||
clock_enable_output_a : STRING;
|
||||
init_file : STRING;
|
||||
intended_device_family : STRING;
|
||||
lpm_hint : STRING;
|
||||
lpm_type : STRING;
|
||||
numwords_a : NATURAL;
|
||||
operation_mode : STRING;
|
||||
outdata_aclr_a : STRING;
|
||||
outdata_reg_a : STRING;
|
||||
power_up_uninitialized : STRING;
|
||||
read_during_write_mode_port_a : STRING;
|
||||
widthad_a : NATURAL;
|
||||
width_a : NATURAL;
|
||||
width_byteena_a : NATURAL
|
||||
);
|
||||
PORT (
|
||||
wren_a : IN STD_LOGIC ;
|
||||
clock0 : IN STD_LOGIC ;
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
q <= sub_wire0(width_a-1 DOWNTO 0);
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
clock_enable_input_a => "BYPASS",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
init_file => init_file,
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**widthad_a,
|
||||
operation_mode => "SINGLE_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_reg_a => outdata_reg_a,
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
widthad_a => widthad_a,
|
||||
width_a => width_a,
|
||||
width_byteena_a => 1
|
||||
)
|
||||
PORT MAP (
|
||||
wren_a => wren,
|
||||
clock0 => clock,
|
||||
address_a => address,
|
||||
data_a => data,
|
||||
q_a => sub_wire0
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
186
common/Amiga/Amiga_Gary.sv
Normal file
186
common/Amiga/Amiga_Gary.sv
Normal file
@@ -0,0 +1,186 @@
|
||||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 20:24:47 10/29/2015
|
||||
// Design Name:
|
||||
// Module Name: Gary
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module Gary(
|
||||
output nVPA,
|
||||
output nCDR,
|
||||
output nCDW,
|
||||
input nKRES,
|
||||
input nMTR,
|
||||
input nDKWD,
|
||||
input nDKWE,
|
||||
input nUDS,
|
||||
input nLDS,
|
||||
input RW,
|
||||
input nAS,
|
||||
input nBGACK,
|
||||
input nDBR,
|
||||
input nSEL0,
|
||||
output nRGAE,
|
||||
output nBLS,
|
||||
output nRAME,
|
||||
output nROME,
|
||||
output nRTCR,
|
||||
output nRTCW,
|
||||
output reg nLATCH,
|
||||
input nCDAC,
|
||||
input C3,
|
||||
input C1,
|
||||
input nOVR,
|
||||
input OVL,
|
||||
input XRDY,
|
||||
input nEXP,
|
||||
input [23:17] A,
|
||||
inout nRESET,
|
||||
output nHALT,
|
||||
output nDTACK,
|
||||
output DKWEB,
|
||||
output DKWDB,
|
||||
output MTR0D,
|
||||
output MTRXD
|
||||
);
|
||||
|
||||
//internal registers
|
||||
reg AS_14D0,nDBR_D0;
|
||||
reg nDTACK_S, nCDR_S, nCDW_S,nBLS_S, MTR0_S;
|
||||
reg [7:0]counter;
|
||||
//generate processor clock
|
||||
wire C7M = C3 ~^ C1; // c1 not xor c2 = 7mhz
|
||||
wire C14M = C7M ^ ~nCDAC; //14MHZ
|
||||
wire DS = ~nUDS | ~nLDS;
|
||||
|
||||
wire chipram = (~OVL & A[23:21]==3'b000
|
||||
//| A[23:19]>5'b00001
|
||||
);
|
||||
wire rom = ( ( OVL & A[23:21]==3'b000 ) //rom overlay during start
|
||||
| A[23:19]==5'b11111 //F80000-FFFFFF
|
||||
| A[23:19]==5'b11100 ); //E00000-E7FFFF
|
||||
wire clock = A[23:17]==7'b1101110; //clock: D80000-DB0000
|
||||
wire cia = A[23:21]==3'b101; //cia: A00000-BFFFFF
|
||||
wire chipset = (nEXP & //expansion selected
|
||||
(A[23:20]==4'b1100 //C00000-CFFFFF
|
||||
|A[23:19]==5'b11010))| //D00000-D7FFFF
|
||||
A[23:18]==6'b110111; //chipset
|
||||
wire ranger = ~nEXP & //expansion selected
|
||||
(A[23:20]==4'b1100 //C00000-CFFFFF
|
||||
|A[23:19]==5'b11010) //D00000-D7FFFF
|
||||
;
|
||||
//all others a bit later with AS_14D0
|
||||
wire other =~chipram & ~rom & ~clock & ~ chipset & ~ranger & ~cia & ~AS_14D0;
|
||||
//reset generation
|
||||
assign nHALT = ~nKRES ? 0 : 1'bz;
|
||||
assign nRESET = ~nKRES ? 0 : 1'bz;
|
||||
|
||||
//assign simple signals
|
||||
assign DKWDB = ~nDKWD;
|
||||
assign DKWEB = nDKWE & nRESET;
|
||||
assign MTRXD = ~nMTR & nRESET;
|
||||
assign MTR0D = MTR0_S ;
|
||||
//select floppy motor
|
||||
always @(negedge nSEL0 ,negedge nRESET)
|
||||
begin
|
||||
if( nRESET==0)
|
||||
begin
|
||||
MTR0_S <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
MTR0_S <= ~nMTR;
|
||||
end
|
||||
end
|
||||
|
||||
//decode address and generate the internal signals
|
||||
always @(posedge C14M)
|
||||
begin
|
||||
//this replaces the nasty latch!
|
||||
nLATCH <= C3;
|
||||
AS_14D0 <= nAS;
|
||||
nDBR_D0 <= nDBR;
|
||||
if(nAS)
|
||||
begin
|
||||
nDTACK_S <=1;
|
||||
nCDR_S <=1;
|
||||
nCDW_S <=1;
|
||||
nBLS_S <=1;
|
||||
counter <=8'h00;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
//count 7Mhz-flanks: odd falling even rising
|
||||
counter <=counter+1; // the cycle starts at S3: this time the first cycle is seen!
|
||||
|
||||
if(
|
||||
((~nDBR | ~nDBR_D0) &( //blitting
|
||||
chipram | chipset | ranger //Agnus
|
||||
)
|
||||
)
|
||||
| cia //cia access
|
||||
& nDTACK_S //not asserted
|
||||
|
||||
)
|
||||
begin
|
||||
nDTACK_S <= 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
nDTACK_S <= ~XRDY; //ready to rambo
|
||||
end
|
||||
|
||||
|
||||
//slow down blitter
|
||||
nBLS_S <= ~(( chipram | ranger | chipset) & (counter[1:0]>=2'b00 & counter[1:0]<=2'b01));
|
||||
|
||||
//read from RAM / register
|
||||
if( counter>=8'h01 //minimum wait
|
||||
& RW //read
|
||||
& nDBR_D0 & nDBR //no blitting
|
||||
& (chipset | chipram | ranger) //agnus-select
|
||||
& nCDR_S //not asseted
|
||||
)
|
||||
begin
|
||||
nCDR_S <= 0;
|
||||
end
|
||||
|
||||
//write to RAM / register
|
||||
if( ~RW //write
|
||||
& nDBR_D0 & nDBR //no blitting
|
||||
& (chipset | chipram | ranger) //agnus-select
|
||||
& nCDW_S //not asseted
|
||||
)
|
||||
begin
|
||||
nCDW_S <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//output signal generation
|
||||
assign nVPA = nOVR & ~nAS ? ~cia : 1'bz;
|
||||
assign nDTACK = (nOVR & ~nAS ) ? nDTACK_S : 1'bz;
|
||||
assign nROME = nOVR & ~nAS ? ~(rom & RW) : 1; //only on read!
|
||||
assign nRTCR = nOVR & ~nAS ? ~(clock & RW & DS) : 1;
|
||||
assign nRTCW = nOVR & ~nAS ? ~(clock & ~RW & DS) : 1;
|
||||
assign nRAME = nOVR & ~nAS ? ~(chipram | ranger ) : 1;
|
||||
assign nCDR = nOVR & ~nAS ? nCDR_S : 1;
|
||||
assign nCDW = nOVR & ~nAS ? nCDW_S : 1;
|
||||
assign nRGAE = nOVR & ~nAS ? ~chipset : 1;
|
||||
assign nBLS = nOVR & ~nAS ? nBLS_S : 1;
|
||||
|
||||
endmodule
|
||||
2
common/CPU/68000/tg68last/README.md
Normal file
2
common/CPU/68000/tg68last/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# TG68K.C
|
||||
switchable 68K CPU-Core
|
||||
4
common/CPU/68000/tg68last/TG68K.qip
Normal file
4
common/CPU/68000/tg68last/TG68K.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) TG68K.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) TG68K_ALU.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) TG68K_Pack.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) TG68KdotC_Kernel.vhd ]
|
||||
212
common/CPU/68000/tg68last/TG68K.vhd
Normal file
212
common/CPU/68000/tg68last/TG68K.vhd
Normal file
@@ -0,0 +1,212 @@
|
||||
-- (c) 2020 d18c7db(a)hotmail
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the GNU General Public License version 3 or, at your option,
|
||||
-- any later version as published by the Free Software Foundation.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
--
|
||||
-- For full details, see the GNU General Public License at www.gnu.org/licenses
|
||||
--
|
||||
-- This file is a wrapper around the TG68KdotC_Kernel
|
||||
-- to adapt it to the real chip pinout and signal timings
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
--pragma translate_off
|
||||
use ieee.std_logic_textio.all;
|
||||
use std.textio.all;
|
||||
--pragma translate_on
|
||||
|
||||
entity TG68K is
|
||||
port(
|
||||
CLK : in std_logic;
|
||||
RST : in std_logic;
|
||||
clkena_ext : in std_logic;
|
||||
DTACK : in std_logic;
|
||||
VPA : in std_logic;
|
||||
IPL : in std_logic_vector( 2 downto 0);
|
||||
DI : in std_logic_vector(15 downto 0);
|
||||
|
||||
AS : out std_logic;
|
||||
UDS : out std_logic;
|
||||
LDS : out std_logic;
|
||||
WR : out std_logic;
|
||||
FC : out std_logic_vector( 2 downto 0);
|
||||
ADDR : out std_logic_vector(23 downto 0);
|
||||
DO : out std_logic_vector(15 downto 0);
|
||||
|
||||
cpusel : in std_logic_vector( 1 downto 0);
|
||||
nRSTout : out std_logic
|
||||
);
|
||||
end TG68K;
|
||||
|
||||
architecture logic of TG68K is
|
||||
signal clk_ena : std_logic:='0';
|
||||
signal as_ena : std_logic:='0';
|
||||
signal nUDS : std_logic:='0';
|
||||
signal nLDS : std_logic:='0';
|
||||
signal nWR : std_logic:='0';
|
||||
signal clkena_in : std_logic:='0';
|
||||
signal skipFetch : std_logic:='0';
|
||||
signal phase : std_logic_vector( 1 downto 0):=(others=>'0');
|
||||
signal busstate : std_logic_vector( 1 downto 0):=(others=>'0');
|
||||
signal data_latch : std_logic_vector(15 downto 0):=(others=>'0');
|
||||
signal addr_out : std_logic_vector(31 downto 0):=(others=>'0');
|
||||
signal data_out : std_logic_vector(15 downto 0):=(others=>'0');
|
||||
|
||||
begin
|
||||
--pragma translate_off
|
||||
debug_writemem : process
|
||||
file file_xx : TEXT open WRITE_MODE is "..\..\SIM\RAM.log";
|
||||
variable s : line;
|
||||
begin
|
||||
wait until falling_edge(CLK);
|
||||
if phase="11" and busstate="10" then -- mem read
|
||||
if addr_out(23 downto 8) = x"0000" then
|
||||
-- reading vector table
|
||||
write(s, " R VECT "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_latch); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
elsif addr_out(23 downto 12) = x"038" then
|
||||
-- Slapstic
|
||||
write(s, " R SLAP "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_latch); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
end if;
|
||||
end if;
|
||||
if phase="11" and busstate="11" then -- mem write
|
||||
case addr_out(23 downto 12) is
|
||||
when x"038" =>
|
||||
-- Slapstic
|
||||
write(s, " W SLAP "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"800" | x"801" =>
|
||||
-- Program RAM
|
||||
write(s, " W PROG "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"802" =>
|
||||
-- EEPROM
|
||||
write(s, " W EROM "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
-- special
|
||||
when x"803" =>
|
||||
if addr_out(11 downto 0) = x"100" then
|
||||
-- 803100 Watchdog reset
|
||||
write(s, " W WDOG "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
elsif addr_out(11 downto 0) = x"12E" then
|
||||
-- 80312E Sound CPU reset
|
||||
write(s, " W SRST "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
elsif addr_out(11 downto 0) = x"140" then
|
||||
-- 803140 VBLANK IRQ acknowledge
|
||||
write(s, " W VBLK "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
elsif addr_out(11 downto 0) = x"150" then
|
||||
-- 803150 EEPROM enable
|
||||
write(s, " W EENA "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
elsif addr_out(11 downto 0) = x"170" then
|
||||
-- 803170 Sound command write
|
||||
write(s, " W WSND "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
else
|
||||
write(s, " W XXXX "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
end if;
|
||||
when x"900" | x"901" =>
|
||||
-- PF RAM
|
||||
write(s, " W PF "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"902" | x"903" =>
|
||||
-- MO RAM
|
||||
write(s, " W MO "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"904" =>
|
||||
-- Spare RAM
|
||||
write(s, "W SPAR ", right, 34); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- "); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"905" =>
|
||||
-- PF Y scroll
|
||||
if addr_out(11 downto 0) = x"F6E" then
|
||||
write(s, " W YSCR "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
else
|
||||
-- AL RAM
|
||||
write(s, " W AL "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
end if;
|
||||
when x"910" =>
|
||||
-- Palette RAM
|
||||
write(s, " W PAL "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when x"930" =>
|
||||
-- 930000 Playfield X scroll
|
||||
write(s, " W XSCR "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
when others => null;
|
||||
-- dump any other writes also
|
||||
write(s, " W XXXX "); hwrite(s, addr_out); write(s, ": "); hwrite(s, data_out); write(s, " "); write(s, nUDS); write(s, nLDS); write(s, " -- ", right, 30); write(s, time'image(now), right, 18); writeline(file_xx,s);
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
--pragma translate_on
|
||||
|
||||
ADDR <= addr_out(23 downto 0);
|
||||
DO<=data_out;
|
||||
u_TG68K : entity work.TG68KdotC_Kernel
|
||||
generic map(
|
||||
SR_Read => 2, --0=>user, 1=>privileged, 2=>switchable with CPU(0)
|
||||
VBR_Stackframe => 2, --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
|
||||
extAddr_Mode => 2, --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
||||
MUL_Mode => 2, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
|
||||
DIV_Mode => 2, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
|
||||
BitField => 2 --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
||||
)
|
||||
port map(
|
||||
clk => CLK,
|
||||
nReset => RST,
|
||||
clkena_in => clkena_in,
|
||||
data_in => data_latch,
|
||||
IPL => IPL,
|
||||
IPL_autovector => '1',
|
||||
addr_out => addr_out,
|
||||
data_write => data_out,
|
||||
nWr => nWR,
|
||||
nUDS => nUDS,
|
||||
nLDS => nLDS,
|
||||
nResetOut => nRSTout,
|
||||
FC => FC,
|
||||
|
||||
CPU => cpusel,
|
||||
busstate => busstate,
|
||||
skipFetch => skipFetch,
|
||||
VBR_out => open
|
||||
);
|
||||
|
||||
clkena_in <= '1' when clkena_ext='1' and (busstate="01" or clk_ena='1') else '0';
|
||||
|
||||
AS <= '1' when busstate="01" else as_ena;
|
||||
WR <= '1' when busstate="01" else as_ena or nWR;
|
||||
UDS <= '1' when busstate="01" else as_ena or nUDS;
|
||||
LDS <= '1' when busstate="01" else as_ena or nLDS;
|
||||
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if RST='0' then
|
||||
phase <= "00";
|
||||
clk_ena <= '0';
|
||||
as_ena <= '1';
|
||||
else
|
||||
clk_ena <= '0';
|
||||
as_ena <= '1';
|
||||
case phase is
|
||||
when "00" =>
|
||||
if busstate/="01" then
|
||||
phase <= "01";
|
||||
as_ena <= '0';
|
||||
end if;
|
||||
when "01" =>
|
||||
phase <= "10";
|
||||
as_ena <= '0';
|
||||
when "10" =>
|
||||
if DTACK='0' or VPA='0' then
|
||||
phase <= "11";
|
||||
data_latch <= DI;
|
||||
else
|
||||
as_ena <= '0';
|
||||
end if;
|
||||
when "11" =>
|
||||
phase <= "00";
|
||||
clk_ena <= '1';
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
end;
|
||||
1279
common/CPU/68000/tg68last/TG68K_ALU.vhd
Normal file
1279
common/CPU/68000/tg68last/TG68K_ALU.vhd
Normal file
File diff suppressed because it is too large
Load Diff
180
common/CPU/68000/tg68last/TG68K_Pack.vhd
Normal file
180
common/CPU/68000/tg68last/TG68K_Pack.vhd
Normal file
@@ -0,0 +1,180 @@
|
||||
------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------
|
||||
-- --
|
||||
-- Copyright (c) 2009-2020 Tobias Gubener --
|
||||
-- Patches by MikeJ, Till Harbaum, Rok Krajnk, ... --
|
||||
-- Subdesign fAMpIGA by TobiFlex --
|
||||
-- --
|
||||
-- This source file is free software: you can redistribute it and/or modify --
|
||||
-- it under the terms of the GNU Lesser 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 <http://www.gnu.org/licenses/>. --
|
||||
-- --
|
||||
------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
package TG68K_Pack is
|
||||
|
||||
type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_AnXn1, ld_AnXn2, st_dAn1, ld_AnXnbd1, ld_AnXnbd2, ld_AnXnbd3,
|
||||
ld_229_1, ld_229_2, ld_229_3, ld_229_4, st_229_1, st_229_2, st_229_3, st_229_4,
|
||||
st_AnXn1, st_AnXn2, bra1, bsr1, bsr2, nopnop, dbcc1, movem1, movem2, movem3,
|
||||
andi, pack1, pack2, pack3, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, rte2, rte3,
|
||||
rte4, rte5, rtd1, rtd2, trap00, trap0, trap1, trap2, trap3, cas1, cas2, cas21, cas22, cas23, cas24,
|
||||
cas25, cas26, cas27, cas28, chk20, chk21, chk22, chk23, chk24,
|
||||
trap4, trap5, trap6, movec1, movep1, movep2, movep3, movep4, movep5, rota1, bf1,
|
||||
mul1, mul2, mul_end1, mul_end2, div1, div2, div3, div4, div_end1, div_end2);
|
||||
|
||||
constant opcMOVE : integer := 0; --
|
||||
constant opcMOVEQ : integer := 1; --
|
||||
constant opcMOVESR : integer := 2; --
|
||||
constant opcADD : integer := 3; --
|
||||
constant opcADDQ : integer := 4; --
|
||||
constant opcOR : integer := 5; --
|
||||
constant opcAND : integer := 6; --
|
||||
constant opcEOR : integer := 7; --
|
||||
constant opcCMP : integer := 8; --
|
||||
constant opcROT : integer := 9; --
|
||||
constant opcCPMAW : integer := 10;
|
||||
constant opcEXT : integer := 11; --
|
||||
constant opcABCD : integer := 12; --
|
||||
constant opcSBCD : integer := 13; --
|
||||
constant opcBITS : integer := 14; --
|
||||
constant opcSWAP : integer := 15; --
|
||||
constant opcScc : integer := 16; --
|
||||
constant andiSR : integer := 17; --
|
||||
constant eoriSR : integer := 18; --
|
||||
constant oriSR : integer := 19; --
|
||||
constant opcMULU : integer := 20; --
|
||||
constant opcDIVU : integer := 21; --
|
||||
constant dispouter : integer := 22; --
|
||||
constant rot_nop : integer := 23; --
|
||||
constant ld_rot_cnt : integer := 24; --
|
||||
constant writePC_add : integer := 25; --
|
||||
constant ea_data_OP1 : integer := 26; --
|
||||
constant ea_data_OP2 : integer := 27; --
|
||||
constant use_XZFlag : integer := 28; --
|
||||
constant get_bfoffset : integer := 29; --
|
||||
constant save_memaddr : integer := 30; --
|
||||
constant opcCHK : integer := 31; --
|
||||
constant movec_rd : integer := 32; --
|
||||
constant movec_wr : integer := 33; --
|
||||
constant Regwrena : integer := 34; --
|
||||
constant update_FC : integer := 35; --
|
||||
constant linksp : integer := 36; --
|
||||
constant movepl : integer := 37; --
|
||||
constant update_ld : integer := 38; --
|
||||
constant OP1addr : integer := 39; --
|
||||
constant write_reg : integer := 40; --
|
||||
constant changeMode : integer := 41; --
|
||||
constant ea_build : integer := 42; --
|
||||
constant trap_chk : integer := 43; --
|
||||
constant store_ea_data : integer := 44; --
|
||||
constant addrlong : integer := 45; --
|
||||
constant postadd : integer := 46; --
|
||||
constant presub : integer := 47; --
|
||||
constant subidx : integer := 48; --
|
||||
constant no_Flags : integer := 49; --
|
||||
constant use_SP : integer := 50; --
|
||||
constant to_CCR : integer := 51; --
|
||||
constant to_SR : integer := 52; --
|
||||
constant OP2out_one : integer := 53; --
|
||||
constant OP1out_zero : integer := 54; --
|
||||
constant mem_addsub : integer := 55; --
|
||||
constant addsub : integer := 56; --
|
||||
constant directPC : integer := 57; --
|
||||
constant direct_delta : integer := 58; --
|
||||
constant directSR : integer := 59; --
|
||||
constant directCCR : integer := 60; --
|
||||
constant exg : integer := 61; --
|
||||
constant get_ea_now : integer := 62; --
|
||||
constant ea_to_pc : integer := 63; --
|
||||
constant hold_dwr : integer := 64; --
|
||||
constant to_USP : integer := 65; --
|
||||
constant from_USP : integer := 66; --
|
||||
constant write_lowlong : integer := 67; --
|
||||
constant write_reminder : integer := 68; --
|
||||
constant movem_action : integer := 69; --
|
||||
constant briefext : integer := 70; --
|
||||
constant get_2ndOPC : integer := 71; --
|
||||
constant mem_byte : integer := 72; --
|
||||
constant longaktion : integer := 73; --
|
||||
constant opcRESET : integer := 74; --
|
||||
constant opcBF : integer := 75; --
|
||||
constant opcBFwb : integer := 76; --
|
||||
constant opcPACK : integer := 77; --
|
||||
constant opcUNPACK : integer := 78; --
|
||||
constant hold_ea_data : integer := 79; --
|
||||
constant store_ea_packdata : integer := 80; --
|
||||
constant exec_BS : integer := 81; --
|
||||
constant hold_OP2 : integer := 82; --
|
||||
constant restore_ADDR : integer := 83; --
|
||||
constant alu_exec : integer := 84; --
|
||||
constant alu_move : integer := 85; --
|
||||
constant alu_setFlags : integer := 86; --
|
||||
constant opcCHK2 : integer := 87; --
|
||||
constant opcEXTB : integer := 88; --
|
||||
|
||||
constant lastOpcBit : integer := 88;
|
||||
|
||||
component TG68K_ALU
|
||||
generic(
|
||||
MUL_Mode :integer; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
|
||||
MUL_Hardware :integer; --0=>no, 1=>yes,
|
||||
DIV_Mode :integer; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
|
||||
BarrelShifter :integer --0=>no, 1=>yes, 2=>switchable with CPU(1)
|
||||
);
|
||||
port(
|
||||
clk : in std_logic;
|
||||
Reset : in std_logic;
|
||||
CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only some parts - yet)
|
||||
clkena_lw : in std_logic:='1';
|
||||
execOPC : in bit;
|
||||
decodeOPC : in bit;
|
||||
exe_condition : in std_logic;
|
||||
exec_tas : in std_logic;
|
||||
long_start : in bit;
|
||||
non_aligned : in std_logic;
|
||||
movem_presub : in bit;
|
||||
set_stop : in bit;
|
||||
Z_error : in bit;
|
||||
rot_bits : in std_logic_vector(1 downto 0);
|
||||
exec : in bit_vector(lastOpcBit downto 0);
|
||||
OP1out : in std_logic_vector(31 downto 0);
|
||||
OP2out : in std_logic_vector(31 downto 0);
|
||||
reg_QA : in std_logic_vector(31 downto 0);
|
||||
reg_QB : in std_logic_vector(31 downto 0);
|
||||
opcode : in std_logic_vector(15 downto 0);
|
||||
-- datatype : in std_logic_vector(1 downto 0);
|
||||
exe_opcode : in std_logic_vector(15 downto 0);
|
||||
exe_datatype : in std_logic_vector(1 downto 0);
|
||||
sndOPC : in std_logic_vector(15 downto 0);
|
||||
last_data_read : in std_logic_vector(15 downto 0);
|
||||
data_read : in std_logic_vector(15 downto 0);
|
||||
FlagsSR : in std_logic_vector(7 downto 0);
|
||||
micro_state : in micro_states;
|
||||
bf_ext_in : in std_logic_vector(7 downto 0);
|
||||
bf_ext_out : out std_logic_vector(7 downto 0);
|
||||
bf_shift : in std_logic_vector(5 downto 0);
|
||||
bf_width : in std_logic_vector(5 downto 0);
|
||||
bf_ffo_offset : in std_logic_vector(31 downto 0);
|
||||
bf_loffset : in std_logic_vector(4 downto 0);
|
||||
|
||||
set_V_Flag : buffer bit;
|
||||
Flags : buffer std_logic_vector(7 downto 0);
|
||||
c_out : buffer std_logic_vector(2 downto 0);
|
||||
addsub_q : buffer std_logic_vector(31 downto 0);
|
||||
ALUout : out std_logic_vector(31 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
end;
|
||||
4103
common/CPU/68000/tg68last/TG68KdotC_Kernel.vhd
Normal file
4103
common/CPU/68000/tg68last/TG68KdotC_Kernel.vhd
Normal file
File diff suppressed because it is too large
Load Diff
10
common/CPU/MC6809/mc6809.qip
Normal file
10
common/CPU/MC6809/mc6809.qip
Normal file
@@ -0,0 +1,10 @@
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80pa.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80s.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80se.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80sed.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T8080se.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Reg.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_MCode.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_ALU.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T80_Pack.vhd ]
|
||||
64
common/Sound/jt51/deprecated/jt51_sh2.v
Normal file
64
common/Sound/jt51/deprecated/jt51_sh2.v
Normal file
@@ -0,0 +1,64 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_sh2 #(parameter width=5, stages=32 )
|
||||
(
|
||||
input clk,
|
||||
input en,
|
||||
input ld,
|
||||
input [width-1:0] din,
|
||||
output [width-1:0] drop
|
||||
);
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for( i=0; i<width; i=i+1) begin: shifter
|
||||
jt51_sh1 #(.stages(stages)) u_sh1(
|
||||
.clk ( clk ),
|
||||
.en ( en ),
|
||||
.ld ( ld ),
|
||||
.din ( din[i] ),
|
||||
.drop ( drop[i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
module jt51_sh1 #(parameter stages=32)
|
||||
(
|
||||
input clk,
|
||||
input en,
|
||||
input ld,
|
||||
input din,
|
||||
output drop
|
||||
);
|
||||
|
||||
reg [stages-1:0] shift;
|
||||
assign drop = shift[0];
|
||||
wire next = ld ? din : drop;
|
||||
|
||||
always @(posedge clk )
|
||||
if( en )
|
||||
shift <= {next, shift[stages-1:1]};
|
||||
|
||||
endmodule
|
||||
63
common/Sound/jt51/filter/jt51_dac2.v
Normal file
63
common/Sound/jt51/filter/jt51_dac2.v
Normal file
@@ -0,0 +1,63 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 9th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
input sampling rate must be the same as clk frequency
|
||||
interpolate input signal accordingly to get the
|
||||
right sampling rate.
|
||||
|
||||
Refer to sigmadelta.ods to see how the internal width (int_w)
|
||||
was determined.
|
||||
|
||||
*/
|
||||
|
||||
module jt51_dac2 #(parameter width=16)
|
||||
(
|
||||
input clk,
|
||||
input rst,
|
||||
input signed [width-1:0] din,
|
||||
output reg dout
|
||||
);
|
||||
|
||||
parameter int_w = width+5;
|
||||
|
||||
reg [int_w-1:0] y, error, error_1, error_2;
|
||||
|
||||
wire [width-1:0] undin = { ~din[width-1], din[width-2:0] };
|
||||
|
||||
always @(*) begin
|
||||
y <= undin + { error_1, 1'b0} - error_2;
|
||||
dout <= ~y[int_w-1];
|
||||
error <= y - {dout, {width{1'b0}}};
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
error_1 <= {int_w{1'b0}};
|
||||
error_2 <= {int_w{1'b0}};
|
||||
end else begin
|
||||
error_1 <= error;
|
||||
error_2 <= error_1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
189
common/Sound/jt51/filter/jt51_fir.v
Normal file
189
common/Sound/jt51/filter/jt51_fir.v
Normal file
@@ -0,0 +1,189 @@
|
||||
/* This file is part of jt51.
|
||||
|
||||
jt51 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.
|
||||
|
||||
jt51 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 jt51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_fir
|
||||
#(parameter data_width=9, output_width=12, coeff_width=9,
|
||||
addr_width=7, stages=81, acc_extra=1)
|
||||
(
|
||||
input clk,
|
||||
input rst,
|
||||
input sample,
|
||||
input signed [data_width-1:0] left_in,
|
||||
input signed [data_width-1:0] right_in,
|
||||
input signed [coeff_width-1:0] coeff,
|
||||
output reg [addr_width-1:0] cnt,
|
||||
output reg signed [output_width-1:0] left_out,
|
||||
output reg signed [output_width-1:0] right_out,
|
||||
output reg sample_out
|
||||
);
|
||||
|
||||
wire signed [data_width-1:0] mem_left, mem_right;
|
||||
|
||||
// pointers
|
||||
reg [addr_width-1:0] addr_left, addr_right,
|
||||
forward, rev, in_pointer;
|
||||
|
||||
|
||||
reg update, last_sample;
|
||||
|
||||
reg [1:0] state;
|
||||
parameter IDLE=2'b00, LEFT=2'b01, RIGHT=2'b10;
|
||||
|
||||
jt51_fir_ram #(.data_width(data_width),.addr_width(addr_width)) chain_left(
|
||||
.clk ( clk ),
|
||||
.data ( left_in ),
|
||||
.addr ( addr_left ),
|
||||
.we ( update ),
|
||||
.q ( mem_left )
|
||||
);
|
||||
|
||||
jt51_fir_ram #(.data_width(data_width),.addr_width(addr_width)) chain_right(
|
||||
.clk ( clk ),
|
||||
.data ( right_in ),
|
||||
.addr ( addr_right),
|
||||
.we ( update ),
|
||||
.q ( mem_right)
|
||||
);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst )
|
||||
{ update, last_sample } <= 2'b00;
|
||||
else begin
|
||||
last_sample <= sample;
|
||||
update <= sample && !last_sample;
|
||||
end
|
||||
|
||||
parameter mac_width=(data_width+1)+coeff_width;
|
||||
parameter acc_width=output_width; // mac_width+3;
|
||||
reg signed [acc_width-1:0] acc_left, acc_right;
|
||||
|
||||
//integer acc,mac;
|
||||
wire [addr_width-1:0] next = cnt+1'b1;
|
||||
|
||||
reg signed [data_width:0] sum;
|
||||
|
||||
wire last_stage = cnt==(stages-1)/2;
|
||||
|
||||
reg signed [data_width-1:0] buffer_left, buffer_right;
|
||||
|
||||
always @(*) begin
|
||||
if( state==LEFT) begin
|
||||
if( last_stage )
|
||||
sum = buffer_left;
|
||||
else
|
||||
sum = buffer_left + mem_left;
|
||||
end
|
||||
else begin
|
||||
if( last_stage )
|
||||
sum = buffer_right;
|
||||
else
|
||||
sum = buffer_right + mem_right;
|
||||
end
|
||||
end
|
||||
|
||||
wire signed [mac_width-1:0] mac = coeff*sum;
|
||||
wire signed [acc_width-1:0] mac_trim = mac[mac_width-1:mac_width-acc_width];
|
||||
//wire signed [acc_width-1:0] mac_trimx = (coeff*sum)>>>(mac_width-acc_width);
|
||||
|
||||
wire [addr_width-1:0]
|
||||
in_pointer_next = in_pointer - 1'b1,
|
||||
forward_next = forward+1'b1,
|
||||
rev_next = rev-1'b1;
|
||||
|
||||
always @(*) begin
|
||||
case( state )
|
||||
default: begin
|
||||
addr_left = update ? rev : in_pointer;
|
||||
addr_right= in_pointer;
|
||||
end
|
||||
LEFT: begin
|
||||
addr_left = forward_next;
|
||||
addr_right= rev;
|
||||
end
|
||||
RIGHT: begin
|
||||
if( cnt==(stages-1)/2 ) begin
|
||||
addr_left = in_pointer_next;
|
||||
addr_right= in_pointer_next;
|
||||
end
|
||||
else begin
|
||||
addr_left = rev_next;
|
||||
addr_right= forward;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
sample_out <= 1'b0;
|
||||
state <= IDLE;
|
||||
in_pointer <= 7'd0;
|
||||
//addr_left <= in_pointer;
|
||||
//addr_right<= in_pointer;
|
||||
end else begin
|
||||
case(state)
|
||||
default: begin
|
||||
if( update ) begin
|
||||
state <= LEFT;
|
||||
buffer_left <= left_in;
|
||||
//addr_left <= rev;
|
||||
end
|
||||
cnt <= 6'd0;
|
||||
acc_left <= {acc_width{1'b0}};
|
||||
acc_right <= {acc_width{1'b0}};
|
||||
rev <= in_pointer+stages-1'b1;
|
||||
forward <= in_pointer;
|
||||
sample_out <= 1'b0;
|
||||
end
|
||||
LEFT: begin
|
||||
acc_left <= acc_left + mac_trim;
|
||||
//addr_left <= forward_next;
|
||||
|
||||
buffer_right <= mem_right;
|
||||
//addr_right <= rev;
|
||||
|
||||
forward<=forward_next;
|
||||
state <= RIGHT;
|
||||
end
|
||||
RIGHT:
|
||||
if( cnt==(stages-1)/2 ) begin
|
||||
left_out <= acc_left;
|
||||
right_out <= acc_right + mac_trim;
|
||||
sample_out <= 1'b1;
|
||||
in_pointer <= in_pointer_next;
|
||||
//addr_left <= in_pointer_next;
|
||||
//addr_right<= in_pointer_next;
|
||||
state <= IDLE;
|
||||
end else begin
|
||||
acc_right <= acc_right + mac_trim;
|
||||
//addr_right <= forward;
|
||||
|
||||
buffer_left <= mem_left;
|
||||
//addr_left <= rev_next;
|
||||
cnt<=next;
|
||||
rev<=rev-1'b1;
|
||||
state <= LEFT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule // jt51_fir8
|
||||
83
common/Sound/jt51/filter/jt51_fir4.v
Normal file
83
common/Sound/jt51/filter/jt51_fir4.v
Normal file
@@ -0,0 +1,83 @@
|
||||
/* This file is part of jt51.
|
||||
|
||||
jt51 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.
|
||||
|
||||
jt51 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 jt51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_fir4
|
||||
#(parameter data_width=9, output_width=12)
|
||||
(
|
||||
input clk,
|
||||
input rst,
|
||||
input sample,
|
||||
input signed [data_width-1:0] left_in,
|
||||
input signed [data_width-1:0] right_in,
|
||||
output signed [output_width-1:0] left_out,
|
||||
output signed [output_width-1:0] right_out,
|
||||
output sample_out
|
||||
);
|
||||
|
||||
parameter coeff_width=9;
|
||||
parameter stages=21;
|
||||
parameter addr_width=5;
|
||||
parameter acc_extra=1;
|
||||
|
||||
reg signed [coeff_width-1:0] coeff;
|
||||
wire [addr_width-1:0] cnt;
|
||||
|
||||
jt51_fir #(
|
||||
.data_width (data_width),
|
||||
.output_width(output_width),
|
||||
.coeff_width (coeff_width),
|
||||
.stages (stages),
|
||||
.addr_width (addr_width),
|
||||
.acc_extra (acc_extra)
|
||||
) i_jt51_fir (
|
||||
.clk (clk ),
|
||||
.rst (rst ),
|
||||
.sample (sample ),
|
||||
.left_in (left_in ),
|
||||
.right_in (right_in ),
|
||||
.left_out (left_out ),
|
||||
.right_out (right_out ),
|
||||
.sample_out(sample_out),
|
||||
.cnt (cnt ),
|
||||
.coeff (coeff )
|
||||
);
|
||||
|
||||
|
||||
always @(*)
|
||||
case( cnt )
|
||||
5'd0: coeff = 9'd18;
|
||||
5'd1: coeff = 9'd24;
|
||||
5'd2: coeff = 9'd40;
|
||||
5'd3: coeff = 9'd66;
|
||||
5'd4: coeff = 9'd99;
|
||||
5'd5: coeff = 9'd134;
|
||||
5'd6: coeff = 9'd171;
|
||||
5'd7: coeff = 9'd205;
|
||||
5'd8: coeff = 9'd231;
|
||||
5'd9: coeff = 9'd249;
|
||||
5'd10: coeff = 9'd255;
|
||||
default: coeff = 9'd0;
|
||||
endcase
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
111
common/Sound/jt51/filter/jt51_fir8.v
Normal file
111
common/Sound/jt51/filter/jt51_fir8.v
Normal file
@@ -0,0 +1,111 @@
|
||||
/* This file is part of jt51.
|
||||
|
||||
jt51 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.
|
||||
|
||||
jt51 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 jt51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_fir8
|
||||
#(parameter data_width=9, output_width=12)
|
||||
(
|
||||
input clk,
|
||||
input rst,
|
||||
input sample,
|
||||
input signed [data_width-1:0] left_in,
|
||||
input signed [data_width-1:0] right_in,
|
||||
output signed [output_width-1:0] left_out,
|
||||
output signed [output_width-1:0] right_out,
|
||||
output sample_out
|
||||
);
|
||||
|
||||
parameter coeff_width=9;
|
||||
parameter stages=81;
|
||||
parameter addr_width=7;
|
||||
parameter acc_extra=1;
|
||||
|
||||
reg signed [coeff_width-1:0] coeff;
|
||||
wire [addr_width-1:0] cnt;
|
||||
|
||||
jt51_fir #(
|
||||
.data_width (data_width),
|
||||
.output_width(output_width),
|
||||
.coeff_width (coeff_width),
|
||||
.stages (stages),
|
||||
.addr_width (addr_width),
|
||||
.acc_extra (acc_extra)
|
||||
) i_jt51_fir (
|
||||
.clk (clk ),
|
||||
.rst (rst ),
|
||||
.sample (sample ),
|
||||
.left_in (left_in ),
|
||||
.right_in (right_in ),
|
||||
.left_out (left_out ),
|
||||
.right_out (right_out ),
|
||||
.sample_out(sample_out),
|
||||
.cnt (cnt ),
|
||||
.coeff (coeff )
|
||||
);
|
||||
|
||||
|
||||
always @(*)
|
||||
case( cnt )
|
||||
7'd0: coeff = -9'd1;
|
||||
7'd1: coeff = 9'd0;
|
||||
7'd2: coeff = 9'd1;
|
||||
7'd3: coeff = 9'd1;
|
||||
7'd4: coeff = 9'd2;
|
||||
7'd5: coeff = 9'd3;
|
||||
7'd6: coeff = 9'd4;
|
||||
7'd7: coeff = 9'd4;
|
||||
7'd8: coeff = 9'd5;
|
||||
7'd9: coeff = 9'd5;
|
||||
7'd10: coeff = 9'd5;
|
||||
7'd11: coeff = 9'd4;
|
||||
7'd12: coeff = 9'd3;
|
||||
7'd13: coeff = 9'd1;
|
||||
7'd14: coeff = -9'd2;
|
||||
7'd15: coeff = -9'd6;
|
||||
7'd16: coeff = -9'd11;
|
||||
7'd17: coeff = -9'd16;
|
||||
7'd18: coeff = -9'd21;
|
||||
7'd19: coeff = -9'd26;
|
||||
7'd20: coeff = -9'd30;
|
||||
7'd21: coeff = -9'd33;
|
||||
7'd22: coeff = -9'd34;
|
||||
7'd23: coeff = -9'd32;
|
||||
7'd24: coeff = -9'd28;
|
||||
7'd25: coeff = -9'd21;
|
||||
7'd26: coeff = -9'd10;
|
||||
7'd27: coeff = 9'd4;
|
||||
7'd28: coeff = 9'd22;
|
||||
7'd29: coeff = 9'd42;
|
||||
7'd30: coeff = 9'd65;
|
||||
7'd31: coeff = 9'd91;
|
||||
7'd32: coeff = 9'd117;
|
||||
7'd33: coeff = 9'd142;
|
||||
7'd34: coeff = 9'd168;
|
||||
7'd35: coeff = 9'd192;
|
||||
7'd36: coeff = 9'd213;
|
||||
7'd37: coeff = 9'd231;
|
||||
7'd38: coeff = 9'd244;
|
||||
7'd39: coeff = 9'd252;
|
||||
7'd40: coeff = 9'd255;
|
||||
default: coeff = 9'd0;
|
||||
endcase // cnt
|
||||
|
||||
endmodule
|
||||
43
common/Sound/jt51/filter/jt51_fir_ram.v
Normal file
43
common/Sound/jt51/filter/jt51_fir_ram.v
Normal file
@@ -0,0 +1,43 @@
|
||||
/* This file is part of jt51.
|
||||
|
||||
jt51 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.
|
||||
|
||||
jt51 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 jt51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_fir_ram
|
||||
#(parameter data_width=8, parameter addr_width=7)
|
||||
(
|
||||
input [(data_width-1):0] data,
|
||||
input [(addr_width-1):0] addr,
|
||||
input we, clk,
|
||||
output [(data_width-1):0] q
|
||||
);
|
||||
|
||||
(* ramstyle = "no_rw_check" *) reg [data_width-1:0] ram[2**addr_width-1:0];
|
||||
|
||||
reg [addr_width-1:0] addr_reg;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (we)
|
||||
ram[addr] <= data;
|
||||
addr_reg <= addr;
|
||||
end
|
||||
|
||||
assign q = ram[addr_reg];
|
||||
endmodule
|
||||
130
common/Sound/jt51/filter/jt51_interpol.v
Normal file
130
common/Sound/jt51/filter/jt51_interpol.v
Normal file
@@ -0,0 +1,130 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_interpol(
|
||||
input clk, // Use a clock at least 162*2 times faster than JT51 sampling rate
|
||||
input rst,
|
||||
input sample_in,
|
||||
input signed [15:0] left_in,
|
||||
input signed [15:0] right_in,
|
||||
// mix in other sound sources, like ADPCM sound of arcade boards
|
||||
// other sound sources should be at the same
|
||||
// sampling frequency than the FM sound
|
||||
// for best results
|
||||
input signed [15:0] left_other,
|
||||
input signed [15:0] right_other,
|
||||
|
||||
output signed [15:0] out_l,
|
||||
output signed [15:0] out_r,
|
||||
output sample_out
|
||||
);
|
||||
|
||||
/* max_clk_count is chosen so as to divide the input clock to
|
||||
obtain a 32xFs frequency.
|
||||
Fs = JT51 sampling frequency, normally ~55kHz
|
||||
32xFs = 1.78MHz
|
||||
If this module's clock is 50MHz then
|
||||
max_clk_count = 50/1.78=28
|
||||
|
||||
The division must be exact, otherwise samples will get out of sync
|
||||
eventually and sound will get distorted.
|
||||
max_clk_count*32 is the number of clock ticks that the FIR module
|
||||
has to process the two sound channels. Each channels needs at least
|
||||
162 clock ticks, so in total it needs just over 324 ticks.
|
||||
(162 is the number of stages of the filter)
|
||||
|
||||
Using 50MHz and max_clk_count=28 gives 896 clock ticks, which is
|
||||
more than enough.
|
||||
|
||||
*/
|
||||
parameter max_clk_count = 7'd111;
|
||||
|
||||
reg [15:0] fir_left_in, fir_right_in, left_mux, right_mux;
|
||||
reg fir_sample_in;
|
||||
reg fir4_sample_in;
|
||||
|
||||
|
||||
reg [2:0] state;
|
||||
reg [6:0] cnt;
|
||||
|
||||
always @(*)
|
||||
case( state )
|
||||
3'd0: { left_mux, right_mux } <= { left_in, right_in};
|
||||
3'd3: { left_mux, right_mux } <= { left_other, right_other};
|
||||
default: { left_mux, right_mux } <= 32'd0;
|
||||
endcase
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
state <= 2'b0;
|
||||
fir_sample_in <= 1'b0;
|
||||
cnt <= 6'd0;
|
||||
end else begin
|
||||
fir4_sample_in <= ( cnt==0 || cnt==28 || cnt==56 || cnt==84 );
|
||||
if( cnt==max_clk_count ) begin
|
||||
cnt <= 6'd0;
|
||||
state <= state+1'b1;
|
||||
fir_sample_in <= 1'b1;
|
||||
{fir_left_in,fir_right_in} <= { left_mux, right_mux };
|
||||
end
|
||||
else begin
|
||||
cnt <= cnt + 1'b1;
|
||||
fir_sample_in <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
localparam fir8_w=16; // at least 16
|
||||
localparam fir4_w=16; // at least 16
|
||||
wire [fir8_w-1:0] fir8_out_l, fir8_out_r;
|
||||
wire [fir4_w-1:0] fir4_out_l, fir4_out_r;
|
||||
|
||||
assign out_l = fir4_out_l[15:0];
|
||||
assign out_r = fir4_out_r[15:0];
|
||||
//assign out_l = fir8_out_l[15:0];
|
||||
//assign out_r = fir8_out_r[15:0];
|
||||
|
||||
//wire fir8_sample;
|
||||
|
||||
jt51_fir8 #(.data_width(16), .output_width(fir8_w)) u_fir8 (
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.sample ( fir_sample_in ),
|
||||
.left_in ( fir_left_in ),
|
||||
.right_in ( fir_right_in ),
|
||||
.left_out ( fir8_out_l ),
|
||||
.right_out ( fir8_out_r )
|
||||
// .sample_out ( fir8_sample )
|
||||
);
|
||||
|
||||
jt51_fir4 #(.data_width(16), .output_width(fir4_w)) u_fir4 (
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.sample ( fir4_sample_in),
|
||||
.left_in ( fir8_out_l[fir8_w-1:fir8_w-16] ),
|
||||
.right_in ( fir8_out_r[fir8_w-1:fir8_w-16] ),
|
||||
.left_out ( fir4_out_l ),
|
||||
.right_out ( fir4_out_r ),
|
||||
.sample_out ( sample_out )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
53
common/Sound/jt51/filter/jt51_sincf.v
Normal file
53
common/Sound/jt51/filter/jt51_sincf.v
Normal file
@@ -0,0 +1,53 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 7th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_sincf #(parameter win=1, wout=5)
|
||||
(
|
||||
input clk,
|
||||
input [win-1:0] din,
|
||||
output reg [wout-1:0] dout
|
||||
);
|
||||
|
||||
reg [win-1:0] mem[23:0];
|
||||
|
||||
genvar i;
|
||||
|
||||
|
||||
generate
|
||||
for (i=23; i>0; i=i-1) begin: meminput
|
||||
always @(posedge clk)
|
||||
mem[i] <= mem[i-1];
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
always @(posedge clk) begin
|
||||
mem[0] <= din;
|
||||
dout <= mem[0] + mem[1] + mem[2] + mem[3] +
|
||||
mem[4] + mem[5] + mem[6] + mem[7] +
|
||||
mem[8] + mem[9] + mem[10] + mem[11] +
|
||||
mem[12] + mem[13] + mem[14] + mem[15] +
|
||||
mem[16] + mem[17] + mem[18] + mem[19] +
|
||||
mem[20] + mem[21] + mem[22] + mem[23];
|
||||
end
|
||||
|
||||
endmodule
|
||||
23
common/Sound/jt51/jt51.qip
Normal file
23
common/Sound/jt51/jt51.qip
Normal file
@@ -0,0 +1,23 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_acc.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_csr_ch.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_csr_op.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_eg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_exp2lin.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_exprom.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_kon.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_lfo.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_lfo_lfsr.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_lin2exp.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_mmr.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_mod.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_noise.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_noise_lfsr.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_op.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_pg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_phinc_rom.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_phrom.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_pm.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_reg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_sh.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt51_timers.v]
|
||||
358
common/Sound/jt51/jt51.v
Normal file
358
common/Sound/jt51/jt51.v
Normal file
@@ -0,0 +1,358 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51(
|
||||
input rst, // reset
|
||||
input clk, // main clock
|
||||
input cen, // clock enable
|
||||
input cen_p1, // clock enable at half the speed
|
||||
input cs_n, // chip select
|
||||
input wr_n, // write
|
||||
input a0,
|
||||
input [7:0] din, // data in
|
||||
output [7:0] dout, // data out
|
||||
// peripheral control
|
||||
output ct1,
|
||||
output ct2,
|
||||
output irq_n, // I do not synchronize this signal
|
||||
// Low resolution output (same as real chip)
|
||||
output sample, // marks new output sample
|
||||
output signed [15:0] left,
|
||||
output signed [15:0] right,
|
||||
// Full resolution output
|
||||
output signed [15:0] xleft,
|
||||
output signed [15:0] xright,
|
||||
// unsigned outputs for sigma delta converters, full resolution
|
||||
output [15:0] dacleft,
|
||||
output [15:0] dacright
|
||||
);
|
||||
|
||||
assign dacleft = { ~xleft [15], xleft[14:0] };
|
||||
assign dacright = { ~xright[15], xright[14:0] };
|
||||
|
||||
// Timers
|
||||
wire [9:0] value_A;
|
||||
wire [7:0] value_B;
|
||||
wire load_A, load_B;
|
||||
wire enable_irq_A, enable_irq_B;
|
||||
wire clr_flag_A, clr_flag_B;
|
||||
wire flag_A, flag_B, overflow_A;
|
||||
wire zero;
|
||||
|
||||
jt51_timers u_timers(
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.rst ( rst ),
|
||||
.zero ( zero ),
|
||||
.value_A ( value_A ),
|
||||
.value_B ( value_B ),
|
||||
.load_A ( load_A ),
|
||||
.load_B ( load_B ),
|
||||
.enable_irq_A( enable_irq_A ),
|
||||
.enable_irq_B( enable_irq_B ),
|
||||
.clr_flag_A ( clr_flag_A ),
|
||||
.clr_flag_B ( clr_flag_B ),
|
||||
.flag_A ( flag_A ),
|
||||
.flag_B ( flag_B ),
|
||||
.overflow_A ( overflow_A ),
|
||||
.irq_n ( irq_n )
|
||||
);
|
||||
|
||||
/*verilator tracing_off*/
|
||||
|
||||
`ifndef JT51_ONLYTIMERS
|
||||
`define YM_TIMER_CTRL 8'h14
|
||||
|
||||
wire [1:0] rl_I;
|
||||
wire [2:0] fb_II;
|
||||
wire [2:0] con_I;
|
||||
wire [6:0] kc_I;
|
||||
wire [5:0] kf_I;
|
||||
wire [2:0] pms_I;
|
||||
wire [1:0] ams_VII;
|
||||
wire [2:0] dt1_II;
|
||||
wire [3:0] mul_VI;
|
||||
wire [6:0] tl_VII;
|
||||
wire [1:0] ks_III;
|
||||
wire [4:0] arate_II;
|
||||
wire amsen_VII;
|
||||
wire [4:0] rate1_II;
|
||||
wire [1:0] dt2_I;
|
||||
wire [4:0] rate2_II;
|
||||
wire [3:0] d1l_I;
|
||||
wire [3:0] rrate_II;
|
||||
|
||||
wire [1:0] cur_op;
|
||||
assign sample =zero;
|
||||
wire keyon_II;
|
||||
|
||||
wire [7:0] lfo_freq;
|
||||
wire [1:0] lfo_w;
|
||||
wire lfo_rst;
|
||||
wire [6:0] am;
|
||||
wire [7:0] pm;
|
||||
wire [6:0] amd, pmd;
|
||||
|
||||
wire m1_enters, m2_enters, c1_enters, c2_enters;
|
||||
wire use_prevprev1,use_internal_x,use_internal_y, use_prev2,use_prev1;
|
||||
|
||||
jt51_lfo u_lfo(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ), // should it be cen_p1?
|
||||
.zero ( zero ),
|
||||
.lfo_rst ( lfo_rst ),
|
||||
.lfo_freq ( lfo_freq ),
|
||||
.lfo_w ( lfo_w ),
|
||||
.lfo_amd ( amd ),
|
||||
.lfo_pmd ( pmd ),
|
||||
.am ( am ),
|
||||
.pm_u ( pm )
|
||||
);
|
||||
|
||||
wire [ 4:0] keycode_III;
|
||||
wire [ 9:0] ph_X;
|
||||
wire pg_rst_III;
|
||||
|
||||
jt51_pg u_pg(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ), // P1
|
||||
.cen ( cen_p1 ),
|
||||
.zero ( zero ),
|
||||
// Channel frequency
|
||||
.kc_I ( kc_I ),
|
||||
.kf_I ( kf_I ),
|
||||
// Operator multiplying
|
||||
.mul_VI ( mul_VI ),
|
||||
// Operator detuning
|
||||
.dt1_II ( dt1_II ),
|
||||
.dt2_I ( dt2_I ),
|
||||
// phase modulation from LFO
|
||||
.pms_I ( pms_I ),
|
||||
.pm ( pm ),
|
||||
// phase operation
|
||||
.pg_rst_III ( pg_rst_III ),
|
||||
.keycode_III( keycode_III ),
|
||||
.pg_phase_X ( ph_X )
|
||||
);
|
||||
|
||||
`ifdef TEST_SUPPORT
|
||||
wire test_eg, test_op0;
|
||||
`endif
|
||||
wire [9:0] eg_XI;
|
||||
|
||||
jt51_eg u_eg(
|
||||
`ifdef TEST_SUPPORT
|
||||
.test_eg ( test_eg ),
|
||||
`endif
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.zero ( zero ),
|
||||
// envelope configuration
|
||||
.keycode_III(keycode_III), // used in stage III
|
||||
.arate_II ( arate_II ),
|
||||
.rate1_II ( rate1_II ),
|
||||
.rate2_II ( rate2_II ),
|
||||
.rrate_II ( rrate_II ),
|
||||
.d1l_I ( d1l_I ),
|
||||
.ks_III ( ks_III ),
|
||||
// envelope operation
|
||||
.keyon_II ( keyon_II ),
|
||||
.pg_rst_III ( pg_rst_III),
|
||||
// envelope number
|
||||
.tl_VII ( tl_VII ),
|
||||
.am ( am ),
|
||||
.ams_VII ( ams_VII ),
|
||||
.amsen_VII ( amsen_VII ),
|
||||
.eg_XI ( eg_XI )
|
||||
);
|
||||
|
||||
wire signed [13:0] op_out;
|
||||
|
||||
jt51_op u_op(
|
||||
`ifdef TEST_SUPPORT
|
||||
.test_eg ( test_eg ),
|
||||
.test_op0 ( test_op0 ),
|
||||
`endif
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.pg_phase_X ( ph_X ),
|
||||
.con_I ( con_I ),
|
||||
.fb_II ( fb_II ),
|
||||
// volume
|
||||
.eg_atten_XI ( eg_XI ),
|
||||
// modulation
|
||||
.m1_enters ( m1_enters ),
|
||||
.c1_enters ( c1_enters ),
|
||||
// Operator
|
||||
.use_prevprev1 ( use_prevprev1 ),
|
||||
.use_internal_x ( use_internal_x ),
|
||||
.use_internal_y ( use_internal_y ),
|
||||
.use_prev2 ( use_prev2 ),
|
||||
.use_prev1 ( use_prev1 ),
|
||||
.test_214 ( 1'b0 ),
|
||||
`ifdef SIMULATION
|
||||
.zero ( zero ),
|
||||
`endif
|
||||
// output data
|
||||
.op_XVII ( op_out )
|
||||
);
|
||||
|
||||
wire [4:0] nfrq;
|
||||
wire [10:0] noise_out;
|
||||
wire ne, op31_acc, op31_no;
|
||||
|
||||
jt51_noise u_noise(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.nfrq ( nfrq ),
|
||||
.eg ( eg_XI ),
|
||||
.out ( noise_out ),
|
||||
.op31_no( op31_no )
|
||||
);
|
||||
|
||||
jt51_acc u_acc(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.m1_enters ( m1_enters ),
|
||||
.m2_enters ( m2_enters ),
|
||||
.c1_enters ( c1_enters ),
|
||||
.c2_enters ( c2_enters ),
|
||||
.op31_acc ( op31_acc ),
|
||||
.rl_I ( rl_I ),
|
||||
.con_I ( con_I ),
|
||||
.op_out ( op_out ),
|
||||
.ne ( ne ),
|
||||
.noise ( noise_out ),
|
||||
.left ( left ),
|
||||
.right ( right ),
|
||||
.xleft ( xleft ),
|
||||
.xright ( xright )
|
||||
);
|
||||
`else
|
||||
assign left = 16'd0;
|
||||
assign right = 16'd0;
|
||||
assign xleft = 16'd0;
|
||||
assign xright = 16'd0;
|
||||
`endif
|
||||
|
||||
wire busy;
|
||||
wire write = !cs_n && !wr_n;
|
||||
|
||||
assign dout = { busy, 5'h0, flag_B, flag_A };
|
||||
|
||||
/*verilator tracing_on*/
|
||||
|
||||
jt51_mmr u_mmr(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_p1 ),
|
||||
.a0 ( a0 ),
|
||||
.write ( write ),
|
||||
.din ( din ),
|
||||
.busy ( busy ),
|
||||
|
||||
// CT
|
||||
.ct1 ( ct1 ),
|
||||
.ct2 ( ct2 ),
|
||||
// LFO
|
||||
.lfo_freq ( lfo_freq ),
|
||||
.lfo_w ( lfo_w ),
|
||||
.lfo_amd ( amd ),
|
||||
.lfo_pmd ( pmd ),
|
||||
.lfo_rst ( lfo_rst ),
|
||||
|
||||
// Noise
|
||||
.ne ( ne ),
|
||||
.nfrq ( nfrq ),
|
||||
|
||||
// Timers
|
||||
.value_A ( value_A ),
|
||||
.value_B ( value_B ),
|
||||
.load_A ( load_A ),
|
||||
.load_B ( load_B ),
|
||||
.enable_irq_A( enable_irq_A ),
|
||||
.enable_irq_B( enable_irq_B ),
|
||||
.clr_flag_A ( clr_flag_A ),
|
||||
.clr_flag_B ( clr_flag_B ),
|
||||
.overflow_A ( overflow_A ),
|
||||
`ifdef TEST_SUPPORT
|
||||
// Test
|
||||
.test_eg ( test_eg ),
|
||||
.test_op0 ( test_op0 ),
|
||||
`endif
|
||||
// REG
|
||||
.rl_I ( rl_I ),
|
||||
.fb_II ( fb_II ),
|
||||
.con_I ( con_I ),
|
||||
.kc_I ( kc_I ),
|
||||
.kf_I ( kf_I ),
|
||||
.pms_I ( pms_I ),
|
||||
.ams_VII ( ams_VII ),
|
||||
.dt1_II ( dt1_II ),
|
||||
.mul_VI ( mul_VI ),
|
||||
.tl_VII ( tl_VII ),
|
||||
.ks_III ( ks_III ),
|
||||
.arate_II ( arate_II ),
|
||||
.amsen_VII ( amsen_VII ),
|
||||
.rate1_II ( rate1_II ),
|
||||
.dt2_I ( dt2_I ),
|
||||
.rate2_II ( rate2_II ),
|
||||
.d1l_I ( d1l_I ),
|
||||
.rrate_II ( rrate_II ),
|
||||
.keyon_II ( keyon_II ),
|
||||
|
||||
.cur_op ( cur_op ),
|
||||
.op31_no ( op31_no ),
|
||||
.op31_acc ( op31_acc ),
|
||||
.zero ( zero ),
|
||||
.m1_enters ( m1_enters ),
|
||||
.m2_enters ( m2_enters ),
|
||||
.c1_enters ( c1_enters ),
|
||||
.c2_enters ( c2_enters ),
|
||||
// Operator
|
||||
.use_prevprev1 ( use_prevprev1 ),
|
||||
.use_internal_x ( use_internal_x ),
|
||||
.use_internal_y ( use_internal_y ),
|
||||
.use_prev2 ( use_prev2 ),
|
||||
.use_prev1 ( use_prev1 )
|
||||
);
|
||||
|
||||
`ifdef SIMULATION
|
||||
`ifndef VERILATOR
|
||||
integer fsnd;
|
||||
initial begin
|
||||
fsnd=$fopen("jt51.raw","wb");
|
||||
end
|
||||
|
||||
always @(posedge zero) begin
|
||||
$fwrite(fsnd,"%u", {xleft, xright});
|
||||
end
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
176
common/Sound/jt51/jt51_acc.v
Normal file
176
common/Sound/jt51/jt51_acc.v
Normal file
@@ -0,0 +1,176 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.1 Date: 14- 4-2017
|
||||
Version: 1.0 Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_acc(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input m1_enters,
|
||||
input m2_enters,
|
||||
input c1_enters,
|
||||
input c2_enters,
|
||||
input op31_acc,
|
||||
input [1:0] rl_I,
|
||||
input [2:0] con_I,
|
||||
input signed [13:0] op_out,
|
||||
input ne, // noise enable
|
||||
input signed [10:0] noise,
|
||||
output signed [15:0] left,
|
||||
output signed [15:0] right,
|
||||
output reg signed [15:0] xleft, // exact outputs
|
||||
output reg signed [15:0] xright
|
||||
);
|
||||
|
||||
reg signed [13:0] op_val;
|
||||
|
||||
always @(*) begin
|
||||
if( ne && op31_acc ) // cambiar a OP 31
|
||||
op_val = { {2{noise[10]}}, noise, 1'd0 };
|
||||
else
|
||||
op_val = op_out;
|
||||
end
|
||||
|
||||
reg sum_en;
|
||||
|
||||
always @(*) begin
|
||||
case ( con_I )
|
||||
3'd0,3'd1,3'd2,3'd3: sum_en = m2_enters;
|
||||
3'd4: sum_en = m1_enters | m2_enters;
|
||||
3'd5,3'd6: sum_en = ~c1_enters;
|
||||
3'd7: sum_en = 1'b1;
|
||||
default: sum_en = 1'bx;
|
||||
endcase
|
||||
end
|
||||
|
||||
wire ren = rl_I[1];
|
||||
wire len = rl_I[0];
|
||||
reg signed [16:0] pre_left, pre_right;
|
||||
wire signed [15:0] total;
|
||||
wire signed [16:0] total_ex = {total[15],total};
|
||||
|
||||
reg sum_all;
|
||||
|
||||
wire rst_sum = c2_enters;
|
||||
//wire rst_sum = c1_enters;
|
||||
//wire rst_sum = m1_enters;
|
||||
//wire rst_sum = m2_enters;
|
||||
|
||||
function signed [15:0] lim16;
|
||||
input signed [16:0] din;
|
||||
lim16 = !din[16] && din[15] ? 16'h7fff :
|
||||
( din[16] && !din[15] ? 16'h8000 : din[15:0] );
|
||||
endfunction
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
sum_all <= 1'b0;
|
||||
end
|
||||
else if(cen) begin
|
||||
if( rst_sum ) begin
|
||||
sum_all <= 1'b1;
|
||||
if( !sum_all ) begin
|
||||
pre_right <= ren ? total_ex : 17'd0;
|
||||
pre_left <= len ? total_ex : 17'd0;
|
||||
end
|
||||
else begin
|
||||
pre_right <= pre_right + (ren ? total_ex : 17'd0);
|
||||
pre_left <= pre_left + (len ? total_ex : 17'd0);
|
||||
end
|
||||
end
|
||||
if( c1_enters ) begin
|
||||
sum_all <= 1'b0;
|
||||
xleft <= lim16(pre_left);
|
||||
xright <= lim16(pre_right);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg signed [15:0] opsum;
|
||||
wire signed [16:0] opsum10 = {{3{op_val[13]}},op_val}+{total[15],total};
|
||||
|
||||
always @(*) begin
|
||||
if( rst_sum )
|
||||
opsum = sum_en ? { {2{op_val[13]}}, op_val } : 16'd0;
|
||||
else begin
|
||||
if( sum_en )
|
||||
if( opsum10[16]==opsum10[15] )
|
||||
opsum = opsum10[15:0];
|
||||
else begin
|
||||
opsum = opsum10[16] ? 16'h8000 : 16'h7fff;
|
||||
end
|
||||
else
|
||||
opsum = total;
|
||||
end
|
||||
end
|
||||
|
||||
jt51_sh #(.width(16),.stages(8)) u_acc(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( opsum ),
|
||||
.drop ( total )
|
||||
);
|
||||
|
||||
|
||||
wire signed [9:0] left_man, right_man;
|
||||
wire [2:0] left_exp, right_exp;
|
||||
|
||||
jt51_exp2lin left_reconstruct(
|
||||
.lin( left ),
|
||||
.man( left_man ),
|
||||
.exp( left_exp )
|
||||
);
|
||||
|
||||
jt51_exp2lin right_reconstruct(
|
||||
.lin( right ),
|
||||
.man( right_man ),
|
||||
.exp( right_exp )
|
||||
);
|
||||
|
||||
jt51_lin2exp left2exp(
|
||||
.lin( xleft ),
|
||||
.man( left_man ),
|
||||
.exp( left_exp ) );
|
||||
|
||||
jt51_lin2exp right2exp(
|
||||
.lin( xright ),
|
||||
.man( right_man ),
|
||||
.exp( right_exp ) );
|
||||
|
||||
`ifdef DUMPLEFT
|
||||
|
||||
reg skip;
|
||||
|
||||
wire signed [15:0] dump = left;
|
||||
|
||||
initial skip=1;
|
||||
|
||||
always @(posedge clk)
|
||||
if( c1_enters && (!skip || dump) && cen) begin
|
||||
$display("%d", dump );
|
||||
skip <= 0;
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
74
common/Sound/jt51/jt51_csr_ch.v
Normal file
74
common/Sound/jt51/jt51_csr_ch.v
Normal file
@@ -0,0 +1,74 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 23-10-2019
|
||||
*/
|
||||
|
||||
module jt51_csr_ch(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input [ 7:0] din,
|
||||
|
||||
input up_rl_ch,
|
||||
input up_fb_ch,
|
||||
input up_con_ch,
|
||||
input up_kc_ch,
|
||||
input up_kf_ch,
|
||||
input up_ams_ch,
|
||||
input up_pms_ch,
|
||||
|
||||
output [1:0] rl,
|
||||
output [2:0] fb,
|
||||
output [2:0] con,
|
||||
output [6:0] kc,
|
||||
output [5:0] kf,
|
||||
output [1:0] ams,
|
||||
output [2:0] pms
|
||||
);
|
||||
|
||||
wire [1:0] rl_in = din[7:6];
|
||||
wire [2:0] fb_in = din[5:3];
|
||||
wire [2:0] con_in = din[2:0];
|
||||
wire [6:0] kc_in = din[6:0];
|
||||
wire [5:0] kf_in = din[7:2];
|
||||
wire [1:0] ams_in = din[1:0];
|
||||
wire [2:0] pms_in = din[6:4];
|
||||
|
||||
wire [25:0] reg_in = {
|
||||
up_rl_ch ? rl_in : rl,
|
||||
up_fb_ch ? fb_in : fb,
|
||||
up_con_ch ? con_in : con,
|
||||
up_kc_ch ? kc_in : kc,
|
||||
up_kf_ch ? kf_in : kf,
|
||||
up_ams_ch ? ams_in : ams,
|
||||
up_pms_ch ? pms_in : pms };
|
||||
|
||||
wire [25:0] reg_out;
|
||||
|
||||
assign { rl, fb, con, kc, kf, ams, pms } = reg_out;
|
||||
|
||||
jt51_sh #( .width(26), .stages(8)) u_regop(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( reg_in ),
|
||||
.drop ( reg_out )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
104
common/Sound/jt51/jt51_csr_op.v
Normal file
104
common/Sound/jt51/jt51_csr_op.v
Normal file
@@ -0,0 +1,104 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 23-10-2019
|
||||
*/
|
||||
|
||||
module jt51_csr_op(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input [ 7:0] din,
|
||||
input up_dt1_op,
|
||||
input up_mul_op,
|
||||
input up_tl_op,
|
||||
input up_ks_op,
|
||||
input up_amsen_op,
|
||||
input up_dt2_op,
|
||||
input up_d1l_op,
|
||||
input up_ar_op,
|
||||
input up_d1r_op,
|
||||
input up_d2r_op,
|
||||
input up_rr_op,
|
||||
|
||||
output [2:0] dt1,
|
||||
output [3:0] mul,
|
||||
output [6:0] tl,
|
||||
output [1:0] ks,
|
||||
output amsen,
|
||||
output [1:0] dt2,
|
||||
output [3:0] d1l,
|
||||
output [4:0] arate,
|
||||
output [4:0] rate1,
|
||||
output [4:0] rate2,
|
||||
output [3:0] rrate
|
||||
);
|
||||
|
||||
wire [2:0] dt1_in = din[6:4];
|
||||
wire [3:0] mul_in = din[3:0];
|
||||
wire [6:0] tl_in = din[6:0];
|
||||
wire [1:0] ks_in = din[7:6];
|
||||
wire amsen_in= din[7];
|
||||
wire [1:0] dt2_in = din[7:6];
|
||||
wire [3:0] d1l_in = din[7:4];
|
||||
wire [4:0] ar_in = din[4:0];
|
||||
wire [4:0] d1r_in = din[4:0];
|
||||
wire [4:0] d2r_in = din[4:0];
|
||||
wire [3:0] rr_in = din[3:0];
|
||||
|
||||
wire [30:0] reg0_in = {
|
||||
up_dt1_op ? dt1_in : dt1, // 3
|
||||
up_mul_op ? mul_in : mul, // 4
|
||||
up_ks_op ? ks_in : ks, // 2
|
||||
up_amsen_op ? amsen_in : amsen, // 1
|
||||
up_dt2_op ? dt2_in : dt2, // 2
|
||||
up_d1l_op ? d1l_in : d1l, // 4
|
||||
|
||||
up_ar_op ? ar_in : arate, // 5
|
||||
up_d1r_op ? d1r_in : rate1, // 5
|
||||
up_d2r_op ? d2r_in : rate2 }; // 5
|
||||
|
||||
wire [10:0] reg1_in = {
|
||||
up_tl_op ? tl_in : tl, // 7
|
||||
up_rr_op ? rr_in : rrate }; // 4
|
||||
|
||||
wire [30:0] reg0_out;
|
||||
wire [10:0] reg1_out;
|
||||
|
||||
assign { dt1, mul, ks, amsen, dt2, d1l, arate, rate1, rate2, tl, rrate }
|
||||
= {reg0_out, reg1_out};
|
||||
|
||||
// reset to zero
|
||||
jt51_sh #( .width(31), .stages(32)) u_reg0op(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( reg0_in ),
|
||||
.drop ( reg0_out )
|
||||
);
|
||||
|
||||
// reset to one
|
||||
jt51_sh #( .width(11), .stages(32), .rstval(1'b1)) u_reg1op(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( reg1_in ),
|
||||
.drop ( reg1_out )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
440
common/Sound/jt51/jt51_eg.v
Normal file
440
common/Sound/jt51/jt51_eg.v
Normal file
@@ -0,0 +1,440 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_eg(
|
||||
`ifdef TEST_SUPPORT
|
||||
input test_eg,
|
||||
`endif
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input zero,
|
||||
// envelope configuration
|
||||
input [4:0] keycode_III,
|
||||
input [4:0] arate_II,
|
||||
input [4:0] rate1_II,
|
||||
input [4:0] rate2_II,
|
||||
input [3:0] rrate_II,
|
||||
input [3:0] d1l_I,
|
||||
input [1:0] ks_III,
|
||||
// envelope operation
|
||||
input keyon_II,
|
||||
output reg pg_rst_III,
|
||||
// envelope number
|
||||
input [6:0] tl_VII,
|
||||
input [6:0] am,
|
||||
input [1:0] ams_VII,
|
||||
input amsen_VII,
|
||||
output [9:0] eg_XI
|
||||
);
|
||||
|
||||
// eg[9:6] -> direct attenuation (divide by 2)
|
||||
// eg[5:0] -> mantisa attenuation (uses LUT)
|
||||
// 1 LSB of eg is -0.09257 dB
|
||||
|
||||
localparam ATTACK=2'd0,
|
||||
DECAY1=2'd1,
|
||||
DECAY2=2'd2,
|
||||
RELEASE=2'd3;
|
||||
|
||||
reg [4:0] d1level_II;
|
||||
reg [2:0] cnt_V;
|
||||
reg [5:0] rate_IV;
|
||||
wire [9:0] eg_VI;
|
||||
reg [9:0] eg_VII, eg_VIII;
|
||||
wire [9:0] eg_II;
|
||||
reg [11:0] sum_eg_tl_VII;
|
||||
|
||||
reg step_V, step_VI;
|
||||
reg sum_up;
|
||||
reg [5:0] rate_V;
|
||||
reg [5:1] rate_VI;
|
||||
|
||||
// remember: { log_msb, pow_addr } <= log_val[11:0] + { tl, 5'd0 } + { eg, 2'd0 };
|
||||
|
||||
reg [1:0] eg_cnt_base;
|
||||
reg [14:0] eg_cnt /*verilator public*/;
|
||||
|
||||
reg [8:0] am_final_VII;
|
||||
|
||||
always @(posedge clk) begin : envelope_counter
|
||||
if( rst ) begin
|
||||
eg_cnt_base <= 2'd0;
|
||||
eg_cnt <=15'd0;
|
||||
end
|
||||
else if(cen) begin
|
||||
if( zero ) begin
|
||||
// envelope counter increases every 3 output samples,
|
||||
// there is one sample every 32 clock ticks
|
||||
if( eg_cnt_base == 2'd2 ) begin
|
||||
eg_cnt <= eg_cnt + 1'b1;
|
||||
eg_cnt_base <= 2'd0;
|
||||
end
|
||||
else eg_cnt_base <= eg_cnt_base + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire cnt_out; // = all_cnt_last[3*31-1:3*30];
|
||||
|
||||
reg [6:0] pre_rate_III;
|
||||
reg [4:0] cfg_III;
|
||||
|
||||
always @(*) begin : pre_rate_calc
|
||||
if( cfg_III == 5'd0 )
|
||||
pre_rate_III = 7'd0;
|
||||
else
|
||||
case( ks_III )
|
||||
2'd3: pre_rate_III = { 1'b0, cfg_III, 1'b0 } + { 2'b0, keycode_III };
|
||||
2'd2: pre_rate_III = { 1'b0, cfg_III, 1'b0 } + { 3'b0, keycode_III[4:1] };
|
||||
2'd1: pre_rate_III = { 1'b0, cfg_III, 1'b0 } + { 4'b0, keycode_III[4:2] };
|
||||
2'd0: pre_rate_III = { 1'b0, cfg_III, 1'b0 } + { 5'b0, keycode_III[4:3] };
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
reg [7:0] step_idx;
|
||||
reg [1:0] state_in_III, state_in_IV, state_in_V, state_in_VI;
|
||||
|
||||
always @(*) begin : rate_step
|
||||
if( rate_V[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x
|
||||
if( rate_V[5:2]==4'hf && state_in_V == ATTACK)
|
||||
step_idx = 8'b11111111; // Maximum attack speed, rates 60&61
|
||||
else
|
||||
case( rate_V[1:0] )
|
||||
2'd0: step_idx = 8'b00000000;
|
||||
2'd1: step_idx = 8'b10001000; // 2
|
||||
2'd2: step_idx = 8'b10101010; // 4
|
||||
2'd3: step_idx = 8'b11101110; // 6
|
||||
endcase
|
||||
end
|
||||
else begin
|
||||
if( rate_V[5:2]==4'd0 && state_in_V != ATTACK)
|
||||
step_idx = 8'b11111110; // limit slowest decay rate_IV
|
||||
else
|
||||
case( rate_V[1:0] )
|
||||
2'd0: step_idx = 8'b10101010; // 4
|
||||
2'd1: step_idx = 8'b11101010; // 5
|
||||
2'd2: step_idx = 8'b11101110; // 6
|
||||
2'd3: step_idx = 8'b11111110; // 7
|
||||
endcase
|
||||
end
|
||||
// a rate_IV of zero keeps the level still
|
||||
step_V = rate_V[5:1]==5'd0 ? 1'b0 : step_idx[ cnt_V ];
|
||||
end
|
||||
|
||||
|
||||
|
||||
wire ar_off_VI;
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
// I
|
||||
if( d1l_I == 4'd15 )
|
||||
d1level_II <= 5'h10; // 48dB
|
||||
else
|
||||
d1level_II <= {1'b0,d1l_I};
|
||||
end
|
||||
|
||||
// II
|
||||
wire keyon_last_II;
|
||||
wire keyon_now_II = !keyon_last_II && keyon_II;
|
||||
wire keyoff_now_II = keyon_last_II && !keyon_II;
|
||||
wire ar_off_II = keyon_now_II && (arate_II == 5'h1f);
|
||||
wire [1:0] state_II;
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
pg_rst_III <= keyon_now_II;
|
||||
// trigger release
|
||||
if( keyoff_now_II ) begin
|
||||
cfg_III <= { rrate_II, 1'b1 };
|
||||
state_in_III <= RELEASE;
|
||||
end
|
||||
else begin
|
||||
// trigger 1st decay
|
||||
if( keyon_now_II ) begin
|
||||
cfg_III <= arate_II;
|
||||
state_in_III <= ATTACK;
|
||||
end
|
||||
else begin : sel_rate
|
||||
case ( state_II )
|
||||
ATTACK: begin
|
||||
if( eg_II==10'd0 ) begin
|
||||
state_in_III <= DECAY1;
|
||||
cfg_III <= rate1_II;
|
||||
end
|
||||
else begin
|
||||
state_in_III <= state_II; // attack
|
||||
cfg_III <= arate_II;
|
||||
end
|
||||
end
|
||||
DECAY1: begin
|
||||
if( eg_II[9:5] >= d1level_II ) begin
|
||||
cfg_III <= rate2_II;
|
||||
state_in_III <= DECAY2;
|
||||
end
|
||||
else begin
|
||||
cfg_III <= rate1_II;
|
||||
state_in_III <= state_II; // decay1
|
||||
end
|
||||
end
|
||||
DECAY2: begin
|
||||
cfg_III <= rate2_II;
|
||||
state_in_III <= state_II; // decay2
|
||||
end
|
||||
RELEASE: begin
|
||||
cfg_III <= { rrate_II, 1'b1 };
|
||||
state_in_III <= state_II; // release
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// III
|
||||
always @(posedge clk) if(cen) begin
|
||||
state_in_IV <= state_in_III;
|
||||
rate_IV <= pre_rate_III[6] ? 6'd63 : pre_rate_III[5:0];
|
||||
end
|
||||
|
||||
// IV
|
||||
always @(posedge clk) if(cen) begin
|
||||
state_in_V <= state_in_IV;
|
||||
rate_V <= rate_IV;
|
||||
if( state_in_IV == ATTACK )
|
||||
case( rate_IV[5:2] )
|
||||
4'h0: cnt_V <= eg_cnt[13:11];
|
||||
4'h1: cnt_V <= eg_cnt[12:10];
|
||||
4'h2: cnt_V <= eg_cnt[11: 9];
|
||||
4'h3: cnt_V <= eg_cnt[10: 8];
|
||||
4'h4: cnt_V <= eg_cnt[ 9: 7];
|
||||
4'h5: cnt_V <= eg_cnt[ 8: 6];
|
||||
4'h6: cnt_V <= eg_cnt[ 7: 5];
|
||||
4'h7: cnt_V <= eg_cnt[ 6: 4];
|
||||
4'h8: cnt_V <= eg_cnt[ 5: 3];
|
||||
4'h9: cnt_V <= eg_cnt[ 4: 2];
|
||||
4'ha: cnt_V <= eg_cnt[ 3: 1];
|
||||
default: cnt_V <= eg_cnt[ 2: 0];
|
||||
endcase
|
||||
else
|
||||
case( rate_IV[5:2] )
|
||||
4'h0: cnt_V <= eg_cnt[14:12];
|
||||
4'h1: cnt_V <= eg_cnt[13:11];
|
||||
4'h2: cnt_V <= eg_cnt[12:10];
|
||||
4'h3: cnt_V <= eg_cnt[11: 9];
|
||||
4'h4: cnt_V <= eg_cnt[10: 8];
|
||||
4'h5: cnt_V <= eg_cnt[ 9: 7];
|
||||
4'h6: cnt_V <= eg_cnt[ 8: 6];
|
||||
4'h7: cnt_V <= eg_cnt[ 7: 5];
|
||||
4'h8: cnt_V <= eg_cnt[ 6: 4];
|
||||
4'h9: cnt_V <= eg_cnt[ 5: 3];
|
||||
4'ha: cnt_V <= eg_cnt[ 4: 2];
|
||||
4'hb: cnt_V <= eg_cnt[ 3: 1];
|
||||
default: cnt_V <= eg_cnt[ 2: 0];
|
||||
endcase
|
||||
end
|
||||
|
||||
// V
|
||||
always @(posedge clk) if(cen) begin
|
||||
state_in_VI <= state_in_V;
|
||||
rate_VI <= rate_V[5:1];
|
||||
sum_up <= cnt_V[0] != cnt_out;
|
||||
step_VI <= step_V;
|
||||
end
|
||||
|
||||
///////////////////////////////////////
|
||||
// VI
|
||||
reg [8:0] ar_sum0_VI;
|
||||
reg [9:0] ar_result_VI, ar_sum_VI;
|
||||
|
||||
always @(*) begin : ar_calculation
|
||||
casez( rate_VI[5:2] )
|
||||
default: ar_sum0_VI = { 3'd0, eg_VI[9:4] } + 9'd1;
|
||||
4'b1100: ar_sum0_VI = { 3'd0, eg_VI[9:4] } + 9'd1;
|
||||
4'b1101: ar_sum0_VI = { 2'd0, eg_VI[9:3] } + 9'd1;
|
||||
4'b111?: ar_sum0_VI = { 1'd0, eg_VI[9:2] } + 9'd1;
|
||||
endcase
|
||||
if( rate_VI[5:4] == 2'b11 )
|
||||
ar_sum_VI = step_VI ? { ar_sum0_VI, 1'b0 } : { 1'b0, ar_sum0_VI };
|
||||
else
|
||||
ar_sum_VI = step_VI ? { 1'b0, ar_sum0_VI } : 10'd0;
|
||||
ar_result_VI = ar_sum_VI<eg_VI ? eg_VI-ar_sum_VI : 10'd0;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
if( ar_off_VI )
|
||||
eg_VII <= 10'd0;
|
||||
else
|
||||
if( state_in_VI == ATTACK ) begin
|
||||
if( sum_up && eg_VI != 10'd0 )
|
||||
if( rate_VI[5:1]==5'hf )
|
||||
eg_VII <= 10'd0;
|
||||
else
|
||||
eg_VII <= ar_result_VI;
|
||||
else
|
||||
eg_VII <= eg_VI;
|
||||
end
|
||||
else begin : DECAY_SUM
|
||||
if( sum_up ) begin
|
||||
if ( eg_VI<= (10'd1023-10'd8) )
|
||||
case( rate_VI[5:2] )
|
||||
4'b1100: eg_VII <= eg_VI + { 8'd0, step_VI, ~step_VI }; // 12
|
||||
4'b1101: eg_VII <= eg_VI + { 7'd0, step_VI, ~step_VI, 1'b0 }; // 13
|
||||
4'b1110: eg_VII <= eg_VI + { 6'd0, step_VI, ~step_VI, 2'b0 }; // 14
|
||||
4'b1111: eg_VII <= eg_VI + 10'd8;// 15
|
||||
default: eg_VII <= eg_VI + { 8'd0, step_VI, 1'b0 };
|
||||
endcase
|
||||
else eg_VII <= 10'h3FF;
|
||||
end
|
||||
else eg_VII <= eg_VI;
|
||||
end
|
||||
end
|
||||
|
||||
// VII
|
||||
always @(*) begin : sum_eg_and_tl
|
||||
casez( {amsen_VII, ams_VII } )
|
||||
3'b0??,3'b100: am_final_VII = 9'd0;
|
||||
3'b101: am_final_VII = { 2'b00, am };
|
||||
3'b110: am_final_VII = { 1'b0, am, 1'b0};
|
||||
3'b111: am_final_VII = { am, 2'b0 };
|
||||
endcase
|
||||
`ifdef TEST_SUPPORT
|
||||
if( test_eg && tl_VII!=7'd0 )
|
||||
sum_eg_tl_VII = 12'd0;
|
||||
else
|
||||
`endif
|
||||
sum_eg_tl_VII = { 2'b0, tl_VII, 3'd0 }
|
||||
+ {2'b0, eg_VII}
|
||||
+ {2'b0, am_final_VII, 1'b0 };
|
||||
end
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
eg_VIII <= sum_eg_tl_VII[11:10] > 2'b0 ? {10{1'b1}} : sum_eg_tl_VII[9:0];
|
||||
end
|
||||
|
||||
jt51_sh #( .width(10), .stages(3) ) u_egpadding (
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( eg_VIII ),
|
||||
.drop ( eg_XI )
|
||||
);
|
||||
|
||||
|
||||
// Shift registers
|
||||
|
||||
jt51_sh #( .width(10), .stages(32-7+2), .rstval(1'b1) ) u_eg1sh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( eg_VII ),
|
||||
.drop ( eg_II )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(10), .stages(4), .rstval(1'b1) ) u_eg2sh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( eg_II ),
|
||||
.drop ( eg_VI )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(1), .stages(4) ) u_aroffsh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( ar_off_II ),
|
||||
.drop ( ar_off_VI )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(1), .stages(32) ) u_konsh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.din ( keyon_II ),
|
||||
.cen ( cen ),
|
||||
.drop ( keyon_last_II )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(1), .stages(32) ) u_cntsh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( cnt_V[0] ),
|
||||
.drop ( cnt_out )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(2), .stages(32-3+2), .rstval(1'b1) ) u_statesh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( state_in_III ),
|
||||
.drop ( state_II )
|
||||
);
|
||||
|
||||
`ifndef JT51_NODEBUG
|
||||
`ifdef SIMULATION
|
||||
/* verilator lint_off PINMISSING */
|
||||
wire [4:0] cnt;
|
||||
|
||||
sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt));
|
||||
|
||||
sep32 #(.width(10),.stg(11)) sep_eg(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( eg_XI ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
sep32 #(.width(7),.stg(7)) sep_tl(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( tl_VII ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
sep32 #(.width(2),.stg(2)) sep_state(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( state_II ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
sep32 #(.width(5),.stg(6)) sep_rate(
|
||||
.clk ( clk ),
|
||||
.mixed ( rate_VI ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
sep32 #(.width(9),.stg(7)) sep_amfinal(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( am_final_VII ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
/* verilator lint_on PINMISSING */
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
42
common/Sound/jt51/jt51_exp2lin.v
Normal file
42
common/Sound/jt51/jt51_exp2lin.v
Normal file
@@ -0,0 +1,42 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_exp2lin(
|
||||
output reg signed [15:0] lin,
|
||||
input signed [9:0] man,
|
||||
input [2:0] exp
|
||||
);
|
||||
|
||||
always @(*) begin
|
||||
case( exp )
|
||||
3'd7: lin = { man, 6'b0 };
|
||||
3'd6: lin = { {1{man[9]}}, man, 5'b0 };
|
||||
3'd5: lin = { {2{man[9]}}, man, 4'b0 };
|
||||
3'd4: lin = { {3{man[9]}}, man, 3'b0 };
|
||||
3'd3: lin = { {4{man[9]}}, man, 2'b0 };
|
||||
3'd2: lin = { {5{man[9]}}, man, 1'b0 };
|
||||
3'd1: lin = { {6{man[9]}}, man };
|
||||
3'd0: lin = 16'd0;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
78
common/Sound/jt51/jt51_exprom.v
Normal file
78
common/Sound/jt51/jt51_exprom.v
Normal file
@@ -0,0 +1,78 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
/* This file is part of JT51.
|
||||
|
||||
|
||||
JT51 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT51 program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on hardware measurements and Sauraen VHDL version of OPN/OPN2,
|
||||
which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-4-2017
|
||||
|
||||
*/
|
||||
|
||||
module jt51_exprom
|
||||
(
|
||||
input [4:0] addr,
|
||||
input clk,
|
||||
input cen,
|
||||
output reg [44:0] exp
|
||||
);
|
||||
|
||||
reg [44:0] explut[31:0];
|
||||
initial
|
||||
begin
|
||||
explut[0] = 45'b111110101011010110001011010000010010111011011;
|
||||
explut[1] = 45'b111101010011010101000011001100101110110101011;
|
||||
explut[2] = 45'b111011111011010011110111001000110010101110011;
|
||||
explut[3] = 45'b111010100101010010101111000100110010101000011;
|
||||
explut[4] = 45'b111001001101010001100111000000110010100001011;
|
||||
explut[5] = 45'b110111111011010000011110111101010010011011011;
|
||||
explut[6] = 45'b110110100011001111010110111001010010010100100;
|
||||
explut[7] = 45'b110101001011001110001110110101110010001110011;
|
||||
explut[8] = 45'b110011111011001101000110110001110010001000011;
|
||||
explut[9] = 45'b110010100011001011111110101110010010000010011;
|
||||
explut[10] = 45'b110001010011001010111010101010010001111011011;
|
||||
explut[11] = 45'b101111111011001001110010100110110001110101011;
|
||||
explut[12] = 45'b101110101011001000101010100011001101101111011;
|
||||
explut[13] = 45'b101101010101000111100110011111010001101001011;
|
||||
explut[14] = 45'b101100000011000110100010011011110001100011011;
|
||||
explut[15] = 45'b101010110011000101011110011000010001011101011;
|
||||
explut[16] = 45'b101001100011000100011010010100101101010111011;
|
||||
explut[17] = 45'b101000010011000011010010010001001101010001011;
|
||||
explut[18] = 45'b100111000011000010010010001101101101001011011;
|
||||
explut[19] = 45'b100101110011000001001110001010001101000101011;
|
||||
explut[20] = 45'b100100100011000000001010000110010000111111011;
|
||||
explut[21] = 45'b100011010010111111001010000011001100111001011;
|
||||
explut[22] = 45'b100010000010111110000101111111101100110011011;
|
||||
explut[23] = 45'b100000110010111101000001111100001100101101011;
|
||||
explut[24] = 45'b011111101010111100000001111000101100101000010;
|
||||
explut[25] = 45'b011110011010111011000001110101001100100010011;
|
||||
explut[26] = 45'b011101001010111010000001110001110000011100011;
|
||||
explut[27] = 45'b011100000010111001000001101110010000010110011;
|
||||
explut[28] = 45'b011010110010111000000001101011001100010001011;
|
||||
explut[29] = 45'b011001101010110111000001100111101100001011011;
|
||||
explut[30] = 45'b011000100000110110000001100100010000000110010;
|
||||
explut[31] = 45'b010111010010110101000001100001001100000000011;
|
||||
end
|
||||
|
||||
always @ (posedge clk) if(cen) begin
|
||||
exp <= explut[addr];
|
||||
end
|
||||
|
||||
endmodule
|
||||
69
common/Sound/jt51/jt51_kon.v
Normal file
69
common/Sound/jt51/jt51_kon.v
Normal file
@@ -0,0 +1,69 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
/* This file is part of JT51.
|
||||
|
||||
|
||||
JT51 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT51 program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-1-2017
|
||||
|
||||
*/
|
||||
|
||||
module jt51_kon(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input [3:0] keyon_op,
|
||||
input [2:0] keyon_ch,
|
||||
input [1:0] cur_op,
|
||||
input [2:0] cur_ch,
|
||||
input up_keyon,
|
||||
input csm,
|
||||
input overflow_A,
|
||||
|
||||
output reg keyon_II
|
||||
);
|
||||
|
||||
//reg csm_copy;
|
||||
|
||||
reg din;
|
||||
wire drop;
|
||||
|
||||
reg [3:0] cur_op_hot;
|
||||
|
||||
always @(posedge clk) if (cen)
|
||||
keyon_II <= (csm&&overflow_A) || drop;
|
||||
|
||||
always @(*) begin
|
||||
case( cur_op )
|
||||
2'd0: cur_op_hot = 4'b0001; // S1 / M1
|
||||
2'd1: cur_op_hot = 4'b0100; // S3 / M2
|
||||
2'd2: cur_op_hot = 4'b0010; // S2 / C1
|
||||
2'd3: cur_op_hot = 4'b1000; // S4 / C2
|
||||
endcase
|
||||
din = keyon_ch==cur_ch && up_keyon ? |(keyon_op&cur_op_hot) : drop;
|
||||
end
|
||||
|
||||
jt51_sh #(.width(1),.stages(32)) u_konch(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( din ),
|
||||
.drop ( drop )
|
||||
);
|
||||
|
||||
endmodule
|
||||
271
common/Sound/jt51/jt51_lfo.v
Normal file
271
common/Sound/jt51/jt51_lfo.v
Normal file
@@ -0,0 +1,271 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
tab size 4
|
||||
|
||||
*/
|
||||
|
||||
module jt51_lfo(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input zero,
|
||||
input lfo_rst,
|
||||
input [7:0] lfo_freq,
|
||||
input [6:0] lfo_amd,
|
||||
input [6:0] lfo_pmd,
|
||||
input [1:0] lfo_w,
|
||||
output reg [6:0] am,
|
||||
output reg [7:0] pm_u
|
||||
);
|
||||
|
||||
reg signed [7:0] pm;
|
||||
|
||||
always @(*) begin: signed_to_unsigned
|
||||
if( pm[7] ) begin
|
||||
pm_u[7] = pm[7];
|
||||
pm_u[6:0] = ~pm[6:0];
|
||||
end
|
||||
else pm_u = pm;
|
||||
end
|
||||
|
||||
wire [6:0] noise_am;
|
||||
wire [7:0] noise_pm;
|
||||
|
||||
parameter b0=3;
|
||||
reg [15+b0:0] base;
|
||||
|
||||
always @(posedge clk) begin : base_counter
|
||||
if( rst ) begin
|
||||
base <= {b0+16{1'b0}};
|
||||
end
|
||||
else if(cen) begin
|
||||
if( zero ) base <= base + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
reg sel_base;
|
||||
reg [4:0] freq_sel;
|
||||
|
||||
always @(*) begin : base_mux
|
||||
freq_sel = {1'b0,lfo_freq[7:4]}
|
||||
+ ( lfo_w==2'd2 ? 5'b1 : 5'b0 );
|
||||
case( freq_sel )
|
||||
5'h10: sel_base = base[b0-1];
|
||||
5'hf: sel_base = base[b0+0];
|
||||
5'he: sel_base = base[b0+1];
|
||||
5'hd: sel_base = base[b0+2];
|
||||
5'hc: sel_base = base[b0+3];
|
||||
5'hb: sel_base = base[b0+4];
|
||||
5'ha: sel_base = base[b0+5];
|
||||
5'h9: sel_base = base[b0+6];
|
||||
5'h8: sel_base = base[b0+7];
|
||||
5'h7: sel_base = base[b0+8];
|
||||
5'h6: sel_base = base[b0+9];
|
||||
5'h5: sel_base = base[b0+10];
|
||||
5'h4: sel_base = base[b0+11];
|
||||
5'h3: sel_base = base[b0+12];
|
||||
5'h2: sel_base = base[b0+13];
|
||||
5'h1: sel_base = base[b0+14];
|
||||
5'h0: sel_base = base[b0+15];
|
||||
default: sel_base = base[b0-1];
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [7:0] cnt, cnt_lim;
|
||||
|
||||
reg signed [10:0] am_bresenham;
|
||||
reg signed [ 9:0] pm_bresenham;
|
||||
|
||||
always @(*) begin : counter_limit
|
||||
case( lfo_freq[3:0] )
|
||||
4'hf: cnt_lim = 8'd66;
|
||||
4'he: cnt_lim = 8'd68;
|
||||
4'hd: cnt_lim = 8'd70;
|
||||
4'hc: cnt_lim = 8'd73;
|
||||
4'hb: cnt_lim = 8'd76;
|
||||
4'ha: cnt_lim = 8'd79;
|
||||
4'h9: cnt_lim = 8'd82;
|
||||
4'h8: cnt_lim = 8'd85;
|
||||
4'h7: cnt_lim = 8'd89;
|
||||
4'h6: cnt_lim = 8'd93;
|
||||
4'h5: cnt_lim = 8'd98;
|
||||
4'h4: cnt_lim = 8'd102;
|
||||
4'h3: cnt_lim = 8'd108;
|
||||
4'h2: cnt_lim = 8'd114;
|
||||
4'h1: cnt_lim = 8'd120;
|
||||
4'h0: cnt_lim = 8'd128;
|
||||
endcase
|
||||
end
|
||||
|
||||
wire signed [7:0] pmd_min = (~{1'b0, lfo_pmd[6:0]})+8'b1;
|
||||
|
||||
reg lfo_clk, last_base, am_up, pm_up;
|
||||
|
||||
always @(posedge clk, posedge rst)
|
||||
if( rst ) begin
|
||||
last_base <= 1'd0;
|
||||
lfo_clk <= 1'b0;
|
||||
cnt <= 8'd0;
|
||||
am <= 7'd0;
|
||||
pm <= 8'd0;
|
||||
am_up <= 1'b1;
|
||||
pm_up <= 1'b1;
|
||||
am_bresenham <= 11'd0;
|
||||
pm_bresenham <= 10'd0;
|
||||
end else begin
|
||||
if( lfo_rst ) begin // synchronous reset
|
||||
last_base <= 1'd0;
|
||||
lfo_clk <= 1'b0;
|
||||
cnt <= 8'd0;
|
||||
am <= 7'd0;
|
||||
pm <= 8'd0;
|
||||
am_up <= 1'b1;
|
||||
pm_up <= 1'b1;
|
||||
am_bresenham <= 11'd0;
|
||||
pm_bresenham <= 10'd0;
|
||||
end else if ( cen ) begin
|
||||
last_base <= sel_base;
|
||||
if( last_base != sel_base ) begin
|
||||
case( lfo_w )
|
||||
2'd0: begin // AM sawtooth
|
||||
if( am_bresenham > 0 ) begin
|
||||
if( am == lfo_amd ) begin
|
||||
am <= 7'd0;
|
||||
am_bresenham <= 11'd0;
|
||||
end
|
||||
else begin
|
||||
am <= am + 1'b1;
|
||||
am_bresenham <= am_bresenham
|
||||
- { 2'd0, cnt_lim, 1'b0} + {4'd0,lfo_amd};
|
||||
end
|
||||
end
|
||||
else am_bresenham <= am_bresenham + {4'd0,lfo_amd};
|
||||
|
||||
if( pm_bresenham > 0 ) begin
|
||||
if( pm == { 1'b0, lfo_pmd } ) begin
|
||||
pm <= pmd_min;
|
||||
pm_bresenham <= 10'd0;
|
||||
end
|
||||
else begin
|
||||
pm <= pm + 1'b1;
|
||||
pm_bresenham <= pm_bresenham
|
||||
- {2'd0,cnt_lim} + {3'd0,lfo_pmd};
|
||||
end
|
||||
end
|
||||
else pm_bresenham <= pm_bresenham + {3'b0,lfo_pmd};
|
||||
end
|
||||
2'd1: // AM square waveform
|
||||
if( cnt == cnt_lim ) begin
|
||||
cnt <= 8'd0;
|
||||
lfo_clk <= ~lfo_clk;
|
||||
am <= lfo_clk ? lfo_amd : 7'd0;
|
||||
pm <= lfo_clk ? {1'b0, lfo_pmd } : pmd_min;
|
||||
end
|
||||
else cnt <= cnt + 1'd1;
|
||||
2'd2: begin // AM triangle
|
||||
if( am_bresenham > 0 ) begin
|
||||
if( am == lfo_amd && am_up) begin
|
||||
am_up <= 1'b0;
|
||||
am_bresenham <= 11'd0;
|
||||
end
|
||||
else if( am == 7'd0 && !am_up) begin
|
||||
am_up <= 1'b1;
|
||||
am_bresenham <= 11'd0;
|
||||
end
|
||||
else begin
|
||||
am <= am_up ? am+1'b1 : am-1'b1;
|
||||
am_bresenham <= am_bresenham
|
||||
- { 2'b0, cnt_lim, 1'b0} + {4'd0,lfo_amd};
|
||||
end
|
||||
end
|
||||
else am_bresenham <= am_bresenham + {4'd0,lfo_amd};
|
||||
|
||||
if( pm_bresenham > 0 ) begin
|
||||
if( pm == {1'b0, lfo_pmd} && pm_up) begin
|
||||
pm_up <= 1'b0;
|
||||
pm_bresenham <= 10'd0;
|
||||
end
|
||||
else if( pm == pmd_min && !pm_up) begin
|
||||
pm_up <= 1'b1;
|
||||
pm_bresenham <= 10'd0;
|
||||
end
|
||||
else begin
|
||||
pm <= pm_up ? pm+1'b1 : pm-1'b1;
|
||||
pm_bresenham <= pm_bresenham
|
||||
- {2'd0,cnt_lim} + {3'd0,lfo_pmd};
|
||||
end
|
||||
end
|
||||
else pm_bresenham <= pm_bresenham + {3'd0,lfo_pmd};
|
||||
end
|
||||
2'd3: begin
|
||||
casez( lfo_amd ) // same as real chip
|
||||
7'b1??????: am <= noise_am[6:0];
|
||||
7'b01?????: am <= { 1'b0, noise_am[5:0] };
|
||||
7'b001????: am <= { 2'b0, noise_am[4:0] };
|
||||
7'b0001???: am <= { 3'b0, noise_am[3:0] };
|
||||
7'b00001??: am <= { 4'b0, noise_am[2:0] };
|
||||
7'b000001?: am <= { 5'b0, noise_am[1:0] };
|
||||
7'b0000001: am <= { 6'b0, noise_am[0] };
|
||||
default: am <= 7'd0;
|
||||
endcase
|
||||
casez( lfo_pmd )
|
||||
7'b1??????: pm <= noise_pm;
|
||||
7'b01?????: pm <= { {2{noise_pm[7]}}, noise_pm[5:0] };
|
||||
7'b001????: pm <= { {3{noise_pm[7]}}, noise_pm[4:0] };
|
||||
7'b0001???: pm <= { {4{noise_pm[7]}}, noise_pm[3:0] };
|
||||
7'b00001??: pm <= { {5{noise_pm[7]}}, noise_pm[2:0] };
|
||||
7'b000001?: pm <= { {6{noise_pm[7]}}, noise_pm[1:0] };
|
||||
7'b0000001: pm <= { {7{noise_pm[7]}}, noise_pm[0] };
|
||||
default: pm <= 8'd0;
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
genvar aux;
|
||||
generate
|
||||
for( aux=0; aux<7; aux=aux+1 ) begin : amnoise
|
||||
jt51_lfo_lfsr #(.init(aux*aux+aux) ) u_noise_am(
|
||||
.rst( rst ),
|
||||
.clk( clk ),
|
||||
.cen( cen ),
|
||||
.base(sel_base),
|
||||
.out( noise_am[aux] )
|
||||
);
|
||||
end
|
||||
for( aux=0; aux<8; aux=aux+1 ) begin : pmnoise
|
||||
jt51_lfo_lfsr #(.init(4*aux*aux-3*aux+40) ) u_noise_pm(
|
||||
.rst( rst ),
|
||||
.clk( clk ),
|
||||
.cen( cen ),
|
||||
.base(sel_base),
|
||||
.out( noise_pm[aux] )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
50
common/Sound/jt51/jt51_lfo_lfsr.v
Normal file
50
common/Sound/jt51/jt51_lfo_lfsr.v
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_lfo_lfsr #(parameter init=220 )(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input base,
|
||||
output out
|
||||
);
|
||||
|
||||
reg [18:0] bb;
|
||||
assign out = bb[18];
|
||||
|
||||
reg last_base;
|
||||
|
||||
always @(posedge clk, posedge rst) begin : base_counter
|
||||
if( rst ) begin
|
||||
bb <= init[18:0];
|
||||
last_base <= 1'b0;
|
||||
end
|
||||
else if(cen) begin
|
||||
last_base <= base;
|
||||
if( last_base != base ) begin
|
||||
bb[18:1] <= bb[17:0];
|
||||
bb[0] <= ^{bb[0],bb[1],bb[14],bb[15],bb[17],bb[18]};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
97
common/Sound/jt51/jt51_lin2exp.v
Normal file
97
common/Sound/jt51/jt51_lin2exp.v
Normal file
@@ -0,0 +1,97 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_lin2exp(
|
||||
input [15:0] lin,
|
||||
output reg [9:0] man,
|
||||
output reg [2:0] exp
|
||||
);
|
||||
|
||||
always @(*) begin
|
||||
casez( lin[15:9] )
|
||||
// negative numbers
|
||||
7'b10?????: begin
|
||||
man = lin[15:6];
|
||||
exp = 3'd7;
|
||||
end
|
||||
7'b110????: begin
|
||||
man = lin[14:5];
|
||||
exp = 3'd6;
|
||||
end
|
||||
7'b1110???: begin
|
||||
man = lin[13:4];
|
||||
exp = 3'd5;
|
||||
end
|
||||
7'b11110??: begin
|
||||
man = lin[12:3];
|
||||
exp = 3'd4;
|
||||
end
|
||||
7'b111110?: begin
|
||||
man = lin[11:2];
|
||||
exp = 3'd3;
|
||||
end
|
||||
7'b1111110: begin
|
||||
man = lin[10:1];
|
||||
exp = 3'd2;
|
||||
end
|
||||
7'b1111111: begin
|
||||
man = lin[ 9:0];
|
||||
exp = 3'd1;
|
||||
end
|
||||
// positive numbers
|
||||
7'b01?????: begin
|
||||
man = lin[15:6];
|
||||
exp = 3'd7;
|
||||
end
|
||||
7'b001????: begin
|
||||
man = lin[14:5];
|
||||
exp = 3'd6;
|
||||
end
|
||||
7'b0001???: begin
|
||||
man = lin[13:4];
|
||||
exp = 3'd5;
|
||||
end
|
||||
7'b00001??: begin
|
||||
man = lin[12:3];
|
||||
exp = 3'd4;
|
||||
end
|
||||
7'b000001?: begin
|
||||
man = lin[11:2];
|
||||
exp = 3'd3;
|
||||
end
|
||||
7'b0000001: begin
|
||||
man = lin[10:1];
|
||||
exp = 3'd2;
|
||||
end
|
||||
7'b0000000: begin
|
||||
man = lin[ 9:0];
|
||||
exp = 3'd1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
man = lin[9:0];
|
||||
exp = 3'd1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
379
common/Sound/jt51/jt51_mmr.v
Normal file
379
common/Sound/jt51/jt51_mmr.v
Normal file
@@ -0,0 +1,379 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_mmr(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen, // P1
|
||||
input [7:0] din,
|
||||
input write,
|
||||
input a0,
|
||||
output reg busy,
|
||||
|
||||
// CT
|
||||
output reg ct1,
|
||||
output reg ct2,
|
||||
|
||||
// Noise
|
||||
output reg ne,
|
||||
output reg [4:0] nfrq,
|
||||
|
||||
// LFO
|
||||
output reg [7:0] lfo_freq,
|
||||
output reg [1:0] lfo_w,
|
||||
output reg [6:0] lfo_amd,
|
||||
output reg [6:0] lfo_pmd,
|
||||
output reg lfo_rst,
|
||||
// Timers
|
||||
output reg [9:0] value_A,
|
||||
output reg [7:0] value_B,
|
||||
output reg load_A,
|
||||
output reg load_B,
|
||||
output reg enable_irq_A,
|
||||
output reg enable_irq_B,
|
||||
output reg clr_flag_A,
|
||||
output reg clr_flag_B,
|
||||
input overflow_A,
|
||||
|
||||
`ifdef TEST_SUPPORT
|
||||
// Test
|
||||
output reg test_eg,
|
||||
output reg test_op0,
|
||||
`endif
|
||||
// REG
|
||||
output [1:0] rl_I,
|
||||
output [2:0] fb_II,
|
||||
output [2:0] con_I,
|
||||
output [6:0] kc_I,
|
||||
output [5:0] kf_I,
|
||||
output [2:0] pms_I,
|
||||
output [1:0] ams_VII,
|
||||
output [2:0] dt1_II,
|
||||
output [3:0] mul_VI,
|
||||
output [6:0] tl_VII,
|
||||
output [1:0] ks_III,
|
||||
output [4:0] arate_II,
|
||||
output amsen_VII,
|
||||
output [4:0] rate1_II,
|
||||
output [1:0] dt2_I,
|
||||
output [4:0] rate2_II,
|
||||
output [3:0] d1l_I,
|
||||
output [3:0] rrate_II,
|
||||
output keyon_II,
|
||||
|
||||
output [1:0] cur_op,
|
||||
output op31_no,
|
||||
output op31_acc,
|
||||
|
||||
output zero,
|
||||
output m1_enters,
|
||||
output m2_enters,
|
||||
output c1_enters,
|
||||
output c2_enters,
|
||||
// Operator
|
||||
output use_prevprev1,
|
||||
output use_internal_x,
|
||||
output use_internal_y,
|
||||
output use_prev2,
|
||||
output use_prev1
|
||||
);
|
||||
|
||||
reg [7:0] selected_register, din_copy ;
|
||||
|
||||
reg up_rl, up_kc, up_kf, up_pms,
|
||||
up_dt1, up_tl, up_ks, up_dt2,
|
||||
up_d1l, up_keyon, up_amsen;
|
||||
reg [1:0] up_op;
|
||||
reg [2:0] up_ch;
|
||||
|
||||
wire busy_reg;
|
||||
|
||||
`ifdef SIMULATION
|
||||
reg mmr_dump;
|
||||
`endif
|
||||
|
||||
parameter REG_TEST = 8'h01,
|
||||
REG_TEST2 = 8'h02,
|
||||
REG_KON = 8'h08,
|
||||
REG_NOISE = 8'h0f,
|
||||
REG_CLKA1 = 8'h10,
|
||||
REG_CLKA2 = 8'h11,
|
||||
REG_CLKB = 8'h12,
|
||||
REG_TIMER = 8'h14,
|
||||
REG_LFRQ = 8'h18,
|
||||
REG_PMDAMD = 8'h19,
|
||||
REG_CTW = 8'h1b,
|
||||
REG_DUMP = 8'h1f;
|
||||
|
||||
reg csm;
|
||||
|
||||
always @(posedge clk, posedge rst) begin : memory_mapped_registers
|
||||
if( rst ) begin
|
||||
selected_register <= 8'h0;
|
||||
{ up_rl, up_kc, up_kf, up_pms, up_dt1, up_tl,
|
||||
up_ks, up_amsen, up_dt2, up_d1l, up_keyon } <= 11'd0;
|
||||
`ifdef TEST_SUPPORT
|
||||
{ test_eg, test_op0 } <= 2'd0;
|
||||
`endif
|
||||
// noise
|
||||
nfrq <= 5'b0;
|
||||
ne <= 1'b0;
|
||||
// timers
|
||||
{ value_A, value_B } <= 18'd0;
|
||||
{ clr_flag_B, clr_flag_A,
|
||||
enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0;
|
||||
// LFO
|
||||
{ lfo_amd, lfo_pmd } <= 14'h0;
|
||||
lfo_freq <= 8'd0;
|
||||
lfo_w <= 2'd0;
|
||||
lfo_rst <= 1'b0;
|
||||
{ ct2, ct1 } <= 2'd0;
|
||||
csm <= 1'b0;
|
||||
din_copy <= 8'd0;
|
||||
`ifdef SIMULATION
|
||||
mmr_dump <= 1'b0;
|
||||
`endif
|
||||
end else begin
|
||||
// WRITE IN REGISTERS
|
||||
if( write ) begin
|
||||
if( !a0 )
|
||||
selected_register <= din;
|
||||
else begin
|
||||
din_copy <= din;
|
||||
up_op <= selected_register[4:3]; // operator to update
|
||||
up_ch <= selected_register[2:0]; // channel to update
|
||||
up_rl <= 1'b0;
|
||||
up_kc <= 1'b0;
|
||||
up_kf <= 1'b0;
|
||||
up_pms <= 1'b0;
|
||||
up_dt1 <= 1'b0;
|
||||
up_tl <= 1'b0;
|
||||
up_ks <= 1'b0;
|
||||
up_amsen <= 1'b0;
|
||||
up_dt2 <= 1'b0;
|
||||
up_d1l <= 1'b0;
|
||||
up_keyon <= 1'b0;
|
||||
// Global registers
|
||||
if( selected_register < 8'h20 ) begin
|
||||
case( selected_register)
|
||||
// registros especiales
|
||||
REG_TEST: lfo_rst <= 1'b1; // regardless of din
|
||||
`ifdef TEST_SUPPORT
|
||||
REG_TEST2: { test_op0, test_eg } <= din[1:0];
|
||||
`endif
|
||||
REG_KON: up_keyon <= 1'b1;
|
||||
REG_NOISE: { ne, nfrq } <= { din[7], din[4:0] };
|
||||
REG_CLKA1: value_A[9:2] <= din;
|
||||
REG_CLKA2: value_A[1:0] <= din[1:0];
|
||||
REG_CLKB: value_B <= din;
|
||||
REG_TIMER: begin
|
||||
csm <= din[7];
|
||||
{ clr_flag_B, clr_flag_A,
|
||||
enable_irq_B, enable_irq_A,
|
||||
load_B, load_A } <= din[5:0];
|
||||
end
|
||||
REG_LFRQ: lfo_freq <= din;
|
||||
REG_PMDAMD: begin
|
||||
if( !din[7] )
|
||||
lfo_amd <= din[6:0];
|
||||
else
|
||||
lfo_pmd <= din[6:0];
|
||||
end
|
||||
REG_CTW: begin
|
||||
{ ct2, ct1 } <= din[7:6];
|
||||
lfo_w <= din[1:0];
|
||||
end
|
||||
`ifdef SIMULATION
|
||||
REG_DUMP:
|
||||
mmr_dump <= 1'b1;
|
||||
`endif
|
||||
default:;
|
||||
endcase
|
||||
end else
|
||||
// channel registers
|
||||
if( selected_register < 8'h40 ) begin
|
||||
case( selected_register[4:3] )
|
||||
2'h0: up_rl <= 1'b1;
|
||||
2'h1: up_kc <= 1'b1;
|
||||
2'h2: up_kf <= 1'b1;
|
||||
2'h3: up_pms<= 1'b1;
|
||||
endcase
|
||||
end
|
||||
else
|
||||
// operator registers
|
||||
begin
|
||||
case( selected_register[7:5] )
|
||||
3'h2: up_dt1 <= 1'b1;
|
||||
3'h3: up_tl <= 1'b1;
|
||||
3'h4: up_ks <= 1'b1;
|
||||
3'h5: up_amsen <= 1'b1;
|
||||
3'h6: up_dt2 <= 1'b1;
|
||||
3'h7: up_d1l <= 1'b1;
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin /* clear once-only bits */
|
||||
`ifdef SIMULATION
|
||||
mmr_dump <= 1'b0;
|
||||
`endif
|
||||
csm <= 1'b0;
|
||||
lfo_rst <= 1'b0;
|
||||
{ clr_flag_B, clr_flag_A } <= 2'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg [4:0] busy_cnt; // busy lasts for 32 synth clock cycles
|
||||
reg old_write;
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
busy <= 1'b0;
|
||||
busy_cnt <= 5'd0;
|
||||
end
|
||||
else begin
|
||||
old_write <= write;
|
||||
if (!old_write && write && a0 ) begin // only set for data writes
|
||||
busy <= 1'b1;
|
||||
busy_cnt <= 5'd0;
|
||||
end
|
||||
else if(cen) begin
|
||||
if( busy_cnt == 5'd31 ) busy <= 1'b0;
|
||||
busy_cnt <= busy_cnt+5'd1;
|
||||
end
|
||||
end
|
||||
|
||||
jt51_reg u_reg(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ), // P1
|
||||
.cen ( cen ), // P1
|
||||
.din ( din_copy ),
|
||||
|
||||
.up_rl ( up_rl ),
|
||||
.up_kc ( up_kc ),
|
||||
.up_kf ( up_kf ),
|
||||
.up_pms ( up_pms ),
|
||||
.up_dt1 ( up_dt1 ),
|
||||
.up_tl ( up_tl ),
|
||||
.up_ks ( up_ks ),
|
||||
.up_amsen ( up_amsen ),
|
||||
.up_dt2 ( up_dt2 ),
|
||||
.up_d1l ( up_d1l ),
|
||||
.up_keyon ( up_keyon ),
|
||||
.op ( up_op ), // operator to update
|
||||
.ch ( up_ch ), // channel to update
|
||||
|
||||
.csm ( csm ),
|
||||
.overflow_A ( overflow_A),
|
||||
|
||||
.busy ( busy_reg ),
|
||||
.rl_I ( rl_I ),
|
||||
.fb_II ( fb_II ),
|
||||
.con_I ( con_I ),
|
||||
|
||||
.kc_I ( kc_I ),
|
||||
.kf_I ( kf_I ),
|
||||
.pms_I ( pms_I ),
|
||||
.ams_VII ( ams_VII ),
|
||||
|
||||
.dt1_II ( dt1_II ),
|
||||
.dt2_I ( dt2_I ),
|
||||
.mul_VI ( mul_VI ),
|
||||
.tl_VII ( tl_VII ),
|
||||
.ks_III ( ks_III ),
|
||||
|
||||
.arate_II ( arate_II ),
|
||||
.amsen_VII ( amsen_VII ),
|
||||
.rate1_II ( rate1_II ),
|
||||
.rate2_II ( rate2_II ),
|
||||
.rrate_II ( rrate_II ),
|
||||
.d1l_I ( d1l_I ),
|
||||
.keyon_II ( keyon_II ),
|
||||
|
||||
.cur_op ( cur_op ),
|
||||
.op31_no ( op31_no ),
|
||||
.op31_acc ( op31_acc ),
|
||||
.zero ( zero ),
|
||||
.m1_enters ( m1_enters ),
|
||||
.m2_enters ( m2_enters ),
|
||||
.c1_enters ( c1_enters ),
|
||||
.c2_enters ( c2_enters ),
|
||||
// Operator
|
||||
.use_prevprev1 ( use_prevprev1 ),
|
||||
.use_internal_x ( use_internal_x ),
|
||||
.use_internal_y ( use_internal_y ),
|
||||
.use_prev2 ( use_prev2 ),
|
||||
.use_prev1 ( use_prev1 )
|
||||
);
|
||||
|
||||
`ifdef SIMULATION
|
||||
`ifndef VERILATOR
|
||||
integer fdump;
|
||||
integer clk_count;
|
||||
initial begin
|
||||
clk_count=0;
|
||||
fdump=$fopen("jt51_cmd.txt","w");
|
||||
end
|
||||
|
||||
always @(posedge clk) clk_count <= clk_count+1;
|
||||
|
||||
always @(posedge write) begin
|
||||
$fdisplay(fdump,"%d,%d,%X",clk_count,a0,din);
|
||||
end
|
||||
`endif
|
||||
`endif
|
||||
|
||||
|
||||
`ifndef JT51_NODEBUG
|
||||
`ifdef SIMULATION
|
||||
/* verilator lint_off PINMISSING */
|
||||
wire [4:0] cnt_aux;
|
||||
|
||||
sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt_aux));
|
||||
|
||||
sep32 #(.width(2),.stg(1)) sep_rl (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rl_I ));
|
||||
sep32 #(.width(3),.stg(2)) sep_fb (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( fb_II ));
|
||||
sep32 #(.width(3),.stg(1)) sep_con(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( con_I ));
|
||||
|
||||
sep32 #(.width(7),.stg(1)) sep_kc (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( kc_I ));
|
||||
sep32 #(.width(6),.stg(1)) sep_kf (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( kf_I ));
|
||||
sep32 #(.width(3),.stg(1)) sep_pms(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( pms_I ));
|
||||
sep32 #(.width(2),.stg(7)) sep_ams(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( ams_VII ));
|
||||
|
||||
sep32 #(.width(3),.stg(2)) sep_dt1(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( dt1_II ));
|
||||
sep32 #(.width(2),.stg(1)) sep_dt2(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( dt2_I ));
|
||||
sep32 #(.width(4),.stg(6)) sep_mul(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( mul_VI ));
|
||||
sep32 #(.width(7),.stg(7)) sep_tl (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( tl_VII ));
|
||||
sep32 #(.width(2),.stg(3)) sep_ks (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( ks_III ));
|
||||
|
||||
sep32 #(.width(5),.stg(2)) sep_ar (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( arate_II ));
|
||||
sep32 #(.width(1),.stg(7)) sep_ame(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( amsen_VII));
|
||||
sep32 #(.width(5),.stg(2)) sep_dr1(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rate1_II ));
|
||||
sep32 #(.width(5),.stg(2)) sep_dr2(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rate2_II ));
|
||||
sep32 #(.width(4),.stg(2)) sep_rr (.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( rrate_II ));
|
||||
sep32 #(.width(4),.stg(1)) sep_d1l(.clk(clk),.cnt(cnt_aux),.cen(cen),.mixed( d1l_I ));
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
67
common/Sound/jt51/jt51_mod.v
Normal file
67
common/Sound/jt51/jt51_mod.v
Normal file
@@ -0,0 +1,67 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
/* This file is part of JT51.
|
||||
|
||||
|
||||
JT51 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT51 program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-4-2017
|
||||
|
||||
*/
|
||||
|
||||
module jt51_mod(
|
||||
input m1_enters,
|
||||
input m2_enters,
|
||||
input c1_enters,
|
||||
input c2_enters,
|
||||
|
||||
input [2:0] alg_I,
|
||||
|
||||
output reg use_prevprev1,
|
||||
output reg use_internal_x,
|
||||
output reg use_internal_y,
|
||||
output reg use_prev2,
|
||||
output reg use_prev1
|
||||
);
|
||||
|
||||
reg [7:0] alg_hot;
|
||||
|
||||
always @(*) begin
|
||||
case( alg_I )
|
||||
3'd0: alg_hot = 8'h1; // D0
|
||||
3'd1: alg_hot = 8'h2; // D1
|
||||
3'd2: alg_hot = 8'h4; // D2
|
||||
3'd3: alg_hot = 8'h8; // D3
|
||||
3'd4: alg_hot = 8'h10; // D4
|
||||
3'd5: alg_hot = 8'h20; // D5
|
||||
3'd6: alg_hot = 8'h40; // D6
|
||||
3'd7: alg_hot = 8'h80; // D7
|
||||
default: alg_hot = 8'hx;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
use_prevprev1 = m1_enters | (m2_enters&alg_hot[5]);
|
||||
use_prev2 = (m2_enters&(|alg_hot[2:0])) | (c2_enters&alg_hot[3]);
|
||||
use_internal_x = c2_enters & alg_hot[2];
|
||||
use_internal_y = c2_enters & (|{alg_hot[4:3],alg_hot[1:0]});
|
||||
use_prev1 = m1_enters | (m2_enters&alg_hot[1]) |
|
||||
(c1_enters&(|{alg_hot[6:3],alg_hot[0]}) )|
|
||||
(c2_enters&(|{alg_hot[5],alg_hot[2]}));
|
||||
end
|
||||
|
||||
endmodule
|
||||
95
common/Sound/jt51/jt51_noise.v
Normal file
95
common/Sound/jt51/jt51_noise.v
Normal file
@@ -0,0 +1,95 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
tab size 4
|
||||
|
||||
See xapp052.pdf from Xilinx
|
||||
|
||||
The NFRQ formula in the App. Note does not make sense:
|
||||
Output rate is 55kHz but for NFRQ=1 the formula states that
|
||||
the noise is 111kHz, twice the output rate per channel.
|
||||
|
||||
That would suggest that the noise for LEFT and RIGHT are
|
||||
different but the rest of the system suggest that LEFT and
|
||||
RIGHT outputs are calculated at the same time, based on the
|
||||
same OP output.
|
||||
|
||||
Also, the block diagram states a 1 bit serial input from
|
||||
EG to NOISE and that seems unnecessary too.
|
||||
|
||||
I have not been able to measure noise in actual chip because
|
||||
operator 31 does not produce any output on my two chips.
|
||||
|
||||
*/
|
||||
|
||||
module jt51_noise(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input [4:0] nfrq,
|
||||
input [9:0] eg,
|
||||
input op31_no,
|
||||
output reg [10:0] out
|
||||
);
|
||||
|
||||
|
||||
reg base;
|
||||
reg [3:0] cnt;
|
||||
|
||||
always @(posedge clk, posedge rst)
|
||||
if( rst ) begin
|
||||
cnt <= 4'b0;
|
||||
end
|
||||
else if(cen) begin
|
||||
if( op31_no ) begin
|
||||
if ( &cnt ) begin
|
||||
cnt <= nfrq[4:1]; // we do not need to use nfrq[0]
|
||||
// because I run it off P1, YM2151 probably ran off PM
|
||||
// but the result is the same, as for NFREQ=31 the YM2151
|
||||
// trips the noise output at each output sample, and for
|
||||
// NFREQ=0 (or 1), the output trips every 16 samples
|
||||
// so NFREQ[0] does not really add resolution
|
||||
end
|
||||
else cnt <= cnt + 4'b1;
|
||||
base <= &cnt;
|
||||
end
|
||||
else base <= 1'b0;
|
||||
end
|
||||
|
||||
wire rnd_sign;
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
if( op31_no )
|
||||
out <= { rnd_sign, {10{~rnd_sign}}^eg };
|
||||
end
|
||||
|
||||
jt51_noise_lfsr #(.init(90)) u_lfsr (
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.base ( base ),
|
||||
.out ( rnd_sign )
|
||||
);
|
||||
|
||||
endmodule
|
||||
48
common/Sound/jt51/jt51_noise_lfsr.v
Normal file
48
common/Sound/jt51/jt51_noise_lfsr.v
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// See xapp052.pdf from Xilinx
|
||||
|
||||
module jt51_noise_lfsr #(parameter init=14220 )(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input base,
|
||||
output out
|
||||
);
|
||||
|
||||
reg [16:0] bb;
|
||||
assign out = bb[16];
|
||||
|
||||
always @(posedge clk, posedge rst) begin : base_counter
|
||||
if( rst ) begin
|
||||
bb <= init[16:0];
|
||||
end
|
||||
else if(cen) begin
|
||||
if( base ) begin
|
||||
bb[16:1] <= bb[15:0];
|
||||
bb[0] <= ~(bb[16]^bb[13]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
344
common/Sound/jt51/jt51_op.v
Normal file
344
common/Sound/jt51/jt51_op.v
Normal file
@@ -0,0 +1,344 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// Pipeline operator
|
||||
|
||||
module jt51_op(
|
||||
`ifdef TEST_SUPPORT
|
||||
input test_eg,
|
||||
input test_op0,
|
||||
`endif
|
||||
input rst,
|
||||
input clk,
|
||||
input cen, // P1
|
||||
input [9:0] pg_phase_X,
|
||||
input [2:0] con_I,
|
||||
input [2:0] fb_II,
|
||||
// volume
|
||||
input [9:0] eg_atten_XI,
|
||||
// modulation
|
||||
input use_prevprev1,
|
||||
input use_internal_x,
|
||||
input use_internal_y,
|
||||
input use_prev2,
|
||||
input use_prev1,
|
||||
input test_214,
|
||||
|
||||
input m1_enters,
|
||||
input c1_enters,
|
||||
`ifdef SIMULATION
|
||||
input zero,
|
||||
`endif
|
||||
// output data
|
||||
output signed [13:0] op_XVII
|
||||
);
|
||||
|
||||
/* enters exits
|
||||
m1 c1
|
||||
m2 S4
|
||||
c1 m1
|
||||
S4 m2
|
||||
*/
|
||||
|
||||
wire signed [13:0] prev1, prevprev1, prev2;
|
||||
|
||||
jt51_sh #( .width(14), .stages(8)) prev1_buffer(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( c1_enters ? op_XVII : prev1 ),
|
||||
.drop ( prev1 )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(14), .stages(8)) prevprev1_buffer(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( c1_enters ? prev1 : prevprev1 ),
|
||||
.drop ( prevprev1 )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(14), .stages(8)) prev2_buffer(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( m1_enters ? op_XVII : prev2 ),
|
||||
.drop ( prev2 )
|
||||
);
|
||||
|
||||
// REGISTER/CYCLE 1
|
||||
// Creation of phase modulation (FM) feedback signal, before shifting
|
||||
reg [13:0] x, y;
|
||||
reg [14:0] xs, ys, pm_preshift_II;
|
||||
reg m1_II;
|
||||
|
||||
always @(*) begin
|
||||
x = ( {14{use_prevprev1}} & prevprev1 ) |
|
||||
( {14{use_internal_x}} & op_XVII ) |
|
||||
( {14{use_prev2}} & prev2 );
|
||||
y = ( {14{use_prev1}} & prev1 ) |
|
||||
( {14{use_internal_y}} & op_XVII );
|
||||
xs = { x[13], x }; // sign-extend
|
||||
ys = { y[13], y }; // sign-extend
|
||||
end
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
pm_preshift_II <= xs + ys; // carry is discarded
|
||||
m1_II <= m1_enters;
|
||||
end
|
||||
|
||||
/* REGISTER/CYCLE 2-7 (also YM2612 extra cycles 1-6)
|
||||
Shifting of FM feedback signal, adding phase from PG to FM phase
|
||||
In YM2203, phasemod_II is not registered at all, it is latched on the first edge
|
||||
in add_pg_phase and the second edge is the output of add_pg_phase. In the YM2612, there
|
||||
are 6 cycles worth of registers between the generated (non-registered) phasemod_II signal
|
||||
and the input to add_pg_phase. */
|
||||
|
||||
reg [9:0] phasemod_II;
|
||||
wire [9:0] phasemod_X;
|
||||
|
||||
always @(*) begin
|
||||
// Shift FM feedback signal
|
||||
if (!m1_II ) // Not m1
|
||||
phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used
|
||||
else // m1
|
||||
case( fb_II )
|
||||
3'd0: phasemod_II = 10'd0;
|
||||
3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] };
|
||||
3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] };
|
||||
3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] };
|
||||
3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] };
|
||||
3'd5: phasemod_II = pm_preshift_II[14:5];
|
||||
3'd6: phasemod_II = pm_preshift_II[13:4];
|
||||
3'd7: phasemod_II = pm_preshift_II[12:3];
|
||||
default: phasemod_II = 10'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
// REGISTER/CYCLE 2-9
|
||||
jt51_sh #( .width(10), .stages(8)) phasemod_sh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( phasemod_II ),
|
||||
.drop ( phasemod_X )
|
||||
);
|
||||
|
||||
|
||||
// REGISTER/CYCLE 10
|
||||
reg [ 9:0] phase;
|
||||
// Sets the maximum number of fanouts for a register or combinational
|
||||
// cell. The Quartus II software will replicate the cell and split
|
||||
// the fanouts among the duplicates until the fanout of each cell
|
||||
// is below the maximum.
|
||||
|
||||
reg [ 7:0] phaselo_XI, aux_X;
|
||||
reg signbit_X;
|
||||
|
||||
always @(*) begin
|
||||
phase = phasemod_X + pg_phase_X;
|
||||
aux_X = phase[7:0] ^ {8{~phase[8]}};
|
||||
signbit_X = phase[9];
|
||||
end
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
phaselo_XI <= aux_X;
|
||||
end
|
||||
|
||||
wire [45:0] sta_XI;
|
||||
|
||||
jt51_phrom u_phrom(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.addr ( aux_X[5:1]),
|
||||
.ph ( sta_XI )
|
||||
);
|
||||
|
||||
// REGISTER/CYCLE 11
|
||||
// Sine table
|
||||
// Main sine table body
|
||||
reg [18:0] stb;
|
||||
reg [10:0] stf, stg;
|
||||
reg [11:0] logsin;
|
||||
reg [10:0] subtresult;
|
||||
reg [11:0] atten_internal_XI;
|
||||
|
||||
always @(*) begin
|
||||
//sta_XI = sinetable[ phaselo_XI[5:1] ];
|
||||
// 2-bit row chooser
|
||||
case( phaselo_XI[7:6] )
|
||||
2'b00: stb = { 10'b0, sta_XI[29], sta_XI[25], 2'b0, sta_XI[18],
|
||||
sta_XI[14], 1'b0, sta_XI[7] , sta_XI[3] };
|
||||
2'b01: stb = { 6'b0 , sta_XI[37], sta_XI[34], 2'b0, sta_XI[28],
|
||||
sta_XI[24], 2'b0, sta_XI[17], sta_XI[13], sta_XI[10], sta_XI[6], sta_XI[2] };
|
||||
2'b10: stb = { 2'b0, sta_XI[43], sta_XI[41], 2'b0, sta_XI[36],
|
||||
sta_XI[33], 2'b0, sta_XI[27], sta_XI[23], 1'b0, sta_XI[20],
|
||||
sta_XI[16], sta_XI[12], sta_XI[9], sta_XI[5], sta_XI[1] };
|
||||
2'b11: stb = {
|
||||
sta_XI[45], sta_XI[44], sta_XI[42], sta_XI[40]
|
||||
, sta_XI[39], sta_XI[38], sta_XI[35], sta_XI[32]
|
||||
, sta_XI[31], sta_XI[30], sta_XI[26], sta_XI[22]
|
||||
, sta_XI[21], sta_XI[19], sta_XI[15], sta_XI[11]
|
||||
, sta_XI[8], sta_XI[4], sta_XI[0] };
|
||||
default: stb = 19'dx;
|
||||
endcase
|
||||
// Fixed value to sum
|
||||
stf = { stb[18:15], stb[12:11], stb[8:7], stb[4:3], stb[0] };
|
||||
// Gated value to sum; bit 14 is indeed used twice
|
||||
if( phaselo_XI[0] )
|
||||
stg = { 2'b0, stb[14], stb[14:13], stb[10:9], stb[6:5], stb[2:1] };
|
||||
else
|
||||
stg = 11'd0;
|
||||
// Sum to produce final logsin value
|
||||
logsin = stf + stg; // Carry-out of 11-bit addition becomes 12th bit
|
||||
// Invert-subtract logsin value from EG attenuation value, with inverted carry
|
||||
// In the actual chip, the output of the above logsin sum is already inverted.
|
||||
// The two LSBs go through inverters (so they're non-inverted); the eg_atten_XI signal goes through inverters.
|
||||
// The adder is normal except the carry-in is 1. It's a 10-bit adder.
|
||||
// The outputs are inverted outputs, including the carry bit.
|
||||
//subtresult = not (('0' & not eg_atten_XI) - ('1' & logsin([11:2])));
|
||||
// After a little pencil-and-paper, turns out this is equivalent to a regular adder!
|
||||
subtresult = eg_atten_XI + logsin[11:2];
|
||||
// Place all but carry bit into result; also two LSBs of logsin
|
||||
// If addition overflowed, make it the largest value (saturate)
|
||||
atten_internal_XI = { subtresult[9:0], logsin[1:0] } | {12{subtresult[10]}};
|
||||
end
|
||||
|
||||
|
||||
// Register cycle 12
|
||||
// Exponential table
|
||||
wire [44:0] exp_XII;
|
||||
reg [11:0] totalatten_XII;
|
||||
reg [12:0] etb;
|
||||
reg [ 9:0] etf;
|
||||
reg [ 2:0] etg;
|
||||
|
||||
jt51_exprom u_exprom(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.addr ( atten_internal_XI[5:1] ),
|
||||
.exp ( exp_XII )
|
||||
);
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
totalatten_XII <= atten_internal_XI;
|
||||
end
|
||||
|
||||
//wire [1:0] et_sel = totalatten_XII[7:6];
|
||||
//wire [4:0] et_fine = totalatten_XII[5:1];
|
||||
|
||||
// Main sine table body
|
||||
always @(*) begin
|
||||
// 2-bit row chooser
|
||||
case( totalatten_XII[7:6] )
|
||||
2'b00: begin
|
||||
etf = { 1'b1, exp_XII[44:36] };
|
||||
etg = { 1'b1, exp_XII[35:34] };
|
||||
end
|
||||
2'b01: begin
|
||||
etf = exp_XII[33:24];
|
||||
etg = { 2'b10, exp_XII[23] };
|
||||
end
|
||||
2'b10: begin
|
||||
etf = { 1'b0, exp_XII[22:14] };
|
||||
etg = exp_XII[13:11];
|
||||
end
|
||||
2'b11: begin
|
||||
etf = { 2'b00, exp_XII[10:3] };
|
||||
etg = exp_XII[2:0];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [9:0] mantissa_XIII;
|
||||
reg [3:0] exponent_XIII;
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
//RESULT
|
||||
mantissa_XIII <= etf + { 7'd0, totalatten_XII[0] ? 3'd0 : etg }; //carry-out discarded
|
||||
exponent_XIII <= totalatten_XII[11:8];
|
||||
end
|
||||
|
||||
// REGISTER/CYCLE 13
|
||||
// Introduce test bit as MSB, 2's complement & Carry-out discarded
|
||||
reg [12:0] shifter, shifter_2, shifter_3;
|
||||
|
||||
always @(*) begin
|
||||
// Floating-point to integer, and incorporating sign bit
|
||||
// Two-stage shifting of mantissa_XIII by exponent_XIII
|
||||
shifter = { 3'b001, mantissa_XIII };
|
||||
case( ~exponent_XIII[1:0] )
|
||||
2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded
|
||||
2'b01: shifter_2 = shifter;
|
||||
2'b10: shifter_2 = { shifter[11:0], 1'b0 };
|
||||
2'b11: shifter_2 = { shifter[10:0], 2'b0 };
|
||||
endcase
|
||||
case( ~exponent_XIII[3:2] )
|
||||
2'b00: shifter_3 = {12'b0, shifter_2[12] };
|
||||
2'b01: shifter_3 = { 8'b0, shifter_2[12:8] };
|
||||
2'b10: shifter_3 = { 4'b0, shifter_2[12:4] };
|
||||
2'b11: shifter_3 = shifter_2;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg signed [13:0] op_XIII;
|
||||
wire signbit_XIII;
|
||||
|
||||
always @(*) begin
|
||||
op_XIII = ({ test_214, shifter_3 } ^ {14{signbit_XIII}}) + {13'd0, signbit_XIII};
|
||||
end
|
||||
|
||||
jt51_sh #( .width(14), .stages(4)) out_padding(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( op_XIII ), // note op_XIII was not latched, is a comb output
|
||||
.drop ( op_XVII )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(1), .stages(3)) shsignbit(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( signbit_X ),
|
||||
.drop ( signbit_XIII )
|
||||
);
|
||||
|
||||
/////////////////// Debug
|
||||
`ifndef JT51_NODEBUG
|
||||
`ifdef SIMULATION
|
||||
/* verilator lint_off PINMISSING */
|
||||
wire [4:0] cnt;
|
||||
|
||||
sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt));
|
||||
|
||||
sep32 #(.width(14),.stg(17)) sep_op(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( op_XVII ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
/* verilator lint_on PINMISSING */
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
300
common/Sound/jt51/jt51_pg.v
Normal file
300
common/Sound/jt51/jt51_pg.v
Normal file
@@ -0,0 +1,300 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_pg(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen /* direct_enable */,
|
||||
input zero,
|
||||
// Channel frequency
|
||||
input [6:0] kc_I,
|
||||
input [5:0] kf_I,
|
||||
// Operator multiplying
|
||||
input [3:0] mul_VI,
|
||||
// Operator detuning
|
||||
input [2:0] dt1_II,
|
||||
input [1:0] dt2_I,
|
||||
// phase modulation from LFO
|
||||
input [7:0] pm,
|
||||
input [2:0] pms_I,
|
||||
// phase operation
|
||||
input pg_rst_III,
|
||||
output reg [ 4:0] keycode_III,
|
||||
output [ 9:0] pg_phase_X
|
||||
);
|
||||
|
||||
wire [19:0] ph_VII;
|
||||
|
||||
reg [19:0] phase_base_VI, phase_step_VII, ph_VIII;
|
||||
reg [17:0] phase_base_IV, phase_base_V;
|
||||
wire pg_rst_VII;
|
||||
|
||||
wire [11:0] phinc_III;
|
||||
|
||||
reg [ 9:0] phinc_addr_III;
|
||||
|
||||
reg [13:0] keycode_II;
|
||||
reg [5:0] dt1_kf_III;
|
||||
reg [ 2:0] dt1_kf_IV;
|
||||
|
||||
reg [4:0] pow2;
|
||||
reg [4:0] dt1_offset_V;
|
||||
reg [2:0] pow2ind_IV;
|
||||
|
||||
reg [2:0] dt1_III, dt1_IV, dt1_V;
|
||||
|
||||
jt51_phinc_rom u_phinctable(
|
||||
// .clk ( clk ),
|
||||
.keycode( phinc_addr_III[9:0] ),
|
||||
.phinc ( phinc_III )
|
||||
);
|
||||
|
||||
always @(*) begin : calcpow2
|
||||
case( pow2ind_IV )
|
||||
3'd0: pow2 = 5'd16;
|
||||
3'd1: pow2 = 5'd17;
|
||||
3'd2: pow2 = 5'd19;
|
||||
3'd3: pow2 = 5'd20;
|
||||
3'd4: pow2 = 5'd22;
|
||||
3'd5: pow2 = 5'd24;
|
||||
3'd6: pow2 = 5'd26;
|
||||
3'd7: pow2 = 5'd29;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [5:0] dt1_limit, dt1_unlimited;
|
||||
reg [4:0] dt1_limited_IV;
|
||||
|
||||
always @(*) begin : dt1_limit_mux
|
||||
case( dt1_IV[1:0] )
|
||||
default: dt1_limit = 6'd8;
|
||||
2'd1: dt1_limit = 6'd8;
|
||||
2'd2: dt1_limit = 6'd16;
|
||||
2'd3: dt1_limit = 6'd22;
|
||||
endcase
|
||||
case( dt1_kf_IV )
|
||||
3'd0: dt1_unlimited = { 5'd0, pow2[4] }; // <2
|
||||
3'd1: dt1_unlimited = { 4'd0, pow2[4:3] }; // <4
|
||||
3'd2: dt1_unlimited = { 3'd0, pow2[4:2] }; // <8
|
||||
3'd3: dt1_unlimited = { 2'd0, pow2[4:1] };
|
||||
3'd4: dt1_unlimited = { 1'd0, pow2[4:0] };
|
||||
3'd5: dt1_unlimited = { pow2[4:0], 1'd0 };
|
||||
default:dt1_unlimited = 6'd0;
|
||||
endcase
|
||||
dt1_limited_IV = dt1_unlimited > dt1_limit ?
|
||||
dt1_limit[4:0] : dt1_unlimited[4:0];
|
||||
end
|
||||
|
||||
reg signed [8:0] mod_I;
|
||||
|
||||
always @(*) begin
|
||||
case( pms_I ) // comprobar en silicio
|
||||
3'd0: mod_I = 9'd0;
|
||||
3'd1: mod_I = { 7'd0, pm[6:5] };
|
||||
3'd2: mod_I = { 6'd0, pm[6:4] };
|
||||
3'd3: mod_I = { 5'd0, pm[6:3] };
|
||||
3'd4: mod_I = { 4'd0, pm[6:2] };
|
||||
3'd5: mod_I = { 3'd0, pm[6:1] };
|
||||
3'd6: mod_I = { 1'd0, pm[6:0], 1'b0 };
|
||||
3'd7: mod_I = { pm[6:0], 2'b0 };
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
reg [3:0] octave_III;
|
||||
|
||||
wire [12:0] keycode_I;
|
||||
|
||||
jt51_pm u_pm(
|
||||
// Channel frequency
|
||||
.kc_I ( kc_I ),
|
||||
.kf_I ( kf_I ),
|
||||
.add ( ~pm[7] ),
|
||||
.mod_I ( mod_I ),
|
||||
.kcex ( keycode_I )
|
||||
);
|
||||
|
||||
// limit value at which we add +64 to the keycode
|
||||
// I assume this is to avoid the note==3 violation somehow
|
||||
parameter dt2_lim2 = 8'd11 + 8'd64;
|
||||
parameter dt2_lim3 = 8'd31 + 8'd64;
|
||||
|
||||
// I
|
||||
always @(posedge clk) if(cen) begin : phase_calculation
|
||||
case ( dt2_I )
|
||||
2'd0: keycode_II <= { 1'b0, keycode_I } +
|
||||
(keycode_I[7:6]==2'd3 ? 14'd64:14'd0);
|
||||
2'd1: keycode_II <= { 1'b0, keycode_I } + 14'd512 +
|
||||
(keycode_I[7:6]==2'd3 ? 14'd64:14'd0);
|
||||
2'd2: keycode_II <= { 1'b0, keycode_I } + 14'd628 +
|
||||
(keycode_I[7:0]>dt2_lim2 ? 14'd64:14'd0);
|
||||
2'd3: keycode_II <= { 1'b0, keycode_I } + 14'd800 +
|
||||
(keycode_I[7:0]>dt2_lim3 ? 14'd64:14'd0);
|
||||
endcase
|
||||
end
|
||||
|
||||
// II
|
||||
always @(posedge clk) if(cen) begin
|
||||
phinc_addr_III <= keycode_II[9:0];
|
||||
octave_III <= keycode_II[13:10];
|
||||
keycode_III <= keycode_II[12:8];
|
||||
case( dt1_II[1:0] )
|
||||
2'd1: dt1_kf_III <= keycode_II[13:8] - (6'b1<<2);
|
||||
2'd2: dt1_kf_III <= keycode_II[13:8] + (6'b1<<2);
|
||||
2'd3: dt1_kf_III <= keycode_II[13:8] + (6'b1<<3);
|
||||
default:dt1_kf_III <= keycode_II[13:8];
|
||||
endcase
|
||||
dt1_III <= dt1_II;
|
||||
end
|
||||
|
||||
// III
|
||||
always @(posedge clk) if(cen) begin
|
||||
case( octave_III )
|
||||
4'd0: phase_base_IV <= { 8'd0, phinc_III[11:2] };
|
||||
4'd1: phase_base_IV <= { 7'd0, phinc_III[11:1] };
|
||||
4'd2: phase_base_IV <= { 6'd0, phinc_III[11:0] };
|
||||
4'd3: phase_base_IV <= { 5'd0, phinc_III[11:0], 1'b0 };
|
||||
4'd4: phase_base_IV <= { 4'd0, phinc_III[11:0], 2'b0 };
|
||||
4'd5: phase_base_IV <= { 3'd0, phinc_III[11:0], 3'b0 };
|
||||
4'd6: phase_base_IV <= { 2'd0, phinc_III[11:0], 4'b0 };
|
||||
4'd7: phase_base_IV <= { 1'd0, phinc_III[11:0], 5'b0 };
|
||||
4'd8: phase_base_IV <= { phinc_III[11:0], 6'b0 };
|
||||
default:phase_base_IV <= 18'd0;
|
||||
endcase
|
||||
pow2ind_IV <= dt1_kf_III[2:0];
|
||||
dt1_IV <= dt1_III;
|
||||
dt1_kf_IV <= dt1_kf_III[5:3];
|
||||
end
|
||||
|
||||
// IV LIMIT_BASE
|
||||
always @(posedge clk) if(cen) begin
|
||||
if( phase_base_IV > 18'd82976 )
|
||||
phase_base_V <= 18'd82976;
|
||||
else
|
||||
phase_base_V <= phase_base_IV;
|
||||
dt1_offset_V <= dt1_limited_IV;
|
||||
dt1_V <= dt1_IV;
|
||||
end
|
||||
|
||||
// V APPLY_DT1
|
||||
always @(posedge clk) if(cen) begin
|
||||
if( dt1_V[1:0]==2'd0 )
|
||||
phase_base_VI <= {2'b0, phase_base_V};
|
||||
else begin
|
||||
if( !dt1_V[2] )
|
||||
phase_base_VI <= {2'b0, phase_base_V} + { 15'd0, dt1_offset_V };
|
||||
else
|
||||
phase_base_VI <= {2'b0, phase_base_V} - { 15'd0, dt1_offset_V };
|
||||
end
|
||||
end
|
||||
|
||||
// VI APPLY_MUL
|
||||
always @(posedge clk) if(cen) begin
|
||||
if( mul_VI==4'd0 )
|
||||
phase_step_VII <= { 1'b0, phase_base_VI[19:1] };
|
||||
else
|
||||
phase_step_VII <= phase_base_VI * mul_VI;
|
||||
end
|
||||
|
||||
// VII have same number of stages as jt51_envelope
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst )
|
||||
ph_VIII <= 20'd0;
|
||||
else if(cen) begin
|
||||
ph_VIII <= pg_rst_VII ? 20'd0 : ph_VII + phase_step_VII;
|
||||
`ifdef DISPLAY_STEP
|
||||
$display( "%d", phase_step_VII );
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
// VIII
|
||||
reg [19:0] ph_IX;
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst )
|
||||
ph_IX <= 20'd0;
|
||||
else if(cen) begin
|
||||
ph_IX <= ph_VIII[19:0];
|
||||
end
|
||||
end
|
||||
|
||||
// IX
|
||||
reg [19:0] ph_X;
|
||||
assign pg_phase_X = ph_X[19:10];
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
ph_X <= 20'd0;
|
||||
end else if(cen) begin
|
||||
ph_X <= ph_IX;
|
||||
end
|
||||
end
|
||||
|
||||
jt51_sh #( .width(20), .stages(32-3) ) u_phsh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( ph_X ),
|
||||
.drop ( ph_VII )
|
||||
);
|
||||
|
||||
jt51_sh #( .width(1), .stages(4) ) u_pgrstsh(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( pg_rst_III),
|
||||
.drop ( pg_rst_VII)
|
||||
);
|
||||
|
||||
`ifndef JT51_NODEBUG
|
||||
`ifdef SIMULATION
|
||||
/* verilator lint_off PINMISSING */
|
||||
|
||||
wire [4:0] cnt;
|
||||
|
||||
sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt));
|
||||
// wire zero_VIII;
|
||||
//
|
||||
// jt51_sh #(.width(1),.stages(7)) u_sep_aux(
|
||||
// .clk ( clk ),
|
||||
// .din ( zero ),
|
||||
// .drop ( zero_VIII )
|
||||
// );
|
||||
//
|
||||
// sep32 #(.width(1),.stg(8)) sep_ref(
|
||||
// .clk ( clk ),
|
||||
// .cen(cen),
|
||||
// .mixed ( zero_VIII ),
|
||||
// .cnt ( cnt )
|
||||
// );
|
||||
sep32 #(.width(10),.stg(10)) sep_ph(
|
||||
.clk ( clk ),
|
||||
.cen(cen),
|
||||
.mixed ( pg_phase_X ),
|
||||
.cnt ( cnt )
|
||||
);
|
||||
|
||||
/* verilator lint_on PINMISSING */
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
1058
common/Sound/jt51/jt51_phinc_rom.v
Normal file
1058
common/Sound/jt51/jt51_phinc_rom.v
Normal file
File diff suppressed because it is too large
Load Diff
77
common/Sound/jt51/jt51_phrom.v
Normal file
77
common/Sound/jt51/jt51_phrom.v
Normal file
@@ -0,0 +1,77 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
|
||||
/* This file is part of JT51.
|
||||
|
||||
|
||||
JT51 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT51 program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-4-2017
|
||||
|
||||
*/
|
||||
|
||||
module jt51_phrom
|
||||
(
|
||||
input [4:0] addr,
|
||||
input clk,
|
||||
input cen,
|
||||
output reg [45:0] ph
|
||||
);
|
||||
|
||||
reg [45:0] sinetable[31:0];
|
||||
initial
|
||||
begin
|
||||
sinetable[5'd0 ] = 46'b0001100000100100010001000010101010101001010010;
|
||||
sinetable[5'd1 ] = 46'b0001100000110100000100000010010001001101000001;
|
||||
sinetable[5'd2 ] = 46'b0001100000110100000100110010001011001101100000;
|
||||
sinetable[5'd3 ] = 46'b0001110000010000000000110010110001001101110010;
|
||||
sinetable[5'd4 ] = 46'b0001110000010000001100000010111010001101101001;
|
||||
sinetable[5'd5 ] = 46'b0001110000010100001001100010000000101101111010;
|
||||
sinetable[5'd6 ] = 46'b0001110000010100001101100010010011001101011010;
|
||||
sinetable[5'd7 ] = 46'b0001110000011100000101010010111000101111111100;
|
||||
sinetable[5'd8 ] = 46'b0001110000111000000001110010101110001101110111;
|
||||
sinetable[5'd9 ] = 46'b0001110000111000010100111000011101011010100110;
|
||||
sinetable[5'd10] = 46'b0001110000111100011000011000111100001001111010;
|
||||
sinetable[5'd11] = 46'b0001110000111100011100111001101011001001110111;
|
||||
sinetable[5'd12] = 46'b0100100001010000010001011001001000111010110111;
|
||||
sinetable[5'd13] = 46'b0100100001010100010001001001110001111100101010;
|
||||
sinetable[5'd14] = 46'b0100100001010100010101101101111110100101000110;
|
||||
sinetable[5'd15] = 46'b0100100011100000001000011001010110101101111001;
|
||||
sinetable[5'd16] = 46'b0100100011100100001000101011100101001011101111;
|
||||
sinetable[5'd17] = 46'b0100100011101100000111011010000001011010110001;
|
||||
sinetable[5'd18] = 46'b0100110011001000000111101010000010111010111111;
|
||||
sinetable[5'd19] = 46'b0100110011001100001011011110101110110110000001;
|
||||
sinetable[5'd20] = 46'b0100110011101000011010111011001010001101110001;
|
||||
sinetable[5'd21] = 46'b0100110011101101011010110101111001010100001111;
|
||||
sinetable[5'd22] = 46'b0111000010000001010111000101010101010110010111;
|
||||
sinetable[5'd23] = 46'b0111000010000101010111110111110101010010111011;
|
||||
sinetable[5'd24] = 46'b0111000010110101101000101100001000010000011001;
|
||||
sinetable[5'd25] = 46'b0111010010011001100100011110100100010010010010;
|
||||
sinetable[5'd26] = 46'b0111010010111010100101100101000000110100100011;
|
||||
sinetable[5'd27] = 46'b1010000010011010101101011101100001110010011010;
|
||||
sinetable[5'd28] = 46'b1010000010111111111100100111010100010000111001;
|
||||
sinetable[5'd29] = 46'b1010010111110100110010001100111001010110100000;
|
||||
sinetable[5'd30] = 46'b1011010111010011111011011110000100110010100001;
|
||||
sinetable[5'd31] = 46'b1110011011110001111011100111100001110110100111;
|
||||
|
||||
end
|
||||
|
||||
always @ (posedge clk) if(cen)
|
||||
ph <= sinetable[addr];
|
||||
|
||||
endmodule
|
||||
95
common/Sound/jt51/jt51_pm.v
Normal file
95
common/Sound/jt51/jt51_pm.v
Normal file
@@ -0,0 +1,95 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_pm(
|
||||
input [6:0] kc_I,
|
||||
input [5:0] kf_I,
|
||||
input [8:0] mod_I,
|
||||
input add,
|
||||
output reg [12:0] kcex
|
||||
);
|
||||
|
||||
reg [9:0] lim;
|
||||
reg [13:0] kcex0, kcex1;
|
||||
reg [1:0] extra;
|
||||
|
||||
reg [6:0] kcin;
|
||||
reg carry;
|
||||
|
||||
always @(*) begin: kc_input_cleaner
|
||||
{ carry, kcin } = kc_I[1:0]==2'd3 ? { 1'b0, kc_I } + 8'd1 : {1'b0,kc_I};
|
||||
end
|
||||
|
||||
always @(*) begin : addition
|
||||
lim = { 1'd0, mod_I } + { 4'd0, kf_I };
|
||||
case( kcin[3:0] )
|
||||
default:
|
||||
if( lim>=10'd448 ) extra = 2'd2;
|
||||
else if( lim>=10'd256 ) extra = 2'd1;
|
||||
else extra = 2'd0;
|
||||
4'd1,4'd5,4'd9,4'd13:
|
||||
if( lim>=10'd384 ) extra = 2'd2;
|
||||
else if( lim>=10'd192 ) extra = 2'd1;
|
||||
else extra = 2'd0;
|
||||
4'd2,4'd6,4'd10,4'd14:
|
||||
if( lim>=10'd512 ) extra = 2'd3;
|
||||
else if( lim>=10'd320 ) extra = 2'd2;
|
||||
else if( lim>=10'd128 ) extra = 2'd1;
|
||||
else extra = 2'd0;
|
||||
endcase
|
||||
kcex0 = {1'b0,kcin,kf_I} + { 6'd0, extra, 6'd0 } + { 5'd0, mod_I };
|
||||
kcex1 = kcex0[7:6]==2'd3 ? kcex0 + 14'd64 : kcex0;
|
||||
end
|
||||
|
||||
reg signed [9:0] slim;
|
||||
reg [1:0] sextra;
|
||||
reg [13:0] skcex0, skcex1;
|
||||
|
||||
always @(*) begin : subtraction
|
||||
slim = { 1'd0, mod_I } - { 4'd0, kf_I };
|
||||
case( kcin[3:0] )
|
||||
default:
|
||||
if( slim>=10'sd449 ) sextra = 2'd3;
|
||||
else if( slim>=10'sd257 ) sextra = 2'd2;
|
||||
else if( slim>=10'sd65 ) sextra = 2'd1;
|
||||
else sextra = 2'd0;
|
||||
4'd1,4'd5,4'd9,4'd13:
|
||||
if( slim>=10'sd321 ) sextra = 2'd2;
|
||||
else if( slim>=10'sd129 ) sextra = 2'd1;
|
||||
else sextra = 2'd0;
|
||||
4'd2,4'd6,4'd10,4'd14:
|
||||
if( slim>=10'sd385 ) sextra = 2'd2;
|
||||
else if( slim>=10'sd193 ) sextra = 2'd1;
|
||||
else sextra = 2'd0;
|
||||
endcase
|
||||
skcex0 = {1'b0,kcin,kf_I} - { 6'd0, sextra, 6'd0 } - { 5'd0, mod_I };
|
||||
skcex1 = skcex0[7:6]==2'd3 ? skcex0 - 14'd64 : skcex0;
|
||||
end
|
||||
|
||||
always @(*) begin : mux
|
||||
if ( add )
|
||||
kcex = kcex1[13] | carry ? {3'd7, 4'd14, 6'd63} : kcex1[12:0];
|
||||
else
|
||||
kcex = carry ? {3'd7, 4'd14, 6'd63} : (skcex1[13] ? 13'd0 : skcex1[12:0]);
|
||||
end
|
||||
|
||||
endmodule
|
||||
303
common/Sound/jt51/jt51_reg.v
Normal file
303
common/Sound/jt51/jt51_reg.v
Normal file
@@ -0,0 +1,303 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_reg(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen, // P1
|
||||
input [7:0] din,
|
||||
|
||||
input up_rl,
|
||||
input up_kc,
|
||||
input up_kf,
|
||||
input up_pms,
|
||||
input up_dt1,
|
||||
input up_tl,
|
||||
input up_ks,
|
||||
input up_amsen,
|
||||
input up_dt2,
|
||||
input up_d1l,
|
||||
input up_keyon,
|
||||
input [1:0] op, // operator to update
|
||||
input [2:0] ch, // channel to update
|
||||
|
||||
input csm,
|
||||
input overflow_A,
|
||||
|
||||
output reg busy,
|
||||
output [1:0] rl_I,
|
||||
output [2:0] fb_II,
|
||||
output [2:0] con_I,
|
||||
output [6:0] kc_I,
|
||||
output [5:0] kf_I,
|
||||
output [2:0] pms_I,
|
||||
output [1:0] ams_VII,
|
||||
output [2:0] dt1_II,
|
||||
output [3:0] mul_VI,
|
||||
output [6:0] tl_VII,
|
||||
output [1:0] ks_III,
|
||||
output amsen_VII,
|
||||
|
||||
output [4:0] arate_II,
|
||||
output [4:0] rate1_II,
|
||||
output [4:0] rate2_II,
|
||||
output [3:0] rrate_II,
|
||||
|
||||
output [1:0] dt2_I,
|
||||
output [3:0] d1l_I,
|
||||
output keyon_II,
|
||||
|
||||
// Pipeline order
|
||||
output reg zero,
|
||||
output reg m1_enters,
|
||||
output reg m2_enters,
|
||||
output reg c1_enters,
|
||||
output reg c2_enters,
|
||||
// Operator
|
||||
output use_prevprev1,
|
||||
output use_internal_x,
|
||||
output use_internal_y,
|
||||
output use_prev2,
|
||||
output use_prev1,
|
||||
|
||||
output [1:0] cur_op,
|
||||
output reg op31_no,
|
||||
output reg op31_acc
|
||||
);
|
||||
|
||||
reg kon, koff;
|
||||
reg [1:0] csm_state;
|
||||
reg [4:0] csm_cnt;
|
||||
|
||||
wire csm_kon = csm_state[0];
|
||||
wire csm_koff = csm_state[1];
|
||||
|
||||
always @(*) begin
|
||||
m1_enters = cur_op == 2'b00;
|
||||
m2_enters = cur_op == 2'b01;
|
||||
c1_enters = cur_op == 2'b10;
|
||||
c2_enters = cur_op == 2'b11;
|
||||
end
|
||||
|
||||
wire up = up_rl | up_kc | up_kf | up_pms | up_dt1 | up_tl |
|
||||
up_ks | up_amsen | up_dt2 | up_d1l | up_keyon;
|
||||
|
||||
reg [4:0] cur;
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
op31_no <= cur == 5'o10;
|
||||
op31_acc <= cur == 5'o16;
|
||||
end
|
||||
|
||||
assign cur_op = cur[4:3];
|
||||
|
||||
wire [4:0] req_I = { op, ch };
|
||||
wire [4:0] req_II = req_I + 5'd1;
|
||||
wire [4:0] req_III = req_II + 5'd1;
|
||||
wire [4:0] req_IV = req_III + 5'd1;
|
||||
wire [4:0] req_V = req_IV + 5'd1;
|
||||
wire [4:0] req_VI = req_V + 5'd1;
|
||||
wire [4:0] req_VII = req_VI + 5'd1;
|
||||
|
||||
|
||||
wire update_op_I = cur == req_I;
|
||||
wire update_op_II = cur == req_II;
|
||||
wire update_op_III = cur == req_III;
|
||||
wire update_op_IV = cur == req_IV;
|
||||
wire update_op_V = cur == req_V;
|
||||
wire update_op_VI = cur == req_VI;
|
||||
wire update_op_VII = cur == req_VII;
|
||||
|
||||
wire up_rl_ch = up_rl & update_op_I;
|
||||
wire up_fb_ch = up_rl & update_op_II;
|
||||
wire up_con_ch = up_rl & update_op_I;
|
||||
|
||||
wire up_kc_ch = up_kc & update_op_I;
|
||||
wire up_kf_ch = up_kf & update_op_I;
|
||||
wire up_pms_ch = up_pms & update_op_I;
|
||||
wire up_ams_ch = up_pms & update_op_VII;
|
||||
|
||||
wire up_dt1_op = up_dt1 & update_op_II; // DT1, MUL
|
||||
wire up_mul_op = up_dt1 & update_op_VI; // DT1, MUL
|
||||
wire up_tl_op = up_tl & update_op_VII;
|
||||
wire up_ks_op = up_ks & update_op_III; // KS, AR
|
||||
wire up_amsen_op= up_amsen & update_op_VII; // AMS-EN, D1R
|
||||
wire up_dt2_op = up_dt2 & update_op_I; // DT2, D2R
|
||||
wire up_d1l_op = up_d1l & update_op_I; // D1L, RR
|
||||
|
||||
wire up_ar_op = up_ks & update_op_II; // KS, AR
|
||||
wire up_d1r_op = up_amsen & update_op_II; // AMS-EN, D1R
|
||||
wire up_d2r_op = up_dt2 & update_op_II; // DT2, D2R
|
||||
wire up_rr_op = up_d1l & update_op_II; // D1L, RR
|
||||
|
||||
wire [4:0] next = cur+5'd1;
|
||||
|
||||
always @(posedge clk, posedge rst) begin : up_counter
|
||||
if( rst ) begin
|
||||
cur <= 5'h0;
|
||||
zero <= 1'b0;
|
||||
busy <= 1'b0;
|
||||
end
|
||||
else if(cen) begin
|
||||
cur <= next;
|
||||
zero <= next== 5'd0;
|
||||
if( &cur ) busy <= up && !busy;
|
||||
end
|
||||
end
|
||||
|
||||
wire [2:0] cur_ch = cur[2:0];
|
||||
wire [3:0] keyon_op = din[6:3];
|
||||
wire [2:0] keyon_ch = din[2:0];
|
||||
|
||||
jt51_kon u_kon (
|
||||
.rst (rst ),
|
||||
.clk (clk ),
|
||||
.cen (cen ),
|
||||
.keyon_op (keyon_op ),
|
||||
.keyon_ch (keyon_ch ),
|
||||
.cur_op (cur_op ),
|
||||
.cur_ch (cur_ch ),
|
||||
.up_keyon (up_keyon && busy ),
|
||||
.csm (csm ),
|
||||
.overflow_A(overflow_A),
|
||||
.keyon_II (keyon_II )
|
||||
);
|
||||
|
||||
|
||||
jt51_mod u_mod(
|
||||
.alg_I ( con_I ),
|
||||
.m1_enters ( m1_enters ),
|
||||
.m2_enters ( m2_enters ),
|
||||
.c1_enters ( c1_enters ),
|
||||
.c2_enters ( c2_enters ),
|
||||
|
||||
.use_prevprev1 ( use_prevprev1 ),
|
||||
.use_internal_x( use_internal_x ),
|
||||
.use_internal_y( use_internal_y ),
|
||||
.use_prev2 ( use_prev2 ),
|
||||
.use_prev1 ( use_prev1 )
|
||||
);
|
||||
|
||||
jt51_csr_op u_csr_op(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ), // P1
|
||||
.din ( din ),
|
||||
|
||||
.up_dt1_op ( up_dt1_op ),
|
||||
.up_mul_op ( up_mul_op ),
|
||||
.up_tl_op ( up_tl_op ),
|
||||
.up_ks_op ( up_ks_op ),
|
||||
.up_amsen_op ( up_amsen_op ),
|
||||
.up_dt2_op ( up_dt2_op ),
|
||||
.up_d1l_op ( up_d1l_op ),
|
||||
.up_ar_op ( up_ar_op ),
|
||||
.up_d1r_op ( up_d1r_op ),
|
||||
.up_d2r_op ( up_d2r_op ),
|
||||
.up_rr_op ( up_rr_op ),
|
||||
|
||||
.dt1 ( dt1_II ),
|
||||
.mul ( mul_VI ),
|
||||
.tl ( tl_VII ),
|
||||
.ks ( ks_III ),
|
||||
.amsen ( amsen_VII ),
|
||||
.dt2 ( dt2_I ),
|
||||
.d1l ( d1l_I ),
|
||||
.arate ( arate_II ),
|
||||
.rate1 ( rate1_II ),
|
||||
.rate2 ( rate2_II ),
|
||||
.rrate ( rrate_II )
|
||||
);
|
||||
|
||||
jt51_csr_ch u_csr_ch(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( din ),
|
||||
|
||||
.up_rl_ch ( up_rl_ch ),
|
||||
.up_fb_ch ( up_fb_ch ),
|
||||
.up_con_ch ( up_con_ch ),
|
||||
.up_kc_ch ( up_kc_ch ),
|
||||
.up_kf_ch ( up_kf_ch ),
|
||||
.up_ams_ch ( up_ams_ch ),
|
||||
.up_pms_ch ( up_pms_ch ),
|
||||
|
||||
.rl ( rl_I ),
|
||||
.fb ( fb_II ),
|
||||
.con ( con_I ),
|
||||
.kc ( kc_I ),
|
||||
.kf ( kf_I ),
|
||||
.ams ( ams_VII ),
|
||||
.pms ( pms_I )
|
||||
);
|
||||
|
||||
//////////////////// Debug
|
||||
`ifndef JT51_NODEBUG
|
||||
`ifdef SIMULATION
|
||||
/* verilator lint_off PINMISSING */
|
||||
wire [4:0] cnt_aux;
|
||||
|
||||
sep32_cnt u_sep32_cnt (.clk(clk), .cen(cen), .zero(zero), .cnt(cnt_aux));
|
||||
|
||||
sep32 #(.width(7),.stg(1)) sep_tl(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( tl_VII ),
|
||||
.cnt ( cnt_aux )
|
||||
);
|
||||
|
||||
sep32 #(.width(5),.stg(1)) sep_ar(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( arate_II ),
|
||||
.cnt ( cnt_aux )
|
||||
);
|
||||
|
||||
|
||||
sep32 #(.width(4),.stg(1)) sep_d1l(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( d1l_I ),
|
||||
.cnt ( cnt_aux )
|
||||
);
|
||||
|
||||
|
||||
sep32 #(.width(4),.stg(1)) sep_rr(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( rrate_II ),
|
||||
.cnt ( cnt_aux )
|
||||
);
|
||||
|
||||
sep32 #(.width(1),.stg(1)) sep_amsen(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.mixed ( amsen_VII ),
|
||||
.cnt ( cnt_aux )
|
||||
);
|
||||
|
||||
/* verilator lint_on PINMISSING */
|
||||
`endif
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
46
common/Sound/jt51/jt51_sh.v
Normal file
46
common/Sound/jt51/jt51_sh.v
Normal file
@@ -0,0 +1,46 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_sh #(parameter width=5, stages=32, rstval=1'b0 ) (
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input [width-1:0] din,
|
||||
output [width-1:0] drop
|
||||
);
|
||||
|
||||
reg [stages-1:0] bits[width-1:0];
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if(rst)
|
||||
bits[i] <= {stages{rstval}};
|
||||
else if(cen)
|
||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||
end
|
||||
assign drop[i] = bits[i][stages-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
106
common/Sound/jt51/jt51_timers.v
Normal file
106
common/Sound/jt51/jt51_timers.v
Normal file
@@ -0,0 +1,106 @@
|
||||
/* This file is part of JT51.
|
||||
|
||||
JT51 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.
|
||||
|
||||
JT51 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 JT51. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-10-2016
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt51_timers(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input zero,
|
||||
input [9:0] value_A,
|
||||
input [7:0] value_B,
|
||||
input load_A,
|
||||
input load_B,
|
||||
input clr_flag_A,
|
||||
input clr_flag_B,
|
||||
input enable_irq_A,
|
||||
input enable_irq_B,
|
||||
output flag_A,
|
||||
output flag_B,
|
||||
output overflow_A,
|
||||
output irq_n
|
||||
);
|
||||
|
||||
assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) );
|
||||
|
||||
jt51_timer #(.counter_width(10)) timer_A(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.zero ( zero ),
|
||||
.start_value( value_A ),
|
||||
.load ( load_A ),
|
||||
.clr_flag ( clr_flag_A),
|
||||
.flag ( flag_A ),
|
||||
.overflow ( overflow_A)
|
||||
);
|
||||
|
||||
jt51_timer #(.counter_width(12)) timer_B(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.zero ( zero ),
|
||||
.start_value( {value_B,4'b0}),
|
||||
.load ( load_B ),
|
||||
.clr_flag ( clr_flag_B ),
|
||||
.flag ( flag_B ),
|
||||
.overflow ( )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module jt51_timer #(parameter counter_width = 10 )
|
||||
(
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input zero,
|
||||
input [counter_width-1:0] start_value,
|
||||
input load,
|
||||
input clr_flag,
|
||||
output reg flag,
|
||||
output reg overflow
|
||||
);
|
||||
|
||||
reg last_load;
|
||||
reg [counter_width-1:0] cnt, next;
|
||||
|
||||
always@(posedge clk, posedge rst)
|
||||
if( rst )
|
||||
flag <= 1'b0;
|
||||
else /*if(cen)*/ begin
|
||||
if( clr_flag )
|
||||
flag <= 1'b0;
|
||||
else if(overflow) flag<=1'b1;
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
{overflow, next } = { 1'b0, cnt } + 1'b1;
|
||||
end
|
||||
|
||||
always @(posedge clk) if(cen && zero) begin : counter
|
||||
last_load <= load;
|
||||
if( (load && !last_load) || overflow ) begin
|
||||
cnt <= start_value;
|
||||
end
|
||||
else if( last_load ) cnt <= next;
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user