1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-05-14 11:08:01 +00:00

Merge pull request #158 from gyurco/m92

Irem M92
This commit is contained in:
Marcel
2023-04-19 23:49:13 +02:00
committed by GitHub
53 changed files with 7962 additions and 320 deletions

View File

@@ -284,7 +284,7 @@ always_comb begin
cpu_io_in = cpu_io_addr[0] ? io16[15:8] : io16[7:0];
end
cpu v30(
v30 v30(
.clk(CLK_32M),
.ce(ce_cpu), // TODO
.ce_4x(ce_4x_cpu), // TODO

View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2011 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
# Version 10.1 Build 197 01/19/2011 Service Pack 1 SJ Full Version
# Date created = 23:49:02 July 13, 2012
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "10.1"
DATE = "23:49:02 July 13, 2012"
# Revisions
PROJECT_REVISION = "IremM92"

View File

@@ -0,0 +1,255 @@
set_global_assignment -name FIT_ATTEMPTS_TO_SKIP 0
# -------------------------------------------------------------------------- #
#
# 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 = 21:06:00 February 29, 2020
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# IremM92_MiST_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
# Project-Wide Assignments
# ========================
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
set_global_assignment -name SMART_RECOMPILE ON
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_54 -to CLOCK_27
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_65 -to AUDIO_L
set_location_assignment PIN_80 -to AUDIO_R
set_location_assignment PIN_105 -to SPI_DO
set_location_assignment PIN_88 -to SPI_DI
set_location_assignment PIN_126 -to SPI_SCK
set_location_assignment PIN_127 -to SPI_SS2
set_location_assignment PIN_91 -to SPI_SS3
set_location_assignment PIN_90 -to SPI_SS4
set_location_assignment PIN_13 -to CONF_DATA0
set_location_assignment PIN_49 -to SDRAM_A[0]
set_location_assignment PIN_44 -to SDRAM_A[1]
set_location_assignment PIN_42 -to SDRAM_A[2]
set_location_assignment PIN_39 -to SDRAM_A[3]
set_location_assignment PIN_4 -to SDRAM_A[4]
set_location_assignment PIN_6 -to SDRAM_A[5]
set_location_assignment PIN_8 -to SDRAM_A[6]
set_location_assignment PIN_10 -to SDRAM_A[7]
set_location_assignment PIN_11 -to SDRAM_A[8]
set_location_assignment PIN_28 -to SDRAM_A[9]
set_location_assignment PIN_50 -to SDRAM_A[10]
set_location_assignment PIN_30 -to SDRAM_A[11]
set_location_assignment PIN_32 -to SDRAM_A[12]
set_location_assignment PIN_83 -to SDRAM_DQ[0]
set_location_assignment PIN_79 -to SDRAM_DQ[1]
set_location_assignment PIN_77 -to SDRAM_DQ[2]
set_location_assignment PIN_76 -to SDRAM_DQ[3]
set_location_assignment PIN_72 -to SDRAM_DQ[4]
set_location_assignment PIN_71 -to SDRAM_DQ[5]
set_location_assignment PIN_69 -to SDRAM_DQ[6]
set_location_assignment PIN_68 -to SDRAM_DQ[7]
set_location_assignment PIN_86 -to SDRAM_DQ[8]
set_location_assignment PIN_87 -to SDRAM_DQ[9]
set_location_assignment PIN_98 -to SDRAM_DQ[10]
set_location_assignment PIN_99 -to SDRAM_DQ[11]
set_location_assignment PIN_100 -to SDRAM_DQ[12]
set_location_assignment PIN_101 -to SDRAM_DQ[13]
set_location_assignment PIN_103 -to SDRAM_DQ[14]
set_location_assignment PIN_104 -to SDRAM_DQ[15]
set_location_assignment PIN_58 -to SDRAM_BA[0]
set_location_assignment PIN_51 -to SDRAM_BA[1]
set_location_assignment PIN_85 -to SDRAM_DQMH
set_location_assignment PIN_67 -to SDRAM_DQML
set_location_assignment PIN_60 -to SDRAM_nRAS
set_location_assignment PIN_64 -to SDRAM_nCAS
set_location_assignment PIN_66 -to SDRAM_nWE
set_location_assignment PIN_59 -to SDRAM_nCS
set_location_assignment PIN_33 -to SDRAM_CKE
set_location_assignment PIN_43 -to SDRAM_CLK
# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name TOP_LEVEL_ENTITY IremM92_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
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE ON
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_NCE_PIN OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name 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"
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"
# 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/cpu.stp
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
# Advanced I/O Timing Assignments
# ===============================
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
# -----------------------------
# start ENTITY(IremM92_MiST)
# Pin & Location Assignments
# ==========================
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[*]
# Fitter Assignments
# ==================
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
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(IremM92_MiST)
# ---------------------------
set_location_assignment PLL_1 -to pll|altpll_component|auto_generated|pll1
set_global_assignment -name DSP_BLOCK_BALANCING "DSP BLOCKS"
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION AUTO
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name SYSTEMVERILOG_FILE rtl/IremM92_MiST.sv
set_global_assignment -name QIP_FILE rtl/pll_mist.qip
set_global_assignment -name QIP_FILE rtl/m92.qip
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../common/CPU/v30/V30.qip
set_global_assignment -name QIP_FILE ../../common/Sound/jt51/jt51.qip
set_global_assignment -name AUTO_RESOURCE_SHARING ON
set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp
set_global_assignment -name SIGNALTAP_FILE output_files/dio.stp
set_global_assignment -name SIGNALTAP_FILE output_files/spr.stp
set_global_assignment -name SIGNALTAP_FILE output_files/layer_a.stp
set_global_assignment -name SIGNALTAP_FILE output_files/cpu2.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -0,0 +1,153 @@
## 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 mem_clk "pll|altpll_component|auto_generated|pll1|clk[1]"
set vid_clk "pll|altpll_component|auto_generated|pll1|clk[2]"
set game_clk "pll|altpll_component|auto_generated|pll1|clk[2]"
#**************************************************************
# 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.4 [get_ports SDRAM_DQ[*]]
set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.2 [get_ports SDRAM_DQ[*]]
#**************************************************************
# Set Output Delay
#**************************************************************
set_output_delay -add_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}]
set_output_delay -add_delay -clock [get_clocks $game_clk] 1.000 [get_ports {AUDIO_L}]
set_output_delay -add_delay -clock [get_clocks $game_clk] 1.000 [get_ports {AUDIO_R}]
set_output_delay -add_delay -clock [get_clocks $game_clk] 1.000 [get_ports {LED}]
set_output_delay -add_delay -clock [get_clocks $vid_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 3
set_multicycle_path -to {VGA_*[*]} -hold 2
set_multicycle_path -from [get_clocks $sdram_clk] -to [get_clocks $mem_clk] -setup 2
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|regs.*} -setup 2
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|regs.*} -hold 1
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|bus_datawrite[*]} -setup 2
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|bus_datawrite[*]} -hold 1
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|bus_addr[*]} -setup 2
set_multicycle_path -from {m92:m92|v30:v30|*} -to {m92:m92|v30:v30|bus_addr[*]} -hold 1
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|regs.*} -setup 2
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|regs.*} -hold 1
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|bus_datawrite[*]} -setup 2
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|bus_datawrite[*]} -hold 1
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|bus_addr[*]} -setup 2
set_multicycle_path -from {m92:m92|sound:sound|v35:v35|v30:core|*} -to {m92:m92|sound:sound|v35:v35|v30:core|bus_addr[*]} -hold 1
#**************************************************************
# Set Maximum Delay
#**************************************************************
#**************************************************************
# Set Minimum Delay
#**************************************************************
#**************************************************************
# Set Input Transition
#**************************************************************

View File

