mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-03-08 03:29:26 +00:00
Jackal: another port
This commit is contained in:
31
Arcade_MiST/Konami Jackal/Jackal.qpf
Normal file
31
Arcade_MiST/Konami Jackal/Jackal.qpf
Normal file
@@ -0,0 +1,31 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# 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 = 00:21:03 December 03, 2019
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "13.1"
|
||||
DATE = "00:21:03 December 03, 2019"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "Jackal"
|
||||
|
||||
249
Arcade_MiST/Konami Jackal/Jackal.qsf
Normal file
249
Arcade_MiST/Konami Jackal/Jackal.qsf
Normal file
@@ -0,0 +1,249 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Copyright (C) 1991-2014 Altera Corporation
|
||||
# Your use of Altera Corporation's design tools, logic functions
|
||||
# and other software and tools, and its AMPP partner logic
|
||||
# functions, and any output files from any of the foregoing
|
||||
# (including device programming or simulation files), and any
|
||||
# associated documentation or information are expressly subject
|
||||
# to the terms and conditions of the Altera Program License
|
||||
# Subscription Agreement, Altera MegaCore Function License
|
||||
# Agreement, or other applicable license agreement, including,
|
||||
# without limitation, that your use is for the sole purpose of
|
||||
# programming logic devices manufactured by Altera and sold by
|
||||
# Altera or its authorized distributors. Please refer to the
|
||||
# applicable agreement for further details.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus II 64-Bit
|
||||
# Version 13.1.4 Build 182 03/12/2014 SJ Full Version
|
||||
# Date created = 19:54:12 November 22, 2020
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# 1) The default values for assignments are stored in the file:
|
||||
# Jackal_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_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
|
||||
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
set_location_assignment PIN_7 -to LED
|
||||
set_location_assignment PIN_54 -to CLOCK_27
|
||||
set_location_assignment PIN_144 -to VGA_R[5]
|
||||
set_location_assignment PIN_143 -to VGA_R[4]
|
||||
set_location_assignment PIN_142 -to VGA_R[3]
|
||||
set_location_assignment PIN_141 -to VGA_R[2]
|
||||
set_location_assignment PIN_137 -to VGA_R[1]
|
||||
set_location_assignment PIN_135 -to VGA_R[0]
|
||||
set_location_assignment PIN_133 -to VGA_B[5]
|
||||
set_location_assignment PIN_132 -to VGA_B[4]
|
||||
set_location_assignment PIN_125 -to VGA_B[3]
|
||||
set_location_assignment PIN_121 -to VGA_B[2]
|
||||
set_location_assignment PIN_120 -to VGA_B[1]
|
||||
set_location_assignment PIN_115 -to VGA_B[0]
|
||||
set_location_assignment PIN_114 -to VGA_G[5]
|
||||
set_location_assignment PIN_113 -to VGA_G[4]
|
||||
set_location_assignment PIN_112 -to VGA_G[3]
|
||||
set_location_assignment PIN_111 -to VGA_G[2]
|
||||
set_location_assignment PIN_110 -to VGA_G[1]
|
||||
set_location_assignment PIN_106 -to VGA_G[0]
|
||||
set_location_assignment PIN_136 -to VGA_VS
|
||||
set_location_assignment PIN_119 -to VGA_HS
|
||||
set_location_assignment PIN_65 -to AUDIO_L
|
||||
set_location_assignment PIN_80 -to AUDIO_R
|
||||
set_location_assignment PIN_105 -to SPI_DO
|
||||
set_location_assignment PIN_88 -to SPI_DI
|
||||
set_location_assignment PIN_126 -to SPI_SCK
|
||||
set_location_assignment PIN_127 -to SPI_SS2
|
||||
set_location_assignment PIN_91 -to SPI_SS3
|
||||
set_location_assignment PIN_13 -to CONF_DATA0
|
||||
set_location_assignment PIN_49 -to SDRAM_A[0]
|
||||
set_location_assignment PIN_44 -to SDRAM_A[1]
|
||||
set_location_assignment PIN_42 -to SDRAM_A[2]
|
||||
set_location_assignment PIN_39 -to SDRAM_A[3]
|
||||
set_location_assignment PIN_4 -to SDRAM_A[4]
|
||||
set_location_assignment PIN_6 -to SDRAM_A[5]
|
||||
set_location_assignment PIN_8 -to SDRAM_A[6]
|
||||
set_location_assignment PIN_10 -to SDRAM_A[7]
|
||||
set_location_assignment PIN_11 -to SDRAM_A[8]
|
||||
set_location_assignment PIN_28 -to SDRAM_A[9]
|
||||
set_location_assignment PIN_50 -to SDRAM_A[10]
|
||||
set_location_assignment PIN_30 -to SDRAM_A[11]
|
||||
set_location_assignment PIN_32 -to SDRAM_A[12]
|
||||
set_location_assignment PIN_83 -to SDRAM_DQ[0]
|
||||
set_location_assignment PIN_79 -to SDRAM_DQ[1]
|
||||
set_location_assignment PIN_77 -to SDRAM_DQ[2]
|
||||
set_location_assignment PIN_76 -to SDRAM_DQ[3]
|
||||
set_location_assignment PIN_72 -to SDRAM_DQ[4]
|
||||
set_location_assignment PIN_71 -to SDRAM_DQ[5]
|
||||
set_location_assignment PIN_69 -to SDRAM_DQ[6]
|
||||
set_location_assignment PIN_68 -to SDRAM_DQ[7]
|
||||
set_location_assignment PIN_86 -to SDRAM_DQ[8]
|
||||
set_location_assignment PIN_87 -to SDRAM_DQ[9]
|
||||
set_location_assignment PIN_98 -to SDRAM_DQ[10]
|
||||
set_location_assignment PIN_99 -to SDRAM_DQ[11]
|
||||
set_location_assignment PIN_100 -to SDRAM_DQ[12]
|
||||
set_location_assignment PIN_101 -to SDRAM_DQ[13]
|
||||
set_location_assignment PIN_103 -to SDRAM_DQ[14]
|
||||
set_location_assignment PIN_104 -to SDRAM_DQ[15]
|
||||
set_location_assignment PIN_58 -to SDRAM_BA[0]
|
||||
set_location_assignment PIN_51 -to SDRAM_BA[1]
|
||||
set_location_assignment PIN_85 -to SDRAM_DQMH
|
||||
set_location_assignment PIN_67 -to SDRAM_DQML
|
||||
set_location_assignment PIN_60 -to SDRAM_nRAS
|
||||
set_location_assignment PIN_64 -to SDRAM_nCAS
|
||||
set_location_assignment PIN_66 -to SDRAM_nWE
|
||||
set_location_assignment PIN_59 -to SDRAM_nCS
|
||||
set_location_assignment PIN_33 -to SDRAM_CKE
|
||||
set_location_assignment PIN_43 -to SDRAM_CLK
|
||||
set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component"
|
||||
|
||||
# Classic Timing Assignments
|
||||
# ==========================
|
||||
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
|
||||
# Analysis & Synthesis Assignments
|
||||
# ================================
|
||||
set_global_assignment -name FAMILY "Cyclone III"
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY Jackal_MiST
|
||||
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
|
||||
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
|
||||
set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP
|
||||
|
||||
# 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 CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
|
||||
# Assembler Assignments
|
||||
# =====================
|
||||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
|
||||
# SignalTap II Assignments
|
||||
# ========================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/jackal.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
|
||||
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
|
||||
|
||||
# Advanced I/O Timing Assignments
|
||||
# ===============================
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
|
||||
|
||||
# ------------------------------
|
||||
# start ENTITY(Jackal_MiST)
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
|
||||
# start DESIGN_PARTITION(Top)
|
||||
# ---------------------------
|
||||
|
||||
# Incremental Compilation Assignments
|
||||
# ===================================
|
||||
|
||||
# end DESIGN_PARTITION(Top)
|
||||
# -------------------------
|
||||
|
||||
# end ENTITY(Jackal_MiST)
|
||||
# ----------------------------
|
||||
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
|
||||
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
|
||||
set_global_assignment -name SMART_RECOMPILE ON
|
||||
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 ALLOW_POWER_UP_DONT_CARE ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
|
||||
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED
|
||||
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
|
||||
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
|
||||
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jackal_MiST.sv
|
||||
set_global_assignment -name QIP_FILE rtl/pll.qip
|
||||
set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jackal.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/hiscore.v
|
||||
set_global_assignment -name VHDL_FILE rtl/spram.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd
|
||||
set_global_assignment -name QIP_FILE rtl/custom/jackal_custom.qip
|
||||
set_global_assignment -name QIP_FILE rtl/sound/jackal_sound.qip
|
||||
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
|
||||
set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v
|
||||
set_global_assignment -name QIP_FILE ../../common/Sound/jt51/jt51.qip
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/jackal.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
134
Arcade_MiST/Konami Jackal/Jackal.sdc
Normal file
134
Arcade_MiST/Konami Jackal/Jackal.sdc
Normal file
@@ -0,0 +1,134 @@
|
||||
## Generated SDC file "vectrex_MiST.out.sdc"
|
||||
|
||||
## Copyright (C) 1991-2013 Altera Corporation
|
||||
## Your use of Altera Corporation's design tools, logic functions
|
||||
## and other software and tools, and its AMPP partner logic
|
||||
## functions, and any output files from any of the foregoing
|
||||
## (including device programming or simulation files), and any
|
||||
## associated documentation or information are expressly subject
|
||||
## to the terms and conditions of the Altera Program License
|
||||
## Subscription Agreement, Altera MegaCore Function License
|
||||
## Agreement, or other applicable license agreement, including,
|
||||
## without limitation, that your use is for the sole purpose of
|
||||
## programming logic devices manufactured by Altera and sold by
|
||||
## Altera or its authorized distributors. Please refer to the
|
||||
## applicable agreement for further details.
|
||||
|
||||
|
||||
## VENDOR "Altera"
|
||||
## PROGRAM "Quartus II"
|
||||
## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition"
|
||||
|
||||
## DATE "Sun Jun 24 12:53:00 2018"
|
||||
|
||||
##
|
||||
## DEVICE "EP3C25E144C8"
|
||||
##
|
||||
|
||||
# Clock constraints
|
||||
|
||||
# Automatically constrain PLL and other generated clocks
|
||||
derive_pll_clocks -create_base_clocks
|
||||
|
||||
# Automatically calculate clock uncertainty to jitter and other effects.
|
||||
derive_clock_uncertainty
|
||||
|
||||
# tsu/th constraints
|
||||
|
||||
# tco constraints
|
||||
|
||||
# tpd constraints
|
||||
|
||||
#**************************************************************
|
||||
# Time Information
|
||||
#**************************************************************
|
||||
|
||||
set_time_format -unit ns -decimal_places 3
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Create Clock
|
||||
#**************************************************************
|
||||
|
||||
create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}]
|
||||
|
||||
set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]"
|
||||
set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]"
|
||||
#**************************************************************
|
||||
# Create Generated Clock
|
||||
#**************************************************************
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Latency
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Uncertainty
|
||||
#**************************************************************
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Delay
|
||||
#**************************************************************
|
||||
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}]
|
||||
|
||||
set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]]
|
||||
set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]]
|
||||
|
||||
#**************************************************************
|
||||
# Set Output Delay
|
||||
#**************************************************************
|
||||
|
||||
set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}]
|
||||
|
||||
set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Groups
|
||||
#**************************************************************
|
||||
|
||||
set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}]
|
||||
|
||||
#**************************************************************
|
||||
# Set False Path
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Multicycle Path
|
||||
#**************************************************************
|
||||
|
||||
set_multicycle_path -to {VGA_*[*]} -setup 2
|
||||
set_multicycle_path -to {VGA_*[*]} -hold 1
|
||||
|
||||
#**************************************************************
|
||||
# Set Maximum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Minimum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Transition
|
||||
#**************************************************************
|
||||
|
||||
11
Arcade_MiST/Konami Jackal/README.md
Normal file
11
Arcade_MiST/Konami Jackal/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# MiST port of Konami Jackal by ACE
|
||||
|
||||
https://github.com/MiSTer-devel/Arcade-Jackal_MiSTer
|
||||
|
||||
## Usage
|
||||
|
||||
- Create ROM and ARC files from the MRA files using the MRA utility.
|
||||
Example: mra -A -z /path/to/mame/roms "Jackal.mra"
|
||||
- Copy the ROM files to the root of the SD Card
|
||||
- Copy the RBF and ARC files to the same folder on the SD Card
|
||||
- MRA utility: https://github.com/sebdel/mra-tools-c/
|
||||
75
Arcade_MiST/Konami Jackal/meta/Jackal (W) [bl].mra
Normal file
75
Arcade_MiST/Konami Jackal/meta/Jackal (W) [bl].mra
Normal file
@@ -0,0 +1,75 @@
|
||||
<misterromdescription>
|
||||
<name>Jackal (bootleg)</name>
|
||||
<region>World</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>yes</bootleg>
|
||||
<version></version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>jackalbl</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,Start,Select,X" names="Machine Gun,Grenades/Rockets,-,-,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>01</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip|jackalbl.zip'>
|
||||
<part crc="5fffee27" name="jackalbl/epr-a-3.bin"/>
|
||||
<part crc="976c8431" name="jackalbl/epr-a-4.bin"/>
|
||||
<part crc="ae2a290a" name="jackalbl/epr-a-2.bin"/>
|
||||
<part crc="ae2a290a" name="jackalbl/epr-a-2.bin"/>
|
||||
<part crc="54aa2d29" name="jackalbl/epr-a-1.bin"/>
|
||||
<part crc="457f42f0" name="631t04.7h"/>
|
||||
<part crc="732b3fc1" name="631t05.8h"/>
|
||||
<part crc="2d10e56e" name="631t06.12h"/>
|
||||
<part crc="4961c397" name="631t07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
0E 00 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
74
Arcade_MiST/Konami Jackal/meta/Jackal (W).mra
Normal file
74
Arcade_MiST/Konami Jackal/meta/Jackal (W).mra
Normal file
@@ -0,0 +1,74 @@
|
||||
<misterromdescription>
|
||||
<name>Jackal</name>
|
||||
<region>World</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>no</bootleg>
|
||||
<version>8-Way Joystick</version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>jackal</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,Start,Select,X" names="Machine Gun,Grenades/Rockets,-,-,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>00</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip'>
|
||||
<part crc="0b7e0584" name="631_v02.15d"/>
|
||||
<part crc="3e0dfb83" name="631_v03.16d"/>
|
||||
<part crc="3e0dfb83" name="631_v03.16d"/>
|
||||
<part crc="b189af6a" name="631_t01.11d"/>
|
||||
<part crc="457f42f0" name="631t04.7h"/>
|
||||
<part crc="732b3fc1" name="631t05.8h"/>
|
||||
<part crc="2d10e56e" name="631t06.12h"/>
|
||||
<part crc="4961c397" name="631t07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
11 90 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
74
Arcade_MiST/Konami Jackal/meta/Jackal (W, Rotary).mra
Normal file
74
Arcade_MiST/Konami Jackal/meta/Jackal (W, Rotary).mra
Normal file
@@ -0,0 +1,74 @@
|
||||
<misterromdescription>
|
||||
<name>Jackal (Rotary Joystick)</name>
|
||||
<region>World</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>no</bootleg>
|
||||
<version>Rotary Joystick</version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>jackalr</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls>Rotary</special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,L,R,Start,Select,X" names="Machine Gun,Grenades/Rockets,Rotary Left,Rotary Right,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>10</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip|jackalr.zip'>
|
||||
<part crc="ed2a7d66" name="631_q02.15d"/>
|
||||
<part crc="b9d34836" name="631_q03.16d"/>
|
||||
<part crc="b9d34836" name="631_q03.16d"/>
|
||||
<part crc="54aa2d29" name="631_q01.11d"/>
|
||||
<part crc="457f42f0" name="631t04.7h"/>
|
||||
<part crc="732b3fc1" name="631t05.8h"/>
|
||||
<part crc="2d10e56e" name="631t06.12h"/>
|
||||
<part crc="4961c397" name="631t07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
11 90 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
74
Arcade_MiST/Konami Jackal/meta/Tokushu Butai Jackal (JP).mra
Normal file
74
Arcade_MiST/Konami Jackal/meta/Tokushu Butai Jackal (JP).mra
Normal file
@@ -0,0 +1,74 @@
|
||||
<misterromdescription>
|
||||
<name>Tokushu Butai Jackal</name>
|
||||
<region>Japan</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>no</bootleg>
|
||||
<version></version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>jackalj</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,Start,Select,X" names="Machine Gun,Grenades/Rockets,-,-,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>00</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip|jackalj.zip'>
|
||||
<part crc="14db6b1a" name="jackalj/631_t02.15d"/>
|
||||
<part crc="fd5f9624" name="jackalj/631_t03.16d"/>
|
||||
<part crc="fd5f9624" name="jackalj/631_t03.16d"/>
|
||||
<part crc="b189af6a" name="631_t01.11d"/>
|
||||
<part crc="457f42f0" name="631t04.7h"/>
|
||||
<part crc="732b3fc1" name="631t05.8h"/>
|
||||
<part crc="2d10e56e" name="631t06.12h"/>
|
||||
<part crc="4961c397" name="631t07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
11 90 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
75
Arcade_MiST/Konami Jackal/meta/Top Gunner (US) [bl].mra
Normal file
75
Arcade_MiST/Konami Jackal/meta/Top Gunner (US) [bl].mra
Normal file
@@ -0,0 +1,75 @@
|
||||
<misterromdescription>
|
||||
<name>Top Gunner (bootleg)</name>
|
||||
<region>US</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>yes</bootleg>
|
||||
<version></version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>topgunbl</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,Start,Select,X" names="Machine Gun,Grenades/Rockets,-,-,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>01</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip|topgunbl.zip'>
|
||||
<part crc="7826ad38" name="topgunbl/t-3.c5"/>
|
||||
<part crc="976c8431" name="topgunbl/t-4.c4"/>
|
||||
<part crc="d53172e5" name="topgunbl/t-2.c6"/>
|
||||
<part crc="d53172e5" name="topgunbl/t-2.c6"/>
|
||||
<part crc="54aa2d29" name="topgunbl/t-1.c14"/>
|
||||
<part crc="50122a12" name="topgunr/631u04.7h"/>
|
||||
<part crc="6943b1a4" name="topgunr/631u05.8h"/>
|
||||
<part crc="37dbbdb0" name="topgunr/631u06.12h"/>
|
||||
<part crc="22effcc8" name="topgunr/631u07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
0E 00 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
74
Arcade_MiST/Konami Jackal/meta/Top Gunner (US).mra
Normal file
74
Arcade_MiST/Konami Jackal/meta/Top Gunner (US).mra
Normal file
@@ -0,0 +1,74 @@
|
||||
<misterromdescription>
|
||||
<name>Top Gunner</name>
|
||||
<region>US</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>no</bootleg>
|
||||
<version></version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Shooter - Multidirectional</category>
|
||||
|
||||
<setname>topgunr</setname>
|
||||
<parent>jackal</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>Jackal</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>vertical (cw)</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (simultaneous)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>2</num_buttons>
|
||||
<buttons default="B,A,Start,Select,X" names="Machine Gun,Grenades/Rockets,-,-,Start,Coin,Pause"></buttons>
|
||||
|
||||
<switches default="00,21,04" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/150K+,50K/200K+,30K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Cabinet Type" ids="Upright,Cocktail"/>
|
||||
<dip bits="18" name="Sound mode" ids="Mono,Stereo"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>00</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='jackal.zip|topgunr.zip'>
|
||||
<part crc="f7e28426" name="topgunr/631_u02.15d"/>
|
||||
<part crc="c086844e" name="topgunr/631_u03.16d"/>
|
||||
<part crc="c086844e" name="topgunr/631_u03.16d"/>
|
||||
<part crc="b189af6a" name="631_t01.11d"/>
|
||||
<part crc="50122a12" name="topgunr/631u04.7h"/>
|
||||
<part crc="6943b1a4" name="topgunr/631u05.8h"/>
|
||||
<part crc="37dbbdb0" name="topgunr/631u06.12h"/>
|
||||
<part crc="22effcc8" name="topgunr/631u07.13h"/>
|
||||
<part crc="7553a172" name="631r08.9h"/>
|
||||
<part crc="a74dd86c" name="631r09.14h"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
11 90 00 00 00 FF 00 02
|
||||
00 02 00 01 00 FF 00 00
|
||||
00 00 72 F8 00 27 00 1D
|
||||
00 00 73 40 00 03 00 00
|
||||
00 00 73 41 00 01 02 02
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4"></rom>
|
||||
|
||||
<nvram index="4" size="43"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210708094853</mratimestamp>
|
||||
</misterromdescription>
|
||||
566
Arcade_MiST/Konami Jackal/rtl/Jackal.sv
Normal file
566
Arcade_MiST/Konami Jackal/rtl/Jackal.sv
Normal file
@@ -0,0 +1,566 @@
|
||||
//============================================================================
|
||||
//
|
||||
// Jackal PCB model
|
||||
// Copyright (C) 2020, 2021 Ace, brknglass, Ash Evans (aka ElectronAsh/OzOnE),
|
||||
// Shane Lynch, JimmyStones and Kitrinx (aka Rysha)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//Module declaration, I/O ports
|
||||
module Jackal
|
||||
(
|
||||
input reset,
|
||||
input clk_49m, //Actual frequency: 49.152MHz
|
||||
input [1:0] coins,
|
||||
input btn_service,
|
||||
input [1:0] btn_start, //1 = Player 2, 0 = Player 1
|
||||
input [3:0] p1_joystick, p2_joystick, //3 = down, 2 = up, 1 = right, 0 = left
|
||||
input [7:0] p1_rotary, p2_rotary,
|
||||
input [1:0] p1_buttons, p2_buttons, //2 buttons per player
|
||||
|
||||
input [19:0] dipsw,
|
||||
|
||||
//The following flag is used to reconfigure the 005885s' video timings, logic for drawing sprites and audio
|
||||
//filtering to reproduce the errors found on bootleg Jackal PCBs (this is a 2-bit signal to reconfigure the
|
||||
//005885s depending on which game's bootleg ROM sets are loaded)
|
||||
input [1:0] is_bootleg,
|
||||
|
||||
//Screen centering (alters HSync and VSync timing in the primary Konami 005885 to reposition the video output)
|
||||
input [3:0] h_center, v_center,
|
||||
|
||||
output signed [15:0] sound_l, sound_r,
|
||||
output video_hsync, video_vsync,
|
||||
output video_csync, //CSync not needed for MiSTer
|
||||
output video_vblank, video_hblank,
|
||||
output [4:0] video_r, video_g, video_b,
|
||||
|
||||
input ioctl_clk,
|
||||
input [24:0] ioctl_addr,
|
||||
input [7:0] ioctl_data,
|
||||
input ioctl_wr,
|
||||
|
||||
input pause,
|
||||
|
||||
input [12:0] hs_address,
|
||||
input [7:0] hs_data_in,
|
||||
output [7:0] hs_data_out,
|
||||
input hs_write,
|
||||
input hs_access,
|
||||
|
||||
//SDRAM signals
|
||||
output reg [16:0] main_cpu_rom_addr,
|
||||
input [7:0] main_cpu_rom_do,
|
||||
output reg [14:0] sub_cpu_rom_addr,
|
||||
input [7:0] sub_cpu_rom_do,
|
||||
output reg [16:1] char1_rom_addr,
|
||||
input [15:0] char1_rom_do,
|
||||
output reg [16:1] char2_rom_addr,
|
||||
input [15:0] char2_rom_do,
|
||||
output sp1_req,
|
||||
input sp1_ack,
|
||||
output [16:1] sp1_rom_addr,
|
||||
input [15:0] sp1_rom_do,
|
||||
output sp2_req,
|
||||
input sp2_ack,
|
||||
output [16:1] sp2_rom_addr,
|
||||
input [15:0] sp2_rom_do
|
||||
);
|
||||
|
||||
//------------------------------------------------------- Clock division -------------------------------------------------------//
|
||||
|
||||
//Generate 6.144MHz and 3.072MHz clock enables (clock division is normally handled inside the primary Konami 005885)
|
||||
reg [3:0] div = 4'd0;
|
||||
always_ff @(posedge clk_49m) begin
|
||||
div <= div + 4'd1;
|
||||
end
|
||||
|
||||
wire cen_6m = !div[2:0];
|
||||
wire n_cen_6m = div[2:0] == 3'b100;
|
||||
wire cen_3m = !div;
|
||||
|
||||
//Phase generator for MC6809E (taken from MiSTer Vectrex core)
|
||||
//Normally handled internally on the primary Konami 005885
|
||||
reg mE = 0;
|
||||
reg mQ = 0;
|
||||
reg sE = 0;
|
||||
reg sQ = 0;
|
||||
always_ff @(posedge clk_49m) begin
|
||||
reg [1:0] clk_phase = 0;
|
||||
mE <= 0;
|
||||
mQ <= 0;
|
||||
sE <= 0;
|
||||
sQ <= 0;
|
||||
if(cen_6m) begin
|
||||
clk_phase <= clk_phase + 1'd1;
|
||||
case(clk_phase)
|
||||
2'b00: sE <= 1;
|
||||
2'b01: mE <= 1;
|
||||
2'b10: sQ <= 1;
|
||||
2'b11: mQ <= 1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//Fractional divider to obtain sound clock (implementation by Jotego as part of JTFRAME)
|
||||
//The PCB uses a 3.579545MHz oscillator directly connected to its YM2151 - this fractional divider replaces it as 3.579545MHz is
|
||||
//not divisible by any integer factor of the main clock
|
||||
//Also use this divider to generate a clock enable for jt49_dcrm2 to high-pass filter the YM2151's sound for original Jackal ROM
|
||||
//sets
|
||||
wire cen_3m58, cen_1m79;
|
||||
wire cen_dcrm;
|
||||
jtframe_frac_cen #(4) jt51_cen
|
||||
(
|
||||
.clk(clk_49m),
|
||||
.n(10'd60),
|
||||
.m(10'd824),
|
||||
.cen({cen_dcrm, 1'bZ, cen_1m79, cen_3m58})
|
||||
);
|
||||
|
||||
//------------------------------------------------------------ CPUs ------------------------------------------------------------//
|
||||
|
||||
//Main CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig)
|
||||
wire maincpu_rw;
|
||||
wire [15:0] maincpu_A;
|
||||
wire [7:0] maincpu_Din, maincpu_Dout;
|
||||
|
||||
mc6809is u16A
|
||||
(
|
||||
.CLK(clk_49m),
|
||||
.fallE_en(mE),
|
||||
.fallQ_en(mQ),
|
||||
.D(maincpu_Din),
|
||||
.DOut(maincpu_Dout),
|
||||
.ADDR(maincpu_A),
|
||||
.RnW(maincpu_rw),
|
||||
.nIRQ(irq),
|
||||
.nFIRQ(1),
|
||||
.nNMI(1),
|
||||
.nHALT(pause),
|
||||
.nRESET(reset),
|
||||
.nDMABREQ(1)
|
||||
);
|
||||
//Address decoding for data inputs to Main CPU
|
||||
wire cs_controls_dip1_dip3 = ~n_iocs & (maincpu_A[3:2] == 2'b00) & maincpu_rw;
|
||||
wire cs_rotary = ~n_iocs & (maincpu_A[3:2] == 2'b01) & maincpu_rw;
|
||||
wire cs_dip2 = ~n_iocs & (maincpu_A[3:2] == 2'b10) & maincpu_rw;
|
||||
wire cs_bankswitch = ~n_iocs & (maincpu_A[3:2] == 2'b11) & ~maincpu_rw;
|
||||
wire cs_mainsharedram = (maincpu_A >= 16'h0060 & maincpu_A <= 16'h1FFF);
|
||||
wire cs_eprom1 = (maincpu_A[15:14] == 2'b01 | maincpu_A[15:14] == 2'b10) & maincpu_rw;
|
||||
wire cs_eprom2 = (maincpu_A[15:14] == 2'b11 & maincpu_rw);
|
||||
//Some of Jackal's address decoding logic is implemented in a PAL chip marked by Konami as the 007343 - instantiate an
|
||||
//implementation of this IC here
|
||||
wire n_cs_main_k005885, n_cs_sec_k005885, n_iocs;
|
||||
k007343 u12D
|
||||
(
|
||||
.A4(maincpu_A[4]),
|
||||
.A5(maincpu_A[5]),
|
||||
.A6(maincpu_A[6]),
|
||||
.A7(maincpu_A[7]),
|
||||
.A8_9(maincpu_A[8] | maincpu_A[9]),
|
||||
.A10(maincpu_A[10]),
|
||||
.A11(maincpu_A[11]),
|
||||
.A12(maincpu_A[12]),
|
||||
.A13(maincpu_A[13]),
|
||||
.WR(maincpu_rw),
|
||||
.OBJB(vram_bank),
|
||||
.GATEB(zram_bank),
|
||||
.GATECS(maincpu_A[15:14] != 2'b00),
|
||||
.MGCS(n_cs_main_k005885),
|
||||
.SGCS(n_cs_sec_k005885),
|
||||
.IOCS(n_iocs)
|
||||
//.CRCS
|
||||
);
|
||||
//Multiplex data inputs to main CPU
|
||||
assign maincpu_Din = (~n_cs_main_k005885 & maincpu_rw) ? main_k005885_Dout:
|
||||
(~n_cs_sec_k005885 & maincpu_rw) ? sec_k005885_Dout:
|
||||
cs_controls_dip1_dip3 ? controls_dip1_dip3:
|
||||
cs_rotary ? rotary:
|
||||
cs_dip2 ? dipsw[15:8]:
|
||||
(cs_mainsharedram & maincpu_rw) ? m_sharedram_D:
|
||||
cs_eprom1 ? eprom1_D:
|
||||
cs_eprom2 ? eprom2_D:
|
||||
8'hFF;
|
||||
|
||||
//Primary game ROM
|
||||
always @(posedge clk_49m)
|
||||
if (|maincpu_A[15:14] & maincpu_rw)
|
||||
main_cpu_rom_addr <= {maincpu_A[15:14] == 2'b11, maincpu_A[15:14] != 2'b11 & eprom1_bank, ~maincpu_A[14], maincpu_A[13:0]};
|
||||
|
||||
wire [7:0] eprom1_D = main_cpu_rom_do;
|
||||
//Secondary game ROM
|
||||
wire [7:0] eprom2_D = main_cpu_rom_do;
|
||||
|
||||
//Bankswitching for primary game ROM, ZRAM + VRAM and sprite RAM
|
||||
reg eprom1_bank = 0;
|
||||
reg zram_bank = 0;
|
||||
reg vram_bank = 0;
|
||||
always_ff @(posedge clk_49m) begin
|
||||
if(!reset) begin
|
||||
eprom1_bank <= 0;
|
||||
zram_bank <= 0;
|
||||
vram_bank <= 0;
|
||||
end
|
||||
else if(cen_3m) begin
|
||||
if(cs_bankswitch) begin
|
||||
eprom1_bank <= maincpu_Dout[5];
|
||||
zram_bank <= maincpu_Dout[4];
|
||||
vram_bank <= maincpu_Dout[3];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Hiscore mux
|
||||
wire [12:0] u14B_addr = hs_access ? hs_address[12:0] : maincpu_A[12:0];
|
||||
wire [7:0] u14B_din = hs_access ? hs_data_in : maincpu_Dout;
|
||||
wire u14B_wren = hs_access ? hs_write : (cs_mainsharedram & ~maincpu_rw);
|
||||
wire [7:0] u14B_dout;
|
||||
assign m_sharedram_D = hs_access ? 8'h00 : u14B_dout;
|
||||
assign hs_data_out = hs_access ? u14B_dout : 8'h00;
|
||||
|
||||
//Shared RAM
|
||||
wire [7:0] m_sharedram_D, s_sharedram_D;
|
||||
dpram_dc #(.widthad_a(13)) u14B
|
||||
(
|
||||
.clock_a(clk_49m),
|
||||
.address_a(u14B_addr),
|
||||
.data_a(u14B_din),
|
||||
.q_a(u14B_dout),
|
||||
.wren_a(u14B_wren),
|
||||
|
||||
.clock_b(clk_49m),
|
||||
.address_b(soundcpu_A[12:0]),
|
||||
.data_b(soundcpu_Dout),
|
||||
.q_b(s_sharedram_D),
|
||||
.wren_b(cs_soundsharedram & ~soundcpu_rw)
|
||||
);
|
||||
|
||||
//Secondary CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig)
|
||||
wire soundcpu_rw;
|
||||
wire [15:0] soundcpu_A;
|
||||
wire [7:0] soundcpu_Din, soundcpu_Dout;
|
||||
|
||||
mc6809is u11A
|
||||
(
|
||||
.CLK(clk_49m),
|
||||
.fallE_en(sE),
|
||||
.fallQ_en(sQ),
|
||||
.D(soundcpu_Din),
|
||||
.DOut(soundcpu_Dout),
|
||||
.ADDR(soundcpu_A),
|
||||
.RnW(soundcpu_rw),
|
||||
.nIRQ(1),
|
||||
.nFIRQ(1),
|
||||
.nNMI(irq),
|
||||
.nHALT(1),
|
||||
.nRESET(reset),
|
||||
.nDMABREQ(1)
|
||||
);
|
||||
//Address decoding for data inputs to sound CPU
|
||||
wire cs_ym2151 = (soundcpu_A[15:13] == 3'b001);
|
||||
wire cs_k007327 = (soundcpu_A[15:13] == 3'b010);
|
||||
wire cs_soundsharedram = (soundcpu_A[15:13] == 3'b011);
|
||||
wire cs_eprom3 = (soundcpu_A[15] & soundcpu_rw);
|
||||
//Multiplex data inputs to sound CPU
|
||||
assign soundcpu_Din = (cs_ym2151 & soundcpu_rw) ? ym2151_Dout:
|
||||
(cs_k007327 & soundcpu_rw) ? k007327_D:
|
||||
(cs_soundsharedram & soundcpu_rw) ? s_sharedram_D:
|
||||
cs_eprom3 ? eprom3_D:
|
||||
8'hFF;
|
||||
|
||||
//Sound ROM
|
||||
always @(posedge clk_49m)
|
||||
if (cs_eprom3) sub_cpu_rom_addr <= soundcpu_A[14:0];
|
||||
|
||||
wire [7:0] eprom3_D = sub_cpu_rom_do;
|
||||
//--------------------------------------------------- Controls & DIP switches --------------------------------------------------//
|
||||
|
||||
//Multiplex player inputs with DIP switch banks 1 and 3
|
||||
wire [7:0] controls_dip1_dip3 = maincpu_A[1:0] == 2'b00 ? dipsw[7:0]:
|
||||
maincpu_A[1:0] == 2'b01 ? {dipsw[19], 1'b1, p1_buttons, p1_joystick}:
|
||||
maincpu_A[1:0] == 2'b10 ? {2'b1, p2_buttons, p2_joystick}:
|
||||
maincpu_A[1:0] == 2'b11 ? {dipsw[18:16], btn_start[1:0], btn_service, coins}:
|
||||
8'hFF;
|
||||
|
||||
//Multiplex rotary controls for supported ROM sets
|
||||
wire [7:0] rotary = maincpu_A[1:0] == 2'b00 ? p1_rotary:
|
||||
maincpu_A[1:0] == 2'b01 ? p2_rotary:
|
||||
8'hFF;
|
||||
|
||||
//--------------------------------------------------- Video timing & graphics --------------------------------------------------//
|
||||
|
||||
//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Jackal's critical
|
||||
//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites
|
||||
//Jackal contains two of these in parallel - this instance is the primary tilemap generator
|
||||
wire [15:0] gfxrom0_Atile, gfxrom0_Asprite;
|
||||
wire [7:0] main_k005885_Dout;
|
||||
wire [4:0] main_color;
|
||||
wire [3:0] main_tile_data; //Jackal does not use a lookup table for tiles; tile data is fed back to the 005885 directly
|
||||
wire [3:0] ocf0, ocb0;
|
||||
wire tile_attrib_D4, tile_attrib_D5;
|
||||
wire e, q, irq;
|
||||
k005885 u11F
|
||||
(
|
||||
.CK49(clk_49m),
|
||||
.NRD(~maincpu_rw),
|
||||
.A(maincpu_A[13:0]),
|
||||
.DBi(maincpu_Dout),
|
||||
.DBo(main_k005885_Dout),
|
||||
.R(gfxrom0_Atile),
|
||||
.RDU(gfxrom0_Dtile[15:8]),
|
||||
.RDL(gfxrom0_Dtile[7:0]),
|
||||
.S(gfxrom0_Asprite),
|
||||
.S_req(sp1_req),
|
||||
.S_ack(sp1_ack),
|
||||
.SDU(gfxrom0_Dsprite[15:8]),
|
||||
.SDL(gfxrom0_Dsprite[7:0]),
|
||||
.VCB(main_tile_data),
|
||||
.VCD(main_tile_data),
|
||||
.OCF(ocf0),
|
||||
.OCB(ocb0),
|
||||
.OCD(prom1_D),
|
||||
.COL(main_color),
|
||||
.NEXR(reset),
|
||||
.NXCS(n_cs_main_k005885),
|
||||
.NCSY(video_csync),
|
||||
.NHSY(video_hsync),
|
||||
.NVSY(video_vsync),
|
||||
.HBLK(video_hblank),
|
||||
.VBLK(video_vblank),
|
||||
.NCPE(e),
|
||||
.NCPQ(q),
|
||||
.NIRQ(irq),
|
||||
.ATR4(tile_attrib_D4),
|
||||
.ATR5(tile_attrib_D5),
|
||||
.HCTR(h_center),
|
||||
.VCTR(v_center),
|
||||
.BTLG(is_bootleg)
|
||||
);
|
||||
|
||||
//Graphics ROMs for primary 005885 tilemap generator (sprites only)
|
||||
assign sp1_rom_addr = gfxrom0_Asprite[15:0];
|
||||
wire [15:0] gfxrom0_Dsprite = sp1_rom_do;
|
||||
//Sprite LUT PROM for primary 005885 tilemap generator
|
||||
wire [3:0] prom1_D;
|
||||
wire prom1_cs_i = ioctl_addr[24:8] == 16'h0A00;
|
||||
dpram_dc #(.widthad_a(8)) u9H
|
||||
(
|
||||
.clock_a(clk_49m),
|
||||
.address_a({ocf0, ocb0}),
|
||||
.q_a(prom1_D),
|
||||
|
||||
.clock_b(ioctl_clk),
|
||||
.address_b(ioctl_addr[7:0]),
|
||||
.data_b(ioctl_data),
|
||||
.wren_b(prom1_cs_i & ioctl_wr)
|
||||
);
|
||||
|
||||
//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Jackal's critical
|
||||
//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites
|
||||
//Jackal contains two of these in parallel - this instance is the secondary tilemap generator
|
||||
wire [15:0] gfxrom1_Atile, gfxrom1_Asprite;
|
||||
wire [7:0] sec_k005885_Dout;
|
||||
wire [4:0] sec_color;
|
||||
wire [3:0] sec_tile_data; //Jackal does not use a lookup table for tiles; tile data is fed back to the 005885 directly
|
||||
wire [3:0] ocf1, ocb1;
|
||||
k005885 u14F
|
||||
(
|
||||
.CK49(clk_49m),
|
||||
.NRD(~maincpu_rw),
|
||||
.A(maincpu_A[13:0]),
|
||||
.DBi(maincpu_Dout),
|
||||
.DBo(sec_k005885_Dout),
|
||||
.R(gfxrom1_Atile),
|
||||
.RDU(gfxrom1_Dtile[15:8]),
|
||||
.RDL(gfxrom1_Dtile[7:0]),
|
||||
.S(gfxrom1_Asprite),
|
||||
.S_req(sp2_req),
|
||||
.S_ack(sp2_ack),
|
||||
.SDU(gfxrom1_Dsprite[15:8]),
|
||||
.SDL(gfxrom1_Dsprite[7:0]),
|
||||
.VCB(sec_tile_data),
|
||||
.VCD(sec_tile_data),
|
||||
.OCF(ocf1),
|
||||
.OCB(ocb1),
|
||||
.OCD(prom2_D),
|
||||
.COL(sec_color),
|
||||
.NEXR(reset),
|
||||
.NXCS(n_cs_sec_k005885),
|
||||
.BTLG(is_bootleg)
|
||||
);
|
||||
|
||||
//Graphics ROMs for secondary 005885 tilemap generator (sprites only)
|
||||
assign sp2_rom_addr = gfxrom1_Asprite[15:0];
|
||||
wire [15:0] gfxrom1_Dsprite = sp2_rom_do;
|
||||
|
||||
//Graphics ROMs (tilemaps only) for both 005885 tilemap generators (accessed externally from SDRAM)
|
||||
wire [15:0] gfxrom0_Dtile, gfxrom1_Dtile;
|
||||
|
||||
always_ff @(posedge clk_49m) begin
|
||||
char1_rom_addr <= {tile_attrib_D5, tile_attrib_D4, gfxrom0_Atile[13:0]};
|
||||
char2_rom_addr <= {tile_attrib_D5, tile_attrib_D4, gfxrom1_Atile[13:0]};
|
||||
end
|
||||
|
||||
assign gfxrom0_Dtile = char1_rom_do;
|
||||
assign gfxrom1_Dtile = char2_rom_do;
|
||||
|
||||
//Sprite LUT PROM for secondary 005885 tilemap generator
|
||||
wire [3:0] prom2_D;
|
||||
wire prom2_cs_i = ioctl_addr[24:8] == 16'h0A01;
|
||||
dpram_dc #(.widthad_a(8)) u14H
|
||||
(
|
||||
.clock_a(clk_49m),
|
||||
.address_a({ocf1, ocb1}),
|
||||
.q_a(prom2_D),
|
||||
|
||||
.clock_b(ioctl_clk),
|
||||
.address_b(ioctl_addr[7:0]),
|
||||
.data_b(ioctl_data),
|
||||
.wren_b(prom2_cs_i & ioctl_wr)
|
||||
);
|
||||
|
||||
//--------------------------------------------------------- Sound chip ---------------------------------------------------------//
|
||||
|
||||
//Sound chip - Yamaha YM2151 (uses JT51 implementation by Jotego)
|
||||
wire [7:0] ym2151_Dout;
|
||||
wire signed [15:0] sound_l_raw, sound_r_raw;
|
||||
wire [15:0] unsgined_sound_l_raw, unsgined_sound_r_raw;
|
||||
jt51 u8C
|
||||
(
|
||||
.rst(~reset),
|
||||
.clk(clk_49m),
|
||||
.cen(cen_3m58),
|
||||
.cen_p1(cen_1m79),
|
||||
.cs_n(~cs_ym2151),
|
||||
.wr_n(soundcpu_rw),
|
||||
.a0(soundcpu_A[0]),
|
||||
.din(soundcpu_Dout),
|
||||
.dout(ym2151_Dout),
|
||||
.xleft(sound_l_raw),
|
||||
.xright(sound_r_raw),
|
||||
.dacleft(unsgined_sound_l_raw),
|
||||
.dacright(unsgined_sound_r_raw)
|
||||
);
|
||||
|
||||
//----------------------------------------------------- Final video output -----------------------------------------------------//
|
||||
|
||||
//Multiplex color data from tilemap generators for color RAM
|
||||
wire color_sel = (main_color[4] & sec_color[4]);
|
||||
wire [3:0] color_mux = main_color[4] ? sec_color[3:0] : main_color[3:0];
|
||||
wire [7:0] color_bus = color_sel ? {main_color[3:0], sec_color[3:0]} : {3'b000, main_color[4], color_mux};
|
||||
|
||||
//Write enable logic for palette RAM
|
||||
reg n_sQ_lat = 1;
|
||||
wire n_sQlat_clr = (e & ~soundcpu_rw);
|
||||
always_ff @(posedge clk_49m or negedge n_sQlat_clr) begin
|
||||
if(!n_sQlat_clr)
|
||||
n_sQ_lat <= 1;
|
||||
else if(cen_6m)
|
||||
n_sQ_lat <= ~q;
|
||||
end
|
||||
wire n_k007327_we = (~cs_k007327 | n_sQ_lat);
|
||||
|
||||
//Multiplex the upper 4 address lines of palette RAM
|
||||
wire [11:8] ra = cs_k007327 ? soundcpu_A[11:8] : {2'b00, color_sel, color_bus[7]};
|
||||
|
||||
//Blank input to palette RAM (black out the signal when all but the uppermost bit of each 005885's color outputs
|
||||
//are all set to 0)
|
||||
//This signal does not exist on bootleg Jackal PCBs
|
||||
wire blank = (is_bootleg == 2'b01) ? 1'b1 : ((|main_color[3:0]) | (|sec_color[3:0]));
|
||||
|
||||
//Konami 007327 custom module - integrates palette RAM along with its multiplexing and write enable logic (multiplexing
|
||||
//logic only covers bits [7:0], the others are generated externally)
|
||||
//This module normally is analog-only as it also integrates the video DAC - for this FPGA implementation of Jackal,
|
||||
//the digital video data can be tapped directly
|
||||
wire [7:0] k007327_D;
|
||||
k007327 u1H
|
||||
(
|
||||
.CLK(clk_49m),
|
||||
.CEN(n_cen_6m),
|
||||
.RA(ra),
|
||||
.A(soundcpu_A[7:0]),
|
||||
.NA0(~soundcpu_A[0]),
|
||||
.CB(color_bus[6:0]),
|
||||
.Di(soundcpu_Dout),
|
||||
.RW(~soundcpu_rw),
|
||||
.SEL(~cs_k007327),
|
||||
.CCS(~cs_k007327),
|
||||
.CWR(n_k007327_we),
|
||||
.BLK(blank),
|
||||
.R(video_r),
|
||||
.G(video_g),
|
||||
.B(video_b),
|
||||
.Do(k007327_D)
|
||||
);
|
||||
|
||||
//----------------------------------------------------- Final audio output -----------------------------------------------------//
|
||||
|
||||
//The original Jackal PCB applies high-pass filtering at around 80Hz - use Jotego's jt49_dcrm2 module to apply this high-pass
|
||||
//filtering with JT51's unsigned output
|
||||
//TODO: Replace this with a proper high-pass filter
|
||||
wire signed [15:0] sound_l_hpf, sound_r_hpf;
|
||||
jt49_dcrm2 #(16) hpf_left
|
||||
(
|
||||
.clk(clk_49m),
|
||||
.cen(cen_dcrm),
|
||||
.rst(~reset),
|
||||
.din(unsigned_sound_l_atten),
|
||||
.dout(sound_l_hpf)
|
||||
);
|
||||
jt49_dcrm2 #(16) hpf_right
|
||||
(
|
||||
.clk(clk_49m),
|
||||
.cen(cen_dcrm),
|
||||
.rst(~reset),
|
||||
.din(unsigned_sound_r_atten),
|
||||
.dout(sound_r_hpf)
|
||||
);
|
||||
|
||||
//Jackal produces sound out of the YM2151 at a significantly higher volume than most other games on the MiSTer platform - apply
|
||||
//6dB attenuation for better balance with other cores
|
||||
wire [15:0] unsigned_sound_l_atten = unsgined_sound_l_raw >> 1;
|
||||
wire [15:0] unsigned_sound_r_atten = unsgined_sound_r_raw >> 1;
|
||||
wire signed [15:0] sound_l_atten = sound_l_raw >>> 1;
|
||||
wire signed [15:0] sound_r_atten = sound_r_raw >>> 1;
|
||||
|
||||
//Jackal employs a 4.823KHz low-pass filter for its YM2151 - filter the audio accordingly here and output the end result
|
||||
//The original PCB also has a variable low-pass filter that applies heavier filtering the higher the volume is set - apply this
|
||||
//extra low-pass filter when original ROMs are used (controlled by the is_bootleg flag - this filter and the 80Hz high-pass filter
|
||||
//are absent on bootleg ROM sets)
|
||||
jackal_lpf lpf_left
|
||||
(
|
||||
.clk(clk_49m),
|
||||
.reset(~reset),
|
||||
.select(is_bootleg[0]),
|
||||
.in1(sound_l_atten),
|
||||
.in2(sound_l_hpf),
|
||||
.out(sound_l)
|
||||
);
|
||||
jackal_lpf lpf_right
|
||||
(
|
||||
.clk(clk_49m),
|
||||
.reset(~reset),
|
||||
.select(is_bootleg[0]),
|
||||
.in1(sound_r_atten),
|
||||
.in2(sound_r_hpf),
|
||||
.out(sound_r)
|
||||
);
|
||||
|
||||
endmodule
|
||||
360
Arcade_MiST/Konami Jackal/rtl/Jackal_MiST.sv
Normal file
360
Arcade_MiST/Konami Jackal/rtl/Jackal_MiST.sv
Normal file
@@ -0,0 +1,360 @@
|
||||
module Jackal_MiST (
|
||||
output LED,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output AUDIO_L,
|
||||
output AUDIO_R,
|
||||
input SPI_SCK,
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SS2,
|
||||
input SPI_SS3,
|
||||
input CONF_DATA0,
|
||||
input CLOCK_27,
|
||||
output [12:0] SDRAM_A,
|
||||
inout [15:0] SDRAM_DQ,
|
||||
output SDRAM_DQML,
|
||||
output SDRAM_DQMH,
|
||||
output SDRAM_nWE,
|
||||
output SDRAM_nCAS,
|
||||
output SDRAM_nRAS,
|
||||
output SDRAM_nCS,
|
||||
output [1:0] SDRAM_BA,
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE
|
||||
|
||||
);
|
||||
|
||||
`include "rtl\build_id.v"
|
||||
|
||||
localparam CONF_STR = {
|
||||
"JACKAL;;",
|
||||
"O2,Rotate Controls,Off,On;",
|
||||
"O34,Scanlines,Off,25%,50%,75%;",
|
||||
"O5,Blend,Off,On;",
|
||||
"O6,Joystick Swap,Off,On;",
|
||||
"O7,Service,Off,On;",
|
||||
"O1,Rotary speed,Normal,Fast;",
|
||||
"DIP;",
|
||||
"T0,Reset;",
|
||||
"V,v1.00.",`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];
|
||||
wire rotary_speed = status[1];
|
||||
|
||||
wire [1:0] orientation = 2'b11;
|
||||
wire [23:0] dip_sw = ~status[31:8];
|
||||
|
||||
wire [1:0] is_bootleg = core_mod[1:0];
|
||||
|
||||
assign LED = ~ioctl_downl;
|
||||
assign SDRAM_CLK = clock_98;
|
||||
assign SDRAM_CKE = 1;
|
||||
|
||||
wire clock_98, clock_49, pll_locked;
|
||||
pll pll(
|
||||
.inclk0(CLOCK_27),
|
||||
.c0(clock_98),
|
||||
.c1(clock_49),//49.152MHz
|
||||
.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 [6:0] core_mod;
|
||||
wire [15:0] audio_l, audio_r;
|
||||
wire hs, vs, cs;
|
||||
wire hb, vb;
|
||||
wire blankn = ~(hb | vb);
|
||||
wire [4:0] r, g, b;
|
||||
wire key_strobe;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
|
||||
wire [16:0] main_rom_addr;
|
||||
wire [15:0] main_rom_do;
|
||||
wire [14:0] sub_rom_addr;
|
||||
wire [15:0] sub_rom_do;
|
||||
wire [15:0] ch1_addr;
|
||||
wire [15:0] ch1_do;
|
||||
wire [15:0] ch2_addr;
|
||||
wire [15:0] ch2_do;
|
||||
wire sp1_req, sp1_ack;
|
||||
wire [15:0] sp1_addr;
|
||||
wire [15:0] sp1_do;
|
||||
wire sp2_req, sp2_ack;
|
||||
wire [15:0] sp2_addr;
|
||||
wire [15:0] sp2_do;
|
||||
|
||||
wire ioctl_downl;
|
||||
wire [7:0] ioctl_index;
|
||||
wire ioctl_wr;
|
||||
wire [24:0] ioctl_addr;
|
||||
wire [7:0] ioctl_dout;
|
||||
|
||||
data_io data_io(
|
||||
.clk_sys ( clock_98 ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS2 ( SPI_SS2 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
.ioctl_download( ioctl_downl ),
|
||||
.ioctl_index ( ioctl_index ),
|
||||
.ioctl_wr ( ioctl_wr ),
|
||||
.ioctl_addr ( ioctl_addr ),
|
||||
.ioctl_dout ( ioctl_dout )
|
||||
);
|
||||
wire [24:0] bg_ioctl_addr = ioctl_addr - 18'h20000;
|
||||
|
||||
reg port1_req, port2_req;
|
||||
sdram #(98) sdram(
|
||||
.*,
|
||||
.init_n ( pll_locked ),
|
||||
.clk ( clock_98 ),
|
||||
|
||||
// port1 for CPUs
|
||||
.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 ? 16'h0000 : main_rom_addr[16:1] ),
|
||||
.cpu1_q ( main_rom_do ),
|
||||
.cpu2_addr ( ioctl_downl ? 16'h0000 : sub_rom_addr[14:1] + 16'hc000 ),
|
||||
.cpu2_q ( sub_rom_do ),
|
||||
|
||||
// port2 for graphics
|
||||
.port2_req ( port2_req ),
|
||||
.port2_ack ( ),
|
||||
.port2_a ( {bg_ioctl_addr[23:18], bg_ioctl_addr[16:0]} ), // merge gfx roms to 16-bit wide words
|
||||
.port2_ds ( {~bg_ioctl_addr[17], bg_ioctl_addr[17]} ),
|
||||
.port2_we ( ioctl_downl ),
|
||||
.port2_d ( {ioctl_dout, ioctl_dout} ),
|
||||
.port2_q ( ),
|
||||
|
||||
.ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ),
|
||||
.ch1_q ( ch1_do ),
|
||||
.ch2_addr ( ioctl_downl ? 16'hffff : ch2_addr ),
|
||||
.ch2_q ( ch2_do ),
|
||||
.sp1_req ( sp1_req ),
|
||||
.sp1_ack ( sp1_ack ),
|
||||
.sp1_addr ( ioctl_downl ? 16'hffff : sp1_addr ),
|
||||
.sp1_q ( sp1_do ),
|
||||
.sp2_req ( sp2_req ),
|
||||
.sp2_ack ( sp2_ack ),
|
||||
.sp2_addr ( ioctl_downl ? 16'hffff : sp2_addr ),
|
||||
.sp2_q ( sp2_do )
|
||||
);
|
||||
|
||||
// ROM download controller
|
||||
always @(posedge clock_98) begin
|
||||
reg ioctl_wr_last = 0;
|
||||
|
||||
ioctl_wr_last <= ioctl_wr;
|
||||
if (ioctl_downl) begin
|
||||
if (~ioctl_wr_last && ioctl_wr) begin
|
||||
port1_req <= ~port1_req;
|
||||
port2_req <= ~port2_req;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg reset = 1;
|
||||
reg rom_loaded = 0;
|
||||
always @(posedge clock_49) begin
|
||||
reg ioctl_downlD;
|
||||
ioctl_downlD <= ioctl_downl;
|
||||
|
||||
if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1;
|
||||
reset <= status[0] | buttons[1] | ~rom_loaded;
|
||||
end
|
||||
|
||||
Jackal Jackal(
|
||||
.reset(~reset),
|
||||
.clk_49m(clock_49),
|
||||
.coins({~m_coin2,~m_coin1}),
|
||||
.btn_start({~m_two_players,~m_one_player}),
|
||||
.p1_joystick({~m_down, ~m_up, ~m_right, ~m_left}),
|
||||
.p2_joystick({~m_down2, ~m_up2, ~m_right2, ~m_left2}),
|
||||
.p1_rotary(~p1_rotary),
|
||||
.p2_rotary(~p2_rotary),
|
||||
.p1_buttons({~m_fireB, ~m_fireA}),
|
||||
.p2_buttons({~m_fire2B, ~m_fire2A}),
|
||||
.btn_service(~service),
|
||||
.dipsw(dip_sw),
|
||||
.is_bootleg(is_bootleg),
|
||||
.video_hsync(hs),
|
||||
.video_vsync(vs),
|
||||
.video_csync(cs),
|
||||
.video_hblank(hb),
|
||||
.video_vblank(vb),
|
||||
.video_r(r),
|
||||
.video_g(g),
|
||||
.video_b(b),
|
||||
.sound_l(audio_l),
|
||||
.sound_r(audio_r),
|
||||
.pause(1'b1),
|
||||
.ioctl_clk(clock_98),
|
||||
.ioctl_addr(ioctl_addr),
|
||||
.ioctl_data(ioctl_dout),
|
||||
.ioctl_wr(ioctl_wr),
|
||||
|
||||
.main_cpu_rom_addr(main_rom_addr),
|
||||
.main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]),
|
||||
.sub_cpu_rom_addr(sub_rom_addr),
|
||||
.sub_cpu_rom_do(sub_rom_addr[0] ? sub_rom_do[15:8] : sub_rom_do[7:0]),
|
||||
.char1_rom_addr(ch1_addr),
|
||||
.char1_rom_do(ch1_do),
|
||||
.char2_rom_addr(ch2_addr),
|
||||
.char2_rom_do(ch2_do),
|
||||
.sp1_req(sp1_req),
|
||||
.sp1_ack(sp1_ack),
|
||||
.sp1_rom_addr(sp1_addr),
|
||||
.sp1_rom_do(sp1_do),
|
||||
.sp2_req(sp2_req),
|
||||
.sp2_ack(sp2_ack),
|
||||
.sp2_rom_addr(sp2_addr),
|
||||
.sp2_rom_do(sp2_do)
|
||||
);
|
||||
|
||||
mist_video #(.COLOR_DEPTH(5), .SD_HCNT_WIDTH(10)) mist_video(
|
||||
.clk_sys ( clock_49 ),
|
||||
.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 ),
|
||||
.ce_divider ( 0 ),
|
||||
.rotate ( { orientation[1], rotate } ),
|
||||
.blend ( blend ),
|
||||
.scandoubler_disable( scandoublerD ),
|
||||
.scanlines ( scanlines ),
|
||||
.ypbpr ( ypbpr ),
|
||||
.no_csync ( no_csync )
|
||||
);
|
||||
|
||||
user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io(
|
||||
.clk_sys (clock_49 ),
|
||||
.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 ),
|
||||
.core_mod (core_mod ),
|
||||
.key_strobe (key_strobe ),
|
||||
.key_pressed (key_pressed ),
|
||||
.key_code (key_code ),
|
||||
.joystick_0 (joystick_0 ),
|
||||
.joystick_1 (joystick_1 ),
|
||||
.status (status )
|
||||
);
|
||||
|
||||
dac #(.C_bits(16))dac_l(
|
||||
.clk_i(clock_49),
|
||||
.res_n_i(1'b1),
|
||||
.dac_i({~audio_l[15], audio_l[14:0]}),
|
||||
.dac_o(AUDIO_L)
|
||||
);
|
||||
|
||||
dac #(.C_bits(16))dac_r(
|
||||
.clk_i(clock_49),
|
||||
.res_n_i(1'b1),
|
||||
.dac_i({~audio_r[15], audio_r[14:0]}),
|
||||
.dac_o(AUDIO_R)
|
||||
);
|
||||
|
||||
//Rotary controls (disable for bootleg ROM sets as although these support rotary controls, bootleg PCBs
|
||||
//have no means of supporting rotary controls as there are no footprints for the required hardware)
|
||||
//TODO: Map the inputs to absolute inputs using an analog stick (Jackal ignores out-of-order inputs)
|
||||
reg [22:0] rotary_div = 23'd0;
|
||||
reg [7:0] rotary1 = 8'h01;
|
||||
reg [7:0] rotary2 = 8'h01;
|
||||
wire m_rotary1_l = m_fireC;
|
||||
wire m_rotary1_r = m_fireD;
|
||||
wire m_rotary2_l = m_fire2C;
|
||||
wire m_rotary2_r = m_fire2D;
|
||||
|
||||
wire rotary_en = rotary_speed ? !rotary_div[21:0] : !rotary_div;
|
||||
always_ff @(posedge clock_49) begin
|
||||
rotary_div <= rotary_div + 23'd1;
|
||||
if(rotary_en) begin
|
||||
if(m_rotary1_l) begin
|
||||
if(rotary1 != 8'h80)
|
||||
rotary1 <= rotary1 << 1;
|
||||
else
|
||||
rotary1 <= 8'h01;
|
||||
end
|
||||
else if(m_rotary1_r) begin
|
||||
if(rotary1 != 8'h01)
|
||||
rotary1 <= rotary1 >> 1;
|
||||
else
|
||||
rotary1 <= 8'h80;
|
||||
end
|
||||
|
||||
if(m_rotary2_l) begin
|
||||
if(rotary2 != 8'h80)
|
||||
rotary2 <= rotary2 << 1;
|
||||
else
|
||||
rotary2 <= 8'h01;
|
||||
end
|
||||
else if(m_rotary2_r) begin
|
||||
if(rotary2 != 8'h01)
|
||||
rotary2 <= rotary2 >> 1;
|
||||
else
|
||||
rotary2 <= 8'h80;
|
||||
end
|
||||
end
|
||||
end
|
||||
wire [7:0] p1_rotary = (is_bootleg == 2'b01) ? 8'hFF : rotary1;
|
||||
wire [7:0] p2_rotary = (is_bootleg == 2'b01) ? 8'hFF : rotary2;
|
||||
|
||||
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 ( clock_49 ),
|
||||
.key_strobe ( key_strobe ),
|
||||
.key_pressed ( key_pressed ),
|
||||
.key_code ( key_code ),
|
||||
.joystick_0 ( joystick_0 ),
|
||||
.joystick_1 ( joystick_1 ),
|
||||
.rotate ( rotate ),
|
||||
.orientation ( orientation ),
|
||||
.joyswap ( joyswap ),
|
||||
.oneplayer ( 1'b0 ),
|
||||
.controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
|
||||
.player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
|
||||
.player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
35
Arcade_MiST/Konami Jackal/rtl/build_id.tcl
Normal file
35
Arcade_MiST/Konami Jackal/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
|
||||
3
Arcade_MiST/Konami Jackal/rtl/custom/jackal_custom.qip
Normal file
3
Arcade_MiST/Konami Jackal/rtl/custom/jackal_custom.qip
Normal file
@@ -0,0 +1,3 @@
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k005885.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k007327.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k007343.sv
|
||||
902
Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv
Normal file
902
Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv
Normal file
@@ -0,0 +1,902 @@
|
||||
//============================================================================
|
||||
//
|
||||
// SystemVerilog implementation of the Konami 005885 custom tilemap
|
||||
// generator
|
||||
// Graphics logic based on the video section of the Green Beret core for
|
||||
// MiSTer by MiSTer-X
|
||||
// Copyright (C) 2020, 2021 Ace
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//Note: This model of the 005885 cannot be used as-is to replace an original 005885.
|
||||
|
||||
module k005885
|
||||
(
|
||||
input CK49, //49.152MHz clock input
|
||||
output NCK2, //6.144MHz clock output
|
||||
output H1O, //3.072MHz clock output
|
||||
output NCPE, //E clock for MC6809E
|
||||
output NCPQ, //Q clock for MC6809E
|
||||
output NEQ, //AND of E and Q clocks for MC6809E
|
||||
input NRD, //Read enable (active low)
|
||||
output NRES, //Reset passthrough
|
||||
input [13:0] A, //Address bus from CPU
|
||||
input [7:0] DBi, //Data bus input from CPU
|
||||
output [7:0] DBo, //Data output to CPU
|
||||
output [3:0] VCF, //Color address to tilemap LUT PROM
|
||||
output [3:0] VCB, //Tile index to tilemap LUT PROM
|
||||
input [3:0] VCD, //Data input from tilemap LUT PROM
|
||||
output [3:0] OCF, //Color address to sprite LUT PROM
|
||||
output [3:0] OCB, //Sprite index to sprite LUT PROM
|
||||
input [3:0] OCD, //Data input from sprite LUT PROM
|
||||
output [4:0] COL, //Color data output from color mixer
|
||||
input NEXR, //Reset input (active low)
|
||||
input NXCS, //Chip select (active low)
|
||||
output NCSY, //Composite sync (active low)
|
||||
output NHSY, //HSync (active low) - Not exposed on the original chip
|
||||
output NVSY, //VSync (active low)
|
||||
output HBLK, //HBlank (active high) - Not exposed on the original chip
|
||||
output VBLK, //VBlank (active high) - Not exposed on the original chip
|
||||
input NBUE, //Unknown
|
||||
output NFIR, //Fast IRQ (FIRQ) output for MC6809E
|
||||
output NIRQ, //IRQ output for MC6809E (VBlank IRQ)
|
||||
output NNMI, //Non-maskable IRQ (NMI) for MC6809E
|
||||
output NIOC, //Inverse of address line A11 for external address decoding logic
|
||||
output NRMW,
|
||||
|
||||
//Split I/O for tile and sprite data
|
||||
output [15:0] R, //Address output to graphics ROMs (tiles)
|
||||
input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles)
|
||||
input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles)
|
||||
output [15:0] S, //Address output to graphics ROMs (sprites)
|
||||
output reg S_req = 0,
|
||||
input S_ack,
|
||||
input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites)
|
||||
input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites)
|
||||
|
||||
//Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output)
|
||||
input [3:0] HCTR, VCTR,
|
||||
|
||||
//Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885
|
||||
//Valid values:
|
||||
//-00: Original behavior
|
||||
//-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen
|
||||
// centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is
|
||||
// flipped)
|
||||
//-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is
|
||||
// offset vertically by 1 line, sprite limit significantly lower than normal)
|
||||
input [1:0] BTLG,
|
||||
|
||||
//Extra data outputs for graphics ROMs
|
||||
output ATR4, //Tilemap attribute bit 4
|
||||
output ATR5, //Tilemap attribute bit 5
|
||||
|
||||
//MiSTer high score system I/O (to be used only with Iron Horse)
|
||||
input [11:0] hs_address,
|
||||
input [7:0] hs_data_in,
|
||||
output [7:0] hs_data_out,
|
||||
input hs_write,
|
||||
input hs_access
|
||||
);
|
||||
|
||||
//------------------------------------------------------- Signal outputs -------------------------------------------------------//
|
||||
|
||||
//Reset line passthrough
|
||||
assign NRES = NEXR;
|
||||
|
||||
//Generate NIOC output (active low)
|
||||
assign NIOC = ~(~NXCS & (A[13:11] == 3'b001));
|
||||
|
||||
//TODO: The timing of the NRMW output is currently unknown - set to 1 for now
|
||||
assign NRMW = 1;
|
||||
|
||||
//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing
|
||||
assign ATR4 = tileram_attrib_D[4];
|
||||
assign ATR5 = tileram_attrib_D[5];
|
||||
|
||||
//Data output to CPU
|
||||
assign DBo = (ram_cs & ~NRD) ? ram_Dout:
|
||||
(zram0_cs & ~NRD) ? zram0_Dout:
|
||||
(zram1_cs & ~NRD) ? zram1_Dout:
|
||||
(zram2_cs & ~NRD) ? zram2_Dout:
|
||||
(tile_attrib_cs & ~NRD) ? tileram_attrib_Dout:
|
||||
(tile_cs & ~NRD) ? tileram_Dout:
|
||||
(tile1_attrib_cs & ~NRD) ? tileram1_attrib_Dout:
|
||||
(tile1_cs & ~NRD) ? tileram1_Dout:
|
||||
(spriteram_cs & ~NRD) ? spriteram_Dout:
|
||||
8'hFF;
|
||||
|
||||
//------------------------------------------------------- Clock division -------------------------------------------------------//
|
||||
|
||||
//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz
|
||||
reg [3:0] div = 4'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
div <= div + 4'd1;
|
||||
end
|
||||
reg [2:0] n_div = 3'd0;
|
||||
always_ff @(negedge CK49) begin
|
||||
n_div <= n_div + 3'd1;
|
||||
end
|
||||
wire cen_6m = !div[2:0];
|
||||
wire n_cen_6m = !n_div;
|
||||
wire cen_3m = !div;
|
||||
assign NCK2 = div[2];
|
||||
assign H1O = div[3];
|
||||
|
||||
//The MC6809E requires two identical clocks with a 90-degree offset - assign these here
|
||||
reg mc6809e_E = 0;
|
||||
reg mc6809e_Q = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
reg [1:0] clk_phase = 0;
|
||||
if(cen_6m) begin
|
||||
clk_phase <= clk_phase + 1'd1;
|
||||
case(clk_phase)
|
||||
2'b00: mc6809e_E <= 0;
|
||||
2'b01: mc6809e_Q <= 1;
|
||||
2'b10: mc6809e_E <= 1;
|
||||
2'b11: mc6809e_Q <= 0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
assign NCPQ = mc6809e_Q;
|
||||
assign NCPE = mc6809e_E;
|
||||
|
||||
//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here
|
||||
assign NEQ = NCPE & NCPQ;
|
||||
|
||||
//-------------------------------------------------------- Video timings -------------------------------------------------------//
|
||||
|
||||
//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both
|
||||
//counters as 9-bit registers.
|
||||
reg [8:0] h_cnt = 9'd0;
|
||||
reg [8:0] v_cnt = 9'd0;
|
||||
|
||||
//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter
|
||||
//rolls over
|
||||
reg hblank = 0;
|
||||
reg vblank = 0;
|
||||
reg vblank_irq_en = 0;
|
||||
reg frame_odd_even = 0;
|
||||
//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical
|
||||
//counter if a bootleg Jackal ROM set is loaded
|
||||
reg [8:0] vcnt_end = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
if(BTLG == 2'b01)
|
||||
vcnt_end <= 9'd252;
|
||||
else if(BTLG == 2'b10)
|
||||
vcnt_end <= 9'd271;
|
||||
else
|
||||
vcnt_end <= 9'd261;
|
||||
end
|
||||
end
|
||||
//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded
|
||||
reg [8:0] hsync_start = 9'd0;
|
||||
reg [8:0] hsync_end = 9'd0;
|
||||
reg [8:0] vsync_start = 9'd0;
|
||||
reg [8:0] vsync_end = 9'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(BTLG == 2'b01) begin
|
||||
hsync_start <= HCTR[3] ? 9'd287 : 9'd295;
|
||||
hsync_end <= HCTR[3] ? 9'd318 : 9'd326;
|
||||
vsync_start <= 9'd244;
|
||||
vsync_end <= 9'd251;
|
||||
end
|
||||
else if(BTLG == 2'b10) begin
|
||||
hsync_start <= HCTR[3] ? 9'd290 : 9'd310;
|
||||
hsync_end <= HCTR[3] ? 9'd321 : 9'd341;
|
||||
vsync_start <= 9'd255;
|
||||
vsync_end <= 9'd262;
|
||||
end
|
||||
else begin
|
||||
hsync_start <= HCTR[3] ? 9'd288 : 9'd296;
|
||||
hsync_end <= HCTR[3] ? 9'd319 : 9'd327;
|
||||
vsync_start <= 9'd254;
|
||||
vsync_end <= 9'd261;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
case(h_cnt)
|
||||
0: begin
|
||||
vblank_irq_en <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
//HBlank ends two lines earlier than normal on bootleg Jackal PCBs
|
||||
11: begin
|
||||
if(BTLG == 2'b01)
|
||||
hblank <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
13: begin
|
||||
if(BTLG != 2'b01)
|
||||
hblank <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
//Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded
|
||||
251: begin
|
||||
if(BTLG == 2'b01)
|
||||
hblank <= 1;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
253: begin
|
||||
if(BTLG != 2'b01)
|
||||
hblank <= 1;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
383: begin
|
||||
h_cnt <= 0;
|
||||
case(v_cnt)
|
||||
15: begin
|
||||
vblank <= 0;
|
||||
v_cnt <= v_cnt + 9'd1;
|
||||
end
|
||||
239: begin
|
||||
vblank <= 1;
|
||||
vblank_irq_en <= 1;
|
||||
frame_odd_even <= ~frame_odd_even;
|
||||
v_cnt <= v_cnt + 9'd1;
|
||||
end
|
||||
vcnt_end: begin
|
||||
v_cnt <= 9'd0;
|
||||
end
|
||||
default: v_cnt <= v_cnt + 9'd1;
|
||||
endcase
|
||||
end
|
||||
default: h_cnt <= h_cnt + 9'd1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//Output HBlank and VBlank (both active high)
|
||||
assign HBLK = hblank;
|
||||
assign VBLK = vblank;
|
||||
|
||||
//Generate horizontal sync and vertical sync (both active low)
|
||||
assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]):
|
||||
~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]);
|
||||
assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR);
|
||||
assign NCSY = NHSY ^ NVSY;
|
||||
|
||||
//------------------------------------------------------------- IRQs -----------------------------------------------------------//
|
||||
|
||||
//IRQ (triggers every VBlank)
|
||||
reg vblank_irq = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
vblank_irq <= 1;
|
||||
else if(cen_6m) begin
|
||||
if(!irq_mask)
|
||||
vblank_irq <= 1;
|
||||
else if(vblank_irq_en)
|
||||
vblank_irq <= 0;
|
||||
end
|
||||
end
|
||||
assign NIRQ = vblank_irq;
|
||||
|
||||
//NMI (triggers every 64 scanlines starting from scanline 48)
|
||||
reg nmi = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
nmi <= 1;
|
||||
else if(cen_3m) begin
|
||||
if(!nmi_mask)
|
||||
nmi <= 1;
|
||||
else if((v_cnt[7:0] + 9'd16) % 9'd64 == 0)
|
||||
nmi <= 0;
|
||||
end
|
||||
end
|
||||
assign NNMI = nmi;
|
||||
|
||||
//FIRQ (triggers every second VBlank)
|
||||
reg firq = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
firq <= 1;
|
||||
else if(cen_3m) begin
|
||||
if(!firq_mask)
|
||||
firq <= 1;
|
||||
else if(!frame_odd_even && v_cnt == 9'd239)
|
||||
firq <= 0;
|
||||
end
|
||||
end
|
||||
assign NFIR = firq;
|
||||
|
||||
//----------------------------------------------------- Internal registers -----------------------------------------------------//
|
||||
|
||||
//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code:
|
||||
/*
|
||||
control registers
|
||||
000: scroll y
|
||||
001: scroll x (low 8 bits)
|
||||
002: -------x scroll x (high bit)
|
||||
----xxx- row/colscroll control
|
||||
000 = solid scroll (finalizr, ddribble bg)
|
||||
100 = solid scroll (jackal)
|
||||
001 = ? (ddribble fg)
|
||||
011 = colscroll (jackal high scores)
|
||||
101 = rowscroll (ironhors, jackal map)
|
||||
003: ------xx high bits of the tile code
|
||||
-----x-- unknown (finalizr)
|
||||
----x--- selects sprite buffer (and makes a copy to a private buffer?)
|
||||
--x----- unknown (ironhors)
|
||||
-x------ unknown (ironhors)
|
||||
x------- unknown (ironhors, jackal)
|
||||
004: -------x nmi enable
|
||||
------x- irq enable
|
||||
-----x-- firq enable
|
||||
----x--- flip screen
|
||||
*/
|
||||
|
||||
wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0);
|
||||
|
||||
reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl;
|
||||
reg nmi_mask = 0;
|
||||
reg irq_mask = 0;
|
||||
reg firq_mask = 0;
|
||||
reg flipscreen = 0;
|
||||
|
||||
//Write to the appropriate register
|
||||
always_ff @(posedge CK49, negedge NEXR) begin
|
||||
if(!NEXR) begin
|
||||
nmi_mask <= 1;
|
||||
irq_mask <= 1;
|
||||
firq_mask <= 1;
|
||||
flipscreen <= 0;
|
||||
end else if(cen_3m) begin
|
||||
if(regs_cs && NRD)
|
||||
case(A[2:0])
|
||||
3'b000: scroll_y <= DBi;
|
||||
3'b001: scroll_x <= DBi;
|
||||
3'b010: scroll_ctrl <= DBi;
|
||||
3'b011: tile_ctrl <= DBi;
|
||||
3'b100: begin
|
||||
nmi_mask <= DBi[0];
|
||||
irq_mask <= DBi[1];
|
||||
firq_mask <= DBi[2];
|
||||
flipscreen <= DBi[3];
|
||||
end
|
||||
default;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//--------------------------------------------------------- Unknown RAM --------------------------------------------------------//
|
||||
|
||||
wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F);
|
||||
|
||||
wire [7:0] ram_Dout;
|
||||
spram #(8, 5) RAM
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(ram_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(ram_Dout)
|
||||
);
|
||||
|
||||
//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------//
|
||||
|
||||
wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F);
|
||||
wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F);
|
||||
wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF);
|
||||
|
||||
//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to
|
||||
//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll,
|
||||
//otherwise don't address it
|
||||
wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]:
|
||||
(scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]:
|
||||
5'h00;
|
||||
wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout;
|
||||
dpram_dc #(.widthad_a(5)) ZRAM0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[4:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(zram0_Dout),
|
||||
.wren_a(zram0_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(zram_A),
|
||||
.q_b(zram0_D)
|
||||
);
|
||||
spram #(8, 5) ZRAM1
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(zram1_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(zram1_Dout)
|
||||
);
|
||||
spram #(8, 5) ZRAM2
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(zram2_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(zram2_Dout)
|
||||
);
|
||||
|
||||
//------------------------------------------------------------ VRAM ------------------------------------------------------------//
|
||||
|
||||
//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers),
|
||||
//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its
|
||||
//constituent components.
|
||||
wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000);
|
||||
wire tile_cs = ~NXCS & (A[13:10] == 4'b1001);
|
||||
wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010);
|
||||
wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011);
|
||||
wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11);
|
||||
|
||||
wire [7:0] tileram_attrib_Dout, tileram_Dout, tileram1_attrib_Dout, tileram1_Dout, spriteram_Dout;
|
||||
wire [7:0] tileram_attrib_D, tileram_D, tileram1_attrib_D, tileram1_D, spriteram_D;
|
||||
//Tilemap layer 0
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram_attrib_Dout),
|
||||
.wren_a(tile_attrib_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram_attrib_D)
|
||||
);
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILECODE0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram_Dout),
|
||||
.wren_a(tile_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram_D)
|
||||
);
|
||||
//Tilemap layer 1
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram1_attrib_Dout),
|
||||
.wren_a(tile1_attrib_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram1_attrib_D)
|
||||
);
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILECODE1
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram1_Dout),
|
||||
.wren_a(tile1_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram1_D)
|
||||
);
|
||||
|
||||
// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM)
|
||||
wire [11:0] VRAM_SPR_AD = hs_access ? hs_address : A[11:0];
|
||||
wire [7:0] VRAM_SPR_DIN = hs_access ? hs_data_in : DBi;
|
||||
wire VRAM_SPR_WE = hs_access ? hs_write : (spriteram_cs & NRD);
|
||||
wire [7:0] VRAM_SPR_DOUT;
|
||||
|
||||
assign hs_data_out = hs_access ? VRAM_SPR_DOUT : 8'h00;
|
||||
assign spriteram_Dout = hs_access ? 8'h00 : VRAM_SPR_DOUT;
|
||||
|
||||
//Sprites
|
||||
dpram_dc #(.widthad_a(12)) VRAM_SPR
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(VRAM_SPR_AD),
|
||||
.data_a(VRAM_SPR_DIN),
|
||||
.q_a(VRAM_SPR_DOUT),
|
||||
.wren_a(VRAM_SPR_WE),
|
||||
|
||||
.clock_b(~CK49),
|
||||
.address_b(spriteram_A),
|
||||
.q_b(spriteram_D)
|
||||
);
|
||||
|
||||
//-------------------------------------------------------- Tilemap layer -------------------------------------------------------//
|
||||
|
||||
//TODO: The current implementation only handles one of the 005885's two tilemap layers - add logic to handle both layers
|
||||
|
||||
//XOR horizontal and vertical counter bits with flipscreen bit
|
||||
wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}};
|
||||
wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}};
|
||||
|
||||
//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on
|
||||
//whether row scroll or column scroll is enabled
|
||||
wire [8:0] row_scroll = (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x};
|
||||
wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y;
|
||||
wire [8:0] tilemap_hpos = hcnt_x + row_scroll;
|
||||
wire [8:0] tilemap_vpos = vcnt_x + col_scroll;
|
||||
|
||||
//Address output to tilemap section of VRAM
|
||||
wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]};
|
||||
|
||||
//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code
|
||||
wire [9:0] tile_index = {tileram_attrib_D[7:6], tileram_D};
|
||||
|
||||
//XOR tile H/V flip bits with the flipscreen bit
|
||||
wire tile_hflip = tileram_attrib_D[4];
|
||||
wire tile_vflip = tileram_attrib_D[5];
|
||||
|
||||
//Address output to graphics ROMs
|
||||
assign R = {tile_ctrl[1:0], tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2] ^ tile_hflip)};
|
||||
|
||||
//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position
|
||||
//bit 1
|
||||
reg [15:0] RD_lat = 16'd0;
|
||||
reg [3:0] tile_color = 4'd0;
|
||||
reg tile_hflip_lat = 0;
|
||||
reg old_tilehpos1;
|
||||
always_ff @(posedge CK49) begin
|
||||
old_tilehpos1 <= tilemap_hpos[1];
|
||||
if(old_tilehpos1 && !tilemap_hpos[1]) begin
|
||||
tile_color <= tileram_attrib_D[3:0];
|
||||
RD_lat <= flipscreen ? {RDL, RDU} : {RDU, RDL};
|
||||
tile_hflip_lat <= tileram_attrib_D[4];
|
||||
end
|
||||
end
|
||||
|
||||
//Multiplex graphics ROM data down from 16 bits to 8 using bit 1 of the horizontal position
|
||||
wire [7:0] RD = (tilemap_hpos[1] ^ tile_hflip_lat) ? RD_lat[7:0] : RD_lat[15:8];
|
||||
|
||||
//Further multiplex graphics ROM data down from 8 bits to 4 using bit 0 of the horizontal position
|
||||
wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_lat) ? RD[3:0] : RD[7:4];
|
||||
|
||||
//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register
|
||||
wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5];
|
||||
reg tilemap_en = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(n_cen_6m) begin
|
||||
tilemap_en <= tile_sel;
|
||||
end
|
||||
end
|
||||
|
||||
//Address output to tilemap LUT PROM
|
||||
assign VCF = tile_color;
|
||||
assign VCB = tile_pixel;
|
||||
|
||||
//Shift the tilemap layer left by two lines when the screen is flipped
|
||||
reg [7:0] tilemap_shift;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
tilemap_shift <= {VCD, tilemap_shift[7:4]};
|
||||
end
|
||||
wire [3:0] tilemap_D = flipscreen ? tilemap_shift[3:0] : VCD;
|
||||
|
||||
//-------------------------------------------------------- Sprite layer --------------------------------------------------------//
|
||||
|
||||
//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format
|
||||
reg [8:0] sprite_hpos = 9'd0;
|
||||
reg [8:0] sprite_vpos = 9'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
sprite_hpos <= h_cnt;
|
||||
//If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the
|
||||
//bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a
|
||||
//vertical offset of 66 lines (65 lines when flipped)
|
||||
if(BTLG == 2'b10)
|
||||
if(flipscreen)
|
||||
sprite_vpos <= v_cnt + 9'd66;
|
||||
else
|
||||
sprite_vpos <= v_cnt + 9'd65;
|
||||
else
|
||||
if(flipscreen)
|
||||
sprite_vpos <= v_cnt + 9'd65;
|
||||
else
|
||||
sprite_vpos <= v_cnt + 9'd66;
|
||||
end
|
||||
end
|
||||
|
||||
//Sprite state machine
|
||||
reg [8:0] sprite_index;
|
||||
reg [2:0] sprite_offset;
|
||||
reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3, sprite_attrib4;
|
||||
reg [2:0] sprite_fsm_state;
|
||||
reg [5:0] sprite_width;
|
||||
//Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit
|
||||
//to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of
|
||||
//5, otherwise)
|
||||
wire [8:0] sprite_limit = (BTLG == 2'b10) ? 9'd155 : 9'd485;
|
||||
always_ff @(posedge CK49) begin
|
||||
//Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0
|
||||
//Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse
|
||||
//ROM sets to prevent graphical garbage from occurring on the top-most line
|
||||
if(sprite_hpos == 9'd0 || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin
|
||||
sprite_width <= 0;
|
||||
sprite_index <= 0;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_fsm_state <= 1;
|
||||
end
|
||||
else
|
||||
case(sprite_fsm_state)
|
||||
0: /* empty */ ;
|
||||
1: begin
|
||||
if(sprite_index > sprite_limit)
|
||||
sprite_fsm_state <= 0;
|
||||
else begin
|
||||
sprite_attrib4 <= spriteram_D;
|
||||
sprite_offset <= 3'd3;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
end
|
||||
2: begin
|
||||
sprite_attrib3 <= spriteram_D;
|
||||
sprite_offset <= 3'd2;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
3: begin
|
||||
//Skip the current sprite if it's inactive, otherwise obtain the sprite Y attribute and continue
|
||||
//scanning out the rest of the sprite attributes
|
||||
if(sprite_active) begin
|
||||
sprite_attrib2 <= spriteram_D;
|
||||
sprite_offset <= 3'd1;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
else begin
|
||||
sprite_index <= sprite_index + 9'd5;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_fsm_state <= 3'd1;
|
||||
end
|
||||
end
|
||||
4: begin
|
||||
sprite_attrib1 <= spriteram_D;
|
||||
sprite_offset <= 3'd0;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
5: begin
|
||||
sprite_attrib0 <= spriteram_D;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_index <= sprite_index + 9'd5;
|
||||
case(sprite_size)
|
||||
3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b100: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
|
||||
default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
|
||||
endcase
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
S_req <= !S_req;
|
||||
end
|
||||
6: if (S_req == S_ack) begin
|
||||
//Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails
|
||||
//to render the last line of sprites), otherwise write sprites as normal
|
||||
if(BTLG == 2'b01 && !flipscreen)
|
||||
if(sprite_width == 6'b111110)
|
||||
sprite_width <= sprite_width + 6'd2;
|
||||
else
|
||||
sprite_width <= sprite_width + 6'd1;
|
||||
else
|
||||
sprite_width <= sprite_width + 6'd1;
|
||||
sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1;
|
||||
S_req <= (wre & sprite_width[1:0] == 2'b11) ? !S_req : S_req;
|
||||
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
//Obtain sprite X position from sprite attribute byte 3 - append a 9th bit based on the state of bit 1 sprite attribute byte 4,
|
||||
//bit 0 of sprite attribute byte 4 if high or the AND of the upper 5 bits of the horizontal position if low
|
||||
reg sprite_x8;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(sprite_attrib4[1])
|
||||
sprite_x8 <= sprite_attrib4[0];
|
||||
else
|
||||
sprite_x8 <= &sprite_attrib3[7:3];
|
||||
end
|
||||
wire [8:0] sprite_x = {sprite_x8 ^ flipscreen, sprite_attrib3 ^ {8{flipscreen}}};
|
||||
|
||||
//If the sprite state machine is in state 3, obtain sprite Y position directly from sprite RAM, otherwise obtain it from
|
||||
//sprite attribute byte 2
|
||||
wire [7:0] sprite_y = (sprite_fsm_state == 3'd3) ? spriteram_D : sprite_attrib2;
|
||||
|
||||
//Sprite flip attributes are stored in bits 5 (horizontal) and 6 (vertical) of sprite attribute byte 4
|
||||
//Also XOR these attributes with the flipscreen bit (XOR with the inverse for vertical flip)
|
||||
wire sprite_hflip = sprite_attrib4[5] ^ flipscreen;
|
||||
wire sprite_vflip = sprite_attrib4[6] ^ ~flipscreen;
|
||||
|
||||
//Sprite code is sprite attribute byte 0 sandwiched between bits 1 and 0 and bits 3 and 2 of sprite attribute byte 1
|
||||
wire [11:0] sprite_code = {sprite_attrib1[1:0], sprite_attrib0, sprite_attrib1[3:2]};
|
||||
|
||||
//Sprite color is the upper 4 bits of sprite attribute byte 1
|
||||
wire [3:0] sprite_color = sprite_attrib1[7:4];
|
||||
|
||||
//The 005885 supports 5 different sprite sizes: 8x8, 8x16, 16x8, 16x16 and 32x32. Retrieve this attribute from bits [4:2] of
|
||||
//sprite attribute byte 4
|
||||
wire [2:0] sprite_size = sprite_attrib4[4:2];
|
||||
|
||||
//Adjust sprite code based on sprite size
|
||||
wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16
|
||||
sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8
|
||||
sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16
|
||||
sprite_size == 3'b011 ? sprite_code: //8x8
|
||||
{sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32
|
||||
|
||||
//Subtract vertical sprite position from sprite Y parameter to obtain sprite height
|
||||
wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos;
|
||||
|
||||
//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall
|
||||
reg sprite_active;
|
||||
always @(*) begin
|
||||
case(sprite_size)
|
||||
3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen);
|
||||
3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
|
||||
3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen);
|
||||
3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
|
||||
3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
|
||||
default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
|
||||
endcase
|
||||
end
|
||||
|
||||
wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}};
|
||||
wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}};
|
||||
|
||||
//Assign address outputs to sprite ROMs
|
||||
assign S = {sprite_code_sized, ly[2:0], lx[2]};
|
||||
|
||||
//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position
|
||||
wire [7:0] SD = lx[1] ? SDL : SDU;
|
||||
|
||||
//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position
|
||||
wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4];
|
||||
|
||||
//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3
|
||||
wire [8:0] sprite_address = (sprite_index + sprite_offset);
|
||||
reg sprite_bank = 0;
|
||||
reg old_vsync;
|
||||
//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes
|
||||
//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded
|
||||
always_ff @(posedge CK49) begin
|
||||
old_vsync <= NVSY;
|
||||
if(!NEXR)
|
||||
sprite_bank <= 0;
|
||||
else if(!old_vsync && NVSY)
|
||||
sprite_bank <= tile_ctrl[3];
|
||||
end
|
||||
wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address};
|
||||
|
||||
//Address output to sprite LUT PROM
|
||||
assign OCF = sprite_color;
|
||||
assign OCB = sprite_pixel;
|
||||
|
||||
//----------------------------------------------------- Sprite line buffer -----------------------------------------------------//
|
||||
|
||||
//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the
|
||||
//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation.
|
||||
|
||||
//Enable writing to sprite line buffer when bit 5 of the sprite width is 1
|
||||
wire wre = sprite_width[5];
|
||||
|
||||
//Set sprite line buffer bank as bit 0 of the sprite vertical position
|
||||
wire sprite_lbuff_bank = sprite_vpos[0];
|
||||
|
||||
//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size:
|
||||
//32 pixels wide: bits [4:0]
|
||||
//16 pixels wide: bits [3:0]
|
||||
//8 pixels wide: bits [2:0]
|
||||
//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites
|
||||
reg [4:0] final_sprite_width;
|
||||
always @(*) begin
|
||||
case(sprite_size)
|
||||
3'b000: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
|
||||
3'b001: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
|
||||
3'b010: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
|
||||
3'b011: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
|
||||
3'b100: final_sprite_width = sprite_width[4:0];
|
||||
default: final_sprite_width = sprite_width[4:0];
|
||||
endcase
|
||||
end
|
||||
wire [8:0] wpx = sprite_x + final_sprite_width;
|
||||
|
||||
//Generate sprite line buffer write addresses
|
||||
reg [9:0] lbuff_A;
|
||||
reg lbuff_we;
|
||||
wire [3:0] lbuff_Din = OCD;
|
||||
always_ff @(posedge CK49) begin
|
||||
lbuff_A <= {~sprite_lbuff_bank, wpx};
|
||||
lbuff_we <= wre & S_req == S_ack;
|
||||
end
|
||||
|
||||
//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen
|
||||
//is flipped)
|
||||
reg [9:0] radr0 = 10'd0;
|
||||
reg [9:0] radr1 = 10'd1;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : sprite_hpos};
|
||||
end
|
||||
|
||||
//Sprite line buffer
|
||||
wire [3:0] lbuff_Dout;
|
||||
dpram_dc #(.widthad_a(10)) LBUFF
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(lbuff_A),
|
||||
.data_a({4'd0, lbuff_Din}),
|
||||
.wren_a(lbuff_we & (lbuff_Din != 0)),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(radr0),
|
||||
.data_b(8'h0),
|
||||
.wren_b(radr0 == radr1),
|
||||
.q_b({4'bZZZZ, lbuff_Dout})
|
||||
);
|
||||
|
||||
//Latch sprite data from the sprite line buffer
|
||||
wire lbuff_read_en = (div[2:0] == 3'b100);
|
||||
reg [3:0] lbuff_read = 4'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(lbuff_read_en) begin
|
||||
if(radr0 != radr1)
|
||||
lbuff_read <= lbuff_Dout;
|
||||
radr1 <= radr0;
|
||||
end
|
||||
end
|
||||
|
||||
//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped)
|
||||
reg [7:0] sprite_dly = 8'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
if(BTLG == 2'b01 && flipscreen)
|
||||
sprite_dly <= {4'd0, lbuff_read};
|
||||
else
|
||||
sprite_dly <= {lbuff_read, sprite_dly[7:4]};
|
||||
end
|
||||
end
|
||||
//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here
|
||||
wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0];
|
||||
|
||||
//--------------------------------------------------------- Color mixer --------------------------------------------------------//
|
||||
|
||||
//Multiplex tile and sprite data, then output the final result
|
||||
wire tile_sprite_sel = (tilemap_en | ~(|sprite_D));
|
||||
wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D;
|
||||
|
||||
//Latch and output pixel data
|
||||
reg [4:0] pixel_D;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
pixel_D <= {tile_sprite_sel, tile_sprite_D};
|
||||
end
|
||||
assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) ||
|
||||
(BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D;
|
||||
//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set
|
||||
//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse
|
||||
//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of
|
||||
//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area
|
||||
|
||||
endmodule
|
||||
911
Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv.bakk
Normal file
911
Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv.bakk
Normal file
@@ -0,0 +1,911 @@
|
||||
//============================================================================
|
||||
//
|
||||
// SystemVerilog implementation of the Konami 005885 custom tilemap
|
||||
// generator
|
||||
// Graphics logic based on the video section of the Green Beret core for
|
||||
// MiSTer by MiSTer-X
|
||||
// Copyright (C) 2020, 2021 Ace
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//Note: This model of the 005885 cannot be used as-is to replace an original 005885.
|
||||
|
||||
module k005885
|
||||
(
|
||||
input CK49, //49.152MHz clock input
|
||||
output NCK2, //6.144MHz clock output
|
||||
output H1O, //3.072MHz clock output
|
||||
output NCPE, //E clock for MC6809E
|
||||
output NCPQ, //Q clock for MC6809E
|
||||
output NEQ, //AND of E and Q clocks for MC6809E
|
||||
input NRD, //Read enable (active low)
|
||||
output NRES, //Reset passthrough
|
||||
input [13:0] A, //Address bus from CPU
|
||||
input [7:0] DBi, //Data bus input from CPU
|
||||
output [7:0] DBo, //Data output to CPU
|
||||
output [3:0] VCF, //Color address to tilemap LUT PROM
|
||||
output [3:0] VCB, //Tile index to tilemap LUT PROM
|
||||
input [3:0] VCD, //Data input from tilemap LUT PROM
|
||||
output [3:0] OCF, //Color address to sprite LUT PROM
|
||||
output [3:0] OCB, //Sprite index to sprite LUT PROM
|
||||
input [3:0] OCD, //Data input from sprite LUT PROM
|
||||
output [4:0] COL, //Color data output from color mixer
|
||||
input NEXR, //Reset input (active low)
|
||||
input NXCS, //Chip select (active low)
|
||||
output NCSY, //Composite sync (active low)
|
||||
output NHSY, //HSync (active low) - Not exposed on the original chip
|
||||
output NVSY, //VSync (active low)
|
||||
output HBLK, //HBlank (active high) - Not exposed on the original chip
|
||||
output VBLK, //VBlank (active high) - Not exposed on the original chip
|
||||
input NBUE, //Unknown
|
||||
output NFIR, //Fast IRQ (FIRQ) output for MC6809E
|
||||
output NIRQ, //IRQ output for MC6809E (VBlank IRQ)
|
||||
output NNMI, //Non-maskable IRQ (NMI) for MC6809E
|
||||
output NIOC, //Inverse of address line A11 for external address decoding logic
|
||||
output NRMW,
|
||||
|
||||
//Split I/O for tile and sprite data
|
||||
output [15:0] R, //Address output to graphics ROMs (tiles)
|
||||
input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles)
|
||||
input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles)
|
||||
output [15:0] S, //Address output to graphics ROMs (sprites)
|
||||
input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites)
|
||||
input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites)
|
||||
|
||||
//Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output)
|
||||
input [3:0] HCTR, VCTR,
|
||||
|
||||
//Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885
|
||||
//Valid values:
|
||||
//-00: Original behavior
|
||||
//-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen
|
||||
// centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is
|
||||
// flipped)
|
||||
//-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is
|
||||
// offset vertically by 1 line, sprite limit significantly lower than normal)
|
||||
input [1:0] BTLG,
|
||||
|
||||
//Extra data outputs for graphics ROMs
|
||||
output ATR4, //Tilemap attribute bit 4
|
||||
output ATR5, //Tilemap attribute bit 5
|
||||
|
||||
//MiSTer high score system I/O (to be used only with Iron Horse)
|
||||
input [11:0] hs_address,
|
||||
input [7:0] hs_data_in,
|
||||
output [7:0] hs_data_out,
|
||||
input hs_write,
|
||||
input hs_access
|
||||
);
|
||||
|
||||
//------------------------------------------------------- Signal outputs -------------------------------------------------------//
|
||||
|
||||
//Reset line passthrough
|
||||
assign NRES = NEXR;
|
||||
|
||||
//Generate NIOC output (active low)
|
||||
assign NIOC = ~(~NXCS & (A[13:11] == 3'b001));
|
||||
|
||||
//TODO: The timing of the NRMW output is currently unknown - set to 1 for now
|
||||
assign NRMW = 1;
|
||||
|
||||
//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing
|
||||
assign ATR4 = tileram_attrib_D[4];
|
||||
assign ATR5 = tileram_attrib_D[5];
|
||||
|
||||
//Data output to CPU
|
||||
assign DBo = (ram_cs & ~NRD) ? ram_Dout:
|
||||
(zram0_cs & ~NRD) ? zram0_Dout:
|
||||
(zram1_cs & ~NRD) ? zram1_Dout:
|
||||
(zram2_cs & ~NRD) ? zram2_Dout:
|
||||
(tile_attrib_cs & ~NRD) ? tileram_attrib_Dout:
|
||||
(tile_cs & ~NRD) ? tileram_Dout:
|
||||
(tile1_attrib_cs & ~NRD) ? tileram1_attrib_Dout:
|
||||
(tile1_cs & ~NRD) ? tileram1_Dout:
|
||||
(spriteram_cs & ~NRD) ? spriteram_Dout:
|
||||
8'hFF;
|
||||
|
||||
//------------------------------------------------------- Clock division -------------------------------------------------------//
|
||||
|
||||
//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz
|
||||
reg [3:0] div = 4'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
div <= div + 4'd1;
|
||||
end
|
||||
reg [2:0] n_div = 3'd0;
|
||||
always_ff @(negedge CK49) begin
|
||||
n_div <= n_div + 3'd1;
|
||||
end
|
||||
wire cen_6m = !div[2:0];
|
||||
wire n_cen_6m = !n_div;
|
||||
wire cen_3m = !div;
|
||||
assign NCK2 = div[2];
|
||||
assign H1O = div[3];
|
||||
|
||||
//The MC6809E requires two identical clocks with a 90-degree offset - assign these here
|
||||
reg mc6809e_E = 0;
|
||||
reg mc6809e_Q = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
reg [1:0] clk_phase = 0;
|
||||
if(cen_6m) begin
|
||||
clk_phase <= clk_phase + 1'd1;
|
||||
case(clk_phase)
|
||||
2'b00: mc6809e_E <= 0;
|
||||
2'b01: mc6809e_Q <= 1;
|
||||
2'b10: mc6809e_E <= 1;
|
||||
2'b11: mc6809e_Q <= 0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
assign NCPQ = mc6809e_Q;
|
||||
assign NCPE = mc6809e_E;
|
||||
|
||||
//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here
|
||||
assign NEQ = NCPE & NCPQ;
|
||||
|
||||
//-------------------------------------------------------- Video timings -------------------------------------------------------//
|
||||
|
||||
//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both
|
||||
//counters as 9-bit registers.
|
||||
reg [8:0] h_cnt = 9'd0;
|
||||
reg [8:0] v_cnt = 9'd0;
|
||||
|
||||
//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter
|
||||
//rolls over
|
||||
reg hblank = 0;
|
||||
reg vblank = 0;
|
||||
reg vblank_irq_en = 0;
|
||||
reg frame_odd_even = 0;
|
||||
//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical
|
||||
//counter if a bootleg Jackal ROM set is loaded
|
||||
reg [8:0] vcnt_end = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
if(BTLG == 2'b01)
|
||||
vcnt_end <= 9'd252;
|
||||
else if(BTLG == 2'b10)
|
||||
vcnt_end <= 9'd271;
|
||||
else
|
||||
vcnt_end <= 9'd261;
|
||||
end
|
||||
end
|
||||
//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded
|
||||
reg [8:0] hsync_start = 9'd0;
|
||||
reg [8:0] hsync_end = 9'd0;
|
||||
reg [8:0] vsync_start = 9'd0;
|
||||
reg [8:0] vsync_end = 9'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(BTLG == 2'b01) begin
|
||||
hsync_start <= HCTR[3] ? 9'd287 : 9'd295;
|
||||
hsync_end <= HCTR[3] ? 9'd318 : 9'd326;
|
||||
vsync_start <= 9'd244;
|
||||
vsync_end <= 9'd251;
|
||||
end
|
||||
else if(BTLG == 2'b10) begin
|
||||
hsync_start <= HCTR[3] ? 9'd290 : 9'd310;
|
||||
hsync_end <= HCTR[3] ? 9'd321 : 9'd341;
|
||||
vsync_start <= 9'd255;
|
||||
vsync_end <= 9'd262;
|
||||
end
|
||||
else begin
|
||||
hsync_start <= HCTR[3] ? 9'd288 : 9'd296;
|
||||
hsync_end <= HCTR[3] ? 9'd319 : 9'd327;
|
||||
vsync_start <= 9'd254;
|
||||
vsync_end <= 9'd261;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
case(h_cnt)
|
||||
0: begin
|
||||
vblank_irq_en <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
//HBlank ends two lines earlier than normal on bootleg Jackal PCBs
|
||||
11: begin
|
||||
if(BTLG == 2'b01)
|
||||
hblank <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
13: begin
|
||||
if(BTLG != 2'b01)
|
||||
hblank <= 0;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
//Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded
|
||||
251: begin
|
||||
if(BTLG == 2'b01)
|
||||
hblank <= 1;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
253: begin
|
||||
if(BTLG != 2'b01)
|
||||
hblank <= 1;
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
end
|
||||
383: begin
|
||||
h_cnt <= 0;
|
||||
case(v_cnt)
|
||||
15: begin
|
||||
vblank <= 0;
|
||||
v_cnt <= v_cnt + 9'd1;
|
||||
end
|
||||
239: begin
|
||||
vblank <= 1;
|
||||
vblank_irq_en <= 1;
|
||||
frame_odd_even <= ~frame_odd_even;
|
||||
v_cnt <= v_cnt + 9'd1;
|
||||
end
|
||||
vcnt_end: begin
|
||||
v_cnt <= 9'd0;
|
||||
end
|
||||
default: v_cnt <= v_cnt + 9'd1;
|
||||
endcase
|
||||
end
|
||||
default: h_cnt <= h_cnt + 9'd1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//Output HBlank and VBlank (both active high)
|
||||
assign HBLK = hblank;
|
||||
assign VBLK = vblank;
|
||||
|
||||
//Generate horizontal sync and vertical sync (both active low)
|
||||
assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]):
|
||||
~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]);
|
||||
assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR);
|
||||
assign NCSY = NHSY ^ NVSY;
|
||||
|
||||
//------------------------------------------------------------- IRQs -----------------------------------------------------------//
|
||||
|
||||
//IRQ (triggers every VBlank)
|
||||
reg vblank_irq = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
vblank_irq <= 1;
|
||||
else if(cen_6m) begin
|
||||
if(!irq_mask)
|
||||
vblank_irq <= 1;
|
||||
else if(vblank_irq_en)
|
||||
vblank_irq <= 0;
|
||||
end
|
||||
end
|
||||
assign NIRQ = vblank_irq;
|
||||
|
||||
//NMI (triggers every 64 scanlines starting from scanline 48)
|
||||
reg nmi = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
nmi <= 1;
|
||||
else if(cen_3m) begin
|
||||
if(!nmi_mask)
|
||||
nmi <= 1;
|
||||
else if((v_cnt[7:0] + 9'd16) % 9'd64 == 0)
|
||||
nmi <= 0;
|
||||
end
|
||||
end
|
||||
assign NNMI = nmi;
|
||||
|
||||
//FIRQ (triggers every second VBlank)
|
||||
reg firq = 1;
|
||||
always_ff @(posedge CK49 or negedge NEXR) begin
|
||||
if(!NEXR)
|
||||
firq <= 1;
|
||||
else if(cen_3m) begin
|
||||
if(!firq_mask)
|
||||
firq <= 1;
|
||||
else if(!frame_odd_even && v_cnt == 9'd239)
|
||||
firq <= 0;
|
||||
end
|
||||
end
|
||||
assign NFIR = firq;
|
||||
|
||||
//----------------------------------------------------- Internal registers -----------------------------------------------------//
|
||||
|
||||
//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code:
|
||||
/*
|
||||
control registers
|
||||
000: scroll y
|
||||
001: scroll x (low 8 bits)
|
||||
002: -------x scroll x (high bit)
|
||||
----xxx- row/colscroll control
|
||||
000 = solid scroll (finalizr, ddribble bg)
|
||||
100 = solid scroll (jackal)
|
||||
001 = ? (ddribble fg)
|
||||
011 = colscroll (jackal high scores)
|
||||
101 = rowscroll (ironhors, jackal map)
|
||||
003: ------xx high bits of the tile code
|
||||
-----x-- unknown (finalizr)
|
||||
----x--- selects sprite buffer (and makes a copy to a private buffer?)
|
||||
--x----- unknown (ironhors)
|
||||
-x------ unknown (ironhors)
|
||||
x------- unknown (ironhors, jackal)
|
||||
004: -------x nmi enable
|
||||
------x- irq enable
|
||||
-----x-- firq enable
|
||||
----x--- flip screen
|
||||
*/
|
||||
|
||||
wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0);
|
||||
|
||||
reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl;
|
||||
reg nmi_mask = 0;
|
||||
reg irq_mask = 0;
|
||||
reg firq_mask = 0;
|
||||
reg flipscreen = 0;
|
||||
|
||||
//Write to the appropriate register
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_3m) begin
|
||||
if(regs_cs && NRD)
|
||||
case(A[2:0])
|
||||
3'b000: scroll_y <= DBi;
|
||||
3'b001: scroll_x <= DBi;
|
||||
3'b010: scroll_ctrl <= DBi;
|
||||
3'b011: tile_ctrl <= DBi;
|
||||
3'b100: begin
|
||||
nmi_mask <= DBi[0];
|
||||
irq_mask <= DBi[1];
|
||||
firq_mask <= DBi[2];
|
||||
flipscreen <= DBi[3];
|
||||
end
|
||||
default;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//--------------------------------------------------------- Unknown RAM --------------------------------------------------------//
|
||||
|
||||
wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F);
|
||||
|
||||
wire [7:0] ram_Dout;
|
||||
spram #(8, 5) RAM
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(ram_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(ram_Dout)
|
||||
);
|
||||
|
||||
//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------//
|
||||
|
||||
wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F);
|
||||
wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F);
|
||||
wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF);
|
||||
|
||||
//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to
|
||||
//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll,
|
||||
//otherwise don't address it
|
||||
wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]:
|
||||
(scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]:
|
||||
5'h00;
|
||||
wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout;
|
||||
dpram_dc #(.widthad_a(5)) ZRAM0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[4:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(zram0_Dout),
|
||||
.wren_a(zram0_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(zram_A),
|
||||
.q_b(zram0_D)
|
||||
);
|
||||
spram #(8, 5) ZRAM1
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(zram1_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(zram1_Dout)
|
||||
);
|
||||
spram #(8, 5) ZRAM2
|
||||
(
|
||||
.clk(CK49),
|
||||
.we(zram2_cs & NRD),
|
||||
.addr(A[4:0]),
|
||||
.data(DBi),
|
||||
.q(zram2_Dout)
|
||||
);
|
||||
|
||||
//------------------------------------------------------------ VRAM ------------------------------------------------------------//
|
||||
|
||||
//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers),
|
||||
//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its
|
||||
//constituent components.
|
||||
wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000);
|
||||
wire tile_cs = ~NXCS & (A[13:10] == 4'b1001);
|
||||
wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010);
|
||||
wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011);
|
||||
wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11);
|
||||
|
||||
wire [7:0] tileram_attrib_Dout, tileram_Dout, tileram1_attrib_Dout, tileram1_Dout, spriteram_Dout;
|
||||
wire [7:0] tileram_attrib_D, tileram_D, tileram1_attrib_D, tileram1_D, spriteram_D;
|
||||
//Tilemap layer 0
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram_attrib_Dout),
|
||||
.wren_a(tile_attrib_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram_attrib_D)
|
||||
);
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILECODE0
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram_Dout),
|
||||
.wren_a(tile_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram_D)
|
||||
);
|
||||
//Tilemap layer 1
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram1_attrib_Dout),
|
||||
.wren_a(tile1_attrib_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram1_attrib_D)
|
||||
);
|
||||
dpram_dc #(.widthad_a(10)) VRAM_TILECODE1
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(A[9:0]),
|
||||
.data_a(DBi),
|
||||
.q_a(tileram1_Dout),
|
||||
.wren_a(tile1_cs & NRD),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(vram_A),
|
||||
.q_b(tileram1_D)
|
||||
);
|
||||
|
||||
// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM)
|
||||
wire [11:0] VRAM_SPR_AD = hs_access ? hs_address : A[11:0];
|
||||
wire [7:0] VRAM_SPR_DIN = hs_access ? hs_data_in : DBi;
|
||||
wire VRAM_SPR_WE = hs_access ? hs_write : (spriteram_cs & NRD);
|
||||
wire [7:0] VRAM_SPR_DOUT;
|
||||
|
||||
assign hs_data_out = hs_access ? VRAM_SPR_DOUT : 8'h00;
|
||||
assign spriteram_Dout = hs_access ? 8'h00 : VRAM_SPR_DOUT;
|
||||
|
||||
//Sprites
|
||||
dpram_dc #(.widthad_a(12)) VRAM_SPR
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(VRAM_SPR_AD),
|
||||
.data_a(VRAM_SPR_DIN),
|
||||
.q_a(VRAM_SPR_DOUT),
|
||||
.wren_a(VRAM_SPR_WE),
|
||||
|
||||
.clock_b(~CK49),
|
||||
.address_b(spriteram_A),
|
||||
.q_b(spriteram_D)
|
||||
);
|
||||
|
||||
//-------------------------------------------------------- Tilemap layer -------------------------------------------------------//
|
||||
|
||||
//TODO: The current implementation only handles one of the 005885's two tilemap layers - add logic to handle both layers
|
||||
|
||||
//XOR horizontal and vertical counter bits with flipscreen bit
|
||||
wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}};
|
||||
wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}};
|
||||
|
||||
//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on
|
||||
//whether row scroll or column scroll is enabled
|
||||
wire [8:0] row_scroll = (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x};
|
||||
wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y;
|
||||
wire [8:0] tilemap_hpos = hcnt_x + row_scroll;
|
||||
wire [8:0] tilemap_vpos = vcnt_x + col_scroll;
|
||||
|
||||
//Address output to tilemap section of VRAM
|
||||
wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]};
|
||||
|
||||
//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code
|
||||
wire [9:0] tile_index = {tileram_attrib_D[7:6], tileram_D};
|
||||
|
||||
//XOR tile H/V flip bits with the flipscreen bit
|
||||
wire tile_hflip = tileram_attrib_D[4];
|
||||
wire tile_vflip = tileram_attrib_D[5];
|
||||
|
||||
//Address output to graphics ROMs
|
||||
assign R = {tile_ctrl[1:0], tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2] ^ tile_hflip)};
|
||||
|
||||
//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position
|
||||
//bit 1
|
||||
reg [15:0] RD_lat = 16'd0;
|
||||
reg [3:0] tile_color = 4'd0;
|
||||
reg tile_hflip_lat = 0;
|
||||
reg old_tilehpos1;
|
||||
always_ff @(posedge CK49) begin
|
||||
old_tilehpos1 <= tilemap_hpos[1];
|
||||
if(old_tilehpos1 && !tilemap_hpos[1]) begin
|
||||
tile_color <= tileram_attrib_D[3:0];
|
||||
RD_lat <= flipscreen ? {RDL, RDU} : {RDU, RDL};
|
||||
tile_hflip_lat <= tileram_attrib_D[4];
|
||||
end
|
||||
end
|
||||
|
||||
//Multiplex graphics ROM data down from 16 bits to 8 using bit 1 of the horizontal position
|
||||
wire [7:0] RD = (tilemap_hpos[1] ^ tile_hflip_lat) ? RD_lat[7:0] : RD_lat[15:8];
|
||||
|
||||
//Further multiplex graphics ROM data down from 8 bits to 4 using bit 0 of the horizontal position
|
||||
wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_lat) ? RD[3:0] : RD[7:4];
|
||||
|
||||
//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register
|
||||
wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5];
|
||||
reg tilemap_en = 0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(n_cen_6m) begin
|
||||
tilemap_en <= tile_sel;
|
||||
end
|
||||
end
|
||||
|
||||
//Address output to tilemap LUT PROM
|
||||
assign VCF = tile_color;
|
||||
assign VCB = tile_pixel;
|
||||
|
||||
//Shift the tilemap layer left by two lines when the screen is flipped
|
||||
reg [7:0] tilemap_shift;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
tilemap_shift <= {VCD, tilemap_shift[7:4]};
|
||||
end
|
||||
wire [3:0] tilemap_D = flipscreen ? tilemap_shift[3:0] : VCD;
|
||||
|
||||
//-------------------------------------------------------- Sprite layer --------------------------------------------------------//
|
||||
|
||||
//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format
|
||||
reg [8:0] sprite_hpos = 9'd0;
|
||||
reg [8:0] sprite_vpos = 9'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
sprite_hpos <= h_cnt;
|
||||
//If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the
|
||||
//bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a
|
||||
//vertical offset of 66 lines (65 lines when flipped)
|
||||
if(BTLG == 2'b10)
|
||||
if(flipscreen)
|
||||
sprite_vpos <= v_cnt + 9'd66;
|
||||
else
|
||||
sprite_vpos <= v_cnt + 9'd65;
|
||||
else
|
||||
if(flipscreen)
|
||||
sprite_vpos <= v_cnt + 9'd65;
|
||||
else
|
||||
sprite_vpos <= v_cnt + 9'd66;
|
||||
end
|
||||
end
|
||||
|
||||
//Sprite state machine
|
||||
reg [8:0] sprite_index;
|
||||
reg [2:0] sprite_offset;
|
||||
reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3, sprite_attrib4;
|
||||
reg [2:0] sprite_fsm_state;
|
||||
reg [5:0] sprite_width;
|
||||
reg [15:0] sprite_rom_addr;
|
||||
//Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit
|
||||
//to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of
|
||||
//5, otherwise)
|
||||
wire [8:0] sprite_limit = (BTLG == 2'b10) ? 9'd155 : 9'd485;
|
||||
reg [3:0] waitstate;
|
||||
|
||||
always_ff @(posedge CK49) begin
|
||||
//Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0
|
||||
//Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse
|
||||
//ROM sets to prevent graphical garbage from occurring on the top-most line
|
||||
if(sprite_hpos == 9'd0 || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin
|
||||
sprite_width <= 0;
|
||||
sprite_index <= 0;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_fsm_state <= 1;
|
||||
waitstate <= 0;
|
||||
end
|
||||
else
|
||||
case(sprite_fsm_state)
|
||||
0: /* empty */ ;
|
||||
1: begin
|
||||
waitstate <= 0;
|
||||
if(sprite_index > sprite_limit)
|
||||
sprite_fsm_state <= 0;
|
||||
else begin
|
||||
sprite_attrib4 <= spriteram_D;
|
||||
sprite_offset <= 3'd3;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
end
|
||||
2: begin
|
||||
sprite_attrib3 <= spriteram_D;
|
||||
sprite_offset <= 3'd2;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
3: begin
|
||||
//Skip the current sprite if it's inactive, otherwise obtain the sprite Y attribute and continue
|
||||
//scanning out the rest of the sprite attributes
|
||||
if(sprite_active) begin
|
||||
sprite_attrib2 <= spriteram_D;
|
||||
sprite_offset <= 3'd1;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
else begin
|
||||
sprite_index <= sprite_index + 9'd5;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_fsm_state <= 3'd1;
|
||||
end
|
||||
end
|
||||
4: begin
|
||||
sprite_attrib1 <= spriteram_D;
|
||||
sprite_offset <= 3'd0;
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
end
|
||||
5: begin
|
||||
sprite_attrib0 <= spriteram_D;
|
||||
sprite_offset <= 3'd4;
|
||||
sprite_index <= sprite_index + 9'd5;
|
||||
case(sprite_size)
|
||||
3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen);
|
||||
3'b100: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
|
||||
default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen);
|
||||
endcase
|
||||
sprite_fsm_state <= sprite_fsm_state + 3'd1;
|
||||
waitstate <= 4'd14;
|
||||
end
|
||||
6: if (waitstate == 0) begin
|
||||
//Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails
|
||||
//to render the last line of sprites), otherwise write sprites as normal
|
||||
if(BTLG == 2'b01 && !flipscreen)
|
||||
if(sprite_width == 6'b111110)
|
||||
sprite_width <= sprite_width + 6'd2;
|
||||
else
|
||||
sprite_width <= sprite_width + 6'd1;
|
||||
else
|
||||
sprite_width <= sprite_width + 6'd1;
|
||||
|
||||
if (sprite_width[1:0] == 2'b11) waitstate <= 4'd14;
|
||||
sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1;
|
||||
end
|
||||
else begin
|
||||
sprite_rom_addr <= {sprite_code_sized, ly[2:0], lx[2]};
|
||||
waitstate <= waitstate - 1'd1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
//Obtain sprite X position from sprite attribute byte 3 - append a 9th bit based on the state of bit 1 sprite attribute byte 4,
|
||||
//bit 0 of sprite attribute byte 4 if high or the AND of the upper 5 bits of the horizontal position if low
|
||||
reg sprite_x8;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(sprite_attrib4[1])
|
||||
sprite_x8 <= sprite_attrib4[0];
|
||||
else
|
||||
sprite_x8 <= &sprite_attrib3[7:3];
|
||||
end
|
||||
wire [8:0] sprite_x = {sprite_x8 ^ flipscreen, sprite_attrib3 ^ {8{flipscreen}}};
|
||||
|
||||
//If the sprite state machine is in state 3, obtain sprite Y position directly from sprite RAM, otherwise obtain it from
|
||||
//sprite attribute byte 2
|
||||
wire [7:0] sprite_y = (sprite_fsm_state == 3'd3) ? spriteram_D : sprite_attrib2;
|
||||
|
||||
//Sprite flip attributes are stored in bits 5 (horizontal) and 6 (vertical) of sprite attribute byte 4
|
||||
//Also XOR these attributes with the flipscreen bit (XOR with the inverse for vertical flip)
|
||||
wire sprite_hflip = sprite_attrib4[5] ^ flipscreen;
|
||||
wire sprite_vflip = sprite_attrib4[6] ^ ~flipscreen;
|
||||
|
||||
//Sprite code is sprite attribute byte 0 sandwiched between bits 1 and 0 and bits 3 and 2 of sprite attribute byte 1
|
||||
wire [11:0] sprite_code = {sprite_attrib1[1:0], sprite_fsm_state == 5 ? spriteram_D : sprite_attrib0, sprite_attrib1[3:2]};
|
||||
|
||||
//Sprite color is the upper 4 bits of sprite attribute byte 1
|
||||
wire [3:0] sprite_color = sprite_attrib1[7:4];
|
||||
|
||||
//The 005885 supports 5 different sprite sizes: 8x8, 8x16, 16x8, 16x16 and 32x32. Retrieve this attribute from bits [4:2] of
|
||||
//sprite attribute byte 4
|
||||
wire [2:0] sprite_size = sprite_attrib4[4:2];
|
||||
|
||||
//Adjust sprite code based on sprite size
|
||||
wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16
|
||||
sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8
|
||||
sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16
|
||||
sprite_size == 3'b011 ? sprite_code: //8x8
|
||||
{sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32
|
||||
|
||||
//Subtract vertical sprite position from sprite Y parameter to obtain sprite height
|
||||
wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos;
|
||||
|
||||
//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall
|
||||
reg sprite_active;
|
||||
always @(*) begin
|
||||
case(sprite_size)
|
||||
3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen);
|
||||
3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
|
||||
3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen);
|
||||
3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen)
|
||||
& (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen);
|
||||
3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
|
||||
default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen);
|
||||
endcase
|
||||
end
|
||||
|
||||
wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}};
|
||||
wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}};
|
||||
|
||||
//Assign address outputs to sprite ROMs
|
||||
assign S = sprite_rom_addr;
|
||||
|
||||
|
||||
//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position
|
||||
wire [7:0] SD = lx[1] ? SDL : SDU;
|
||||
|
||||
//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position
|
||||
wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4];
|
||||
|
||||
//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3
|
||||
wire [8:0] sprite_address = (sprite_index + sprite_offset);
|
||||
reg sprite_bank = 0;
|
||||
reg old_vsync;
|
||||
//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes
|
||||
//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded
|
||||
always_ff @(posedge CK49) begin
|
||||
old_vsync <= NVSY;
|
||||
if(!NEXR)
|
||||
sprite_bank <= 0;
|
||||
else if(!old_vsync && NVSY)
|
||||
sprite_bank <= tile_ctrl[3];
|
||||
end
|
||||
wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address};
|
||||
|
||||
//Address output to sprite LUT PROM
|
||||
assign OCF = sprite_color;
|
||||
assign OCB = sprite_pixel;
|
||||
|
||||
//----------------------------------------------------- Sprite line buffer -----------------------------------------------------//
|
||||
|
||||
//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the
|
||||
//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation.
|
||||
|
||||
//Enable writing to sprite line buffer when bit 5 of the sprite width is 1
|
||||
wire wre = sprite_width[5];
|
||||
|
||||
//Set sprite line buffer bank as bit 0 of the sprite vertical position
|
||||
wire sprite_lbuff_bank = sprite_vpos[0];
|
||||
|
||||
//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size:
|
||||
//32 pixels wide: bits [4:0]
|
||||
//16 pixels wide: bits [3:0]
|
||||
//8 pixels wide: bits [2:0]
|
||||
//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites
|
||||
reg [4:0] final_sprite_width;
|
||||
always @(*) begin
|
||||
case(sprite_size)
|
||||
3'b000: final_sprite_width <= {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
|
||||
3'b001: final_sprite_width <= {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]};
|
||||
3'b010: final_sprite_width <= {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
|
||||
3'b011: final_sprite_width <= {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]};
|
||||
3'b100: final_sprite_width <= sprite_width[4:0];
|
||||
default: final_sprite_width <= sprite_width[4:0];
|
||||
endcase
|
||||
end
|
||||
wire [8:0] wpx = sprite_x + final_sprite_width;
|
||||
|
||||
//Generate sprite line buffer write addresses
|
||||
reg [9:0] lbuff_A;
|
||||
reg lbuff_we;
|
||||
always_ff @(posedge CK49) begin
|
||||
lbuff_A <= {~sprite_lbuff_bank, wpx};
|
||||
lbuff_we <= wre & (waitstate == 0);
|
||||
//lbuff_Din <= OCD;
|
||||
end
|
||||
|
||||
//Latch sprite LUT PROM data on the falling edge of the main clock
|
||||
wire [3:0] lbuff_Din = OCD;
|
||||
//always_ff @(negedge CK49) begin
|
||||
// lbuff_Din <= OCD;
|
||||
//end
|
||||
|
||||
//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen
|
||||
//is flipped)
|
||||
reg [9:0] radr0 = 10'd0;
|
||||
reg [9:0] radr1 = 10'd1;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : sprite_hpos};
|
||||
end
|
||||
|
||||
//Sprite line buffer
|
||||
wire [3:0] lbuff_Dout;
|
||||
dpram_dc #(.widthad_a(10)) LBUFF
|
||||
(
|
||||
.clock_a(CK49),
|
||||
.address_a(lbuff_A),
|
||||
.data_a({4'd0, lbuff_Din}),
|
||||
.wren_a(lbuff_we & (lbuff_Din != 0)),
|
||||
|
||||
.clock_b(CK49),
|
||||
.address_b(radr0),
|
||||
.data_b(8'h0),
|
||||
.wren_b(radr0 == radr1),
|
||||
.q_b({4'bZZZZ, lbuff_Dout})
|
||||
);
|
||||
|
||||
//Latch sprite data from the sprite line buffer
|
||||
wire lbuff_read_en = (div[2:0] == 3'b100);
|
||||
reg [3:0] lbuff_read = 4'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(lbuff_read_en) begin
|
||||
if(radr0 != radr1)
|
||||
lbuff_read <= lbuff_Dout;
|
||||
radr1 <= radr0;
|
||||
end
|
||||
end
|
||||
|
||||
//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped)
|
||||
reg [7:0] sprite_dly = 8'd0;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m) begin
|
||||
if(BTLG == 2'b01 && flipscreen)
|
||||
sprite_dly <= {4'd0, lbuff_read};
|
||||
else
|
||||
sprite_dly <= {lbuff_read, sprite_dly[7:4]};
|
||||
end
|
||||
end
|
||||
//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here
|
||||
wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0];
|
||||
|
||||
//--------------------------------------------------------- Color mixer --------------------------------------------------------//
|
||||
|
||||
//Multiplex tile and sprite data, then output the final result
|
||||
wire tile_sprite_sel = (tilemap_en | ~(|sprite_D));
|
||||
wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D;
|
||||
|
||||
//Latch and output pixel data
|
||||
reg [4:0] pixel_D;
|
||||
always_ff @(posedge CK49) begin
|
||||
if(cen_6m)
|
||||
pixel_D <= {tile_sprite_sel, tile_sprite_D};
|
||||
end
|
||||
assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) ||
|
||||
(BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D;
|
||||
//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set
|
||||
//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse
|
||||
//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of
|
||||
//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area
|
||||
|
||||
endmodule
|
||||
149
Arcade_MiST/Konami Jackal/rtl/custom/k007327.sv
Normal file
149
Arcade_MiST/Konami Jackal/rtl/custom/k007327.sv
Normal file
@@ -0,0 +1,149 @@
|
||||
//============================================================================
|
||||
//
|
||||
// SystemVerilog implementation of the Konami 007327 custom palette RAM +
|
||||
// video DAC module
|
||||
// Copyright (C) 2021 Ace & SnakeGrunger
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//Module pinout:
|
||||
/* _______________________
|
||||
_| |_
|
||||
CCS |_|1 40|_| CLK
|
||||
_| |_
|
||||
CWR |_|2 39|_| BLK
|
||||
_| |_
|
||||
D[7] |_|3 38|_| RW
|
||||
_| |_
|
||||
D[6] |_|4 37|_| A[0]
|
||||
_| |_
|
||||
D[5] |_|5 36|_| NA0
|
||||
_| |_
|
||||
D[4] |_|6 35|_| A[1]
|
||||
_| |_
|
||||
D[3] |_|7 34|_| A[2]
|
||||
_| |_
|
||||
D[2] |_|8 33|_| A[3]
|
||||
_| |_
|
||||
D[1] |_|9 32|_| A[4]
|
||||
_| |_
|
||||
D[0] |_|10 31|_| A[5]
|
||||
_| |_
|
||||
GND |_|11 30|_| A[6]
|
||||
_| |_
|
||||
VCC |_|12 29|_| A[7]
|
||||
_| |_
|
||||
B |_|13 28|_| CB[0]
|
||||
_| |_
|
||||
G |_|14 27|_| CB[1]
|
||||
_| |_
|
||||
R |_|15 26|_| CB[2]
|
||||
_| |_
|
||||
GND |_|16 25|_| CB[3]
|
||||
_| |_
|
||||
RA[8] |_|17 24|_| CB[4]
|
||||
_| |_
|
||||
RA[9] |_|18 23|_| CB[5]
|
||||
_| |_
|
||||
RA[10] |_|19 22|_| CB[6]
|
||||
_| |_
|
||||
RA[11] |_|20 21|_| SEL
|
||||
|_______________________|
|
||||
*/
|
||||
|
||||
module k007327
|
||||
(
|
||||
input CLK, //Clock input
|
||||
input CEN, //Clock enable input (set to 1 if replacing an actual 007327)
|
||||
input [11:8] RA, //External address inputs to palette RAM's upper 4 address bits
|
||||
input [7:0] A, //Address bus from CPU
|
||||
input NA0, //Inverse of address bit A0
|
||||
input [6:0] CB, //7-bit Color bus input
|
||||
input [7:0] Di, //CPU data input
|
||||
input RW, //Read/write input
|
||||
input SEL, //Color/CPU data select input
|
||||
input CCS, //Chip select input (active low)
|
||||
input CWR, //Color write enable (active low)
|
||||
input BLK, //Blank input
|
||||
output [4:0] R, G, B, //15-bit RGB color output, 5 bits per color
|
||||
output [7:0] Do //CPU data output
|
||||
);
|
||||
|
||||
//Multiplex address lines A[6:0] for palette RAM
|
||||
wire [10:0] paletteram_A;
|
||||
assign paletteram_A[10:7] = RA[11:8];
|
||||
assign paletteram_A[6:0] = SEL ? CB : A[7:1];
|
||||
|
||||
//Generate read and write enable signals for palette RAM
|
||||
wire n_paletteram0_cs = (CCS | NA0);
|
||||
wire n_paletteram1_cs = (CCS | A[0]);
|
||||
wire n_paletteram0_wr = (n_paletteram0_cs | CWR);
|
||||
wire n_paletteram1_wr = (n_paletteram1_cs | CWR);
|
||||
|
||||
//Palette RAM
|
||||
wire [15:0] paletteram_D;
|
||||
spram #(8, 11) PALRAM_L
|
||||
(
|
||||
.clk(CLK),
|
||||
.addr(paletteram_A),
|
||||
.data(Di),
|
||||
.q(paletteram_D[7:0]),
|
||||
.we(~n_paletteram0_wr & RW)
|
||||
);
|
||||
spram #(8, 11) PALRAM_H
|
||||
(
|
||||
.clk(CLK),
|
||||
.addr(paletteram_A),
|
||||
.data(Di),
|
||||
.q(paletteram_D[15:8]),
|
||||
.we(~n_paletteram1_wr & RW)
|
||||
);
|
||||
|
||||
//Output palette RAM data to CPU
|
||||
assign Do = (~n_paletteram0_cs & ~RW) ? paletteram_D[7:0]:
|
||||
(~n_paletteram1_cs & ~RW) ? paletteram_D[15:8]:
|
||||
8'hFF;
|
||||
|
||||
//Latch blank input at every positive edge of the incoming clock
|
||||
reg blank = 1;
|
||||
always_ff @(posedge CLK) begin
|
||||
if(CEN)
|
||||
blank <= BLK;
|
||||
end
|
||||
|
||||
//Latch pixel data
|
||||
reg [4:0] pixel_red = 0;
|
||||
reg [4:0] pixel_green = 0;
|
||||
reg [4:0] pixel_blue = 0;
|
||||
always_ff @(posedge CLK) begin
|
||||
if(CEN) begin
|
||||
pixel_red <= paletteram_D[12:8];
|
||||
pixel_green <= {paletteram_D[1:0], paletteram_D[15:13]};
|
||||
pixel_blue <= paletteram_D[6:2];
|
||||
end
|
||||
end
|
||||
|
||||
//Generate final RGB output
|
||||
assign R = blank ? pixel_red : 5'd0;
|
||||
assign G = blank ? pixel_green : 5'd0;
|
||||
assign B = blank ? pixel_blue : 5'd0;
|
||||
|
||||
endmodule
|
||||
92
Arcade_MiST/Konami Jackal/rtl/custom/k007343.sv
Normal file
92
Arcade_MiST/Konami Jackal/rtl/custom/k007343.sv
Normal file
@@ -0,0 +1,92 @@
|
||||
//============================================================================
|
||||
//
|
||||
// SystemVerilog implementation of the Konami K007343, a PAL16L8 used as part
|
||||
// of the address decoding hardware on Jackal/Top Gunner arcade PCBs
|
||||
// Converted from dump available at the PLD Archive
|
||||
// http://wiki.pldarchive.co.uk/index.php?title=Jackal
|
||||
// Copyright (C) 2021 Ace
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
//Chip pinout:
|
||||
/* _____________
|
||||
_| |_
|
||||
A13 |_|1 20|_| VCC
|
||||
_| |_
|
||||
A12 |_|2 19|_| MGCS
|
||||
_| |_
|
||||
A11 |_|3 18|_| NC
|
||||
_| |_
|
||||
A10 |_|4 17|_| CRCS
|
||||
_| |_
|
||||
A8_9 |_|5 16|_| IOCS
|
||||
_| |_
|
||||
A7 |_|6 15|_| GATEB
|
||||
_| |_
|
||||
A6 |_|7 14|_| WR
|
||||
_| |_
|
||||
A5 |_|8 13|_| OBJB
|
||||
_| |_
|
||||
A4 |_|9 12|_| SGCS
|
||||
_| |_
|
||||
GND |_|10 11|_| GATECS
|
||||
|_____________|
|
||||
*/
|
||||
|
||||
module k007343
|
||||
(
|
||||
input A4,
|
||||
input A5,
|
||||
input A6,
|
||||
input A7,
|
||||
input A8_9,
|
||||
input A10,
|
||||
input A11,
|
||||
input A12,
|
||||
input A13,
|
||||
input WR,
|
||||
input OBJB,
|
||||
input GATEB,
|
||||
input GATECS,
|
||||
output MGCS,
|
||||
output SGCS,
|
||||
output IOCS,
|
||||
output CRCS
|
||||
);
|
||||
|
||||
wire o18 = ~(A13 & A12 & ~A10 & ~GATECS |
|
||||
A13 & A12 & ~A8_9 & ~GATECS);
|
||||
|
||||
assign MGCS = ~(~GATECS & ~OBJB & ~GATEB & IOCS & CRCS |
|
||||
~GATECS & ~GATEB & IOCS & CRCS & o18);
|
||||
assign CRCS = ~(~A13 & A12 & ~GATECS |
|
||||
~A13 & ~A12 & A11 & ~GATECS |
|
||||
~A13 & ~A12 & A8_9 & ~GATECS |
|
||||
~A13 & ~A12 & A7 & ~GATECS |
|
||||
~A13 & ~A12 & A6 & A5 & ~GATECS |
|
||||
~A13 & ~A12 & A10 & ~GATECS);
|
||||
assign IOCS = ~(~A13 & ~A12 & ~A11 & ~A10 & ~A8_9 & ~A7 & ~A6 & ~A5 & A4 & ~GATECS);
|
||||
assign SGCS = ~(~GATECS & GATEB & IOCS & CRCS |
|
||||
~GATECS & OBJB & ~WR & IOCS & CRCS |
|
||||
~GATECS & OBJB & IOCS & CRCS & ~o18 |
|
||||
~GATECS & ~WR & IOCS & CRCS & o18);
|
||||
|
||||
endmodule
|
||||
136
Arcade_MiST/Konami Jackal/rtl/dpram_dc.vhd
Normal file
136
Arcade_MiST/Konami Jackal/rtl/dpram_dc.vhd
Normal file
@@ -0,0 +1,136 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY dpram_dc IS
|
||||
GENERIC
|
||||
(
|
||||
init_file : string := " ";
|
||||
widthad_a : natural;
|
||||
width_a : natural := 8;
|
||||
outdata_reg_a : string := "UNREGISTERED";
|
||||
outdata_reg_b : string := "UNREGISTERED"
|
||||
);
|
||||
PORT
|
||||
(
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0');
|
||||
clock_a : IN STD_LOGIC ;
|
||||
clock_b : IN STD_LOGIC ;
|
||||
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
|
||||
data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
|
||||
wren_a : IN STD_LOGIC := '0';
|
||||
wren_b : IN STD_LOGIC := '0';
|
||||
byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
|
||||
byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END dpram_dc;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram_dc IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
|
||||
|
||||
|
||||
COMPONENT altsyncram
|
||||
GENERIC (
|
||||
address_reg_b : STRING;
|
||||
clock_enable_input_a : STRING;
|
||||
clock_enable_input_b : STRING;
|
||||
clock_enable_output_a : STRING;
|
||||
clock_enable_output_b : STRING;
|
||||
indata_reg_b : STRING;
|
||||
init_file : STRING;
|
||||
intended_device_family : STRING;
|
||||
lpm_type : STRING;
|
||||
numwords_a : NATURAL;
|
||||
numwords_b : NATURAL;
|
||||
operation_mode : STRING;
|
||||
outdata_aclr_a : STRING;
|
||||
outdata_aclr_b : STRING;
|
||||
outdata_reg_a : STRING;
|
||||
outdata_reg_b : STRING;
|
||||
power_up_uninitialized : STRING;
|
||||
read_during_write_mode_port_a : STRING;
|
||||
read_during_write_mode_port_b : STRING;
|
||||
widthad_a : NATURAL;
|
||||
widthad_b : NATURAL;
|
||||
width_a : NATURAL;
|
||||
width_b : NATURAL;
|
||||
width_byteena_a : NATURAL;
|
||||
width_byteena_b : NATURAL;
|
||||
wrcontrol_wraddress_reg_b : STRING
|
||||
);
|
||||
PORT (
|
||||
wren_a : IN STD_LOGIC ;
|
||||
clock0 : IN STD_LOGIC ;
|
||||
wren_b : IN STD_LOGIC ;
|
||||
clock1 : IN STD_LOGIC ;
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
|
||||
byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
|
||||
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
q_a <= sub_wire0(width_a-1 DOWNTO 0);
|
||||
q_b <= sub_wire1(width_a-1 DOWNTO 0);
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "BYPASS",
|
||||
clock_enable_input_b => "BYPASS",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
init_file => init_file,
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**widthad_a,
|
||||
numwords_b => 2**widthad_a,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => outdata_reg_a,
|
||||
outdata_reg_b => outdata_reg_a,
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
widthad_a => widthad_a,
|
||||
widthad_b => widthad_a,
|
||||
width_a => width_a,
|
||||
width_b => width_a,
|
||||
width_byteena_a => width_a/8,
|
||||
width_byteena_b => width_a/8,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
wren_a => wren_a,
|
||||
clock0 => clock_a,
|
||||
wren_b => wren_b,
|
||||
clock1 => clock_b,
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
q_a => sub_wire0,
|
||||
q_b => sub_wire1,
|
||||
byteena_a => byteena_a,
|
||||
byteena_b => byteena_b
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
602
Arcade_MiST/Konami Jackal/rtl/hiscore.v
Normal file
602
Arcade_MiST/Konami Jackal/rtl/hiscore.v
Normal file
@@ -0,0 +1,602 @@
|
||||
//============================================================================
|
||||
// MAME hiscore.dat support for MiSTer arcade cores.
|
||||
//
|
||||
// https://github.com/JimmyStones/Hiscores_MiSTer
|
||||
//
|
||||
// Copyright (c) 2021 Alan Steremberg
|
||||
// Copyright (c) 2021 Jim Gregory
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//============================================================================
|
||||
/*
|
||||
Version history:
|
||||
0001 - 2021-03-06 - First marked release
|
||||
0002 - 2021-03-06 - Added HS_DUMPFORMAT localparam to identify dump version (for future use)
|
||||
Add HS_CONFIGINDEX and HS_DUMPINDEX parameters to configure ioctl_indexes
|
||||
0003 - 2021-03-10 - Added WRITE_REPEATCOUNT and WRITE_REPEATWAIT to handle tricky write situations
|
||||
0004 - 2021-03-15 - Fix ram_access assignment
|
||||
0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes
|
||||
0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header
|
||||
0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states
|
||||
0008 - 2021-05-12 - Feed back core-level pause to halt startup timer
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
module hiscore
|
||||
#(
|
||||
parameter HS_ADDRESSWIDTH=10, // Max size of game RAM address for highscores
|
||||
parameter HS_SCOREWIDTH=8, // Max size of capture RAM For highscore data (default 8 = 256 bytes max)
|
||||
parameter HS_CONFIGINDEX=3, // ioctl_index for config transfer
|
||||
parameter HS_DUMPINDEX=4, // ioctl_index for dump transfer
|
||||
parameter CFG_ADDRESSWIDTH=4, // Max size of RAM address for highscore.dat entries (default 4 = 16 entries max)
|
||||
parameter CFG_LENGTHWIDTH=1 // Max size of length for each highscore.dat entries (default 1 = 256 bytes max)
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input paused, // Signal from core confirming CPU is paused
|
||||
input reset,
|
||||
|
||||
input ioctl_upload,
|
||||
input ioctl_download,
|
||||
input ioctl_wr,
|
||||
input [24:0] ioctl_addr,
|
||||
input [7:0] ioctl_dout,
|
||||
input [7:0] ioctl_din,
|
||||
input [7:0] ioctl_index,
|
||||
|
||||
output [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data
|
||||
output [7:0] data_to_ram, // Data to write to game RAM
|
||||
output reg ram_write, // Write to game RAM (active high)
|
||||
output ram_access, // RAM read or write required (active high)
|
||||
output reg pause_cpu // Pause core CPU to prepare for/relax after RAM access
|
||||
);
|
||||
|
||||
// Parameters read from config header
|
||||
reg [31:0] START_WAIT =32'd0; // Delay before beginning check process
|
||||
reg [15:0] CHECK_WAIT =16'hFF; // Delay between start/end check attempts
|
||||
reg [15:0] CHECK_HOLD =16'd2; // Hold time for start/end check reads
|
||||
reg [15:0] WRITE_HOLD =16'd2; // Hold time for game RAM writes
|
||||
reg [15:0] WRITE_REPEATCOUNT =16'b1; // Number of times to write score to game RAM
|
||||
reg [15:0] WRITE_REPEATWAIT =16'b1111; // Delay between subsequent write attempts to game RAM
|
||||
reg [7:0] ACCESS_PAUSEPAD =8'd4; // Cycles to wait with paused CPU before and after RAM access
|
||||
|
||||
|
||||
// State machine constants
|
||||
localparam SM_STATEWIDTH = 4; // Width of state machine net
|
||||
|
||||
localparam SM_INIT = 0;
|
||||
localparam SM_TIMER = 1;
|
||||
|
||||
localparam SM_CHECKPREP = 2;
|
||||
localparam SM_CHECKBEGIN = 3;
|
||||
localparam SM_CHECKSTARTVAL = 4;
|
||||
localparam SM_CHECKENDVAL = 5;
|
||||
localparam SM_CHECKCANCEL = 6;
|
||||
|
||||
localparam SM_WRITEPREP = 7;
|
||||
localparam SM_WRITEBEGIN = 8;
|
||||
localparam SM_WRITEREADY = 9;
|
||||
localparam SM_WRITEDONE = 10;
|
||||
localparam SM_WRITECOMPLETE = 11;
|
||||
localparam SM_WRITERETRY = 12;
|
||||
|
||||
localparam SM_STOPPED = 13;
|
||||
|
||||
/*
|
||||
Hiscore config data structure (version 1)
|
||||
-----------------------------------------
|
||||
[16 byte header]
|
||||
[8 byte * no. of entries]
|
||||
|
||||
- Header format
|
||||
00 00 FF FF 00 FF 00 02 00 02 00 01 11 11 00 00
|
||||
[ SW ] [ CW] [ CH] [ WH] [WRC] [WRW] [PAD]
|
||||
4 byte START_WAIT
|
||||
2 byte CHECK_WAIT
|
||||
2 byte CHECK_HOLD
|
||||
2 byte WRITE_HOLD
|
||||
2 byte WRITE_REPEATCOUNT
|
||||
2 byte WRITE_REPEATWAIT
|
||||
2 byte (padding/future use)
|
||||
|
||||
- Entry format (when CFG_LENGTHWIDTH=1)
|
||||
00 00 43 0b 0f 10 01 00
|
||||
00 00 40 23 02 04 12 00
|
||||
[ ADDR ] LEN START END PAD
|
||||
|
||||
4 bytes Address of ram entry (in core memory map)
|
||||
1 byte Length of ram entry in bytes
|
||||
1 byte Start value to check for at start of address range before proceeding
|
||||
1 byte End value to check for at end of address range before proceeding
|
||||
1 byte (padding)
|
||||
|
||||
- Entry format (when CFG_LENGTHWIDTH=2)
|
||||
00 00 43 0b 00 0f 10 01
|
||||
00 00 40 23 00 02 04 12
|
||||
[ ADDR ] [LEN ] START END
|
||||
|
||||
4 bytes Address of ram entry (in core memory map)
|
||||
2 bytes Length of ram entry in bytes
|
||||
1 byte Start value to check for at start of address range before proceeding
|
||||
1 byte End value to check for at end of address range before proceeding
|
||||
|
||||
*/
|
||||
|
||||
localparam HS_VERSION =8; // Version identifier for module
|
||||
localparam HS_DUMPFORMAT =1; // Version identifier for dump format
|
||||
localparam HS_HEADERLENGTH =16; // Size of header chunk (default=16 bytes)
|
||||
|
||||
// HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data
|
||||
|
||||
// Hiscore config and dump status
|
||||
wire downloading_config;
|
||||
wire parsing_header;
|
||||
wire downloading_dump;
|
||||
wire uploading_dump;
|
||||
reg downloaded_config = 1'b0;
|
||||
reg downloaded_dump = 1'b0;
|
||||
reg uploaded_dump = 1'b0;
|
||||
reg [3:0] initialised;
|
||||
reg writing_scores = 1'b0;
|
||||
reg checking_scores = 1'b0;
|
||||
|
||||
assign downloading_config = ioctl_download && (ioctl_index==HS_CONFIGINDEX);
|
||||
assign parsing_header = downloading_config && (ioctl_addr<=HS_HEADERLENGTH);
|
||||
assign downloading_dump = ioctl_download && (ioctl_index==HS_DUMPINDEX);
|
||||
assign uploading_dump = ioctl_upload && (ioctl_index==HS_DUMPINDEX);
|
||||
assign ram_access = uploading_dump | writing_scores | checking_scores;
|
||||
assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0];
|
||||
|
||||
reg [(SM_STATEWIDTH-1):0] state = SM_INIT; // Current state machine index
|
||||
reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT; // Next state machine index to move to after wait timer expires
|
||||
reg [31:0] wait_timer; // Wait timer for inital/read/write delays
|
||||
|
||||
reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry
|
||||
reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries
|
||||
reg reset_last = 1'b0; // Last cycle reset
|
||||
reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt
|
||||
|
||||
reg [7:0] last_ioctl_index; // Last cycle HPS IO index
|
||||
reg last_ioctl_download = 0;// Last cycle HPS IO download
|
||||
reg last_ioctl_upload = 0; // Last cycle HPS IO upload
|
||||
reg [7:0] last_ioctl_dout; // Last cycle HPS IO data out
|
||||
reg [7:0] last_ioctl_dout2; // Last cycle +1 HPS IO data out
|
||||
reg [7:0] last_ioctl_dout3; // Last cycle +2 HPS IO data out
|
||||
|
||||
reg [24:0] ram_addr; // Target RAM address for hiscore read/write
|
||||
reg [24:0] old_io_addr;
|
||||
reg [24:0] base_io_addr;
|
||||
wire [23:0] addr_base;
|
||||
wire [(CFG_LENGTHWIDTH*8)-1:0] length;
|
||||
wire [24:0] end_addr = (addr_base + length - 1'b1);
|
||||
reg [HS_SCOREWIDTH-1:0] local_addr;
|
||||
wire [7:0] start_val;
|
||||
wire [7:0] end_val;
|
||||
|
||||
wire [23:0] address_data_in;
|
||||
wire [(CFG_LENGTHWIDTH*8)-1:0] length_data_in;
|
||||
|
||||
assign address_data_in = {last_ioctl_dout2, last_ioctl_dout, ioctl_dout};
|
||||
assign length_data_in = (CFG_LENGTHWIDTH == 1'b1) ? ioctl_dout : {last_ioctl_dout, ioctl_dout};
|
||||
|
||||
wire address_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3);
|
||||
wire length_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd3 + CFG_LENGTHWIDTH);
|
||||
wire startdata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd4 + CFG_LENGTHWIDTH);
|
||||
wire enddata_we = downloading_config & ~parsing_header & (ioctl_addr[2:0] == 3'd5 + CFG_LENGTHWIDTH);
|
||||
|
||||
// RAM chunks used to store configuration data
|
||||
// - address_table
|
||||
// - length_table
|
||||
// - startdata_table
|
||||
// - enddata_table
|
||||
dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(24))
|
||||
address_table(
|
||||
.clk(clk),
|
||||
.addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
|
||||
.we_a(address_we & ioctl_wr),
|
||||
.d_a(address_data_in),
|
||||
.addr_b(counter),
|
||||
.q_b(addr_base)
|
||||
);
|
||||
// Length table - variable width depending on CFG_LENGTHWIDTH
|
||||
dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(CFG_LENGTHWIDTH*8))
|
||||
length_table(
|
||||
.clk(clk),
|
||||
.addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
|
||||
.we_a(length_we & ioctl_wr),
|
||||
.d_a(length_data_in),
|
||||
.addr_b(counter),
|
||||
.q_b(length)
|
||||
);
|
||||
dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
|
||||
startdata_table(
|
||||
.clk(clk),
|
||||
.addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
|
||||
.we_a(startdata_we & ioctl_wr),
|
||||
.d_a(ioctl_dout),
|
||||
.addr_b(counter),
|
||||
.q_b(start_val)
|
||||
);
|
||||
dpram_hs #(.aWidth(CFG_ADDRESSWIDTH),.dWidth(8))
|
||||
enddata_table(
|
||||
.clk(clk),
|
||||
.addr_a(ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2),
|
||||
.we_a(enddata_we & ioctl_wr),
|
||||
.d_a(ioctl_dout),
|
||||
.addr_b(counter),
|
||||
.q_b(end_val)
|
||||
);
|
||||
|
||||
// RAM chunk used to store hiscore data
|
||||
dpram_hs #(.aWidth(HS_SCOREWIDTH),.dWidth(8))
|
||||
hiscoredata (
|
||||
.clk(clk),
|
||||
.addr_a(ioctl_addr[(HS_SCOREWIDTH-1):0]),
|
||||
.we_a(downloading_dump),
|
||||
.d_a(ioctl_dout),
|
||||
.addr_b(local_addr),
|
||||
.we_b(ioctl_upload),
|
||||
.d_b(ioctl_din),
|
||||
.q_b(data_to_ram)
|
||||
);
|
||||
|
||||
wire [3:0] header_chunk = ioctl_addr[3:0];
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
|
||||
if (downloading_config)
|
||||
begin
|
||||
// Get header chunk data
|
||||
if(parsing_header)
|
||||
begin
|
||||
if(ioctl_wr)
|
||||
begin
|
||||
if(header_chunk == 4'd3) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd5) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd7) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd9) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout };
|
||||
if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= ioctl_dout;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Keep track of the largest entry during config download
|
||||
total_entries <= ioctl_addr[CFG_ADDRESSWIDTH+2:3] - 2'd2;
|
||||
end
|
||||
end
|
||||
|
||||
// Track completion of configuration and dump download
|
||||
if ((last_ioctl_download != ioctl_download) && (ioctl_download == 1'b0))
|
||||
begin
|
||||
if (last_ioctl_index==HS_CONFIGINDEX) downloaded_config <= 1'b1;
|
||||
if (last_ioctl_index==HS_DUMPINDEX) downloaded_dump <= 1'b1;
|
||||
end
|
||||
|
||||
// Track completion of dump upload
|
||||
if ((last_ioctl_upload != ioctl_upload) && (ioctl_upload == 1'b0))
|
||||
begin
|
||||
if (last_ioctl_index==HS_DUMPINDEX)
|
||||
begin
|
||||
uploaded_dump <= 1'b1;
|
||||
// Mark uploaded dump as readable in case of reset
|
||||
downloaded_dump <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Track last ioctl values
|
||||
last_ioctl_download <= ioctl_download;
|
||||
last_ioctl_upload <= ioctl_upload;
|
||||
last_ioctl_index <= ioctl_index;
|
||||
if(ioctl_download && ioctl_wr)
|
||||
begin
|
||||
last_ioctl_dout3 = last_ioctl_dout2;
|
||||
last_ioctl_dout2 = last_ioctl_dout;
|
||||
last_ioctl_dout = ioctl_dout;
|
||||
end
|
||||
|
||||
if(downloaded_config)
|
||||
begin
|
||||
// Check for end of state machine reset to initialise state machine
|
||||
reset_last <= reset;
|
||||
if (reset_last == 1'b1 && reset == 1'b0)
|
||||
begin
|
||||
wait_timer <= START_WAIT;
|
||||
next_state <= SM_INIT;
|
||||
state <= SM_TIMER;
|
||||
counter <= 1'b0;
|
||||
initialised <= initialised + 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Upload scores to HPS
|
||||
if (uploading_dump == 1'b1)
|
||||
begin
|
||||
// generate addresses to read high score from game memory. Base addresses off ioctl_address
|
||||
if (ioctl_addr == 25'b0) begin
|
||||
local_addr <= 0;
|
||||
base_io_addr <= 25'b0;
|
||||
counter <= 1'b0000;
|
||||
end
|
||||
// Move to next entry when last address is reached
|
||||
if (old_io_addr!=ioctl_addr && ram_addr==end_addr[24:0])
|
||||
begin
|
||||
counter <= counter + 1'b1;
|
||||
base_io_addr <= ioctl_addr;
|
||||
end
|
||||
// Set game ram address for reading back to HPS
|
||||
ram_addr <= addr_base + (ioctl_addr - base_io_addr);
|
||||
// Set local addresses to update cached dump in case of reset
|
||||
local_addr <= ioctl_addr[HS_SCOREWIDTH-1:0];
|
||||
end
|
||||
|
||||
if (ioctl_upload == 1'b0 && downloaded_dump == 1'b1 && reset == 1'b0)
|
||||
begin
|
||||
// State machine to write data to game RAM
|
||||
case (state)
|
||||
SM_INIT: // Start state machine
|
||||
begin
|
||||
// Setup base addresses
|
||||
local_addr <= 0;
|
||||
base_io_addr <= 25'b0;
|
||||
// Reset entry counter and states
|
||||
counter <= 0;
|
||||
writing_scores <= 1'b0;
|
||||
checking_scores <= 1'b0;
|
||||
pause_cpu <= 1'b0;
|
||||
state <= SM_CHECKPREP;
|
||||
end
|
||||
|
||||
// Start/end check states
|
||||
// ----------------------
|
||||
SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access
|
||||
begin
|
||||
state <= SM_TIMER;
|
||||
next_state <= SM_CHECKBEGIN;
|
||||
pause_cpu <= 1'b1;
|
||||
wait_timer <= ACCESS_PAUSEPAD;
|
||||
end
|
||||
|
||||
SM_CHECKBEGIN: // Begin start/end check run - enable RAM access
|
||||
begin
|
||||
checking_scores <= 1'b1;
|
||||
ram_addr <= {1'b0, addr_base};
|
||||
state <= SM_CHECKSTARTVAL;
|
||||
wait_timer <= CHECK_HOLD;
|
||||
end
|
||||
|
||||
SM_CHECKSTARTVAL: // Start check
|
||||
begin
|
||||
// Check for matching start value
|
||||
if(wait_timer != CHECK_HOLD & ioctl_din == start_val)
|
||||
begin
|
||||
// Prepare end check
|
||||
ram_addr <= end_addr;
|
||||
state <= SM_CHECKENDVAL;
|
||||
wait_timer <= CHECK_HOLD;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ram_addr <= {1'b0, addr_base};
|
||||
if (wait_timer > 1'b0)
|
||||
begin
|
||||
wait_timer <= wait_timer - 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// - If no match after read wait then stop check run and schedule restart of state machine
|
||||
next_state <= SM_CHECKCANCEL;
|
||||
state <= SM_TIMER;
|
||||
checking_scores <= 1'b0;
|
||||
wait_timer <= ACCESS_PAUSEPAD;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SM_CHECKENDVAL: // End check
|
||||
begin
|
||||
// Check for matching end value
|
||||
if (wait_timer != CHECK_HOLD & ioctl_din == end_val)
|
||||
begin
|
||||
if (counter == total_entries)
|
||||
begin
|
||||
// If this was the last entry then move on to writing scores to game ram
|
||||
checking_scores <= 1'b0;
|
||||
state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused
|
||||
counter <= 1'b0;
|
||||
write_counter <= 1'b0;
|
||||
ram_write <= 1'b0;
|
||||
ram_addr <= {1'b0, addr_base};
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Increment counter and restart state machine to check next entry
|
||||
counter <= counter + 1'b1;
|
||||
state <= SM_CHECKBEGIN;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
ram_addr <= end_addr;
|
||||
if (wait_timer > 1'b0)
|
||||
begin
|
||||
wait_timer <= wait_timer - 1'b1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// - If no match after read wait then stop check run and schedule restart of state machine
|
||||
next_state <= SM_CHECKCANCEL;
|
||||
state <= SM_TIMER;
|
||||
checking_scores <= 1'b0;
|
||||
wait_timer <= ACCESS_PAUSEPAD;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused
|
||||
begin
|
||||
pause_cpu <= 1'b0;
|
||||
next_state <= SM_INIT;
|
||||
state <= SM_TIMER;
|
||||
wait_timer <= CHECK_WAIT;
|
||||
end
|
||||
|
||||
// Write to game RAM states
|
||||
// ----------------------
|
||||
SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts)
|
||||
begin
|
||||
state <= SM_TIMER;
|
||||
next_state <= SM_WRITEBEGIN;
|
||||
pause_cpu <= 1'b1;
|
||||
wait_timer <= ACCESS_PAUSEPAD;
|
||||
end
|
||||
|
||||
SM_WRITEBEGIN: // Writing scores to game RAM begins
|
||||
begin
|
||||
writing_scores <= 1'b1; // Enable muxes if necessary
|
||||
write_counter <= write_counter + 1'b1;
|
||||
state <= SM_WRITEREADY;
|
||||
end
|
||||
|
||||
SM_WRITEREADY: // local ram should be correct, start write to game RAM
|
||||
begin
|
||||
ram_addr <= addr_base + (local_addr - base_io_addr);
|
||||
state <= SM_TIMER;
|
||||
next_state <= SM_WRITEDONE;
|
||||
wait_timer <= WRITE_HOLD;
|
||||
ram_write <= 1'b1;
|
||||
end
|
||||
|
||||
SM_WRITEDONE:
|
||||
begin
|
||||
local_addr <= local_addr + 1'b1; // Increment to next byte of entry
|
||||
if (ram_addr == end_addr)
|
||||
begin
|
||||
// End of entry reached
|
||||
if (counter == total_entries)
|
||||
begin
|
||||
state <= SM_WRITECOMPLETE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Move to next entry
|
||||
counter <= counter + 1'b1;
|
||||
write_counter <= 1'b0;
|
||||
base_io_addr <= local_addr + 1'b1;
|
||||
state <= SM_WRITEBEGIN;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
state <= SM_WRITEREADY;
|
||||
end
|
||||
ram_write <= 1'b0;
|
||||
end
|
||||
|
||||
SM_WRITECOMPLETE: // Hiscore write to RAM completed
|
||||
begin
|
||||
ram_write <= 1'b0;
|
||||
writing_scores <= 1'b0;
|
||||
state <= SM_TIMER;
|
||||
if(write_counter < WRITE_REPEATCOUNT)
|
||||
begin
|
||||
// Schedule next write
|
||||
next_state <= SM_WRITERETRY;
|
||||
local_addr <= 0;
|
||||
wait_timer <= WRITE_REPEATWAIT;
|
||||
end
|
||||
else
|
||||
begin
|
||||
next_state <= SM_STOPPED;
|
||||
wait_timer <= ACCESS_PAUSEPAD;
|
||||
end
|
||||
end
|
||||
|
||||
SM_WRITERETRY: // Stop pause and schedule next write
|
||||
begin
|
||||
pause_cpu <= 1'b0;
|
||||
state <= SM_TIMER;
|
||||
next_state <= SM_WRITEPREP;
|
||||
wait_timer <= WRITE_REPEATWAIT;
|
||||
end
|
||||
|
||||
SM_STOPPED:
|
||||
begin
|
||||
pause_cpu <= 1'b0;
|
||||
end
|
||||
|
||||
SM_TIMER: // timer wait state
|
||||
begin
|
||||
// Do not progress timer if CPU is paused by source other than this module
|
||||
// - Stops initial hiscore load delay being foiled by user pausing/entering OSD
|
||||
if (paused == 1'b0 || pause_cpu == 1'b1)
|
||||
begin
|
||||
if (wait_timer > 1'b0)
|
||||
wait_timer <= wait_timer - 1'b1;
|
||||
else
|
||||
state <= next_state;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
old_io_addr<=ioctl_addr;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module dpram_hs #(
|
||||
parameter dWidth=8,
|
||||
parameter aWidth=8
|
||||
)(
|
||||
input clk,
|
||||
|
||||
input [aWidth-1:0] addr_a,
|
||||
input [dWidth-1:0] d_a,
|
||||
input we_a,
|
||||
output reg [dWidth-1:0] q_a,
|
||||
|
||||
input [aWidth-1:0] addr_b,
|
||||
input [dWidth-1:0] d_b,
|
||||
input we_b,
|
||||
output reg [dWidth-1:0] q_b
|
||||
);
|
||||
|
||||
reg [dWidth-1:0] ram [2**aWidth-1:0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (we_a) begin
|
||||
ram[addr_a] <= d_a;
|
||||
q_a <= d_a;
|
||||
end
|
||||
else
|
||||
begin
|
||||
q_a <= ram[addr_a];
|
||||
end
|
||||
|
||||
if (we_b) begin
|
||||
ram[addr_b] <= d_b;
|
||||
q_b <= d_b;
|
||||
end
|
||||
else
|
||||
begin
|
||||
q_b <= ram[addr_b];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
58
Arcade_MiST/Konami Jackal/rtl/jtframe_frac_cen.v
Normal file
58
Arcade_MiST/Konami Jackal/rtl/jtframe_frac_cen.v
Normal file
@@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Fractional clock enable signal
|
||||
// W refers to the number of divided down cen signals available
|
||||
// each one is divided by 2
|
||||
|
||||
module jtframe_frac_cen #(parameter W=2)(
|
||||
input clk,
|
||||
input [9:0] n, // numerator
|
||||
input [9:0] m, // denominator
|
||||
output reg [W-1:0] cen,
|
||||
output reg [W-1:0] cenb // 180 shifted
|
||||
);
|
||||
|
||||
wire [10:0] step={1'b0,n};
|
||||
wire [10:0] lim ={1'b0,m};
|
||||
wire [10:0] absmax = lim+step;
|
||||
|
||||
reg [10:0] cencnt=11'd0;
|
||||
reg [10:0] next;
|
||||
reg [10:0] next2;
|
||||
|
||||
always @(*) begin
|
||||
next = cencnt+step;
|
||||
next2 = next-lim;
|
||||
end
|
||||
|
||||
reg half = 1'b0;
|
||||
wire over = next>=lim;
|
||||
wire halfway = next >= (lim>>1) && !half;
|
||||
|
||||
reg [W-1:0] edgecnt = {W{1'b0}};
|
||||
wire [W-1:0] next_edgecnt = edgecnt + 1'b1;
|
||||
wire [W-1:0] toggle = next_edgecnt & ~edgecnt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cen <= {W{1'b0}};
|
||||
cenb <= {W{1'b0}};
|
||||
|
||||
if( cencnt >= absmax ) begin
|
||||
// something went wrong: restart
|
||||
cencnt <= 11'd0;
|
||||
end else
|
||||
if( halfway ) begin
|
||||
half <= 1'b1;
|
||||
cenb[0] <= 1'b1;
|
||||
end
|
||||
if( over ) begin
|
||||
cencnt <= next2;
|
||||
half <= 1'b0;
|
||||
edgecnt <= next_edgecnt;
|
||||
cen <= { toggle[W-2:0], 1'b1 };
|
||||
end else begin
|
||||
cencnt <= next;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
93
Arcade_MiST/Konami Jackal/rtl/pause.v
Normal file
93
Arcade_MiST/Konami Jackal/rtl/pause.v
Normal file
@@ -0,0 +1,93 @@
|
||||
//============================================================================
|
||||
// Generic pause handling for MiSTer cores.
|
||||
//
|
||||
// https://github.com/JimmyStones/Pause_MiSTer
|
||||
//
|
||||
// Copyright (c) 2021 Jim Gregory
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//============================================================================
|
||||
/*
|
||||
Features:
|
||||
- Pause can be triggered by user input, hiscore module or OSD opening (optionally controlled by setting in OSD)
|
||||
- When paused the RGB outputs will be halved after 10 seconds to reduce burn-in (optionally controlled by setting in OSD)
|
||||
- Reset signal will cancel user triggered pause
|
||||
|
||||
Version history:
|
||||
0001 - 2021-03-15 - First marked release
|
||||
============================================================================
|
||||
*/
|
||||
module pause #(
|
||||
parameter RW=8, // Width of red channel
|
||||
parameter GW=8, // Width of green channel
|
||||
parameter BW=8, // Width of blue channel
|
||||
parameter CLKSPD = 12 // Main clock speed in MHz
|
||||
)
|
||||
(
|
||||
input clk_sys, // Core system clock (should match HPS module)
|
||||
input reset, // CPU reset signal (active-high)
|
||||
input user_button, // User pause button signal (active-high)
|
||||
input pause_request, // Pause requested by other code (active-high)
|
||||
input [1:0] options, // Pause options from OSD
|
||||
// [0] = pause in OSD (active-high)
|
||||
// [1] = dim video (active-high)
|
||||
input OSD_STATUS, // OSD is open (active-high)
|
||||
input [(RW-1):0] r, // Red channel
|
||||
input [(GW-1):0] g, // Green channel
|
||||
input [(BW-1):0] b, // Blue channel
|
||||
|
||||
output pause_cpu, // Pause signal to CPU (active-high)
|
||||
output [(RW+GW+BW-1):0] rgb_out // RGB output to arcade_video module
|
||||
|
||||
);
|
||||
|
||||
// Option constants
|
||||
localparam pause_in_osd = 1'b0;
|
||||
localparam dim_video = 1'b1;
|
||||
|
||||
reg pause_toggle = 1'b0; // User paused (active-high)
|
||||
reg [31:0] pause_timer = 1'b0; // Time since pause
|
||||
reg [31:0] dim_timeout = (CLKSPD*10000000); // Time until video output dim (10 seconds @ CLKSPD Mhz)
|
||||
|
||||
assign pause_cpu = (pause_request | pause_toggle | (OSD_STATUS & options[pause_in_osd])) & !reset;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
|
||||
// Track user pause button down
|
||||
reg user_button_last;
|
||||
user_button_last <= user_button;
|
||||
if(!user_button_last & user_button) pause_toggle <= ~pause_toggle;
|
||||
|
||||
// Clear user pause on reset
|
||||
if(pause_toggle & reset) pause_toggle <= 0;
|
||||
|
||||
if(pause_cpu & options[dim_video])
|
||||
begin
|
||||
// Track pause duration for video dim
|
||||
if((pause_timer<dim_timeout))
|
||||
begin
|
||||
pause_timer <= pause_timer + 1'b1;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
pause_timer <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Dim video output if pause timer exceeds threshold
|
||||
assign rgb_out = (pause_timer >= dim_timeout) ? {r >> 1,g >> 1, b >> 1} : {r,g,b};
|
||||
|
||||
endmodule
|
||||
4
Arcade_MiST/Konami Jackal/rtl/pll.qip
Normal file
4
Arcade_MiST/Konami Jackal/rtl/pll.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
|
||||
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]
|
||||
348
Arcade_MiST/Konami Jackal/rtl/pll.v
Normal file
348
Arcade_MiST/Konami Jackal/rtl/pll.v
Normal file
@@ -0,0 +1,348 @@
|
||||
// megafunction wizard: %ALTPLL%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altpll
|
||||
|
||||
// ============================================================
|
||||
// File Name: pll.v
|
||||
// Megafunction Name(s):
|
||||
// altpll
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module pll (
|
||||
areset,
|
||||
inclk0,
|
||||
c0,
|
||||
c1,
|
||||
locked);
|
||||
|
||||
input areset;
|
||||
input inclk0;
|
||||
output c0;
|
||||
output c1;
|
||||
output locked;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri0 areset;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [4:0] sub_wire0;
|
||||
wire sub_wire2;
|
||||
wire [0:0] sub_wire6 = 1'h0;
|
||||
wire [0:0] sub_wire3 = sub_wire0[0:0];
|
||||
wire [1:1] sub_wire1 = sub_wire0[1:1];
|
||||
wire c1 = sub_wire1;
|
||||
wire locked = sub_wire2;
|
||||
wire c0 = sub_wire3;
|
||||
wire sub_wire4 = inclk0;
|
||||
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
|
||||
|
||||
altpll altpll_component (
|
||||
.areset (areset),
|
||||
.inclk (sub_wire5),
|
||||
.clk (sub_wire0),
|
||||
.locked (sub_wire2),
|
||||
.activeclock (),
|
||||
.clkbad (),
|
||||
.clkena ({6{1'b1}}),
|
||||
.clkloss (),
|
||||
.clkswitch (1'b0),
|
||||
.configupdate (1'b0),
|
||||
.enable0 (),
|
||||
.enable1 (),
|
||||
.extclk (),
|
||||
.extclkena ({4{1'b1}}),
|
||||
.fbin (1'b1),
|
||||
.fbmimicbidir (),
|
||||
.fbout (),
|
||||
.fref (),
|
||||
.icdrclk (),
|
||||
.pfdena (1'b1),
|
||||
.phasecounterselect ({4{1'b1}}),
|
||||
.phasedone (),
|
||||
.phasestep (1'b1),
|
||||
.phaseupdown (1'b1),
|
||||
.pllena (1'b1),
|
||||
.scanaclr (1'b0),
|
||||
.scanclk (1'b0),
|
||||
.scanclkena (1'b1),
|
||||
.scandata (1'b0),
|
||||
.scandataout (),
|
||||
.scandone (),
|
||||
.scanread (1'b0),
|
||||
.scanwrite (1'b0),
|
||||
.sclkout0 (),
|
||||
.sclkout1 (),
|
||||
.vcooverrange (),
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 105,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 382,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.clk1_divide_by = 105,
|
||||
altpll_component.clk1_duty_cycle = 50,
|
||||
altpll_component.clk1_multiply_by = 191,
|
||||
altpll_component.clk1_phase_shift = "0",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 37037,
|
||||
altpll_component.intended_device_family = "Cyclone III",
|
||||
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
|
||||
altpll_component.lpm_type = "altpll",
|
||||
altpll_component.operation_mode = "NORMAL",
|
||||
altpll_component.pll_type = "AUTO",
|
||||
altpll_component.port_activeclock = "PORT_UNUSED",
|
||||
altpll_component.port_areset = "PORT_USED",
|
||||
altpll_component.port_clkbad0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkloss = "PORT_UNUSED",
|
||||
altpll_component.port_clkswitch = "PORT_UNUSED",
|
||||
altpll_component.port_configupdate = "PORT_UNUSED",
|
||||
altpll_component.port_fbin = "PORT_UNUSED",
|
||||
altpll_component.port_inclk0 = "PORT_USED",
|
||||
altpll_component.port_inclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_locked = "PORT_USED",
|
||||
altpll_component.port_pfdena = "PORT_UNUSED",
|
||||
altpll_component.port_phasecounterselect = "PORT_UNUSED",
|
||||
altpll_component.port_phasedone = "PORT_UNUSED",
|
||||
altpll_component.port_phasestep = "PORT_UNUSED",
|
||||
altpll_component.port_phaseupdown = "PORT_UNUSED",
|
||||
altpll_component.port_pllena = "PORT_UNUSED",
|
||||
altpll_component.port_scanaclr = "PORT_UNUSED",
|
||||
altpll_component.port_scanclk = "PORT_UNUSED",
|
||||
altpll_component.port_scanclkena = "PORT_UNUSED",
|
||||
altpll_component.port_scandata = "PORT_UNUSED",
|
||||
altpll_component.port_scandataout = "PORT_UNUSED",
|
||||
altpll_component.port_scandone = "PORT_UNUSED",
|
||||
altpll_component.port_scanread = "PORT_UNUSED",
|
||||
altpll_component.port_scanwrite = "PORT_UNUSED",
|
||||
altpll_component.port_clk0 = "PORT_USED",
|
||||
altpll_component.port_clk1 = "PORT_USED",
|
||||
altpll_component.port_clk2 = "PORT_UNUSED",
|
||||
altpll_component.port_clk3 = "PORT_UNUSED",
|
||||
altpll_component.port_clk4 = "PORT_UNUSED",
|
||||
altpll_component.port_clk5 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena2 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena3 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena4 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena5 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk0 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk2 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk3 = "PORT_UNUSED",
|
||||
altpll_component.self_reset_on_loss_lock = "OFF",
|
||||
altpll_component.width_clock = 5;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285"
|
||||
// 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 "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: MULT_FACTOR0 NUMERIC "382"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191"
|
||||
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 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_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: PLL_ADVANCED_PARAM_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
|
||||
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
|
||||
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
|
||||
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
|
||||
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
|
||||
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
|
||||
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
|
||||
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
|
||||
// Retrieval info: PRIVATE: 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_CLKENA0 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA1 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 "105"
|
||||
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382"
|
||||
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105"
|
||||
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191"
|
||||
// Retrieval info: CONSTANT: CLK1_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_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
|
||||
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
|
||||
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
|
||||
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
|
||||
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
|
||||
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
|
||||
// Retrieval info: USED_PORT: 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: locked 0 0 0 0 @locked 0 0 0 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
// Retrieval info: CBX_MODULE_PREFIX: ON
|
||||
363
Arcade_MiST/Konami Jackal/rtl/sdram.sv
Normal file
363
Arcade_MiST/Konami Jackal/rtl/sdram.sv
Normal file
@@ -0,0 +1,363 @@
|
||||
//
|
||||
// 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 [16:1] cpu1_addr,
|
||||
output reg [15:0] cpu1_q,
|
||||
input [16: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 [15:0] port2_q,
|
||||
input [16:1] ch1_addr,
|
||||
output reg [15:0] ch1_q,
|
||||
input [16:1] ch2_addr,
|
||||
output reg [15:0] ch2_q,
|
||||
input sp1_req,
|
||||
input [16:1] sp1_addr,
|
||||
output reg [15:0] sp1_q,
|
||||
output reg sp1_ack,
|
||||
input sp2_req,
|
||||
input [16:1] sp2_addr,
|
||||
output reg [15:0] sp2_q,
|
||||
output reg sp2_ack
|
||||
);
|
||||
|
||||
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'b000; // 000=1, 001=2, 010=4, 011=8
|
||||
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
|
||||
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
// 64ms/8192 rows = 7.8us
|
||||
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
|
||||
1 ras0
|
||||
2 data1 returned
|
||||
3 CAS0
|
||||
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_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;
|
||||
// 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 [16:1] addr_last[6];
|
||||
reg [16:1] addr_last2[6];
|
||||
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 = 3'd0;
|
||||
localparam PORT_CPU1 = 3'd1;
|
||||
localparam PORT_CPU2 = 3'd2;
|
||||
localparam PORT_CH1 = 3'd1;
|
||||
localparam PORT_CH2 = 3'd2;
|
||||
localparam PORT_SP1 = 3'd3;
|
||||
localparam PORT_SP2 = 3'd4;
|
||||
localparam PORT_REQ = 3'd5;
|
||||
|
||||
reg [2:0] next_port[2];
|
||||
reg [2:0] port[2];
|
||||
|
||||
reg refresh;
|
||||
reg [10:0] refresh_cnt;
|
||||
wire need_refresh = (refresh_cnt >= RFRSH_CYCLES);
|
||||
|
||||
// PORT1: bank 0,1
|
||||
always @(*) begin
|
||||
if (refresh) begin
|
||||
next_port[0] = PORT_NONE;
|
||||
addr_latch_next[0] = addr_latch[0];
|
||||
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] = { 8'd0, cpu1_addr };
|
||||
end else if (cpu2_addr != addr_last[PORT_CPU2]) begin
|
||||
next_port[0] = PORT_CPU2;
|
||||
addr_latch_next[0] = { 8'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 (ch1_addr != addr_last2[PORT_CH1]) begin
|
||||
next_port[1] = PORT_CH1;
|
||||
addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, ch1_addr };
|
||||
end else if (ch2_addr != addr_last2[PORT_CH2]) begin
|
||||
next_port[1] = PORT_CH2;
|
||||
addr_latch_next[1] = { 1'b1, 5'd0, 2'b10, ch2_addr };
|
||||
end else if (sp1_req != sp1_ack) begin
|
||||
next_port[1] = PORT_SP1;
|
||||
addr_latch_next[1] = { 1'b1, 5'd0, 2'b01, sp1_addr };
|
||||
end else if (sp2_req != sp2_ack) begin
|
||||
next_port[1] = PORT_SP2;
|
||||
addr_latch_next[1] = { 1'b1, 5'd0, 2'b11, sp2_addr };
|
||||
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;
|
||||
|
||||
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][16: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 <= 1'b0;
|
||||
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:1];
|
||||
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
|
||||
|
||||
if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin
|
||||
refresh <= 1'b1;
|
||||
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: begin port2_q <= sd_din; port2_ack <= port2_req; end
|
||||
PORT_CH1 : ch1_q <= sd_din;
|
||||
PORT_CH2 : ch2_q <= sd_din;
|
||||
PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end
|
||||
PORT_SP2 : begin sp2_q <= sd_din; sp2_ack <= sp2_req; end
|
||||
default: ;
|
||||
endcase;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
173
Arcade_MiST/Konami Jackal/rtl/sound/Filter/audio_iir_filter.v
Normal file
173
Arcade_MiST/Konami Jackal/rtl/sound/Filter/audio_iir_filter.v
Normal file
@@ -0,0 +1,173 @@
|
||||
/*MIT License
|
||||
|
||||
Copyright (c) 2019 Gregory Hogan (Soltan_G42)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.*/
|
||||
|
||||
module iir_1st_order
|
||||
#(
|
||||
parameter COEFF_WIDTH = 18,
|
||||
parameter COEFF_SCALE = 15,
|
||||
parameter DATA_WIDTH = 16,
|
||||
parameter COUNT_BITS = 10
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
input [COUNT_BITS - 1 : 0] div,
|
||||
input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2,
|
||||
input signed [DATA_WIDTH - 1 :0] in,
|
||||
output [DATA_WIDTH - 1:0] out
|
||||
);
|
||||
|
||||
reg signed [DATA_WIDTH-1:0] x0,x1,y0;
|
||||
reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32;
|
||||
reg [COUNT_BITS - 1:0] count;
|
||||
|
||||
// Usage:
|
||||
// Design your 1st order iir low/high-pass with a tool that will give you the
|
||||
// filter coefficients for the difference equation. Filter coefficients can
|
||||
// be generated in Octave/matlab/scipy using a command similar to
|
||||
// [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass
|
||||
// assuming 106528Hz sample rate.
|
||||
//
|
||||
// The Matlab output is:
|
||||
// B = [0.093863 0.093863]
|
||||
// A = [1.00000 -0.81227]
|
||||
//
|
||||
// Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
|
||||
//
|
||||
// B = [3076 3076]
|
||||
// A = [32768 -26616]
|
||||
//
|
||||
// Discard A(1) because it is assumed 1.0 before scaling
|
||||
//
|
||||
// This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076
|
||||
// B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768
|
||||
//
|
||||
// Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz
|
||||
//
|
||||
// COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
|
||||
// handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0
|
||||
|
||||
assign out = y0;
|
||||
|
||||
always @ (*) begin
|
||||
out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if(reset) begin
|
||||
count <= 0;
|
||||
x0 <= 0;
|
||||
x1 <= 0;
|
||||
y0 <= 0;
|
||||
end
|
||||
else begin
|
||||
count <= count + 1'd1;
|
||||
if (count == div - 1) begin
|
||||
count <= 0;
|
||||
y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]};
|
||||
x1 <= x0;
|
||||
x0 <= in;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //iir_1st_order
|
||||
|
||||
module iir_2nd_order
|
||||
#(
|
||||
parameter COEFF_WIDTH = 18,
|
||||
parameter COEFF_SCALE = 14,
|
||||
parameter DATA_WIDTH = 16,
|
||||
parameter COUNT_BITS = 10
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
input [COUNT_BITS - 1 : 0] div,
|
||||
input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3,
|
||||
input signed [DATA_WIDTH - 1 : 0] in,
|
||||
output [DATA_WIDTH - 1 : 0] out
|
||||
);
|
||||
|
||||
reg signed [DATA_WIDTH-1 : 0] x0,x1,x2;
|
||||
reg signed [DATA_WIDTH-1 : 0] y0,y1;
|
||||
reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32;
|
||||
reg [COUNT_BITS : 0] count;
|
||||
|
||||
|
||||
// Usage:
|
||||
// Design your 1st order iir low/high-pass with a tool that will give you the
|
||||
// filter coefficients for the difference equation. Filter coefficients can
|
||||
// be generated in Octave/matlab/scipy using a command similar to
|
||||
// [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass
|
||||
// assuming 48000Hz sample rate.
|
||||
//
|
||||
// Output is:
|
||||
// B = [ 0.072231 0.144462 0.072231]
|
||||
// A = [1.00000 -1.10923 0.39815]
|
||||
//
|
||||
// Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
|
||||
// Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits.
|
||||
//
|
||||
// B = [1183 2367 1183]
|
||||
// A = [16384 -18174 6523]
|
||||
//
|
||||
// Discard A(1) because it is assumed 1.0 before scaling
|
||||
//
|
||||
// This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183
|
||||
// B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384
|
||||
//
|
||||
// Sample frequency is "clk rate/div"
|
||||
//
|
||||
// COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
|
||||
// handle temporary overflow during this computation:
|
||||
// out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1);
|
||||
|
||||
assign out = y0;
|
||||
|
||||
always @ (*) begin
|
||||
out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if(reset) begin
|
||||
count <= 0;
|
||||
x0 <= 0;
|
||||
x1 <= 0;
|
||||
x2 <= 0;
|
||||
y0 <= 0;
|
||||
y1 <= 0;
|
||||
end
|
||||
else begin
|
||||
count <= count + 1'd1;
|
||||
if (count == div - 1) begin
|
||||
count <= 0;
|
||||
y1 <= y0;
|
||||
y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]};
|
||||
x2 <= x1;
|
||||
x1 <= x0;
|
||||
x0 <= in;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //iir_2nd_order
|
||||
81
Arcade_MiST/Konami Jackal/rtl/sound/Filter/jackal_lpf.sv
Normal file
81
Arcade_MiST/Konami Jackal/rtl/sound/Filter/jackal_lpf.sv
Normal file
@@ -0,0 +1,81 @@
|
||||
/*MIT License
|
||||
|
||||
Copyright (c) 2019 Gregory Hogan (Soltan_G42)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.*/
|
||||
|
||||
//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter
|
||||
//tuned to low-pass filter the YM2151 on Jackal.
|
||||
|
||||
module jackal_lpf(
|
||||
input clk,
|
||||
input reset,
|
||||
input select,
|
||||
input signed [15:0] in1,
|
||||
input signed [15:0] in2,
|
||||
output signed [15:0] out);
|
||||
|
||||
localparam div = 10'd64; //Sample at 49.152MHz/64 = 768000Hz
|
||||
|
||||
//Coefficients computed with Octave/Matlab/Online filter calculators.
|
||||
//or with scipy.signal.bessel or similar tools
|
||||
|
||||
//0.015398864, 0.015398864
|
||||
//1.0000000, -0.96920227
|
||||
reg signed [17:0] lpf1_A2;
|
||||
reg signed [17:0] lpf1_B2;
|
||||
reg signed [17:0] lpf1_B1;
|
||||
|
||||
//0.018668513, 0.018668513
|
||||
//1.0000000, -0.96266297
|
||||
reg signed [17:0] lpf2_A2;
|
||||
reg signed [17:0] lpf2_B2;
|
||||
reg signed [17:0] lpf2_B1;
|
||||
|
||||
wire signed [15:0] audio_pre_lpf1 = select ? in1 : in2;
|
||||
wire signed [15:0] audio_post_lpf1, audio_post_lpf2;
|
||||
|
||||
always @ (*) begin
|
||||
lpf1_A2 = -18'd31758;
|
||||
lpf1_B1 = 18'd505;
|
||||
lpf1_B2 = 18'd505;
|
||||
lpf2_A2 = -18'd31544;
|
||||
lpf2_B1 = 18'd612;
|
||||
lpf2_B2 = 18'd612;
|
||||
end
|
||||
|
||||
iir_1st_order lpf1_6db(.clk(clk),
|
||||
.reset(reset),
|
||||
.div(div),
|
||||
.A2(lpf1_A2),
|
||||
.B1(lpf1_B1),
|
||||
.B2(lpf1_B2),
|
||||
.in(audio_pre_lpf1),
|
||||
.out(audio_post_lpf1));
|
||||
|
||||
iir_1st_order lpf2_6db(.clk(clk),
|
||||
.reset(reset),
|
||||
.div(div),
|
||||
.A2(lpf2_A2),
|
||||
.B1(lpf2_B1),
|
||||
.B2(lpf2_B2),
|
||||
.in(audio_post_lpf1),
|
||||
.out(audio_post_lpf2));
|
||||
|
||||
assign out = select ? audio_post_lpf1 : audio_post_lpf2;
|
||||
|
||||
endmodule
|
||||
62
Arcade_MiST/Konami Jackal/rtl/sound/Filter/jt49_dcrm2.v
Normal file
62
Arcade_MiST/Konami Jackal/rtl/sound/Filter/jt49_dcrm2.v
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This file is part of JT49.
|
||||
|
||||
JT49 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.
|
||||
|
||||
JT49 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 JT49. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 15-Jan-2019
|
||||
|
||||
*/
|
||||
|
||||
// DC removal filter
|
||||
// input is unsigned
|
||||
// output is signed
|
||||
|
||||
module jt49_dcrm2 #(parameter sw=8) (
|
||||
input clk,
|
||||
input cen,
|
||||
input rst,
|
||||
input [sw-1:0] din,
|
||||
output signed [sw-1:0] dout
|
||||
);
|
||||
|
||||
localparam dw=10; // widht of the decimal portion
|
||||
|
||||
reg signed [sw+dw:0] integ, exact, error;
|
||||
//reg signed [2*(9+dw)-1:0] mult;
|
||||
// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1};
|
||||
reg signed [sw:0] pre_dout;
|
||||
// reg signed [sw+dw:0] dout_ext;
|
||||
reg signed [sw:0] q;
|
||||
|
||||
always @(*) begin
|
||||
exact = integ+error;
|
||||
q = exact[sw+dw:dw];
|
||||
pre_dout = { 1'b0, din } - q;
|
||||
//dout_ext = { pre_dout, {dw{1'b0}} };
|
||||
//mult = dout_ext;
|
||||
end
|
||||
|
||||
assign dout = pre_dout[sw-1:0];
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
integ <= {sw+dw+1{1'b0}};
|
||||
error <= {sw+dw+1{1'b0}};
|
||||
end else if( cen ) begin
|
||||
integ <= integ + pre_dout; //mult[sw+dw*2:dw];
|
||||
error <= exact-{q, {dw{1'b0}}};
|
||||
end
|
||||
|
||||
endmodule
|
||||
3
Arcade_MiST/Konami Jackal/rtl/sound/jackal_sound.qip
Normal file
3
Arcade_MiST/Konami Jackal/rtl/sound/jackal_sound.qip
Normal file
@@ -0,0 +1,3 @@
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/Filter/jackal_lpf.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/sound/Filter/jt49_dcrm2.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/sound/Filter/audio_iir_filter.v
|
||||
46
Arcade_MiST/Konami Jackal/rtl/spram.vhd
Normal file
46
Arcade_MiST/Konami Jackal/rtl/spram.vhd
Normal file
@@ -0,0 +1,46 @@
|
||||
library ieee;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.std_logic_unsigned.ALL;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity spram is
|
||||
|
||||
generic
|
||||
(
|
||||
DATA_WIDTH : natural := 8;
|
||||
ADDR_WIDTH : natural := 10
|
||||
);
|
||||
|
||||
port
|
||||
(
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0);
|
||||
data : in std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
q : out std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
we : in std_logic := '0'
|
||||
);
|
||||
|
||||
end spram;
|
||||
|
||||
architecture rtl of spram is
|
||||
|
||||
subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
|
||||
type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
|
||||
|
||||
shared variable ram : memory_t;
|
||||
|
||||
begin
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if(rising_edge(clk)) then
|
||||
if(we = '1') then
|
||||
ram(to_integer(unsigned(addr))) := data;
|
||||
q <= data;
|
||||
else
|
||||
q <= ram(to_integer(unsigned(addr)));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
@@ -535,13 +535,12 @@ endgenerate
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
always @(posedge CLK)
|
||||
always @(posedge CLK or posedge wNMIClear)
|
||||
begin
|
||||
reg old_sample;
|
||||
old_sample <= NMISample2;
|
||||
|
||||
if (wNMIClear == 1) NMILatched <= 1;
|
||||
else if(old_sample & ~NMISample2) NMILatched <= NMIMask;
|
||||
if (wNMIClear == 1)
|
||||
NMILatched <= 1;
|
||||
else if (fallE_en && ~NMISample & NMISample2) // falling edge of NMISample2
|
||||
NMILatched <= NMIMask;
|
||||
end
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user