@@ -0,0 +1,39 @@
# Irem M92 Core
![](docs/header-small.png)
This is the port of the [MiSTer FPGA core for the Irem M92 arcade system](https://github.com/MiSTer-devel/Arcade-IremM92_MiSTer) (http://www.system16.com/hardware.php?id=747). The Irem M92 system is known for its high-quality graphics and sound, and this core brings these games to FPGA platforms for arcade enthusiasts to enjoy.
New SDRAM controller, optimizations to fit into the MiST FPGA by Gyorgy Szombathelyi. Original core by [Martin Donlon](https://github.com/wickerwaka).
The Irem M92 core includes numerous games that have not been ported elsewhere, providing a unique and authentic arcade experience. Some of the popular games available in this core are:
- In the Hunt
- Gunforce
- R-Type Leo
- Hook
- Blade Master
- Mystic Riders
- Undercover Cops
- Ninja Baseball Batman
## Controls
All of the games use standard 8-way input with two buttons with the exception of *Superior Soldiers* which uses six button input. Several of the games support 3 or 4 players but you will need to change a DIP switch in the DIP switch menu to enable that. By default the button buttons are mapped to the MiSTers SNES-like layout as `B,A,X,Y,L,R`. The `Coin` and `Start` buttons are mapped to Select and Start. There are two additional buttons that can be mapped that are not mapped by default. `P2 Start` maps the the second players start button. The only purpose this serves is for accessing the service menu with a single controller since most games require pressing P1 and P2 start to access it. The second unmapped button is `Pause` which pauses the core.
Standard MAME keyboard controls are also supported for up to 4-players.
## Thanks
Many people, knowingly or not, contributed to this work.
- Mark, for his R-Type Leo PCB and his support through the years.
- @sorgelig, for developing and maintaining MiSTer.
- @RobertPeip, for the v30mz cpu I am using as the basis for the v33 & v35.
- @jotego, for the YM2151 implementation and analog adjustment module.
- @ArtemioUrbina, for their support building [MDfourier](https://junkerhq.net/MDFourier/) tests.
- @zakk4223, for hiscore support.
- @birdybro, @Toryalai1 & @wwark for MRA help.
- Sanborn, for help with the docs.
- The people from PLD Archive collecting and archiving PAL information https://wiki.pldarchive.co.uk/index.php?title=Category:Irem_M92
- The MiSTer FPGA discord server for support, advice and testing.

View File

@@ -0,0 +1,36 @@
@echo off
del /s *.bak
del /s *.orig
del /s *.rej
del /s *~
rmdir /s /q db
rmdir /s /q incremental_db
rmdir /s /q output_files
rmdir /s /q simulation
rmdir /s /q greybox_tmp
rmdir /s /q hc_output
rmdir /s /q .qsys_edit
rmdir /s /q hps_isw_handoff
rmdir /s /q sys\.qsys_edit
rmdir /s /q sys\vip
for /d %%i in (sys\*_sim) do rmdir /s /q "%%i"
for /d %%i in (rtl\*_sim) do rmdir /s /q "%%i"
del build_id.v
del c5_pin_model_dump.txt
del PLLJ_PLLSPE_INFO.txt
del /s *.qws
del /s *.ppf
del /s *.ddb
del /s *.csv
del /s *.cmp
del /s *.sip
del /s *.spd
del /s *.bsf
del /s *.f
del /s *.sopcinfo
del /s *.xml
del *.cdf
del *.rpt
del /s new_rtl_netlist
del /s old_rtl_netlist
pause

View File

@@ -0,0 +1,104 @@
<misterromdescription>
<name>Blade Master (World)</name>
<mameversion>0245</mameversion>
<setname>bmaster</setname>
<year>1991</year>
<manufacturer>Irem</manufacturer>
<category>Brawler</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Attack,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="4" ids="300k,None" name="Bonus Life"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="bmaster.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0a 00 00</part>
<interleave output="16">
<part name="bm_d-h0-b.5m" crc="49b257c7" map="10" />
<part name="bm_d-l0-b.5f" crc="a873523e" map="01" />
</interleave>
<interleave output="16">
<part name="bm_d-h1-b.5l" crc="082b7158" map="10" />
<part name="bm_d-l1-b.5j" crc="6ff0c04e" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="bm_c0.rom" crc="2cc966b8" map="0001" />
<part name="bm_c1.rom" crc="46df773e" map="0010" />
<part name="bm_c2.rom" crc="05b867bd" map="0100" />
<part name="bm_c3.rom" crc="0a2227a4" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 20 00 00</part>
<interleave output="32">
<part name="bm_000.rom" crc="339fc9f3" map="0001" />
<part name="bm_010.rom" crc="6a14377d" map="0010" />
<part name="bm_020.rom" crc="31532198" map="0100" />
<part name="bm_030.rom" crc="d1a041d3" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="bm_d-sh0.rom" crc="9f7c075b" map="10" />
<part name="bm_d-sl0.rom" crc="1fa87c89" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
90 90 79 90 9d 48 90 90 90 90 2e 90 90 a5 72 90
46 5b b1 3a c3 90 35 90 90 23 90 99 90 05 90 3c
3b 76 11 90 90 4b 90 92 90 32 5d 90 f7 5a 9c 90
26 40 89 90 90 90 90 57 90 90 90 90 90 ba 53 bb
42 59 2f 90 77 90 90 4f bf 4a cb 86 62 7d 90 b8
90 34 90 5f 90 7f f8 80 a0 84 12 52 90 90 90 47
90 2b 88 f9 90 a3 83 90 75 87 90 ab eb 90 fe 90
90 af d0 2c d1 e6 90 43 a2 e7 85 e2 49 22 29 90
7c 90 90 9a 90 90 b9 90 14 cf 33 02 90 90 90 73
90 c5 90 90 90 f3 f6 24 90 56 d3 90 09 01 90 90
03 2d 1b 90 f5 be 90 90 fb 8e 21 8d 0b 90 90 b2
fc fa c6 90 e8 d2 90 08 0a a8 78 ff 90 b5 90 90
c7 06 18 90 90 1e 7e b0 0e 0f 90 90 0c aa 55 90
90 74 3d 90 90 38 27 50 90 b6 5e 8b 07 e5 39 ea
bd 90 81 b7 90 8a 0d 90 58 a1 a9 36 90 c4 90 8f
8c 1f 51 04 f2 90 b3 b4 e9 2a 90 90 90 25 90 bc
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="bm_da.rom" crc="62ce5798" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<!--Blade Master modifies the hiscore table when displaying it
This may cause 'extra' hiscore saving, but shouldn't cause any
loss of saved scores
-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 75 0e 00 80 d3 00
</part>
</rom>
<nvram index="4" size="128"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,106 @@
<misterromdescription>
<name>Dream Soccer '94 (Japan, M92 hardware)</name>
<mameversion>0245</mameversion>
<parent>dsoccr94</parent>
<setname>dsoccr94j</setname>
<year>1994</year>
<manufacturer>Irem</manufacturer>
<category>Sport</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Shoot/Speed Up,Pass/Sliding Tackle,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2:00,2:30,3:00,1:30" name="Time"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="4" ids="Match Mode,Power Mode" name="Game Mode"></dip>
<dip bits="5" ids="Start,Button 1" name="Starting Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
<dip bits="16,17" ids="1000,2000,1500,500" name="Player Power"></dip>
</switches>
<rom index="0" zip="dsoccr94.zip|dsoccr94j.zip" md5="None">
<!-- board type -->
<part>86</part>
<!-- maincpu -->
<part>00 10 00 00</part>
<interleave output="16">
<part name="a3_-h0-e.bin" crc="8de1dbcd" map="10" />
<part name="a3_-l0-e.bin" crc="d3df8bfd" map="01" />
</interleave>
<interleave output="16">
<part name="ds_h1-c.rom" crc="6109041b" map="10" />
<part name="ds_l1-c.rom" crc="97a01f6b" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 40 00 00</part>
<interleave output="32">
<part name="c0.bin" crc="83ea8a47" map="0001" />
<part name="c1.bin" crc="64063e6d" map="0010" />
<part name="c2.bin" crc="cc1f621a" map="0100" />
<part name="c3.bin" crc="515829e1" map="1000" />
</interleave>
<!-- gfx2 wide sprites -->
<part>06 40 00 00</part>
<interleave output="64">
<part name="a3-o00-w.bin" crc="b094e5ad" map="00010000" />
<part name="a3-o01-w.bin" crc="91f34018" map="00000001" />
<part name="a3-o10-w.bin" crc="edddeef4" map="00100000" />
<part name="a3-o11-w.bin" crc="274a9526" map="00000010" />
<part name="a3-o20-w.bin" crc="32064393" map="01000000" />
<part name="a3-o21-w.bin" crc="57bae3d9" map="00000100" />
<part name="a3-o30-w.bin" crc="be838e2f" map="10000000" />
<part name="a3-o31-w.bin" crc="bf899f0d" map="00001000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="ds_sh0.rom" crc="23fe6ffc" map="10" />
<part name="ds_sl0.rom" crc="768132e5" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
90 d1 90 90 90 79 2e 90 90 90 5a 0f 90 90 43 90
90 90 e8 50 90 90 90 a0 5d 22 90 90 b2 3a 90 90
f6 8a 41 90 90 81 90 90 90 90 2b 58 90 90 90 c6
90 90 b9 90 90 2a 90 3c 90 80 26 90 b0 90 47 90
90 90 0a 55 90 90 90 88 90 90 87 90 90 b4 0c 90
73 53 90 90 3b 1f 90 90 90 90 90 90 90 90 90 90
f7 90 90 90 90 1e 90 90 c3 90 a3 74 90 32 42 75
fc 90 b8 90 33 90 5e 90 90 aa 90 90 04 90 9c ba
90 90 24 89 90 90 ea 90 23 90 90 90 bb 90 90 c7
90 8e 90 52 90 18 90 72 90 90 90 90 b6 90 90 90
fa 90 90 90 90 90 90 90 b1 90 90 90 90 57 78 a2
90 3d 51 90 90 bf 46 2c 90 90 fb 90 90 90 90 38
56 90 cf 90 08 90 90 90 5b 07 90 90 90 20 9d 90
03 90 90 90 90 90 bc 86 59 90 02 90 ff d2 8b 90
90 d0 90 90 90 90 90 e9 06 90 5f f3 90 b5 90 90
eb 90 90 90 90 90 83 90 36 90 90 90 90 bd fe 90
</part>
<!-- iremg20 -->
<part>05 10 00 00</part>
<part name="ds_da0.rom" crc="67fc52fd" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e ad 6d 00 80 10 04
</part>
</rom>
<nvram index="4" size="128"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,99 @@
<misterromdescription>
<name>Gun Force II (US)</name>
<mameversion>0245</mameversion>
<setname>gunforc2</setname>
<year>1994</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Fire,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="gunforc2.zip" md5="None">
<!-- board type -->
<part>06</part>
<!-- maincpu -->
<part>00 10 00 00</part>
<interleave output="16">
<part name="a2-h0-a.6h" crc="49965e22" map="10" />
<part name="a2-l0-a.8h" crc="8c88b278" map="01" />
</interleave>
<interleave output="16">
<part name="a2-h1-a.6f" crc="34280b88" map="10" />
<part name="a2-l1-a.8f" crc="c8c13f51" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 20 00 00</part>
<interleave output="32">
<part name="a2_c0.1a" crc="68b8f574" map="0001" />
<part name="a2_c1.1b" crc="0b9efe67" map="0010" />
<part name="a2_c2.3a" crc="7a9e9978" map="0100" />
<part name="a2_c3.3b" crc="1395ee6d" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="a2_000.8a" crc="38e03147" map="0001" />
<part name="a2_010.8b" crc="1d5b05f8" map="0010" />
<part name="a2_020.8c" crc="f2f461cc" map="0100" />
<part name="a2_030.8d" crc="97609d9d" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="a2_sh0.3l" crc="2e2d103d" map="10" />
<part name="a2_sl0.5l" crc="2287e0b3" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
7f 26 5d 90 ba 90 1e 5e b8 49 bc e8 01 90 4a 25
90 bd 90 22 10 90 02 57 70 90 7c 90 e7 52 90 a9
90 90 c6 06 a0 fe cf 8e 43 8f 2d 8c d4 85 75 a2
3d 90 90 38 7e 89 d1 80 3b 72 07 90 42 37 0a 18
88 b4 98 8b b9 9c ad 0e 2b 90 bf 90 55 90 56 b0
93 91 90 eb 90 50 41 29 47 90 90 60 90 ab 90 90
c3 e2 d0 b2 11 79 90 08 82 fb 90 2c 23 90 28 0d
90 90 90 83 3c 90 1b 34 5b 90 40 90 90 04 fc cd
b1 f3 8a 90 90 87 90 90 90 90 90 90 be 84 1f e6
ff 90 12 90 b5 36 90 b3 90 90 90 d2 4e 90 90 90
a5 90 90 c7 90 27 0b 90 20 90 90 90 90 90 61 7d
63 90 86 0f 90 b7 90 4f 13 90 c0 fd 90 39 90 77
05 3a 90 48 92 71 3e 03 90 f8 90 59 a8 5f f9 bb
81 fa 9d e9 2e a1 c1 33 90 78 90 0c 90 24 aa ac
90 b6 90 ea 90 73 e5 58 00 f7 90 74 90 76 90 a3
90 5a f6 32 46 2a 90 90 53 4b 90 35 51 68 99 13
</part>
<!-- iremg20 -->
<part>05 10 00 00</part>
<part name="a2_da.1l" crc="3c8cdb6a" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 0A 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e a5 ae 00 4b 00 a6
</part>
</rom>
<nvram index="4" size="75"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>Gunforce - Battle Fire Engulfed Terror Island (World)</name>
<mameversion>0245</mameversion>
<setname>gunforce</setname>
<year>1991</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>2</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Fire,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="3,2,4,5" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="4" ids="20k/40k/90k/150k,15k/35k/75k/120k" name="Bonus Life"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="gunforce.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 08 00 00</part>
<interleave output="16">
<part name="gf_h0-c.5m" crc="c09bb634" map="10" />
<part name="gf_l0-c.5f" crc="1bef6f7d" map="01" />
</interleave>
<interleave output="16">
<part name="gf_h1-c.5l" crc="c84188b7" map="10" />
<part name="gf_l1-c.5j" crc="b189f72a" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="gf_c0.rom" crc="b3b74979" map="0001" />
<part name="gf_c1.rom" crc="f5c8590a" map="0010" />
<part name="gf_c2.rom" crc="30f9fb64" map="0100" />
<part name="gf_c3.rom" crc="87b3e621" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 10 00 00</part>
<interleave output="32">
<part name="gf_000.rom" crc="209e8e8d" map="0001" />
<part name="gf_010.rom" crc="6e6e7808" map="0010" />
<part name="gf_020.rom" crc="6f5c3cb0" map="0100" />
<part name="gf_030.rom" crc="18978a9f" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="gf_sh0.rom" crc="3f8f16e0" map="10" />
<part name="gf_sl0.rom" crc="db0b13a3" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
ff 90 90 2c 90 90 43 88 90 13 0a bd ba 60 ea 90
90 90 f2 29 b3 22 90 0c a9 5f 9d 07 90 90 0b bb
8a 90 90 90 3a 3c 5a 38 99 90 f8 89 90 91 90 55
ac 40 73 90 59 90 fc 90 50 fa 90 25 90 34 47 b7
90 90 90 49 90 0f 8b 05 c3 a5 bf 83 86 c5 90 90
08 77 24 b4 90 92 90 3b 5e b6 80 0d 2e ab e7 90
48 90 ad c0 90 1b c6 a3 04 90 90 90 16 b0 7d 98
87 46 8c 90 90 fe 90 cf 90 68 84 90 d2 90 18 51
76 a4 36 52 fb 90 b9 90 90 b1 1c 21 e6 b5 17 27
3d 45 be ae 90 4a 0e e5 90 58 1f 61 f3 02 90 e8
90 90 90 f7 56 96 aa bc 4f 90 90 79 d0 90 2a 12
4e b8 90 41 90 90 d3 90 2d 33 f6 90 90 14 90 32
5d a8 53 26 2b 20 81 75 7f 3e 90 90 00 93 90 b2
57 90 a0 90 39 90 90 72 90 01 42 74 9c 1e 90 5b
90 f9 90 2f 85 90 eb a2 90 e2 11 90 4b 7e 90 78
90 90 09 a1 03 90 23 c1 8e e9 d1 7c 90 90 c7 06
</part>
<!-- iremg20 -->
<part>05 02 00 00</part>
<part name="gf-da.rom" crc="933ba935" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 66 33 00 40 44 20
</part>
</rom>
<nvram index="4" size="64"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,102 @@
<misterromdescription>
<name>Hook (World)</name>
<mameversion>0245</mameversion>
<setname>hook</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Brawler</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Attack,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="9" ids="2 Players,4 Players" name="Cabinet"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="hook.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0c 00 00</part>
<interleave output="16">
<part name="h-h0-d.3h" crc="40189ff6" map="10" />
<part name="h-l0-d.5h" crc="14567690" map="01" />
</interleave>
<interleave output="16">
<part name="h-h1.rom" crc="264ba1f0" map="10" />
<part name="h-l1.rom" crc="f9913731" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="hook-c0.rom" crc="dec63dcf" map="0001" />
<part name="hook-c1.rom" crc="e4eb0b92" map="0010" />
<part name="hook-c2.rom" crc="a52b320b" map="0100" />
<part name="hook-c3.rom" crc="7ef67731" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="hook-000.rom" crc="ccceac30" map="0001" />
<part name="hook-010.rom" crc="8ac8da67" map="0010" />
<part name="hook-020.rom" crc="8847af9a" map="0100" />
<part name="hook-030.rom" crc="239e877e" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="h-sh0.rom" crc="86a4e56e" map="10" />
<part name="h-sl0.rom" crc="10fd9676" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
b6 20 22 90 0f 57 59 c6 eb 90 b0 bb 3b 90 90 90
36 90 90 90 90 90 90 90 90 fe 90 90 90 90 90 a0
2e 90 0b 90 90 58 90 90 90 90 90 90 90 80 90 90
33 90 90 bf 55 90 90 90 53 90 90 90 90 90 90 90
47 74 90 b1 b4 90 90 88 90 90 38 cf 90 8e 90 90
90 c7 90 32 90 52 3c 90 90 90 90 90 90 90 83 72
90 73 90 5a 90 43 90 90 90 90 41 e9 bd 90 b2 d2
90 aa a2 90 90 90 90 90 90 90 90 26 90 90 8a 90
90 90 90 90 90 90 90 18 90 9d 90 90 90 5d 90 46
90 90 90 f6 c3 a3 1e 07 5f 81 90 0c 90 b8 90 75
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 79
90 5e 90 90 06 90 ff 90 5b 24 90 2b 90 90 90 02
86 90 90 fb 90 90 50 fc 08 90 90 90 03 90 b9 90
90 bc e8 1f fa 42 90 90 89 90 23 87 90 2a 90 90
8b 90 f3 ea 04 2c b5 90 0a 90 51 90 90 3a 90 9c
90 90 78 90 ba 90 90 90 90 90 90 90 d0 56 90 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="hook-da.rom" crc="88cd0212" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e a6 ad 00 ec 00 4f
</part>
</rom>
<nvram index="4" size="236"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,102 @@
<misterromdescription>
<name>In The Hunt (World)</name>
<mameversion>0245</mameversion>
<setname>inthunt</setname>
<year>1993</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>2</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Torpedo,Mine/Missle,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="3,2,4,5" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="inthunt.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0c 00 00</part>
<interleave output="16">
<part name="ith-h0-d.ic28" crc="52f8e7a6" map="10" />
<part name="ith-l0-d.ic39" crc="5db79eb7" map="01" />
</interleave>
<interleave output="16">
<part name="ith-h1-b.ic38" crc="fc2899df" map="10" />
<part name="ith-l1-b.ic27" crc="955a605a" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 20 00 00</part>
<interleave output="32">
<part name="ith_c0.ic26" crc="4c1818cf" map="0001" />
<part name="ith_c1.ic25" crc="91145bae" map="0010" />
<part name="ith_c2.ic24" crc="fc03fe3b" map="0100" />
<part name="ith_c3.ic23" crc="ee156a0a" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="ith_000.ic34" crc="a019766e" map="0001" />
<part name="ith_010.ic35" crc="3fca3073" map="0010" />
<part name="ith_020.ic36" crc="20d1b28b" map="0100" />
<part name="ith_030.ic37" crc="90b6fd4b" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="ith-sh0.ic30" crc="209c8b7f" map="10" />
<part name="ith-sl0.ic31" crc="18472d65" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
1f 90 bb 50 90 58 42 57 90 90 e9 90 90 90 90 0b
90 90 9d 9c 90 90 1e 90 90 b4 5b 90 90 90 90 90
90 90 78 c7 90 90 83 90 90 0c b0 04 90 90 90 90
90 90 90 90 3b c3 b5 47 90 90 90 90 59 90 90 90
90 90 90 38 90 90 90 90 5f a3 fa 90 e8 36 75 90
88 33 90 90 90 90 43 90 90 87 90 90 90 90 90 90
90 90 90 90 8e f3 56 90 90 90 90 26 ff 90 90 90
90 90 90 2a 90 8a 90 18 90 90 03 89 24 90 90 90
0a 90 eb 90 86 90 90 90 79 3a 90 90 90 90 a0 90
ea 90 90 90 90 90 2c 90 c6 90 90 46 90 aa b6 5e
90 90 90 90 8b 90 90 90 90 90 ba 90 b9 53 a2 90
90 07 90 90 90 3c 32 90 2b 90 b8 90 90 90 90 90
bd 90 90 90 90 81 90 d0 08 90 55 06 cf 90 90 fc
90 90 90 b1 bf 90 90 51 52 90 5d 90 5a 90 b2 90
fe 90 90 22 20 72 f6 80 02 2e 90 74 0f 90 90 90
90 90 90 90 bc 41 90 fb 73 90 90 90 23 d2 90 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="ith_da.ic9" crc="318ee71a" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 01 80 00 d8 00 02
</part>
</rom>
<nvram index="4" size="216"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>Lethal Thunder (World)</name>
<mameversion>0245</mameversion>
<setname>lethalth</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>vertical</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Shoot,Thunder,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="3,2,4,5" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="16,17" ids="700k/1.5M,500k/1M,1M/2M,700k/1.5M/3M/4.5M" name="Bonus Life"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="1"><part>01</part></rom>
<rom index="0" zip="lethalth.zip" md5="None">
<!-- board type -->
<part>10</part>
<!-- maincpu -->
<part>00 08 00 00</part>
<interleave output="16">
<part name="lt_d-h0.rom" crc="20c68935" map="10" />
<part name="lt_d-l0.rom" crc="e1432fb3" map="01" />
</interleave>
<interleave output="16">
<part name="lt_d-h1.rom" crc="d7dd3d48" map="10" />
<part name="lt_d-l1.rom" crc="b94b3bd8" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="lt_7a.rom" crc="ada0fd50" map="0001" />
<part name="lt_7b.rom" crc="d2596883" map="0010" />
<part name="lt_7d.rom" crc="2de637ef" map="0100" />
<part name="lt_7h.rom" crc="9f6585cd" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 10 00 00</part>
<interleave output="32">
<part name="lt_7j.rom" crc="baf8863e" map="0001" />
<part name="lt_7l.rom" crc="40fd50af" map="0010" />
<part name="lt_7s.rom" crc="c8e970df" map="0100" />
<part name="lt_7y.rom" crc="f5436708" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="lt_d-sh0.rom" crc="af5b224f" map="10" />
<part name="lt_d-sl0.rom" crc="cb3faac3" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
7f 26 5d 90 ba 90 1e 5e b8 49 bc e8 01 90 4a 25
90 bd 90 22 10 90 02 57 70 90 7c 90 e7 52 90 a9
90 90 c6 06 a0 fe cf 8e 43 8f 2d 8c d4 85 75 a2
3d 90 90 38 7e 89 d1 80 3b 72 07 90 42 37 0a 18
88 b4 98 8b b9 9c ad 0e 2b 90 bf 90 55 90 56 b0
93 91 90 eb 90 50 41 29 47 90 90 60 90 ab 90 90
c3 e2 d0 b2 11 79 90 08 82 fb 90 2c 23 90 28 0d
90 90 90 83 3c 90 1b 34 5b 90 40 90 90 04 fc cd
b1 f3 8a 90 90 87 90 90 90 90 90 90 be 84 1f e6
ff 90 12 90 b5 36 90 b3 90 90 90 d2 4e 90 90 90
a5 90 90 c7 90 27 0b 90 20 90 90 90 90 90 61 7d
63 90 86 0f 90 b7 90 4f 13 90 c0 fd 90 39 90 77
05 3a 90 48 92 71 3e 03 90 f8 90 59 a8 5f f9 bb
81 fa 9d e9 2e a1 c1 33 90 78 90 0c 90 24 aa ac
90 b6 90 ea 90 73 e5 58 00 f7 90 74 90 76 90 a3
90 5a f6 32 46 2a 90 90 53 4b 90 35 51 68 99 13
</part>
<!-- iremg20 -->
<part>05 04 00 00</part>
<part name="lt_8a.rom" crc="357762a2" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 00 86 00 b7 00 08
</part>
</rom>
<nvram index="4" size="183"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>Major Title 2 (World, set 1)</name>
<mameversion>0245</mameversion>
<setname>majtitl2</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Sports</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>4</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Attack,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="9" ids="2 Players,4 Players" name="Cabinet"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="majtitl2.zip" md5="None">
<!-- board type -->
<part>06</part>
<!-- maincpu -->
<part>00 10 00 00</part>
<interleave output="16">
<part name="mt2-h0-b.5m" crc="b163b12e" map="10" />
<part name="mt2-l0-b.5f" crc="6f3b5d9d" map="01" />
</interleave>
<interleave output="16">
<part name="is-h1.5l" crc="9ba8e1f2" map="10" />
<part name="is-l1.5j" crc="e4e00626" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="hr0.ic9" crc="7e61e4b5" map="0001" />
<part name="hr1.ic10" crc="0a667564" map="0010" />
<part name="hr2.ic11" crc="5eb44312" map="0100" />
<part name="hr3.ic12" crc="f2866294" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="k30.ic42" crc="8c9a2678" map="0001" />
<part name="k31.ic43" crc="5455df78" map="0010" />
<part name="k32.ic44" crc="3a258c41" map="0100" />
<part name="k33.ic45" crc="c1e91a14" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="mt2-sh0-.ic14" crc="1ecbea43" map="10" />
<part name="mt2-sl0-.ic17" crc="8fd5b531" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
87 90 78 aa 90 90 90 2c 32 0a 0f 90 5e 90 c6 8a
33 90 90 90 90 ea 90 72 90 90 90 90 90 90 24 55
90 90 90 89 fb 90 59 02 90 90 5d 90 90 90 36 90
90 06 79 90 90 1e 07 90 90 90 83 90 90 90 90 90
9d 90 90 74 90 90 90 0c 58 90 90 90 90 90 90 90
3c 90 03 90 90 fa 43 90 bf 90 90 75 90 88 90 80
90 a3 90 fe 90 90 90 90 90 90 90 90 3a 90 90 90
2b 90 90 90 90 e9 5f 90 46 90 41 90 18 b8 90 90
b4 5a b1 90 90 50 e8 20 90 b2 90 90 90 90 90 51
90 90 90 56 90 90 90 90 90 cf 90 90 90 c3 90 90
90 90 90 90 0b 90 90 b5 57 90 90 c7 3b 90 90 90
90 90 90 90 b6 90 eb 90 38 90 a0 08 90 86 b0 90
42 1f 73 90 f6 90 90 90 53 90 52 90 04 bd 90 90
26 ff 2e 90 81 90 47 90 90 90 90 d0 22 90 90 b9
23 90 f3 90 90 90 90 90 90 d2 8b ba 90 90 90 5b
90 90 9c 90 90 90 90 fc bc a2 2a 90 90 8e bb 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="k0d.ic8" crc="713b9e9f" />
<!-- eeprom -->
<part>07 00 20 00</part>
<part name="mt2eep" crc="208af971" />
</rom>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>Mystic Riders (World)</name>
<mameversion>0245</mameversion>
<setname>mysticri</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Gun Shoot,Broom Shoot,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="3,2,4,5" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="4" ids="20k/50k/90k,15k/35k/60k" name="Bonus Life"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="mysticri.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0a 00 00</part>
<interleave output="16">
<part name="mr-h0-b.bin" crc="d529f887" map="10" />
<part name="mr-l0-b.bin" crc="a457ab44" map="01" />
</interleave>
<interleave output="16">
<part name="mr-h1-b.bin" crc="e17649b9" map="10" />
<part name="mr-l1-b.bin" crc="a87c62b4" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="mr-c0.bin" crc="872a8fad" map="0001" />
<part name="mr-c1.bin" crc="d2ffb27a" map="0010" />
<part name="mr-c2.bin" crc="62bff287" map="0100" />
<part name="mr-c3.bin" crc="d0da62ab" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 20 00 00</part>
<interleave output="32">
<part name="mr-o00.bin" crc="a0f9ce16" map="0001" />
<part name="mr-o10.bin" crc="4e70a9e9" map="0010" />
<part name="mr-o20.bin" crc="b9c468fc" map="0100" />
<part name="mr-o30.bin" crc="cc32433a" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="mr-sh0.bin" crc="50d335e4" map="10" />
<part name="mr-sl0.bin" crc="0fa32721" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
90 57 90 90 90 90 90 90 bf 43 90 90 b3 90 fc 90
90 90 90 90 90 52 a3 26 90 c7 90 0f 90 0c 90 90
90 90 ff 90 90 02 90 90 2e 90 5f 90 90 90 73 50
b2 3a 90 90 bb 90 90 90 90 90 90 90 90 90 90 90
90 90 8e 3c 42 90 90 b9 90 90 2a 90 47 a0 2b 03
b5 1f 90 aa 90 fb 90 90 90 90 90 90 38 90 90 90
2c 90 90 c6 90 90 b1 90 90 90 90 90 90 90 a2 90
e9 e8 90 90 86 90 8b 90 90 90 90 90 5b 72 90 90
90 90 5d 0a 90 90 89 90 b0 88 90 b7 90 87 75 bd
90 51 90 90 90 90 90 be 90 90 90 5a 58 90 90 56
90 8a 90 55 90 90 90 b4 08 90 f6 90 90 9d 90 bc
0b 00 90 5e 90 90 90 22 36 4b 1e 90 b6 ba 23 90
20 90 90 90 59 53 90 04 81 90 90 f3 90 90 3b 06
e2 79 83 9c 90 18 80 90 c3 90 90 90 32 90 cf 90
eb 90 90 33 90 fa 90 90 d2 90 24 90 74 41 b8 90
34 90 d0 07 f8 90 90 90 90 46 90 ea fe 78 90 90
</part>
<!-- iremg20 -->
<part>05 04 00 00</part>
<part name="mr-da.bin" crc="1a11fc59" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 8a f8 00 38 00 4d
00 0e 8b 30 00 94 2e 00
</part>
</rom>
<nvram index="4" size="204"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,103 @@
<misterromdescription>
<name>Ninja Baseball Bat Man (World)</name>
<mameversion>0245</mameversion>
<setname>nbbatman</setname>
<year>1993</year>
<manufacturer>Irem</manufacturer>
<category>Fighter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>4</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Attack,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="9" ids="2 Players,4 Players" name="Cabinet"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="nbbatman.zip" md5="None">
<!-- board type -->
<part>06</part>
<!-- maincpu -->
<part>00 10 00 00</part>
<interleave output="16">
<part name="6_h0.34" crc="5c4a1e3f" map="10" />
<part name="3_l0.31" crc="3d6d70ae" map="01" />
</interleave>
<interleave output="16">
<part name="a1-h1-.33" crc="3ce2aab5" map="10" />
<part name="a1-l1-.32" crc="116d9bcc" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 20 00 00</part>
<interleave output="32">
<part name="lh534k0c.9" crc="314a0c6d" map="0001" />
<part name="lh534k0e.10" crc="dc31675b" map="0010" />
<part name="lh534k0f.11" crc="e15d8bfb" map="0100" />
<part name="lh534k0g.12" crc="888d71a3" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="lh538393.42" crc="26cdd224" map="0001" />
<part name="lh538394.43" crc="4bbe94fa" map="0010" />
<part name="lh538395.44" crc="2a533b5e" map="0100" />
<part name="lh538396.45" crc="863a66fa" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="a1-sh0-.14" crc="b7fae3e6" map="10" />
<part name="a1-sl0-.17" crc="b26d54fc" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
90 90 90 55 bb 90 23 79 90 90 90 90 90 90 38 90
f7 90 90 90 90 90 90 90 3d 90 90 90 ba 90 1e 90
2c 46 90 b5 90 4b 90 fe 90 90 fb 2e 90 90 36 04
cf 90 f3 5a 8a 0c 9c 90 90 90 b2 50 90 90 90 5f
90 90 24 90 90 41 2b 90 e9 90 08 3b 90 90 90 90
90 d2 51 90 90 90 22 90 eb 3a 5b a2 b1 80 90 90
90 90 90 90 59 b4 88 90 90 bf d1 90 b9 57 90 90
72 90 73 90 90 90 90 0f 90 90 90 90 56 90 90 c6
90 90 90 90 90 2a 8e 90 81 a3 58 90 aa 78 89 90
90 90 90 90 90 90 bd 90 90 90 ff 90 90 90 07 53
a0 90 90 5e b0 90 83 f6 90 26 32 90 90 90 74 0a
18 90 90 90 75 03 90 90 b6 02 90 90 43 90 b8 90
e8 90 fc 90 20 c3 90 06 90 1f 86 00 90 90 90 d0
47 90 87 90 90 9d 3c c7 90 90 90 90 90 90 90 90
90 90 90 8b 90 90 33 90 90 90 90 90 fa 42 90 90
90 90 90 ea 90 52 90 5d 90 90 90 90 bc 90 90 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="lh534k0k.8" crc="735e6380" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 25 d4 00 4f 00 03
</part>
</rom>
<nvram index="4" size="79"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>R-Type Leo (World)</name>
<mameversion>0245</mameversion>
<setname>rtypeleo</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Shooter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>2</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Fire,Psy-Bits Control,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="3,2,4,5" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Yes,No" name="Allow Continue"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="rtypeleo.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0c 00 00</part>
<interleave output="16">
<part name="rtl-h0-c.bin" crc="5fef7fa1" map="10" />
<part name="rtl-l0-c.bin" crc="8156456b" map="01" />
</interleave>
<interleave output="16">
<part name="rtl-h1-d.bin" crc="352ff444" map="10" />
<part name="rtl-l1-d.bin" crc="fd34ea46" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 20 00 00</part>
<interleave output="32">
<part name="rtl-c0.bin" crc="fb588d7c" map="0001" />
<part name="rtl-c1.bin" crc="e5541bff" map="0010" />
<part name="rtl-c2.bin" crc="faa9ae27" map="0100" />
<part name="rtl-c3.bin" crc="3a2343f6" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="rtl-000.bin" crc="82a06870" map="0001" />
<part name="rtl-010.bin" crc="417e7a56" map="0010" />
<part name="rtl-020.bin" crc="f9a3f3a1" map="0100" />
<part name="rtl-030.bin" crc="03528d95" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="rtl-sh0a.bin" crc="e518b4e3" map="10" />
<part name="rtl-sl0a.bin" crc="896f0d36" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
5d 90 c6 90 90 90 2a 3a 90 90 90 86 90 22 90 f3
90 90 90 90 90 38 f7 42 04 90 90 1f 4b 90 90 58
57 2e 90 90 53 90 b9 90 90 90 90 90 20 55 90 3d
a0 90 90 0c 03 90 83 90 90 90 8a 00 90 aa 90 90
90 90 90 90 90 90 90 90 90 41 0a 26 8b 56 5e 90
90 74 90 90 90 90 06 90 90 89 5b c7 43 90 90 90
90 b6 90 3b 90 90 90 90 90 36 ea 80 90 90 90 5f
90 0f 90 90 90 46 90 90 3c 8e 90 a3 87 90 90 90
2b fb 47 0b 90 fc 02 90 90 90 90 90 90 90 72 2c
33 90 90 90 90 90 9d bd 90 b2 90 78 75 b8 90 90
90 90 90 90 cf 5a 88 90 90 90 c3 90 eb fa 90 32
90 90 90 52 b4 90 90 90 90 bc 90 90 90 b1 59 50
90 90 b5 90 08 a2 bf bb 1e 9c 90 73 90 d0 90 90
90 90 90 90 81 90 79 90 90 24 23 90 90 b0 07 ff
90 ba f6 51 90 90 90 fe 90 92 90 90 90 90 e9 90
90 90 90 90 90 90 e8 d2 90 18 90 90 90 d1 90 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="rtl-da.bin" crc="dbebd1ff" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 F0 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 22 1e 00 38 40 20
00 0e 22 56 00 03 40 01
</part>
</rom>
<nvram index="4" size="59"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,101 @@
<misterromdescription>
<name>Superior Soldiers (US)</name>
<mameversion>0245</mameversion>
<setname>ssoldier</setname>
<year>1993</year>
<manufacturer>Irem</manufacturer>
<category>Fighter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<joystick>8-way</joystick>
<num_buttons>6</num_buttons>
<buttons default="B,A,R,X,Y,L,Start,Select" names="Soft Punch,Medium Punch,Hard Punch,Soft Kick,Medium Kick,Hard Kick,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="ssoldier.zip" md5="None">
<!-- board type -->
<part>40</part>
<!-- maincpu -->
<part>00 0c 00 00</part>
<interleave output="16">
<part name="f3-l0-h.bin" crc="419361a2" map="01" />
<part name="f3-h0-h.bin" crc="b63fb9da" map="10" />
</interleave>
<interleave output="16">
<part name="f3-l1-a.bin" crc="8cb5c396" map="01" />
<part name="f3-h1-a.bin" crc="e3d9f619" map="10" />
</interleave>
<!-- gfx1 tiles -->
<part>01 10 00 00</part>
<interleave output="32">
<part name="f3_w50.c0" crc="47e788ee" map="0001" />
<part name="f3_w51.c1" crc="8e535e3f" map="0010" />
<part name="f3_w52.c2" crc="a6eb2e56" map="0100" />
<part name="f3_w53.c3" crc="2f992807" map="1000" />
</interleave>
<!-- gfx2 wide sprites -->
<part>06 80 00 00</part>
<interleave output="64">
<part name="f3_w37.000" crc="fd4cda03" map="00010000" />
<part name="f3_w38.001" crc="755bab10" map="00000001" />
<part name="f3_w39.010" crc="b21ced92" map="00100000" />
<part name="f3_w40.011" crc="2e906889" map="00000010" />
<part name="f3_w41.020" crc="02455d10" map="01000000" />
<part name="f3_w42.021" crc="124589b9" map="00000100" />
<part name="f3_w43.030" crc="dae7327a" map="10000000" />
<part name="f3_w44.031" crc="d0fc84ac" map="00001000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="f3_sh0.sh0" crc="90b55e5e" map="10" />
<part name="f3_sl0.sl0" crc="77c16d57" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
90 90 90 8a 90 aa 90 90 90 20 23 55 90 b5 0a 90
90 46 90 b6 90 74 8b 90 90 ba f7 90 90 5a 86 fb
b2 90 b0 90 42 06 1e 08 22 9d 90 90 90 90 90 73
90 90 5f 90 90 d0 90 ff 90 90 bd 90 03 90 b9 90
90 90 90 51 5e 24 90 90 90 90 90 58 59 90 90 90
52 90 90 90 a0 90 90 02 d2 90 79 26 3a 0f cf b4
f3 90 90 50 90 75 b1 90 d1 47 90 90 90 90 90 90
c6 90 90 90 90 90 bc 90 90 90 90 90 53 41 90 90
90 90 90 90 90 90 04 90 90 90 90 2c 90 bf 90 90
90 90 e8 90 90 78 90 bb 90 90 1f 2b 87 90 4b 56
36 33 90 90 90 9c c3 90 90 81 90 e9 90 fa 90 90
90 72 90 a2 90 90 c7 90 90 92 90 90 88 90 90 90
3b 90 0c 90 80 90 90 90 90 2e 90 90 90 57 90 8e
07 90 a3 90 90 90 3d 90 fe 90 90 fc ea 90 38 90
3c f6 90 90 90 18 90 90 b8 90 90 90 2a 5d 5b 90
90 43 32 90 90 90 eb 90 90 90 90 90 83 89 90 90
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="f3_w95.da" crc="f7ca432b" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 0F 00 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 1b 0f 00 31 10 31
</part>
</rom>
<nvram index="4" size="49"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,103 @@
<misterromdescription>
<name>Undercover Cops (World)</name>
<mameversion>0245</mameversion>
<setname>uccops</setname>
<year>1992</year>
<manufacturer>Irem</manufacturer>
<category>Fighter</category>
<rbf>IremM92</rbf>
<rotation>horizontal</rotation>
<players>3</players>
<joystick>8-way</joystick>
<num_buttons>2</num_buttons>
<buttons default="B,A,Start,Select" names="Attack,Jump,-,-,-,-,Start,Coin,P2 Start,Pause"></buttons>
<switches default="00 00 00" base="16" page_id="1" page_name="Switches">
<dip bits="0,1" ids="2,3,4,1" name="Lives"></dip>
<dip bits="2,3" ids="Normal,Easy,Hard,Very Easy" name="Difficulty"></dip>
<dip bits="5" ids="Start,Any" name="Start Button"></dip>
<dip bits="6" ids="Off,On" name="Demo Sounds"></dip>
<dip bits="7" ids="Off,On" name="Service Mode"></dip>
<dip bits="8" ids="Off,On" name="Flip Screen"></dip>
<dip bits="9" ids="2 Players,3 Players" name="Cabinet"></dip>
<dip bits="12,15" ids="1C/1C,2C/1C,3C/1C,4C/1C,5C/1C,6C/1C,1C/2C,1C/3C,1C/4C,1C/5C,1C/6C,2C/3C,3C/2C,4C/3C,2S/1C,Free Play" name="Coin Mode"></dip>
</switches>
<rom index="0" zip="uccops.zip" md5="None">
<!-- board type -->
<part>00</part>
<!-- maincpu -->
<part>00 0c 00 00</part>
<interleave output="16">
<part name="ucc_e-h0.ic28" crc="240aa5f7" map="10" />
<part name="ucc_e-l0.ic39" crc="df9a4826" map="01" />
</interleave>
<interleave output="16">
<part name="ucc_h1.ic27" crc="8d29bcd6" map="10" />
<part name="ucc_l1.ic38" crc="a8a402d8" map="01" />
</interleave>
<!-- gfx1 tiles -->
<part>01 20 00 00</part>
<interleave output="32">
<part name="uc_w38m.rom" crc="130a40e5" map="0001" />
<part name="uc_w39m.rom" crc="e42ca144" map="0010" />
<part name="uc_w40m.rom" crc="c2961648" map="0100" />
<part name="uc_w41m.rom" crc="f5334b80" map="1000" />
</interleave>
<!-- gfx2 sprites -->
<part>02 40 00 00</part>
<interleave output="32">
<part name="uc_k16m.rom" crc="4a225f09" map="0001" />
<part name="uc_k17m.rom" crc="e4ed9a54" map="0010" />
<part name="uc_k18m.rom" crc="a626eb12" map="0100" />
<part name="uc_k19m.rom" crc="5df46549" map="1000" />
</interleave>
<!-- soundcpu -->
<part>03 02 00 00</part>
<interleave output="16">
<part name="ucc_e-sh0.ic30" crc="df90b198" map="10" />
<part name="ucc_e-sl0.ic31" crc="96c11aac" map="01" />
</interleave>
<!-- soundcpu key -->
<part>04 00 01 00</part>
<part>
1f 51 84 90 3d 09 0d 90 90 57 90 90 90 32 11 90
90 9c 90 90 4b 90 90 03 90 90 90 89 b0 90 90 90
90 bb 18 be 53 21 55 7c 90 90 47 58 f6 90 90 b2
06 90 2b 90 2f 0b fc 91 90 90 fa 81 83 40 38 90
90 90 49 85 d1 f5 07 e2 5e 1e 90 04 90 90 90 b1
c7 90 96 f2 b6 d2 c3 90 87 ba cb 88 90 b9 d0 b5
9a 80 a2 72 90 b4 90 aa 26 7d 52 33 2e bc 08 79
48 90 76 36 02 90 5b 12 8b e7 90 90 90 ab 90 4f
90 90 a8 e5 39 0e a9 90 90 14 90 ff 7f 90 90 27
90 01 90 90 e6 8a d3 90 90 8e 56 a5 92 90 90 f9
22 90 5f 90 90 a1 90 74 b8 90 46 05 eb cf bf 5d
24 90 9d 90 90 90 90 90 59 8d 3c f8 c5 90 f3 4e
90 90 50 c6 e9 fe 0a 90 99 86 90 90 af 8c 42 f7
90 41 90 a3 90 3a 2a 43 90 b3 e8 90 c4 35 78 25
75 90 b7 90 23 90 90 8f 90 90 2c 90 77 7e 90 0f
0c a0 bd 90 90 2d 29 ea 90 3b 73 90 fb 20 90 5a
</part>
<!-- iremg20 -->
<part>05 08 00 00</part>
<part name="uc_w42.rom" crc="d17d3fd6" />
</rom>
<!--hiscore support. see hiscore.sv for modified header values-->
<rom index="3" md5="none">
<part>
00 00 00 0F 05 FF 00 01 00 0F 00 01 00 01 02 00
00 0e 3e 9a 00 49 30 01
</part>
</rom>
<nvram index="4" size="73"></nvram>
</misterromdescription>

View File

@@ -0,0 +1,492 @@
import m92_pkg::*;
module IremM92_MiST(
output LED,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_HS,
output VGA_VS,
output AUDIO_L,
output AUDIO_R,
input SPI_SCK,
inout SPI_DO,
input SPI_DI,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
input CLOCK_27,
output [12:0] SDRAM_A,
inout [15:0] SDRAM_DQ,
output SDRAM_DQML,
output SDRAM_DQMH,
output SDRAM_nWE,
output SDRAM_nCAS,
output SDRAM_nRAS,
output SDRAM_nCS,
output [1:0] SDRAM_BA,
output SDRAM_CLK,
output SDRAM_CKE
);
`include "build_id.v"
//`define DEBUG 1
`define CORE_NAME "BMASTER"
wire [6:0] core_mod;
localparam CONF_STR = {
`CORE_NAME,";;",
"O3,Rotate Controls,Off,On;",
"O45,Scanlines,Off,25%,50%,75%;",
"O6,Swap Joystick,Off,On;",
//"O7,Blending,Off,On;",
"O8,Pause,Off,On;",
`ifdef DEBUG
"O9,Layer A,On,Off;",
"OA,Layer B,On,Off;",
"OB,Layer C,On,Off;",
"OC,FM Enable,On,Off;",
`endif
//"OD,Audio Filters,On,Off;",
"DIP;",
"R8192,Save EEPROM;",
"T0,Reset;",
"V,v1.0.",`BUILD_DATE
};
wire rotate = status[3];
wire [1:0] scanlines = status[5:4];
wire joyswap = status[6];
wire blend = 0;//status[7];
wire system_pause = status[8];
wire [2:0] dbg_en_layers = ~status[11:9];
wire dbg_fm_en = ~status[12];
wire dbg_sprite_freeze = 0;
wire filters = 0;//~status[13];
wire [1:0] orientation = {1'b0, core_mod[0]};
reg oneplayer = 0;
wire [15:0] dip_sw = status[31:16];
assign LED = ~ioctl_downl;
assign SDRAM_CKE = 1;
wire CLK_120M, CLK_40M;
wire pll_locked;
pll_mist pll(
.inclk0(CLOCK_27),
.c0(SDRAM_CLK),
.c1(CLK_120M),
.c2(CLK_40M),
.locked(pll_locked)
);
wire [31:0] status;
wire [1:0] buttons;
wire [1:0] switches;
wire [15:0] joystick_0;
wire [15:0] joystick_1;
wire [15:0] joystick_2;
wire [15:0] joystick_3;
wire scandoublerD;
wire ypbpr;
wire no_csync;
wire key_pressed;
wire [7:0] key_code;
wire key_strobe;
wire [9:0] conf_str_addr;
wire [7:0] conf_str_char;
always @(posedge CLK_40M)
conf_str_char <= CONF_STR[(($size(CONF_STR)>>3) - conf_str_addr - 1)<<3 +:8];
user_io #(
//.STRLEN(($size(CONF_STR)>>3)),
.ROM_DIRECT_UPLOAD(1'b1))
user_io(
.clk_sys (CLK_40M ),
.conf_str (CONF_STR ),
.SPI_CLK (SPI_SCK ),
.SPI_SS_IO (CONF_DATA0 ),
.SPI_MISO (SPI_DO ),
.SPI_MOSI (SPI_DI ),
.conf_addr (conf_str_addr ),
.conf_chr (conf_str_char ),
.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 ),
.joystick_2 (joystick_2 ),
.joystick_3 (joystick_3 ),
.status (status )
);
wire ioctl_downl;
wire ioctl_upl;
wire [7:0] ioctl_index;
wire ioctl_wr;
wire [24:0] ioctl_addr;
wire [7:0] ioctl_dout;
wire [7:0] ioctl_din;
data_io #(.ROM_DIRECT_UPLOAD(1'b1)) data_io(
.clk_sys ( CLK_40M ),
.SPI_SCK ( SPI_SCK ),
.SPI_SS2 ( SPI_SS2 ),
.SPI_SS4 ( SPI_SS4 ),
.SPI_DI ( SPI_DI ),
.SPI_DO ( SPI_DO ),
.clkref_n ( 1'b0 ),
.ioctl_download( ioctl_downl ),
.ioctl_upload ( ioctl_upl ),
.ioctl_index ( ioctl_index ),
.ioctl_wr ( ioctl_wr ),
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_dout ),
.ioctl_din ( ioctl_din )
);
// reset signal generation
reg reset = 1;
reg rom_loaded = 0;
always @(posedge CLK_40M) begin
reg ioctl_downlD;
ioctl_downlD <= ioctl_downl;
reset <= 0;
if (status[0] | buttons[1] | ~rom_loaded) reset <= 1;
if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1;
end
wire sdr_vram_req;
wire [24:0] sdr_vram_addr;
wire [31:0] sdr_vram_data;
wire [63:0] sdr_sprite_dout;
wire [24:0] sdr_sprite_addr;
wire sdr_sprite_req, sdr_sprite_ack;
wire [31:0] sdr_bg_data_a;
wire [24:0] sdr_bg_addr_a;
wire sdr_bg_req_a, sdr_bg_ack_a;
wire [31:0] sdr_bg_data_b;
wire [24:0] sdr_bg_addr_b;
wire sdr_bg_req_b, sdr_bg_ack_b;
wire [31:0] sdr_bg_data_c;
wire [24:0] sdr_bg_addr_c;
wire sdr_bg_req_c, sdr_bg_ack_c;
wire [15:0] sdr_cpu_dout, sdr_cpu_din;
wire [24:0] sdr_cpu_addr;
wire sdr_cpu_req, sdr_cpu_ack;
wire [1:0] sdr_cpu_wr_sel;
wire [15:0] sdr_audio_cpu_dout, sdr_audio_cpu_din;
wire [24:0] sdr_audio_cpu_addr;
wire sdr_audio_cpu_req, sdr_audio_cpu_ack;
wire [1:0] sdr_audio_cpu_wr_sel;
wire [24:0] sdr_rom_addr;
wire [15:0] sdr_rom_data;
wire [1:0] sdr_rom_be;
wire sdr_rom_req;
wire sdr_rom_ack;
wire [24:0] sample_rom_addr;
wire [63:0] sample_rom_dout;
wire sample_rom_req;
wire sample_rom_ack;
wire sdr_rom_write = ioctl_downl && (ioctl_index == 0);
wire [19:0] bram_addr;
wire [7:0] bram_data;
wire [3:0] bram_cs;
wire bram_wr;
board_cfg_t board_cfg;
sdram_4w_cl3 #(120) sdram
(
.*,
.init_n ( pll_locked ),
.clk ( CLK_120M ),
// Bank 0-1 ops
.port1_a ( sdr_rom_addr[24:1] ),
.port1_req ( sdr_rom_req ),
.port1_ack ( sdr_rom_ack ),
.port1_we ( sdr_rom_write ),
.port1_ds ( sdr_rom_be ),
.port1_d ( sdr_rom_data ),
.port1_q ( sdr_rom_ack ),
// Main CPU
.cpu1_rom_addr ( ),
.cpu1_rom_cs ( ),
.cpu1_rom_q ( ),
.cpu1_rom_valid( ),
.cpu1_ram_req ( sdr_cpu_req ),
.cpu1_ram_ack ( sdr_cpu_ack ),
.cpu1_ram_addr ( sdr_cpu_addr[24:1] ),
.cpu1_ram_we ( |sdr_cpu_wr_sel ),
.cpu1_ram_d ( sdr_cpu_din ),
.cpu1_ram_q ( sdr_cpu_dout ),
.cpu1_ram_ds ( |sdr_cpu_wr_sel ? sdr_cpu_wr_sel : 2'b11 ),
// Audio CPU
.cpu2_ram_req ( sdr_audio_cpu_req ),
.cpu2_ram_ack ( sdr_audio_cpu_ack ),
.cpu2_ram_addr ( sdr_audio_cpu_addr[24:1] ),
.cpu2_ram_we ( |sdr_audio_cpu_wr_sel ),
.cpu2_ram_d ( sdr_audio_cpu_din ),
.cpu2_ram_q ( sdr_audio_cpu_dout ),
.cpu2_ram_ds ( |sdr_audio_cpu_wr_sel ? sdr_audio_cpu_wr_sel : 2'b11 ),
// VRAM
.vram_addr ( sdr_vram_addr[24:1] ),
.vram_req ( sdr_vram_req ),
.vram_q ( sdr_vram_data ),
.vram_ack ( ),
// Bank 2-3 ops
.port2_a ( sdr_rom_addr[24:1] ),
.port2_req ( sdr_rom_req ),
.port2_ack ( sdr_rom_ack ),
.port2_we ( sdr_rom_write ),
.port2_ds ( sdr_rom_be ),
.port2_d ( sdr_rom_data ),
.port2_q ( sdr_rom_ack ),
.gfx1_req ( sdr_bg_req_a ),
.gfx1_ack ( sdr_bg_ack_a ),
.gfx1_addr ( sdr_bg_addr_a[24:1] ),
.gfx1_q ( sdr_bg_data_a ),
.gfx2_req ( sdr_bg_req_b ),
.gfx2_ack ( sdr_bg_ack_b ),
.gfx2_addr ( sdr_bg_addr_b[24:1] ),
.gfx2_q ( sdr_bg_data_b ),
.gfx3_req ( sdr_bg_req_c ),
.gfx3_ack ( sdr_bg_ack_c ),
.gfx3_addr ( sdr_bg_addr_c[24:1] ),
.gfx3_q ( sdr_bg_data_c ),
.sample_addr ( {sample_rom_addr[24:3], 2'b00} ),
.sample_q ( sample_rom_dout ),
.sample_req ( sample_rom_req ),
.sample_ack ( sample_rom_ack ),
.sp_addr ( sdr_sprite_addr[24:1] ),
.sp_req ( sdr_sprite_req ),
.sp_ack ( sdr_sprite_ack ),
.sp_q ( sdr_sprite_dout )
);
rom_loader rom_loader(
.sys_clk(CLK_40M),
.ioctl_downl(ioctl_downl),
.ioctl_wr(ioctl_wr && !ioctl_index),
.ioctl_data(ioctl_dout[7:0]),
.ioctl_wait(),
.sdr_addr(sdr_rom_addr),
.sdr_data(sdr_rom_data),
.sdr_be(sdr_rom_be),
.sdr_req(sdr_rom_req),
.sdr_ack(sdr_rom_ack),
.bram_addr(bram_addr),
.bram_data(bram_data),
.bram_cs(bram_cs),
.bram_wr(bram_wr),
.board_cfg(board_cfg)
);
wire [15:0] ch_left, ch_right;
wire [7:0] R, G, B;
wire HBlank, VBlank, HSync, VSync;
wire blankn = !(HBlank | VBlank);
wire ce_pix;
m92 m92(
.clk_sys(CLK_40M),
.ce_pix(ce_pix),
.reset_n(~reset),
.HBlank(HBlank),
.VBlank(VBlank),
.HSync(HSync),
.VSync(VSync),
.R(R),
.G(G),
.B(B),
.AUDIO_L(ch_left),
.AUDIO_R(ch_right),
.board_cfg(board_cfg),
.coin({2'd0, m_coin2, m_coin1}),
.start_buttons({m_four_players, m_three_players, m_two_players, m_one_player}),
.p1_input({m_fire1[5:0], m_up1, m_down1, m_left1, m_right1}),
.p2_input({m_fire2[5:0], m_up2, m_down2, m_left2, m_right2}),
.p3_input({m_fire3[5:0], m_up3, m_down3, m_left3, m_right3}),
.p4_input({m_fire4[5:0], m_up4, m_down4, m_left4, m_right4}),
.dip_sw(dip_sw),
.sdr_sprite_addr(sdr_sprite_addr),
.sdr_sprite_dout(sdr_sprite_dout),
.sdr_sprite_req(sdr_sprite_req),
.sdr_sprite_ack(sdr_sprite_ack),
.sdr_bg_data_a(sdr_bg_data_a),
.sdr_bg_addr_a(sdr_bg_addr_a),
.sdr_bg_req_a(sdr_bg_req_a),
.sdr_bg_ack_a(sdr_bg_ack_a),
.sdr_bg_data_b(sdr_bg_data_b),
.sdr_bg_addr_b(sdr_bg_addr_b),
.sdr_bg_req_b(sdr_bg_req_b),
.sdr_bg_ack_b(sdr_bg_ack_b),
.sdr_bg_data_c(sdr_bg_data_c),
.sdr_bg_addr_c(sdr_bg_addr_c),
.sdr_bg_req_c(sdr_bg_req_c),
.sdr_bg_ack_c(sdr_bg_ack_c),
.sdr_cpu_dout(sdr_cpu_dout),
.sdr_cpu_din(sdr_cpu_din),
.sdr_cpu_addr(sdr_cpu_addr),
.sdr_cpu_req(sdr_cpu_req),
.sdr_cpu_ack(sdr_cpu_ack),
.sdr_cpu_wr_sel(sdr_cpu_wr_sel),
.sdr_vram_req(sdr_vram_req),
.sdr_vram_addr(sdr_vram_addr),
.sdr_vram_data(sdr_vram_data),
.sdr_audio_cpu_dout(sdr_audio_cpu_dout),
.sdr_audio_cpu_din(sdr_audio_cpu_din),
.sdr_audio_cpu_addr(sdr_audio_cpu_addr),
.sdr_audio_cpu_req(sdr_audio_cpu_req),
.sdr_audio_cpu_ack(sdr_audio_cpu_ack),
.sdr_audio_cpu_wr_sel(sdr_audio_cpu_wr_sel),
.sdr_audio_addr(sample_rom_addr),
.sdr_audio_dout(sample_rom_dout),
.sdr_audio_req(sample_rom_req),
.sdr_audio_ack(sample_rom_ack),
.clk_bram(CLK_40M),
.bram_addr(bram_addr),
.bram_data(bram_data),
.bram_cs(bram_cs),
.bram_wr(bram_wr),
.ioctl_download(ioctl_downl && ioctl_index == 8'hFF),
.ioctl_wr(ioctl_wr),
.ioctl_addr(ioctl_addr),
.ioctl_dout(ioctl_dout),
.ioctl_upload(ioctl_upl && ioctl_index == 8'hFF),
.ioctl_din(ioctl_din),
`ifdef M72_DEBUG
.pause_rq(system_pause | debug_stall),
`else
.pause_rq(system_pause),
`endif
.dbg_en_layers(dbg_en_layers),
.dbg_solid_sprites(),
.sprite_freeze(dbg_sprite_freeze),
.dbg_fm_en(dbg_fm_en),
.en_audio_filters(filters)
);
mist_video #(.COLOR_DEPTH(6), .SD_HCNT_WIDTH(10)) mist_video(
.clk_sys ( CLK_40M ),
.SPI_SCK ( SPI_SCK ),
.SPI_SS3 ( SPI_SS3 ),
.SPI_DI ( SPI_DI ),
.R ( blankn ? R[7:2] : 0 ),
.G ( blankn ? G[7:2] : 0 ),
.B ( blankn ? B[7:2] : 0 ),
.HSync ( HSync ),
.VSync ( VSync ),
.VGA_R ( VGA_R ),
.VGA_G ( VGA_G ),
.VGA_B ( VGA_B ),
.VGA_VS ( VGA_VS ),
.VGA_HS ( VGA_HS ),
.rotate ( { orientation[1], rotate } ),
.ce_divider ( 3'd2 ),
.scandoubler_disable( scandoublerD ),
.scanlines ( scanlines ),
.blend ( blend ),
.ypbpr ( ypbpr ),
.no_csync ( no_csync )
);
dac #(
.C_bits(16))
dacl(
.clk_i(CLK_40M),
.res_n_i(1),
.dac_i({~ch_left[15], ch_left[14:0]}),
.dac_o(AUDIO_L)
);
dac #(
.C_bits(16))
dacr(
.clk_i(CLK_40M),
.res_n_i(1),
.dac_i({~ch_right[15], ch_right[14:0]}),
.dac_o(AUDIO_R)
);
wire m_up1, m_down1, m_left1, m_right1, m_up1B, m_down1B, m_left1B, m_right1B;
wire m_up2, m_down2, m_left2, m_right2, m_up2B, m_down2B, m_left2B, m_right2B;
wire m_up3, m_down3, m_left3, m_right3, m_up3B, m_down3B, m_left3B, m_right3B;
wire m_up4, m_down4, m_left4, m_right4, m_up4B, m_down4B, m_left4B, m_right4B;
wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
wire [11:0] m_fire1, m_fire2, m_fire3, m_fire4;
arcade_inputs inputs (
.clk ( CLK_40M ),
.key_strobe ( key_strobe ),
.key_pressed ( key_pressed ),
.key_code ( key_code ),
.joystick_0 ( joystick_0 ),
.joystick_1 ( joystick_1 ),
.joystick_2 ( joystick_2 ),
.joystick_3 ( joystick_3 ),
.rotate ( rotate ),
.orientation ( orientation ),
.joyswap ( joyswap ),
.oneplayer ( oneplayer ),
.controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
.player1 ( {m_up1B, m_down1B, m_left1B, m_right1B, m_fire1, m_up1, m_down1, m_left1, m_right1} ),
.player2 ( {m_up2B, m_down2B, m_left2B, m_right2B, m_fire2, m_up2, m_down2, m_left2, m_right2} ),
.player3 ( {m_up3B, m_down3B, m_left3B, m_right3B, m_fire3, m_up3, m_down3, m_left3, m_right3} ),
.player4 ( {m_up4B, m_down4B, m_left4B, m_right4B, m_fire4, m_up4, m_down4, m_left4, m_right4} )
);
endmodule

View 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 "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

View File

@@ -0,0 +1,175 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
`timescale 1ns / 1ps
module dualport_ram #(
parameter width = 8,
parameter widthad = 10
) (
// Port A
input wire clock_a,
input wire wren_a,
input wire [widthad-1:0] address_a,
input wire [width-1:0] data_a,
output reg [width-1:0] q_a,
// Port B
input wire clock_b,
input wire wren_b,
input wire [widthad-1:0] address_b,
input wire [width-1:0] data_b,
output reg [width-1:0] q_b
);
// Shared ramory
reg [width-1:0] ram[(2**widthad)-1:0];
// Port A
always @(posedge clock_a) begin
if (wren_a) begin
ram[address_a] <= data_a;
q_a <= data_a;
end else begin
q_a <= ram[address_a];
end
end
// Port B
always @(posedge clock_b) begin
if(wren_b) begin
q_b <= data_b;
ram[address_b] <= data_b;
end else begin
q_b <= ram[address_b];
end
end
endmodule
module singleport_ram #(
parameter width = 8,
parameter widthad = 10,
parameter name = "NONE"
) (
input wire clock,
input wire wren,
input wire [widthad-1:0] address,
input wire [width-1:0] data,
output reg [width-1:0] q
);
altsyncram altsyncram_component (
.address_a (address),
.clock0 (clock),
.data_a (data),
.wren_a (wren),
.q_a (q),
.aclr0 (1'b0),
.aclr1 (1'b0),
.address_b (1'b1),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b (1'b1),
.eccstatus (),
.q_b (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone V",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2**widthad,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.ram_block_type = "M10K",
altsyncram_component.read_during_write_mode_port_a = "DONT_CARE",
altsyncram_component.widthad_a = widthad,
altsyncram_component.width_a = width,
altsyncram_component.width_byteena_a = 1;
endmodule
module singleport_unreg_ram #(
parameter width = 8,
parameter widthad = 10,
parameter name = "NONE"
) (
input wire clock,
input wire wren,
input wire [widthad-1:0] address,
input wire [width-1:0] data,
output wire [width-1:0] q
);
altsyncram altsyncram_component (
.address_a (address),
.clock0 (clock),
.data_a (data),
.wren_a (wren),
.q_a (q),
.aclr0 (1'b0),
.aclr1 (1'b0),
.address_b (1'b1),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b (1'b1),
.eccstatus (),
.q_b (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone V",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2**widthad,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.ram_block_type = "M10K",
altsyncram_component.read_during_write_mode_port_a = "DONT_CARE",
altsyncram_component.widthad_a = widthad,
altsyncram_component.width_a = width,
altsyncram_component.width_byteena_a = 1;
endmodule

View File

@@ -0,0 +1,169 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module eeprom_28C64 #(parameter WRITE_CYCLES=0) (
// Hardware ports
input clk,
input reset,
input ce,
input wr,
input rd,
input [12:0] addr,
input [7:0] data,
output [7:0] q,
output ready,
// MiSTer support
output reg modified,
input ioctl_download,
input ioctl_wr,
input [12:0] ioctl_addr,
input [7:0] ioctl_dout,
input ioctl_upload,
output [7:0] ioctl_din,
input ioctl_rd
);
wire [7:0] q0;
dualport_ram #(8, 13) mem(
.clock_a(clk),
.wren_a(wr),
.address_a(addr),
.data_a(data),
.q_a(q0),
.clock_b(clk),
.wren_b(ioctl_download & ioctl_wr),
.address_b(ioctl_addr),
.data_b(ioctl_dout),
.q_b(ioctl_din)
);
wire busy;
reg [31:0] write_timer;
reg prev_upload;
assign ready = write_timer == 32'd0;
assign busy = ~ready;
assign q = ready ? q0 : ( ~q0 );
always_ff @(posedge clk) begin
if (reset) begin
write_timer <= 32'd0;
modified <= 0;
end else if (ce) begin
if (ioctl_upload & ~prev_upload) modified <= 0;
prev_upload <= ioctl_upload;
if (wr) modified <= 1;
if (busy) begin
write_timer <= write_timer - 32'd1;
end else if (wr) begin
write_timer <= WRITE_CYCLES;
end
end
end
endmodule
// This is completely untested. I wrote it and then realized it was not the eeprom that the M92 uses.
// Keeping it here in case it comes in useful at some point. It is an Atmel 28 series eeprom with 64
// byte pages.
module eeprom_28xx_paged(
input clk,
input reset,
input ce,
input wr,
input rd,
input [13:0] addr,
input [7:0] data,
output reg [7:0] q
);
reg [7:0] mem[16384];
reg [7:0] write_page;
reg [5:0] write_addrs[64];
reg [7:0] write_bytes[64];
reg [6:0] write_index;
reg [6:0] store_index;
reg write_queuing;
reg store_pending;
reg [31:0] write_timer;
reg [7:0] last_byte;
always @(posedge clk) begin
if (reset) begin
store_pending <= 0;
write_queuing <= 0;
write_index <= 7'd0;
store_index <= 7'd0;
end else if (ce) begin
if (store_pending) begin
if (store_index == write_index) begin
store_pending <= 0;
end else begin
mem[{write_page, write_addrs[store_index]}] <= write_bytes[store_index];
store_index <= store_index + 7'd1;
end
end else if (wr) begin
write_timer <= 32'd0;
write_queuing <= 1;
write_addrs[write_index] <= addr[5:0];
write_bytes[write_index] <= data;
write_index <= write_index + 7'd1;
write_page <= addr[13:6];
last_byte <= data;
if (write_index == 7'd63) begin
store_pending <= 1;
store_index <= 7'd0;
write_queuing <= 0;
end
end else if (write_queuing) begin
write_timer <= write_timer + 32'd1;
if (write_timer == 32'd100_000) begin
store_pending <= 1;
store_index <= 7'd0;
write_queuing <= 0;
end
end
if (rd) begin
if (write_queuing | store_pending) begin
q <= { ~last_byte[7], last_byte[6:0] };
last_byte[6] <= ~last_byte[6];
end else begin
q <= mem[addr];
end
end
end
end
endmodule

View File

@@ -0,0 +1,306 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module ga20_channel(
input clk,
input reset,
input ce,
input cs,
input rd,
input wr,
input [2:0] addr,
input [7:0] din,
output reg [7:0] dout,
output [19:0] sample_addr,
output reg sample_req,
input sample_ack,
input [63:0] sample_din,
output [15:0] sample_out
);
reg step;
reg [5:0] volume;
reg [7:0] rate;
reg [19:0] start_addr, end_addr, cur_addr;
reg [1:0] play;
reg [8:0] rate_cnt;
reg [7:0] sample_s8;
reg play_set;
wire [7:0] sample_data;
assign sample_addr = cur_addr;
always @(*) begin
case(cur_addr[2:0])
3'd0: sample_data = sample_din[ 7: 0];
3'd1: sample_data = sample_din[15: 8];
3'd2: sample_data = sample_din[23:16];
3'd3: sample_data = sample_din[31:24];
3'd4: sample_data = sample_din[39:32];
3'd5: sample_data = sample_din[47:40];
3'd6: sample_data = sample_din[55:48];
default: sample_data = sample_din[63:56];
endcase;
end
always_ff @(posedge clk, posedge reset) begin
if (reset) begin
volume <= 6'd00;
play <= 2'd0;
step <= 0;
play_set <= 0;
sample_s8 <= 8'h00;
end else begin
if (cs & rd) begin
if (addr == 3'd7) dout <= { 7'd0, play[1] };
end else if (cs & wr) begin
case (addr)
3'd0: start_addr[11:0] <= { din, 4'b0000 };
3'd1: start_addr[19:12] <= din;
3'd2: end_addr[11:0] <= { din, 4'b0000 };
3'd3: end_addr[19:12] <= din;
3'd4: rate <= din;
3'd5: volume <= din[5:0];
3'd6: begin
play <= din[1:0];
play_set <= din[1];
end
endcase
end
if (ce && sample_req == sample_ack) begin
step <= ~step;
if (~step) begin
// first cycle
if (play_set) begin
cur_addr <= start_addr;
sample_req <= ~sample_req;
play_set <= 0;
rate_cnt <= rate + 9'd2;
end else begin
rate_cnt <= rate_cnt + 9'd2;
end
end else begin
// second cycle
if (~play_set & play[1]) begin
if (sample_data == 8'd0) begin
play[1] <= 0;
sample_s8 <= 8'h00;
end else begin
sample_s8 <= { ~sample_data[7], sample_data[6:0] };
if (rate_cnt[8]) begin
cur_addr <= cur_addr + 20'd1;
if (cur_addr[2:0] == 3'b111) begin
sample_req <= ~sample_req;
end
rate_cnt <= rate_cnt + { 1'b1, rate };
if (cur_addr == end_addr) begin
if (play[0]) begin
cur_addr <= start_addr;
sample_req <= ~sample_req;
end else begin
sample_s8 <= 8'h00;
play[1] <= 0;
end
end
end
end
end
end
end
end
end
// apply attenuation after filtering
always_ff @(posedge clk) begin
bit [7:0] vol_one;
vol_one = { 2'd0, volume } + 8'd1;
sample_out <= $signed(sample_s8) * $signed(vol_one);
end
endmodule
module ga20(
input clk,
input reset,
input filter_en,
input ce,
input cs,
input rd,
input wr,
input [4:0] addr,
input [7:0] din,
output [7:0] dout,
output reg sample_rom_req,
output reg [19:0] sample_rom_addr,
input sample_rom_ack,
input [63:0] sample_rom_din,
output [15:0] sample_out
);
reg [2:0] step;
wire ce0 = step[2:1] == 2'd0;
wire ce1 = step[2:1] == 2'd1;
wire ce2 = step[2:1] == 2'd2;
wire ce3 = step[2:1] == 2'd3;
wire cs0 = cs && addr[4:3] == 2'd0;
wire cs1 = cs && addr[4:3] == 2'd1;
wire cs2 = cs && addr[4:3] == 2'd2;
wire cs3 = cs && addr[4:3] == 2'd3;
wire [7:0] dout0, dout1, dout2, dout3;
assign dout = cs0 ? dout0 : cs1 ? dout1 : cs2 ? dout2 : dout3;
wire [19:0] sample_addr[4];
wire [15:0] sample_out0, sample_out1, sample_out2, sample_out3;
wire [3:0] sample_req;
reg [3:0] sample_ack;
reg [63:0] sample_data[4];
reg [3:0] req_pending;
ga20_channel ch0( .clk(clk), .reset(reset), .ce(ce & ce0), .cs(cs0), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout0), .sample_addr(sample_addr[0]), .sample_req(sample_req[0]), .sample_ack(sample_ack[0]), .sample_din(sample_data[0]), .sample_out(sample_out0));
ga20_channel ch1( .clk(clk), .reset(reset), .ce(ce & ce1), .cs(cs1), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout1), .sample_addr(sample_addr[1]), .sample_req(sample_req[1]), .sample_ack(sample_ack[1]), .sample_din(sample_data[1]), .sample_out(sample_out1));
ga20_channel ch2( .clk(clk), .reset(reset), .ce(ce & ce2), .cs(cs2), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout2), .sample_addr(sample_addr[2]), .sample_req(sample_req[2]), .sample_ack(sample_ack[2]), .sample_din(sample_data[2]), .sample_out(sample_out2));
ga20_channel ch3( .clk(clk), .reset(reset), .ce(ce & ce3), .cs(cs3), .rd(rd), .wr(wr), .addr(addr[2:0]), .din(din), .dout(dout3), .sample_addr(sample_addr[3]), .sample_req(sample_req[3]), .sample_ack(sample_ack[3]), .sample_din(sample_data[3]), .sample_out(sample_out3));
always_ff @(posedge clk, posedge reset) begin
if (reset) begin
sample_data[0] <= 0;
sample_data[1] <= 0;
sample_data[2] <= 0;
sample_data[3] <= 0;
req_pending <= 0;
end else begin
if (req_pending[0]) begin
if (sample_rom_req == sample_rom_ack) begin
req_pending[0] <= 0;
sample_ack[0] <= sample_req[0];
sample_data[0] <= sample_rom_din;
end
end else if (req_pending[1]) begin
if (sample_rom_req == sample_rom_ack) begin
req_pending[1] <= 0;
sample_ack[1] <= sample_req[1];
sample_data[1] <= sample_rom_din;
end
end else if (req_pending[2]) begin
if (sample_rom_req == sample_rom_ack) begin
req_pending[2] <= 0;
sample_ack[2] <= sample_req[2];
sample_data[2] <= sample_rom_din;
end
end else if (req_pending[3]) begin
if (sample_rom_req == sample_rom_ack) begin
req_pending[3] <= 0;
sample_ack[3] <= sample_req[3];
sample_data[3] <= sample_rom_din;
end
end else if (sample_req[0] != sample_ack[0]) begin
sample_rom_addr <= sample_addr[0];
sample_rom_req <= ~sample_rom_req;
req_pending[0] <= 1;
end else if (sample_req[1] != sample_ack[1]) begin
sample_rom_addr <= sample_addr[1];
sample_rom_req <= ~sample_rom_req;
req_pending[1] <= 1;
end else if (sample_req[2] != sample_ack[2]) begin
sample_rom_addr <= sample_addr[2];
sample_rom_req <= ~sample_rom_req;
req_pending[2] <= 1;
end else if (sample_req[3] != sample_ack[3]) begin
sample_rom_addr <= sample_addr[3];
sample_rom_req <= ~sample_rom_req;
req_pending[3] <= 1;
end
end
end
always_ff @(posedge clk, posedge reset) begin
if (reset) begin
step <= 3'd0;
end else begin
reg prev_ce = 0;
prev_ce <= ce;
if (~ce & prev_ce) begin
step <= step + 3'd1;
end
end
end
reg [15:0] sample_combined;
// 9685hz 2nd order 10749hz 1st order
localparam CX = 0.00000741947949554119;
localparam CY0 = -2.95726738834813529522;
localparam CY1 = 2.91526970775390958934;
localparam CY2 = -0.95799698165074131939;
reg [15:0] sample_filtered;
IIR_filter #(
.use_params(1),
.stereo(0),
.coeff_x(CX),
.coeff_x0(3),
.coeff_x1(3),
.coeff_x2(1),
.coeff_y0(CY0),
.coeff_y1(CY1),
.coeff_y2(CY2)) lpf_sample (
.clk(clk),
.reset(reset),
.ce(ce),
.sample_ce(ce),
.cx(), .cx0(), .cx1(), .cx2(), .cy0(), .cy1(), .cy2(),
.input_l(sample_combined),
.output_l(sample_filtered),
.input_r(),
.output_r()
);
always_ff @(posedge clk) begin
sample_combined <= sample_out0 + sample_out1 + sample_out2 + sample_out3;
end
assign sample_out = filter_en ? sample_filtered : sample_combined;
endmodule

View File

@@ -0,0 +1,238 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module GA21(
input clk,
input ce,
input reset,
input [15:0] din,
output [15:0] dout,
input [10:0] addr,
input reg_cs,
input buf_cs,
input wr,
output busy,
output [15:0] obj_dout,
input [15:0] obj_din,
output [10:0] obj_addr,
output obj_we,
output buffer_we,
output [10:0] buffer_addr,
output [15:0] buffer_dout,
input [15:0] buffer_din,
input [9:0] count,
output [12:0] pal_addr,
output [15:0] pal_dout,
input [15:0] pal_din,
output pal_we,
output pal_cs
// TODO pal latching and OE signals?
);
reg [7:0] reg_direct_access;
reg [7:0] reg_obj_ptr;
reg [15:0] reg_copy_mode;
wire [2:0] pal_addr_high = reg_copy_mode[10:8];
wire layer_ordered_copy = reg_copy_mode[0];
wire full_copy = reg_copy_mode[7] & ~reg_copy_mode[0];
reg obj_addr_high = 0;
enum {
IDLE,
IDLE_DELAY,
INIT_COPY_PAL,
COPY_PAL,
INIT_CLEAR_OBJ,
CLEAR_OBJ,
INIT_COPY_OBJ,
COPY_OBJ
} copy_state = IDLE;
reg [10:0] copy_counter;
reg [15:0] copy_dout;
reg [10:0] copy_obj_addr;
reg [9:0] copy_pal_addr;
reg [2:0] copy_obj_word;
reg [8:0] copy_obj_idx;
reg [10:0] buffer_src_addr;
reg [10:0] next_buffer_src_addr;
reg [2:0] copy_layer;
reg copy_this_obj;
reg copy_obj_we, copy_pal_we;
wire direct_access_pal = reg_direct_access[1];
wire direct_access_obj = reg_direct_access[0];
always_ff @(posedge clk or posedge reset) begin
bit [8:0] obj_y;
bit [1:0] obj_height;
bit [1:0] obj_log2_cols;
bit [2:0] obj_layer;
bit [3:0] obj_cols;
bit [8:0] next_obj_idx;
if (reset) begin
copy_state <= IDLE;
reg_direct_access <= 0;
reg_obj_ptr <= 0;
reg_copy_mode <= 0;
copy_obj_we <= 0;
copy_pal_we <= 0;
end else begin
if (reg_cs & wr) begin
if (addr == 11'h0) reg_obj_ptr <= din[7:0];
if (addr == 11'h1) reg_direct_access <= din[7:0];
if (addr == 11'h2) reg_copy_mode <= din[15:0];
if (addr == 11'h4) begin
copy_state <= INIT_COPY_PAL;
end
end
if (ce) begin
copy_obj_we <= 0;
copy_pal_we <= 0;
case(copy_state)
IDLE_DELAY: copy_state <= IDLE;
IDLE: begin
end
INIT_COPY_PAL: begin
buffer_src_addr <= 11'h400;
copy_pal_addr <= ~10'd0;
copy_state <= COPY_PAL;
end
COPY_PAL: begin
if (buffer_src_addr == 11'h000) begin
copy_state <= INIT_CLEAR_OBJ;
end else begin
buffer_src_addr <= buffer_src_addr + 11'd1;
copy_pal_addr <= copy_pal_addr + 10'd1;
copy_dout <= buffer_din;
copy_pal_we <= 1;
end
end
INIT_CLEAR_OBJ: begin
copy_dout <= 16'd0;
copy_obj_addr <= 11'd0;
copy_obj_we <= 1;
copy_state <= CLEAR_OBJ;
end
CLEAR_OBJ: begin
copy_obj_addr <= copy_obj_addr + 11'd1;
copy_obj_we <= 1;
if (&copy_obj_addr) begin
copy_state <= INIT_COPY_OBJ;
end
end
INIT_COPY_OBJ: begin
copy_state <= COPY_OBJ;
copy_this_obj <= 0;
buffer_src_addr <= 11'd0;
copy_obj_word <= 2'd0;
copy_layer <= 3'd0;
copy_obj_idx <= 9'h100 - {1'b0, reg_obj_ptr};
end
COPY_OBJ: begin
copy_dout <= buffer_din;
buffer_src_addr <= buffer_src_addr + 11'd1;
copy_obj_word <= copy_obj_word + 2'd1;
copy_obj_addr <= {1'b0, copy_obj_idx[7:0], copy_obj_word[1:0]};
copy_obj_we <= copy_this_obj;
if (buffer_src_addr[1:0] == 2'b00) begin
if (copy_obj_idx == 9'd0) begin
copy_state <= IDLE;
copy_obj_we <= 0;
end else begin
obj_y = buffer_din[8:0];
obj_height = buffer_din[10:9];
obj_log2_cols = buffer_din[12:11];
obj_layer = buffer_din[15:13];
obj_cols = 4'd1 << obj_log2_cols;
if (full_copy || (layer_ordered_copy == 0 && obj_layer != 3'd7) || (obj_layer == copy_layer)) begin
copy_this_obj <= 1;
copy_obj_we <= 1;
next_obj_idx = copy_obj_idx - obj_cols;
if (next_obj_idx[8]) begin // wrapped around
copy_state <= IDLE;
copy_obj_we <= 0;
end else begin
copy_obj_addr <= {1'b0, next_obj_idx, copy_obj_word[1:0]};
copy_obj_idx <= next_obj_idx;
end
end else begin
copy_this_obj <= 0;
copy_obj_we <= 0;
end
next_buffer_src_addr <= buffer_src_addr + { obj_cols, 2'b00 };
end
end else if (buffer_src_addr[1:0] == 2'b11) begin
if (next_buffer_src_addr[10]) begin // end of input
if (layer_ordered_copy && (copy_layer != 3'd6)) begin
copy_layer <= copy_layer + 3'd1;
buffer_src_addr <= 11'd0;
end else begin
copy_state <= IDLE_DELAY; // delay for one cycle so final write can complete
end
end else begin
buffer_src_addr <= next_buffer_src_addr;
end
end
end
endcase
end
end
end
assign dout = buf_cs ? (direct_access_obj ? obj_din : (direct_access_pal ? pal_din : buffer_din)) : 16'd0;
assign busy = copy_state != IDLE;
assign buffer_we = ~busy & buf_cs & wr & ~direct_access_obj & ~direct_access_pal;
assign buffer_addr = busy ? buffer_src_addr : addr;
assign buffer_dout = din;
assign obj_dout = direct_access_obj ? din : copy_dout;
assign obj_addr = direct_access_obj ? addr : (busy ? copy_obj_addr : {obj_addr_high, count});
assign obj_we = direct_access_obj ? (buf_cs & wr) : (busy ? copy_obj_we : 1'b0);
assign pal_dout = direct_access_pal ? din : copy_dout;
assign pal_addr = {pal_addr_high, direct_access_pal ? addr[9:0] : (busy ? copy_pal_addr : 10'd0)};
assign pal_we = direct_access_pal ? (buf_cs & wr) : (busy ? copy_pal_we : 1'b0);
assign pal_cs = direct_access_pal ? buf_cs : 1'b0;
endmodule

View File

@@ -0,0 +1,39 @@
module ga21_tb;
reg clk;
reg buf_cs;
reg [10:0] addr;
reg reg_cs;
reg reset;
reg wr;
GA21 ga21( .clk(clk), .ce(1), .reset(reset), .buf_cs(0), .wr(wr), .reg_cs(reg_cs), .addr(addr));
always begin
clk = 1'b1;
#1;
clk = 1'b0;
#1;
end
initial begin
reset = 1;
buf_cs = 0;
reg_cs = 0;
wr = 0;
#5;
reset = 0;
#5;
addr = 'h9008 >> 1;
reg_cs = 1;
wr = 1;
#2;
reg_cs = 0;
wr = 0;
#1000000;
$stop;
end
endmodule

View File

@@ -0,0 +1,171 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
import m92_pkg::*;
module GA22 (
input clk,
input ce, // 13.33Mhz
input ce_pix, // 6.66Mhz
input reset,
output reg [11:0] color,
input NL,
input hpulse,
input vpulse,
output reg [9:0] count,
input [63:0] obj_in,
input [63:0] sdr_data,
output reg [24:0] sdr_addr,
output reg sdr_req,
input sdr_ack,
output reg sdr_refresh,
input dbg_solid_sprites
);
reg [6:0] linebuf_color;
reg linebuf_prio;
reg [9:0] linebuf_x;
reg linebuf_write;
reg linebuf_flip;
reg scan_toggle = 0;
reg [9:0] scan_pos = 0;
wire [9:0] scan_pos_nl = scan_pos ^ {10{NL}};
wire [11:0] scan_out;
double_linebuf line_buffer(
.clk(clk),
.ce_pix(ce_pix),
.scan_pos(scan_pos_nl),
.scan_toggle(scan_toggle),
.scan_out(scan_out),
.bitplanes(dbg_solid_sprites ? 64'hffff_ffff_ffff_ffff : sdr_data),
.flip(linebuf_flip),
.color(linebuf_color),
.prio(linebuf_prio),
.pos(linebuf_x),
.we(linebuf_write),
.idle()
);
reg [63:0] obj_data;
wire [8:0] obj_org_y = obj_data[8:0];
wire [1:0] obj_height = obj_data[10:9];
wire [1:0] obj_width = obj_data[12:11];
wire [2:0] obj_layer = obj_data[15:13];
wire [15:0] obj_code = obj_data[31:16];
wire [6:0] obj_color = obj_data[38:32];
wire obj_pri = obj_data[39];
wire obj_flipx = obj_data[40];
wire obj_flipy = obj_data[41];
wire [9:0] obj_org_x = obj_data[57:48];
always_ff @(posedge clk) begin
reg visible;
reg [3:0] span;
reg [3:0] end_span;
reg [8:0] V;
reg [15:0] code;
reg [8:0] height_px;
reg [3:0] width;
reg [8:0] rel_y;
reg [8:0] row_y;
linebuf_write <= 0;
if (reset) begin
V <= 9'd0;
end else if (ce) begin
count <= count + 10'd1;
sdr_refresh <= 0;
if (ce_pix) begin
color <= scan_out[11:0];
scan_pos <= scan_pos + 10'd1;
if (hpulse) begin
count <= 10'd0;
V <= V + 9'd1;
scan_pos <= 10'd44;
scan_toggle <= ~scan_toggle;
span <= 0;
end_span <= 0;
visible <= 0;
sdr_refresh <= 1;
end
end
if (vpulse) begin
V <= 9'd126;
end
case(count[1:0])
0: begin
linebuf_flip <= obj_flipx;
linebuf_color <= obj_color;
linebuf_prio <= obj_pri;
linebuf_x <= obj_org_x + ( 10'd16 * span );
linebuf_write <= visible;
if (span == end_span) begin
span <= 4'd0;
obj_data <= obj_in;
end else begin
span <= span + 4'd1;
end
end
1: begin
end_span <= ( 4'd1 << obj_width ) - 1'd1;
height_px = 9'd16 << obj_height;
width = 4'd1 << obj_width;
rel_y = V + obj_org_y + ( 9'd16 << obj_height );
row_y = obj_flipy ? (height_px - rel_y - 9'd1) : rel_y;
if (rel_y < height_px) begin
code = obj_code + row_y[8:4] + ( ( obj_flipx ? ( width - span - 16'd1 ) : span ) * 16'd8 );
sdr_addr <= REGION_SPRITE.base_addr[24:0] + { code[15:0], row_y[3:0], 3'b000 };
sdr_req <= ~sdr_req;
visible <= 1;
end else begin
visible <= 0;
sdr_refresh <= 1;
end
end
2: begin
sdr_refresh <= 1;
end
3: begin
sdr_refresh <= 0;
end
endcase
end
end
endmodule

View File

@@ -0,0 +1,191 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module linebuf(
input clk,
input ce_pix,
input [9:0] scan_pos,
input scan_active,
output [11:0] scan_out,
input [11:0] color0,
input [11:0] color1,
input [9:0] draw_pos,
input draw_we
);
wire [11:0] scan_odd, scan_even;
assign scan_out = scan_pos[0] ? scan_odd : scan_even;
wire [11:0] odd_color = draw_pos[0] ? color0 : color1;
wire [11:0] even_color = draw_pos[0] ? color1 : color0;
wire [8:0] odd_addr = draw_pos[9:1];
wire [8:0] even_addr = draw_pos[0] ? draw_pos[9:1] + 9'd1 : draw_pos[9:1];
dualport_ram #(.widthad(9), .width(12)) buffer_odd
(
.clock_a(clk),
.address_a(scan_pos[9:1]),
.q_a(scan_odd),
.wren_a(scan_active & ce_pix & scan_pos[0]),
.data_a(12'd0),
.clock_b(clk),
.address_b(odd_addr),
.data_b(odd_color),
.wren_b((~scan_active) & draw_we & |odd_color[3:0]),
.q_b()
);
dualport_ram #(.widthad(9), .width(12)) buffer_even
(
.clock_a(clk),
.address_a(scan_pos[9:1]),
.q_a(scan_even),
.wren_a(scan_active & ce_pix & ~scan_pos[0]),
.data_a(12'd0),
.clock_b(clk),
.address_b(even_addr),
.data_b(even_color),
.wren_b((~scan_active) & draw_we & |even_color[3:0]),
.q_b()
);
endmodule
module double_linebuf(
input clk,
input ce_pix,
input [9:0] scan_pos,
input scan_toggle,
output [11:0] scan_out,
input [63:0] bitplanes,
input flip,
input [6:0] color,
input prio,
input [9:0] pos,
input we,
output idle
);
wire [11:0] scan_out_0, scan_out_1;
assign scan_out = scan_toggle ? scan_out_0 : scan_out_1;
reg [11:0] color0;
reg [11:0] color1;
reg [9:0] draw_pos;
reg draw_we = 0;
linebuf buf_0(
.clk(clk),
.ce_pix(ce_pix),
.scan_active(scan_toggle),
.scan_out(scan_out_0),
.scan_pos(scan_pos),
.color0(color0),
.color1(color1),
.draw_pos(draw_pos),
.draw_we(draw_we)
);
linebuf buf_1(
.clk(clk),
.ce_pix(ce_pix),
.scan_active(~scan_toggle),
.scan_out(scan_out_1),
.scan_pos(scan_pos),
.color0(color0),
.color1(color1),
.draw_pos(draw_pos),
.draw_we(draw_we)
);
// d is 16 pixels stored as 2 sets of 4 bitplanes
// d[31:0] is 8 pixels, made up from planes d[7:0], d[15:8], etc
// d[63:32] is 8 pixels made up from planes d[39:32], d[47:40], etc
// Returns 16 pixels stored as 4 bit planes d[15:0], d[31:16], etc
function [63:0] deswizzle(input [63:0] d, input rev);
begin
integer i;
bit [7:0] plane[8];
bit [7:0] t;
for( i = 0; i < 8; i = i + 1 ) begin
t = d[(i*8) +: 8];
plane[i] = rev ? { t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7] } : t;
end
deswizzle[15:0] = rev ? { plane[4], plane[0] } : { plane[0], plane[4] };
deswizzle[31:16] = rev ? { plane[5], plane[1] } : { plane[1], plane[5] };
deswizzle[47:32] = rev ? { plane[6], plane[2] } : { plane[2], plane[6] };
deswizzle[63:48] = rev ? { plane[7], plane[3] } : { plane[3], plane[7] };
end
endfunction
reg [3:0] count = 0;
assign idle = count == 4'd0;
always_ff @(posedge clk) begin
reg [63:0] bits_r;
bit [63:0] bits;
reg [6:0] color_r;
reg prio_r;
draw_we <= 0;
if (count != 4'd0) begin
color0 <= { prio_r, color_r, bits_r[63], bits_r[47], bits_r[31], bits_r[15] };
color1 <= { prio_r, color_r, bits_r[62], bits_r[46], bits_r[30], bits_r[14] };
draw_pos <= draw_pos + 10'd2;
draw_we <= 1;
bits_r <= { bits_r[61:0], 2'b00 };
count <= count - 4'd1;
end
if (we) begin
bits = deswizzle(bitplanes, flip);
color0 <= { prio, color, bits[63], bits[47], bits[31], bits[15] };
color1 <= { prio, color, bits[62], bits[46], bits[30], bits[14] };
draw_we <= 1;
draw_pos <= pos;
bits_r <= { bits[61:0], 2'b00 };
color_r <= color;
prio_r <= prio;
count <= 4'd7;
end
end
endmodule

View File

@@ -0,0 +1,312 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module GA23(
input clk,
input ce,
input paused,
input reset,
input io_wr,
input [15:0] addr,
input [15:0] cpu_din,
output reg [14:0] vram_addr,
output reg vram_req,
input [31:0] vram_din,
input large_tileset,
input [31:0] sdr_data_a,
output [24:0] sdr_addr_a,
output sdr_req_a,
input sdr_ack_a,
input [31:0] sdr_data_b,
output [24:0] sdr_addr_b,
output sdr_req_b,
input sdr_ack_b,
input [31:0] sdr_data_c,
output [24:0] sdr_addr_c,
output sdr_req_c,
input sdr_ack_c,
output vblank,
output vsync,
output hblank,
output hsync,
output hpulse,
output vpulse,
output hint,
output reg [10:0] color_out,
output reg prio_out,
input [2:0] dbg_en_layers
);
//// VIDEO TIMING
reg [9:0] hcnt, vcnt;
reg [9:0] hint_line;
assign hsync = hcnt < 10'd65 || hcnt > 10'd448;
assign hblank = hcnt < 10'd104 || hcnt > 10'd422;
assign vblank = vcnt > 10'd113 && vcnt < 10'd136;
assign vsync = vcnt > 10'd119 && vcnt < 10'd125;
assign hpulse = hcnt == 10'd48;
assign vpulse = (vcnt == 10'd124 && hcnt > 10'd260) || (vcnt == 10'd125 && hcnt < 10'd260);
assign hint = vcnt == hint_line && hcnt > 10'd422 && ~paused;
always_ff @(posedge clk) begin
if (ce) begin
hcnt <= hcnt + 10'd1;
if (hcnt == 10'd471) begin
hcnt <= 10'd48;
vcnt <= vcnt + 10'd1;
if (vcnt == 10'd375) begin
vcnt <= 10'd114;
end
end
end
end
wire [21:0] rom_addr[3];
wire [31:0] rom_data[3];
wire rom_req[3];
wire rom_ack[3];
//// MEMORY ACCESS
reg [2:0] mem_cyc;
reg [3:0] rs_cyc;
reg [9:0] x_ofs[3], y_ofs[3];
reg [7:0] control[3];
reg [9:0] rowscroll[3];
wire [14:0] layer_vram_addr[3];
reg layer_load[3];
wire layer_prio[3];
wire [10:0] layer_color[3];
reg [15:0] vram_latch;
reg [37:0] control_save_0[512];
reg [37:0] control_save_1[512];
reg [37:0] control_save_2[512];
reg [37:0] control_restore[3];
reg rowscroll_active, rowscroll_pending;
always_ff @(posedge clk, posedge reset) begin
bit [9:0] rs_y;
if (reset) begin
mem_cyc <= 0;
// layer regs
x_ofs[0] <= 10'd0; x_ofs[1] <= 10'd0; x_ofs[2] <= 10'd0;
y_ofs[0] <= 10'd0; y_ofs[1] <= 10'd0; y_ofs[2] <= 10'd0;
control[0] <= 8'd0; control[1] <= 8'd0; control[2] <= 8'd0;
hint_line <= 10'd0;
rowscroll_pending <= 0;
rowscroll_active <= 0;
end else begin
if (ce) begin
layer_load[0] <= 0; layer_load[1] <= 0; layer_load[2] <= 0;
mem_cyc <= mem_cyc + 3'd1;
if (hpulse) begin
mem_cyc <= 3'd7;
rowscroll_pending <= 1;
end
if (rowscroll_active) begin
rs_cyc <= rs_cyc + 4'd1;
case(rs_cyc)
0: vram_addr <= 'h7800;
4: begin
rs_y = y_ofs[0] + vcnt;
vram_addr <= 'h7a00 + rs_y[8:0];
vram_req <= ~vram_req;
end
7: rowscroll[0] <= vram_din[9:0];
8: begin
rs_y = y_ofs[1] + vcnt;
vram_addr <= 'h7c00 + rs_y[8:0];
vram_req <= ~vram_req;
end
10: rowscroll[1] <= vram_din[9:0];
12: begin
rs_y = y_ofs[2] + vcnt;
vram_addr <= 'h7e00 + rs_y[8:0];
vram_req <= ~vram_req;
end
14: rowscroll[2] <= vram_din[9:0];
15: rowscroll_active <= 0;
endcase
end else begin
case(mem_cyc)
3'd0: begin
vram_addr <= layer_vram_addr[0];
vram_req <= ~vram_req;
end
3'd1: begin
layer_load[0] <= 1; // would be better a bit later
end
3'd2: begin
vram_addr <= layer_vram_addr[1];
vram_req <= ~vram_req;
end
3'd4: begin
layer_load[1] <= 1;
end
3'd5: begin
vram_addr <= layer_vram_addr[2];
vram_req <= ~vram_req;
end
3'd7: begin
layer_load[2] <= 1;
if (rowscroll_pending) begin
rowscroll_pending <= 0;
rowscroll_active <= 1;
rs_cyc <= 4'd0;
end
end
endcase
end
prio_out <= layer_prio[0] | layer_prio[1] | layer_prio[2];
if (|layer_color[0][3:0]) begin
color_out <= layer_color[0];
end else if (|layer_color[1][3:0]) begin
color_out <= layer_color[1];
end else begin
color_out <= layer_color[2];
end
end
if (io_wr) begin
case(addr[7:0])
'h80: y_ofs[0][7:0] <= cpu_din[7:0];
'h81: y_ofs[0][9:8] <= cpu_din[1:0];
'h84: x_ofs[0][7:0] <= cpu_din[7:0];
'h85: x_ofs[0][9:8] <= cpu_din[1:0];
'h88: y_ofs[1][7:0] <= cpu_din[7:0];
'h89: y_ofs[1][9:8] <= cpu_din[1:0];
'h8c: x_ofs[1][7:0] <= cpu_din[7:0];
'h8d: x_ofs[1][9:8] <= cpu_din[1:0];
'h90: y_ofs[2][7:0] <= cpu_din[7:0];
'h91: y_ofs[2][9:8] <= cpu_din[1:0];
'h94: x_ofs[2][7:0] <= cpu_din[7:0];
'h95: x_ofs[2][9:8] <= cpu_din[1:0];
'h98: control[0] <= cpu_din[7:0];
'h9a: control[1] <= cpu_din[7:0];
'h9c: control[2] <= cpu_din[7:0];
'h9e: hint_line[7:0] <= cpu_din[7:0];
'h9f: hint_line[9:8] <= cpu_din[1:0];
endcase
end
`ifdef CTRL_SAVE
if (hcnt == 10'd104 && ~paused) begin // end of hblank
control_save_0[vcnt] <= { y_ofs[0], x_ofs[0], control[0], rowscroll[0] };
control_save_1[vcnt] <= { y_ofs[1], x_ofs[1], control[1], rowscroll[1] };
control_save_2[vcnt] <= { y_ofs[2], x_ofs[2], control[2], rowscroll[2] };
end else if (paused) begin
control_restore[0] <= control_save_0[vcnt];
control_restore[1] <= control_save_1[vcnt];
control_restore[2] <= control_save_2[vcnt];
end
`endif
end
end
assign rom_data[0] = sdr_data_a;
assign sdr_addr_a = REGION_TILE.base_addr[24:0] | rom_addr[0];
assign sdr_req_a = rom_req[0];
assign rom_ack[0] = sdr_ack_a;
assign rom_data[1] = sdr_data_b;
assign sdr_addr_b = REGION_TILE.base_addr[24:0] | rom_addr[1];
assign sdr_req_b = rom_req[1];
assign rom_ack[1] = sdr_ack_b;
assign rom_data[2] = sdr_data_c;
assign sdr_addr_c = REGION_TILE.base_addr[24:0] | rom_addr[2];
assign sdr_req_c = rom_req[2];
assign rom_ack[2] = sdr_ack_c;
//// LAYERS
generate
genvar i;
for(i = 0; i < 3; i = i + 1 ) begin : generate_layer
wire [9:0] _y_ofs = paused ? control_restore[i][37:28] : y_ofs[i];
wire [9:0] _x_ofs = paused ? control_restore[i][27:18] : x_ofs[i];
wire [7:0] _control = paused ? control_restore[i][17:10] : control[i];
wire [9:0] _rowscroll = paused ? control_restore[i][9:0] : rowscroll[i];
ga23_layer layer(
.clk(clk),
.ce_pix(ce),
.NL(0),
.large_tileset(large_tileset),
.x_ofs(_x_ofs),
.y_ofs(_y_ofs),
.control(_control),
.x_base({hcnt[9:3], 3'd0}),
.y(_y_ofs + vcnt),
.rowscroll(_rowscroll),
.vram_addr(layer_vram_addr[i]),
.load(layer_load[i]),
.attrib(vram_din[31:16]),
.index(vram_din[15:0]),
.color_out(layer_color[i]),
.prio_out(layer_prio[i]),
.sdr_addr(rom_addr[i]),
.sdr_data(rom_data[i]),
.sdr_req(rom_req[i]),
.sdr_ack(rom_ack[i]),
.dbg_enabled(dbg_en_layers[i])
);
end
endgenerate
endmodule

View File

@@ -0,0 +1,112 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module ga23_layer(
input clk,
input ce_pix,
input NL,
input large_tileset,
// io registers
input [9:0] x_ofs,
input [9:0] y_ofs,
input [7:0] control,
// position
input [9:0] x_base,
input [9:0] y,
input [9:0] rowscroll,
// vram address for current tile
output [14:0] vram_addr,
//
input load,
input [15:0] attrib,
input [15:0] index,
output prio_out,
output [10:0] color_out,
input [31:0] sdr_data,
output reg [21:0] sdr_addr,
output reg sdr_req,
input sdr_ack,
input dbg_enabled
);
wire [14:0] vram_base = { control[1:0], 13'd0 };
wire wide = control[2];
wire enabled = ~control[4] & dbg_enabled;
wire en_rowscroll = control[6];
wire [9:0] x = x_base + ( en_rowscroll ? rowscroll : x_ofs );
wire [6:0] tile_x = x[9:3] + ( wide ? 7'd32 : 7'd0);
wire [5:0] tile_y = y[8:3];
assign vram_addr = vram_base + (wide ? {1'b0, tile_y, tile_x[6:0], 1'b0} : {2'b00, tile_y, tile_x[5:0], 1'b0});
reg [3:0] cnt;
reg [1:0] prio;
reg [6:0] palette;
reg flip_x;
wire flip_y = attrib[10];
reg [2:0] offset;
always_ff @(posedge clk) begin
if (ce_pix) begin
cnt <= cnt + 4'd1;
if (load & dbg_enabled) begin
cnt <= 4'd0;
sdr_addr <= { (large_tileset ? attrib[15] : 1'b0), index, flip_y ? ~y[2:0] : y[2:0], 2'b00 };
sdr_req <= ~sdr_req;
palette <= attrib[6:0];
prio <= attrib[8:7];
flip_x <= attrib[9];
offset <= x[2:0];
end
end
end
wire [1:0] shift_prio_out;
wire [10:0] shift_color_out;
ga23_shifter shifter(
.clk(clk),
.ce_pix(ce_pix),
.offset(offset),
.load(load),
.reverse(flip_x),
.row(sdr_data),
.palette(palette),
.prio(prio),
.color_out(shift_color_out),
.prio_out(shift_prio_out)
);
assign color_out = enabled ? shift_color_out : 11'd0;
assign prio_out = enabled ? ( ( shift_prio_out[0] & shift_color_out[3] ) | ( shift_prio_out[1] & |shift_color_out[3:0] ) ) : 1'b0;
endmodule

View File

@@ -0,0 +1,70 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module ga23_shifter(
input clk,
input ce_pix,
input [2:0] offset,
input load,
input reverse,
input [31:0] row,
input [6:0] palette,
input [1:0] prio,
output [10:0] color_out,
output [1:0] prio_out
);
reg [2:0] cnt;
reg [31:0] pix_next, pix_cur;
reg [6:0] pal_next, pal_cur;
reg [1:0] prio_next, prio_cur;
wire [2:0] flip_cnt = cnt + offset;
always_ff @(posedge clk) begin
if (ce_pix) begin
pix_cur[27:0] <= pix_cur[31:4];
cnt <= cnt + 3'd1;
if (&flip_cnt) begin
pix_cur <= pix_next;
prio_cur <= prio_next;
pal_cur <= pal_next;
end
if (load) begin
integer i;
for( i = 0; i < 8; i = i + 1 ) begin
pix_next[(i * 4) + 3] = reverse ? row[24 + i] : row[31 - i];
pix_next[(i * 4) + 2] = reverse ? row[16 + i] : row[23 - i];
pix_next[(i * 4) + 1] = reverse ? row[ 8 + i] : row[15 - i];
pix_next[(i * 4) + 0] = reverse ? row[ 0 + i] : row[ 7 - i];
end
pal_next <= palette;
prio_next <= prio;
cnt <= 0;
end
end
end
assign prio_out = prio_cur;
assign color_out = { pal_cur, pix_cur[3:0] };
endmodule

View File

@@ -0,0 +1,213 @@
// 3-tap IIR filter for 2 channels.
// Copyright (C) 2020 Sorgelig
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Can be converted to 2-tap (coeff_x2 = 0, coeff_y2 = 0) or 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0)
//
module IIR_filter
#(
parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables.
parameter stereo = 1, // 0 for mono (input_l)
parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9)
parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7
parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7
parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7
parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9)
parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9)
parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9)
)
(
input clk,
input reset,
input ce, // must be double of calculated rate for stereo!
input sample_ce, // desired output sample rate
input [39:0] cx,
input [7:0] cx0,
input [7:0] cx1,
input [7:0] cx2,
input [23:0] cy0,
input [23:0] cy1,
input [23:0] cy2,
input [15:0] input_l, input_r, // signed samples
output [15:0] output_l, output_r // signed samples
);
localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000;
localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000;
localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000;
localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000;
wire [39:0] vcoeff = use_params ? pcoeff_x : cx;
wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0;
wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1;
wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2;
wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff);
wire [39:0] x = inp_mul[59:20];
wire [39:0] y = x + tap0;
wire [39:0] tap0;
iir_filter_tap iir_tap_0
(
.clk(clk),
.reset(reset),
.ce(ce),
.ch(ch),
.cx(use_params ? coeff_x0[7:0] : cx0),
.cy(vcoeff_y0),
.x(x),
.y(y),
.z(tap1),
.tap(tap0)
);
wire [39:0] tap1;
iir_filter_tap iir_tap_1
(
.clk(clk),
.reset(reset),
.ce(ce),
.ch(ch),
.cx(use_params ? coeff_x1[7:0] : cx1),
.cy(vcoeff_y1),
.x(x),
.y(y),
.z(tap2),
.tap(tap1)
);
wire [39:0] tap2;
iir_filter_tap iir_tap_2
(
.clk(clk),
.reset(reset),
.ce(ce),
.ch(ch),
.cx(use_params ? coeff_x2[7:0] : cx2),
.cy(vcoeff_y2),
.x(x),
.y(y),
.z(0),
.tap(tap2)
);
wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20];
reg ch = 0;
reg [15:0] out_l, out_r, out_m;
reg [15:0] inp, inp_m;
always @(posedge clk) if (ce) begin
if(!stereo) begin
ch <= 0;
inp <= input_l;
out_l <= y_clamp;
out_r <= y_clamp;
end
else begin
ch <= ~ch;
if(ch) begin
out_m <= y_clamp;
inp <= inp_m;
end
else begin
out_l <= out_m;
out_r <= y_clamp;
inp <= input_l;
inp_m <= input_r;
end
end
end
reg [31:0] out;
always @(posedge clk) if (sample_ce) out <= {out_l, out_r};
assign {output_l, output_r} = out;
endmodule
module iir_filter_tap
(
input clk,
input reset,
input ce,
input ch,
input [7:0] cx,
input [23:0] cy,
input [39:0] x,
input [39:0] y,
input [39:0] z,
output [39:0] tap
);
wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy);
function [39:0] x_mul;
input [39:0] x;
begin
x_mul = 0;
if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]};
if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]};
if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]};
if(cx[7]) x_mul = ~x_mul; //cheap NEG
end
endfunction
(* ramstyle = "logic" *) reg [39:0] intreg[2];
always @(posedge clk, posedge reset) begin
if(reset) {intreg[0],intreg[1]} <= 80'd0;
else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z;
end
assign tap = intreg[ch];
endmodule
// simplified IIR 1-tap.
module DC_blocker
(
input clk,
input ce, // 48/96 KHz
input mute,
input sample_rate,
input [15:0] din,
output [15:0] dout
);
wire [39:0] x = {din[15], din, 23'd0};
wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]});
wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]});
wire [39:0] y0 = x0 - x1 + y1;
reg [39:0] x1, y;
always @(posedge clk) if(ce) begin
x1 <= x0;
y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0;
end
assign dout = mute ? 16'd0 : y[38:23];
endmodule

View File

@@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////
// 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 cen_in,
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 (cen_in) begin
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
end
endmodule

View File

@@ -0,0 +1,21 @@
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./rom.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./pal.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga22.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sound.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga23_layer.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./eeprom.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m92_pkg.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m92.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./palram.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga22_linebuffer.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga21.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m92_pic.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga20.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./dpramv.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./objram.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga23_shifter.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sdram_4w_cl3.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ga23.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./v35.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./jtframe_frac_cen.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./iir_filter.v ]

View File

@@ -0,0 +1,724 @@
//============================================================================
// Irem M92 for MiSTer FPGA - Main module
//
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
import m92_pkg::*;
module m92 (
input clk_sys,
input reset_n,
output reg ce_pix,
input board_cfg_t board_cfg,
output [7:0] R,
output [7:0] G,
output [7:0] B,
output HSync,
output VSync,
output HBlank,
output VBlank,
output [15:0] AUDIO_L,
output [15:0] AUDIO_R,
input [3:0] coin,
input [3:0] start_buttons,
input [9:0] p1_input,
input [9:0] p2_input,
input [9:0] p3_input,
input [9:0] p4_input,
input [23:0] dip_sw,
input pause_rq,
output cpu_paused,
output [24:0] sdr_vram_addr,
input [31:0] sdr_vram_data,
output sdr_vram_req,
output [24:0] sdr_sprite_addr,
input [63:0] sdr_sprite_dout,
output sdr_sprite_req,
input sdr_sprite_ack,
output sdr_sprite_refresh,
output [24:0] sdr_bg_addr_a,
input [31:0] sdr_bg_data_a,
output sdr_bg_req_a,
input sdr_bg_ack_a,
output [24:0] sdr_bg_addr_b,
input [31:0] sdr_bg_data_b,
output sdr_bg_req_b,
input sdr_bg_ack_b,
output [24:0] sdr_bg_addr_c,
input [31:0] sdr_bg_data_c,
output sdr_bg_req_c,
input sdr_bg_ack_c,
output reg [24:0] sdr_cpu_addr,
input [15:0] sdr_cpu_dout,
output reg [15:0] sdr_cpu_din,
output reg sdr_cpu_req,
input sdr_cpu_ack,
output reg [1:0] sdr_cpu_wr_sel,
output reg [24:0] sdr_audio_cpu_addr,
input [15:0] sdr_audio_cpu_dout,
output reg [15:0] sdr_audio_cpu_din,
output reg sdr_audio_cpu_req,
input sdr_audio_cpu_ack,
output reg [1:0] sdr_audio_cpu_wr_sel,
output [24:0] sdr_audio_addr,
input [63:0] sdr_audio_dout,
output sdr_audio_req,
input sdr_audio_ack,
input clk_bram,
input bram_wr,
input [7:0] bram_data,
input [19:0] bram_addr,
input [4:0] bram_cs,
input ioctl_download,
input ioctl_wr,
input [26:0] ioctl_addr,
input [7:0] ioctl_dout,
input ioctl_upload,
output [7:0] ioctl_upload_index,
output [7:0] ioctl_din,
input ioctl_rd,
output ioctl_upload_req,
input [2:0] dbg_en_layers,
input dbg_solid_sprites,
input en_audio_filters,
input dbg_fm_en,
input sprite_freeze,
input dbg_io_write,
input [7:0] dbg_io_data,
output reg dbg_io_wait
);
assign ioctl_upload_index = 8'd1;
wire [15:0] rgb_color;
assign R = { rgb_color[4:0], rgb_color[4:2] };
assign G = { rgb_color[9:5], rgb_color[9:7] };
assign B = { rgb_color[14:10], rgb_color[14:12] };
reg paused = 0;
assign cpu_paused = paused;
always @(posedge clk_sys) begin
if (pause_rq & ~paused) begin
if (~cpu_mem_read & ~cpu_mem_write & ~mem_rq_active & vpulse) begin
paused <= 1;
end
end else if (~pause_rq & paused) begin
paused <= ~vpulse;
end
end
wire ce_13m;
jtframe_frac_cen #(2) pixel_cen
(
.clk(clk_sys),
.cen_in(1),
.n(10'd1),
.m(10'd3),
.cen({ce_pix, ce_13m})
);
wire ce_9m, ce_18m;
jtframe_frac_cen #(2) cpu_cen
(
.clk(clk_sys),
.cen_in(1),
.n(10'd9),
.m(10'd20),
.cen({ce_9m, ce_18m})
);
wire dma_busy;
wire [15:0] cpu_mem_out;
wire [19:0] cpu_mem_addr;
wire [1:0] cpu_mem_sel;
// v30 bus read/write signals are only asserted for a single clock cycle, so latch them for an additional one
reg cpu_mem_read_lat, cpu_mem_write_lat;
wire cpu_mem_read_w, cpu_mem_write_w;
wire cpu_mem_read = cpu_mem_read_w | cpu_mem_read_lat;
wire cpu_mem_write = cpu_mem_write_w | cpu_mem_write_lat;
wire cpu_io_read, cpu_io_write;
wire [7:0] cpu_io_in;
wire [7:0] cpu_io_out;
wire [7:0] cpu_io_addr;
wire [15:0] cpu_mem_in;
/* Global signals from schematics */
wire IOWR = cpu_io_write; // IO Write
wire IORD = cpu_io_read; // IO Read
wire MWR = cpu_mem_write; // Mem Write
wire MRD = cpu_mem_read; // Mem Read
wire [15:0] cpu_word_out = cpu_mem_addr[0] ? { cpu_mem_out[7:0], 8'h00 } : cpu_mem_out;
wire [1:0] cpu_word_byte_sel = cpu_mem_addr[0] ? { cpu_mem_sel[0], 1'b0 } : cpu_mem_sel;
reg [15:0] cpu_ram_rom_data;
wire [24:0] cpu_region_addr;
wire cpu_region_writable;
wire ram_rom_memrq;
wire buffer_memrq;
wire sprite_control_memrq;
wire video_control_memrq;
wire eeprom_memrq;
wire banked_memrq;
wire [7:0] snd_latch_dout;
wire snd_latch_rdy;
reg [1:0] ce_counter_cpu;
reg ce_cpu, ce_4x_cpu;
reg mem_rq_active = 0;
always @(posedge clk_sys, negedge reset_n) begin
if (!reset_n) begin
ce_cpu <= 0;
ce_4x_cpu <= 0;
ce_counter_cpu <= 0;
end else begin
ce_cpu <= 0;
ce_4x_cpu <= 0;
if (~paused) begin
if (~((ram_rom_memrq) & (cpu_mem_read | cpu_mem_write)) & ~mem_rq_active) begin // stall main cpu while fetching from sdram
ce_counter_cpu <= ce_counter_cpu + 2'd1;
ce_4x_cpu <= 1;
ce_cpu <= &ce_counter_cpu;
end
end
end
end
function [15:0] word_shuffle(input [19:0] addr, input [15:0] data);
begin
word_shuffle = addr[0] ? { 8'h00, data[15:8] } : data;
end
endfunction
always_ff @(posedge clk_sys or negedge reset_n) begin
if (!reset_n) begin
mem_rq_active <= 0;
end else begin
cpu_mem_read_lat <= cpu_mem_read_w;
cpu_mem_write_lat <= cpu_mem_write_w;
if (!mem_rq_active) begin
if (ram_rom_memrq & ((cpu_mem_read_w & ~cpu_mem_read_lat) | (cpu_mem_write_w & ~cpu_mem_write_lat))) begin // sdram request
sdr_cpu_wr_sel <= 2'b00;
sdr_cpu_addr <= cpu_region_addr;
if (cpu_mem_write & cpu_region_writable ) begin
sdr_cpu_wr_sel <= cpu_word_byte_sel;
sdr_cpu_din <= cpu_word_out;
end
sdr_cpu_req <= ~sdr_cpu_req;
mem_rq_active <= 1;
end
end else if (sdr_cpu_req == sdr_cpu_ack) begin
mem_rq_active <= 0;
cpu_ram_rom_data <= sdr_cpu_dout;
end
end
end
wire rom0_ce, rom1_ce, ram_cs2;
reg [7:0] dbg_io_latch;
reg [3:0] bank_select = 4'd0;
wire [7:0] switches_p1 = board_cfg.kick_harness ? { p1_input[4], p1_input[5], p1_input[6], 1'b0, p1_input[3], p1_input[2], p1_input[1], p1_input[0] }
: { p1_input[4], p1_input[5], 1'b0, 1'b0, p1_input[3], p1_input[2], p1_input[1], p1_input[0] };
wire [7:0] switches_p2 = board_cfg.kick_harness ? { p2_input[4], p2_input[5], p2_input[6], 1'b0, p2_input[3], p2_input[2], p2_input[1], p2_input[0] }
: { p2_input[4], p2_input[5], 1'b0, 1'b0, p2_input[3], p2_input[2], p2_input[1], p2_input[0] };
wire [7:0] switches_p3 = board_cfg.kick_harness ? { 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0 }
: { p3_input[4], p3_input[5], coin[2], start_buttons[2], p3_input[3], p3_input[2], p3_input[1], p3_input[0] };
wire [7:0] switches_p4 = board_cfg.kick_harness ? { p2_input[9], p2_input[8], p2_input[7], 1'b0, p1_input[9], p1_input[8], p1_input[7], 1'b0 }
: { p4_input[4], p4_input[5], coin[3], start_buttons[3], p4_input[3], p4_input[2], p4_input[1], p4_input[0] };
wire [15:0] switches_p1_p2 = { ~switches_p2, ~switches_p1 };
`ifdef M92_DEBUG_IO
wire [15:0] switches_p3_p4 = { dbg_io_latch, dbg_io_latch };
`else
wire [15:0] switches_p3_p4 = { ~switches_p4, ~switches_p3 };
`endif
wire [15:0] flags = { ~dip_sw[23:16], ~dma_busy, 1'b1, 1'b1 /*TEST*/, 1'b1 /*R*/, ~coin[1:0], ~start_buttons[1:0] };
reg [7:0] sys_flags = 0;
wire COIN0 = sys_flags[0];
wire COIN1 = sys_flags[1];
wire SOFT_NL = ~sys_flags[2];
wire CBLK = sys_flags[3];
wire BRQ = ~sys_flags[4];
wire BANK = sys_flags[5];
wire NL = SOFT_NL ^ ~dip_sw[8];
// TODO BANK, CBLK, NL
always @(posedge clk_sys) begin
if (IOWR && cpu_io_addr == 8'h02) sys_flags <= cpu_io_out[7:0];
if (IOWR && cpu_io_addr == 8'h20) bank_select <= cpu_io_out[3:0];
end
reg [15:0] vid_ctrl;
always @(posedge clk_sys or negedge reset_n) begin
if (~reset_n) begin
vid_ctrl <= 0;
end else if (video_control_memrq & MWR) begin
vid_ctrl <= cpu_word_out;
end
end
`ifdef M92_DEBUG_IO
always @(posedge clk_sys or negedge reset_n) begin
if (~reset_n) begin
dbg_io_wait <= 0;
dbg_io_latch <= 8'hff;
end else begin
if (IORD && cpu_io_addr == 8'h06) begin
dbg_io_wait <= 0;
end
if (dbg_io_write) begin
dbg_io_wait <= 1;
dbg_io_latch <= dbg_io_data;
end
end
end
`endif
wire [15:0] ga21_dout;
wire [7:0] eeprom_dout;
// mux io and memory reads
always_comb begin
bit [15:0] d16;
bit [15:0] io16;
if (buffer_memrq) d16 = ga21_dout;
else if(eeprom_memrq) d16 = { eeprom_dout, eeprom_dout };
else d16 = cpu_ram_rom_data;
cpu_mem_in = word_shuffle(cpu_mem_addr, d16);
case ({cpu_io_addr[7:1], 1'b0})
8'h00: io16 = switches_p1_p2;
8'h02: io16 = flags;
8'h04: io16 = ~dip_sw[15:0];
8'h06: io16 = switches_p3_p4;
8'h08: io16 = { snd_latch_dout, snd_latch_dout };
default: io16 = 16'hffff;
endcase
cpu_io_in = cpu_io_addr[0] ? io16[15:8] : io16[7:0];
end
wire int_req, int_ack;
wire [8:0] int_vector;
v30 v30(
.clk(clk_sys),
.ce(ce_cpu),
.ce_4x(ce_4x_cpu),
.reset(~reset_n),
.turbo(1),
.SLOWTIMING(0),
.cpu_idle(),
.cpu_halt(),
.cpu_irqrequest(),
.cpu_prefix(),
.bus_read(cpu_mem_read_w),
.bus_write(cpu_mem_write_w),
.bus_be(cpu_mem_sel),
.bus_addr(cpu_mem_addr),
.bus_datawrite(cpu_mem_out),
.bus_dataread(cpu_mem_in),
.irqrequest_in(int_req),
.irqvector_in(int_vector),
.irqrequest_ack(int_ack),
// TODO
.cpu_done(),
.RegBus_Din(cpu_io_out),
.RegBus_Adr(cpu_io_addr),
.RegBus_wren(cpu_io_write),
.RegBus_rden(cpu_io_read),
.RegBus_Dout(cpu_io_in)
);
address_translator address_translator(
.A(cpu_mem_addr),
.board_cfg(board_cfg),
.ram_rom_memrq(ram_rom_memrq),
.sdr_addr(cpu_region_addr),
.writable(cpu_region_writable),
.buffer_memrq(buffer_memrq),
.sprite_control_memrq(sprite_control_memrq),
.video_control_memrq(video_control_memrq),
.eeprom_memrq(eeprom_memrq),
.bank_select(bank_select)
);
wire vblank, hblank, vsync, hsync, vpulse, hpulse, hint;
m92_pic m92_pic(
.clk(clk_sys),
.ce(ce_cpu),
.reset(~reset_n),
.cs((IORD | IOWR) & ~cpu_io_addr[7] & cpu_io_addr[6] & ~cpu_io_addr[0]), // 0x40-0x43
.wr(IOWR),
.rd(0),
.a0(cpu_io_addr[1]),
.din(cpu_io_out),
.int_req(int_req),
.int_vector(int_vector),
.int_ack(int_ack),
.intp({4'd0, snd_latch_rdy, hint, ~dma_busy, vblank})
);
assign HSync = hsync;
assign HBlank = hblank;
assign VSync = vsync;
assign VBlank = vblank;
wire objram_we;
wire [15:0] objram_data, objram_q;
wire [63:0] objram_q64;
wire [10:0] objram_addr;
wire [11:0] ga22_color, ga23_color;
wire ga23_prio;
objram objram(
.clk(clk_sys),
.addr(objram_addr),
.we(objram_we),
.data(objram_data),
.q(objram_q),
.q64(objram_q64)
);
wire bufram_we;
wire [15:0] bufram_data;
wire [15:0] bufram_q00, bufram_q01, bufram_q10, bufram_q11;
wire [10:0] bufram_addr;
wire [1:0] bufram_cs = ( ~bufram_addr[10] & ~dma_busy ) ? { 1'b0, vid_ctrl[0] } :
( bufram_addr[10] & ~dma_busy ) ? { vid_ctrl[2], vid_ctrl[1] } :
( ~bufram_addr[10] & dma_busy ) ? { 1'b0, vid_ctrl[3] } :
( bufram_addr[10] & dma_busy ) ? { vid_ctrl[5], vid_ctrl[4] } : 2'b00;
wire [15:0] bufram_q;
wire [12:0] ga21_palram_addr;
wire ga21_palram_we, ga21_palram_cs;
wire [15:0] ga21_palram_dout;
wire [15:0] palram_q;
wire [10:0] ga22_count;
singleport_unreg_ram #(.widthad(13), .width(16), .name("BUFRAM")) bufram(
.clock(clk_sys),
.address({bufram_cs, bufram_addr}),
.q(bufram_q),
.wren(bufram_we),
.data(bufram_data)
);
palram palram(
.clk(clk_sys),
.ce_pix(ce_pix),
.vid_ctrl(vid_ctrl),
.dma_busy(dma_busy),
.cpu_addr(cpu_mem_addr[10:1]),
.ga21_addr(ga21_palram_addr),
.ga21_we(ga21_palram_we),
.ga21_req(ga21_palram_cs),
.obj_color(ga22_color[10:0]),
.obj_prio(ga22_color[11]),
.obj_active(|ga22_color[3:0]),
.pf_color(ga23_color),
.pf_prio(~ga23_prio),
.din(ga21_palram_dout),
.dout(palram_q),
.rgb_out(rgb_color)
);
GA21 ga21(
.clk(clk_sys),
.ce(ce_9m),
.reset(),
.din(cpu_word_out),
.dout(ga21_dout),
.addr(cpu_mem_addr[11:1]),
.reg_cs(sprite_control_memrq),
.buf_cs(buffer_memrq),
.wr(MWR),
.busy(dma_busy),
.obj_dout(objram_data),
.obj_din(objram_q),
.obj_addr(objram_addr),
.obj_we(objram_we),
.buffer_dout(bufram_data),
.buffer_din(bufram_q),
.buffer_addr(bufram_addr),
.buffer_we(bufram_we),
.count(ga22_count),
.pal_addr(ga21_palram_addr),
.pal_dout(ga21_palram_dout),
.pal_din(palram_q),
.pal_we(ga21_palram_we),
.pal_cs(ga21_palram_cs)
);
GA22 ga22(
.clk(clk_sys),
.ce(ce_13m), // 13.33Mhz
.ce_pix(ce_pix), // 6.66Mhz
.reset(~reset_n),
.color(ga22_color),
.NL(NL),
.hpulse(hpulse),
.vpulse(vpulse),
.count(ga22_count),
.obj_in(objram_q64),
.sdr_data(sdr_sprite_dout),
.sdr_addr(sdr_sprite_addr),
.sdr_req(sdr_sprite_req),
.sdr_ack(sdr_sprite_ack),
.sdr_refresh(sdr_sprite_refresh),
.dbg_solid_sprites(dbg_solid_sprites)
);
wire [14:0] vram_addr;
assign sdr_vram_addr = {REGION_VRAM.base_addr[24:16], vram_addr, 1'b0};
GA23 ga23(
.clk(clk_sys),
.ce(ce_pix),
.reset(~reset_n),
.paused(paused),
.io_wr(IOWR),
.addr(IOWR ? {8'd0, cpu_io_addr} : cpu_mem_addr),
.cpu_din(IOWR ? {8'd0, cpu_io_out} : cpu_mem_out),
.vram_addr(vram_addr),
.vram_din(sdr_vram_data),
.vram_req(sdr_vram_req),
.large_tileset(board_cfg.large_tileset),
.sdr_data_a(sdr_bg_data_a),
.sdr_addr_a(sdr_bg_addr_a),
.sdr_req_a(sdr_bg_req_a),
.sdr_ack_a(sdr_bg_ack_a),
.sdr_data_b(sdr_bg_data_b),
.sdr_addr_b(sdr_bg_addr_b),
.sdr_req_b(sdr_bg_req_b),
.sdr_ack_b(sdr_bg_ack_b),
.sdr_data_c(sdr_bg_data_c),
.sdr_addr_c(sdr_bg_addr_c),
.sdr_req_c(sdr_bg_req_c),
.sdr_ack_c(sdr_bg_ack_c),
.vblank(vblank),
.hblank(hblank),
.vsync(vsync),
.hsync(hsync),
.hpulse(hpulse),
.vpulse(vpulse),
.hint(hint),
.color_out(ga23_color),
.prio_out(ga23_prio),
.dbg_en_layers(dbg_en_layers)
);
/*
// Sound board test (select sound with P1 left/right)
reg [7:0] snd_id;
reg snd_wr;
reg left_last, right_last;
wire left = p1_input[1];
wire right = p1_input[0];
always @(posedge clk_sys) begin
if (!reset_n) begin
snd_wr <= 0;
snd_id <= 0;
end else begin
snd_wr <= 0;
left_last <= left;
right_last <= right;
if (!left_last & left) begin
snd_id <= snd_id - 1'd1;
snd_wr <= 1;
end
if (!right_last & right) begin
snd_id <= snd_id + 1'd1;
snd_wr <= 1;
end
end
end
*/
wire [15:0] sound_sample;
sound sound(
.clk_sys(clk_sys),
.reset(~reset_n),
.filter_en(en_audio_filters),
.dbg_fm_en(dbg_fm_en),
.paused(paused),
.latch_wr(IOWR & cpu_io_addr == 8'h00),
//.latch_wr(snd_wr),
.latch_rd(IORD & cpu_io_addr == 8'h08),
.latch_din(cpu_io_out),
//.latch_din(snd_id),
.latch_dout(snd_latch_dout),
.latch_rdy(snd_latch_rdy),
.rom_addr(bram_addr),
.rom_data(bram_data),
.rom_wr(bram_wr & bram_cs[1]),
.secure_addr(bram_addr[7:0]),
.secure_data(bram_data),
.secure_wr(bram_wr & bram_cs[0]),
.sample(sound_sample),
.sdr_cpu_addr(sdr_audio_cpu_addr),
.sdr_cpu_dout(sdr_audio_cpu_dout),
.sdr_cpu_din(sdr_audio_cpu_din),
.sdr_cpu_req(sdr_audio_cpu_req),
.sdr_cpu_ack(sdr_audio_cpu_ack),
.sdr_cpu_wr_sel(sdr_audio_cpu_wr_sel),
.sdr_addr(sdr_audio_addr),
.sdr_data(sdr_audio_dout),
.sdr_req(sdr_audio_req),
.sdr_ack(sdr_audio_ack)
);
assign AUDIO_L = sound_sample;
assign AUDIO_R = sound_sample;
eeprom_28C64 eeprom(
.clk(clk_sys),
.reset(~reset_n),
.ce(1),
.rd(MRD & eeprom_memrq),
.wr(MWR & eeprom_memrq),
.addr(cpu_mem_addr[13:1]),
.q(eeprom_dout),
.data(cpu_mem_out[7:0]),
.ready(),
.modified(ioctl_upload_req),
.ioctl_download(ioctl_download | bram_cs[2]),
.ioctl_wr(bram_cs[2] ? bram_wr : ioctl_wr),
.ioctl_addr(bram_cs[2] ? bram_addr[12:0] : ioctl_addr[12:0]),
.ioctl_dout(ioctl_dout),
.ioctl_upload(ioctl_upload),
.ioctl_din(ioctl_din),
.ioctl_rd(ioctl_rd)
);
endmodule

View File

@@ -0,0 +1,153 @@
//============================================================================
// Irem M92 for MiSTer FPGA - Programmable interrupt controller
//
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module m92_pic(
input clk,
input ce,
input reset,
input cs,
input wr,
input rd,
input a0,
input [7:0] din,
output int_req,
output reg [8:0] int_vector,
input int_ack,
input [7:0] intp
);
enum {
UNINIT,
INIT_IW2,
INIT_IW3,
INIT_IW4,
INIT_DONE
} init_state = UNINIT;
reg [7:0] IW1, IW2, IW3, IW4;
reg [7:0] IMW;
reg [7:0] PFCW;
reg [7:0] MCW;
reg [7:0] IRR;
int ISR;
wire [7:0] IRQ = ( IRR & ~IMW );
assign int_req = IRQ != 8'd0;
wire iw4_write = IW1[0];
wire iw4_not_written = ~IW1[0];
wire single_mode = IW1[1];
wire extended_mode = ~IW1[1];
wire address_gap_4 = IW1[2];
wire address_gap_8 = ~IW1[2];
wire level_triggered = IW1[3];
wire edge_triggered = ~IW1[3];
reg [7:0] intp_latch = 0;
always_ff @(posedge clk or posedge reset) begin
if (reset) begin
init_state <= UNINIT;
intp_latch <= 0;
IRR <= 8'd0;
ISR <= 8;
end else if (ce) begin
if (cs & wr) begin
if (~a0) begin
if (din[4]) begin
init_state <= INIT_IW2;
IW1 <= din;
PFCW <= 0;
MCW <= 0;
IMW <= 0;
IRR <= 0;
ISR <= 8;
end else if (~din[4] & ~din[3]) begin
PFCW <= din;
end else if (~din[4] & din[3]) begin
MCW <= din;
end
end
if (a0) begin
case (init_state)
INIT_IW2: begin
IW2 <= din;
if (extended_mode) init_state <= INIT_IW3;
else if (iw4_write) init_state <= INIT_IW4;
else init_state <= INIT_DONE;
end
INIT_IW3: begin
IW3 <= din;
if (iw4_write) init_state <= INIT_IW4;
else init_state <= INIT_DONE;
end
INIT_IW4: begin
IW4 <= din;
init_state <= INIT_DONE;
end
INIT_DONE: begin
IMW <= din;
end
endcase
end
end
if (init_state == INIT_DONE) begin
bit [7:0] trig;
int p;
intp_latch <= intp;
if (int_req) begin
if (int_ack) begin
if ( IRQ[0] ) begin int_vector <= {IW2[6:3], 3'd0, 2'b00}; IRR[0] <= 0; end
else if ( IRQ[1] ) begin int_vector <= {IW2[6:3], 3'd1, 2'b00}; IRR[1] <= 0; end
else if ( IRQ[2] ) begin int_vector <= {IW2[6:3], 3'd2, 2'b00}; IRR[2] <= 0; end
else if ( IRQ[3] ) begin int_vector <= {IW2[6:3], 3'd3, 2'b00}; IRR[3] <= 0; end
else if ( IRQ[4] ) begin int_vector <= {IW2[6:3], 3'd4, 2'b00}; IRR[4] <= 0; end
else if ( IRQ[5] ) begin int_vector <= {IW2[6:3], 3'd5, 2'b00}; IRR[5] <= 0; end
else if ( IRQ[6] ) begin int_vector <= {IW2[6:3], 3'd6, 2'b00}; IRR[6] <= 0; end
else if ( IRQ[7] ) begin int_vector <= {IW2[6:3], 3'd7, 2'b00}; IRR[7] <= 0; end
end
end
if (edge_triggered)
trig = intp & ~intp_latch;
else
trig = intp;
for( p = 0; p < 8; p = p + 1 ) begin
if (intp[p]) begin
if (trig[p]) begin
IRR[p] <= 1'b1;
end
end
end
end
end
end
endmodule

View File

@@ -0,0 +1,61 @@
//============================================================================
// Irem M92 for MiSTer FPGA - Common definitions
//
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
package m92_pkg;
typedef struct packed {
bit [27:0] base_addr;
bit reorder_64;
bit [4:0] bram_cs;
} region_t;
parameter region_t REGION_CPU_ROM = '{ 28'h000_0000, 0, 5'b00000 };
parameter region_t REGION_CPU_RAM = '{ 28'h010_0000, 0, 5'b00000 };
parameter region_t REGION_SOUND = '{ 28'h020_0000, 0, 5'b00000 };
parameter region_t REGION_GA20 = '{ 28'h030_0000, 0, 5'b00000 };
parameter region_t REGION_SPRITE = '{ 28'h040_0000, 1, 5'b00000 };
parameter region_t REGION_TILE = '{ 28'h0c0_0000, 0, 5'b00000 };
parameter region_t REGION_CRYPT = '{ 28'h000_0000, 0, 5'b00001 };
parameter region_t REGION_WIDE_SPRITE = '{ 28'h040_0000, 0, 5'b00000 };
parameter region_t REGION_EEPROM = '{ 28'h000_0000, 0, 5'b00100 };
parameter region_t REGION_VRAM = '{ 28'h070_0000, 0, 5'b00000 };
parameter region_t REGION_SOUND_RAM = '{ 28'h078_0000, 0, 5'b00000 };
parameter region_t LOAD_REGIONS[8] = '{
REGION_CPU_ROM,
REGION_TILE,
REGION_SPRITE,
REGION_SOUND,
REGION_CRYPT,
REGION_GA20,
REGION_WIDE_SPRITE,
REGION_EEPROM
};
typedef struct packed {
bit large_tileset;
bit kick_harness;
bit wide_sprites;
bit alt_map;
bit [3:0] bank_mask;
} board_cfg_t;
endpackage

View File

@@ -0,0 +1,77 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module objram(
input clk,
input [10:0] addr,
input we,
input [15:0] data,
output [15:0] q,
output [63:0] q64
);
wire [1:0] col = addr[1:0];
wire [63:0] data64 = { col == 2'd3 ? data : 16'd0, col == 2'd2 ? data : 16'd0, col == 2'd1 ? data : 16'd0, col == 2'd0 ? data : 16'd0 };
wire [7:0] byte_en = { col == 2'd3 ? 2'b11 : 2'b00, col == 2'd2 ? 2'b11 : 2'b00, col == 2'd1 ? 2'b11 : 2'b00, col == 2'd0 ? 2'b11 : 2'b00 };
assign q = col == 2'd0 ? q64[15:0] : col == 2'd1 ? q64[31:16] : col == 2'd2 ? q64[47:32] : q64[63:48];
altsyncram altsyncram_component (
.address_a (addr[10:2]),
.byteena_a (byte_en),
.clock0 (clk),
.data_a (data64),
.wren_a (we),
.q_a (q64),
.aclr0 (1'b0),
.aclr1 (1'b0),
.address_b (1'b1),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b (1'b1),
.eccstatus (),
.q_b (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.byte_size = 8,
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone V",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 512,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "DONT_CARE",
altsyncram_component.widthad_a = 9,
altsyncram_component.width_a = 64,
altsyncram_component.width_byteena_a = 8;
endmodule

View File

@@ -0,0 +1,85 @@
//============================================================================
// Irem M92 for MiSTer FPGA - PAL address decoders
//
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
import m92_pkg::*;
module address_translator
(
input logic [19:0] A,
input logic [3:0] bank_select,
input board_cfg_t board_cfg,
output [24:0] sdr_addr,
output writable,
output ram_rom_memrq,
output buffer_memrq,
output sprite_control_memrq,
output video_control_memrq,
output eeprom_memrq
);
wire [3:0] bank_a19_16 = ( bank_select & board_cfg.bank_mask ) | ( A[19:16] & ~board_cfg.bank_mask );
always_comb begin
ram_rom_memrq = 0;
writable = 0;
sdr_addr = 0;
buffer_memrq = 0;
sprite_control_memrq = 0;
video_control_memrq = 0;
eeprom_memrq = 0;
casex (A[19:0])
// 0xc0000-0xcffff
20'b1100_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 0; sdr_addr = { REGION_CPU_ROM.base_addr[24:16], A[15:0] }; end
// 0xd0000-0xdffff
20'b1101_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 1; sdr_addr = { REGION_VRAM.base_addr[24:16], A[15:0] }; end
// 0xe0000-0xeffff
20'b1110_xxxx_xxxx_xxxx_xxxx: begin ram_rom_memrq = 1; writable = 1; sdr_addr = { REGION_CPU_RAM.base_addr[24:16], A[15:0] }; end
// 0xf0000-0xf3fff
20'b1111_00xx_xxxx_xxxx_xxxx: eeprom_memrq = 1;
// 0xf8000-0xf87ff
20'b1111_1000_xxxx_xxxx_xxxx: buffer_memrq = 1;
// 0xf9000-0xf900f
20'b1111_1001_0000_0000_xxxx: sprite_control_memrq = 1;
// 0xf9800-0xf9801
20'b1111_1001_1000_0000_000x: video_control_memrq = 1;
// 0xffff0-0xfffff
20'b1111_1111_1111_1111_xxxx: begin ram_rom_memrq = 1; writable = 0; sdr_addr = { REGION_CPU_ROM.base_addr[24:20], 16'h7fff, A[3:0] }; end
// 0x00000-0xbffff
default: begin
if (board_cfg.alt_map && A[19:16] == 4'h8) begin
ram_rom_memrq = 1;
writable = 1;
sdr_addr = { REGION_VRAM.base_addr[24:16], A[15:0] };
end else begin
ram_rom_memrq = 1;
writable = 0;
sdr_addr = { REGION_CPU_ROM.base_addr[24:20], A[19:17] == 3'b101 ? bank_a19_16 : A[19:16], A[15:0] };
end
end
endcase
end
endmodule

View File

@@ -0,0 +1,84 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module palram(
input clk,
input ce_pix,
input [15:0] vid_ctrl,
input dma_busy,
input [9:0] cpu_addr,
input [12:0] ga21_addr,
input ga21_we,
input ga21_req,
input [10:0] obj_color,
input obj_prio,
input obj_active,
input [10:0] pf_color,
input pf_prio,
input [15:0] din,
output [15:0] dout,
output reg [15:0] rgb_out
);
wire obj_pal_bank = ~vid_ctrl[13] & obj_prio;
wire obj_avail = ~vid_ctrl[7] & obj_active;
wire n_sela = ~dma_busy & (
( vid_ctrl[13] & obj_prio & obj_avail ) |
( ~obj_prio & pf_prio & obj_avail ) |
( ~vid_ctrl[13] & obj_prio & pf_prio & obj_avail ) |
( vid_ctrl[12] ) |
ga21_req
);
wire selb = ~dma_busy & ~ga21_req & ~vid_ctrl[12];
wire [1:0] sel = { selb, ~n_sela };
wire [12:0] full_cpu_addr = { vid_ctrl[10:8], cpu_addr[9:0] };
wire [12:0] obj_addr = { vid_ctrl[15], obj_pal_bank, obj_color };
wire [12:0] pf_addr = { vid_ctrl[15], vid_ctrl[14], pf_color };
wire we = sel == 0 ? ga21_we : sel == 1 ? ga21_we : 1'b0;
wire [12:0] selected_addr = sel == 0 ? full_cpu_addr :
sel == 1 ? ga21_addr :
sel == 2 ? obj_addr :
pf_addr;
singleport_unreg_ram #(.widthad(13), .width(16), .name("PALRAM")) ram
(
.clock(clk),
.address(selected_addr),
.q(dout),
.wren(we),
.data(din)
);
always_ff @(posedge clk) begin
if (ce_pix) rgb_out <= dout;
end
endmodule

View 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_mist.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_mist.ppf"]

View File

@@ -0,0 +1,365 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll_mist.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
// ************************************************************
//Copyright (C) 1991-2014 Altera Corporation
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, Altera MegaCore Function License
//Agreement, or other applicable license agreement, including,
//without limitation, that your use is for the sole purpose of
//programming logic devices manufactured by Altera and sold by
//Altera or its authorized distributors. Please refer to the
//applicable agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll_mist (
inclk0,
c0,
c1,
c2,
locked);
input inclk0;
output c0;
output c1;
output c2;
output locked;
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire7 = 1'h0;
wire [2:2] sub_wire4 = sub_wire0[2:2];
wire [0:0] sub_wire3 = sub_wire0[0:0];
wire [1:1] sub_wire1 = sub_wire0[1:1];
wire c1 = sub_wire1;
wire locked = sub_wire2;
wire c0 = sub_wire3;
wire c2 = sub_wire4;
wire sub_wire5 = inclk0;
wire [1:0] sub_wire6 = {sub_wire7, sub_wire5};
altpll altpll_component (
.inclk (sub_wire6),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.areset (1'b0),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 9,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 40,
altpll_component.clk0_phase_shift = "-694",
altpll_component.clk1_divide_by = 9,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 40,
altpll_component.clk1_phase_shift = "0",
altpll_component.clk2_divide_by = 27,
altpll_component.clk2_duty_cycle = 50,
altpll_component.clk2_multiply_by = 40,
altpll_component.clk2_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone III",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_mist",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_USED",
altpll_component.port_clk3 = "PORT_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 "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "120.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "120.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "40.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "1"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "120.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "120.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "40.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "-0.69444400"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "ns"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_mist.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLK2 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "40"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "-694"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "40"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "27"
// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "40"
// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_mist_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

View File

@@ -0,0 +1,124 @@
//============================================================================
// Irem M72 for MiSTer FPGA - ROM loading
//
// Copyright (C) 2022 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
import m92_pkg::*;
module rom_loader
(
input sys_clk,
input ioctl_downl,
input ioctl_wr,
input [7:0] ioctl_data,
output ioctl_wait,
output [24:0] sdr_addr,
output [15:0] sdr_data,
output [1:0] sdr_be,
output reg sdr_req,
input sdr_ack,
output [19:0] bram_addr,
output [7:0] bram_data,
output reg [4:0] bram_cs,
output bram_wr,
output board_cfg_t board_cfg
);
reg [27:0] base_addr;
reg reorder_64;
reg [24:0] offset;
reg [23:0] size;
enum {
BOARD_CFG,
REGION_IDX,
SIZE_0,
SIZE_1,
SIZE_2,
SDR_DATA,
BRAM_DATA
} stage = BOARD_CFG;
integer region = 0;
always @(posedge sys_clk) begin
if (!ioctl_downl) begin
stage <= BOARD_CFG;
region <= 0;
bram_cs <= 0;
end
if (sdr_ack == sdr_req) begin
ioctl_wait <= 0;
end
bram_wr <= 0;
if (ioctl_wr) begin
case (stage)
BOARD_CFG: begin board_cfg <= board_cfg_t'(ioctl_data); stage <= REGION_IDX; end
REGION_IDX: begin
if (ioctl_data == 8'hff) region <= region + 4'd1;
else region <= ioctl_data[3:0];
stage <= SIZE_0;
end
SIZE_0: begin size[23:16] <= ioctl_data; stage <= SIZE_1; end
SIZE_1: begin size[15:8] <= ioctl_data; stage <= SIZE_2; end
SIZE_2: begin
size[7:0] <= ioctl_data;
base_addr <= LOAD_REGIONS[region].base_addr;
reorder_64 <= LOAD_REGIONS[region].reorder_64;
bram_cs <= LOAD_REGIONS[region].bram_cs;
offset <= 25'd0;
if ({size[23:8], ioctl_data} == 24'd0)
stage <= REGION_IDX;
else if (LOAD_REGIONS[region].bram_cs != 0)
stage <= BRAM_DATA;
else
stage <= SDR_DATA;
end
SDR_DATA: begin
if (reorder_64)
sdr_addr <= base_addr[24:0] + {offset[24:7], offset[5:2], offset[6], offset[1:0]};
else
sdr_addr <= base_addr[24:0] + offset[24:0];
sdr_data = {ioctl_data, ioctl_data};
sdr_be <= { offset[0], ~offset[0] };
offset <= offset + 25'd1;
sdr_req <= ~sdr_req;
ioctl_wait <= 1;
if (offset == ( size - 1)) stage <= REGION_IDX;
end
BRAM_DATA: begin
bram_addr <= offset[19:0];
bram_data <= ioctl_data;
bram_wr <= 1;
offset <= offset + 25'd1;
if (offset == ( size - 1)) stage <= REGION_IDX;
end
endcase
end
end
endmodule

View File

@@ -0,0 +1,499 @@
//
// 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-2022 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_4w_cl3 (
// 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
// 1st bank
input port1_req,
output reg port1_ack = 0,
input port1_we,
input [23:1] port1_a,
input [1:0] port1_ds,
input [15:0] port1_d,
output reg [15:0] port1_q,
// cpu1 rom/ram
input [20:1] cpu1_rom_addr,
input cpu1_rom_cs,
output reg [15:0] cpu1_rom_q,
output reg cpu1_rom_valid,
input cpu1_ram_req,
output reg cpu1_ram_ack = 0,
input [22:1] cpu1_ram_addr,
input cpu1_ram_we,
input [1:0] cpu1_ram_ds,
input [15:0] cpu1_ram_d,
output reg [15:0] cpu1_ram_q,
// cpu2 rom/ram
input cpu2_ram_req,
output reg cpu2_ram_ack = 0,
input [22:1] cpu2_ram_addr,
input cpu2_ram_we,
input [1:0] cpu2_ram_ds,
input [15:0] cpu2_ram_d,
output reg [15:0] cpu2_ram_q,
// cpu3 rom
input vram_req,
output reg vram_ack = 0,
input [22:1] vram_addr,
output reg [31:0] vram_q,
// 2nd bank
input port2_req,
output reg port2_ack = 0,
input port2_we,
input [23:1] port2_a,
input [1:0] port2_ds,
input [15:0] port2_d,
output reg [31:0] port2_q,
input gfx1_req,
output reg gfx1_ack = 0,
input [23:1] gfx1_addr,
output reg [31:0] gfx1_q,
input gfx2_req,
output reg gfx2_ack = 0,
input [23:1] gfx2_addr,
output reg [31:0] gfx2_q,
input gfx3_req,
output reg gfx3_ack = 0,
input [23:1] gfx3_addr,
output reg [31:0] gfx3_q,
input sample_req,
output reg sample_ack = 0,
input [23:1] sample_addr,
output reg [63:0] sample_q,
input sp_req,
output reg sp_ack = 0,
input [23:1] sp_addr,
output reg [63:0] sp_q
);
parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate
localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 2 cycles@<100MHz
localparam BURST_LENGTH = 3'b010; // 000=1, 001=2, 010=4, 011=8
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
localparam CAS_LATENCY = 3'd3; // 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
4 words burst, CL3
cmd issued registered
0 RAS0 data1 returned
1 ras0, data1 returned
2 data1 returned
3 CAS0
4 RAS1 cas0
5 ras1
6
7 CAS1 data0 returned
8 cas1 - data0 masked if cas1 write
9 data0 returned (but masked via DQM)
10 data0 returned (but masked via DQM)
11 data1 returned
*/
localparam STATE_RAS0 = 4'd0; // first state in cycle
localparam STATE_CAS0 = 4'd3;
localparam STATE_READ0 = 4'd8; // STATE_CAS0 + CAS_LATENCY + 2'd2;
localparam STATE_READ0b = 4'd9;
localparam STATE_DS0 = 4'd4;
localparam STATE_DS0b = 4'd5;
localparam STATE_RAS1 = 4'd4; // Second ACTIVE command after RAS0 + tRRD (15ns)
localparam STATE_CAS1 = 4'd7; // CAS phase
localparam STATE_READ1 = 4'd0;
localparam STATE_READ1b = 4'd1;
localparam STATE_READ1c = 4'd2;
localparam STATE_READ1d = 4'd3;
localparam STATE_DS1a = 4'd8;
localparam STATE_DS1b = 4'd9;
localparam STATE_DS1c = 4'd10;
localparam STATE_DS1d = 4'd11;
localparam STATE_LAST = 4'd11;
reg [3: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[3];
reg [24:1] addr_latch_next[2];
reg [15:0] din_next;
reg [15:0] din_latch[2];
reg oe_next;
reg [1:0] oe_latch;
reg we_next;
reg [1:0] we_latch;
reg [1:0] ds_next;
reg [1:0] ds[2];
reg port1_state;
reg port2_state;
reg cpu1_ram_req_state;
reg cpu2_ram_req_state;
reg vram_req_state;
reg sp_req_state;
reg sample_req_state;
localparam PORT_NONE = 3'd0;
localparam PORT_CPU1_ROM = 3'd1;
localparam PORT_CPU1_RAM = 3'd2;
localparam PORT_CPU2_RAM = 3'd3;
localparam PORT_VRAM = 3'd4;
localparam PORT_GFX1 = 3'd1;
localparam PORT_GFX2 = 3'd2;
localparam PORT_GFX3 = 3'd3;
localparam PORT_SAMPLE = 3'd4;
localparam PORT_SP = 3'd5;
localparam PORT_REQ = 3'd6;
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
next_port[0] = PORT_NONE;
addr_latch_next[0] = addr_latch[0];
ds_next = 2'b00;
{ oe_next, we_next } = 2'b00;
din_next = 0;
if (refresh) begin
// nothing
end else if (port1_req ^ port1_state) begin
next_port[0] = PORT_REQ;
addr_latch_next[0] = { 1'b0, port1_a };
ds_next = port1_ds;
{ oe_next, we_next } = { ~port1_we, port1_we };
din_next = port1_d;
end else if (vram_req ^ vram_req_state) begin
next_port[0] = PORT_VRAM;
addr_latch_next[0] = { 2'b00, vram_addr };
ds_next = 2'b11;
{ oe_next, we_next } = 2'b10;
end else if (/*cpu1_rom_addr != addr_last[PORT_CPU1_ROM] &&*/ cpu1_rom_cs && !cpu1_rom_valid) begin
next_port[0] = PORT_CPU1_ROM;
addr_latch_next[0] = { 4'd0, cpu1_rom_addr };
ds_next = 2'b11;
{ oe_next, we_next } = 2'b10;
end else if (cpu1_ram_req ^ cpu1_ram_req_state) begin
next_port[0] = PORT_CPU1_RAM;
addr_latch_next[0] = { 2'b00, cpu1_ram_addr };
ds_next = cpu1_ram_ds;
{ oe_next, we_next } = { ~cpu1_ram_we, cpu1_ram_we };
din_next = cpu1_ram_d;
end else if (cpu2_ram_req ^ cpu2_ram_req_state) begin
next_port[0] = PORT_CPU2_RAM;
addr_latch_next[0] = { 2'b00, cpu2_ram_addr };
ds_next = cpu2_ram_ds;
{ oe_next, we_next } = { ~cpu2_ram_we, cpu2_ram_we };
din_next = cpu2_ram_d;
end
end
// PORT1: bank 2,3
always @(*) begin
if (port2_req ^ port2_state) begin
next_port[1] = PORT_REQ;
addr_latch_next[1] = { 1'b1, port2_a };
end else if (sp_req ^ sp_req_state) begin
next_port[1] = PORT_SP;
addr_latch_next[1] = { 1'b1, sp_addr };
end else if (gfx1_req ^ gfx1_ack) begin
next_port[1] = PORT_GFX1;
addr_latch_next[1] = { 1'b1, gfx1_addr };
end else if (gfx2_req ^ gfx2_ack) begin
next_port[1] = PORT_GFX2;
addr_latch_next[1] = { 1'b1, gfx2_addr };
end else if (gfx3_req ^ gfx3_ack) begin
next_port[1] = PORT_GFX3;
addr_latch_next[1] = { 1'b1, gfx3_addr };
end else if (sample_req ^ sample_req_state) begin
next_port[1] = PORT_SAMPLE;
addr_latch_next[1] = { 1'b1, sample_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
cpu1_rom_valid <= 0;
// 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
if (!cpu1_rom_cs) cpu1_rom_valid <= 0;
// RAS phase
// bank 0,1
if(t == STATE_RAS0) begin
addr_latch[0] <= addr_latch_next[0];
port[0] <= next_port[0];
ds[0] <= ds_next;
{ oe_latch[0], we_latch[0] } <= { oe_next, we_next };
din_latch[0] <= din_next;
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];
end
if (next_port[0] == PORT_REQ) port1_state <= port1_req;
if (next_port[0] == PORT_CPU1_RAM) cpu1_ram_req_state <= cpu1_ram_req;
if (next_port[0] == PORT_CPU2_RAM) cpu2_ram_req_state <= cpu2_ram_req;
if (next_port[0] == PORT_VRAM) vram_req_state <= vram_req;
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];
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_SP) sp_req_state <= sp_req;
if (next_port[1] == PORT_SAMPLE) sample_req_state <= sample_req;
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;
if (we_latch[0]) begin
{ SDRAM_DQMH, SDRAM_DQML } <= ~ds[0];
SDRAM_DQ <= din_latch[0];
case(port[0])
PORT_REQ: port1_ack <= port1_req;
PORT_CPU1_RAM: cpu1_ram_ack <= cpu1_ram_req;
PORT_CPU2_RAM: cpu2_ram_ack <= cpu2_ram_req;
default: ;
endcase;
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;
if (we_latch[1]) begin
{ SDRAM_DQMH, SDRAM_DQML } <= ~ds[1];
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
if(t == STATE_DS0 && oe_latch[0]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
if(t == STATE_DS0b && oe_latch[0] && !we_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
// 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_ROM: begin cpu1_rom_q <= sd_din; cpu1_rom_valid <= 1; end
PORT_CPU1_RAM: begin cpu1_ram_q <= sd_din; cpu1_ram_ack <= cpu1_ram_req; end
PORT_CPU2_RAM: begin cpu2_ram_q <= sd_din; cpu2_ram_ack <= cpu2_ram_req; end
PORT_VRAM: vram_q[15:0] <= sd_din;
default: ;
endcase;
end
if(t == STATE_READ0b && oe_latch[0]) begin
case(port[0])
PORT_VRAM: begin vram_q[31:16] <= sd_din; vram_ack <= vram_req; end
default: ;
endcase;
end
if(t == STATE_DS1a && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
if(t == STATE_DS1c && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
if(t == STATE_DS1d && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= 0;
if(t == STATE_READ1 && oe_latch[1]) begin
case(port[1])
PORT_REQ : port2_q[15:0] <= sd_din;
PORT_GFX1 : gfx1_q[15:0] <= sd_din;
PORT_GFX2 : gfx2_q[15:0] <= sd_din;
PORT_GFX3 : gfx3_q[15:0] <= sd_din;
PORT_SAMPLE: sample_q[15:0] <= sd_din;
PORT_SP : sp_q[15:0] <= sd_din;
default: ;
endcase;
end
if(t == STATE_READ1b && oe_latch[1]) begin
case(port[1])
PORT_REQ : begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end
PORT_GFX1 : begin gfx1_q[31:16] <= sd_din; gfx1_ack <= gfx1_req; end
PORT_GFX2 : begin gfx2_q[31:16] <= sd_din; gfx2_ack <= gfx2_req; end
PORT_GFX3 : begin gfx3_q[31:16] <= sd_din; gfx3_ack <= gfx3_req; end
PORT_SAMPLE: sample_q[31:16] <= sd_din;
PORT_SP : sp_q[31:16] <= sd_din;
default: ;
endcase;
end
if(t == STATE_READ1c && oe_latch[1]) begin
case(port[1])
PORT_SAMPLE: sample_q[47:32] <= sd_din;
PORT_SP: sp_q[47:32] <= sd_din;
default: ;
endcase;
end
if(t == STATE_READ1d && oe_latch[1]) begin
case(port[1])
PORT_SAMPLE: begin sample_q[63:48] <= sd_din; sample_ack <= sample_req; end
PORT_SP: begin sp_q[63:48] <= sd_din; sp_ack <= sp_req; end
default: ;
endcase;
end
end
end
endmodule

View File

@@ -0,0 +1,266 @@
//============================================================================
// Copyright (C) 2023 Martin Donlon
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module sound(
input clk_sys, // 40M
input reset,
input paused,
input filter_en,
input dbg_fm_en,
input latch_wr,
input latch_rd,
input [7:0] latch_din,
output [7:0] latch_dout,
output latch_rdy,
// ioctl load
input [19:0] rom_addr,
input [7:0] rom_data,
input rom_wr,
input [7:0] secure_addr,
input [7:0] secure_data,
input secure_wr,
output reg [15:0] sample,
// sdr
output [24:0] sdr_addr,
input [63:0] sdr_data,
output sdr_req,
input sdr_ack,
output reg [24:0] sdr_cpu_addr,
input [15:0] sdr_cpu_dout,
output reg [15:0] sdr_cpu_din,
output reg sdr_cpu_req,
input sdr_cpu_ack,
output reg [1:0] sdr_cpu_wr_sel
);
wire [15:0] sample_out, fm_sample, fm_sample_flt;
localparam OVERALL_GAIN = 0.9;
wire [11:0] fm_scale = int'(1.3 * OVERALL_GAIN * 128);
wire [11:0] pcm_scale = int'(3.1 * OVERALL_GAIN * 128);
always_ff @(posedge clk_sys) begin
reg [27:0] sum;
reg [27:0] fm;
reg [27:0] pcm;
fm <= $signed(filter_en ? fm_sample_flt : fm_sample) * fm_scale;
pcm <= $signed(sample_out) * pcm_scale;
if (!dbg_fm_en) fm <= 0;
sum <= fm + pcm;
if (&sum[27:22] || &(~sum[27:22])) sample <= sum[22:7];
else if (sum[27]) sample <= 16'h8000;
else sample <= 16'h7fff;
end
wire ce_28m, ce_14m, ce_7m, ce_3_5m, ce_1_7m;
jtframe_frac_cen #(6) pixel_cen
(
.clk(clk_sys),
.cen_in(~paused),
.n(10'd63),
.m(10'd88),
.cen({ce_1_7m, ce_3_5m, ce_7m, ce_14m, ce_28m})
);
wire ram_cs, rom_cs, io_cs;
wire ym2151_cs, ga20_cs, snd_latch_cs, main_latch_cs;
wire [1:0] cpu_be;
wire [15:0] cpu_dout, cpu_din;
wire [19:0] cpu_addr;
reg [15:0] ramrom_dout;
wire cpu_rd, cpu_wr;
wire [7:0] ym2151_dout;
wire ym2151_irq_n;
wire [7:0] ga20_dout;
reg [7:0] main_latch, snd_latch;
reg main_latch_rdy, snd_latch_rdy;
assign latch_rdy = main_latch_rdy;
assign latch_dout = main_latch;
wire [15:0] cpu_word_dout = cpu_addr[0] ? { cpu_dout[7:0], 8'h00 } : cpu_dout;
wire [1:0] cpu_word_be = cpu_addr[0] ? { cpu_be[0], 1'b0 } : cpu_be;
assign ram_cs = cpu_addr[19:14] == {4'ha, 2'b00};// cpu_addr[13:12]>= 8'ha0 && cpu_addr[19:12] < 8'ha4;
assign io_cs = cpu_addr[19:12] == 8'ha8;
assign rom_cs = ~ram_cs & ~io_cs;
assign ga20_cs = io_cs & cpu_addr[7:6] == 2'b00; // 0xa8000 - 0xa803f
assign ym2151_cs = io_cs & cpu_addr[7:2] == 6'b010000; // 0xa8040 - 0xa8043
assign snd_latch_cs = io_cs & cpu_addr[7:0] == 8'h44;
assign main_latch_cs = io_cs & cpu_addr[7:0] == 8'h46;
assign cpu_din = rom_cs ? ( cpu_addr[0] ? { ramrom_dout[7:0], ramrom_dout[15:8] } : ramrom_dout ) :
ram_cs ? ( cpu_addr[0] ? { 8'd0, ramrom_dout[15:8] } : ramrom_dout ) :
ym2151_cs ? { 8'd0, ym2151_dout } :
snd_latch_cs ? { 8'd0, snd_latch } :
ga20_cs ? { 8'd0, ga20_dout } :
16'hffff;
wire ram_rom_memrq = rom_cs | ram_cs;
wire cpu_region_writable = !rom_cs;
reg mem_rq_active;
reg cpu_rd_lat, cpu_wr_lat;
wire cpu_mem_read = cpu_rd | cpu_rd_lat;
wire cpu_mem_write = cpu_wr | cpu_wr_lat;
wire ramrom_busy = ((ram_rom_memrq) & (cpu_mem_read | cpu_mem_write)) | mem_rq_active;
always_ff @(posedge clk_sys, posedge reset) begin
if (reset) begin
mem_rq_active <= 0;
end else begin
cpu_rd_lat <= cpu_rd;
cpu_wr_lat <= cpu_wr;
if (!mem_rq_active) begin
if (ram_rom_memrq & ((cpu_rd & ~cpu_rd_lat) | (cpu_wr & ~cpu_wr_lat))) begin // sdram request
sdr_cpu_wr_sel <= 2'b00;
sdr_cpu_addr <= rom_cs ? {REGION_SOUND.base_addr[24:17], cpu_addr[16:0]} : {REGION_SOUND_RAM.base_addr[24:14], cpu_addr[13:0]};
if (cpu_wr & cpu_region_writable) begin
sdr_cpu_wr_sel <= cpu_word_be;
sdr_cpu_din <= cpu_word_dout;
end
sdr_cpu_req <= ~sdr_cpu_req;
mem_rq_active <= 1;
end
end else if (sdr_cpu_req == sdr_cpu_ack) begin
mem_rq_active <= 0;
ramrom_dout <= sdr_cpu_dout;
end
end
end
v35 v35(
.clk(clk_sys),
.ce(ce_28m & !ramrom_busy),
.ce_cycle(ce_7m & !ramrom_busy),
.reset(reset),
.mem_rd(cpu_rd),
.mem_wr(cpu_wr),
.mem_be(cpu_be),
.mem_addr(cpu_addr),
.mem_dout(cpu_dout),
.mem_din(cpu_din),
.intp0(ym2151_irq_n),
.intp1(~snd_latch_rdy),
.intp2(0),
.secure(1),
.secure_wr(secure_wr),
.secure_addr(secure_addr),
.secure_data(secure_data)
);
jt51 ym2151(
.rst(reset),
.clk(clk_sys),
.cen(ce_3_5m),
.cen_p1(ce_1_7m),
.cs_n(~ym2151_cs),
.wr_n(~cpu_wr),
.a0(cpu_addr[1]),
.din(cpu_dout[7:0]),
.dout(ym2151_dout),
.irq_n(ym2151_irq_n),
.xright(fm_sample),
.xleft()
);
// fc1 = 19020hz
// fc2 = 8707hz
IIR_filter #( .use_params(1), .stereo(0), .coeff_x(0.000001054852861174913), .coeff_x0(3), .coeff_x1(3), .coeff_x2(1), .coeff_y0(-2.94554610428990093496), .coeff_y1(2.89203308225615352001), .coeff_y2(-0.94647938909674766972)) lpf_ym (
.clk(clk_sys),
.reset(reset),
.ce(ce_3_5m),
.sample_ce(ce_3_5m),
.cx(), .cx0(), .cx1(), .cx2(), .cy0(), .cy1(), .cy2(),
.input_l(fm_sample),
.output_l(fm_sample_flt),
.input_r(),
.output_r()
);
wire [19:0] sample_rom_addr;
assign sdr_addr = { REGION_GA20.base_addr[24:20], sample_rom_addr };
ga20 ga20(
.clk(clk_sys),
.reset(reset),
.filter_en(filter_en),
.ce(ce_3_5m),
.cs(ga20_cs),
.rd(cpu_rd),
.wr(cpu_wr),
.addr(cpu_addr[5:1]),
.din(cpu_dout[7:0]),
.dout(ga20_dout),
.sample_rom_req(sdr_req),
.sample_rom_addr(sample_rom_addr),
.sample_rom_ack(sdr_ack),
.sample_rom_din(sdr_data),
.sample_out(sample_out)
);
always_ff @(posedge clk_sys, posedge reset) begin
if (reset) begin
main_latch_rdy <= 0;
snd_latch_rdy <= 0;
end else begin
if (latch_rd) begin
main_latch_rdy <= 0;
end
if (latch_wr) begin
snd_latch <= latch_din;
snd_latch_rdy <= 1;
end
if (snd_latch_cs & cpu_wr) begin
snd_latch_rdy <= 0;
end
if (main_latch_cs & cpu_wr) begin
main_latch <= cpu_dout[7:0];
main_latch_rdy <= 1;
end
end
end
endmodule

View File

@@ -0,0 +1,395 @@
module v35(
input clk,
input ce, // 4x internal clock
input ce_cycle, // real internal clock
input reset,
output mem_rd,
output mem_wr,
output [1:0] mem_be,
output [19:0] mem_addr,
output [15:0] mem_dout,
input [15:0] mem_din,
input intp0,
input intp1,
input intp2,
input secure,
input secure_wr,
input [7:0] secure_addr,
input [7:0] secure_data
);
wire rd, wr;
wire prefetching;
wire [1:0] be;
wire [19:0] addr;
wire [15:0] dout, din;
reg [2:0] irq_pending = 0;
reg [7:0] irq_vec;
wire irq_ack;
wire irq_fini;
reg [15:0] TM0, MD0, TM1, MD1, WTC;
reg [7:0] P0, PM0, PMC0, P1, PM1, PMC1, P2, PM2;
reg [7:0] PMC2, PT, PMT, INTM, EMS0, EMS1, EMS2, EXIC0;
reg [7:0] EXIC1, EXIC2, ISPR, RXB0, TXB0, SRMS0, STMS0, SCM0;
reg [7:0] SCC0, BRG0, SCE0, SEIC0, SRIC0, STIC0, RXB1, TXB1;
reg [7:0] SRMS1, STMS1, SCM1, SCC1, BRG1, SCE1, SEIC1, SRIC1;
reg [7:0] STIC1, TMC0, TMC1, TMMS0, TMMS1, TMMS2, TMIC0, TMIC1;
reg [7:0] TMIC2, DMAC0, DMAM0, DMAC1, DMAM1, DIC0, DIC1, STBC;
reg [7:0] RFM, FLAG, PRC, TBIC, IDB;
wire RAMEN = PRC[6];
wire [1:0] TB = PRC[3:2];
wire [1:0] PCK = PRC[1:0];
wire ESNMI = INTM[0];
wire ES0 = INTM[2];
wire ES1 = INTM[4];
wire ES2 = INTM[6];
reg [7:0] exi_prio_bit;
reg [15:0] internal_din;
reg [7:0] iram[256];
reg [1:0] wait_cycles = 0;
reg intp0_prev, intp1_prev, intp2_prev;
wire internal_rq = ~prefetching && ( addr[19:9] == { IDB, 3'b111 } || addr[19:0] == 20'hfffff );
wire internal_ram_rq = RAMEN & internal_rq & ~addr[8];
wire sfr_area_rq = internal_rq & addr[8];
reg internal_rq_latch;
assign mem_rd = rd & ~internal_rq;
assign mem_wr = wr & ~internal_rq;
assign mem_be = be;
assign mem_addr = addr;
assign mem_dout = dout;
assign din = internal_rq_latch ? internal_din : mem_din;
always_ff @(posedge clk) begin
if (reset) begin
PM0 <= 8'hff;
PMC0 <= 8'h00;
PM1 <= 8'hff;
PMC1 <= 8'h00;
PM2 <= 8'hff;
PMC2 <= 8'h00;
PMT <= 8'h00;
INTM <= 8'h00;
EXIC0 <= 8'h47;
EXIC1 <= 8'h47;
EXIC2 <= 8'h47;
ISPR <= 8'h00;
SCM0 <= 8'h00;
SCC0 <= 8'h00;
BRG0 <= 8'h00;
SCE0 <= 8'h00;
SEIC0 <= 8'h47;
SRIC0 <= 8'h47;
STIC0 <= 8'h47;
SCM1 <= 8'h00;
SCC1 <= 8'h00;
BRG1 <= 8'h00;
SCE1 <= 8'h00;
SEIC1 <= 8'h47;
SRIC1 <= 8'h47;
STIC1 <= 8'h47;
TMC0 <= 8'h00;
TMC1 <= 8'h00;
TMIC0 <= 8'h47;
TMIC1 <= 8'h47;
TMIC2 <= 8'h47;
DMAM0 <= 8'h00;
DMAM1 <= 8'h00;
DIC0 <= 8'h47;
DIC1 <= 8'h47;
STBC <= 8'h00;
RFM <= 8'hfc;
WTC <= 16'hffff;
FLAG <= 8'h00;
PRC <= 8'h4e;
TBIC <= 8'h47;
IDB <= 8'hff;
irq_pending <= 0;
wait_cycles <= 2'd0;
end else begin
if (sfr_area_rq) begin
if (wr) begin
case(addr[7:0])
8'h00: P0 <= dout[7:0];
8'h01: PM0 <= dout[7:0];
8'h02: PMC0 <= dout[7:0];
8'h08: P1 <= dout[7:0];
8'h09: PM1 <= dout[7:0];
8'h0a: PMC1 <= dout[7:0];
8'h10: P2 <= dout[7:0];
8'h11: PM2 <= dout[7:0];
8'h12: PMC2 <= dout[7:0];
8'h3b: PMT <= dout[7:0];
8'h40: INTM <= dout[7:0];
8'h44: EMS0 <= dout[7:0];
8'h45: EMS1 <= dout[7:0];
8'h46: EMS2 <= dout[7:0];
8'h4c: EXIC0 <= dout[7:0];
8'h4d: EXIC1 <= dout[7:0];
8'h4e: EXIC2 <= dout[7:0];
8'h62: TXB0 <= dout[7:0];
8'h65: SRMS0 <= dout[7:0];
8'h66: STMS0 <= dout[7:0];
8'h68: SCM0 <= dout[7:0];
8'h69: SCC0 <= dout[7:0];
8'h6a: BRG0 <= dout[7:0];
8'h6c: SEIC0 <= dout[7:0];
8'h6d: SRIC0 <= dout[7:0];
8'h6e: STIC0 <= dout[7:0];
8'h72: TXB1 <= dout[7:0];
8'h75: SRMS1 <= dout[7:0];
8'h76: STMS1 <= dout[7:0];
8'h78: SCM1 <= dout[7:0];
8'h79: SCC1 <= dout[7:0];
8'h7a: BRG1 <= dout[7:0];
8'h7c: SEIC1 <= dout[7:0];
8'h7d: SRIC1 <= dout[7:0];
8'h7e: STIC1 <= dout[7:0];
8'h80: begin
if (be[0]) TM0[7:0] <= dout[7:0];
if (be[1]) TM0[15:8] <= dout[15:8];
end
8'h81: TM0[15:8] <= dout[7:0];
8'h82: begin
if (be[0]) MD0[7:0] <= dout[7:0];
if (be[1]) MD0[15:8] <= dout[15:8];
end
8'h83: MD0[15:8] <= dout[7:0];
8'h88: begin
if (be[0]) TM1[7:0] <= dout[7:0];
if (be[1]) TM1[15:8] <= dout[15:8];
end
8'h89: TM1[15:8] <= dout[7:0];
8'h8a: begin
if (be[0]) MD1[7:0] <= dout[7:0];
if (be[1]) MD1[15:8] <= dout[15:8];
end
8'h8b: MD1[15:8] <= dout[7:0];
8'h90: TMC0 <= dout[7:0];
8'h91: TMC1 <= dout[7:0];
8'h94: TMMS0 <= dout[7:0];
8'h95: TMMS1 <= dout[7:0];
8'h96: TMMS2 <= dout[7:0];
8'h9c: TMIC0 <= dout[7:0];
8'h9d: TMIC1 <= dout[7:0];
8'h9e: TMIC2 <= dout[7:0];
8'ha0: DMAC0 <= dout[7:0];
8'ha1: DMAM0 <= dout[7:0];
8'ha2: DMAC1 <= dout[7:0];
8'ha3: DMAM1 <= dout[7:0];
8'hac: DIC0 <= dout[7:0];
8'had: DIC1 <= dout[7:0];
8'he0: STBC <= dout[7:0];
8'he1: RFM <= dout[7:0];
8'he8: begin
if (be[0]) WTC[7:0] <= dout[7:0];
if (be[1]) WTC[15:8] <= dout[15:8];
end
8'he9: WTC[15:8] <= dout[7:0];
8'hea: FLAG <= dout[7:0];
8'heb: PRC <= dout[7:0];
8'hec: TBIC <= dout[7:0];
8'hff: IDB <= dout[7:0];
endcase
end else if (rd) begin
case(addr[7:0])
8'h00: internal_din <= { 8'd0, P0 };
8'h08: internal_din <= { 8'd0, P1 };
8'h10: internal_din <= { 8'd0, P2 };
8'h38: internal_din <= { 8'd0, PT };
8'h3b: internal_din <= { 8'd0, PMT };
8'h40: internal_din <= { 8'd0, INTM };
8'h44: internal_din <= { 8'd0, EMS0 };
8'h45: internal_din <= { 8'd0, EMS1 };
8'h46: internal_din <= { 8'd0, EMS2 };
8'h4c: internal_din <= { 8'd0, EXIC0 };
8'h4d: internal_din <= { 8'd0, EXIC1 };
8'h4e: internal_din <= { 8'd0, EXIC2 };
8'hfc: internal_din <= { 8'd0, ISPR };
8'h60: internal_din <= { 8'd0, RXB0 };
8'h65: internal_din <= { 8'd0, SRMS0 };
8'h66: internal_din <= { 8'd0, STMS0 };
8'h68: internal_din <= { 8'd0, SCM0 };
8'h69: internal_din <= { 8'd0, SCC0 };
8'h6a: internal_din <= { 8'd0, BRG0 };
8'h6b: internal_din <= { 8'd0, SCE0 };
8'h6c: internal_din <= { 8'd0, SEIC0 };
8'h6d: internal_din <= { 8'd0, SRIC0 };
8'h6e: internal_din <= { 8'd0, STIC0 };
8'h70: internal_din <= { 8'd0, RXB1 };
8'h75: internal_din <= { 8'd0, SRMS1 };
8'h76: internal_din <= { 8'd0, STMS1 };
8'h78: internal_din <= { 8'd0, SCM1 };
8'h79: internal_din <= { 8'd0, SCC1 };
8'h7a: internal_din <= { 8'd0, BRG1 };
8'h7b: internal_din <= { 8'd0, SCE1 };
8'h7c: internal_din <= { 8'd0, SEIC1 };
8'h7d: internal_din <= { 8'd0, SRIC1 };
8'h7e: internal_din <= { 8'd0, STIC1 };
8'h80: internal_din <= TM0;
8'h81: internal_din <= { 8'd0, TM0[15:8] };
8'h82: internal_din <= MD0;
8'h83: internal_din <= { 8'd0, MD0[15:8] };
8'h88: internal_din <= TM1;
8'h89: internal_din <= { 8'd0, TM1[15:8] };
8'h8a: internal_din <= MD1;
8'h8b: internal_din <= { 8'd0, MD1[15:8] };
8'h90: internal_din <= { 8'd0, TMC0 };
8'h91: internal_din <= { 8'd0, TMC1 };
8'h94: internal_din <= { 8'd0, TMMS0 };
8'h95: internal_din <= { 8'd0, TMMS1 };
8'h96: internal_din <= { 8'd0, TMMS2 };
8'h9c: internal_din <= { 8'd0, TMIC0 };
8'h9d: internal_din <= { 8'd0, TMIC1 };
8'h9e: internal_din <= { 8'd0, TMIC2 };
8'ha0: internal_din <= { 8'd0, DMAC0 };
8'ha1: internal_din <= { 8'd0, DMAM0 };
8'ha2: internal_din <= { 8'd0, DMAC1 };
8'ha3: internal_din <= { 8'd0, DMAM1 };
8'hac: internal_din <= { 8'd0, DIC0 };
8'had: internal_din <= { 8'd0, DIC1 };
8'he0: internal_din <= { 8'd0, STBC };
8'he1: internal_din <= { 8'd0, RFM };
8'he8: internal_din <= WTC;
8'he9: internal_din <= { 8'd0, WTC[15:8] };
8'hea: internal_din <= { 8'd0, FLAG };
8'heb: internal_din <= { 8'd0, PRC };
8'hec: internal_din <= { 8'd0, TBIC };
8'hff: internal_din <= { 8'd0, IDB };
endcase
end
end else if (internal_ram_rq) begin
/*
if (wr) begin
if (be[0]) iram[addr[7:0]] <= dout[7:0];
if (be[1]) iram[addr[7:0] + 8'd1] <= dout[15:8];
end else if (rd) begin
internal_din <= { iram[addr[7:0] + 8'd1], iram[addr[7:0]] };
end
*/
end
if (rd) internal_rq_latch <= internal_rq;
if (rd | wr) begin
case(addr[19:16])
4'h0, 4'h1: wait_cycles <= WTC[1:0];
4'h2, 4'h3: wait_cycles <= WTC[3:2];
4'h4, 4'h5: wait_cycles <= WTC[5:4];
4'h6, 4'h7: wait_cycles <= WTC[7:6];
4'h8, 4'h9: wait_cycles <= WTC[9:8];
4'ha, 4'hb: wait_cycles <= WTC[11:10];
4'hc, 4'hf: wait_cycles <= WTC[13:12];
endcase
end
if (ce_cycle) begin
if (wait_cycles != 2'd0) wait_cycles <= wait_cycles - 2'd1;
/////////////////////////////////////////////
//// General CE processing
if (irq_ack) begin
ISPR <= ISPR | exi_prio_bit;
case(irq_pending)
1: EXIC0[7] <= 0;
2: EXIC1[7] <= 0;
3: EXIC2[7] <= 0;
endcase
irq_pending <= 0;
end
if (irq_fini) begin
casex(ISPR)
8'bxxxxxxx1: ISPR <= ISPR & 8'b11111110;
8'bxxxxxx10: ISPR <= ISPR & 8'b11111100;
8'bxxxxx100: ISPR <= ISPR & 8'b11111000;
8'bxxxx1000: ISPR <= ISPR & 8'b11110000;
8'bxxx10000: ISPR <= ISPR & 8'b11100000;
8'bxx100000: ISPR <= ISPR & 8'b11000000;
8'bx1000000: ISPR <= ISPR & 8'b10000000;
8'b10000000: ISPR <= ISPR & 8'b00000000;
endcase
end
intp0_prev <= intp0;
intp1_prev <= intp1;
intp2_prev <= intp2;
if (intp0 != intp0_prev && intp0 == ES0) EXIC0[7] <= 1;
if (intp1 != intp1_prev && intp1 == ES1) EXIC1[7] <= 1;
if (intp2 != intp2_prev && intp2 == ES2) EXIC2[7] <= 1;
if (irq_pending == 0 && (ISPR & exi_prio_bit) == 8'd0) begin
if (EXIC0[7] & ~EXIC0[6]) begin
irq_pending <= 2'd1;
irq_vec <= 8'd24;
end else if (EXIC1[7] & ~EXIC1[6]) begin
irq_pending <= 2'd2;
irq_vec <= 8'd25;
end else if (EXIC2[7] & ~EXIC2[6]) begin
irq_pending <= 2'd3;
irq_vec <= 8'd26;
end
end
end
end
exi_prio_bit <= 8'd1 << EXIC0[2:0];
end
v30 core(
.clk(clk),
.ce(ce_cycle & (wait_cycles == 2'd0)),
.ce_4x(ce & (wait_cycles == 2'd0)),
.reset(reset),
.turbo(1),
.SLOWTIMING(),
.cpu_idle(),
.cpu_halt(),
.cpu_irqrequest(),
.cpu_prefix(),
.cpu_done(),
.bus_read(rd),
.bus_write(wr),
.bus_prefetch(prefetching),
.bus_be(be),
.bus_addr(addr),
.bus_datawrite(dout),
.bus_dataread(din),
.irqrequest_in(irq_pending != 0),
.irqvector_in({irq_vec, 2'b00}),
.irqrequest_ack(irq_ack),
.irqrequest_fini(irq_fini),
.secure(secure),
.secure_wr(secure_wr),
.secure_addr(secure_addr),
.secure_data(secure_data),
// TODO - m92 doesn't use IO ports, but we want to merge these with data anyway
.RegBus_Din(),
.RegBus_Adr(),
.RegBus_wren(),
.RegBus_rden(),
.RegBus_Dout(0)
);
endmodule

View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2011 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
# Version 10.1 Build 197 01/19/2011 Service Pack 1 SJ Full Version
# Date created = 23:49:02 July 13, 2012
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "10.1"
DATE = "23:49:02 July 13, 2012"
# Revisions
PROJECT_REVISION = "IremM92"

View File

@@ -0,0 +1,252 @@
set_global_assignment -name FIT_ATTEMPTS_TO_SKIP 0
# -------------------------------------------------------------------------- #
#
# 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 = 21:06:00 February 29, 2020
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# IremM92_MiST_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
# Project-Wide Assignments
# ========================
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:../rtl/build_id.tcl"
set_global_assignment -name SMART_RECOMPILE ON
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_G1 -to LED
set_location_assignment PIN_E1 -to CLOCK_27
set_location_assignment PIN_P16 -to VGA_R[5]
set_location_assignment PIN_P15 -to VGA_R[4]
set_location_assignment PIN_R16 -to VGA_R[3]
set_location_assignment PIN_R14 -to VGA_R[2]
set_location_assignment PIN_T15 -to VGA_R[1]
set_location_assignment PIN_T14 -to VGA_R[0]
set_location_assignment PIN_J16 -to VGA_B[5]
set_location_assignment PIN_J15 -to VGA_B[4]
set_location_assignment PIN_J14 -to VGA_B[3]
set_location_assignment PIN_K16 -to VGA_B[2]
set_location_assignment PIN_K15 -to VGA_B[1]
set_location_assignment PIN_J13 -to VGA_B[0]
set_location_assignment PIN_F16 -to VGA_G[5]
set_location_assignment PIN_F15 -to VGA_G[4]
set_location_assignment PIN_L16 -to VGA_G[3]
set_location_assignment PIN_L15 -to VGA_G[2]
set_location_assignment PIN_N15 -to VGA_G[1]
set_location_assignment PIN_N16 -to VGA_G[0]
set_location_assignment PIN_T10 -to VGA_VS
set_location_assignment PIN_T11 -to VGA_HS
set_location_assignment PIN_T12 -to AUDIO_L
set_location_assignment PIN_T13 -to AUDIO_R
set_location_assignment PIN_T2 -to SPI_DO
set_location_assignment PIN_R1 -to SPI_DI
set_location_assignment PIN_T3 -to SPI_SCK
set_location_assignment PIN_T4 -to SPI_SS2
set_location_assignment PIN_G15 -to SPI_SS3
set_location_assignment PIN_G16 -to SPI_SS4
set_location_assignment PIN_H2 -to CONF_DATA0
set_location_assignment PIN_B14 -to SDRAM_A[0]
set_location_assignment PIN_C14 -to SDRAM_A[1]
set_location_assignment PIN_C15 -to SDRAM_A[2]
set_location_assignment PIN_C16 -to SDRAM_A[3]
set_location_assignment PIN_B16 -to SDRAM_A[4]
set_location_assignment PIN_A15 -to SDRAM_A[5]
set_location_assignment PIN_A14 -to SDRAM_A[6]
set_location_assignment PIN_A13 -to SDRAM_A[7]
set_location_assignment PIN_A12 -to SDRAM_A[8]
set_location_assignment PIN_D16 -to SDRAM_A[9]
set_location_assignment PIN_B13 -to SDRAM_A[10]
set_location_assignment PIN_D15 -to SDRAM_A[11]
set_location_assignment PIN_D14 -to SDRAM_A[12]
set_location_assignment PIN_C3 -to SDRAM_DQ[0]
set_location_assignment PIN_C2 -to SDRAM_DQ[1]
set_location_assignment PIN_A4 -to SDRAM_DQ[2]
set_location_assignment PIN_B4 -to SDRAM_DQ[3]
set_location_assignment PIN_A6 -to SDRAM_DQ[4]
set_location_assignment PIN_D6 -to SDRAM_DQ[5]
set_location_assignment PIN_A7 -to SDRAM_DQ[6]
set_location_assignment PIN_B7 -to SDRAM_DQ[7]
set_location_assignment PIN_E6 -to SDRAM_DQ[8]
set_location_assignment PIN_C6 -to SDRAM_DQ[9]
set_location_assignment PIN_B6 -to SDRAM_DQ[10]
set_location_assignment PIN_B5 -to SDRAM_DQ[11]
set_location_assignment PIN_A5 -to SDRAM_DQ[12]
set_location_assignment PIN_B3 -to SDRAM_DQ[13]
set_location_assignment PIN_A3 -to SDRAM_DQ[14]
set_location_assignment PIN_A2 -to SDRAM_DQ[15]
set_location_assignment PIN_A11 -to SDRAM_BA[0]
set_location_assignment PIN_B12 -to SDRAM_BA[1]
set_location_assignment PIN_C9 -to SDRAM_DQMH
set_location_assignment PIN_C8 -to SDRAM_DQML
set_location_assignment PIN_A10 -to SDRAM_nRAS
set_location_assignment PIN_B10 -to SDRAM_nCAS
set_location_assignment PIN_D8 -to SDRAM_nWE
set_location_assignment PIN_B11 -to SDRAM_nCS
set_location_assignment PIN_C11 -to SDRAM_CKE
set_location_assignment PIN_R4 -to SDRAM_CLK
# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name TOP_LEVEL_ENTITY IremM92_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
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE ON
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE EP4CE22F17C8
set_global_assignment -name FAMILY "Cyclone IV E"
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"
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"
# 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/cpu.stp
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
# Advanced I/O Timing Assignments
# ===============================
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
# -----------------------------
# start ENTITY(IremM92_MiST)
# Pin & Location Assignments
# ==========================
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[*]
# Fitter Assignments
# ==================
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
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(IremM92_MiST)
# ---------------------------
set_location_assignment PLL_1 -to pll|altpll_component|auto_generated|pll1
set_global_assignment -name DSP_BLOCK_BALANCING "DSP BLOCKS"
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION AUTO
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name AUTO_RESOURCE_SHARING ON
set_global_assignment -name SDC_FILE ../IremM92.sdc
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/IremM92_MiST.sv
set_global_assignment -name QIP_FILE ../rtl/pll_mist.qip
set_global_assignment -name QIP_FILE ../rtl/m92.qip
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/v30/V30.qip
set_global_assignment -name QIP_FILE ../../../common/Sound/jt51/jt51.qip
set_global_assignment -name VERILOG_MACRO "JT51_ONLYTIMERS=1"
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -233,6 +233,8 @@ architecture rtl of T80 is
signal LDHLSP : std_logic;
signal ADDSPdd : std_logic;
signal IORQ_i : std_logic;
signal Write_i : std_logic;
signal NoRead_i : std_logic;
signal Special_LD : std_logic_vector(2 downto 0);
signal ExchangeDH : std_logic;
signal ExchangeRp : std_logic;
@@ -262,6 +264,8 @@ architecture rtl of T80 is
signal No_PC : std_logic;
signal DOR : std_logic_vector(127 downto 0);
signal Really_Wait : std_logic;
begin
REG <= IntE_FF2 & IntE_FF1 & IStatus & DOR & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC when Alternate = '0'
@@ -338,8 +342,8 @@ begin
SetEI => SetEI,
IMode => IMode,
Halt => Halt,
NoRead => NoRead,
Write => Write,
NoRead => NoRead_i,
Write => Write_i,
R800_mode => R800_mode,
No_PC => No_PC,
XYbit_undoc => XYbit_undoc);
@@ -370,6 +374,8 @@ begin
Q => ALU_Q,
F_Out => F_Out);
Really_Wait <= not Wait_n and (Write_i or not NoRead_i);
ClkEn <= CEN and not BusAck;
T_Res <= '1' when TState = unsigned(TStates) else '0';
@@ -679,7 +685,7 @@ begin
end if;
end if;
if (TState = 2 and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then
if (TState = 2 and Really_Wait = '0' and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then
ioq := ('0' & DI_Reg) + ('0' & std_logic_vector(ID16(7 downto 0)));
F(Flag_N) <= DI_Reg(7);
F(Flag_C) <= ioq(8);
@@ -688,7 +694,7 @@ begin
F(Flag_P) <= not (ioq(0) xor ioq(1) xor ioq(2) xor ioq(3) xor ioq(4) xor ioq(5) xor ioq(6) xor ioq(7));
end if;
if TState = 2 and Wait_n = '1' then
if TState = 2 and Really_Wait = '0' then
if ISet = "01" and MCycle = "111" then
IR <= DInst;
end if;
@@ -716,7 +722,7 @@ begin
end if;
end if;
if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then
if (TState = 2 and Really_Wait = '0') or (TState = 4 and MCycle = "001") then
if IncDec_16(2 downto 0) = "111" then
if IncDec_16(3) = '1' then
SP <= SP - 1;
@@ -1005,7 +1011,7 @@ begin
signed(RegBusA) + 1;
process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, I_MULU, T_Res,
ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Wait_n, LDHLSP)
ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Really_Wait, LDHLSP)
begin
RegWEH <= '0';
RegWEL <= '0';
@@ -1034,7 +1040,7 @@ begin
RegWEL <= '1';
end if;
if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
if IncDec_16(2) = '1' and ((TState = 2 and Really_Wait = '0' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
case IncDec_16(1 downto 0) is
when "00" | "01" | "10" =>
RegWEH <= '1';
@@ -1047,7 +1053,7 @@ begin
TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux)));
process (Save_Mux, RegBusB, RegBusA_r, ID16, I_MULU, MULU_Prod32, MULU_tmp, T_Res,
ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Wait_n, LDHLSP, TmpAddr2, WZ)
ExchangeDH, ExchangeWH, IncDec_16, MCycle, TState, Really_Wait, LDHLSP, TmpAddr2, WZ)
begin
RegDIH <= Save_Mux;
RegDIL <= Save_Mux;
@@ -1204,6 +1210,8 @@ begin
IntCycle_n <= not IntCycle;
IntE <= IntE_FF1;
IORQ <= IORQ_i;
NoRead <= NoRead_i;
Write <= Write_i;
Stop <= I_DJNZ;
-------------------------------------------------------------------------
--
@@ -1275,7 +1283,7 @@ begin
if BusReq_s = '1' and BusAck = '1' then
else
BusAck <= '0';
if TState = 2 and Wait_n = '0' then
if TState = 2 and Really_Wait = '1' then
elsif T_Res = '1' then
if Halt = '1' and ( not(Mode = 3 and INT_n = '0' and IntE_FF1 = '0')) then -- halt bug when Mode = 3 , INT_n = '0' and IME=0
Halt_FF <= '1';

View File

@@ -291,7 +291,7 @@ begin
if TState = "001" then
IORQ_int <= not IntCycle_n;
end if;
if TState = "010" then
if TState = "010" and Wait_s = '1' then
IORQ_int <= '0';
end if;
end if;

View File

@@ -52,6 +52,8 @@
--
-- v2.3: Output last used Address during non-bus MCycle seems more correct.
--
-- v2.4: Use the fixed WAIT_n in T80.vhd
--
library IEEE;
use IEEE.std_logic_1164.all;
@@ -103,6 +105,7 @@ architecture rtl of T80pa is
signal TState : std_logic_vector(2 downto 0);
signal CEN_pol : std_logic;
signal CEN : std_logic;
signal Wait_s : std_logic;
begin
CEN <= CEN_p and not CEN_pol;
@@ -121,7 +124,7 @@ begin
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => '1',
WAIT_n => Wait_s,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
@@ -154,25 +157,24 @@ begin
CEN_pol <= '0';
elsif CEN_p = '1' and CEN_pol = '0' then
CEN_pol <= '1';
if MCycle = "001" then
if TState = "010" then
IORQ_n <= '1';
MREQ_n <= '1';
RD_n <= '1';
end if;
else
if TState = "001" and IORQ = '1' then
WR_n <= not Write;
RD_n <= Write;
IORQ_n <= '0';
if WAIT_s = '1' or TState /= "010" then
if MCycle = "001" then
if TState = "010" then
IORQ_n <= '1';
MREQ_n <= '1';
RD_n <= '1';
end if;
else
if TState = "001" and IORQ = '1' then
WR_n <= not Write;
RD_n <= Write;
IORQ_n <= '0';
end if;
end if;
end if;
elsif CEN_n = '1' and CEN_pol = '1' then
if TState = "010" then
CEN_pol <= not WAIT_n;
else
CEN_pol <= '0';
end if;
Wait_s <= Wait_n;
CEN_pol <= '0';
if TState = "011" and BUSAK = '1' then
DI_Reg <= DI;
end if;

File diff suppressed because it is too large Load Diff

View File

@@ -185,9 +185,8 @@ end
wire [10:0] osd_hcnt = h_cnt - h_osd_start;
wire [10:0] osd_vcnt = v_cnt - v_osd_start;
wire [10:0] osd_hcnt_next = osd_hcnt + 2'd1; // one pixel offset for osd pixel
wire [10:0] osd_hcnt_next2 = osd_hcnt + 2'd2; // two pixel offset for osd byte address register
reg osd_de;
wire [10:0] osd_hcnt_next = osd_hcnt + 2'd1; // one pixel offset for osd byte address register
reg osd_de;
reg [10:0] osd_buffer_addr;
wire [7:0] osd_byte = osd_buffer[osd_buffer_addr];
@@ -195,16 +194,16 @@ reg osd_pixel;
always @(posedge clk_sys) begin
if(ce_pix) begin
osd_buffer_addr <= rotate[0] ? {rotate[1] ? osd_hcnt_next2[7:5] : ~osd_hcnt_next2[7:5],
osd_buffer_addr <= rotate[0] ? {rotate[1] ? osd_hcnt_next[7:5] : ~osd_hcnt_next[7:5],
rotate[1] ? (doublescan ? ~osd_vcnt[7:0] : ~{osd_vcnt[6:0], 1'b0}) :
(doublescan ? osd_vcnt[7:0] : {osd_vcnt[6:0], 1'b0})} :
{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt_next2[7:0]};
{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt_next[7:0]};
osd_pixel <= rotate[0] ? osd_byte[rotate[1] ? osd_hcnt_next[4:2] : ~osd_hcnt_next[4:2]] :
osd_pixel <= rotate[0] ? osd_byte[rotate[1] ? osd_hcnt[4:2] : ~osd_hcnt[4:2]] :
osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]];
osd_de <= osd_enable &&
(HSync != hs_pol) && ((h_cnt + 1'd1) >= h_osd_start) && ((h_cnt + 1'd1) < h_osd_end) &&
(HSync != hs_pol) && (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) &&
(VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end);
end
end