From 41dc423146e474468dcd243cfd3a022b0fd3d7d8 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Thu, 16 Dec 2021 20:21:23 +0100 Subject: [PATCH 1/7] Xevious: fix cocktail mode --- .../Xevious_MiST/rtl/xevious.vhd | 55 ++++++++++++------- .../Xevious_MiST/rtl/xevious_mist.sv | 6 ++ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious.vhd b/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious.vhd index 151f97f6..0fd37f64 100644 --- a/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious.vhd +++ b/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious.vhd @@ -36,7 +36,7 @@ --------------------------------------------------------------------------------- -- Features : -- TV 15KHz mode only (atm) --- Cocktail mode : todo +-- Cocktail mode : done -- -- Sound ok, Ship explode ok with true mb88 processor @@ -178,6 +178,12 @@ port( right : in std_logic; fire : in std_logic; bomb : in std_logic; + up2 : in std_logic; + down2 : in std_logic; + left2 : in std_logic; + right2 : in std_logic; + fire2 : in std_logic; + bomb2 : in std_logic; dl_addr : in std_logic_vector(16 downto 0); dl_wr : in std_logic; @@ -194,6 +200,9 @@ architecture struct of xevious is signal slot : std_logic_vector(2 downto 0) := (others => '0'); signal hcnt : std_logic_vector(8 downto 0); signal vcnt : std_logic_vector(8 downto 0); + signal hflip : std_logic_vector(8 downto 0); + signal vflip : std_logic_vector(8 downto 0); + signal bg_mask : std_logic_vector(8 downto 0); signal vblank : std_logic; signal ena_vidgen : std_logic; signal ena_snd_machine : std_logic; @@ -443,7 +452,7 @@ clock_18n <= not clock_18; reset_n <= not reset; dip_switch_a <= dipa; -- | cabinet(1) | lives(2)| bonus life(3) | coinage A(2) | -dip_switch_b <= dipb(7 downto 5) & not bomb & dipb(3 downto 1) & not bomb; -- |freeze(1)| difficulty(2)| input B(1) | coinage B (2) | Flags bonus life (1) | input A (1) | +dip_switch_b <= dipb(7 downto 5) & not bomb2 & dipb(3 downto 1) & not bomb; -- |freeze(1)| difficulty(2)| input B(1) | coinage B (2) | Flags bonus life (1) | input A (1) | dip_switch_do <= dip_switch_a(to_integer(unsigned(ram_bus_addr(3 downto 0)))) & dip_switch_b(to_integer(unsigned(ram_bus_addr(3 downto 0)))); @@ -542,6 +551,10 @@ begin end if; end process; +hflip <= hcnt when flip_h = '0' else 544 - hcnt; +vflip <= vcnt when flip_h = '0' else not vcnt; +bg_mask <= "000000000" when flip_h = '1' else "000000111"; + --- SPRITES MACHINE --- ----------------------- -- Sprite machine makes use of two video memory lines. Read and write process are toggled every other line. @@ -758,15 +771,16 @@ end process; -- for horizontal offset only 6 msb (8-3) are used to get synchronized with 8 pixels addressing process. -- for background the 3 lsb (2-0) will be use to control a shift register to finish horizontal scrolling. -- even in original there is no provision to finish horizontal scrolling for foreground. -bg_scan_h <= hcnt + (bg_offset_hs(8 downto 3) & "000"); -bg_scan_v <= vcnt + bg_offset_vs; +bg_scan_h <= hflip + 264 + (bg_offset_hs(8 downto 3) & "000") when flip_h = '1' else hflip + (bg_offset_hs(8 downto 3) & "000"); +bg_scan_v <= vflip - bg_offset_vs when flip_h = '1' else vflip + bg_offset_vs; bg_scan_addr <= bg_scan_v(7 downto 3) & bg_scan_h(8 downto 3); fg_offset_hs <= fg_offset_h + ('1'&X"77"); --sw(8 downto 0);--('1'&X"77"); -- dbg fg_offset_vs <= fg_offset_v + ('0'&X"00"); --sw(17 downto 9);--('0'&X"00"); -- dbg -fg_scan_h <= hcnt + (fg_offset_hs(8 downto 3) & "000"); -fg_scan_v <= vcnt + fg_offset_vs; +fg_scan_h <= hflip - (fg_offset_hs(8 downto 3) & "000") - 32 when flip_h = '1' else hflip + (fg_offset_hs(8 downto 3) & "000"); +fg_scan_v <= vflip - fg_offset_vs + 4 when flip_h = '1' else vcnt + fg_offset_vs; + fg_scan_addr <= fg_scan_v(7 downto 3) & fg_scan_h(8 downto 3); process (clock_18, slot24) @@ -816,19 +830,19 @@ end process; -- set bg graphics rom address (external) from bg tile code, vertical bg line with respect to vertical flip -- rom data will be latch within bg/fg machine for slot24 = "01011" and slot24 = "10001" with bg_attr_p(7) select -bg_grphx_addr <= bg_attr_p(0) & bg_code_p & bg_scan_v(2 downto 0) when '0', - bg_attr_p(0) & bg_code_p & not bg_scan_v(2 downto 0) when others; +bg_grphx_addr <= bg_attr_p(0) & bg_code_p & bg_scan_v(2 downto 0) when '0', + bg_attr_p(0) & bg_code_p & not bg_scan_v(2 downto 0) when others; -- set fg graphics rom address (external) from fg tile code, vertical fg line with respect to vertical flip -- (flip H is used to access rom horizontal flipped character) -- rom data will be latch within bg/fg machine for slot24 = "00101" with fg_attr_p(7) select -fg_grphx_addr <= flip_h & fg_code_p & fg_scan_v(2 downto 0) when '0', - flip_h & fg_code_p & not fg_scan_v(2 downto 0) when others; +fg_grphx_addr <= flip_h & fg_code_p & fg_scan_v(2 downto 0) when '0', + flip_h & fg_code_p & not fg_scan_v(2 downto 0) when others; -- serialize bg graphics (2 bits / pixel) -bg_bits <= bg_grphx_0(to_integer(unsigned(hcnt(2 downto 0) xor "111"))) & - bg_grphx_1(to_integer(unsigned(hcnt(2 downto 0) xor "111" ))) ; +bg_bits <= bg_grphx_0(to_integer(unsigned(hcnt(2 downto 0) xor not(flip_h & flip_h & flip_h)))) & + bg_grphx_1(to_integer(unsigned(hcnt(2 downto 0) xor not(flip_h & flip_h & flip_h)))); -- serialize fg graphics (1 bit / pixel) fg_bit <= fg_grphx(to_integer(unsigned(hcnt(2 downto 0) xor "111"))); @@ -848,13 +862,12 @@ begin bg_color_delay_5 <= bg_color_delay_5(6 downto 0) & bg_palette_msb_do(1); -- select delay line output to finish bg horizontal scrolling with respect to 3 lsb bits - bg_color(0) <= bg_color_delay_0(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - bg_color(1) <= bg_color_delay_1(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - bg_color(2) <= bg_color_delay_2(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - bg_color(3) <= bg_color_delay_3(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - bg_color(4) <= bg_color_delay_4(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - bg_color(5) <= bg_color_delay_5(to_integer(unsigned(not bg_offset_hs(2 downto 0)))); - + bg_color(0) <= bg_color_delay_0(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); + bg_color(1) <= bg_color_delay_1(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); + bg_color(2) <= bg_color_delay_2(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); + bg_color(3) <= bg_color_delay_3(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); + bg_color(4) <= bg_color_delay_4(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); + bg_color(5) <= bg_color_delay_5(to_integer(unsigned(bg_mask xor bg_offset_hs(2 downto 0)))); -- set fg color or transparent color with respect to fg serialized graphic bit if fg_bit = '1' then fg_color <= "0"&fg_attr(1 downto 0) & fg_attr(5 downto 2); @@ -1298,8 +1311,8 @@ port map( ena => cs5Xxx_ena, r0_port_in => not left¬ down¬ right¬ up, -- pin 22,23,24,25 - r1_port_in => x"F", -- pin 26,27,28,29 - r2_port_in => not start2¬ start1&'1'¬ fire, -- pin 30,31,32,33 + r1_port_in => not left2¬ down2¬ right2¬ up2, -- pin 26,27,28,29 + r2_port_in => not start2¬ start1¬ fire2¬ fire, -- pin 30,31,32,33 r3_port_in => not b_test&"11"¬ coin, -- pin 34,35,36,37 r0_port_out => open, r1_port_out => open, diff --git a/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious_mist.sv b/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious_mist.sv index 593b9cb7..00b0f0a0 100644 --- a/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious_mist.sv +++ b/Arcade_MiST/Galaga Hardware/Xevious_MiST/rtl/xevious_mist.sv @@ -246,6 +246,12 @@ xevious xevious( .down(m_down), .fire(m_fireA), .bomb(m_fireB), + .left2(m_left2), + .right2(m_right2), + .up2(m_up2), + .down2(m_down2), + .fire2(m_fire2A), + .bomb2(m_fire2B), .start2(m_two_players), .b_test(), .b_svce(), From 235fdb6cb2ad05e5a40f53b287f1c1aeb917f9a9 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Wed, 29 Dec 2021 20:34:50 +0100 Subject: [PATCH 2/7] Arkanoid --- Arcade_MiST/Taito Arkanoid/Arkanoid.qpf | 31 + Arcade_MiST/Taito Arkanoid/Arkanoid.qsf | 251 ++++++ Arcade_MiST/Taito Arkanoid/Arkanoid.sdc | 135 +++ Arcade_MiST/Taito Arkanoid/README.txt | 12 + .../Taito Arkanoid/meta/Arkanoid (JP).mra | 81 ++ .../Taito Arkanoid/meta/Arkanoid (US).mra | 83 ++ .../Arkanoid (Unl. Lives, slower) [hb].mra | 87 ++ .../meta/Arkanoid (Unl. lives) [hb].mra | 82 ++ .../Taito Arkanoid/meta/Arkanoid (W).mra | 81 ++ Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv | 770 ++++++++++++++++++ .../Taito Arkanoid/rtl/Arkanoid_MiST.sv | 353 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v | 60 ++ .../Taito Arkanoid/rtl/audio_iir_filter.v | 173 ++++ Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl | 35 + Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd | 136 ++++ Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v | 62 ++ .../Taito Arkanoid/rtl/jtframe_frac_cen.v | 58 ++ Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv | 124 +++ Arcade_MiST/Taito Arkanoid/rtl/pll.qip | 4 + Arcade_MiST/Taito Arkanoid/rtl/pll.v | 348 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv | 261 ++++++ Arcade_MiST/Taito Arkanoid/rtl/sdram.sv | 350 ++++++++ Arcade_MiST/Taito Arkanoid/rtl/spram.vhd | 46 ++ 23 files changed, 3623 insertions(+) create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.qpf create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.qsf create mode 100644 Arcade_MiST/Taito Arkanoid/Arkanoid.sdc create mode 100644 Arcade_MiST/Taito Arkanoid/README.txt create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra create mode 100644 Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/pll.qip create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/pll.v create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/sdram.sv create mode 100644 Arcade_MiST/Taito Arkanoid/rtl/spram.vhd diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf b/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf new file mode 100644 index 00000000..aa7b8519 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "14:21:03 December 29, 2021" + +# Revisions + +PROJECT_REVISION = "Arkanoid" + diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf b/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf new file mode 100644 index 00000000..3022ea8f --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.qsf @@ -0,0 +1,251 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Arkanoid_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" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY Arkanoid_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/spin.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(Arkanoid_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Arkanoid_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON + +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Arkanoid_MiST.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Arkanoid.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/mb112s146.sv +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name VERILOG_FILE rtl/build_id.v +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name VERILOG_FILE rtl/arkanoid_lpf.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/pll.v +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip +set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/vol_table_array.vhd +set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/YM2149.vhd +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp +set_global_assignment -name SIGNALTAP_FILE output_files/gfx.stp +set_global_assignment -name SIGNALTAP_FILE output_files/spin.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc b/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc new file mode 100644 index 00000000..59bf935d --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/Arkanoid.sdc @@ -0,0 +1,135 @@ +## 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 sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set aud_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $aud_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Taito Arkanoid/README.txt b/Arcade_MiST/Taito Arkanoid/README.txt new file mode 100644 index 00000000..8316ec8f --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/README.txt @@ -0,0 +1,12 @@ +A MiST port of Arkanoid (https://github.com/MiSTer-devel/Arcade-Arkanoid_MISTer) + +An FPGA implementation of Arkanoid by Ace, ElectronAsh, Enforcer, Sorgelig, Kitrinx and JimmyStones + +Controls: keyboard, joystick, mouse + +Usage: +- Create .ROM and ARC files from MAME ROM zip files using the mra utility and the meta/mra files. +- Example: mra -A -z /path/to/mame/roms Arkanoid.mra +- Copy the resulting ROM and ARC files to the root of the SD Card, next to the Arkanoid.rbf. + +- MRA utilty: https://github.com/sebdel/mra-tools-c diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra new file mode 100644 index 00000000..004fbf12 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (JP).mra @@ -0,0 +1,81 @@ + + Arkanoid (JP) + Japan + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoidj + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra new file mode 100644 index 00000000..342cafdb --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (US).mra @@ -0,0 +1,83 @@ + + Arkanoid (US, older) + US + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoiduo + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 1 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra new file mode 100644 index 00000000..f1c4d63a --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. Lives, slower) [hb].mra @@ -0,0 +1,87 @@ + + Arkanoid (Homebrew, Unlimited Lives, Slower) + + yes + no + Unl. Lives, slower + + + + 1986 + Taito + Ball and Paddle + + arkanhb1 + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + 00 + FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF + + + 05 + 00 00 00 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra new file mode 100644 index 00000000..230c7f61 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (Unl. lives) [hb].mra @@ -0,0 +1,82 @@ + + Arkanoid (Homebrew, Unlimited Lives) + + yes + no + Unl. lives + + + + 1986 + Taito + Ball and Paddle + + arkanhb2 + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 0 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 92 + 00 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra new file mode 100644 index 00000000..feedfc8a --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/meta/Arkanoid (W).mra @@ -0,0 +1,81 @@ + + Arkanoid + World + no + no + + + + + 1986 + Taito + Ball and Paddle + + arkanoid + arkanoid + 0220 + arkanoid + + + 15kHz + vertical (cw) + yes + + 2 (alternating) + + spinner + 1 + + + + + + + + + + + + + + + + + + + + + + + 49 + 49 + 49 + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 + 00 00 00 00 00 + + 4E 4F 54 49 43 45 BE 54 + 49 + 15 + EB + AF + ED + 33 + + + + + 00 80 00 00 00 FF 00 02 00 02 00 01 00 FF 02 00 + 00 00 EF 79 00 23 00 52 + 00 00 C4 DF 00 03 00 00 + + + + + + + 20210430005030 + diff --git a/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv new file mode 100644 index 00000000..5379e867 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid.sv @@ -0,0 +1,770 @@ +//============================================================================ +// +// Arkanoid top-level module +// Copyright (C) 2018, 2020 Ace, Enforcer, Ash Evans (aka ElectronAsh/OzOnE) +// and Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Module declaration, I/O ports +module Arkanoid +( + input reset, + input clk_48m, + input [1:0] spinner, //1 = left, 0 = right + input coin1, coin2, + input btn_shot, btn_service, tilt, + input btn_1p_start, btn_2p_start, + + input [7:0] dip_sw, + + input ym2149_clk_div, + input vol_boost, + + //This input serves to select different methods of acheiving 3MHz for the YM2149 depending on whether Arkanoid runs with + //original or overclocked timings to normalize sync frequencies + input overclock, + + output signed [15:0] sound, + + //Screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] h_center, + input [2:0] v_center, + + output video_hsync, video_vsync, + output video_csync, + output video_vblank, video_hblank, + output [3:0] video_r, video_g, video_b, + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, + + input [15:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write, + + output [15:0] cpu_rom_addr, + input [7:0] cpu_rom_do, + + output [14:0] gfx_rom_addr, + input [31:0] gfx_rom_do +); + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i; +wire cp1_cs_i, cp2_cs_i, cp3_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .cp1_cs(cp1_cs_i), + .cp2_cs(cp2_cs_i), + .cp3_cs(cp3_cs_i) +); + +//-------------------------------------------------- MiSTer hiscore load/save --------------------------------------------------// + +// Setup multipex between CPU Work RAM and Video RAM for hiscore data +wire [7:0] hs_data_out_wram /* synthesis keep */; +wire [7:0] hs_data_out_vram_h /* synthesis keep */; +wire [7:0] hs_data_out_vram_l /* synthesis keep */; +wire hs_cs_wram /* synthesis keep */; +wire hs_cs_vram_h /* synthesis keep */; +wire hs_cs_vram_l /* synthesis keep */; +assign hs_cs_wram = hs_address[15:12] == 4'b1100; +assign hs_cs_vram_l = hs_address[15:12] == 4'b1110 && !hs_address[0]; +assign hs_cs_vram_h = hs_address[15:12] == 4'b1110 && hs_address[0]; +assign hs_data_out = hs_cs_wram ? hs_data_out_wram : hs_cs_vram_l ? hs_data_out_vram_l : hs_data_out_vram_h; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6MHz and 3MHz clock enables +//Also generate an extra clock enable for DC offset removal in the sound section +reg [8:0] div = 9'd0; +always_ff @(posedge clk_48m) begin + div <= div + 9'd1; +end +wire cen_6m = !div[2:0]; +wire n_cen_6m = div[2:0] == 3'b100; +wire n_cen_3m = div[3:0] == 4'b1000; +wire dcrm_cen = !div; + +//Generate 3MHz clock enable for YM2149 to maintain consistent sound pitch when overclocked to normalize video timings +//(uses Jotego's fractional clock divider from JTFRAME) +wire n_cen_3m_adjust; +jtframe_frac_cen sound_cen +( + .clk(clk_48m), + .n(10'd31), + .m(10'd503), + .cenb({1'bZ, n_cen_3m_adjust}) +); + +//Edge detection for signals other than clocks used to latch data +reg old_hcnt0, old_hcnt2, old_hcnt3, old_vcnt4, old_nvblank, old_spinner_clk; +always_ff @(posedge clk_48m) begin + old_hcnt0 <= h_cnt[0]; + old_hcnt2 <= h_cnt[2]; + old_hcnt3 <= h_cnt[3]; + old_vcnt4 <= v_cnt[4]; + old_nvblank <= n_vblank; + old_spinner_clk <= spin_cnt_clk; +end + +//------------------------------------------------------------ CPUs ------------------------------------------------------------// + +wire z80_n_m1, z80_n_mreq, z80_n_iorq, z80_n_rd, z80_n_wr; +wire [15:0] z80_A; +wire [7:0] z80_Dout, z80_ram_D; +//Main CPU - Zilog Z80 (uses T80s variant of the T80 soft core) +//NMI, BUSRQ unused, pull high +T80s IC12 +( + .RESET_n(z80_n_reset), + .CLK(clk_48m), + //.CEN_p(cen_6m & ~pause), + .CEN(n_cen_6m & ~pause), + .WAIT_n(z80_n_wait), + .INT_n(z80_n_int), + .NMI_n(1), + .BUSRQ_n(1), + .MREQ_n(z80_n_mreq), + .IORQ_n(z80_n_iorq), + .RD_n(z80_n_rd), + .WR_n(z80_n_wr), + .A(z80_A), + .DI(z80_Din), + .DO(z80_Dout) +); +//Address decoding for data inputs to Z80 +wire cs_rom1 = (~z80_A[15] & ~z80_n_rd); +wire cs_rom2 = (z80_A[15:14] == 2'b10 & ~z80_n_rd); +wire cs_z80_ram = z80_A[15:12] == 4'b1100; +wire cs_ym2149 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b00); +wire cs_buttons2 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b01 & ~z80_n_rd); +wire cs_buttons1 = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b10 & ~z80_n_rd); +wire cs_spinner = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b11 & ~z80_n_rd); +wire cs_mainlatch = (~z80_n_wr & z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b01); +wire cs_vram_l = h_cnt[0] ? 1'b1 : (z80_A[15:12] == 4'b1110 & ~z80_A[0] & ~z80_n_mreq); +wire cs_vram_h = h_cnt[0] ? 1'b1 : (z80_A[15:12] == 4'b1110 & z80_A[0] & ~z80_n_mreq); +//Multiplex data inputs to Z80 +wire [7:0] z80_Din = cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + (cs_z80_ram & ~z80_n_rd) ? z80_ram_D: + (~ym2149_bdir & z80_A[0] & ym2149_bc1) ? ym2149_data: + (vram_oe & cs_vram_h & vram_rd) ? vram_D[7:0]: + (vram_oe & cs_vram_l & vram_rd) ? vram_D[15:8]: + cs_buttons2 ? buttons2: + cs_buttons1 ? buttons1: + cs_spinner ? spinner_D: + 8'hFF; + +//Game ROMs +assign cpu_rom_addr = z80_A[15] ? {1'b1, eprom2_A14, z80_A[13:0]} : {1'b0, z80_A[14:0]}; +`ifdef EXT_ROM +wire [7:0] eprom1_D = cpu_rom_do; +wire [7:0] eprom2_D = cpu_rom_do; +`else +//ROM 1/2 +wire [7:0] eprom1_D; +eprom_1 IC17 +( + .ADDR(z80_A[14:0]), + .CLK(clk_48m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +//ROM 2/2 +wire [7:0] eprom2_D; +eprom_2 IC16 +( + .ADDR({eprom2_A14, z80_A[13:0]}), + .CLK(clk_48m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +`endif + +//Z80 work RAM +dpram_dc #(.widthad_a(11)) IC15 +( + .clock_a(clk_48m), + .address_a(z80_A[10:0]), + .data_a(z80_Dout), + .q_a(z80_ram_D), + .wren_a(cs_z80_ram & ~z80_n_wr), + + .clock_b(clk_48m), + .address_b(hs_address[10:0]), + .data_b(hs_data_in), + .q_b(hs_data_out_wram), + .wren_b(hs_write & hs_cs_wram) +); + +//Watchdog - counts 128 VBlanks before triggering a reset if Arkanoid encounters a run-time issue +wire watchdog_clr = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b10 & ~z80_n_wr) | pause; +reg [7:0] watchdog_timer = 8'd0; +always_ff @(posedge clk_48m) begin + if(watchdog_clr) + watchdog_timer <= 8'd0; + else if(old_nvblank && !n_vblank) + watchdog_timer <= watchdog_timer + 8'd1; +end + +//AND the reset input to the Z80 with the watchdog output +wire z80_n_reset = reset & ~watchdog_timer[7]; + +//Generate Z80 IRQ on the rising edge of the active-low VBlank +reg z80_n_int = 1; +always_ff @(posedge clk_48m) begin + if(!z80_n_iorq) + z80_n_int <= 1; + else if(!old_nvblank && n_vblank) + z80_n_int <= 0; +end + +//Generate Z80 WAIT signal +wire wait_trigger = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b00); +reg n_wait = 1; +reg wait_clear; +always_ff @(posedge clk_48m) begin + if(wait_clear) + n_wait <= 1; + else if(cen_6m) begin + n_wait <= ~wait_trigger; + wait_clear <= ~n_wait; + end +end +wire z80_n_wait = (~(z80_A[15:12] == 4'b1110 & ~z80_n_mreq) | ~h_cnt[0]) & n_wait; + +//Main latch +reg vflip, hflip, spinner_sel, mcu_sel, prom_bank, gfxrom_bank, eprom2_bank; +always_ff @(posedge clk_48m) begin + if(!z80_n_reset) begin + mcu_sel <= 0; + prom_bank <= 0; + gfxrom_bank <= 0; + eprom2_bank <= 0; + spinner_sel <= 0; + vflip <= 0; + hflip <= 0; + end + else if(n_cen_6m && cs_mainlatch) begin + mcu_sel <= z80_Dout[7]; + prom_bank <= z80_Dout[6]; + gfxrom_bank <= z80_Dout[5]; + eprom2_bank <= z80_Dout[4]; + spinner_sel <= z80_Dout[2]; + vflip <= z80_Dout[1]; + hflip <= z80_Dout[0]; + end +end +assign gfxrom_A[14] = gfxrom_bank; +wire eprom2_A14 = eprom2_bank; + +//------------------------------------------------------------ MCUs ------------------------------------------------------------// + +//Arkanoid uses an MC68705 microcontroller at IC14 on the PCB for protection and for reading spinner inputs - this MCU is +//currently unimplemented +wire mcu_data_latch = (z80_A[15:12] == 4'b1101 & z80_A[4:3] == 2'b11 & ~z80_n_wr); + +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Reverse DIP switch order +wire [7:0] dipsw = {dip_sw[0], dip_sw[1], dip_sw[2], dip_sw[3], dip_sw[4], dip_sw[5], dip_sw[6], dip_sw[7]}; + +//Group and multiplex button inputs +wire [7:0] buttons1 = {5'b11111, btn_shot, 1'b1, btn_shot}; +wire [7:0] buttons2 = z80_A[2] ? {2'b01, coin2, coin1, tilt, btn_service, btn_2p_start, btn_1p_start} : 8'hFF; + +//Invert spinner inputs +wire [1:0] n_spinner1 = {~spinner[1], ~spinner[0]}; +wire [1:0] n_spinner2 = {~spinner[1], ~spinner[0]}; + +//Select which spinner inputs to send to the spinner input counters +wire spin_cnt_u_d = spinner_sel ? n_spinner1[1] : n_spinner2[1]; +wire spin_cnt_clk = spinner_sel ? n_spinner2[0] : n_spinner1[0]; + +//Spinner input counters +wire spin_cnt_en = (z80_A[2] | ~cs_buttons2); +reg [7:0] spin_cnt = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_spinner_clk && spin_cnt_clk) + if(spin_cnt_en) + spin_cnt <= spin_cnt_u_d ? (spin_cnt + 8'd1) : (spin_cnt - 8'd1); +end + +//Latch spinner counter values to the Z80 on the rising edge of horizontal counter bit 0 - this is normally done through the MCU, +//though bootlegs without an MCU directly latch the spinner counters to the Z80 as a workaround +reg [7:0] spinner_D = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt0 && h_cnt[0]) + spinner_D <= spin_cnt; +end + +//-------------------------------------------------------- Video timing --------------------------------------------------------// + +//Arkanoid's horizontal and vertical counters are 9 bits wide - delcare them here +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Define the range of values the vertical counter will count between based on the additional vertical center signal +//Shift the screen up by 1 line when horizontal centering shifts the screen left +wire [8:0] vcnt_start = 9'd248 - v_center; +wire [8:0] vcnt_end = 9'd511 - v_center; + +//The horizontal and vertical counters behave as follows at every rising edge of the pixel clock: +//-Start at 0, then count to 511 +//-Horizontal counter resets to 128 for a total of 384 horizontal lines +//-Vertical counter resets to 248 for a total of 264 vertical lines (adjustable with added vertical center signal) +//-Vertical counter increments when the horizontal counter equals 128 +//Model this behavior here +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + case(h_cnt) + 128: begin + h_cnt <= h_cnt + 9'd1; + case(v_cnt) + vcnt_end: v_cnt <= vcnt_start; + default: v_cnt <= v_cnt + 9'd1; + endcase + end + 511: h_cnt <= 9'd128; + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Generate h256 by latching bit 8 of the horizontal counter on the rising edge of bit 3 of that same counter +reg h256; +always_ff @(posedge clk_48m) begin + if(!old_hcnt3 && h_cnt[3]) + h256 <= h_cnt[8]; +end + +//XOR horizontal counter bits [7:3] with horizontal flip bit +wire [7:3] hcnt_x = h_cnt[7:3] ^ {5{hflip}}; + +//XOR vertical counter bits with vertical flip bit +wire [8:0] vcnt_x = v_cnt ^ {9{vflip}}; + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//Multiplex VRAM address lines based on horizontal counter bits 8 and 0 +wire [10:0] vram_A = !h_cnt[0] ? z80_A[11:1]: + h_cnt[8] ? {1'b0, vcnt_x[7:3], hcnt_x[7:3]}: + {1'b1, 5'b00000, h_cnt[6:2]}; + +//Multiplex VRAM write, output and chip enable signals based on the state of horizontal counter bit 0 +wire vram_we = n_cen_6m & (h_cnt[0] ? 1'b0 : z80_n_rd); +wire vram_oe = h_cnt[0] ? 1'b1 : ~z80_n_rd; + +//Generate active-high VRAM read enable +wire vram_rd = ~z80_n_rd & (z80_A[15:12] == 4'b1110 & ~z80_n_mreq); + +//VRAM +//Upper 8 bits +wire [15:0] vram_D; +dpram_dc #(.widthad_a(11)) IC57 +( + .clock_a(clk_48m), + .address_a(vram_A), + .data_a(z80_Dout), + .q_a(vram_D[15:8]), + .wren_a(cs_vram_l & vram_we), + + .clock_b(clk_48m), + .address_b(hs_address[11:1]), + .data_b(hs_data_in), + .q_b(hs_data_out_vram_l), + .wren_b(hs_write & hs_cs_vram_l) +); +//Lower 8 bits +dpram_dc #(.widthad_a(11)) IC58 +( + .clock_a(clk_48m), + .address_a(vram_A), + .data_a(z80_Dout), + .q_a(vram_D[7:0]), + .wren_a(cs_vram_h & vram_we), + + .clock_b(clk_48m), + .address_b(hs_address[11:1]), + .data_b(hs_data_in), + .q_b(hs_data_out_vram_h), + .wren_b(hs_write & hs_cs_vram_h) +); + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//Latch tilemap data from VRAM on the rising edge of horizontal counter bit 2 +reg [7:0] tiles_D = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt2 && h_cnt[2]) + tiles_D <= {vram_D[6], vram_D[4:3], vram_D[1], vram_D[2], vram_D[0], vram_D[7], vram_D[5]}; +end + +//Sum tilemap data with vertical counter bits [7:0] +wire [7:0] sr = {tiles_D[1], tiles_D[7], tiles_D[0], tiles_D[6:5], tiles_D[3], tiles_D[4], tiles_D[2]} + vcnt_x[7:0]; + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//Latch horizontal position and tilemap data from VRAM on the rising edge of horizontal counter bit 2 +reg [7:0] h_pos = 8'd0; +always_ff @(posedge clk_48m) begin + if(!old_hcnt2 && h_cnt[2]) + h_pos <= {vram_D[8], vram_D[15], vram_D[10], vram_D[13], vram_D[14], vram_D[12:11], vram_D[9]}; +end + +//Latch sprite data on the falling edge of horizontal counter bit 2 +reg [4:0] sprites_D = 5'd0; +always_ff @(posedge clk_48m) begin + if(old_hcnt2 && !h_cnt[2]) + sprites_D <= {vram_D[11], vram_D[14:12], vram_D[15]}; +end + +//Multiplex sprite horizontal position based on bit 8 of the horizontal counter +wire [7:0] sprite_hpos = h_cnt[8] ? {8{hflip}} : {h_pos[3], h_pos[6], h_pos[4], h_pos[2], h_pos[5], h_pos[1], h_pos[0], h_pos[7]}; + +//Generate sprite RAM addresses +wire [8:0] spriteram_A; +reg [7:0] spriteram_cnt = 8'd0; +wire spriteram_u_d = ~(hflip & h256); +wire n_spriteram_cnt_load = shift_ld | (h_cnt[8] & h256); +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + if(!n_spriteram_cnt_load) + spriteram_cnt <= {sprite_hpos[6], sprite_hpos[7], sprite_hpos[5:4], sprite_hpos[2], sprite_hpos[3], sprite_hpos[1:0]}; + else + spriteram_cnt <= spriteram_u_d ? (spriteram_cnt + 4'd1) : (spriteram_cnt - 4'd1); + end +end +assign spriteram_A[8] = ~h256 & ~(sprite_pixel1 | sprite_pixel2 | sprite_pixel3); +assign spriteram_A[7:0] = spriteram_cnt; + +//Latch sprite pixel signal on the falling edge of horizontal counter bit 2 and generate individual sprite pixel signals for each +//shifted graphics ROM data +reg n_inre; +always_ff @(posedge clk_48m) begin + if(old_hcnt0 && !h_cnt[0]) begin + if(h_cnt[8]) + n_inre <= 1; + else + n_inre <= ~(&sr[7:4]); + end +end +reg sprite_pixel; +always_ff @(posedge clk_48m) begin + if(old_hcnt2 && !h_cnt[2]) + sprite_pixel <= ~n_inre; +end +wire sprite_pixel1 = sprite_pixel & eprom3_shift; +wire sprite_pixel2 = sprite_pixel & eprom5_shift; +wire sprite_pixel3 = sprite_pixel & eprom4_shift; + +//Assign sprite RAM data input +wire [7:0] spriteram_Din = {sprites_D[0], sprites_D[3:1], sprites_D[4], sprite_pixel2, sprite_pixel3, sprite_pixel1}; + +//Sprite RAM (the original PCB uses a 2KB RAM chip with 11 address lines, but only 9 are used, limiting its capacity to 512 bytes) +wire [7:0] spriteram_Dout; +spram #(8, 9) IC51 +( + .clk(clk_48m), + .we(n_cen_6m), + .addr(spriteram_A), + .data(spriteram_Din), + .q(spriteram_Dout) +); + +//-------------------------------------------------------- Graphics ROMs -------------------------------------------------------// + +//Latch data from VRAM to be used as addresses for the graphics ROMs on the falling edge of horizontal counter bit 0 and +//multiplex based on horizontal counter bit 8 +wire [14:0] gfxrom_A; +reg [13:0] gfx_address = 14'd0; +always_ff @(posedge clk_48m) begin + if(old_hcnt0 && !h_cnt[0]) begin + if(h_cnt[8]) + gfx_address <= {vram_D[10:0], vcnt_x[2:0]}; + else + gfx_address <= {vram_D[9:0], sr[3:0]}; + end +end +assign gfxrom_A[13:0] = gfx_address; + +assign gfx_rom_addr = gfxrom_A; + +//Graphics ROMs +`ifdef EXT_ROM +wire [7:0] eprom3_D = gfx_rom_do[7:0]; +wire [7:0] eprom4_D = gfx_rom_do[15:8]; +wire [7:0] eprom5_D = gfx_rom_do[23:16]; +`else +//ROM 1/3 +wire [7:0] eprom3_D; +eprom_3 IC64 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +//ROM 2/3 +wire [7:0] eprom4_D; +eprom_4 IC63 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom4_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); + +//ROM 3/3 +wire [7:0] eprom5_D; +eprom_5 IC62 +( + .ADDR(gfxrom_A), + .CLK(clk_48m), + .DATA(eprom5_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); +`endif + +//Fujitsu MB112S146 - Custom bit shifter used by Arkanoid to left/right shift graphics data from the graphics ROMs +//Instantiate two instances of this chip to shift graphics data from the 3 graphics ROMs +wire shift_ld = ~(&h_cnt[2:0]); +wire flip_sel = hflip & h256; +wire eprom5_shift; +mb112s146 IC77 +( + .clk(clk_48m), + .cen(n_cen_6m), + .n_clr(1), + .shift_ld(shift_ld), + .sel(flip_sel), + .s_in(2'b00), + .d2_in(8'h00), //This shift register is unused, pull inputs low + .d1_in(eprom5_D), + .shift_out({1'bZ, eprom5_shift}) //Shift register 1 unused +); +wire eprom3_shift, eprom4_shift; +mb112s146 IC78 +( + .clk(clk_48m), + .cen(n_cen_6m), + .n_clr(1), + .shift_ld(shift_ld), + .sel(flip_sel), + .s_in(2'b00), + .d2_in(eprom3_D), + .d1_in(eprom4_D), + .shift_out({eprom3_shift, eprom4_shift}) +); + +//Latch tilemap and sprite data for color PROMs +reg [7:0] tiles = 8'd0; +reg [7:0] sprites = 8'd0; +always_ff @(posedge clk_48m) begin + if(n_cen_6m) begin + tiles <= {eprom3_shift, eprom5_shift, sprites_D[4], eprom4_shift, sprites_D[2], sprites_D[0], sprites_D[3], sprites_D[1]}; + sprites <= {spriteram_Dout[3], spriteram_Dout[0], spriteram_Dout[1], spriteram_Dout[6], spriteram_Dout[2], spriteram_Dout[5:4], spriteram_Dout[7]}; + end +end + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Generate BDIR and BCI inputs for YM2149 +wire ym2149_bdir = (~z80_n_wr & cs_ym2149); +wire ym2149_bc1 = (~z80_n_rd & cs_ym2149); + +//Select whether to use a fractional or integer clock divider for the YM2149 to maintain consistent sound pitch at both original +//and overclocked timings +wire cen_sound = overclock ? n_cen_3m_adjust : n_cen_3m; + +//Sound chip - Yamaha YM2149 (implementation by MikeJ) +//Implements volume table to simulate mixing of the three analog outputs directly at the chip as per the original Arkanoid PCB +wire [7:0] ym2149_data; +ym2149 #(.MIXER_VOLTABLE(1'b1)) IC2 +( + .I_DA(z80_Dout), + .O_DA(ym2149_data), + .I_A9_L(0), + .I_A8(1), + .I_BDIR(ym2149_bdir), + .I_BC2(z80_A[0]), + .I_BC1(ym2149_bc1), + .I_SEL_L(ym2149_clk_div), + .O_AUDIO_L(sound_raw), + .I_IOB(dipsw), + .ENA(cen_sound), + .RESET_L(z80_n_reset), + .CLK(clk_48m) +); + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Multiplex tilemaps and sprites to color PROM addresses +wire prom_A_sel = ~(sprites[6] | sprites[5] | sprites[3]); +reg [7:0] prom_A = 8'd0; +always_ff @(posedge clk_48m) begin + if(cen_6m) begin + if(prom_A_sel) + prom_A <= {tiles[2], tiles[1], tiles[3], tiles[0], tiles[5], tiles[6], tiles[4], tiles[7]}; + else + prom_A <= {sprites[0], sprites[4], sprites[2], sprites[1], sprites[7], sprites[3], sprites[5], sprites[6]}; + end +end + +//Arkanoid generates its final video output by latching data from 3 LUT PROMs, one per color, for 12-bit RGB with 4 bits per color +//Red color PROM +wire [3:0] prom1_data; +color_prom_1 IC24 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom1_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp1_cs_i), + .WR(ioctl_wr) +); +//Green color PROM +wire [3:0] prom2_data; +color_prom_2 IC23 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom2_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp2_cs_i), + .WR(ioctl_wr) +); +//Blue color PROM +wire [3:0] prom3_data; +color_prom_3 IC22 +( + .ADDR({prom_bank, prom_A}), + .CLK(clk_48m), + .DATA(prom3_data), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_48m), + .DATA_IN(ioctl_data), + .CS_DL(cp3_cs_i), + .WR(ioctl_wr) +); + +//Generate active-low VBlank (this VBlank is imperfect - use as part of the video output logic to recreate the 1-pixel upward +//vertical shift on the last 10 vertical lines on the right side of the screen) +reg n_vblank; +always_ff @(posedge clk_48m) begin + if(!old_vcnt4 && v_cnt[4]) + n_vblank <= ~(&v_cnt[7:5]); +end + +//Latch data from color PROMs for video output +reg [3:0] red, green, blue; +always_ff @(posedge clk_48m) begin + if(!n_vblank || video_hblank) begin + red <= 4'd0; + green <= 4'd0; + blue <= 4'd0; + end + else if(cen_6m) begin + red <= prom1_data; + green <= prom2_data; + blue <= prom3_data; + end +end +assign video_r = red; +assign video_g = green; +assign video_b = blue; + +//Video sync & blanking outputs (HSync and blanks active-high, VSync active-low) +assign video_hsync = h_center[3] ? (~h_cnt[8] && h_cnt[6:0] > (7'd54 - h_center[2:0]) && h_cnt[6:0] < (7'd87 - h_center[2:0])): + (~h_cnt[8] && h_cnt[6:0] > (7'd47 - h_center[2:0]) && h_cnt[6:0] < (7'd80 - h_center[2:0])); +assign video_vsync = ~(v_cnt >= vcnt_start && v_cnt <= vcnt_start + 9'd7); +assign video_csync = video_hsync ^ video_vsync; +assign video_vblank = (v_cnt < 271 || v_cnt > 495); +assign video_hblank = (h_cnt > 137 && h_cnt < 266); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Remove DC offset from audio output (uses jt49_dcrm2 from JT49 by Jotego) +wire [9:0] sound_raw; + +wire signed [15:0] sound_dcrm; +jt49_dcrm2 #(16) dcrm +( + .clk(clk_48m), + .cen(dcrm_cen), + .rst(~reset), + .din({5'd0, sound_raw}), + .dout(sound_dcrm) +); + +//Low-pass filter the audio output (cutoff frequency ~16.7KHz) +wire signed [15:0] sound_filtered; + +arkanoid_lpf lpf +( + .clk(clk_48m), + .reset(~reset), + .in(sound_dcrm), + .out(sound_filtered) +); + +//Apply gain to final audio output (mute when the game is paused) +assign sound = pause ? 16'd0 : vol_boost ? (sound_filtered <<< 16'd5) : (sound_filtered <<< 16'd4); + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv new file mode 100644 index 00000000..ec2669c7 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/Arkanoid_MiST.sv @@ -0,0 +1,353 @@ +module Arkanoid_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "Arkanoid;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire [1:0] orientation = 2'b11; +wire [7:0] dip_sw = status[15:8]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_96; +assign SDRAM_CKE = 1; +assign AUDIO_R = AUDIO_L; + +wire clock_48, clock_96, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_96), + .c1(clock_48), + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; +wire mouse_strobe; +wire [8:0] mouse_x; +wire [7:0] mouse_flags; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_48 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .mouse_strobe (mouse_strobe ), + .mouse_flags (mouse_flags ), + .mouse_x (mouse_x ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + + +wire [15:0] cpu_rom_addr; +wire [15:0] cpu_rom_do; +wire [14:0] bg_addr; +wire [31:0] bg_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_48 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 17'h10000; + +reg port1_req, port2_req; + +sdram #(96) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_96 ), + + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'hffff : {1'b0, cpu_rom_addr[15:1]} ), + .cpu1_q ( cpu_rom_do ), + .cpu2_addr ( ), + .cpu2_q ( ), + + // port2 for sprite graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( {bg_ioctl_addr[24:17], bg_ioctl_addr[14:0], bg_ioctl_addr[16]} ), // merge sprite roms to 32-bit wide words + .port2_ds ( {bg_ioctl_addr[15], ~bg_ioctl_addr[15]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .sp_addr ( ioctl_downl ? 16'hffff : bg_addr ), + .sp_q ( bg_do ) +); + +// ROM download controller +always @(posedge clock_48) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_48) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +// quadrature encoder (spinner) +reg [1:0] spinner_encoder; +reg [11:0] position = 0; +wire [11:0] position_next = position + {{4{mouse_x[8]}}, mouse_x[7:0]}; + +always @(posedge clock_48) begin + reg [15:0] spin_counter; + reg [2:0] ce_6m; + reg [11:0] div_4k; + + ce_6m <= ce_6m + 3'd1; + if(!ce_6m) begin + + div_4k <= div_4k + 1'd1; + if(div_4k == 1499) div_4k <= 0; + + if(position != 0) begin //we need to drive position to 0 still; + if(!div_4k) begin + case({position[11] , spinner_encoder}) + {1'b1, 2'b00}: spinner_encoder <= 2'b01; + {1'b1, 2'b01}: spinner_encoder <= 2'b11; + {1'b1, 2'b11}: spinner_encoder <= 2'b10; + {1'b1, 2'b10}: spinner_encoder <= 2'b00; + {1'b0, 2'b00}: spinner_encoder <= 2'b10; + {1'b0, 2'b10}: spinner_encoder <= 2'b11; + {1'b0, 2'b11}: spinner_encoder <= 2'b01; + {1'b0, 2'b01}: spinner_encoder <= 2'b00; + endcase + + if(position[11]) position <= position + 1'b1; + else position <= position - 1'b1; + end + end + + if (m_left | m_right) begin // 0.167us per cycle + // DPAD left/right + if (spin_counter == 'd48000) begin// roughly 8ms to emulate 125hz standard mouse poll rate + position <= m_right ? (m_fireB ? 12'd9 : 12'd4) : (m_fireB ? -12'd9 : -12'd4); + spin_counter <= 0; + end else begin + spin_counter <= spin_counter + 1'b1; + end + end else begin + spin_counter <= 0; + end + end + if(mouse_strobe) begin + if (position[11] != mouse_x[8] || position[11] == position_next[11]) + position <= position_next; + else + position <= {position[11], {11{~position[11]}}}; + end +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +Arkanoid Arkanoid_inst +( + .reset(~reset), //input reset + + .clk_48m(clock_48), //input clk_48m + + .spinner(spinner_encoder), //input [1:0] spinner + + .coin1(m_coin1), //input coin1 + .coin2(m_coin2), //input coin2 + + .btn_shot(~(m_fireA | |mouse_flags[1:0])), //input btn_shot + .btn_service(~service), //input btn_service + + .tilt(1), //input tilt + + .btn_1p_start(~m_one_player), //input btn_1p_start + .btn_2p_start(~m_two_players), //input btn_2p_start + + .dip_sw(~dip_sw), //input [7:0] dip_sw + + .sound(audio), //output [15:0] sound + + .h_center(), //Screen centering + .v_center(), + + .video_hsync(hs), //output video_hsync + .video_vsync(vs), //output video_vsync + .video_vblank(vblank), //output video_vblank + .video_hblank(hblank), //output video_hblank + + .video_r(r), //output [3:0] video_r + .video_g(g), //output [3:0] video_g + .video_b(b), //output [3:0] video_b + + .ym2149_clk_div(1'b1), //Easter egg - controls the YM2149 clock divider for bootlegs with overclocked AY-3-8910s (default on) + .vol_boost(1'b0), //Audio volume boost option + .overclock(1'b0), //Flag to signal that Arkanoid has been overclocked to normalize video timings in order to maintain consistent sound pitch + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(1'b0), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write(hs_write_enable), + + .cpu_rom_addr(cpu_rom_addr), + .cpu_rom_do(cpu_rom_addr[0] ? cpu_rom_do[15:8] : cpu_rom_do[7:0]), + .gfx_rom_addr(bg_addr), + .gfx_rom_do(bg_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_48 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +dac #(.C_bits(16))dac_l( + .clk_i(clock_48), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(AUDIO_L) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_48 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v b/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v new file mode 100644 index 00000000..36a867b6 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/arkanoid_lpf.v @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to low-pass filter the YM2149 on Arkanoid. + +module arkanoid_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 48MHz/256 = 187500Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.22211491, 0.22211491 + //1.0000000, -0.55577018 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd18211; + B1 = 18'd7278; + B2 = 18'd7278; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v b/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl b/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd b/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v b/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v b/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv b/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv new file mode 100644 index 00000000..5e18653d --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/mb112s146.sv @@ -0,0 +1,124 @@ +//============================================================================ +// +// SystemVerilog mplementation of the Fujitsu MB112S146 custom IC +// Contains two left/right shift registers and a multiplexer +// Copyright (C) 2019 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Chip pinout: +/* _____________ + _| |_ +shift_ld |_|1 28|_| VCC + _| |_ +latch |_|2 27|_| n_clr + _| |_ +s_in(0) |_|3 26|_| sel + _| |_ +s_in(1) |_|4 25|_| GND + _| |_ +clk |_|5 24|_| d2_in(0) + _| |_ +d1_in(0) |_|6 23|_| d2_in(1) + _| |_ +d1_in(1) |_|7 22|_| d2_in(2) + _| |_ +d1_in(2) |_|8 21|_| d2_in(3) + _| |_ +d1_in(3) |_|9 20|_| d2_in(4) + _| |_ +d1_in(4) |_|10 19|_| d2_in(5) + _| |_ +d1_in(5) |_|11 18|_| d2_in(6) + _| |_ +d1_in(6) |_|12 17|_| d2_in(7) + _| |_ +d1_in(7) |_|13 16|_| shift_out(0) + _| |_ +GND |_|14 15|_| shift_out(1) + |_____________| +*/ + +module mb112s146 +( + input clk, cen, + input n_clr, shift_ld, + input sel, + input [1:0] s_in, + input [7:0] d1_in, d2_in, + output [1:0] shift_out +); + +reg [7:0] shift_l_1, shift_l_2; +reg [7:0] shift_r_1, shift_r_2; + +always_ff @(posedge clk or negedge n_clr) begin + if(!n_clr) begin + //Reset internal registers + shift_l_1 <= 8'd0; + shift_l_2 <= 8'd0; + shift_r_1 <= 8'd0; + shift_r_2 <= 8'd0; + end + else if(cen) begin + //Left shift data 1 input + shift_l_1[0] <= (s_in[0] & shift_ld) | (~shift_ld & d1_in[0]); + shift_l_1[1] <= (shift_l_1[0] & shift_ld) | (~shift_ld & d1_in[1]); + shift_l_1[2] <= (shift_l_1[1] & shift_ld) | (~shift_ld & d1_in[2]); + shift_l_1[3] <= (shift_l_1[2] & shift_ld) | (~shift_ld & d1_in[3]); + shift_l_1[4] <= (shift_l_1[3] & shift_ld) | (~shift_ld & d1_in[4]); + shift_l_1[5] <= (shift_l_1[4] & shift_ld) | (~shift_ld & d1_in[5]); + shift_l_1[6] <= (shift_l_1[5] & shift_ld) | (~shift_ld & d1_in[6]); + shift_l_1[7] <= (shift_l_1[6] & shift_ld) | (~shift_ld & d1_in[7]); + //Left shift data 2 input + shift_l_2[0] <= (s_in[1] & shift_ld) | (~shift_ld & d2_in[0]); + shift_l_2[1] <= (shift_l_2[0] & shift_ld) | (~shift_ld & d2_in[1]); + shift_l_2[2] <= (shift_l_2[1] & shift_ld) | (~shift_ld & d2_in[2]); + shift_l_2[3] <= (shift_l_2[2] & shift_ld) | (~shift_ld & d2_in[3]); + shift_l_2[4] <= (shift_l_2[3] & shift_ld) | (~shift_ld & d2_in[4]); + shift_l_2[5] <= (shift_l_2[4] & shift_ld) | (~shift_ld & d2_in[5]); + shift_l_2[6] <= (shift_l_2[5] & shift_ld) | (~shift_ld & d2_in[6]); + shift_l_2[7] <= (shift_l_2[6] & shift_ld) | (~shift_ld & d2_in[7]); + //Right shift data 1 input + shift_r_1[0] <= (s_in[0] & shift_ld) | (~shift_ld & d1_in[7]); + shift_r_1[1] <= (shift_r_1[0] & shift_ld) | (~shift_ld & d1_in[6]); + shift_r_1[2] <= (shift_r_1[1] & shift_ld) | (~shift_ld & d1_in[5]); + shift_r_1[3] <= (shift_r_1[2] & shift_ld) | (~shift_ld & d1_in[4]); + shift_r_1[4] <= (shift_r_1[3] & shift_ld) | (~shift_ld & d1_in[3]); + shift_r_1[5] <= (shift_r_1[4] & shift_ld) | (~shift_ld & d1_in[2]); + shift_r_1[6] <= (shift_r_1[5] & shift_ld) | (~shift_ld & d1_in[1]); + shift_r_1[7] <= (shift_r_1[6] & shift_ld) | (~shift_ld & d1_in[0]); + //Right shift data 2 input + shift_r_2[0] <= (s_in[1] & shift_ld) | (~shift_ld & d2_in[7]); + shift_r_2[1] <= (shift_r_2[0] & shift_ld) | (~shift_ld & d2_in[6]); + shift_r_2[2] <= (shift_r_2[1] & shift_ld) | (~shift_ld & d2_in[5]); + shift_r_2[3] <= (shift_r_2[2] & shift_ld) | (~shift_ld & d2_in[4]); + shift_r_2[4] <= (shift_r_2[3] & shift_ld) | (~shift_ld & d2_in[3]); + shift_r_2[5] <= (shift_r_2[4] & shift_ld) | (~shift_ld & d2_in[2]); + shift_r_2[6] <= (shift_r_2[5] & shift_ld) | (~shift_ld & d2_in[1]); + shift_r_2[7] <= (shift_r_2[6] & shift_ld) | (~shift_ld & d2_in[0]); + end +end + +assign shift_out = sel ? {shift_r_2[7], shift_r_1[7]}: + {shift_l_2[7], shift_l_1[7]}; + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/pll.qip b/Arcade_MiST/Taito Arkanoid/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Taito Arkanoid/rtl/pll.v b/Arcade_MiST/Taito Arkanoid/rtl/pll.v new file mode 100644 index 00000000..18e1d7fd --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 9, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 32, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 9, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 16, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "360" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "96.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "48.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 "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "191" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "96.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "48.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "32" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "16" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv b/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv new file mode 100644 index 00000000..bb888c11 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/rom_loader.sv @@ -0,0 +1,261 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Arkanoid: +// 0x0000 - 0x7FFF = eprom_1 +// 0x8000 - 0xFFFF = eprom_2 +// 0x10000 - 0x17FFF = eprom_3 +// 0x18000 - 0x1FFFF = eprom_4 +// 0x20000 - 0x27FFF = eprom_5 +// 0x28000 - 0x281FF = color_prom_1 +// 0x28200 - 0x283FF = color_prom_2 +// 0x28400 - 0x285FF = color_prom_3 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, cp1_cs, cp2_cs, cp3_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, cp1_cs, cp2_cs, cp3_cs} = 0; + if(ioctl_addr < 'h8000) + ep1_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h10000) + ep2_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h18000) + ep3_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h20000) + ep4_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28000) + ep5_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28200) + cp1_cs = 1; // 0x200 9 + else if(ioctl_addr < 'h28400) + cp2_cs = 1; // 0x200 9 + else + cp3_cs = 1; // 0x200 9 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_4 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_5 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module color_prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_1 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_2 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [8:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(9)) cprom_3 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[8:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv b/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv new file mode 100644 index 00000000..9f5bc668 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/sdram.sv @@ -0,0 +1,350 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [16:1] cpu1_addr, + output reg [15:0] cpu1_q, + input [16:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [31:0] port2_q, + + input [16:2] sp_addr, + output reg [31:0] sp_q +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b001; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 - data0 read burst terminated + 1 ras0 + 2 data1 returned + 3 CAS0 data1 returned + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_DS1b = 3'd0; +localparam STATE_READ1b = 3'd4; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [16:1] addr_last[2]; +reg [16:2] addr_last2[2]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CPU2 = 2'd2; +localparam PORT_SP = 2'd1; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 8'd0, cpu1_addr }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 8'd0, cpu2_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (sp_addr != addr_last2[PORT_SP]) begin + next_port[1] = PORT_SP; + addr_latch_next[1] = { 1'b1, 7'd0, sp_addr, 1'b0 }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][16:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][16:2]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: port2_q[15:0] <= sd_din; + PORT_SP : sp_q[15:0] <= sd_din; + default: ; + endcase; + end + + if(t == STATE_DS1b && oe_latch[1]) { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + + if(t == STATE_READ1b && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q[31:16] <= sd_din; port2_ack <= port2_req; end + PORT_SP : begin sp_q[31:16] <= sd_din; end + default: ; + endcase; + end + end +end + +endmodule diff --git a/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd b/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Taito Arkanoid/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl; From e64964ce9f021e2b17d93dae8cfef663e138522d Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Thu, 30 Dec 2021 03:04:03 +0100 Subject: [PATCH 3/7] Konami Iron Horse --- Arcade_MiST/Konami Iron Horse/IronHors.qpf | 31 + Arcade_MiST/Konami Iron Horse/IronHors.qsf | 257 +++++ Arcade_MiST/Konami Iron Horse/IronHors.sdc | 134 +++ Arcade_MiST/Konami Iron Horse/README.md | 11 + .../meta/Iron Horse (Ver. K).mra | 84 ++ .../Konami Iron Horse/rtl/IronHorse.sv | 627 +++++++++++ .../Konami Iron Horse/rtl/IronHorse_MiST.sv | 323 ++++++ .../Konami Iron Horse/rtl/audio_iir_filter.v | 173 +++ .../Konami Iron Horse/rtl/build_id.tcl | 35 + .../Konami Iron Horse/rtl/dpram_dc.vhd | 136 +++ .../Konami Iron Horse/rtl/ironhorse_fm_lpf.sv | 60 ++ .../rtl/ironhorse_ssg_lpf.sv | 61 ++ .../Konami Iron Horse/rtl/jt49_dcrm2.v | 62 ++ .../Konami Iron Horse/rtl/jtframe_frac_cen.v | 58 + Arcade_MiST/Konami Iron Horse/rtl/k005885.sv | 992 ++++++++++++++++++ Arcade_MiST/Konami Iron Horse/rtl/pll.qip | 4 + Arcade_MiST/Konami Iron Horse/rtl/pll.v | 348 ++++++ .../Konami Iron Horse/rtl/rom_loader.sv | 366 +++++++ Arcade_MiST/Konami Iron Horse/rtl/sdram.sv | 363 +++++++ Arcade_MiST/Konami Iron Horse/rtl/spram.vhd | 46 + common/CPU/MC6809/mc6809is.v | 10 +- common/Sound/JT12/LICENSE | 674 ++++++++++++ common/Sound/JT12/README.md | 43 + common/Sound/JT12/hdl/adpcm/gen_lingain.py | 14 + common/Sound/JT12/hdl/adpcm/jt10_adpcm.v | 132 +++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v | 90 ++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v | 181 ++++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v | 134 +++ .../Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v | 54 + common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v | 62 ++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v | 335 ++++++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v | 124 +++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v | 130 +++ common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v | 176 ++++ common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v | 142 +++ common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v | 112 ++ common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v | 108 ++ .../Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v | 39 + .../JT12/hdl/adpcm/jt10_adpcmb_interpol.v | 96 ++ common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v | 59 ++ common/Sound/JT12/hdl/alt/eg_cnt.v | 84 ++ common/Sound/JT12/hdl/alt/eg_comb.v | 184 ++++ common/Sound/JT12/hdl/alt/eg_mux.v | 79 ++ common/Sound/JT12/hdl/alt/eg_step.v | 46 + common/Sound/JT12/hdl/alt/eg_step_ram.v | 45 + common/Sound/JT12/hdl/dac/jt12_dac.v | 56 + common/Sound/JT12/hdl/dac/jt12_dac2.v | 63 ++ common/Sound/JT12/hdl/deprecated/jt12_amp.v | 172 +++ common/Sound/JT12/hdl/deprecated/jt12_mod24.v | 14 + common/Sound/JT12/hdl/deprecated/jt12_mod6.v | 52 + common/Sound/JT12/hdl/deprecated/jt12_opram.v | 45 + common/Sound/JT12/hdl/jt03.qip | 35 + common/Sound/JT12/hdl/jt03.v | 97 ++ common/Sound/JT12/hdl/jt03_acc.v | 73 ++ common/Sound/JT12/hdl/jt03_fm.qip | 33 + common/Sound/JT12/hdl/jt10.qip | 63 ++ common/Sound/JT12/hdl/jt10.v | 97 ++ common/Sound/JT12/hdl/jt10_acc.v | 173 +++ common/Sound/JT12/hdl/jt12.qip | 42 + common/Sound/JT12/hdl/jt12.v | 80 ++ common/Sound/JT12/hdl/jt12.vhd | 44 + common/Sound/JT12/hdl/jt12_acc.v | 107 ++ common/Sound/JT12/hdl/jt12_csr.v | 82 ++ common/Sound/JT12/hdl/jt12_div.v | 141 +++ common/Sound/JT12/hdl/jt12_dout.v | 47 + common/Sound/JT12/hdl/jt12_eg.v | 203 ++++ common/Sound/JT12/hdl/jt12_eg_cnt.v | 50 + common/Sound/JT12/hdl/jt12_eg_comb.v | 139 +++ common/Sound/JT12/hdl/jt12_eg_ctrl.v | 122 +++ common/Sound/JT12/hdl/jt12_eg_final.v | 57 + common/Sound/JT12/hdl/jt12_eg_pure.v | 81 ++ common/Sound/JT12/hdl/jt12_eg_step.v | 111 ++ common/Sound/JT12/hdl/jt12_exprom.v | 302 ++++++ common/Sound/JT12/hdl/jt12_kon.v | 151 +++ common/Sound/JT12/hdl/jt12_lfo.v | 103 ++ common/Sound/JT12/hdl/jt12_logsin.v | 298 ++++++ common/Sound/JT12/hdl/jt12_mmr.v | 511 +++++++++ common/Sound/JT12/hdl/jt12_mmr_sim.vh | 854 +++++++++++++++ common/Sound/JT12/hdl/jt12_mod.v | 153 +++ common/Sound/JT12/hdl/jt12_op.v | 332 ++++++ common/Sound/JT12/hdl/jt12_pcm.v | 109 ++ common/Sound/JT12/hdl/jt12_pcm_interpol.v | 109 ++ common/Sound/JT12/hdl/jt12_pg.v | 114 ++ common/Sound/JT12/hdl/jt12_pg_comb.v | 90 ++ common/Sound/JT12/hdl/jt12_pg_dt.v | 82 ++ common/Sound/JT12/hdl/jt12_pg_inc.v | 50 + common/Sound/JT12/hdl/jt12_pg_sum.v | 49 + common/Sound/JT12/hdl/jt12_pm.v | 186 ++++ common/Sound/JT12/hdl/jt12_reg.v | 372 +++++++ common/Sound/JT12/hdl/jt12_rst.v | 38 + common/Sound/JT12/hdl/jt12_sh.v | 44 + common/Sound/JT12/hdl/jt12_sh24.v | 81 ++ common/Sound/JT12/hdl/jt12_sh_rst.v | 56 + common/Sound/JT12/hdl/jt12_single_acc.v | 63 ++ common/Sound/JT12/hdl/jt12_sumch.v | 47 + common/Sound/JT12/hdl/jt12_timers.v | 141 +++ common/Sound/JT12/hdl/jt12_top.v | 671 ++++++++++++ common/Sound/JT12/hdl/mixer/jt12_comb.v | 59 ++ common/Sound/JT12/hdl/mixer/jt12_decim.v | 90 ++ common/Sound/JT12/hdl/mixer/jt12_fm_uprate.v | 95 ++ common/Sound/JT12/hdl/mixer/jt12_genmix.v | 180 ++++ common/Sound/JT12/hdl/mixer/jt12_interpol.v | 92 ++ common/Sound/JT12/hdl/mixer/jt12_mixer.v | 84 ++ 103 files changed, 15207 insertions(+), 2 deletions(-) create mode 100644 Arcade_MiST/Konami Iron Horse/IronHors.qpf create mode 100644 Arcade_MiST/Konami Iron Horse/IronHors.qsf create mode 100644 Arcade_MiST/Konami Iron Horse/IronHors.sdc create mode 100644 Arcade_MiST/Konami Iron Horse/README.md create mode 100644 Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/k005885.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/pll.qip create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/pll.v create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/sdram.sv create mode 100644 Arcade_MiST/Konami Iron Horse/rtl/spram.vhd create mode 100644 common/Sound/JT12/LICENSE create mode 100644 common/Sound/JT12/README.md create mode 100644 common/Sound/JT12/hdl/adpcm/gen_lingain.py create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v create mode 100644 common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v create mode 100644 common/Sound/JT12/hdl/alt/eg_cnt.v create mode 100644 common/Sound/JT12/hdl/alt/eg_comb.v create mode 100644 common/Sound/JT12/hdl/alt/eg_mux.v create mode 100644 common/Sound/JT12/hdl/alt/eg_step.v create mode 100644 common/Sound/JT12/hdl/alt/eg_step_ram.v create mode 100644 common/Sound/JT12/hdl/dac/jt12_dac.v create mode 100644 common/Sound/JT12/hdl/dac/jt12_dac2.v create mode 100644 common/Sound/JT12/hdl/deprecated/jt12_amp.v create mode 100644 common/Sound/JT12/hdl/deprecated/jt12_mod24.v create mode 100644 common/Sound/JT12/hdl/deprecated/jt12_mod6.v create mode 100644 common/Sound/JT12/hdl/deprecated/jt12_opram.v create mode 100644 common/Sound/JT12/hdl/jt03.qip create mode 100644 common/Sound/JT12/hdl/jt03.v create mode 100644 common/Sound/JT12/hdl/jt03_acc.v create mode 100644 common/Sound/JT12/hdl/jt03_fm.qip create mode 100644 common/Sound/JT12/hdl/jt10.qip create mode 100644 common/Sound/JT12/hdl/jt10.v create mode 100644 common/Sound/JT12/hdl/jt10_acc.v create mode 100644 common/Sound/JT12/hdl/jt12.qip create mode 100644 common/Sound/JT12/hdl/jt12.v create mode 100644 common/Sound/JT12/hdl/jt12.vhd create mode 100644 common/Sound/JT12/hdl/jt12_acc.v create mode 100644 common/Sound/JT12/hdl/jt12_csr.v create mode 100644 common/Sound/JT12/hdl/jt12_div.v create mode 100644 common/Sound/JT12/hdl/jt12_dout.v create mode 100644 common/Sound/JT12/hdl/jt12_eg.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_cnt.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_comb.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_ctrl.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_final.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_pure.v create mode 100644 common/Sound/JT12/hdl/jt12_eg_step.v create mode 100644 common/Sound/JT12/hdl/jt12_exprom.v create mode 100644 common/Sound/JT12/hdl/jt12_kon.v create mode 100644 common/Sound/JT12/hdl/jt12_lfo.v create mode 100644 common/Sound/JT12/hdl/jt12_logsin.v create mode 100644 common/Sound/JT12/hdl/jt12_mmr.v create mode 100644 common/Sound/JT12/hdl/jt12_mmr_sim.vh create mode 100644 common/Sound/JT12/hdl/jt12_mod.v create mode 100644 common/Sound/JT12/hdl/jt12_op.v create mode 100644 common/Sound/JT12/hdl/jt12_pcm.v create mode 100644 common/Sound/JT12/hdl/jt12_pcm_interpol.v create mode 100644 common/Sound/JT12/hdl/jt12_pg.v create mode 100644 common/Sound/JT12/hdl/jt12_pg_comb.v create mode 100644 common/Sound/JT12/hdl/jt12_pg_dt.v create mode 100644 common/Sound/JT12/hdl/jt12_pg_inc.v create mode 100644 common/Sound/JT12/hdl/jt12_pg_sum.v create mode 100644 common/Sound/JT12/hdl/jt12_pm.v create mode 100644 common/Sound/JT12/hdl/jt12_reg.v create mode 100644 common/Sound/JT12/hdl/jt12_rst.v create mode 100644 common/Sound/JT12/hdl/jt12_sh.v create mode 100644 common/Sound/JT12/hdl/jt12_sh24.v create mode 100644 common/Sound/JT12/hdl/jt12_sh_rst.v create mode 100644 common/Sound/JT12/hdl/jt12_single_acc.v create mode 100644 common/Sound/JT12/hdl/jt12_sumch.v create mode 100644 common/Sound/JT12/hdl/jt12_timers.v create mode 100644 common/Sound/JT12/hdl/jt12_top.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_comb.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_decim.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_fm_uprate.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_genmix.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_interpol.v create mode 100644 common/Sound/JT12/hdl/mixer/jt12_mixer.v diff --git a/Arcade_MiST/Konami Iron Horse/IronHors.qpf b/Arcade_MiST/Konami Iron Horse/IronHors.qpf new file mode 100644 index 00000000..17e50e86 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/IronHors.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "00:21:03 December 03, 2019" + +# Revisions + +PROJECT_REVISION = "IronHors" + diff --git a/Arcade_MiST/Konami Iron Horse/IronHors.qsf b/Arcade_MiST/Konami Iron Horse/IronHors.qsf new file mode 100644 index 00000000..7fcc10f7 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/IronHors.qsf @@ -0,0 +1,257 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# IronHors_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" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY IronHorse_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/sdram.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(IronHorse_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(IronHorse_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name SYSTEMVERILOG_FILE rtl/IronHorse_MiST.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name SYSTEMVERILOG_FILE rtl/IronHorse.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/k005885.sv +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ironhorse_ssg_lpf.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ironhorse_fm_lpf.sv +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v +set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip +set_global_assignment -name QIP_FILE ../../common/Sound/JT12/hdl/jt03.qip +set_global_assignment -name QIP_FILE ../../common/Sound/JT49/jt49.qip +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name FORCE_SYNCH_CLEAR ON +set_global_assignment -name SIGNALTAP_FILE output_files/sdram.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/IronHors.sdc b/Arcade_MiST/Konami Iron Horse/IronHors.sdc new file mode 100644 index 00000000..4a373c09 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/IronHors.sdc @@ -0,0 +1,134 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Konami Iron Horse/README.md b/Arcade_MiST/Konami Iron Horse/README.md new file mode 100644 index 00000000..9e8bd00a --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/README.md @@ -0,0 +1,11 @@ +# MiST port of Konami Iron Horse by ACE + +https://github.com/MiSTer-devel/Arcade-IronHorse_MiSTer + +## Usage + +- Create ROM and ARC files from the MRA files using the MRA utility. + Example: mra -A -z /path/to/mame/roms "Iron Horse (Ver. K).mra" +- Copy the ROM files to the root of the SD Card +- Copy the RBF and ARC files to the same folder on the SD Card +- MRA utility: https://github.com/sebdel/mra-tools-c/ \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra b/Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra new file mode 100644 index 00000000..3c5f7d58 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra @@ -0,0 +1,84 @@ + + Iron Horse + World + no + no + Version K + + + + 1986 + Konami + Platformer + + ironhors + ironhors + 0224 + IronHors + + + 15kHz + no + no + + 2 (alternating) + 8-way + + 3 + + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + 16 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 02 00 + 00 00 32 F1 00 03 02 00 + 00 00 33 00 00 40 23 00 + + + + + 02 58 00 23 2C 1F 01 00 02 58 00 29 2C 29 01 00 + 02 22 00 11 2C 24 00 00 01 95 00 1B 2C 11 00 00 + 01 38 00 19 2C 25 00 00 01 30 00 23 2C 23 00 00 + 01 20 00 1E 2C 1D 00 00 01 10 00 23 2C 19 00 00 + 01 00 00 + + + + + + + + 20210803143815 + diff --git a/Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv b/Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv new file mode 100644 index 00000000..bec013e7 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv @@ -0,0 +1,627 @@ +//============================================================================ +// +// Iron Horse PCB model +// Copyright (C) 2020, 2021 Ace, Ash Evans (aka ElectronAsh/OzOnE) and +// Kitrinx +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Module declaration, I/O ports +module IronHorse +( + input reset, + input clk_49m, //Actual frequency: 49.152MHz + input [1:0] coin, + input [1:0] btn_start, //1 = Player 2, 0 = Player 1 + input [3:0] p1_joystick, p2_joystick, //3 = down, 2 = up, 1 = right, 0 = left + input [2:0] p1_buttons, p2_buttons, //3 buttons per player + input btn_service, + input [23:0] dipsw, + + //The following flag is used to reconfigure the 005885s' video timings and logic for drawing sprites to + //reproduce the errors found on bootleg Iron Horse PCBs (this is a 2-bit signal to reconfigure the 005885s + //depending on which game's bootleg ROM sets are loaded) + input [1:0] is_bootleg, + + //This input serves to select a fractional divider to acheive 3.072MHz for the YM2203 depending on whether Iron Horse + //runs with original or underclocked timings to normalize sync frequencies + input underclock, + + //Screen centering (alters HSync and VSync timing in the primary Konami 005885 to reposition the video output) + input [3:0] h_center, v_center, + + output video_hsync, video_vsync, video_csync, + output video_vblank, video_hblank, + output [3:0] video_r, video_g, video_b, + output signed [15:0] sound, + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, +`ifdef MISTER_HISCORE + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_read, + input hs_access_write, +`endif + + //SDRAM signals + output reg [15:0] main_cpu_rom_addr, + input [7:0] main_cpu_rom_do, + output reg [14:0] sub_cpu_rom_addr, + input [7:0] sub_cpu_rom_do, + output reg [15:1] char1_rom_addr, + input [15:0] char1_rom_do, + output sp1_req, + input sp1_ack, + output [15:1] sp1_rom_addr, + input [15:0] sp1_rom_do +); + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i, ep6_cs_i, ep7_cs_i; +wire prom1_cs_i, prom2_cs_i, prom3_cs_i, prom4_cs_i, prom5_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .ep6_cs(ep6_cs_i), + .ep7_cs(ep7_cs_i), + .prom1_cs(prom1_cs_i), + .prom2_cs(prom2_cs_i), + .prom3_cs(prom3_cs_i), + .prom4_cs(prom4_cs_i), + .prom5_cs(prom5_cs_i) +); + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6.144MHz and (inverted) 3.072MHz clock enables (clock division is normally handled inside the Konami 005885) +//Also generate an extra clock enable for DC offset removal in the sound section +reg [6:0] div = 7'd0; +always_ff @(posedge clk_49m) begin + div <= div + 7'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div[3:0]; +wire dcrm_cen = !div; + +//Phase generator for MC6809E (taken from MiSTer Vectrex core) +//Normally handled internally on the Konami 005885 +reg E = 0; +reg Q = 0; +always_ff @(posedge clk_49m) begin + reg [1:0] clk_phase = 0; + E <= 0; + Q <= 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b01: Q <= 1; + 2'b10: E <= 1; + endcase + end +end + +//Generate 3.072MHz clock enable for YM2203 to maintain consistent sound pitch when underclocked to normalize video timings +//(uses Jotego's fractional clock divider from JTFRAME) +wire cen_3m_adjust; +jtframe_frac_cen sound_cen +( + .clk(clk_49m), + .n(10'd50), + .m(10'd786), + .cen({1'bZ, cen_3m_adjust}) +); + +//------------------------------------------------------------ CPUs ------------------------------------------------------------// + +//Main CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig) +wire [15:0] mc6809e_A; +wire [7:0] mc6809e_Din, mc6809e_Dout; +wire mc6809e_rw; +mc6809is u13A +( + .CLK(clk_49m), + .fallE_en(E), + .fallQ_en(Q), + .D(mc6809e_Din), + .DOut(mc6809e_Dout), + .ADDR(mc6809e_A), + .RnW(mc6809e_rw), + .nIRQ(irq), + .nFIRQ(firq), + .nNMI(nmi), + .nHALT(pause), + .nRESET(reset), + .nDMABREQ(1) +); +//Address decoding for data inputs to MC6809E +wire cs_k005885 = (mc6809e_A[15:14] == 2'b00); +wire cs_soundlatch = ~nioc & (mc6809e_A[10:8] == 3'b000) & ~mc6809e_rw; +wire cs_dip3 = ~nioc & (mc6809e_A[10:8] == 3'b001) & mc6809e_rw; +wire sirq_trigger = ~nioc & (mc6809e_A[10:8] == 3'b001) & ~mc6809e_rw; +wire cs_dip2 = ~nioc & (mc6809e_A[10:8] == 3'b010) & mc6809e_rw; +wire cs_palettelatch = ~nioc & (mc6809e_A[10:8] == 3'b010) & ~mc6809e_rw; +wire cs_controls_dip1 = ~nioc & (mc6809e_A[10:8] == 3'b011) & mc6809e_rw; +wire cs_rom1 = (mc6809e_A[15:14] == 2'b01 || mc6809e_A[15:14] == 2'b10) & mc6809e_rw; +wire cs_rom2 = (mc6809e_A[15:14] == 2'b11 & mc6809e_rw); +//Multiplex data inputs to main CPU +assign mc6809e_Din = + (cs_k005885 & nioc) ? k005885_Dout: + cs_dip3 ? {4'hF, dipsw[19:16]}: + cs_dip2 ? dipsw[15:8]: + cs_controls_dip1 ? controls_dip1: + cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + 8'hFF; + +//Game ROMs +`ifdef EXT_ROM +always_ff @(posedge clk_49m) + if (|mc6809e_A[15:14] & mc6809e_rw) + main_cpu_rom_addr <= mc6809e_A[15:0] - 16'h4000; + +wire [7:0] eprom1_D = main_cpu_rom_do; +wire [7:0] eprom2_D = main_cpu_rom_do; +`else +wire [7:0] eprom1_D; +eprom_1 u13C +( + .ADDR({~mc6809e_A[14], mc6809e_A[13:0]}), + .CLK(clk_49m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +wire [7:0] eprom2_D; +eprom_2 u12C +( + .ADDR(mc6809e_A[13:0]), + .CLK(clk_49m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +`endif + +//Palette latch +reg [7:0] pal_latch = 8'd0; +always_ff @(posedge clk_49m) begin + if(!reset) + pal_latch <= 8'd0; + else if(cen_3m) begin + if(cs_palettelatch) + pal_latch <= mc6809e_Dout; + end +end +wire [2:0] FA = pal_latch[2:0]; + +//Sound latch +reg [7:0] sound_data = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && cs_soundlatch) + sound_data <= mc6809e_Dout; +end + +//Sound IRQ trigger +reg sound_irq = 1; +always_ff @(posedge clk_49m) begin + if(cen_3m) begin + if(sirq_trigger) + sound_irq <= 1; + else + sound_irq <= 0; + end +end + +//Sound CPU - Zilog Z80 (uses T80s variant of the T80 soft core) +wire z80_n_m1, z80_n_mreq, z80_n_iorq, z80_n_rfsh, z80_n_rd, z80_n_wr; +wire [15:0] z80_A; +wire [7:0] z80_Din, z80_Dout; +T80s u9A +( + .RESET_n(reset), + .CLK(clk_49m), + .CEN(cen_sound), + .INT_n(z80_n_int), + .MREQ_n(z80_n_mreq), + .IORQ_n(z80_n_iorq), + .RD_n(z80_n_rd), + .WR_n(z80_n_wr), + .M1_n(z80_n_m1), + .RFSH_n(z80_n_rfsh), + .A(z80_A), + .DI(z80_Din), + .DO(z80_Dout) +); +//Address decoding for data inputs to Z80 +wire z80_decode_en = (z80_n_rfsh & ~z80_n_mreq); +wire soundrom_cs = z80_decode_en & (z80_A[15:14] == 2'b00); +wire soundram_cs = z80_decode_en & (z80_A[15:14] == 2'b01); +wire sounddata_cs = z80_decode_en & (z80_A[15:14] == 2'b10); +//Multiplex data inputs to sound CPU +assign z80_Din = + soundrom_cs ? eprom3_D: + (soundram_cs & ~z80_n_rd) ? soundram_D: + sounddata_cs ? sound_data: + (~z80_n_iorq & ~z80_n_rd) ? ym2203_D: + 8'hFF; + +//Sound ROM +`ifdef EXT_ROM +wire [7:0] eprom3_D = sub_cpu_rom_do; +always_ff @(posedge clk_49m) + if (soundrom_cs) sub_cpu_rom_addr <= z80_A[13:0]; + +`else +wire [7:0] eprom3_D; +eprom_3 u10C +( + .ADDR(z80_A[13:0]), + .CLK(clk_49m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +`endif + +//Sound RAM +wire [7:0] soundram_D; +spram #(8, 11) u11C +( + .clk(clk_49m), + .we(soundram_cs & ~z80_n_wr), + .addr(z80_A[10:0]), + .data(z80_Dout), + .q(soundram_D) +); + +//Generate sound IRQ +wire sirq_clr = (~reset | ~(z80_n_m1 | z80_n_iorq)); +reg z80_n_int = 1; +always_ff @(posedge clk_49m or posedge sirq_clr) begin + if(sirq_clr) + z80_n_int <= 1; + else if(cen_sound && sound_irq) + z80_n_int <= 0; +end + +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Multiplex player inputs and DIP switch bank 1 +wire [7:0] controls_dip1 = (mc6809e_A[1:0] == 2'b00) ? dipsw[7:0]: + (mc6809e_A[1:0] == 2'b01) ? {1'b1, p1_buttons[2], p2_buttons[1:0], p2_joystick}: + (mc6809e_A[1:0] == 2'b10) ? {1'b1, p2_buttons[2], p1_buttons[1:0], p1_joystick}: + (mc6809e_A[1:0] == 2'b11) ? {3'b111, btn_start, btn_service, coin}: + 8'hFF; + +//--------------------------------------------------- Video timing & graphics --------------------------------------------------// + +//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Iron Horse's critical +//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites +wire [15:0] gfxrom_A, sprites_A; +//wire [12:0] vram_A; +//wire [7:0] vram_Din, vram_Dout; +//wire n_vram_oe, n_vram_we; +wire [7:0] k005885_Dout, tilemap_lut_A, sprite_lut_A; +wire [4:0] color_A; +wire tile_attrib_D5, firq, irq, nmi, nioc; +k005885 u11D +( + .CK49(clk_49m), + .NRD(~mc6809e_rw), + .A(mc6809e_A[13:0]), + .DBi(mc6809e_Dout), + .DBo(k005885_Dout), + .R(gfxrom_A), + .RDU(tiles_D[15:8]), + .RDL(tiles_D[7:0]), + .S(sprites_A), + .S_req(sp1_req), + .S_ack(sp1_ack), + .SDU(sprites_D[15:8]), + .SDL(sprites_D[7:0]), + .VCF(tilemap_lut_A[7:4]), + .VCB(tilemap_lut_A[3:0]), + .VCD(tilemap_lut_D), + .OCF(sprite_lut_A[7:4]), + .OCB(sprite_lut_A[3:0]), + .OCD(sprite_lut_D), + .COL(color_A), + .NEXR(reset), + .NXCS(~cs_k005885), + .NCSY(video_csync), + .NHSY(video_hsync), + .NVSY(video_vsync), + .HBLK(video_hblank), + .VBLK(video_vblank), + .NFIR(firq), + .NIRQ(irq), + .NNMI(nmi), + .NIOC(nioc), + .ATR5(tile_attrib_D5), + .HCTR(h_center), + .VCTR(v_center), + .BTLG(is_bootleg) +`ifdef MISTER_HISCORE + , + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_read(hs_access_read), + .hs_access_write(hs_access_write) +`endif + +); + +//Graphics ROMs +always_ff @(posedge clk_49m) + char1_rom_addr <= {gfxrom_A[14], tile_attrib_D5, gfxrom_A[12:0]}; +assign sp1_rom_addr = sprites_A[14:0]; + +`ifdef EXT_ROM +wire [7:0] eprom4_D = sp1_rom_do[15:8]; +wire [7:0] eprom5_D = sp1_rom_do[7:0]; +wire [7:0] eprom6_D = char1_rom_do[15:8]; +wire [7:0] eprom7_D = char1_rom_do[7:0]; +`else +wire [7:0] eprom4_D, eprom5_D; +eprom_4 u8F +( + .ADDR(sprites_A[14:0]), + .CLK(~clk_49m), + .DATA(eprom4_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); +eprom_5 u7F +( + .ADDR(sprites_A[14:0]), + .CLK(~clk_49m), + .DATA(eprom5_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); + +wire [7:0] eprom6_D, eprom7_D; +eprom_6 u9F +( + .ADDR({gfxrom_A[14], tile_attrib_D5, gfxrom_A[12:0]}), + .CLK(clk_49m), + .DATA(eprom6_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep6_cs_i), + .WR(ioctl_wr) +); +eprom_7 u6F +( + .ADDR({gfxrom_A[14], tile_attrib_D5, gfxrom_A[12:0]}), + .CLK(clk_49m), + .DATA(eprom7_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep7_cs_i), + .WR(ioctl_wr) +); +`endif + +//Combine graphics ROM data outputs to 16 bits +wire [15:0] tiles_D = {eprom6_D, eprom7_D}; +wire [15:0] sprites_D = {eprom4_D, eprom5_D}; + +//Tilemap LUT PROM +wire [3:0] tilemap_lut_D; +prom_4 u11F +( + .ADDR(tilemap_lut_A), + .CLK(clk_49m), + .DATA(tilemap_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom4_cs_i), + .WR(ioctl_wr) +); + +//Sprite LUT PROM +wire [3:0] sprite_lut_D; +prom_5 u10F +( + .ADDR(sprite_lut_A), + .CLK(clk_49m), + .DATA(sprite_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom5_cs_i), + .WR(ioctl_wr) +); + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Select whether to use a fractional or integer clock divider for the YM2203 to maintain consistent sound pitch at both original +//and underclocked timings +wire cen_sound = underclock ? cen_3m_adjust : cen_3m; + +//Sound chip (Yamaha YM2203 - uses JT03 implementation by Jotego) +wire [2:0] filter_en; +wire [7:0] ym2203_D; +wire [7:0] ym2203_ssgA_raw, ym2203_ssgB_raw, ym2203_ssgC_raw; +wire signed [15:0] ym2203_fm_raw; + +jt03 u6D +( + .rst(~reset), + .clk(clk_49m), + .cen(cen_sound), + .din(z80_Dout), + .dout(ym2203_D), + .IOA_out({5'bZZZZZ, filter_en}), + .addr(z80_A[0]), + .cs_n(z80_n_iorq), + .wr_n(z80_n_wr), + .psg_A(ym2203_ssgA_raw), + .psg_B(ym2203_ssgB_raw), + .psg_C(ym2203_ssgC_raw), + .fm_snd(ym2203_fm_raw) +); + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Iron Horse's video output is straightforward: three color LUT PROMs, one per color, 12-bit RGB with 4 bits per color +prom_1 u3F +( + .ADDR({FA, color_A}), + .CLK(clk_49m), + .DATA(video_r), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom1_cs_i), + .WR(ioctl_wr) +); +prom_2 u4F +( + .ADDR({FA, color_A}), + .CLK(clk_49m), + .DATA(video_g), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom2_cs_i), + .WR(ioctl_wr) +); +prom_3 u5F +( + .ADDR({FA, color_A}), + .CLK(clk_49m), + .DATA(video_b), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom3_cs_i), + .WR(ioctl_wr) +); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Iron Horse uses a 4.823KHz low-pass filter for the FM side of its YM2203 - filter the audio accordingly here. +wire signed [15:0] ym2203_fm_lpf; +ironhorse_fm_lpf lpf_fm +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_fm_raw), + .out(ym2203_fm_lpf) +); + +//Iron Horse also uses 3 switchable low-pass filters on the SSG side of its YM2203 with a cutoff frequency of +//723.432Hz (actually closer to 492.130Hz due to internal resistance inside the 74HC4066 handling the filter switching). +//Model the switchable filters here. +wire signed [15:0] ym2203_ssgA_lpf, ym2203_ssgB_lpf, ym2203_ssgC_lpf; +ironhorse_ssg_lpf lpf_ssgA +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgA_dcrm), + .out(ym2203_ssgA_lpf) +); +ironhorse_ssg_lpf lpf_ssgB +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgB_dcrm), + .out(ym2203_ssgB_lpf) +); +ironhorse_ssg_lpf lpf_ssgC +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgC_dcrm), + .out(ym2203_ssgC_lpf) +); + +//Remove DC offset from SSG outputs and apply gain to prevent losing quiet sounds after low-pass filtering +wire signed [15:0] ym2203_ssgA_dcrm, ym2203_ssgB_dcrm, ym2203_ssgC_dcrm; +jt49_dcrm2 #(16) dcrm_ssgA +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgA_raw, 5'd0}), + .dout(ym2203_ssgA_dcrm) +); +jt49_dcrm2 #(16) dcrm_ssgB +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgB_raw, 5'd0}), + .dout(ym2203_ssgB_dcrm) +); +jt49_dcrm2 #(16) dcrm_ssgC +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgC_raw, 5'd0}), + .dout(ym2203_ssgC_dcrm) +); + +//Apply the switchable low-pass filters and attenuate SSG outputs back to raw levels +wire signed [15:0] ym2203_ssgA = filter_en[2] ? ym2203_ssgA_lpf >>> 15'd5 : ym2203_ssgA_dcrm >>> 15'd5; +wire signed [15:0] ym2203_ssgB = filter_en[1] ? ym2203_ssgB_lpf >>> 15'd5 : ym2203_ssgB_dcrm >>> 15'd5; +wire signed [15:0] ym2203_ssgC = filter_en[0] ? ym2203_ssgC_lpf >>> 15'd5 : ym2203_ssgC_dcrm >>> 15'd5; + +//Mix all audio sources for the final output +assign sound = (ym2203_fm_lpf + (ym2203_ssgA * 15'd24) + (ym2203_ssgB * 15'd24) + (ym2203_ssgC * 15'd24)) <<< 15'd1; + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv b/Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv new file mode 100644 index 00000000..cd7cb069 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv @@ -0,0 +1,323 @@ +module IronHorse_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "IRONHORS;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "O1,Pause,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire pause = status[1]; + +wire [1:0] orientation = 2'b10; +wire [23:0] dip_sw = ~status[31:8]; + +wire [1:0] is_bootleg = core_mod[1:0]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_98; +assign SDRAM_CKE = 1; + +wire clock_98, clock_49, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_98), + .c1(clock_49),//49.152MHz + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_49 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + +wire [15:0] main_rom_addr; +wire [15:0] main_rom_do; +wire [14:0] sub_rom_addr; +wire [15:0] sub_rom_do; +wire [15:1] ch1_addr; +wire [15:0] ch1_do; +wire sp1_req, sp1_ack; +wire [15:1] sp1_addr; +wire [15:0] sp1_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 17'h10000; + +reg port1_req, port2_req; +sdram #(98) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_98 ), + + // port1 for CPUs + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'h0000 : main_rom_addr[15:1] ), + .cpu1_q ( main_rom_do ), + .cpu2_addr ( ioctl_downl ? 16'h0000 : sub_rom_addr[14:1] + 16'h6000 ), + .cpu2_q ( sub_rom_do ), + + // port2 for graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( {bg_ioctl_addr[23:16], bg_ioctl_addr[14:0]} ), // merge gfx roms to 16-bit wide words + .port2_ds ( {~bg_ioctl_addr[15], bg_ioctl_addr[15]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ), + .ch1_q ( ch1_do ), + .ch2_addr ( ), + .ch2_q ( ), + .sp1_req ( sp1_req ), + .sp1_ack ( sp1_ack ), + .sp1_addr ( ioctl_downl ? 16'hffff : sp1_addr ), + .sp1_q ( sp1_do ), + .sp2_req ( ), + .sp2_ack ( ), + .sp2_addr ( ), + .sp2_q ( ) +); + +// ROM download controller +always @(posedge clock_49) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_49) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +//Instantiate Iron Horse top-level module +IronHorse IronHorse_inst +( + .reset(~reset), // input reset + + .clk_49m(clock_49), // input clk_49m + + .coin({~m_coin2, ~m_coin1}), // input coin + .btn_service(~service), // input btn_service + + .btn_start({~m_two_players, ~m_one_player}), // input [1:0] btn_start + + .p1_joystick({~m_down, ~m_up, ~m_right, ~m_left}), + .p2_joystick({~m_down2, ~m_up2, ~m_right2, ~m_left2}), + .p1_buttons({~m_fireC, ~m_fireB, ~m_fireA}), + .p2_buttons({~m_fire2C, ~m_fire2B, ~m_fire2A}), + + .dipsw(dip_sw), // input [24:0] dipsw + + .is_bootleg(is_bootleg), // Flag to reconfigure core for differences + // present on bootleg Iron Horse PCBs + + .sound(audio), // output [15:0] sound + + .h_center(), // Screen centering + .v_center(), + + .video_hsync(hs), // output video_hsync + .video_vsync(vs), // output video_vsync + .video_vblank(vblank), // output video_vblank + .video_hblank(hblank), // output video_hblank + + .video_r(r), // output [4:0] video_r + .video_g(g), // output [4:0] video_g + .video_b(b), // output [4:0] video_b + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(~pause), + + .underclock(), //Flag to signal that Iron Horse has been underclocked to normalize video timings in order to maintain consistent sound pitch +/* + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_read(hs_access_read), + .hs_access_write(hs_access_write), +*/ + .main_cpu_rom_addr(main_rom_addr), + .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]), + .sub_cpu_rom_addr(sub_rom_addr), + .sub_cpu_rom_do(sub_rom_addr[0] ? sub_rom_do[15:8] : sub_rom_do[7:0]), + .char1_rom_addr(ch1_addr), + .char1_rom_do(ch1_do), + .sp1_req(sp1_req), + .sp1_ack(sp1_ack), + .sp1_rom_addr(sp1_addr), + .sp1_rom_do(sp1_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +wire audio_out; +assign AUDIO_L = audio_out; +assign AUDIO_R = audio_out; + +dac #(.C_bits(16))dac( + .clk_i(clock_49), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(audio_out) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_49 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v b/Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl b/Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd b/Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv b/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv new file mode 100644 index 00000000..37eb3294 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to low-pass filter the FM part of the YM2203 on Iron Horse. + +module ironhorse_fm_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 128; //Sample at 49.152MHz/128 = 384000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.037979203, 0.037979203 + //1.0000000, -0.92404159 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd30278; + B1 = 18'd1245; + B2 = 18'd1245; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv b/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv new file mode 100644 index 00000000..8c40f2e4 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv @@ -0,0 +1,61 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned for the switchable low-pass filters the SSG part of the YM2203 on +//Iron Horse. + +module ironhorse_ssg_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 49.152MHz/96 = 192000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.0079883055, 0.0079883055 + //1.0000000, -0.98402339 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd32244; + B1 = 18'd262; + B2 = 18'd262; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v b/Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Iron Horse/rtl/k005885.sv b/Arcade_MiST/Konami Iron Horse/rtl/k005885.sv new file mode 100644 index 00000000..f8dff57a --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/k005885.sv @@ -0,0 +1,992 @@ +//============================================================================ +// +// SystemVerilog implementation of the Konami 005885 custom tilemap +// generator +// Graphics logic based on the video section of the Green Beret core for +// MiSTer by MiSTer-X +// Copyright (C) 2020, 2022 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Note: This model of the 005885 cannot be used as-is to replace an original 005885. + +module k005885 +( + input CK49, //49.152MHz clock input + output NCK2, //6.144MHz clock output + output H1O, //3.072MHz clock output + output NCPE, //E clock for MC6809E + output NCPQ, //Q clock for MC6809E + output NEQ, //AND of E and Q clocks for MC6809E + input NRD, //Read enable (active low) + output NRES, //Reset passthrough + input [13:0] A, //Address bus from CPU + input [7:0] DBi, //Data bus input from CPU + output [7:0] DBo, //Data output to CPU + output [3:0] VCF, //Color address to tilemap LUT PROM + output [3:0] VCB, //Tile index to tilemap LUT PROM + input [3:0] VCD, //Data input from tilemap LUT PROM + output [3:0] OCF, //Color address to sprite LUT PROM + output [3:0] OCB, //Sprite index to sprite LUT PROM + input [3:0] OCD, //Data input from sprite LUT PROM + output [4:0] COL, //Color data output from color mixer + input NEXR, //Reset input (active low) + input NXCS, //Chip select (active low) + output NCSY, //Composite sync (active low) + output NHSY, //HSync (active low) - Not exposed on the original chip + output NVSY, //VSync (active low) + output HBLK, //HBlank (active high) - Not exposed on the original chip + output VBLK, //VBlank (active high) - Not exposed on the original chip + input NBUE, //Unknown + output NFIR, //Fast IRQ (FIRQ) output for MC6809E + output NIRQ, //IRQ output for MC6809E (VBlank IRQ) + output NNMI, //Non-maskable IRQ (NMI) for MC6809E + output NIOC, //Inverse of address line A11 for external address decoding logic + output NRMW, + + //Split I/O for tile and sprite data + output [15:0] R, //Address output to graphics ROMs (tiles) + input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles) + input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles) + output [15:0] S, //Address output to graphics ROMs (sprites) + output reg S_req = 0, + input S_ack, + input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites) + input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites) + + //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] HCTR, VCTR, + + //Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885 + //Valid values: + //-00: Original behavior + //-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen + // centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is + // flipped) + //-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is + // offset vertically by 1 line, sprite limit significantly lower than normal) + input [1:0] BTLG, + //Extra data outputs for graphics ROMs + output reg ATR4, //Tilemap attribute bit 4 + output reg ATR5 //Tilemap attribute bit 5 + + `ifdef MISTER_HISCORE + //MiSTer high score system I/O (to be used only with Iron Horse) + , + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_read, + input hs_access_write + `endif +); + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Reset line passthrough +assign NRES = NEXR; + +//Generate NIOC output (active low) +assign NIOC = ~(~NXCS & (A[13:11] == 3'b001)); + +//TODO: The timing of the NRMW output is currently unknown - set to 1 for now +assign NRMW = 1; + +//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing +/* +assign ATR4 = tile_ctrl[2] ? tile_attrib_D[4] : tile0_attrib_D[4]; +assign ATR5 = tile_ctrl[2] ? tile_attrib_D[5] : tile0_attrib_D[5]; +*/ +//Data output to CPU +assign DBo = (ram_cs & ~NRD) ? ram_Dout: + (zram0_cs & ~NRD) ? zram0_Dout: + (zram1_cs & ~NRD) ? zram1_Dout: + (zram2_cs & ~NRD) ? zram2_Dout: + (tile_attrib_cs & ~NRD) ? tile0_attrib_Dout: + (tile_cs & ~NRD) ? tile0_Dout: + (tile1_attrib_cs & ~NRD) ? tile1_attrib_Dout: + (tile1_cs & ~NRD) ? tile1_Dout: + (spriteram_cs & ~NRD) ? spriteram_Dout: + 8'hFF; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz +reg [3:0] div = 4'd0; +always_ff @(posedge CK49) begin + div <= div + 4'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div; +assign NCK2 = div[2]; +assign H1O = div[3]; + +//The MC6809E requires two identical clocks with a 90-degree offset - assign these here +reg mc6809e_E = 0; +reg mc6809e_Q = 0; +always_ff @(posedge CK49) begin + reg [1:0] clk_phase = 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b00: mc6809e_E <= 0; + 2'b01: mc6809e_Q <= 1; + 2'b10: mc6809e_E <= 1; + 2'b11: mc6809e_Q <= 0; + endcase + end +end +assign NCPQ = mc6809e_Q; +assign NCPE = mc6809e_E; + +//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here +assign NEQ = NCPE & NCPQ; + +//-------------------------------------------------------- Video timings -------------------------------------------------------// + +//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both +//counters as 9-bit registers. +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter +//rolls over +reg hblank = 0; +reg vblank = 0; +reg frame_odd_even = 0; +//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical +//counter if a bootleg Jackal ROM set is loaded +reg [8:0] vcnt_end = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + if(BTLG == 2'b01) + vcnt_end <= 9'd252; + else if(BTLG == 2'b10) + vcnt_end <= 9'd271; + else + vcnt_end <= 9'd261; + end +end +//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded +reg [8:0] hsync_start = 9'd0; +reg [8:0] hsync_end = 9'd0; +reg [8:0] vsync_start = 9'd0; +reg [8:0] vsync_end = 9'd0; +always_ff @(posedge CK49) begin + if(BTLG == 2'b01) begin + hsync_start <= HCTR[3] ? 9'd287 : 9'd295; + hsync_end <= HCTR[3] ? 9'd318 : 9'd326; + vsync_start <= 9'd244; + vsync_end <= 9'd251; + end + else if(BTLG == 2'b10) begin + hsync_start <= HCTR[3] ? 9'd290 : 9'd310; + hsync_end <= HCTR[3] ? 9'd321 : 9'd341; + vsync_start <= 9'd255; + vsync_end <= 9'd262; + end + else if(tile_ctrl[2]) begin + hsync_start <= HCTR[3] ? 9'd312 : 9'd320; + hsync_end <= HCTR[3] ? 9'd343 : 9'd351; + vsync_start <= 9'd254; + vsync_end <= 9'd261; + end + else begin + hsync_start <= HCTR[3] ? 9'd288 : 9'd296; + hsync_end <= HCTR[3] ? 9'd319 : 9'd327; + vsync_start <= 9'd254; + vsync_end <= 9'd261; + end +end +always_ff @(posedge CK49) begin + if(cen_6m) begin + case(h_cnt) + //HBlank ends two lines earlier than normal on bootleg Jackal PCBs + 10: begin + if(BTLG == 2'b01) + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + 12: begin + if(BTLG != 2'b01) + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + //Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded + 250: begin + if(BTLG == 2'b01 && !tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 252: begin + if(BTLG != 2'b01 && !tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + //Shift the start of HBlank 40 lines later when using the wider 280x224 video mode + 292: begin + if(tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 383: begin + h_cnt <= 0; + case(v_cnt) + 15: begin + vblank <= 0; + v_cnt <= v_cnt + 9'd1; + end + 239: begin + vblank <= 1; + frame_odd_even <= ~frame_odd_even; + v_cnt <= v_cnt + 9'd1; + end + vcnt_end: begin + v_cnt <= 9'd0; + end + default: v_cnt <= v_cnt + 9'd1; + endcase + end + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Output HBlank and VBlank (both active high) +assign HBLK = hblank; +assign VBLK = vblank; + +//Generate horizontal sync and vertical sync (both active low) +assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]): + ~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]); +assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR); +assign NCSY = NHSY ^ NVSY; + +//------------------------------------------------------------- IRQs -----------------------------------------------------------// + +//Edge detection for VBlank and vertical counter bits 4 and 5 for IRQ generation +reg old_vblank, old_vcnt4, old_vcnt5; +always_ff @(posedge CK49) begin + old_vcnt4 <= v_cnt[4]; + old_vcnt5 <= v_cnt[5]; + old_vblank <= vblank; +end + +//IRQ (triggers every VBlank) +reg vblank_irq = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !irq_mask) + vblank_irq <= 1; + else if(!old_vblank && vblank) + vblank_irq <= 0; +end +assign NIRQ = vblank_irq; + +//NMI (triggers on the falling edge of vertical counter bits 4 or 5 based on the state of tile control register bit 2) +reg nmi = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !nmi_mask) + nmi <= 1; + else begin + if(tile_ctrl[2]) begin + if(old_vcnt4 && !v_cnt[4]) + nmi <= 0; + end + else begin + if(old_vcnt5 && !v_cnt[5]) + nmi <= 0; + end + end +end +assign NNMI = nmi; + +//FIRQ (triggers every second VBlank) +reg firq = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !firq_mask) + firq <= 1; + else begin + if(frame_odd_even && !old_vblank && vblank) + firq <= 0; + end +end +assign NFIR = firq; + +//----------------------------------------------------- Internal registers -----------------------------------------------------// + +//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code: +/* +control registers +000: scroll y +001: scroll x (low 8 bits) +002: -------x scroll x (high bit) + ----xxx- row/colscroll control + 000 = solid scroll (finalizr, ddribble bg) + 100 = solid scroll (jackal) + 001 = ? (ddribble fg) + 011 = colscroll (jackal high scores) + 101 = rowscroll (ironhors, jackal map) +003: ------xx high bits of the tile code + -----x-- unknown (finalizr) + ----x--- selects sprite buffer (and makes a copy to a private buffer?) + --x----- unknown (ironhors) + -x------ unknown (ironhors) + x------- unknown (ironhors, jackal) +004: -------x nmi enable + ------x- irq enable + -----x-- firq enable + ----x--- flip screen +*/ + +wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0); + +reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl; +reg nmi_mask = 0; +reg irq_mask = 0; +reg firq_mask = 0; +reg flipscreen = 0; + +//Write to the appropriate register +always_ff @(posedge CK49) begin + reg rightD, leftD, upD; + if(cen_3m) begin + if(regs_cs && NRD) + case(A[2:0]) + 3'b000: scroll_y <= DBi; + 3'b001: scroll_x <= DBi; + 3'b010: scroll_ctrl <= DBi; + 3'b011: tile_ctrl <= DBi; + 3'b100: begin + nmi_mask <= DBi[0]; + irq_mask <= DBi[1]; + firq_mask <= DBi[2]; + flipscreen <= DBi[3]; + end + default; + endcase + end +end + +//--------------------------------------------------------- Unknown RAM --------------------------------------------------------// + +wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F); + +wire [7:0] ram_Dout; +spram #(8, 5) RAM +( + .clk(CK49), + .we(ram_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(ram_Dout) +); + +//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------// + +wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F); +wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F); +wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF); + +//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to +//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll, +//otherwise don't address it +wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]: + (scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]: + 5'h00; +wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout; +dpram_dc #(.widthad_a(5)) ZRAM0 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram0_Dout), + .wren_a(zram0_cs & NRD), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram0_D) +); +spram #(8, 5) ZRAM1 +( + .clk(CK49), + .we(zram1_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(zram1_Dout) +); +spram #(8, 5) ZRAM2 +( + .clk(CK49), + .we(zram2_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(zram2_Dout) +); + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers), +//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its +//constituent components. +wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000); +wire tile_cs = ~NXCS & (A[13:10] == 4'b1001); +wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010); +wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011); +wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11); + +wire [7:0] tile0_attrib_Dout, tile0_Dout, tile1_attrib_Dout, tile1_Dout, spriteram_Dout; +wire [7:0] tile0_attrib_D, tile0_D, tile1_attrib_D, tile1_D, spriteram_D; +//Tilemap layer 0 +dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile0_attrib_Dout), + .wren_a(tile_attrib_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile0_attrib_D) +); +dpram_dc #(.widthad_a(10)) VRAM_TILECODE0 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile0_Dout), + .wren_a(tile_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile0_D) +); +//Tilemap layer 1 +dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile1_attrib_Dout), + .wren_a(tile1_attrib_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile1_attrib_D) +); +dpram_dc #(.widthad_a(10)) VRAM_TILECODE1 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile1_Dout), + .wren_a(tile1_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile1_D) +); + + + +`ifndef MISTER_HISCORE +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(A[11:0]), + .data_a(DBi), + .q_a(spriteram_Dout), + .wren_a(spriteram_cs & NRD), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +`else +// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM) +// - Mirrored sprite RAM used to protect against corruption while retrieving highscore data +wire [11:0] VRAM_SPR_AD = hs_access_write ? hs_address : A[11:0]; +wire [7:0] VRAM_SPR_DIN = hs_access_write ? hs_data_in : DBi; +wire VRAM_SPR_WE = hs_access_write ? hs_write_enable : (spriteram_cs & NRD); +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .q_a(spriteram_Dout), + .wren_a(VRAM_SPR_WE), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +//Sprite RAM shadow for highscore read access +dpram_dc #(.widthad_a(12)) VRAM_SPR_SHADOW +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .wren_a(VRAM_SPR_WE), + + .clock_b(CK49), + .address_b(hs_address), + .q_b(hs_data_out) +); +`endif + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//The Konami 005885 contains two tilemap layers. Finalizer - Super Transformation uses the second layer to draw the HUD at the +//top of the screen. Latch tilemap data out of bank 0 or bank 1 of the tilemap section of VRAM based on how far the game has +//drawn the tilemap layer when tile control bit 2 is set, otherwise grab tilemap data from bank 0 of the tilemap section of VRAM +//at all times + +//Loosely based on TimePilot 84's schematics +reg [7:0] tile_attrib_D, tile_D; +wire tile1_en = flipscreen ? h_cnt > 9'd243 : h_cnt < 9'd40; +wire [5:0] tile_hoffset = tile_ctrl[2] ? (~tile1_en ? (flipscreen ? 6'd4 : 6'd32) : 6'd0) : (flipscreen ? 6'd4 : 6'd0); + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if(h_cnt[1:0] == 2'b01) begin // posedge of h_cnt[1] + if(tile_ctrl[2] && tile1_en) begin + tile_D <= tile1_D; + tile_attrib_D <= tile1_attrib_D; + end + else begin + tile_D <= tile0_D; + tile_attrib_D <= tile0_attrib_D; + end + end + end +end + +//XOR horizontal and vertical counter bits with flipscreen bit +wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}}; +wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}}; + +//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on +//whether row scroll or column scroll is enabled (do not allow scrolling when drawing Finalizer - Super Transformation's HUD +//and offset the tilemap layer with this game) +wire [8:0] row_scroll = (tile_ctrl[2] & !flipscreen & tile1_en) ? 9'd0: + (tile_ctrl[2] & flipscreen & tile1_en) ? 9'd28: + (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x}; +wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y; +wire [7:2] tilemap_hpos = hcnt_x[7:2] + row_scroll[7:2] - tile_hoffset[5:2] + {!tile_ctrl[2] & !flipscreen, 1'b0}/* synthesis keep */; +wire [8:0] tilemap_vpos = vcnt_x + col_scroll; + +//Address output to tilemap section of VRAM +wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]}; + +//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code +wire [9:0] tile_index = {tile_attrib_D[7:6], tile_D} /* synthesis keep */; + +//XOR tile H/V flip bits with the flipscreen bit +wire tile_hflip = tile_attrib_D[4]; +wire tile_vflip = tile_attrib_D[5]; + +//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position +//bit 1 (direct for Finalizer) +reg [15:0] RD_lat = 16'd0; +reg [3:0] tile_color, tile_color_r; +reg tile_hflip_lat, tile_hflip_lat_r; +reg tile_vflip_lat; +reg hpos2_lat; +reg [2:0] yscroll_lat; +reg [1:0] xscroll_lat, xscroll_lat_r, xscroll_lat_rr; + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if(h_cnt[1:0] == 2'b11) begin // negedge of h_cnt[1] + hpos2_lat <= tilemap_hpos[2]; + xscroll_lat <= row_scroll[1:0]; + xscroll_lat_r <= xscroll_lat; + yscroll_lat <= tilemap_vpos[2:0]; + tile_color <= tile_attrib_D[3:0]; + tile_color_r <= tile_color; + tile_hflip_lat <= tile_hflip; + tile_hflip_lat_r <= tile_hflip_lat; + tile_vflip_lat <= tile_vflip; + //Address output to graphics ROMs + R[15:4] <= {tile_ctrl[1:0], tile_index}; + //Latch graphics ROM output + RD_lat <= {RDU, RDL}; + //Output bits 4 and 5 of tilemap attributes for graphics ROM addressing + ATR4 <= tile_attrib_D[4]; + ATR5 <= tile_attrib_D[5]; + end + xscroll_lat_rr <= xscroll_lat_r; + end +end +assign R[3:0] = {yscroll_lat[2:0] ^ {3{tile_vflip_lat}}, hpos2_lat ^ tile_hflip_lat}; + +reg [3:0] tile_pixel /* synthesis keep */; +always @(*) begin + case (hcnt_x[1:0] ^ {2{tile_hflip_lat_r}}) + 2'b00: tile_pixel = RD_lat[15:12]; + 2'b01: tile_pixel = RD_lat[11: 8]; + 2'b10: tile_pixel = RD_lat[ 7: 4]; + 2'b11: tile_pixel = RD_lat[ 3: 0]; + default: ; + endcase +end + +//Address output to tilemap LUT PROM +assign VCF = tile_color_r; +assign VCB = tile_pixel; + +// latch pixel data, and generate 4 shifted pixel positions for fine scroll +reg [3:0] pix0, pix1, pix2, pix3; +always_ff @(posedge CK49) begin + if (cen_6m) begin + pix0 <= VCD; + pix1 <= pix0; + pix2 <= pix1; + pix3 <= pix2; + end +end + +// select the appropriate shifted pixel according to scroll value +reg [3:0] tilemap_D /* synthesis keep */; +wire hud_left = !flipscreen && tile_ctrl[2] && h_cnt < 52; +wire hud_right = flipscreen && tile_ctrl[2] && h_cnt > 252; +always @(*) begin + case ({2{flipscreen}} ^ xscroll_lat_rr) + 2'b00: tilemap_D = pix3; + 2'b01: tilemap_D = pix2; + 2'b10: tilemap_D = pix1; + 2'b11: tilemap_D = pix0; + default: ; + endcase + if (hud_left ) tilemap_D = pix3; + if (hud_right) tilemap_D = pix0; +end + +//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register +wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5]; +//Prioritize the tilemap layer when using the extended 280x224 mode for Finalizer in the score display area, otherwise give priority +//to sprites +wire tilemap_en = tile_ctrl[2] ? (hud_left | hud_right) : tile_sel; + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format +reg [8:0] sprite_hpos = 9'd0; +reg [8:0] sprite_vpos = 9'd0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + sprite_hpos <= h_cnt; + //If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the + //bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a + //vertical offset of 66 lines (65 lines when flipped) + if(BTLG == 2'b10) + if(flipscreen) + sprite_vpos <= v_cnt + 9'd66; + else + sprite_vpos <= v_cnt + 9'd65; + else + if(flipscreen) + sprite_vpos <= v_cnt + 9'd65; + else + sprite_vpos <= v_cnt + 9'd66; + end +end + +//Sprite state machine +reg [8:0] sprite_index; +reg [2:0] sprite_offset; +reg [2:0] sprite_fsm_state; +reg [11:0] sprite_code; +reg [8:0] sprite_limit; +reg [8:0] sprite_x; +reg [7:0] sprite_y; +reg [5:0] sprite_width; +reg [3:0] sprite_color; +reg [2:0] sprite_size; +reg sprite_hflip, sprite_vflip, sprite_x8_sel, sprite_x8_vram; +wire [8:0] sprite_fsm_reset = tile_ctrl[2] ? 9'd40 : 9'd0; +always_ff @(posedge CK49) begin + //Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit + //to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of + //5, otherwise) + sprite_limit <= (BTLG == 2'b10) ? 9'd155 : 9'd485; + //Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0 + //Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse + //ROM sets to prevent graphical garbage from occurring on the top-most line + if(sprite_hpos == sprite_fsm_reset || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin + sprite_width <= 0; + sprite_index <= 0; + sprite_offset <= 3'd4; + sprite_fsm_state <= 1; + end + else + case(sprite_fsm_state) + 0: /* empty */ ; + 1: begin + //If the sprite limit is reached, hold the state machine in an empty state, otherwise latch the sprite H/V flip + //bits, sprite size, bit 8 of the sprite X position and its select bit + if(sprite_index > sprite_limit) + sprite_fsm_state <= 0; + else begin + sprite_vflip <= spriteram_D[6] ^ ~flipscreen; + sprite_hflip <= spriteram_D[5] ^ flipscreen; + sprite_size <= spriteram_D[4:2]; + sprite_x8_sel <= spriteram_D[1]; + sprite_x8_vram <= spriteram_D[0]; + sprite_offset <= 3'd3; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + end + 2: begin + //Latch sprite X position and set the 9th bit as either the one latched previously from VRAM or the AND of position + //bits [7:3] based on the state of the select bit + if(sprite_x8_sel) + sprite_x[8] <= sprite_x8_vram ^ flipscreen; + else + sprite_x[8] <= (&spriteram_D[7:3]) ^ flipscreen; + sprite_x[7:0] <= spriteram_D ^ {8{flipscreen}}; + sprite_offset <= 3'd2; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 3: begin + //Latch sprite Y position + sprite_y <= spriteram_D; + sprite_offset <= 3'd1; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 4: begin + //Skip the current sprite if it's inactive, otherwise latch sprite color and the upper/lower 2 bits of the sprite + //code, and continue scanning out the rest of the sprite attributes + if(sprite_active) begin + sprite_color <= spriteram_D[7:4]; + sprite_code[1:0] <= spriteram_D[3:2]; + sprite_code[11:10] <= spriteram_D[1:0]; + sprite_offset <= 3'd0; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + else begin + sprite_index <= sprite_index + 9'd5; + sprite_offset <= 3'd4; + sprite_fsm_state <= 3'd1; + end + end + 5: begin + //Latch bits [9:2] of the sprite code and set up the sprite width based on the sprite size + sprite_code[9:2] <= spriteram_D; + sprite_offset <= 3'd4; + sprite_index <= sprite_index + 9'd5; + case(sprite_size) + 3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen); + 3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen); + 3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); + 3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); + default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen); + endcase + sprite_fsm_state <= sprite_fsm_state + 3'd1; + S_req <= !S_req; + end + 6: if (S_req == S_ack) begin + //Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails + //to render the last line of sprites), otherwise write sprites as normal + if(BTLG == 2'b01 && !flipscreen) + if(sprite_width == 6'b111110) + sprite_width <= sprite_width + 6'd2; + else + sprite_width <= sprite_width + 6'd1; + else + sprite_width <= sprite_width + 6'd1; + sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1; + S_req <= (wre & sprite_width[1:0] == 2'b11) ? !S_req : S_req; + + end + default:; + endcase +end + +//Adjust sprite code based on sprite size +wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16 + sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8 + sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16 + sprite_size == 3'b011 ? sprite_code: //8x8 + {sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32 + +//Subtract vertical sprite position from sprite Y parameter to obtain sprite height +wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos; + +//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall +reg sprite_active; +always @(*) begin + case(sprite_size) + 3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen); + 3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen); + 3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen); + 3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen); + 3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen); + default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen); + endcase +end + +wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}}; +wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}}; + +//Assign address outputs to sprite ROMs +assign S = {sprite_code_sized, ly[2:0], lx[2]}; + +//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position +wire [7:0] SD = lx[1] ? SDL : SDU; + +//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4]; + +//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3 +wire [8:0] sprite_address = (sprite_index + sprite_offset); +reg sprite_bank = 0; +reg old_vsync; +//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes +//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded +//Finalizer - Super Transformation only reads sprite information from the lower sprite bank +always_ff @(posedge CK49) begin + old_vsync <= NVSY; + if(!NEXR) + sprite_bank <= 0; + else if(!old_vsync && NVSY) + sprite_bank <= tile_ctrl[3]; +end +wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address}; + +//Address output to sprite LUT PROM +assign OCF = sprite_color; +assign OCB = sprite_pixel; + +//----------------------------------------------------- Sprite line buffer -----------------------------------------------------// + +//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the +//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation. + +//Enable writing to sprite line buffer when bit 5 of the sprite width is 1 +wire wre = sprite_width[5]; + +//Set sprite line buffer bank as bit 0 of the sprite vertical position +wire sprite_lbuff_bank = sprite_vpos[0]; + +//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size: +//32 pixels wide: bits [4:0] +//16 pixels wide: bits [3:0] +//8 pixels wide: bits [2:0] +//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites +reg [4:0] final_sprite_width; +always @(*) begin + case(sprite_size) + 3'b000: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]}; + 3'b001: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]}; + 3'b010: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]}; + 3'b011: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]}; + 3'b100: final_sprite_width = sprite_width[4:0]; + default: final_sprite_width = sprite_width[4:0]; + endcase +end +wire [8:0] wpx = sprite_x + final_sprite_width; + +//Generate sprite line buffer write addresses +reg [9:0] lbuff_A; +reg lbuff_we; +wire [3:0] lbuff_Din = OCD; +always_ff @(posedge CK49) begin + lbuff_A <= {~sprite_lbuff_bank, wpx}; + lbuff_we <= wre & S_req == S_ack; +end + +//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen +//is flipped) +reg [9:0] radr0 = 10'd0; +reg [9:0] radr1 = 10'd1; +always_ff @(posedge CK49) begin + if(cen_6m) + radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : tile_ctrl[2] ? sprite_hpos - 9'd40 : sprite_hpos}; +end + +//Sprite line buffer +wire [3:0] lbuff_Dout; +dpram_dc #(.widthad_a(10)) LBUFF +( + .clock_a(CK49), + .address_a(lbuff_A), + .data_a({4'd0, lbuff_Din}), + .wren_a(lbuff_we & (lbuff_Din != 0)), + + .clock_b(CK49), + .address_b(radr0), + .data_b(8'h0), + .wren_b(radr0 == radr1), + .q_b({4'bZZZZ, lbuff_Dout}) +); + +//Latch sprite data from the sprite line buffer +wire lbuff_read_en = (div[2:0] == 3'b100); +reg [3:0] lbuff_read = 4'd0; +always_ff @(posedge CK49) begin + if(lbuff_read_en) begin + if(radr0 != radr1) + lbuff_read <= lbuff_Dout; + radr1 <= radr0; + end +end + +//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped) +reg [7:0] sprite_dly = 8'd0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + if(BTLG == 2'b01 && flipscreen) + sprite_dly <= {4'd0, lbuff_read}; + else + sprite_dly <= {lbuff_read, sprite_dly[7:4]}; + end +end +//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here +wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0]; + +//--------------------------------------------------------- Color mixer --------------------------------------------------------// + +//Multiplex tile and sprite data, then output the final result +wire tile_sprite_sel = (tilemap_en | ~(|sprite_D)); +wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D; + +//Latch and output pixel data +reg [4:0] pixel_D; +always_ff @(posedge CK49) begin + if(cen_6m) + pixel_D <= {tile_sprite_sel, tile_sprite_D}; +end +assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) || + (BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D; +//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set +//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse +//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of +//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/pll.qip b/Arcade_MiST/Konami Iron Horse/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Konami Iron Horse/rtl/pll.v b/Arcade_MiST/Konami Iron Horse/rtl/pll.v new file mode 100644 index 00000000..1960b7f8 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 105, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 382, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 105, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 191, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv b/Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv new file mode 100644 index 00000000..3f05104a --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv @@ -0,0 +1,366 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019, 2020 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Iron Horse: +// 0x0000 - 0xFFFF = eprom_1 +// 0x10000 - 0x13FFF = eprom_2 +// 0x14000 - 0x1BFFF = eprom_3 +// 0x1C000 - 0x3BFFF = maskrom_1 +// 0x3C000 - 0x5BFFF = maskrom_2 +// 0x5C000 - 0x7BFFF = maskrom_3 +// 0x7C000 - 0x9BFFF = maskrom_4 +// 0x9C000 - 0x9C0FF = prom_1 +// 0x9C100 - 0x9C1FF = prom_2 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, prom1_cs, prom2_cs, prom3_cs, prom4_cs, prom5_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, prom1_cs, prom2_cs, prom3_cs, prom4_cs, prom5_cs} = 0; + if(ioctl_addr < 'h8000) + ep1_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'hC000) + ep2_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h10000) + ep3_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h18000) + ep4_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h20000) + ep5_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28000) + ep6_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h30000) + ep7_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h30100) + prom1_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h30200) + prom2_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h30300) + prom3_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h30400) + prom4_cs = 1; // 0x100 8 + else + prom5_cs = 1; // 0x100 8 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_4 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_5 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_6 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_6 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_7 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_7 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_1 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_2 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_3 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_4 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_5 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/sdram.sv b/Arcade_MiST/Konami Iron Horse/rtl/sdram.sv new file mode 100644 index 00000000..28b3c6ee --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/sdram.sv @@ -0,0 +1,363 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [15:1] cpu1_addr, + output reg [15:0] cpu1_q, + input [15:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [15:0] port2_q, + input [15:1] ch1_addr, + output reg [15:0] ch1_q, + input [15:1] ch2_addr, + output reg [15:0] ch2_q, + input sp1_req, + input [15:1] sp1_addr, + output reg [15:0] sp1_q, + output reg sp1_ack, + input sp2_req, + input [15:1] sp2_addr, + output reg [15:0] sp2_q, + output reg sp2_ack +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 + 1 ras0 + 2 data1 returned + 3 CAS0 + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [15:1] addr_last[6]; +reg [15:1] addr_last2[6]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 3'd0; +localparam PORT_CPU1 = 3'd1; +localparam PORT_CPU2 = 3'd2; +localparam PORT_CH1 = 3'd1; +localparam PORT_CH2 = 3'd2; +localparam PORT_SP1 = 3'd3; +localparam PORT_SP2 = 3'd4; +localparam PORT_REQ = 3'd5; + +reg [2:0] next_port[2]; +reg [2:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 9'd0, cpu1_addr }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 9'd0, cpu2_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (ch1_addr != addr_last2[PORT_CH1]) begin + next_port[1] = PORT_CH1; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b001, ch1_addr }; + end else if (ch2_addr != addr_last2[PORT_CH2]) begin + next_port[1] = PORT_CH2; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b011, ch2_addr }; + end else if (sp1_req != sp1_ack) begin + next_port[1] = PORT_SP1; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b000, sp1_addr }; + end else if (sp2_req != sp2_ack) begin + next_port[1] = PORT_SP2; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b010, sp2_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][15:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][15:1]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end + PORT_CH1 : ch1_q <= sd_din; + PORT_CH2 : ch2_q <= sd_din; + PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end + PORT_SP2 : begin sp2_q <= sd_din; sp2_ack <= sp2_req; end + default: ; + endcase; + end + + end +end + +endmodule diff --git a/Arcade_MiST/Konami Iron Horse/rtl/spram.vhd b/Arcade_MiST/Konami Iron Horse/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Konami Iron Horse/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl; diff --git a/common/CPU/MC6809/mc6809is.v b/common/CPU/MC6809/mc6809is.v index fdb860e6..0a86c7c4 100644 --- a/common/CPU/MC6809/mc6809is.v +++ b/common/CPU/MC6809/mc6809is.v @@ -17,6 +17,7 @@ // Revision: // Revision 1.0 - Initial Release // Revision 1.0s - Sinchronous version (by Sorgelig) +// Revision 1.0sk - Add direct injection of KONAMI-1 encrypted opcodes (by Ace) // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// @@ -41,12 +42,14 @@ module mc6809is #( - parameter ILLEGAL_INSTRUCTIONS="GHOST" + parameter ILLEGAL_INSTRUCTIONS="GHOST", + parameter IS_KONAMI1="FALSE" ) ( input CLK, input fallE_en, input fallQ_en, + input [7:0] OP, input [7:0] D, output [7:0] DOut, @@ -452,7 +455,10 @@ wire [7:0] MappedInstruction; generate if (ILLEGAL_INSTRUCTIONS=="GHOST") begin : ghost - assign MappedInstruction = MapInstruction(D); + if(IS_KONAMI1=="FALSE") //Modification by Ace: accept opcodes directly for KONAMI-1 CPU + assign MappedInstruction = MapInstruction(D); + else + assign MappedInstruction = MapInstruction(OP); end else begin diff --git a/common/Sound/JT12/LICENSE b/common/Sound/JT12/LICENSE new file mode 100644 index 00000000..9cecc1d4 --- /dev/null +++ b/common/Sound/JT12/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/common/Sound/JT12/README.md b/common/Sound/JT12/README.md new file mode 100644 index 00000000..7dc44b2f --- /dev/null +++ b/common/Sound/JT12/README.md @@ -0,0 +1,43 @@ +# JT12 FPGA Clone of Yamaha OPN hardware by Jose Tejada (@topapate) +=================================================================== + +You can show your appreciation through +* [Patreon](https://patreon.com/topapate), by supporting releases +* [Paypal](https://paypal.me/topapate), with a donation + + +JT12 is an FM sound source written in Verilog, fully compatible with YM2612/YM3438 (Megadrive), YM2610 (NeoGeo) and YM2203 (PC88, arcades). + +The implementation tries to be as close to original hardware as possible. Low usage of FPGA resources has also been a design goal. Except in the operator section (jt12_op) where an exact replica of the original circuit is done. This could be done in less space with a different style but because this piece of the circuit was reversed engineered by Sauraen, I decided to use that knowledge. + +## Directories + +* hdl -> all relevant RTL files, written in verilog +* ver -> test benches +* ver/verilator -> test bench that can play vgm files + +## Usage + +Chip | Top Level | QIP File +--------|---------------|--------- +YM2610 | jt10.v | jt10.qip +YM2612 | jt12.v | jt12.qip +YM2203 | jt03.v | jt03.qip + +## Simulation + +There are several simulation test benches in the **ver** folder. The most important one is in the **ver/verilator** folder. The simulation script is called with the shell script **go** in the same folder. The script will compile the file **test.cpp** together with other files and the design and will simulate the tune specificied with the -f command. It can read **vgm** tunes and generate .wav output of them. + +## Related Projects + +Other sound chips from the same author + +Chip | Repository +-----------------------|------------ +YM2203, YM2612, YM2610 | [JT12](https://github.com/jotego/jt12) +YM2151 | [JT51](https://github.com/jotego/jt51) +YM3526 | [JTOPL](https://github.com/jotego/jtopl) +YM2149 | [JT49](https://github.com/jotego/jt49) +sn76489an | [JT89](https://github.com/jotego/jt89) +OKI 6295 | [JT6295](https://github.com/jotego/jt6295) +OKI MSM5205 | [JT5205](https://github.com/jotego/jt5205) \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/gen_lingain.py b/common/Sound/JT12/hdl/adpcm/gen_lingain.py new file mode 100644 index 00000000..d0fbb850 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/gen_lingain.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +import sys + +db=0 + +for k in range(64): + lin = 10**(db/20)*511 + sys.stdout.write(" mem[%03d] = 9'd%03d;" % (k, lin)) + if( k%4 == 3 ): + sys.stdout.write("\n") + # else: + # sys.stdout.write(" ") + db = db - 0.75 diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm.v new file mode 100644 index 00000000..2237300f --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm.v @@ -0,0 +1,132 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// ADPCM-A algorithm + +module jt10_adpcm( + input rst_n, + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [3:0] data, + input chon, // high if this channel is on + input clr, + output signed [15:0] pcm +); + +localparam sigw = 13; // 1 bit more than the actual signal width so +localparam shift = 3; //16-sigw; + // there is room for overflow +wire signed [sigw-1:0] max_pos = { 2'b00, {sigw-2{1'b1}} }; +wire signed [sigw-1:0] max_neg = { 2'b11, {sigw-2{1'b0}} }; + +reg signed [sigw-1:0] x1, x2, x3, x4, x5, x6; +reg signed [sigw-1:0] inc4; +reg [5:0] step1, step2, step6, step3, step4, step5; +reg [5:0] step_next, step_1p; +reg sign2, sign3, sign4, sign5, xsign5; + +// All outputs from stage 1 +assign pcm = { {16-sigw{x1[sigw-1]}}, x1 } <<< shift; + +// This could be decomposed in more steps as the pipeline +// has room for it +always @(*) begin + casez( data[2:0] ) + 3'b0??: step_next = step1==6'd0 ? 6'd0 : (step1-6'd1); + 3'b100: step_next = step1+6'd2; + 3'b101: step_next = step1+6'd5; + 3'b110: step_next = step1+6'd7; + 3'b111: step_next = step1+6'd9; + endcase + step_1p = step_next > 6'd48 ? 6'd48 : step_next; +end + +wire [11:0] inc3; +reg [8:0] lut_addr2; + + +jt10_adpcma_lut u_lut( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen ), + .addr ( lut_addr2 ), + .inc ( inc3 ) +); + +// Original pipeline: 6 stages, 6 channels take 36 clock cycles +// 8 MHz -> /12 divider -> 666 kHz +// 666 kHz -> 18.5 kHz = 55.5/3 kHz + +reg chon2, chon3, chon4; +wire [sigw-1:0] inc3_long = { {sigw-12{1'b0}},inc3 }; + +always @( posedge clk or negedge rst_n ) + if( ! rst_n ) begin + x1 <= 'd0; step1 <= 0; + x2 <= 'd0; step2 <= 0; + x3 <= 'd0; step3 <= 0; + x4 <= 'd0; step4 <= 0; + x5 <= 'd0; step5 <= 0; + x6 <= 'd0; step6 <= 0; + sign2 <= 'b0; + chon2 <= 'b0; chon3 <= 'b0; chon4 <= 'b0; + lut_addr2 <= 'd0; + inc4 <= 'd0; + end else if(cen) begin + // I + sign2 <= data[3]; + x2 <= clr ? {sigw{1'b0}} : x1; + step2 <= clr ? 6'd0 : (chon ? step_1p : step1); + chon2 <= chon; + lut_addr2 <= { step1, data[2:0] }; + // II 2's complement of inc2 if necessary + sign3 <= sign2; + x3 <= x2; + step3 <= step2; + chon3 <= chon2; + // III + sign4 <= sign3; + inc4 <= sign3 ? ~inc3_long + 1 : inc3_long; + x4 <= x3; + step4 <= step3; + chon4 <= chon3; + // IV + sign5 <= sign4; + xsign5 <= x4[sigw-1]; + x5 <= chon4 ? x4 + inc4 : x4; + step5 <= step4; + // V + // if( xsign5!=x5[sigw-1] && sign5!=x5[sigw-1] ) begin // enable limiter + // if( sign5 ) // it was negative + // x6 <= {1'b1, {sigw-1{1'b0}}}; + // else // it was positive + // x6 <= {1'b0, {sigw-1{1'b1}}}; + // end else + x6 <= x5; + if( x5 > max_pos) x6 <= max_pos; + if( x5 < max_neg) x6 <= max_neg; + step6 <= step5; + // VI: close the loop + x1 <= x6; + step1 <= step6; + end + +endmodule // jt10_adpcm \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v new file mode 100644 index 00000000..7e5ae01b --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v @@ -0,0 +1,90 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Adds all 6 channels and apply linear interpolation to rise +// sampling frequency to 55.5 kHz + +module jt10_adpcm_acc( + input rst_n, + input clk, // CPU clock + input cen, // 111 kHz + // pipeline channel + input [5:0] cur_ch, + input [5:0] en_ch, + input match, + + input en_sum, + input signed [15:0] pcm_in, // 18.5 kHz + output signed [15:0] pcm_out // 55.5 kHz +); + +wire signed [17:0] pcm_in_long = en_sum ? { {2{pcm_in[15]}}, pcm_in } : 18'd0; +reg signed [17:0] acc, last, pcm_full; +reg signed [17:0] step; + +reg signed [17:0] diff; +reg signed [22:0] diff_ext, step_full; + +always @(*) begin + diff = acc-last; + diff_ext = { {5{diff[17]}}, diff }; + step_full = diff_ext // 1/128 + + ( diff_ext << 1 ) // 1/64 + + ( diff_ext << 3 ) // 1/16 + + ( diff_ext << 5 ); // 1/4 + +end + +wire adv = en_ch[0] & cur_ch[0]; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + step <= 'd0; + acc <= 18'd0; + last <= 18'd0; + end else if(cen) begin + if( match ) + acc <= en_ch[0] ? pcm_in_long : ( pcm_in_long + acc ); + if( adv ) begin + // step = diff * (1/4+1/16+1/64+1/128) + step <= { {2{step_full[22]}}, step_full[22:7] }; // >>>7; + last <= acc; + end + end +wire overflow = |pcm_full[17:15] & ~&pcm_full[17:15]; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + pcm_full <= 18'd0; + end else if(cen && cur_ch[0]) begin + case( en_ch ) + 6'b000_001: pcm_full <= last; + 6'b000_100, + 6'b010_000: pcm_full <= pcm_full + step; + default:; + endcase + if( overflow ) + pcm_out <= pcm_full[17] ? 16'h8000 : 16'h7fff; // saturate + else + pcm_out <= pcm_full[15:0]; + end + +endmodule // jt10_adpcm_acc \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v new file mode 100644 index 00000000..aeca48f8 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v @@ -0,0 +1,181 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt10_adpcm_cnt( + input rst_n, + input clk, // CPU clock + input cen, // 666 kHz + // pipeline channel + input [ 5:0] cur_ch, + input [ 5:0] en_ch, + // Address writes from CPU + input [15:0] addr_in, + input [ 2:0] addr_ch, + input up_start, + input up_end, + // Counter control + input aon, + input aoff, + // ROM driver + output [19:0] addr_out, + output [ 3:0] bank, + output sel, + output roe_n, + output decon, + output clr, // inform the decoder that a new section begins + // Flags + output reg [ 5:0] flags, + input [ 5:0] clr_flags, + // + output [15:0] start_top, + output [15:0] end_top +); + +reg [20:0] addr1, addr2, addr3, addr4, addr5, addr6; +reg [3:0] bank1, bank2, bank3, bank4, bank5, bank6; +reg [11:0] start1, start2, start3, start4, start5, start6, + end1, end2, end3, end4, end5, end6; +reg on1, on2, on3, on4, on5, on6; +reg done5, done6, done1; +reg [5:0] done_sr, zero; + +reg roe_n1, decon1; + +reg clr1, clr2, clr3, clr4, clr5, clr6; + +// All outputs from stage 1 +assign addr_out = addr1[20:1]; +assign sel = addr1[0]; +assign bank = bank1; +assign roe_n = roe_n1; +assign clr = clr1; +assign decon = decon1; + +wire active5 = { cur_ch[1:0], cur_ch[5:2] } == en_ch; +wire sumup5 = on5 && !done5 && active5; +reg sumup6; + +reg [5:0] last_done, set_flags; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + zero <= 6'd1; + done_sr <= ~6'd0; + last_done <= ~6'd0; + end else if(cen) begin + zero <= { zero[0], zero[5:1] }; + done_sr <= { done1, done_sr[5:1]}; + if( zero[0] ) begin + last_done <= done_sr; + set_flags <= ~last_done & done_sr; + end + end + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + flags <= 6'd0; + end else begin + flags <= ~clr_flags & (set_flags | flags); + end + +`ifdef SIMULATION +wire [11:0] addr1_cmp = addr1[20:9]; +`endif + +assign start_top = {bank1, start1}; +assign end_top = {bank1, end1}; + +reg [5:0] cur_ch, addr_ch_dec; +reg [5:0] en_ch; + +always @(*) + case(addr_ch) + 3'd0: addr_ch_dec = 6'b000_001; + 3'd1: addr_ch_dec = 6'b000_010; + 3'd2: addr_ch_dec = 6'b000_100; + 3'd3: addr_ch_dec = 6'b001_000; + 3'd4: addr_ch_dec = 6'b010_000; + 3'd5: addr_ch_dec = 6'b100_000; + default: addr_ch_dec = 6'd0; + endcase // up_addr + +wire up1 = cur_ch == addr_ch_dec; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + addr1 <= 'd0; addr2 <= 'd0; addr3 <= 'd0; + addr4 <= 'd0; addr5 <= 'd0; addr6 <= 'd0; + done1 <= 'd1; done5 <= 'd1; done6 <= 'd1; + start1 <= 'd0; start2 <= 'd0; start3 <= 'd0; + start4 <= 'd0; start5 <= 'd0; start6 <= 'd0; + end1 <= 'd0; end2 <= 'd0; end3 <= 'd0; + end4 <= 'd0; end5 <= 'd0; end6 <= 'd0; + end else if( cen ) begin + addr2 <= addr1; + on2 <= aoff ? 1'b0 : (aon | on1); + clr2 <= aoff || (aon && !on1); // Each time a A-ON is sent the address counter restarts + start2 <= (up_start && up1) ? addr_in[11:0] : start1; + end2 <= (up_end && up1) ? addr_in[11:0] : end1; + bank2 <= ((up_end | up_start) && up1) ? addr_in[15:12] : bank1; + + addr3 <= addr2; // clr2 ? {start2,9'd0} : addr2; + on3 <= on2; + clr3 <= clr2; + start3 <= start2; + end3 <= end2; + bank3 <= bank2; + + addr4 <= addr3; + on4 <= on3; + clr4 <= clr3; + start4 <= start3; + end4 <= end3; + bank4 <= bank3; + + addr5 <= addr4; + on5 <= on4; + clr5 <= clr4; + done5 <= addr4[20:9] == end4; // && addr4[8:0]==~9'b0; + start5 <= start4; + end5 <= end4; + bank5 <= bank4; + // V + addr6 <= addr5; + on6 <= on5; + clr6 <= clr5; + done6 <= done5; + start6 <= start5; + end6 <= end5; + bank6 <= bank5; + sumup6 <= sumup5; + + addr1 <= clr6 ? {start6,9'd0} : (sumup6 ? addr6+21'd1 :addr6); + on1 <= on6; + done1 <= done6; + start1 <= start6; + end1 <= end6; + roe_n1 <= ~sumup6; + decon1 <= sumup6; + bank1 <= bank6; + clr1 <= clr6; + end + +endmodule // jt10_adpcm_cnt diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v new file mode 100644 index 00000000..c0f63ac7 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v @@ -0,0 +1,134 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Sampling rates: 2kHz ~ 55.5 kHz. in 0.85Hz steps + +module jt10_adpcm_comb( + input rst_n, + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [3:0] data, + input chon, // high if this channel is on + output signed [15:0] pcm +); + +localparam stepw = 15; + +reg signed [15:0] x1, x2, x3, x4, x5, x6; +reg [stepw-1:0] step1, step2, step6; +reg [stepw+1:0] step3, step4, step5; +assign pcm = x2; + +reg [18:0] d2l; +reg [15:0] d3,d4; +reg [3:0] d1,d2; +reg sign2, sign3, sign4, sign5; +reg [7:0] step_val; +reg [22:0] step2l; + +// Original pipeline: 6 stages, 6 channels take 36 clock cycles +// 8 MHz -> /12 divider -> 666 kHz +// 666 kHz -> 18.5 kHz = 55.5/3 kHz + +reg chon2, chon3, chon4, chon5; +reg signEqu4, signEqu5; +reg [3:0] data1,data2; + +always @( * ) + if( ! rst_n ) begin + x2 = 'd0; step2 = 'd127; + x3 = 'd0; step3 = 'd127; + x4 = 'd0; step4 = 'd127; + x5 = 'd0; step5 = 'd127; + x6 = 'd0; step6 = 'd127; + d2 = 'd0; d3 = 'd0; d4 = 'd0; + sign2 = 'b0; + sign3 = 'b0; + sign4 = 'b0; sign5 = 'b0; + chon2 = 'b0; chon3 = 'b0; chon4 = 'b0; chon5 = 1'b0; + end else begin + // I + d2 = d1; + sign2 = data1[3]; + data2 = data1; + x2 = x1; + step2 = step1; + chon2 = chon; + // II multiply and obtain the offset + casez( d2[3:1] ) + 3'b0_??: step_val = 8'd57; + 3'b1_00: step_val = 8'd77; + 3'b1_01: step_val = 8'd102; + 3'b1_10: step_val = 8'd128; + 3'b1_11: step_val = 8'd153; + endcase // data[2:0] + d2l = d2 * step2; // 4 + 15 = 19 bits -> div by 8 -> 16 bits + step2l = step_val * step2; // 15 bits + 8 bits = 23 bits -> div 64 -> 17 bits + d3 = d2l[18:3]; // 16 bits + sign3 = sign2; + x3 = x2; + step3 = step2l[22:6]; + chon3 = chon2; + // III 2's complement of d3 if necessary + d4 = sign3 ? ~d3+16'b1 : d3; + sign4 = sign3; + signEqu4 = sign3 == x3[15]; + x4 = x3; + step4 = step3; + chon4 = chon3; + // IV Advance the waveform + x5 = x4+d4; + sign5 = sign4; + signEqu5 = signEqu4; + step5 = step4; + chon5 = chon4; + // V: limit or reset outputs + if( chon5 ) begin + if( signEqu5 && (sign5!=x5[15]) ) + x6 = sign5 ? 16'h8000 : 16'h7FFF; + else + x6 = x5; + + if( step5 < 127 ) + step6 = 15'd127; + else if( step5 > 24576 ) + step6 = 15'd24576; + else + step6 = step5[14:0]; + end else begin + x6 = 'd0; + step6 = 'd127; + end + end + +always @(posedge clk or negedge rst_n) + if( ! rst_n ) begin + x1 <= 'd0; step1 <= 'd127; + d1 <= 'd0; data1 <= 'd0; + end else if(cen) begin + // VI: close the loop + d1 <= {data[2:0],1'b1}; + x1 <= x6; + step1 <= step6; + data1 <= data; + end + +endmodule // jt10_adpcm \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v new file mode 100644 index 00000000..5ba7d4ac --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v @@ -0,0 +1,54 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// dB to linear + +module jt10_adpcm_dbrom( + input clk, // CPU clock + input [5:0] db, + output [8:0] lin +); + +reg [8:0] mem[0:63]; + +initial begin // generated with file gen_lingain.py + mem[000] = 9'd511; mem[001] = 9'd468; mem[002] = 9'd429; mem[003] = 9'd394; + mem[004] = 9'd361; mem[005] = 9'd331; mem[006] = 9'd304; mem[007] = 9'd279; + mem[008] = 9'd256; mem[009] = 9'd234; mem[010] = 9'd215; mem[011] = 9'd197; + mem[012] = 9'd181; mem[013] = 9'd166; mem[014] = 9'd152; mem[015] = 9'd139; + mem[016] = 9'd128; mem[017] = 9'd117; mem[018] = 9'd107; mem[019] = 9'd099; + mem[020] = 9'd090; mem[021] = 9'd083; mem[022] = 9'd076; mem[023] = 9'd070; + mem[024] = 9'd064; mem[025] = 9'd059; mem[026] = 9'd054; mem[027] = 9'd049; + mem[028] = 9'd045; mem[029] = 9'd041; mem[030] = 9'd038; mem[031] = 9'd035; + mem[032] = 9'd032; mem[033] = 9'd029; mem[034] = 9'd027; mem[035] = 9'd024; + mem[036] = 9'd022; mem[037] = 9'd020; mem[038] = 9'd019; mem[039] = 9'd017; + mem[040] = 9'd016; mem[041] = 9'd014; mem[042] = 9'd013; mem[043] = 9'd012; + mem[044] = 9'd011; mem[045] = 9'd010; mem[046] = 9'd009; mem[047] = 9'd008; + mem[048] = 9'd008; mem[049] = 9'd007; mem[050] = 9'd006; mem[051] = 9'd006; + mem[052] = 9'd005; mem[053] = 9'd005; mem[054] = 9'd004; mem[055] = 9'd004; + mem[056] = 9'd004; mem[057] = 9'd003; mem[058] = 9'd003; mem[059] = 9'd003; + mem[060] = 9'd002; mem[061] = 9'd002; mem[062] = 9'd002; mem[063] = 9'd002; +end + +always @(posedge clk) + lin <= mem[db]; + +endmodule // jt10_adpcm_dbrom \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v new file mode 100644 index 00000000..41ed279a --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v @@ -0,0 +1,62 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// calculates d=a/b +// a = b*d + r + +module jt10_adpcm_div #(parameter dw=16)( + input rst_n, + input clk, // CPU clock + input cen, + input start, // strobe + input [dw-1:0] a, + input [dw-1:0] b, + output reg [dw-1:0] d, + output reg [dw-1:0] r, + output working +); + +reg [dw-1:0] cycle; +assign working = cycle[0]; + +wire [dw:0] sub = { r[dw-2:0], d[dw-1] } - b; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + cycle <= 'd0; + end else if(cen) begin + if( start ) begin + cycle <= {dw{1'd1}}; + r <= 'd0; + d <= a; + end else if(cycle[0]) begin + cycle <= { 1'b0, cycle[dw-1:1] }; + if( sub[dw] == 0 ) begin + r <= sub[dw-1:0]; + d <= { d[dw-2:0], 1'b1}; + end else begin + r <= { r[dw-2:0], d[dw-1] }; + d <= { d[dw-2:0], 1'b0 }; + end + end + end + +endmodule // jt10_adpcm_div diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v new file mode 100644 index 00000000..8444f0c6 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v @@ -0,0 +1,335 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt10_adpcm_drvA( + input rst_n, + input clk, // CPU clock + input cen, // same cen as MMR + input cen6, // clk & cen = 666 kHz + input cen1, // clk & cen = 111 kHz + + output [19:0] addr, // real hardware has 10 pins multiplexed through RMPX pin + output [3:0] bank, + output reg roe_n, // ADPCM-A ROM output enable + + // Control Registers + input [5:0] atl, // ADPCM Total Level + input [7:0] lracl_in, + input [15:0] addr_in, + + input [2:0] up_lracl, + input up_start, + input up_end, + input [2:0] up_addr, + + input [7:0] aon_cmd, // ADPCM ON equivalent to key on for FM + input up_aon, + + input [7:0] datain, + + // Flags + output [5:0] flags, + input [5:0] clr_flags, + + output reg signed [15:0] pcm55_l, + output reg signed [15:0] pcm55_r +); + +/* verilator tracing_on */ + +reg [5:0] cur_ch; +reg [5:0] en_ch; +reg [3:0] data; +wire nibble_sel; +wire signed [15:0] pcm_att; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + data <= 4'd0; + end else if(cen) begin + data <= !nibble_sel ? datain[7:4] : datain[3:0]; + end + +reg [ 5:0] aon_sr, aoff_sr; + +reg [7:0] aon_cmd_cpy; + +always @(posedge clk) if(cen) begin + if( up_aon ) aon_cmd_cpy <= aon_cmd; else if(cur_ch[5] && cen6) aon_cmd_cpy <= 8'd0; +end + +always @(posedge clk) if(cen6) begin + if( cur_ch[5] ) begin + aon_sr <= ~{6{aon_cmd_cpy[7]}} & aon_cmd_cpy[5:0]; + aoff_sr <= {6{aon_cmd_cpy[7]}} & aon_cmd_cpy[5:0]; + end else begin + aon_sr <= { 1'b0, aon_sr[5:1] }; + aoff_sr <= { 1'b0, aoff_sr[5:1] }; + end +end + +reg match; // high when cur_ch==en_ch, but calculated one clock cycle ahead + // so it can be latched +wire [5:0] cur_next = { cur_ch[4:0], cur_ch[5] }; +wire [5:0] en_next = {en_ch[4:0], en_ch[5] }; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + cur_ch <= 6'b1; en_ch <= 6'b1; + match <= 0; + end else if( cen6 ) begin + cur_ch <= cur_next; + if( cur_ch[5] ) en_ch <= en_next; + match <= cur_next == (cur_ch[5] ? en_next : en_ch); + end + +wire [15:0] start_top, end_top; + +wire clr_dec, decon; + +jt10_adpcm_cnt u_cnt( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen6 ), + // Pipeline + .cur_ch ( cur_ch ), + .en_ch ( en_ch ), + // START/END update + .addr_in ( addr_in ), + .addr_ch ( up_addr ), + .up_start ( up_start ), + .up_end ( up_end ), + // Control + .aon ( aon_sr[0] ), + .aoff ( aoff_sr[0] ), + .clr ( clr_dec ), + // ROM driver + .addr_out ( addr ), + .bank ( bank ), + .sel ( nibble_sel ), + .roe_n ( roe_n ), + .decon ( decon ), + // Flags + .flags ( flags ), + .clr_flags ( clr_flags ), + .start_top ( start_top ), + .end_top ( end_top ) +); + +// wire chactive = chon & cen6; +wire signed [15:0] pcmdec; + +jt10_adpcm u_decoder( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen6 ), + .data ( data ), + .chon ( decon ), + .clr ( clr_dec ), + .pcm ( pcmdec ) +); +/* + +always @(posedge clk) begin + if( cen3 && chon ) begin + pcm55_l <= pre_pcm55_l; + pcm55_r <= pre_pcm55_r; + end +end +*/ + +wire [1:0] lr; + +jt10_adpcm_gain u_gain( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen6 ), + // Pipeline + .cur_ch ( cur_ch ), + .en_ch ( en_ch ), + .match ( match ), + // Gain control + .atl ( atl ), // ADPCM Total Level + .lracl ( lracl_in ), + .up_ch ( up_lracl ), + + .lr ( lr ), + .pcm_in ( pcmdec ), + .pcm_att( pcm_att ) +); + +wire signed [15:0] pre_pcm55_l, pre_pcm55_r; + +assign pcm55_l = pre_pcm55_l; +assign pcm55_r = pre_pcm55_r; + +jt10_adpcm_acc u_acc_left( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen6 ), + // Pipeline + .cur_ch ( cur_ch ), + .en_ch ( en_ch ), + .match ( match ), + // left/right enable + .en_sum ( lr[1] ), + + .pcm_in ( pcm_att ), // 18.5 kHz + .pcm_out( pre_pcm55_l ) // 55.5 kHz +); + +jt10_adpcm_acc u_acc_right( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen6 ), + // Pipeline + .cur_ch ( cur_ch ), + .en_ch ( en_ch ), + .match ( match ), + // left/right enable + .en_sum ( lr[0] ), + + .pcm_in ( pcm_att ), // 18.5 kHz + .pcm_out( pre_pcm55_r ) // 55.5 kHz +); + + +`ifdef SIMULATION +integer fch0, fch1, fch2, fch3, fch4, fch5; +initial begin + fch0 = $fopen("ch0.dec","w"); + fch1 = $fopen("ch1.dec","w"); + fch2 = $fopen("ch2.dec","w"); + fch3 = $fopen("ch3.dec","w"); + fch4 = $fopen("ch4.dec","w"); + fch5 = $fopen("ch5.dec","w"); +end + +reg signed [15:0] pcm_ch0, pcm_ch1, pcm_ch2, pcm_ch3, pcm_ch4, pcm_ch5; +always @(posedge cen6) if(en_ch[0]) begin + if(cur_ch[0]) begin + pcm_ch0 <= pcmdec; + $fwrite( fch0, "%d\n", pcmdec ); + end + if(cur_ch[1]) begin + pcm_ch1 <= pcmdec; + $fwrite( fch1, "%d\n", pcmdec ); + end + if(cur_ch[2]) begin + pcm_ch2 <= pcmdec; + $fwrite( fch2, "%d\n", pcmdec ); + end + if(cur_ch[3]) begin + pcm_ch3 <= pcmdec; + $fwrite( fch3, "%d\n", pcmdec ); + end + if(cur_ch[4]) begin + pcm_ch4 <= pcmdec; + $fwrite( fch4, "%d\n", pcmdec ); + end + if(cur_ch[5]) begin + pcm_ch5 <= pcmdec; + $fwrite( fch5, "%d\n", pcmdec ); + end +end + +reg [15:0] sim_start0, sim_start1, sim_start2, sim_start3, sim_start4, sim_start5; +reg [15:0] sim_end0, sim_end1, sim_end2, sim_end3, sim_end4, sim_end5; +reg [ 7:0] sim_lracl0, sim_lracl1, sim_lracl2, sim_lracl3, sim_lracl4, sim_lracl5; +/* +reg div3b; +reg [2:0] chframe; +always @(posedge clk) div3b<=div3; +always @(negedge div3b) chframe <= chfast; + + +reg [7:0] aon_cpy, aon_cpy2; +always @(posedge clk) begin + aon_cpy<=aon_cmd; // This prevents a Verilator circular-logic warning + aon_cpy2 <= aon_cmd; +end + +always @(posedge aon_cpy[0]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 0 - %X",sim_start0); +always @(posedge aon_cpy[1]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 1 - %X",sim_start1); +always @(posedge aon_cpy[2]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 2 - %X",sim_start2); +always @(posedge aon_cpy[3]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 3 - %X",sim_start3); +always @(posedge aon_cpy[4]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 4 - %X",sim_start4); +always @(posedge aon_cpy[5]) if(!aon_cpy2[7]) $display("INFO: ADPCM-A ON 5 - %X",sim_start5); +*/ +always @(posedge cen6) if(up_start) + case(up_addr) + 3'd0: sim_start0 <= addr_in; + 3'd1: sim_start1 <= addr_in; + 3'd2: sim_start2 <= addr_in; + 3'd3: sim_start3 <= addr_in; + 3'd4: sim_start4 <= addr_in; + 3'd5: sim_start5 <= addr_in; + default:; + endcase // up_addr + +always @(posedge cen6) if(up_end) + case(up_addr) + 3'd0: sim_end0 <= addr_in; + 3'd1: sim_end1 <= addr_in; + 3'd2: sim_end2 <= addr_in; + 3'd3: sim_end3 <= addr_in; + 3'd4: sim_end4 <= addr_in; + 3'd5: sim_end5 <= addr_in; + default:; + endcase // up_addr + +always @(posedge cen6) + case(up_lracl) + 3'd0: sim_lracl0 <= lracl_in; + 3'd1: sim_lracl1 <= lracl_in; + 3'd2: sim_lracl2 <= lracl_in; + 3'd3: sim_lracl3 <= lracl_in; + 3'd4: sim_lracl4 <= lracl_in; + 3'd5: sim_lracl5 <= lracl_in; + default:; + endcase // up_addr + + /* +reg start_error, end_error; +always @(posedge cen6) begin + case(chframe) + 3'd0: start_error <= start_top != sim_start0; + 3'd1: start_error <= start_top != sim_start1; + 3'd2: start_error <= start_top != sim_start2; + 3'd3: start_error <= start_top != sim_start3; + 3'd4: start_error <= start_top != sim_start4; + 3'd5: start_error <= start_top != sim_start5; + default:; + endcase + case(chframe) + 3'd0: end_error <= end_top != sim_end0; + 3'd1: end_error <= end_top != sim_end1; + 3'd2: end_error <= end_top != sim_end2; + 3'd3: end_error <= end_top != sim_end3; + 3'd4: end_error <= end_top != sim_end4; + 3'd5: end_error <= end_top != sim_end5; + default:; + endcase +end +*/ +`endif + +endmodule // jt10_adpcm_drvA \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v new file mode 100644 index 00000000..8c1ccd9a --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v @@ -0,0 +1,124 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt10_adpcm_drvB( + input rst_n, + input clk, + input cen, // 8MHz cen + input cen55, // clk & cen55 = 55 kHz + // Control + input acmd_on_b, // Control - Process start, Key On + input acmd_rep_b, // Control - Repeat + input acmd_rst_b, // Control - Reset + input [ 1:0] alr_b, // Left / Right + input [15:0] astart_b, // Start address + input [15:0] aend_b, // End address + input [15:0] adeltan_b, // Delta-N + input [ 7:0] aeg_b, // Envelope Generator Control + output flag, + input clr_flag, + // memory + output [23:0] addr, + input [ 7:0] data, + output roe_n, + + output reg signed [15:0] pcm55_l, + output reg signed [15:0] pcm55_r +); + +wire nibble_sel; +wire adv; // advance to next reading + +// `ifdef SIMULATION +// real fsample; +// always @(posedge acmd_on_b) begin +// fsample = adeltan_b; +// fsample = fsample/65536; +// fsample = fsample * 55.5; +// $display("\nINFO: ADPCM-B ON: %X delta N = %6d (%2.1f kHz)", astart_b, adeltan_b, fsample ); +// end +// `endif + +always @(posedge clk) roe_n <= ~adv; + +jt10_adpcmb_cnt u_cnt( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen55 ), + .delta_n ( adeltan_b ), + .clr ( acmd_rst_b ), + .on ( acmd_on_b ), + .astart ( astart_b ), + .aend ( aend_b ), + .arepeat ( acmd_rep_b ), + .addr ( addr ), + .nibble_sel ( nibble_sel ), + // Flag control + .clr_flag ( clr_flag ), + .flag ( flag ), + .adv ( adv ) +); + +reg [3:0] din; + +always @(posedge clk) din <= !nibble_sel ? data[7:4] : data[3:0]; + +wire signed [15:0] pcmdec, pcminter, pcmgain; + +jt10_adpcmb u_decoder( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen ), + .adv ( adv & cen55 ), + .data ( din ), + .chon ( acmd_on_b ), + .pcm ( pcmdec ) +); + +`ifndef NOBINTERPOL +jt10_adpcmb_interpol u_interpol( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen ), + .cen55 ( cen55 ), + .adv ( adv ), + .pcmdec ( pcmdec ), + .pcmout ( pcminter ) +); +`else +assign pcminter = pcmdec; +`endif + +jt10_adpcmb_gain u_gain( + .rst_n ( rst_n ), + .clk ( clk ), + .cen55 ( cen55 ), + .tl ( aeg_b ), + .pcm_in ( pcminter ), + .pcm_out( pcmgain ) +); + +always @(posedge clk) if(cen55) begin + pcm55_l <= alr_b[1] ? pcmgain : 16'd0; + pcm55_r <= alr_b[0] ? pcmgain : 16'd0; +end + +endmodule // jt10_adpcm_drvB \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v new file mode 100644 index 00000000..06aba776 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v @@ -0,0 +1,130 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Sampling rates: 2kHz ~ 55.5 kHz. in 0.85Hz steps + +module jt10_adpcm_dt( + input rst_n, + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [3:0] data, + input chon, // high if this channel is on + output signed [15:0] pcm +); + +localparam stepw = 15; + +reg signed [15:0] x1, x2, x3, x4, x5, x6; +reg [stepw-1:0] step1, step2, step6; +reg [stepw+1:0] step3, step4, step5; +assign pcm = x2; + +reg [18:0] d2l; +reg [15:0] d3,d4; +reg [3:0] d2; +reg sign2, sign3, sign4, sign5; +reg [7:0] step_val; +reg [22:0] step2l; + +always @(*) begin + casez( d2[3:1] ) + 3'b0_??: step_val = 8'd57; + 3'b1_00: step_val = 8'd77; + 3'b1_01: step_val = 8'd102; + 3'b1_10: step_val = 8'd128; + 3'b1_11: step_val = 8'd153; + endcase // data[2:0] + d2l = d2 * step2; // 4 + 15 = 19 bits -> div by 8 -> 16 bits + step2l = step_val * step2; // 15 bits + 8 bits = 23 bits -> div 64 -> 17 bits +end + +// Original pipeline: 6 stages, 6 channels take 36 clock cycles +// 8 MHz -> /12 divider -> 666 kHz +// 666 kHz -> 18.5 kHz = 55.5/3 kHz + +reg chon2, chon3, chon4, chon5; +reg signEqu4, signEqu5; +reg [3:0] data2; + +always @( posedge clk or negedge rst_n ) + if( ! rst_n ) begin + x1 <= 'd0; step1 <= 'd127; + x2 <= 'd0; step2 <= 'd127; + x3 <= 'd0; step3 <= 'd127; + x4 <= 'd0; step4 <= 'd127; + x5 <= 'd0; step5 <= 'd127; + x6 <= 'd0; step6 <= 'd127; + d2 <= 'd0; d3 <= 'd0; d4 <= 'd0; + sign2 <= 'b0; + sign3 <= 'b0; + sign4 <= 'b0; sign5 <= 'b0; + chon2 <= 'b0; chon3 <= 'b0; chon4 <= 'b0; chon5 <= 1'b0; + end else if(cen) begin + // I + d2 <= {data[2:0],1'b1}; + sign2 <= data[3]; + data2 <= data; + x2 <= x1; + step2 <= step1; + chon2 <= chon; + // II multiply and obtain the offset + d3 <= d2l[18:3]; // 16 bits + sign3 <= sign2; + x3 <= x2; + step3 <= step2l[22:6]; + chon3 <= chon2; + // III 2's complement of d3 if necessary + d4 <= sign3 ? ~d3+16'b1 : d3; + sign4 <= sign3; + signEqu4 <= sign3 == x3[15]; + x4 <= x3; + step4 <= step3; + chon4 <= chon3; + // IV Advance the waveform + x5 <= x4+d4; + sign5 <= sign4; + signEqu5 <= signEqu4; + step5 <= step4; + chon5 <= chon4; + // V: limit or reset outputs + if( chon5 ) begin + if( signEqu5 && (sign5!=x5[15]) ) + x6 <= sign5 ? 16'h8000 : 16'h7FFF; + else + x6 <= x5; + + if( step5 < 127 ) + step6 <= 15'd127; + else if( step5 > 24576 ) + step6 <= 15'd24576; + else + step6 <= step5[14:0]; + end else begin + x6 <= 'd0; + step6 <= 'd127; + end + // VI: close the loop + x1 <= x6; + step1 <= step6; + end + + +endmodule // jt10_adpcm \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v new file mode 100644 index 00000000..61cd327f --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v @@ -0,0 +1,176 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt10_adpcm_gain( + input rst_n, + input clk, // CPU clock + input cen, // 666 kHz + // pipeline channel + input [5:0] cur_ch, + input [5:0] en_ch, + input match, + + input [5:0] atl, // ADPCM Total Level + // Gain update + input [7:0] lracl, + input [2:0] up_ch, + // Data + output [1:0] lr, + input signed [15:0] pcm_in, + output signed [15:0] pcm_att +); + +reg [5:0] up_ch_dec; +always @(*) + case(up_ch) + 3'd0: up_ch_dec = 6'b000_001; + 3'd1: up_ch_dec = 6'b000_010; + 3'd2: up_ch_dec = 6'b000_100; + 3'd3: up_ch_dec = 6'b001_000; + 3'd4: up_ch_dec = 6'b010_000; + 3'd5: up_ch_dec = 6'b100_000; + default: up_ch_dec = 6'd0; + endcase + +wire [5:0] en_ch2 = { en_ch[4:0], en_ch[5] }; // shift the bits to fit in the pipeline slot correctly + +reg [6:0] db5; +always @(*) + case( db5[2:0] ) + 3'd0: lin_5b = 10'd512; + 3'd1: lin_5b = 10'd470; + 3'd2: lin_5b = 10'd431; + 3'd3: lin_5b = 10'd395; + 3'd4: lin_5b = 10'd362; + 3'd5: lin_5b = 10'd332; + 3'd6: lin_5b = 10'd305; + 3'd7: lin_5b = 10'd280; + endcase + +reg [7:0] lracl1, lracl2, lracl3, lracl4, lracl5, lracl6; +reg [9:0] lin_5b, lin1, lin2, lin6; +reg [3:0] sh1, sh6; + +// dB to linear conversion +assign lr = lracl1[7:6]; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + lracl1 <= 8'd0; lracl2 <= 8'd0; + lracl3 <= 8'd0; lracl4 <= 8'd0; + lracl5 <= 8'd0; lracl6 <= 8'd0; + db5 <= 'd0; + sh1 <= 4'd0; sh6 <= 4'd0; + lin1 <= 10'd0; + lin6 <= 10'd0; + end else if(cen) begin + + // I + lracl2 <= up_ch_dec == cur_ch ? lracl : lracl1; + // II + lracl3 <= lracl2; + // III + lracl4 <= lracl3; + // IV: new data is accepted here + lracl5 <= lracl4; + db5 <= { 1'b0, ~lracl4[5:0] } + {1'b0, ~atl}; + // V + lracl6 <= lracl5; + lin6 <= lin_5b; + sh6 <= db5[6:3]; + // VI close the loop + lracl1 <= lracl6; + lin1 <= sh6[3] ? 10'h0 : lin6; + sh1 <= sh6; + end + +// Apply gain +// The pipeline has 6 stages, there is new input data once every 6*6=36 clock cycles +// New data is read once and it takes 4*6 cycles to get through because the shift +// operation is distributed among several iterations. This prevents the need of +// a 10x16-input mux which is very large. Instead of that, this uses two 10x2-input mux'es +// which iterated allow the max 16 shift operation + +reg [3:0] shcnt1, shcnt2, shcnt3, shcnt4, shcnt5, shcnt6; + +reg shcnt_mod3, shcnt_mod4, shcnt_mod5; +reg [31:0] pcm2_mul; +wire signed [15:0] lin2s = {6'b0,lin2}; + +always @(*) begin + shcnt_mod3 = shcnt3 != 0; + shcnt_mod4 = shcnt4 != 0; + shcnt_mod5 = shcnt5 != 0; + pcm2_mul = pcm2 * lin2s; +end + +reg signed [15:0] pcm1, pcm2, pcm3, pcm4, pcm5, pcm6; +reg match2; + +assign pcm_att = pcm1; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + pcm1 <= 'd0; pcm2 <= 'd0; + pcm3 <= 'd0; pcm4 <= 'd0; + pcm5 <= 'd0; pcm6 <= 'd0; + shcnt1 <= 'd0; shcnt2 <= 'd0; + shcnt3 <= 'd0; shcnt4 <= 'd0; + shcnt5 <= 'd0; shcnt6 <= 'd0; + end else if(cen) begin + // I + pcm2 <= match ? pcm_in : pcm1; + lin2 <= lin1; + shcnt2 <= match ? sh1 : shcnt1; + match2 <= match; + // II + pcm3 <= match2 ? pcm2_mul[24:9] : pcm2; + shcnt3 <= shcnt2; + // III, shift by 0 or 1 + if( shcnt_mod3 ) begin + pcm4 <= pcm3>>>1; + shcnt4 <= shcnt3-1; + end else begin + pcm4 <= pcm3; + shcnt4 <= shcnt3; + end + // IV, shift by 0 or 1 + if( shcnt_mod4 ) begin + pcm5 <= pcm4>>>1; + shcnt5 <= shcnt4-1; + end else begin + pcm5 <= pcm4; + shcnt5 <= shcnt4; + end + // V, shift by 0 or 1 + if( shcnt_mod5 ) begin + pcm6 <= pcm5>>>1; + shcnt6 <= shcnt5-1; + end else begin + pcm6 <= pcm5; + shcnt6 <= shcnt5; + end + // VI close the loop and output + pcm1 <= pcm6; + shcnt1 <= shcnt6; + end + +endmodule // jt10_adpcm_gain diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v new file mode 100644 index 00000000..138dff4c --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v @@ -0,0 +1,142 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// ADPCM-A uses a LUT because it is very sensitive to rounding +// it looks like the original algorithm also used a table + +module jt10_adpcma_lut( + input clk, // CPU clock + input rst_n, + input cen, + input [8:0] addr, // = {step,delta}; + output reg [11:0] inc +); + +reg [11:0] lut[0:391]; + +initial begin +lut[9'o00_0] = 12'd0002; lut[9'o00_1] = 12'd0006; lut[9'o00_2] = 12'd0012; lut[9'o00_3] = 12'd0016; +lut[9'o00_4] = 12'd0022; lut[9'o00_5] = 12'd0026; lut[9'o00_6] = 12'd0032; lut[9'o00_7] = 12'd0036; +lut[9'o01_0] = 12'd0002; lut[9'o01_1] = 12'd0006; lut[9'o01_2] = 12'd0012; lut[9'o01_3] = 12'd0016; +lut[9'o01_4] = 12'd0023; lut[9'o01_5] = 12'd0027; lut[9'o01_6] = 12'd0033; lut[9'o01_7] = 12'd0037; +lut[9'o02_0] = 12'd0002; lut[9'o02_1] = 12'd0007; lut[9'o02_2] = 12'd0013; lut[9'o02_3] = 12'd0020; +lut[9'o02_4] = 12'd0025; lut[9'o02_5] = 12'd0032; lut[9'o02_6] = 12'd0036; lut[9'o02_7] = 12'd0043; +lut[9'o03_0] = 12'd0002; lut[9'o03_1] = 12'd0007; lut[9'o03_2] = 12'd0015; lut[9'o03_3] = 12'd0022; +lut[9'o03_4] = 12'd0027; lut[9'o03_5] = 12'd0034; lut[9'o03_6] = 12'd0042; lut[9'o03_7] = 12'd0047; +lut[9'o04_0] = 12'd0002; lut[9'o04_1] = 12'd0010; lut[9'o04_2] = 12'd0016; lut[9'o04_3] = 12'd0024; +lut[9'o04_4] = 12'd0031; lut[9'o04_5] = 12'd0037; lut[9'o04_6] = 12'd0045; lut[9'o04_7] = 12'd0053; +lut[9'o05_0] = 12'd0003; lut[9'o05_1] = 12'd0011; lut[9'o05_2] = 12'd0017; lut[9'o05_3] = 12'd0025; +lut[9'o05_4] = 12'd0034; lut[9'o05_5] = 12'd0042; lut[9'o05_6] = 12'd0050; lut[9'o05_7] = 12'd0056; +lut[9'o06_0] = 12'd0003; lut[9'o06_1] = 12'd0012; lut[9'o06_2] = 12'd0021; lut[9'o06_3] = 12'd0030; +lut[9'o06_4] = 12'd0037; lut[9'o06_5] = 12'd0046; lut[9'o06_6] = 12'd0055; lut[9'o06_7] = 12'd0064; +lut[9'o07_0] = 12'd0003; lut[9'o07_1] = 12'd0013; lut[9'o07_2] = 12'd0023; lut[9'o07_3] = 12'd0033; +lut[9'o07_4] = 12'd0042; lut[9'o07_5] = 12'd0052; lut[9'o07_6] = 12'd0062; lut[9'o07_7] = 12'd0072; +lut[9'o10_0] = 12'd0004; lut[9'o10_1] = 12'd0014; lut[9'o10_2] = 12'd0025; lut[9'o10_3] = 12'd0035; +lut[9'o10_4] = 12'd0046; lut[9'o10_5] = 12'd0056; lut[9'o10_6] = 12'd0067; lut[9'o10_7] = 12'd0077; +lut[9'o11_0] = 12'd0004; lut[9'o11_1] = 12'd0015; lut[9'o11_2] = 12'd0027; lut[9'o11_3] = 12'd0040; +lut[9'o11_4] = 12'd0051; lut[9'o11_5] = 12'd0062; lut[9'o11_6] = 12'd0074; lut[9'o11_7] = 12'd0105; +lut[9'o12_0] = 12'd0005; lut[9'o12_1] = 12'd0017; lut[9'o12_2] = 12'd0031; lut[9'o12_3] = 12'd0043; +lut[9'o12_4] = 12'd0056; lut[9'o12_5] = 12'd0070; lut[9'o12_6] = 12'd0102; lut[9'o12_7] = 12'd0114; +lut[9'o13_0] = 12'd0005; lut[9'o13_1] = 12'd0020; lut[9'o13_2] = 12'd0034; lut[9'o13_3] = 12'd0047; +lut[9'o13_4] = 12'd0062; lut[9'o13_5] = 12'd0075; lut[9'o13_6] = 12'd0111; lut[9'o13_7] = 12'd0124; +lut[9'o14_0] = 12'd0006; lut[9'o14_1] = 12'd0022; lut[9'o14_2] = 12'd0037; lut[9'o14_3] = 12'd0053; +lut[9'o14_4] = 12'd0070; lut[9'o14_5] = 12'd0104; lut[9'o14_6] = 12'd0121; lut[9'o14_7] = 12'd0135; +lut[9'o15_0] = 12'd0006; lut[9'o15_1] = 12'd0024; lut[9'o15_2] = 12'd0042; lut[9'o15_3] = 12'd0060; +lut[9'o15_4] = 12'd0075; lut[9'o15_5] = 12'd0113; lut[9'o15_6] = 12'd0131; lut[9'o15_7] = 12'd0147; +lut[9'o16_0] = 12'd0007; lut[9'o16_1] = 12'd0026; lut[9'o16_2] = 12'd0045; lut[9'o16_3] = 12'd0064; +lut[9'o16_4] = 12'd0103; lut[9'o16_5] = 12'd0122; lut[9'o16_6] = 12'd0141; lut[9'o16_7] = 12'd0160; +lut[9'o17_0] = 12'd0010; lut[9'o17_1] = 12'd0030; lut[9'o17_2] = 12'd0051; lut[9'o17_3] = 12'd0071; +lut[9'o17_4] = 12'd0112; lut[9'o17_5] = 12'd0132; lut[9'o17_6] = 12'd0153; lut[9'o17_7] = 12'd0173; +lut[9'o20_0] = 12'd0011; lut[9'o20_1] = 12'd0033; lut[9'o20_2] = 12'd0055; lut[9'o20_3] = 12'd0077; +lut[9'o20_4] = 12'd0122; lut[9'o20_5] = 12'd0144; lut[9'o20_6] = 12'd0166; lut[9'o20_7] = 12'd0210; +lut[9'o21_0] = 12'd0012; lut[9'o21_1] = 12'd0036; lut[9'o21_2] = 12'd0062; lut[9'o21_3] = 12'd0106; +lut[9'o21_4] = 12'd0132; lut[9'o21_5] = 12'd0156; lut[9'o21_6] = 12'd0202; lut[9'o21_7] = 12'd0226; +lut[9'o22_0] = 12'd0013; lut[9'o22_1] = 12'd0041; lut[9'o22_2] = 12'd0067; lut[9'o22_3] = 12'd0115; +lut[9'o22_4] = 12'd0143; lut[9'o22_5] = 12'd0171; lut[9'o22_6] = 12'd0217; lut[9'o22_7] = 12'd0245; +lut[9'o23_0] = 12'd0014; lut[9'o23_1] = 12'd0044; lut[9'o23_2] = 12'd0074; lut[9'o23_3] = 12'd0124; +lut[9'o23_4] = 12'd0155; lut[9'o23_5] = 12'd0205; lut[9'o23_6] = 12'd0235; lut[9'o23_7] = 12'd0265; +lut[9'o24_0] = 12'd0015; lut[9'o24_1] = 12'd0050; lut[9'o24_2] = 12'd0102; lut[9'o24_3] = 12'd0135; +lut[9'o24_4] = 12'd0170; lut[9'o24_5] = 12'd0223; lut[9'o24_6] = 12'd0255; lut[9'o24_7] = 12'd0310; +lut[9'o25_0] = 12'd0016; lut[9'o25_1] = 12'd0054; lut[9'o25_2] = 12'd0111; lut[9'o25_3] = 12'd0147; +lut[9'o25_4] = 12'd0204; lut[9'o25_5] = 12'd0242; lut[9'o25_6] = 12'd0277; lut[9'o25_7] = 12'd0335; +lut[9'o26_0] = 12'd0020; lut[9'o26_1] = 12'd0060; lut[9'o26_2] = 12'd0121; lut[9'o26_3] = 12'd0161; +lut[9'o26_4] = 12'd0222; lut[9'o26_5] = 12'd0262; lut[9'o26_6] = 12'd0323; lut[9'o26_7] = 12'd0363; +lut[9'o27_0] = 12'd0021; lut[9'o27_1] = 12'd0065; lut[9'o27_2] = 12'd0131; lut[9'o27_3] = 12'd0175; +lut[9'o27_4] = 12'd0240; lut[9'o27_5] = 12'd0304; lut[9'o27_6] = 12'd0350; lut[9'o27_7] = 12'd0414; +lut[9'o30_0] = 12'd0023; lut[9'o30_1] = 12'd0072; lut[9'o30_2] = 12'd0142; lut[9'o30_3] = 12'd0211; +lut[9'o30_4] = 12'd0260; lut[9'o30_5] = 12'd0327; lut[9'o30_6] = 12'd0377; lut[9'o30_7] = 12'd0446; +lut[9'o31_0] = 12'd0025; lut[9'o31_1] = 12'd0100; lut[9'o31_2] = 12'd0154; lut[9'o31_3] = 12'd0227; +lut[9'o31_4] = 12'd0302; lut[9'o31_5] = 12'd0355; lut[9'o31_6] = 12'd0431; lut[9'o31_7] = 12'd0504; +lut[9'o32_0] = 12'd0027; lut[9'o32_1] = 12'd0107; lut[9'o32_2] = 12'd0166; lut[9'o32_3] = 12'd0246; +lut[9'o32_4] = 12'd0325; lut[9'o32_5] = 12'd0405; lut[9'o32_6] = 12'd0464; lut[9'o32_7] = 12'd0544; +lut[9'o33_0] = 12'd0032; lut[9'o33_1] = 12'd0116; lut[9'o33_2] = 12'd0202; lut[9'o33_3] = 12'd0266; +lut[9'o33_4] = 12'd0353; lut[9'o33_5] = 12'd0437; lut[9'o33_6] = 12'd0523; lut[9'o33_7] = 12'd0607; +lut[9'o34_0] = 12'd0034; lut[9'o34_1] = 12'd0126; lut[9'o34_2] = 12'd0217; lut[9'o34_3] = 12'd0311; +lut[9'o34_4] = 12'd0402; lut[9'o34_5] = 12'd0474; lut[9'o34_6] = 12'd0565; lut[9'o34_7] = 12'd0657; +lut[9'o35_0] = 12'd0037; lut[9'o35_1] = 12'd0136; lut[9'o35_2] = 12'd0236; lut[9'o35_3] = 12'd0335; +lut[9'o35_4] = 12'd0434; lut[9'o35_5] = 12'd0533; lut[9'o35_6] = 12'd0633; lut[9'o35_7] = 12'd0732; +lut[9'o36_0] = 12'd0042; lut[9'o36_1] = 12'd0150; lut[9'o36_2] = 12'd0256; lut[9'o36_3] = 12'd0364; +lut[9'o36_4] = 12'd0471; lut[9'o36_5] = 12'd0577; lut[9'o36_6] = 12'd0705; lut[9'o36_7] = 12'd1013; +lut[9'o37_0] = 12'd0046; lut[9'o37_1] = 12'd0163; lut[9'o37_2] = 12'd0277; lut[9'o37_3] = 12'd0414; +lut[9'o37_4] = 12'd0531; lut[9'o37_5] = 12'd0646; lut[9'o37_6] = 12'd0762; lut[9'o37_7] = 12'd1077; +lut[9'o40_0] = 12'd0052; lut[9'o40_1] = 12'd0176; lut[9'o40_2] = 12'd0322; lut[9'o40_3] = 12'd0446; +lut[9'o40_4] = 12'd0573; lut[9'o40_5] = 12'd0717; lut[9'o40_6] = 12'd1043; lut[9'o40_7] = 12'd1167; +lut[9'o41_0] = 12'd0056; lut[9'o41_1] = 12'd0213; lut[9'o41_2] = 12'd0347; lut[9'o41_3] = 12'd0504; +lut[9'o41_4] = 12'd0641; lut[9'o41_5] = 12'd0776; lut[9'o41_6] = 12'd1132; lut[9'o41_7] = 12'd1267; +lut[9'o42_0] = 12'd0063; lut[9'o42_1] = 12'd0231; lut[9'o42_2] = 12'd0377; lut[9'o42_3] = 12'd0545; +lut[9'o42_4] = 12'd0713; lut[9'o42_5] = 12'd1061; lut[9'o42_6] = 12'd1227; lut[9'o42_7] = 12'd1375; +lut[9'o43_0] = 12'd0070; lut[9'o43_1] = 12'd0250; lut[9'o43_2] = 12'd0430; lut[9'o43_3] = 12'd0610; +lut[9'o43_4] = 12'd0771; lut[9'o43_5] = 12'd1151; lut[9'o43_6] = 12'd1331; lut[9'o43_7] = 12'd1511; +lut[9'o44_0] = 12'd0075; lut[9'o44_1] = 12'd0271; lut[9'o44_2] = 12'd0464; lut[9'o44_3] = 12'd0660; +lut[9'o44_4] = 12'd1053; lut[9'o44_5] = 12'd1247; lut[9'o44_6] = 12'd1442; lut[9'o44_7] = 12'd1636; +lut[9'o45_0] = 12'd0104; lut[9'o45_1] = 12'd0314; lut[9'o45_2] = 12'd0524; lut[9'o45_3] = 12'd0734; +lut[9'o45_4] = 12'd1144; lut[9'o45_5] = 12'd1354; lut[9'o45_6] = 12'd1564; lut[9'o45_7] = 12'd1774; +lut[9'o46_0] = 12'd0112; lut[9'o46_1] = 12'd0340; lut[9'o46_2] = 12'd0565; lut[9'o46_3] = 12'd1013; +lut[9'o46_4] = 12'd1240; lut[9'o46_5] = 12'd1466; lut[9'o46_6] = 12'd1713; lut[9'o46_7] = 12'd2141; +lut[9'o47_0] = 12'd0122; lut[9'o47_1] = 12'd0366; lut[9'o47_2] = 12'd0633; lut[9'o47_3] = 12'd1077; +lut[9'o47_4] = 12'd1344; lut[9'o47_5] = 12'd1610; lut[9'o47_6] = 12'd2055; lut[9'o47_7] = 12'd2321; +lut[9'o50_0] = 12'd0132; lut[9'o50_1] = 12'd0417; lut[9'o50_2] = 12'd0704; lut[9'o50_3] = 12'd1171; +lut[9'o50_4] = 12'd1456; lut[9'o50_5] = 12'd1743; lut[9'o50_6] = 12'd2230; lut[9'o50_7] = 12'd2515; +lut[9'o51_0] = 12'd0143; lut[9'o51_1] = 12'd0452; lut[9'o51_2] = 12'd0761; lut[9'o51_3] = 12'd1270; +lut[9'o51_4] = 12'd1577; lut[9'o51_5] = 12'd2106; lut[9'o51_6] = 12'd2415; lut[9'o51_7] = 12'd2724; +lut[9'o52_0] = 12'd0155; lut[9'o52_1] = 12'd0510; lut[9'o52_2] = 12'd1043; lut[9'o52_3] = 12'd1376; +lut[9'o52_4] = 12'd1731; lut[9'o52_5] = 12'd2264; lut[9'o52_6] = 12'd2617; lut[9'o52_7] = 12'd3152; +lut[9'o53_0] = 12'd0170; lut[9'o53_1] = 12'd0551; lut[9'o53_2] = 12'd1131; lut[9'o53_3] = 12'd1512; +lut[9'o53_4] = 12'd2073; lut[9'o53_5] = 12'd2454; lut[9'o53_6] = 12'd3034; lut[9'o53_7] = 12'd3415; +lut[9'o54_0] = 12'd0204; lut[9'o54_1] = 12'd0615; lut[9'o54_2] = 12'd1226; lut[9'o54_3] = 12'd1637; +lut[9'o54_4] = 12'd2250; lut[9'o54_5] = 12'd2661; lut[9'o54_6] = 12'd3272; lut[9'o54_7] = 12'd3703; +lut[9'o55_0] = 12'd0221; lut[9'o55_1] = 12'd0665; lut[9'o55_2] = 12'd1330; lut[9'o55_3] = 12'd1774; +lut[9'o55_4] = 12'd2437; lut[9'o55_5] = 12'd3103; lut[9'o55_6] = 12'd3546; lut[9'o55_7] = 12'd3777; +lut[9'o56_0] = 12'd0240; lut[9'o56_1] = 12'd0740; lut[9'o56_2] = 12'd1441; lut[9'o56_3] = 12'd2141; +lut[9'o56_4] = 12'd2642; lut[9'o56_5] = 12'd3342; lut[9'o56_6] = 12'd3777; lut[9'o56_7] = 12'd3777; +lut[9'o57_0] = 12'd0260; lut[9'o57_1] = 12'd1021; lut[9'o57_2] = 12'd1561; lut[9'o57_3] = 12'd2322; +lut[9'o57_4] = 12'd3063; lut[9'o57_5] = 12'd3624; lut[9'o57_6] = 12'd3777; lut[9'o57_7] = 12'd3777; +lut[9'o60_0] = 12'd0302; lut[9'o60_1] = 12'd1106; lut[9'o60_2] = 12'd1712; lut[9'o60_3] = 12'd2516; +lut[9'o60_4] = 12'd3322; lut[9'o60_5] = 12'd3777; lut[9'o60_6] = 12'd3777; lut[9'o60_7] = 12'd3777; +end + +always @(posedge clk or negedge rst_n) + if(!rst_n) + inc <= 'd0; + else if(cen) + inc <= lut[addr]; + +endmodule // jt10_adpcma_lut \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v new file mode 100644 index 00000000..a17c754a --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v @@ -0,0 +1,112 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Sampling rates: 2kHz ~ 55.5 kHz. in 0.85Hz steps + +module jt10_adpcmb( + input rst_n, + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [3:0] data, + input chon, // high if this channel is on + input adv, + output signed [15:0] pcm +); + +localparam stepw = 15, xw=16; + +reg signed [xw-1:0] x1, next_x5; +reg [stepw-1:0] step1; +reg [stepw+1:0] next_step3; +assign pcm = x1[xw-1:xw-16]; + +wire [xw-1:0] limpos = {1'b0, {xw-1{1'b1}}}; +wire [xw-1:0] limneg = {1'b1, {xw-1{1'b0}}}; + +reg [18:0] d2l; +reg [xw-1:0] d3,d4; +reg [3:0] d2; +reg [7:0] step_val; +reg [22:0] step2l; + +always @(*) begin + casez( d2[3:1] ) + 3'b0_??: step_val = 8'd57; + 3'b1_00: step_val = 8'd77; + 3'b1_01: step_val = 8'd102; + 3'b1_10: step_val = 8'd128; + 3'b1_11: step_val = 8'd153; + endcase + d2l = d2 * step1; // 4 + 15 = 19 bits -> div by 8 -> 16 bits + step2l = step_val * step1; // 15 bits + 8 bits = 23 bits -> div 64 -> 17 bits +end + +// Original pipeline: 6 stages, 6 channels take 36 clock cycles +// 8 MHz -> /12 divider -> 666 kHz +// 666 kHz -> 18.5 kHz = 55.5/3 kHz + +reg [3:0] data2; +reg sign_data; + +reg [3:0] adv2; + +always @( posedge clk or negedge rst_n ) + if( ! rst_n ) begin + x1 <= 'd0; step1 <= 'd127; + d2 <= 'd0; d3 <= 'd0; d4 <= 'd0; + end else if(cen) begin + adv2 <= {1'b0,adv2[3:1]}; + // I + if( adv ) begin + d2 <= {data[2:0],1'b1}; + sign_data <= data[3]; + adv2[3] <= 1'b1; + end + // II multiply and obtain the offset + d3 <= { {xw-16{1'b0}}, d2l[18:3] }; // xw bits + next_step3<= step2l[22:6]; + // III 2's complement of d3 if necessary + d4 <= sign_data ? ~d3+1 : d3; + // IV Advance the waveform + next_x5 <= x1+d4; + // V: limit or reset outputs + if( chon ) begin // update values if needed + if( adv2[0] ) begin + if( sign_data == x1[xw-1] && (x1[xw-1]!=next_x5[xw-1]) ) + x1 <= x1[xw-1] ? limneg : limpos; + else + x1 <= next_x5; + + if( next_step3 < 127 ) + step1 <= 15'd127; + else if( next_step3 > 24576 ) + step1 <= 15'd24576; + else + step1 <= next_step3[14:0]; + end + end else begin + x1 <= 'd0; + step1 <= 'd127; + end + end + + +endmodule // jt10_adpcm \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v new file mode 100644 index 00000000..9491edc0 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v @@ -0,0 +1,108 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// ADPCM-B counter + +module jt10_adpcmb_cnt( + input rst_n, + input clk, // CPU clock + input cen, // clk & cen = 55 kHz + + // counter control + input [15:0] delta_n, + input clr, + input on, + // Address + input [15:0] astart, + input [15:0] aend, + input arepeat, + output reg [23:0] addr, + output reg nibble_sel, + // Flag + output reg flag, + input clr_flag, + + output reg adv +); + +// Counter +reg [15:0] cnt; + +always @(posedge clk or negedge rst_n) + if(!rst_n) begin + cnt <= 'd0; + adv <= 'b0; + end else if(cen) begin + if( clr ) begin + cnt <= 'd0; + adv <= 'b0; + end else begin + if( on ) + {adv, cnt} <= {1'b0, cnt} + {1'b0, delta_n }; + else + adv <= 1'b1; // let the rest of the signal chain advance + // when channel is off so all registers go to reset values + end + end + +reg set_flag, last_set; + +always @(posedge clk or negedge rst_n) + if(!rst_n) begin + flag <= 1'b0; + last_set <= 'b0; + end else begin + last_set <= set_flag; + if( clr_flag ) flag <= 1'b0; + if( !last_set && set_flag ) flag <= 1'b1; + end + +// Address +reg last_on; + +always @(posedge clk or negedge rst_n) + if(!rst_n) begin + addr <= 'd0; + nibble_sel <= 'b0; + set_flag <= 'd0; + end else if(cen) begin + last_on <= on; + + if( (on && !last_on) || clr ) begin + addr <= {astart,8'd0}; + nibble_sel <= 'b0; + end else if( on && adv ) begin + if( addr[23:8] < aend ) begin + { addr, nibble_sel } <= { addr, nibble_sel } + 25'd1; + set_flag <= 'd0; + end + else begin + set_flag <= 'd1; + if(arepeat) begin + addr <= {astart,8'd0}; + nibble_sel <= 'b0; + end + end + end + end // cen + + +endmodule // jt10_adpcmb_cnt \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v new file mode 100644 index 00000000..e501c7d8 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v @@ -0,0 +1,39 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Gain is assumed to be 0.75dB per bit. + +module jt10_adpcmb_gain( + input rst_n, + input clk, // CPU clock + input cen55, + input [ 7:0] tl, // ADPCM Total Level + input signed [15:0] pcm_in, + output reg signed [15:0] pcm_out +); + +wire signed [15:0] factor = {8'd0, tl}; +wire signed [31:0] pcm_mul = pcm_in * factor; // linear gain + +always @(posedge clk) if(cen55) + pcm_out <= pcm_mul[23:8]; + +endmodule // jt10_adpcm_gain diff --git a/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v new file mode 100644 index 00000000..02d91543 --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v @@ -0,0 +1,96 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt10_adpcmb_interpol( + input rst_n, + input clk, + input cen, // 8MHz cen + input cen55, // clk & cen55 = 55 kHz + input adv, + input signed [15:0] pcmdec, + output signed [15:0] pcmout +); + +localparam stages=6; + +reg signed [15:0] pcmlast, delta_x; +reg signed [16:0] pre_dx; +reg start_div=1'b0; +reg [3:0] deltan, pre_dn; +reg [stages-1:0] adv2; +reg signed [15:0] pcminter; +wire [15:0] step, next_step; +reg step_sign, next_step_sign; + +assign pcmout = pcminter; + +always @(posedge clk) if(cen) begin + adv2 <= {adv2[stages-2:0], cen55 & adv }; // give some time to get the data from memory +end + +always @(posedge clk) if(cen55) begin + if ( adv ) begin + pre_dn <= 'd1; + deltan <= pre_dn; + end else + pre_dn <= pre_dn + 1; +end + + +always @(posedge clk) if(cen) begin + start_div <= 1'b0; + if(adv2[1]) begin + pcmlast <= pcmdec; + pcminter <= pcmlast; + end + if(adv2[4]) begin + pre_dx <= { pcmdec[15], pcmdec } - { pcmlast[15], pcmlast }; + end + if( adv2[5] ) begin + start_div <= 1'b1; + delta_x <= pre_dx[16] ? ~pre_dx[15:0]+1 : pre_dx[15:0]; + next_step_sign <= pre_dx[16]; + end +end + +always @(posedge clk) if(cen55) begin + if( adv ) begin + step <= next_step; + step_sign <= next_step_sign; + pcminter <= pcmlast; + end + else pcminter <= step_sign ? pcminter - step : pcminter + step; +end + +jt10_adpcm_div #(.dw(16)) u_div( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen ), + .start ( start_div ), + .a ( delta_x ), + .b ( {12'd0, deltan } ), + .d ( next_step ), + .r ( ), + .working( ) +); + + +endmodule // jt10_adpcmb_interpol \ No newline at end of file diff --git a/common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v b/common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v new file mode 100644 index 00000000..393665ba --- /dev/null +++ b/common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v @@ -0,0 +1,59 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// Let a fixed number of clock enable pulses to pass through + +module jt10_cen_burst #(parameter cntmax=3'd6, cntw=3)( + input rst_n, + input clk, + input cen, // 8MHz cen + input start, + input start_cen, + output cen_out +); + +reg [cntw-1:0] cnt; +reg last_start; +reg pass; + +always @(posedge clk or negedge rst_n) + if( !rst_n ) begin + cnt <= {cntw{1'b1}}; + pass <= 1'b0; + end else if(cen) begin + last_start <= start; + if( start && start_cen ) begin + cnt <= 'd0; + pass <= 1'b1; + end else begin + if(cnt != cntmax ) cnt <= cnt+1; + else pass <= 1'b0; + end + end + +reg pass_negedge; +assign cen_out = cen & pass_negedge; + +always @(negedge clk) begin + pass_negedge <= pass; +end + +endmodule // jt10_cen_burst \ No newline at end of file diff --git a/common/Sound/JT12/hdl/alt/eg_cnt.v b/common/Sound/JT12/hdl/alt/eg_cnt.v new file mode 100644 index 00000000..8e838b8c --- /dev/null +++ b/common/Sound/JT12/hdl/alt/eg_cnt.v @@ -0,0 +1,84 @@ +/* +Using two large case statements: ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_cnt/ | | 9/13 | 13/19 | 15/18 | 0/3 | 0/0 | 0/0 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | eg_cnt | +| +u_cntsh | | 4/4 | 6/6 | 3/3 | 3/3 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_cnt/u_cntsh | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Using one large case statement: ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_cnt/ | | 8/11 | 13/19 | 12/15 | 0/3 | 0/0 | 0/0 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | eg_cnt | +| +u_cntsh | | 3/3 | 6/6 | 3/3 | 3/3 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_cnt/u_cntsh | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +*/ + +module eg_cnt( + input clk, + input clk_en, + input rst, + input [14:0] eg_cnt, + input [2:0] state_IV, + input [5:0] rate_IV, + + output reg [2:0] state_V, + output reg [5:0] rate_V, + output [2:0] cnt_V, + output reg sum_up +); + +localparam ATTACK=3'd0, DECAY1=3'd1, DECAY2=3'd2, RELEASE=3'd7, HOLD=3'd3; +wire [2:0] cnt_out; +assign cnt_V = cnt_out; +reg lsb; +reg [2:0] cnt_in; +reg [3:0] mux_sel; + +always @(*) begin + mux_sel = (state_IV == ATTACK && rate_IV[5:2]!=4'hf) ? (rate_IV[5:2]+4'd1): rate_IV[5:2]; + case( mux_sel ) + 4'h0: lsb = eg_cnt[12]; + 4'h1: lsb = eg_cnt[11]; + 4'h2: lsb = eg_cnt[10]; + 4'h3: lsb = eg_cnt[ 9]; + 4'h4: lsb = eg_cnt[ 8]; + 4'h5: lsb = eg_cnt[ 7]; + 4'h6: lsb = eg_cnt[ 6]; + 4'h7: lsb = eg_cnt[ 5]; + 4'h8: lsb = eg_cnt[ 4]; + 4'h9: lsb = eg_cnt[ 3]; + 4'ha: lsb = eg_cnt[ 2]; + 4'hb: lsb = eg_cnt[ 1]; + default: lsb = eg_cnt[ 0]; + endcase + cnt_in =lsb!=cnt_out ? (cnt_out+3'd1) : cnt_out; +end + +always @(posedge clk) if( clk_en ) begin + if( rst ) begin + state_V <= RELEASE; + rate_V <= 6'h1F; // should it be 6'h3F? TODO + //cnt_V<= 3'd0; + end + else begin + state_V <= state_IV; + rate_V <= rate_IV; + end +end + +jt12_sh/*_rst*/ #( .width(3), .stages(24) ) u_cntsh( + .clk ( clk ), + .clk_en ( clk_en ), +// .rst ( rst ), + .din ( cnt_in ), + .drop ( cnt_out ) +); + +always @(posedge clk) + if( clk_en ) + sum_up <= lsb!=cnt_out; + +endmodule // eg_mux \ No newline at end of file diff --git a/common/Sound/JT12/hdl/alt/eg_comb.v b/common/Sound/JT12/hdl/alt/eg_comb.v new file mode 100644 index 00000000..7f127669 --- /dev/null +++ b/common/Sound/JT12/hdl/alt/eg_comb.v @@ -0,0 +1,184 @@ +/* ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_comb/ | | 49/49 | 0/0 | 153/153 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_comb | +| eg_comb/ | | 42/42 | 0/0 | 134/134 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_comb | +| eg_comb/ | | 39/39 | 0/0 | 129/129 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_comb | +| eg_comb/ | | 43/43 | 0/0 | 122/122 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_comb | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +This module represents all the envelope generator calculations. +Everything is combinational. The testbench ver/eg2 checks the +functionality of this module. + +*/ + +module eg_comb( + input attack, + input [ 4:0] base_rate, + input [ 4:0] keycode, + input [14:0] eg_cnt, + input cnt_in, + input [ 1:0] ks, + input [ 9:0] eg_in, + input [ 6:0] lfo_mod, + input amsen, + input [ 1:0] ams, + input [ 6:0] tl, + output cnt_lsb, + output reg [9:0] eg_limited, + output reg [9:0] eg_pure +); + +reg [6:0] pre_rate; +reg [5:0] rate; + +always @(*) begin : pre_rate_calc + if( base_rate == 5'd0 ) + pre_rate = 7'd0; + else + case( ks ) + 2'd3: pre_rate = { base_rate, 1'b0 } + { 1'b0, keycode }; + 2'd2: pre_rate = { base_rate, 1'b0 } + { 2'b0, keycode[4:1] }; + 2'd1: pre_rate = { base_rate, 1'b0 } + { 3'b0, keycode[4:2] }; + 2'd0: pre_rate = { base_rate, 1'b0 } + { 4'b0, keycode[4:3] }; + endcase +end + +always @(*) + rate = pre_rate[6] ? 6'd63 : pre_rate[5:0]; + +reg [2:0] cnt; + +reg [4:0] mux_sel; +always @(*) begin + mux_sel = attack ? (rate[5:2]+4'd1): {1'b0,rate[5:2]}; +end // always @(*) + +always @(*) + case( mux_sel ) + 5'h0: cnt = eg_cnt[14:12]; + 5'h1: cnt = eg_cnt[13:11]; + 5'h2: cnt = eg_cnt[12:10]; + 5'h3: cnt = eg_cnt[11: 9]; + 5'h4: cnt = eg_cnt[10: 8]; + 5'h5: cnt = eg_cnt[ 9: 7]; + 5'h6: cnt = eg_cnt[ 8: 6]; + 5'h7: cnt = eg_cnt[ 7: 5]; + 5'h8: cnt = eg_cnt[ 6: 4]; + 5'h9: cnt = eg_cnt[ 5: 3]; + 5'ha: cnt = eg_cnt[ 4: 2]; + 5'hb: cnt = eg_cnt[ 3: 1]; + default: cnt = eg_cnt[ 2: 0]; + endcase + +//////////////////////////////// +reg step; +reg [7:0] step_idx; + +always @(*) begin : rate_step + if( rate[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x + if( rate[5:2]==4'hf && attack) + step_idx = 8'b11111111; // Maximum attack speed, rates 60&61 + else + case( rate[1:0] ) + 2'd0: step_idx = 8'b00000000; + 2'd1: step_idx = 8'b10001000; // 2 + 2'd2: step_idx = 8'b10101010; // 4 + 2'd3: step_idx = 8'b11101110; // 6 + endcase + end + else begin + if( rate[5:2]==4'd0 && !attack) + step_idx = 8'b11111110; // limit slowest decay rate + else + case( rate[1:0] ) + 2'd0: step_idx = 8'b10101010; // 4 + 2'd1: step_idx = 8'b11101010; // 5 + 2'd2: step_idx = 8'b11101110; // 6 + 2'd3: step_idx = 8'b11111110; // 7 + endcase + end + // a rate of zero keeps the level still + step = rate[5:1]==5'd0 ? 1'b0 : step_idx[ cnt ]; +end + +reg sum_up; +assign cnt_lsb = cnt[0]; +always @(*) begin + sum_up = cnt[0] != cnt_in; +end +////////////////////////////////////////////////////////////// +// cnt/cnt_lsb/cnt_in not used below this point + +reg [3:0] dr_sum; +reg [10:0] dr_result; + +always @(*) begin + case( rate[5:2] ) + 4'b1100: dr_sum = { 2'b0, step, ~step }; // 12 + 4'b1101: dr_sum = { 1'b0, step, ~step, 1'b0 }; // 13 + 4'b1110: dr_sum = { step, ~step, 2'b0 }; // 14 + 4'b1111: dr_sum = 4'd8;// 15 + default: dr_sum = { 2'b0, step, 1'b0 }; + endcase + dr_result = {6'd0, dr_sum} + eg_in; +end + +reg [ 7:0] ar_sum0; +reg [ 8:0] ar_sum1; +reg [10:0] ar_result; +reg [ 9:0] ar_sum; + +always @(*) begin : ar_calculation + casez( rate[5:2] ) + default: ar_sum0 = {2'd0, eg_in[9:4]}; + 4'b1101: ar_sum0 = {1'd0, eg_in[9:3]}; + 4'b111?: ar_sum0 = eg_in[9:2]; + endcase + ar_sum1 = ar_sum0+9'd1; + if( rate[5:4] == 2'b11 ) + ar_sum = step ? { ar_sum1, 1'b0 } : { 1'b0, ar_sum1 }; + else + ar_sum = step ? { 1'b0, ar_sum1 } : 10'd0; + ar_result = rate[5:1]==5'h1F ? 11'd0 : eg_in-ar_sum; +end +/////////////////////////////////////////////////////////// +// rate not used below this point +always @(*) begin + if(sum_up) begin + if( attack ) + eg_pure = ar_result[10] ? 10'd0: ar_result[9:0]; + else + eg_pure = dr_result[10] ? 10'h3FF : dr_result[9:0]; + end + else eg_pure = eg_in; +end + +////////////////////////////////////////////////////////////// +reg [ 8:0] am_final; +reg [10:0] sum_eg_tl; +reg [11:0] sum_eg_tl_am; +reg [ 5:0] am_inverted; + +always @(*) begin + am_inverted = lfo_mod[6] ? ~lfo_mod[5:0] : lfo_mod[5:0]; +end + +always @(*) begin + casez( {amsen, ams } ) + default: am_final = 9'd0; + 3'b1_01: am_final = { 5'd0, am_inverted[5:2] }; + 3'b1_10: am_final = { 3'd0, am_inverted }; + 3'b1_11: am_final = { 2'd0, am_inverted, 1'b0 }; + endcase + sum_eg_tl = { tl, 3'd0 } + eg_pure; + sum_eg_tl_am = sum_eg_tl + { 3'd0, am_final }; +end + +always @(*) + eg_limited = sum_eg_tl_am[11:10]==2'd0 ? sum_eg_tl_am[9:0] : 10'h3ff; + + +endmodule // eg_comb \ No newline at end of file diff --git a/common/Sound/JT12/hdl/alt/eg_mux.v b/common/Sound/JT12/hdl/alt/eg_mux.v new file mode 100644 index 00000000..6e59c212 --- /dev/null +++ b/common/Sound/JT12/hdl/alt/eg_mux.v @@ -0,0 +1,79 @@ +/* +Using two large case statements: ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_mux/ | | 11/12 | 13/14 | 31/31 | 1/1 | 0/0 | 0/0 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | eg_mux | +| +u_cntsh | | 1/1 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_mux/u_cntsh | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +Using one large case statement: ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_mux/ | | 11/12 | 13/14 | 21/21 | 1/1 | 0/0 | 0/0 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | eg_mux | +| +u_cntsh | | 1/1 | 1/1 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_mux/u_cntsh | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +*/ + +module eg_mux( + input clk, + input clk_en, + input rst, + input [14:0] eg_cnt, + input [2:0] state_IV, + input [5:0] rate_IV, + + output reg [2:0] state_V, + output reg [5:0] rate_V, + output reg [2:0] cnt_V, + output reg sum_up +); + +localparam ATTACK=3'd0, DECAY1=3'd1, DECAY2=3'd2, RELEASE=3'd7, HOLD=3'd3; +wire cnt_out; +reg [3:0] mux_sel; + +always @(*) begin + mux_sel = (state_IV == ATTACK && rate_IV[5:2]!=4'hf) ? (rate_IV[5:2]+4'd1): rate_IV[5:2]; +end // always @(*) + +always @(posedge clk) if( clk_en ) begin + if( rst ) begin + state_V <= RELEASE; + rate_V <= 6'h1F; // should it be 6'h3F? TODO + //cnt_V<= 3'd0; + end + else begin + state_V <= state_IV; + rate_V <= rate_IV; + case( mux_sel ) + 4'h0: cnt_V <= eg_cnt[14:12]; + 4'h1: cnt_V <= eg_cnt[13:11]; + 4'h2: cnt_V <= eg_cnt[12:10]; + 4'h3: cnt_V <= eg_cnt[11: 9]; + 4'h4: cnt_V <= eg_cnt[10: 8]; + 4'h5: cnt_V <= eg_cnt[ 9: 7]; + 4'h6: cnt_V <= eg_cnt[ 8: 6]; + 4'h7: cnt_V <= eg_cnt[ 7: 5]; + 4'h8: cnt_V <= eg_cnt[ 6: 4]; + 4'h9: cnt_V <= eg_cnt[ 5: 3]; + 4'ha: cnt_V <= eg_cnt[ 4: 2]; + 4'hb: cnt_V <= eg_cnt[ 3: 1]; + default: cnt_V <= eg_cnt[ 2: 0]; + endcase + end +end + +jt12_sh/*_rst*/ #( .width(1), .stages(24) ) u_cntsh( + .clk ( clk ), + .clk_en ( clk_en ), +// .rst ( rst ), + .din ( cnt_V[0] ), + .drop ( cnt_out ) +); + +always @(posedge clk) + if( clk_en ) + sum_up <= cnt_V[0] != cnt_out; + +endmodule // eg_mux \ No newline at end of file diff --git a/common/Sound/JT12/hdl/alt/eg_step.v b/common/Sound/JT12/hdl/alt/eg_step.v new file mode 100644 index 00000000..a06614f6 --- /dev/null +++ b/common/Sound/JT12/hdl/alt/eg_step.v @@ -0,0 +1,46 @@ +/* ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_step/ | | 3/3 | 0/0 | 7/7 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_step | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +*/ + +module eg_step( + input [2:0] state_V, + input [5:0] rate_V, + input [2:0] cnt_V, + output reg step_V +); + +localparam ATTACK=3'd0, DECAY1=3'd1, DECAY2=3'd2, RELEASE=3'd7, HOLD=3'd3; +reg [7:0] step_idx; + +always @(*) begin : rate_step + if( rate_V[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x + if( rate_V[5:2]==4'hf && state_V == ATTACK) + step_idx = 8'b11111111; // Maximum attack speed, rates 60&61 + else + case( rate_V[1:0] ) + 2'd0: step_idx = 8'b00000000; + 2'd1: step_idx = 8'b10001000; // 2 + 2'd2: step_idx = 8'b10101010; // 4 + 2'd3: step_idx = 8'b11101110; // 6 + endcase + end + else begin + if( rate_V[5:2]==4'd0 && state_V != ATTACK) + step_idx = 8'b11111110; // limit slowest decay rate_IV + else + case( rate_V[1:0] ) + 2'd0: step_idx = 8'b10101010; // 4 + 2'd1: step_idx = 8'b11101010; // 5 + 2'd2: step_idx = 8'b11101110; // 6 + 2'd3: step_idx = 8'b11111110; // 7 + endcase + end + // a rate_IV of zero keeps the level still + step_V = rate_V[5:1]==5'd0 ? 1'b0 : step_idx[ cnt_V ]; +end + +endmodule // eg_step \ No newline at end of file diff --git a/common/Sound/JT12/hdl/alt/eg_step_ram.v b/common/Sound/JT12/hdl/alt/eg_step_ram.v new file mode 100644 index 00000000..ea701ebc --- /dev/null +++ b/common/Sound/JT12/hdl/alt/eg_step_ram.v @@ -0,0 +1,45 @@ +/* ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Module | Partition | Slices* | Slice Reg | LUTs | LUTRAM | BRAM/FIFO | DSP48A1 | BUFG | BUFIO | BUFR | DCM | PLL_ADV | Full Hierarchical | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| eg_step_ram/ | | 3/3 | 0/0 | 7/7 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | 0/0 | eg_step | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +*/ + +module eg_step_ram( + input [2:0] state_V, + input [5:0] rate_V, + input [2:0] cnt_V, + output reg step_V +); + +localparam ATTACK=3'd0, DECAY1=3'd1, DECAY2=3'd2, RELEASE=3'd7, HOLD=3'd3; +reg [7:0] step_idx; +reg [7:0] step_ram; + +always @(*) + case( { rate_V[5:4]==2'b11, rate_V[1:0]} ) + 3'd0: step_ram = 8'b00000000; + 3'd1: step_ram = 8'b10001000; // 2 + 3'd2: step_ram = 8'b10101010; // 4 + 3'd3: step_ram = 8'b11101110; // 6 + 3'd4: step_ram = 8'b10101010; // 4 + 3'd5: step_ram = 8'b11101010; // 5 + 3'd6: step_ram = 8'b11101110; // 6 + 3'd7: step_ram = 8'b11111110; // 7 + endcase + +always @(*) begin : rate_step + if( rate_V[5:2]==4'hf && state_V == ATTACK) + step_idx = 8'b11111111; // Maximum attack speed, rates 60&61 + else + if( rate_V[5:2]==4'd0 && state_V != ATTACK) + step_idx = 8'b11111110; // limit slowest decay rate_IV + else + step_idx = step_ram; + // a rate_IV of zero keeps the level still + step_V = rate_V[5:1]==5'd0 ? 1'b0 : step_idx[ cnt_V ]; +end + +endmodule // eg_step \ No newline at end of file diff --git a/common/Sound/JT12/hdl/dac/jt12_dac.v b/common/Sound/JT12/hdl/dac/jt12_dac.v new file mode 100644 index 00000000..6fb6ed0e --- /dev/null +++ b/common/Sound/JT12/hdl/dac/jt12_dac.v @@ -0,0 +1,56 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 9th 2017 + */ + +`timescale 1ns / 1ps + +/* + + input sampling rate must be the same as clk frequency + interpolation the input signal accordingly to get the + right sampling rate + +*/ + +module jt12_dac #(parameter width=12) +( + input clk, + input rst, + input signed [width-1:0] din, + output dout +); +localparam acc_w = width+1; + +reg [width-1:0] nosign; +reg [acc_w-1:0] acc; +wire [acc_w-2:0] err = acc[acc_w-2:0]; + +assign dout = acc[acc_w-1]; + +always @(posedge clk) +if( rst ) begin + acc <= {(acc_w){1'b0}}; + nosign <= {width{1'b0}}; +end +else begin + nosign <= { ~din[width-1], din[width-2:0] }; + acc <= nosign + err; +end + +endmodule diff --git a/common/Sound/JT12/hdl/dac/jt12_dac2.v b/common/Sound/JT12/hdl/dac/jt12_dac2.v new file mode 100644 index 00000000..08f7af41 --- /dev/null +++ b/common/Sound/JT12/hdl/dac/jt12_dac2.v @@ -0,0 +1,63 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: March, 9th 2017 + */ + +`timescale 1ns / 1ps + +/* + + input sampling rate must be the same as clk frequency + interpolate input signal accordingly to get the + right sampling rate. + + Refer to sigmadelta.ods to see how the internal width (int_w) + was determined. + +*/ + +module jt12_dac2 #(parameter width=12) +( + input clk, + input rst, + input signed [width-1:0] din, + output reg dout +); + +localparam int_w = width+5; + +reg [int_w-1:0] y, error, error_1, error_2; + +wire [width-1:0] undin = { ~din[width-1], din[width-2:0] }; + +always @(*) begin + y = undin + { error_1, 1'b0} - error_2; + dout = ~y[int_w-1]; + error = y - {dout, {width{1'b0}}}; +end + +always @(posedge clk) + if( rst ) begin + error_1 <= {int_w{1'b0}}; + error_2 <= {int_w{1'b0}}; + end else begin + error_1 <= error; + error_2 <= error_1; + end + +endmodule diff --git a/common/Sound/JT12/hdl/deprecated/jt12_amp.v b/common/Sound/JT12/hdl/deprecated/jt12_amp.v new file mode 100644 index 00000000..ddb9c401 --- /dev/null +++ b/common/Sound/JT12/hdl/deprecated/jt12_amp.v @@ -0,0 +1,172 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 23-2-2017 + +*/ + + + +`timescale 1ns / 1ps + +module jt12_amp( + input clk, + input rst, + input sample, + input [2:0] volume, + + input signed [13:0] pre, + output reg signed [15:0] post +); + +wire signed [14:0] x2 = pre<<<1; +wire signed [15:0] x3 = x2+pre; +wire signed [15:0] x4 = pre<<<2; +//wire signed [16:0] x5 = x4+pre; +wire signed [16:0] x6 = x4+x2; +//wire signed [16:0] x7 = x4+x3; +wire signed [16:0] x8 = pre<<<3; +wire signed [17:0] x12 = x8+x4; +wire signed [17:0] x16 = pre<<<4; + +always @(posedge clk) +if( rst ) + post <= 16'd0; +else +if( sample ) + case( volume ) + 3'd0: // /2 + post <= { {2{pre[13]}}, pre }; + 3'd1: // x1 + post <= { x2[14], x2 }; + 3'd2: // x2 + post <= { x2, 1'd0 }; + /* + 3'd3: // x3 + case( x3[15:14] ) + 2'b00, 2'b11: post <= { x3[14:0], 1'd0 }; + 2'b01: post <= 16'h7FFF; + 2'b10: post <= 16'h8000; + endcase + */ + 3'd3: // x4 + post <= x4; + /* + 3'd5: // x5 + case( x5[16:15] ) + 2'b00, 2'b11: post <= x5[15:0]; + 2'b01: post <= 16'h7FFF; + 2'b10: post <= 16'h8000; + endcase + */ + 3'd4: // x6 + casex( x6[16:15] ) + 2'b00, 2'b11: post <= x6[15:0]; + 2'b0x: post <= 16'h7FFF; + 2'b1x: post <= 16'h8000; + endcase +/* + 3'd7: // x7 + case( x7[16:15] ) + 2'b00, 2'b11: post <= x7[15:0]; + 2'b01: post <= 16'h7FFF; + 2'b10: post <= 16'h8000; + endcase +*/ + 3'd5: // x8 + casex( x8[16:15] ) + 2'b00, 2'b11: post <= x8[15:0]; + 2'b0x: post <= 16'h7FFF; + 2'b1x: post <= 16'h8000; + endcase + 3'd6: // x12 + casex( x12[17:15] ) + 3'b000, 3'b111: post <= x12[15:0]; + 3'b0xx: post <= 16'h7FFF; + 3'b1xx: post <= 16'h8000; + endcase + 3'd7: // x16 + casex( x16[17:15] ) + 3'b000, 3'b111: post <= x16[15:0]; + 3'b0xx: post <= 16'h7FFF; + 3'b1xx: post <= 16'h8000; + endcase + endcase + +endmodule + +module jt12_amp_stereo( + input clk, + input rst, + input sample, + + input [ 5:0] psg, + input enable_psg, + + input signed [11:0] fmleft, + input signed [11:0] fmright, + input [2:0] volume, + + output signed [15:0] postleft, + output signed [15:0] postright +); + +wire signed [13:0] preleft; +wire signed [13:0] preright; + +// psg, 6'd0 suena muy fuerte +// According to Nemesis: +// All 4 PSG channels at max combined is equivalent to the maximum output of a single YM2612 channel at max. +// A single channel at max is 11'd255 + +//wire signed [5:0] psgm = psg-6'h20; +//wire signed [8:0] psg_dac = psgm<<<3; +//wire signed [12:0] psg_sum = {13{enable_psg}} & { {3{psg_dac[8]}}, psg_dac }; + +//wire signed [5:0] psgm = psg-6'h20; +wire signed [8:0] psg_dac = psg<<<3; + +//wire signed [12:0] psg_sum = {13{enable_psg}} & { 3'b0, psg_dac }; +wire signed [12:0] psg_sum = {13{enable_psg}} & { 2'b0, psg_dac, 1'b0 }; + + +assign preleft = { fmleft [11], fmleft, 1'd0 } + psg_sum; +assign preright= { fmright[11],fmright, 1'd0 } + psg_sum; + +jt12_amp amp_left( + .clk ( clk ), + .rst ( rst ), + .sample ( sample ), + .pre ( preleft ), + .post ( postleft ), + .volume ( volume ) +); + +jt12_amp amp_right( + .clk ( clk ), + .rst ( rst ), + .sample ( sample ), + .pre ( preright ), + .post ( postright ), + .volume ( volume ) +); + +endmodule diff --git a/common/Sound/JT12/hdl/deprecated/jt12_mod24.v b/common/Sound/JT12/hdl/deprecated/jt12_mod24.v new file mode 100644 index 00000000..0d5568a1 --- /dev/null +++ b/common/Sound/JT12/hdl/deprecated/jt12_mod24.v @@ -0,0 +1,14 @@ +`timescale 1ns / 1ps + +module jt12_mod24( + input [4:0] base, + input [3:0] extra, + output [4:0] mod +); + +wire [5:0] sum = base+extra; +wire [4:0] wrap = base+extra-5'd24; + +assign mod = sum > 6'd23 ? wrap : sum[4:0]; + +endmodule diff --git a/common/Sound/JT12/hdl/deprecated/jt12_mod6.v b/common/Sound/JT12/hdl/deprecated/jt12_mod6.v new file mode 100644 index 00000000..c64f25af --- /dev/null +++ b/common/Sound/JT12/hdl/deprecated/jt12_mod6.v @@ -0,0 +1,52 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 19-3-2017 + +*/ + + +module jt12_mod6 +( + input [2:0] in, // only 0 to 5 are valid entries + input [2:0] sum, + output reg [2:0] out // output between 0 to 5 +); + +reg [3:0] aux; + +always @(*) begin + aux <= in+sum; + case( aux ) + 4'd6: out <= 3'd0; + 4'd7: out <= 3'd1; + 4'd8: out <= 3'd2; + 4'd9: out <= 3'd3; + 4'ha: out <= 3'd4; + 4'hb: out <= 3'd5; + 4'hc: out <= 3'd0; + 4'he: out <= 3'd1; + 4'hf: out <= 3'd2; + default: out <= aux; + endcase +end + +endmodule diff --git a/common/Sound/JT12/hdl/deprecated/jt12_opram.v b/common/Sound/JT12/hdl/deprecated/jt12_opram.v new file mode 100644 index 00000000..d695a17a --- /dev/null +++ b/common/Sound/JT12/hdl/deprecated/jt12_opram.v @@ -0,0 +1,45 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +module jt12_opram +( + input [4:0] wr_addr, + input [4:0] rd_addr, + input clk, + input clk_en, + input [43:0] data, + output reg [43:0] q +); + + reg [43:0] ram[31:0]; + + always @ (posedge clk) if(clk_en) begin + q <= ram[rd_addr]; + ram[wr_addr] <= data; + end + +endmodule diff --git a/common/Sound/JT12/hdl/jt03.qip b/common/Sound/JT12/hdl/jt03.qip new file mode 100644 index 00000000..649ed30c --- /dev/null +++ b/common/Sound/JT12/hdl/jt03.qip @@ -0,0 +1,35 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03.v ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) jt12.vhd ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_top.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_single_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_csr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_logsin.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_dout.v ] + diff --git a/common/Sound/JT12/hdl/jt03.v b/common/Sound/JT12/hdl/jt03.v new file mode 100644 index 00000000..6a7fed86 --- /dev/null +++ b/common/Sound/JT12/hdl/jt03.v @@ -0,0 +1,97 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-12-2018 +*/ + +// Wrapper to output only combined channels. Defaults to YM2203 mode. + + + +module jt03( + input rst, // rst should be at least 6 clk&cen cycles long + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [7:0] din, + input addr, + input cs_n, + input wr_n, + + output [7:0] dout, + output irq_n, + // I/O pins used by YM2203 embedded YM2149 chip + input [7:0] IOA_in, + input [7:0] IOB_in, + output [7:0] IOA_out, + output [7:0] IOB_out, + // Separated output + output [ 7:0] psg_A, + output [ 7:0] psg_B, + output [ 7:0] psg_C, + output signed [15:0] fm_snd, + // combined output + output [ 9:0] psg_snd, + output signed [15:0] snd, + output snd_sample +); + +jt12_top #( + .use_lfo(0),.use_ssg(1), .num_ch(3), .use_pcm(0), .use_adpcm(0) ) +u_jt12( + .rst ( rst ), // rst should be at least 6 clk&cen cycles long + .clk ( clk ), // CPU clock + .cen ( cen ), // optional clock enable, it not needed leave as 1'b1 + .din ( din ), + .addr ( {1'b0, addr} ), + .cs_n ( cs_n ), + .wr_n ( wr_n ), + + .dout ( dout ), + .irq_n ( irq_n ), + // YM2203 I/O pins + .IOA_out ( IOA_out ), + .IOB_out ( IOB_out ), + .IOA_in ( IOA_in ), + .IOB_in ( IOB_in ), + // Unused ADPCM pins + .en_hifi_pcm ( 1'b0 ), // used only on YM2612 mode + .adpcma_addr ( ), // real hardware has 10 pins multiplexed through RMPX pin + .adpcma_bank ( ), + .adpcma_roe_n ( ), // ADPCM-A ROM output enable + .adpcma_data ( 8'd0 ), // Data from RAM + .adpcmb_data ( 8'd0 ), + .adpcmb_addr ( ), // real hardware has 12 pins multiplexed through PMPX pin + .adpcmb_roe_n ( ), // ADPCM-B ROM output enable + // Separated output + .psg_A ( psg_A ), + .psg_B ( psg_B ), + .psg_C ( psg_C ), + .psg_snd ( psg_snd ), + .fm_snd_left ( fm_snd ), + .fm_snd_right (), + .adpcmA_l (), + .adpcmA_r (), + .adpcmB_l (), + .adpcmB_r (), + + .snd_right ( snd ), + .snd_left (), + .snd_sample ( snd_sample ) +); + +endmodule // jt03 diff --git a/common/Sound/JT12/hdl/jt03_acc.v b/common/Sound/JT12/hdl/jt03_acc.v new file mode 100644 index 00000000..d57419f9 --- /dev/null +++ b/common/Sound/JT12/hdl/jt03_acc.v @@ -0,0 +1,73 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-11-2018 + +*/ + +`timescale 1ns / 1ps + +// Use for YM2203 +// no left/right channels +// full operator resolution +// clamped to maximum output of signed 16 bits +// This version does not clamp each channel individually +// That does not correspond to real hardware behaviour. I should +// change it. + +module jt03_acc +( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input signed [13:0] op_result, + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + input zero, + input [2:0] alg, + // combined output + output signed [15:0] snd +); + +reg sum_en; + +always @(*) begin + case ( alg ) + default: sum_en = s4_enters; + 3'd4: sum_en = s2_enters | s4_enters; + 3'd5,3'd6: sum_en = ~s1_enters; + 3'd7: sum_en = 1'b1; + endcase +end + +localparam res=18; +wire [res-1:0] hires; +assign snd = hires[res-1:res-16]; + +jt12_single_acc #(.win(14),.wout(res)) u_mono( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( op_result ), + .sum_en ( sum_en ), + .zero ( zero ), + .snd ( hires ) +); + +endmodule diff --git a/common/Sound/JT12/hdl/jt03_fm.qip b/common/Sound/JT12/hdl/jt03_fm.qip new file mode 100644 index 00000000..312a4cc6 --- /dev/null +++ b/common/Sound/JT12/hdl/jt03_fm.qip @@ -0,0 +1,33 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03.v ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) jt12.vhd ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_top.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_single_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_csr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_logsin.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ] diff --git a/common/Sound/JT12/hdl/jt10.qip b/common/Sound/JT12/hdl/jt10.qip new file mode 100644 index 00000000..ba4076b3 --- /dev/null +++ b/common/Sound/JT12/hdl/jt10.qip @@ -0,0 +1,63 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt10.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_top.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_single_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_csr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_logsin.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pcm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_genmix.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_decim.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_interpol.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_fm_uprate.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_dout.v ] +# SSG +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_exp.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_noise.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ../jt49/hdl/jt49_cen.v ] +# ADPCM +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcma_lut.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcmb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcmb_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcmb_gain.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_dbrom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_drvA.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_drvB.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_gain.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_cen_burst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcmb_interpol.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt10_acc.v ] diff --git a/common/Sound/JT12/hdl/jt10.v b/common/Sound/JT12/hdl/jt10.v new file mode 100644 index 00000000..38ebb87f --- /dev/null +++ b/common/Sound/JT12/hdl/jt10.v @@ -0,0 +1,97 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +// YM2610 wrapper +// Clock enabled at 7.5 - 8.5MHz + +module jt10( + input rst, // rst should be at least 6 clk&cen cycles long + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [7:0] din, + input [1:0] addr, + input cs_n, + input wr_n, + + output [7:0] dout, + output irq_n, + // ADPCM pins + output [19:0] adpcma_addr, // real hardware has 10 pins multiplexed through RMPX pin + output [3:0] adpcma_bank, + output adpcma_roe_n, // ADPCM-A ROM output enable + input [7:0] adpcma_data, // Data from RAM + output [23:0] adpcmb_addr, // real hardware has 12 pins multiplexed through PMPX pin + output adpcmb_roe_n, // ADPCM-B ROM output enable + input [7:0] adpcmb_data, + // Separated output + output [ 7:0] psg_A, + output [ 7:0] psg_B, + output [ 7:0] psg_C, + output signed [15:0] fm_snd, + // combined output + output [ 9:0] psg_snd, + output signed [15:0] snd_right, + output signed [15:0] snd_left, + output snd_sample +); + +// Uses 6 FM channels but only 4 are outputted +jt12_top #( + .use_lfo(1),.use_ssg(1), .num_ch(6), .use_pcm(0), .use_adpcm(1), + .JT49_DIV(3) ) +u_jt12( + .rst ( rst ), // rst should be at least 6 clk&cen cycles long + .clk ( clk ), // CPU clock + .cen ( cen ), // optional clock enable, it not needed leave as 1'b1 + .din ( din ), + .addr ( addr ), + .cs_n ( cs_n ), + .wr_n ( wr_n ), + + .dout ( dout ), + .irq_n ( irq_n ), + // ADPCM pins + .adpcma_addr ( adpcma_addr ), // real hardware has 10 pins multiplexed through RMPX pin + .adpcma_bank ( adpcma_bank ), + .adpcma_roe_n ( adpcma_roe_n ), // ADPCM-A ROM output enable + .adpcma_data ( adpcma_data ), // Data from RAM + .adpcmb_addr ( adpcmb_addr ), // real hardware has 12 pins multiplexed through PMPX pin + .adpcmb_roe_n ( adpcmb_roe_n ), // ADPCM-B ROM output enable + .adpcmb_data ( adpcmb_data ), // Data from RAM + // Separated output + .psg_A ( psg_A ), + .psg_B ( psg_B ), + .psg_C ( psg_C ), + .psg_snd ( psg_snd ), + .fm_snd_left ( fm_snd ), + .fm_snd_right (), + // Unused YM2203 + .IOA_in (), + .IOB_in (), + // Sound output + .snd_right ( snd_right ), + .snd_left ( snd_left ), + .snd_sample ( snd_sample ), + // unused pins + .en_hifi_pcm ( 1'b0 ) // used only on YM2612 mode +); + +endmodule // jt03 diff --git a/common/Sound/JT12/hdl/jt10_acc.v b/common/Sound/JT12/hdl/jt10_acc.v new file mode 100644 index 00000000..93d5534f --- /dev/null +++ b/common/Sound/JT12/hdl/jt10_acc.v @@ -0,0 +1,173 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 + + Each channel can use the full range of the DAC as they do not + get summed in the real chip. + + Operator data is summed up without adding extra bits. This is + the case of real YM3438, which was used on Megadrive 2 models. + + +*/ + +// YM2610 +// ADPCM inputs +// Full OP resolution +// No PCM +// 4 OP channels + +// ADPCM-A input is added for the time assigned to FM channel 0_10 (i.e. 3) + +module jt10_acc( + input clk, + input clk_en /* synthesis direct_enable */, + input signed [13:0] op_result, + input [ 1:0] rl, + input zero, + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + input [2:0] cur_ch, + input [1:0] cur_op, + input [2:0] alg, + input signed [15:0] adpcmA_l, + input signed [15:0] adpcmA_r, + input signed [15:0] adpcmB_l, + input signed [15:0] adpcmB_r, + // combined output + output signed [15:0] left, + output signed [15:0] right +); + +reg sum_en; + +always @(*) begin + case ( alg ) + default: sum_en = s4_enters; + 3'd4: sum_en = s2_enters | s4_enters; + 3'd5,3'd6: sum_en = ~s1_enters; + 3'd7: sum_en = 1'b1; + endcase +end + +wire left_en = rl[1]; +wire right_en= rl[0]; +wire signed [15:0] opext = { {2{op_result[13]}}, op_result }; +reg signed [15:0] acc_input_l, acc_input_r; +reg acc_en_l, acc_en_r; + +// YM2610 mode: +// uses channels 0 and 4 for ADPCM data, throwing away FM data for those channels +// reference: YM2610 Application Notes. +always @(*) + case( {cur_op,cur_ch} ) + {2'd0,3'd0}: begin // ADPCM-A: + acc_input_l = (adpcmA_l <<< 2) + (adpcmA_l <<< 1); + acc_input_r = (adpcmA_r <<< 2) + (adpcmA_r <<< 1); + `ifndef NOMIX + acc_en_l = 1'b1; + acc_en_r = 1'b1; + `else + acc_en_l = 1'b0; + acc_en_r = 1'b0; + `endif + end + {2'd0,3'd4}: begin // ADPCM-B: + acc_input_l = adpcmB_l >>> 1; // Operator width is 14 bit, ADPCM-B is 16 bit + acc_input_r = adpcmB_r >>> 1; // accumulator width per input channel is 14 bit + `ifndef NOMIX + acc_en_l = 1'b1; + acc_en_r = 1'b1; + `else + acc_en_l = 1'b0; + acc_en_r = 1'b0; + `endif + end + default: begin + // Note by Jose Tejada: + // I don't think we should divide down the FM output + // but someone was looking at the balance of the different + // channels and made this arrangement + // I suppose ADPCM-A would saturate if taken up a factor of 8 instead of 4 + // I'll leave it as it is but I think it is worth revisiting this: + acc_input_l = opext >>> 1; + acc_input_r = opext >>> 1; + acc_en_l = sum_en & left_en; + acc_en_r = sum_en & right_en; + end + endcase + +// Continuous output + +jt12_single_acc #(.win(16),.wout(16)) u_left( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( acc_input_l ), + .sum_en ( acc_en_l ), + .zero ( zero ), + .snd ( left ) +); + +jt12_single_acc #(.win(16),.wout(16)) u_right( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( acc_input_r ), + .sum_en ( acc_en_r ), + .zero ( zero ), + .snd ( right ) +); + +`ifdef SIMULATION +// Dump each channel independently +// It dumps values in decimal, left and right +integer f0,f1,f2,f4,f5,f6; +reg signed [15:0] sum_l[7], sum_r[7]; + +initial begin + f0=$fopen("fm0.raw","w"); + f1=$fopen("fm1.raw","w"); + f2=$fopen("fm2.raw","w"); + f4=$fopen("fm4.raw","w"); + f5=$fopen("fm5.raw","w"); + f6=$fopen("fm6.raw","w"); +end + +always @(posedge clk) begin + if(cur_op==2'b0) begin + sum_l[cur_ch] <= acc_en_l ? acc_input_l : 16'd0; + sum_r[cur_ch] <= acc_en_r ? acc_input_r : 16'd0; + end else begin + sum_l[cur_ch] <= sum_l[cur_ch] + (acc_en_l ? acc_input_l : 16'd0); + sum_r[cur_ch] <= sum_r[cur_ch] + (acc_en_r ? acc_input_r : 16'd0); + end +end + +always @(posedge zero) begin + $fwrite(f0,"%d,%d\n", sum_l[0], sum_r[0]); + $fwrite(f1,"%d,%d\n", sum_l[1], sum_r[1]); + $fwrite(f2,"%d,%d\n", sum_l[2], sum_r[2]); + $fwrite(f4,"%d,%d\n", sum_l[4], sum_r[4]); + $fwrite(f5,"%d,%d\n", sum_l[5], sum_r[5]); + $fwrite(f6,"%d,%d\n", sum_l[6], sum_r[6]); +end +`endif + +endmodule diff --git a/common/Sound/JT12/hdl/jt12.qip b/common/Sound/JT12/hdl/jt12.qip new file mode 100644 index 00000000..8c5eb8f4 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12.qip @@ -0,0 +1,42 @@ +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) jt12.vhd ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_top.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_single_acc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_csr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_logsin.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pcm_interpol.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_dout.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_rst.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) adpcm/jt10_adpcm_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_genmix.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_decim.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_interpol.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_comb.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mixer/jt12_fm_uprate.v ] diff --git a/common/Sound/JT12/hdl/jt12.v b/common/Sound/JT12/hdl/jt12.v new file mode 100644 index 00000000..77683d9a --- /dev/null +++ b/common/Sound/JT12/hdl/jt12.v @@ -0,0 +1,80 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-12-2018 + +*/ + +// Wrapper to output only combined channels. Defaults to YM2612 mode. + +module jt12 ( + input rst, // rst should be at least 6 clk&cen cycles long + input clk, // CPU clock + input cen, // optional clock enable, if not needed leave as 1'b1 + input [7:0] din, + input [1:0] addr, + input cs_n, + input wr_n, + + output [7:0] dout, + output irq_n, + // configuration + input en_hifi_pcm, + // combined output + output signed [15:0] snd_right, + output signed [15:0] snd_left, + output snd_sample +); + +// Default parameters for JT12 select a YM2612 +jt12_top u_jt12( + .rst ( rst ), // rst should be at least 6 clk&cen cycles long + .clk ( clk ), // CPU clock + .cen ( cen ), // optional clock enable, it not needed leave as 1'b1 + .din ( din ), + .addr ( addr ), + .cs_n ( cs_n ), + .wr_n ( wr_n ), + + .dout ( dout ), + .irq_n ( irq_n ), + // configuration + .en_hifi_pcm ( en_hifi_pcm ), + // Unused ADPCM pins + .adpcma_addr ( ), // real hardware has 10 pins multiplexed through RMPX pin + .adpcma_bank ( ), + .adpcma_roe_n ( ), // ADPCM-A ROM output enable + .adpcma_data ( 8'd0 ), // Data from RAM + .adpcmb_addr ( ), // real hardware has 12 pins multiplexed through PMPX pin + .adpcmb_roe_n ( ), // ADPCM-B ROM output enable + // Separated output + .psg_A (), + .psg_B (), + .psg_C (), + .fm_snd_left (), + .fm_snd_right (), + // Unused YM2203 + .IOA_in (), + .IOB_in (), + // combined output + .psg_snd (), + .snd_right ( snd_right ), // FM+PSG + .snd_left ( snd_left ), // FM+PSG + .snd_sample ( snd_sample ) +); +endmodule // jt03 diff --git a/common/Sound/JT12/hdl/jt12.vhd b/common/Sound/JT12/hdl/jt12.vhd new file mode 100644 index 00000000..014ea1ce --- /dev/null +++ b/common/Sound/JT12/hdl/jt12.vhd @@ -0,0 +1,44 @@ +library IEEE; +use IEEE.std_logic_1164.all; + +package jt12 is + +component jt12 +port +( + rst : in std_logic; + clk : in std_logic; -- CPU clock + cen : in std_logic := '1'; -- optional clock enable, if not needed leave as '1' + din : in std_logic_vector(7 downto 0); + addr : in std_logic_vector(1 downto 0); + cs_n : in std_logic; + wr_n : in std_logic; + + dout : out std_logic_vector(7 downto 0); + irq_n : out std_logic; + en_hifi_pcm: in std_logic; -- set high to use interpolation on PCM samples + + -- combined output + snd_right : out std_logic_vector(15 downto 0); -- signed + snd_left : out std_logic_vector(15 downto 0); -- signed + snd_sample : out std_logic +); +end component; + +component jt12_genmix +port +( + rst : in std_logic; + clk : in std_logic; -- expects 54 MHz clock + fm_left : in std_logic_vector(15 downto 0); -- FM at 55kHz + fm_right: in std_logic_vector(15 downto 0); -- FM at 55kHz + psg_snd : in std_logic_vector(10 downto 0); -- PSG at 220kHz + fm_en : in std_logic; + psg_en : in std_logic; + -- Mixed sound at 54 MHz + snd_left : out std_logic_vector(15 downto 0); + snd_right : out std_logic_vector(15 downto 0) +); +end component; + +end; diff --git a/common/Sound/JT12/hdl/jt12_acc.v b/common/Sound/JT12/hdl/jt12_acc.v new file mode 100644 index 00000000..3d59c100 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_acc.v @@ -0,0 +1,107 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + + Each channel can use the full range of the DAC as they do not + get summed in the real chip. + + Operator data is summed up without adding extra bits. This is + the case of real YM3438, which was used on Megadrive 2 models. + + +*/ + +/* + YM2612 had a limiter to prevent overflow + YM3438 did not + JT12 always has a limiter enabled + */ + +module jt12_acc( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input signed [8:0] op_result, + input [ 1:0] rl, + input zero, + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + input ch6op, + input [2:0] alg, + input pcm_en, // only enabled for channel 6 + input signed [8:0] pcm, + // combined output + output reg signed [11:0] left, + output reg signed [11:0] right +); + +reg sum_en; + +always @(*) begin + case ( alg ) + default: sum_en = s4_enters; + 3'd4: sum_en = s2_enters | s4_enters; + 3'd5,3'd6: sum_en = ~s1_enters; + 3'd7: sum_en = 1'b1; + endcase +end + +reg pcm_sum; + +always @(posedge clk) if(clk_en) + if( zero ) pcm_sum <= 1'b1; + else if( ch6op ) pcm_sum <= 1'b0; + +wire use_pcm = ch6op && pcm_en; +wire sum_or_pcm = sum_en | use_pcm; +wire left_en = rl[1]; +wire right_en= rl[0]; +wire signed [8:0] pcm_data = pcm_sum ? pcm : 9'd0; +wire [8:0] acc_input = use_pcm ? pcm_data : op_result; + +// Continuous output +wire signed [11:0] pre_left, pre_right; +jt12_single_acc #(.win(9),.wout(12)) u_left( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( acc_input ), + .sum_en ( sum_or_pcm & left_en ), + .zero ( zero ), + .snd ( pre_left ) +); + +jt12_single_acc #(.win(9),.wout(12)) u_right( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( acc_input ), + .sum_en ( sum_or_pcm & right_en ), + .zero ( zero ), + .snd ( pre_right ) +); + +// Output can be amplied by 8/6=1.33 to use full range +// an easy alternative is to add 1/4th and get 1.25 amplification +always @(posedge clk) if(clk_en) begin + left <= pre_left + { {2{pre_left [11]}}, pre_left [11:2] }; + right <= pre_right + { {2{pre_right[11]}}, pre_right[11:2] }; +end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_csr.v b/common/Sound/JT12/hdl/jt12_csr.v new file mode 100644 index 00000000..74e56abe --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_csr.v @@ -0,0 +1,82 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2017 + +*/ + +module jt12_csr( // Circular Shift Register + input mux + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input [ 7:0] din, + input [43:0] shift_in, + output [43:0] shift_out, + + input up_tl, + input up_dt1, + input up_ks_ar, + input up_amen_dr, + input up_sr, + input up_sl_rr, + input up_ssgeg, + input update_op_I, + input update_op_II, + input update_op_IV +); + +localparam regop_width=44; + +reg [regop_width-1:0] regop_in; + +jt12_sh_rst #(.width(regop_width),.stages(12)) u_regch( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( regop_in ), + .drop ( shift_out ) +); + +wire up_tl_op = up_tl & update_op_IV; +wire up_dt1_op = up_dt1 & update_op_I; +wire up_mul_op = up_dt1 & update_op_II; +wire up_ks_op = up_ks_ar & update_op_II; +wire up_ar_op = up_ks_ar & update_op_I; +wire up_amen_op = up_amen_dr& update_op_IV; +wire up_dr_op = up_amen_dr& update_op_I; +wire up_sr_op = up_sr & update_op_I; +wire up_sl_op = up_sl_rr & update_op_I; +wire up_rr_op = up_sl_rr & update_op_I; +wire up_ssg_op = up_ssgeg & update_op_I; + +always @(*) + regop_in = { + up_tl_op ? din[6:0] : shift_in[43:37], // 7 + up_dt1_op ? din[6:4] : shift_in[36:34], // 3 + up_mul_op ? din[3:0] : shift_in[33:30], // 4 + up_ks_op ? din[7:6] : shift_in[29:28], // 2 + up_ar_op ? din[4:0] : shift_in[27:23], // 5 + up_amen_op ? din[7] : shift_in[ 22], // 1 + up_dr_op ? din[4:0] : shift_in[21:17], // 5 + up_sr_op ? din[4:0] : shift_in[16:12], // 5 + up_sl_op ? din[7:4] : shift_in[11: 8], // 4 + up_rr_op ? din[3:0] : shift_in[ 7: 4], // 4 + up_ssg_op ? din[3:0] : shift_in[ 3: 0] // 4 + }; + +endmodule // jt12_reg \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_div.v b/common/Sound/JT12/hdl/jt12_div.v new file mode 100644 index 00000000..e610bd68 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_div.v @@ -0,0 +1,141 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2017 + */ + +`timescale 1ns / 1ps + +module jt12_div( + input rst, + input clk, + input cen /* synthesis direct_enable */, + input [1:0] div_setting, + output reg clk_en, // after prescaler + output reg clk_en_2, // cen divided by 2 + output reg clk_en_ssg, + output reg clk_en_666, // 666 kHz + output reg clk_en_111, // 111 kHz + output reg clk_en_55 // 55 kHz +); + +parameter use_ssg=0; + +reg [3:0] opn_pres, opn_cnt=4'd0; +reg [2:0] ssg_pres, ssg_cnt=3'd0; +reg [4:0] adpcm_cnt666 = 5'd0; +reg [2:0] adpcm_cnt111 = 3'd0, adpcm_cnt55=3'd0; +reg cen_int, cen_ssg_int, cen_adpcm_int, cen_adpcm3_int; + +// prescaler values for FM +// reset: 1/3 +// sel1/sel2 +// 0 0 1/3 +// 0 1 1/2 +// 1 0 1/6 +// 1 1 1/2 +// +// According to YM2608 document +// FM SSG div[1:0] +// reset value 1/6 1/4 10 +// 2D 1/6 1/4 10 | 10 +// 2D,2E 1/3 1/2 11 | 01 +// 2F 1/2 1/1 00 & 00 +// + +always @(*) begin + casez( div_setting ) + 2'b0?: begin // FM 1/2 - SSG 1/1 + opn_pres = 4'd2-4'd1; + ssg_pres = 3'd0; + end + 2'b10: begin // FM 1/6 - SSG 1/4 (reset value. Fixed for YM2610) + opn_pres = 4'd6-4'd1; + ssg_pres = 3'd3; + end + 2'b11: begin // FM 1/3 - SSG 1/2 + opn_pres = 4'd3-4'd1; + ssg_pres = 3'd1; + end + endcase // div_setting +end + +`ifdef SIMULATION +initial clk_en_666 = 1'b0; +`endif + +reg cen_55_int; +reg [1:0] div2=2'b0; + +always @(posedge clk) begin + cen_int <= opn_cnt == 4'd0; + cen_ssg_int <= ssg_cnt == 3'd0; + cen_adpcm_int <= adpcm_cnt666 == 5'd0; + cen_adpcm3_int <= adpcm_cnt111 == 3'd0; + cen_55_int <= adpcm_cnt55 == 3'd0; + `ifdef FASTDIV + // always enabled for fast sims (use with GYM output, timer will not work well) + clk_en <= 1'b1; + clk_en_ssg <= 1'b1; + clk_en_666 <= 1'b1; + clk_en_55 <= 1'b1; + `else + clk_en <= cen & cen_int; + clk_en_2 <= cen && (div2==2'b00); + clk_en_ssg <= use_ssg ? (cen & cen_ssg_int) : 1'b0; + clk_en_666 <= cen & cen_adpcm_int; + clk_en_111 <= cen & cen_adpcm_int & cen_adpcm3_int; + clk_en_55 <= cen & cen_adpcm_int & cen_adpcm3_int & cen_55_int; + `endif +end + +// Div/2 +always @(posedge clk) + if( cen ) begin + div2 <= div2==2'b10 ? 2'b00 : (div2+2'b01); + end + +// OPN +always @(posedge clk) + if( cen ) begin + if( opn_cnt == opn_pres ) begin + opn_cnt <= 4'd0; + end + else opn_cnt <= opn_cnt + 4'd1; + end + +// SSG +always @(posedge clk) + if( cen ) begin + if( ssg_cnt == ssg_pres ) begin + ssg_cnt <= 3'd0; + end + else ssg_cnt <= ssg_cnt + 3'd1; + end + +// ADPCM-A +always @(posedge clk) + if( cen ) begin + adpcm_cnt666 <= adpcm_cnt666==5'd11 ? 5'd0 : adpcm_cnt666 + 5'd1; + if( adpcm_cnt666==5'd0 ) begin + adpcm_cnt111 <= adpcm_cnt111==3'd5 ? 3'd0 : adpcm_cnt111+3'd1; + if( adpcm_cnt111==3'd0) + adpcm_cnt55 <= adpcm_cnt55==3'd1 ? 3'd0: adpcm_cnt55+3'd1; + end + end + +endmodule // jt12_div diff --git a/common/Sound/JT12/hdl/jt12_dout.v b/common/Sound/JT12/hdl/jt12_dout.v new file mode 100644 index 00000000..4666b572 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_dout.v @@ -0,0 +1,47 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt12_dout( + // input rst_n, + input clk, // CPU clock + input flag_A, + input flag_B, + input busy, + input [5:0] adpcma_flags, + input adpcmb_flag, + input [7:0] psg_dout, + input [1:0] addr, + output reg [7:0] dout +); + +parameter use_ssg=0, use_adpcm=0; + +always @(posedge clk) begin + casez( addr ) + 2'b00: dout <= {busy, 5'd0, flag_B, flag_A }; // YM2203 + 2'b01: dout <= (use_ssg ==1) ? psg_dout : {busy, 5'd0, flag_B, flag_A }; + 2'b1?: dout <= (use_adpcm==1) ? + { adpcmb_flag, 1'b0, adpcma_flags } : + { busy, 5'd0, flag_B, flag_A }; + endcase +end + +endmodule // jt12_dout \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg.v b/common/Sound/JT12/hdl/jt12_eg.v new file mode 100644 index 00000000..fbf10640 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg.v @@ -0,0 +1,203 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg ( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input zero, + input eg_stop, + // envelope configuration + input [4:0] keycode_II, + input [4:0] arate_I, // attack rate + input [4:0] rate1_I, // decay rate + input [4:0] rate2_I, // sustain rate + input [3:0] rrate_I, // release rate + input [3:0] sl_I, // sustain level + input [1:0] ks_II, // key scale + // SSG operation + input ssg_en_I, + input [2:0] ssg_eg_I, + // envelope operation + input keyon_I, + // envelope number + input [6:0] lfo_mod, + input amsen_IV, + input [1:0] ams_IV, + input [6:0] tl_IV, + + output reg [9:0] eg_V, + output reg pg_rst_II +); + +parameter num_ch=6; + +wire [14:0] eg_cnt; + +jt12_eg_cnt u_egcnt( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en & ~eg_stop ), + .zero ( zero ), + .eg_cnt ( eg_cnt) +); + +wire keyon_last_I; +wire keyon_now_I = !keyon_last_I && keyon_I; +wire keyoff_now_I = keyon_last_I && !keyon_I; + +wire cnt_in_II, cnt_lsb_II, step_II, pg_rst_I; + +wire ssg_inv_in_I, ssg_inv_out_I; +reg ssg_inv_II, ssg_inv_III, ssg_inv_IV; +wire [2:0] state_in_I, state_next_I; + +reg attack_II, attack_III; +wire [4:0] base_rate_I; +reg [4:0] base_rate_II; +wire [5:0] rate_out_II; +reg [5:1] rate_in_III; +reg step_III, ssg_en_II, ssg_en_III; +wire sum_out_II; +reg sum_in_III; + +wire [9:0] eg_in_I, pure_eg_out_III, eg_next_III, eg_out_IV; +reg [9:0] eg_in_II, eg_in_III, eg_in_IV; + + + +jt12_eg_comb u_comb( + /////////////////////////////////// + // I + .keyon_now ( keyon_now_I ), + .keyoff_now ( keyoff_now_I ), + .state_in ( state_in_I ), + .eg_in ( eg_in_I ), + // envelope configuration + .arate ( arate_I ), // attack rate + .rate1 ( rate1_I ), // decay rate + .rate2 ( rate2_I ), // sustain rate + .rrate ( rrate_I ), + .sl ( sl_I ), // sustain level + // SSG operation + .ssg_en ( ssg_en_I ), + .ssg_eg ( ssg_eg_I ), + // SSG output inversion + .ssg_inv_in ( ssg_inv_in_I ), + .ssg_inv_out ( ssg_inv_out_I ), + + .base_rate ( base_rate_I ), + .state_next ( state_next_I ), + .pg_rst ( pg_rst_I ), + /////////////////////////////////// + // II + .step_attack ( attack_II ), + .step_rate_in ( base_rate_II ), + .keycode ( keycode_II ), + .eg_cnt ( eg_cnt ), + .cnt_in ( cnt_in_II ), + .ks ( ks_II ), + .cnt_lsb ( cnt_lsb_II ), + .step ( step_II ), + .step_rate_out ( rate_out_II ), + .sum_up_out ( sum_out_II ), + /////////////////////////////////// + // III + .pure_attack ( attack_III ), + .pure_step ( step_III ), + .pure_rate ( rate_in_III[5:1] ), + .pure_ssg_en ( ssg_en_III ), + .pure_eg_in ( eg_in_III ), + .pure_eg_out ( pure_eg_out_III ), + .sum_up_in ( sum_in_III ), + /////////////////////////////////// + // IV + .lfo_mod ( lfo_mod ), + .amsen ( amsen_IV ), + .ams ( ams_IV ), + .tl ( tl_IV ), + .final_ssg_inv ( ssg_inv_IV ), + .final_eg_in ( eg_in_IV ), + .final_eg_out ( eg_out_IV ) +); + +always @(posedge clk) if(clk_en) begin + eg_in_II <= eg_in_I; + attack_II <= state_next_I[0]; + base_rate_II<= base_rate_I; + ssg_en_II <= ssg_en_I; + ssg_inv_II <= ssg_inv_out_I; + pg_rst_II <= pg_rst_I; + + eg_in_III <= eg_in_II; + attack_III <= attack_II; + rate_in_III <= rate_out_II[5:1]; + ssg_en_III <= ssg_en_II; + ssg_inv_III <= ssg_inv_II; + step_III <= step_II; + sum_in_III <= sum_out_II; + + ssg_inv_IV <= ssg_inv_III; + eg_in_IV <= pure_eg_out_III; + eg_V <= eg_out_IV; +end + +jt12_sh #( .width(1), .stages(4*num_ch) ) u_cntsh( + .clk ( clk ), + .clk_en ( clk_en ), + .din ( cnt_lsb_II), + .drop ( cnt_in_II ) +); + +jt12_sh_rst #( .width(10), .stages(4*num_ch-3), .rstval(1'b1) ) u_egsh( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( eg_in_IV ), + .drop ( eg_in_I ) +); + +jt12_sh_rst #( .width(3), .stages(4*num_ch), .rstval(1'b1) ) u_egstate( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( state_next_I ), + .drop ( state_in_I ) +); + +jt12_sh_rst #( .width(1), .stages(4*num_ch-3), .rstval(1'b0) ) u_ssg_inv( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( ssg_inv_IV ), + .drop ( ssg_inv_in_I ) +); + +jt12_sh_rst #( .width(1), .stages(4*num_ch), .rstval(1'b0) ) u_konsh( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( keyon_I ), + .drop ( keyon_last_I ) +); + + +endmodule // jt12_eg \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_cnt.v b/common/Sound/JT12/hdl/jt12_eg_cnt.v new file mode 100644 index 00000000..df006d6e --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_cnt.v @@ -0,0 +1,50 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg_cnt( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input zero, + output reg [14:0] eg_cnt +); + +reg [1:0] eg_cnt_base; + +always @(posedge clk, posedge rst) begin : envelope_counter + if( rst ) begin + eg_cnt_base <= 2'd0; + eg_cnt <=15'd0; + end + else begin + if( zero && clk_en ) begin + // envelope counter increases every 3 output samples, + // there is one sample every 24 clock ticks + if( eg_cnt_base == 2'd2 ) begin + eg_cnt <= eg_cnt + 1'b1; + eg_cnt_base <= 2'd0; + end + else eg_cnt_base <= eg_cnt_base + 1'b1; + end + end +end + +endmodule // jt12_eg_cnt \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_comb.v b/common/Sound/JT12/hdl/jt12_eg_comb.v new file mode 100644 index 00000000..ddf0c533 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_comb.v @@ -0,0 +1,139 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 30-10-2018 + + */ + +module jt12_eg_comb( + input keyon_now, + input keyoff_now, + input [2:0] state_in, + input [9:0] eg_in, + // envelope configuration + input [4:0] arate, // attack rate + input [4:0] rate1, // decay rate + input [4:0] rate2, // sustain rate + input [3:0] rrate, + input [3:0] sl, // sustain level + // SSG operation + input ssg_en, + input [2:0] ssg_eg, + // SSG output inversion + input ssg_inv_in, + output ssg_inv_out, + + output [4:0] base_rate, + output [2:0] state_next, + output pg_rst, + /////////////////////////////////// + // II + input step_attack, + input [ 4:0] step_rate_in, + input [ 4:0] keycode, + input [14:0] eg_cnt, + input cnt_in, + input [ 1:0] ks, + output cnt_lsb, + output step, + output [5:0] step_rate_out, + output sum_up_out, + /////////////////////////////////// + // III + input pure_attack, + input pure_step, + input [ 5:1] pure_rate, + input pure_ssg_en, + input [ 9:0] pure_eg_in, + output [9:0] pure_eg_out, + input sum_up_in, + /////////////////////////////////// + // IV + input [ 6:0] lfo_mod, + input amsen, + input [ 1:0] ams, + input [ 6:0] tl, + input [ 9:0] final_eg_in, + input final_ssg_inv, + output [9:0] final_eg_out +); + +// I +jt12_eg_ctrl u_ctrl( + .keyon_now ( keyon_now ), + .keyoff_now ( keyoff_now ), + .state_in ( state_in ), + .eg ( eg_in ), + // envelope configuration + .arate ( arate ), // attack rate + .rate1 ( rate1 ), // decay rate + .rate2 ( rate2 ), // sustain rate + .rrate ( rrate ), + .sl ( sl ), // sustain level + // SSG operation + .ssg_en ( ssg_en ), + .ssg_eg ( ssg_eg ), + // SSG output inversion + .ssg_inv_in ( ssg_inv_in ), + .ssg_inv_out ( ssg_inv_out ), + + .base_rate ( base_rate ), + .state_next ( state_next ), + .pg_rst ( pg_rst ) +); + +// II + +jt12_eg_step u_step( + .attack ( step_attack ), + .base_rate ( step_rate_in ), + .keycode ( keycode ), + .eg_cnt ( eg_cnt ), + .cnt_in ( cnt_in ), + .ks ( ks ), + .cnt_lsb ( cnt_lsb ), + .step ( step ), + .rate ( step_rate_out ), + .sum_up ( sum_up_out ) +); + +// III + +wire [9:0] egin, egout; +jt12_eg_pure u_pure( + .attack ( pure_attack ), + .step ( pure_step ), + .rate ( pure_rate ), + .ssg_en ( pure_ssg_en ), + .eg_in ( pure_eg_in ), + .eg_pure( pure_eg_out ), + .sum_up ( sum_up_in ) +); + +// IV + +jt12_eg_final u_final( + .lfo_mod ( lfo_mod ), + .amsen ( amsen ), + .ams ( ams ), + .tl ( tl ), + .ssg_inv ( final_ssg_inv ), + .eg_pure_in ( final_eg_in ), + .eg_limited ( final_eg_out ) +); + +endmodule // jt12_eg_comb \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_ctrl.v b/common/Sound/JT12/hdl/jt12_eg_ctrl.v new file mode 100644 index 00000000..ddd8698e --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_ctrl.v @@ -0,0 +1,122 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg_ctrl( + input keyon_now, + input keyoff_now, + input [2:0] state_in, + input [9:0] eg, + // envelope configuration + input [4:0] arate, // attack rate + input [4:0] rate1, // decay rate + input [4:0] rate2, // sustain rate + input [3:0] rrate, + input [3:0] sl, // sustain level + // SSG operation + input ssg_en, + input [2:0] ssg_eg, + // SSG output inversion + input ssg_inv_in, + output reg ssg_inv_out, + + output reg [4:0] base_rate, + output reg [2:0] state_next, + output reg pg_rst +); + +localparam ATTACK = 3'b001, + DECAY = 3'b010, + HOLD = 3'b100, + RELEASE= 3'b000; // default state is release + +// wire is_decaying = state_in[1] | state_in[2]; + +reg [4:0] sustain; + +always @(*) + if( sl == 4'd15 ) + sustain = 5'h1f; // 93dB + else + sustain = {1'b0, sl}; + +wire ssg_en_out; +reg ssg_en_in, ssg_pg_rst; + +// aliases +wire ssg_att = ssg_eg[2]; +wire ssg_alt = ssg_eg[1]; +wire ssg_hold = ssg_eg[0] & ssg_en; + +reg ssg_over; + + +always @(*) begin + ssg_over = ssg_en && eg[9]; // eg >=10'h200 + ssg_pg_rst = ssg_over && !( ssg_alt || ssg_hold ); + pg_rst = keyon_now | ssg_pg_rst; +end + +always @(*) + casez ( { keyoff_now, keyon_now, state_in} ) + 5'b01_???: begin // key on + base_rate = arate; + state_next = ATTACK; + ssg_inv_out = ssg_att & ssg_en; + end + {2'b00, ATTACK}: + if( eg==10'd0 ) begin + base_rate = rate1; + state_next = DECAY; + ssg_inv_out = ssg_inv_in; + end + else begin + base_rate = arate; + state_next = ATTACK; + ssg_inv_out = ssg_inv_in; + end + {2'b00, DECAY}: begin + if( ssg_over ) begin + base_rate = ssg_hold ? 5'd0 : arate; + state_next = ssg_hold ? HOLD : ATTACK; + ssg_inv_out = ssg_en & (ssg_alt ^ ssg_inv_in); + end + else begin + base_rate = eg[9:5] >= sustain ? rate2 : rate1; // equal comparison according to Nuke + state_next = DECAY; + ssg_inv_out = ssg_inv_in; + end + end + {2'b00, HOLD}: begin + base_rate = 5'd0; + state_next = HOLD; + ssg_inv_out = ssg_inv_in; + end + default: begin // RELEASE, note that keyoff_now==1 will enter this state too + base_rate = { rrate, 1'b1 }; + state_next = RELEASE; // release + ssg_inv_out = 1'b0; // this can produce a glitch in the output + // But to release from SSG cannot be done nicely while + // inverting the ouput + end + endcase + + +endmodule // jt12_eg_ctrl \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_final.v b/common/Sound/JT12/hdl/jt12_eg_final.v new file mode 100644 index 00000000..5919fc0f --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_final.v @@ -0,0 +1,57 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg_final( + input [ 6:0] lfo_mod, + input amsen, + input [ 1:0] ams, + input [ 6:0] tl, + input [ 9:0] eg_pure_in, + input ssg_inv, + output reg [9:0] eg_limited +); + +reg [ 8:0] am_final; +reg [11:0] sum_eg_tl; +reg [11:0] sum_eg_tl_am; +reg [ 5:0] am_inverted; +reg [ 9:0] eg_pream; + +always @(*) begin + am_inverted = lfo_mod[6] ? ~lfo_mod[5:0] : lfo_mod[5:0]; +end + +always @(*) begin + casez( {amsen, ams } ) + default: am_final = 9'd0; + 3'b1_01: am_final = { 5'd0, am_inverted[5:2] }; + 3'b1_10: am_final = { 3'd0, am_inverted }; + 3'b1_11: am_final = { 2'd0, am_inverted, 1'b0 }; + endcase + eg_pream = ssg_inv ? (10'h200-eg_pure_in) : eg_pure_in; + sum_eg_tl = { 1'b0, tl, 3'd0 } + {1'b0, eg_pream}; // leading zeros needed to compute correctly + sum_eg_tl_am = sum_eg_tl + { 3'd0, am_final }; +end + +always @(*) + eg_limited = sum_eg_tl_am[11:10]==2'd0 ? sum_eg_tl_am[9:0] : 10'h3ff; + +endmodule // jt12_eg_final \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_pure.v b/common/Sound/JT12/hdl/jt12_eg_pure.v new file mode 100644 index 00000000..02a36780 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_pure.v @@ -0,0 +1,81 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg_pure( + input attack, + input step, + input [ 5:1] rate, + input [ 9:0] eg_in, + input ssg_en, + input sum_up, + output reg [9:0] eg_pure +); + +reg [ 3:0] dr_sum; +reg [ 9:0] dr_adj; +reg [10:0] dr_result; + +always @(*) begin : dr_calculation + case( rate[5:2] ) + 4'b1100: dr_sum = { 2'b0, step, ~step }; // 12 + 4'b1101: dr_sum = { 1'b0, step, ~step, 1'b0 }; // 13 + 4'b1110: dr_sum = { step, ~step, 2'b0 }; // 14 + 4'b1111: dr_sum = 4'd8;// 15 + default: dr_sum = { 2'b0, step, 1'b0 }; + endcase + // Decay rate attenuation is multiplied by 4 for SSG operation + dr_adj = ssg_en ? {4'd0, dr_sum, 2'd0} : {6'd0, dr_sum}; + dr_result = dr_adj + eg_in; +end + +reg [ 7:0] ar_sum0; +reg [ 8:0] ar_sum1; +reg [10:0] ar_result; +reg [ 9:0] ar_sum; + +always @(*) begin : ar_calculation + casez( rate[5:2] ) + default: ar_sum0 = {2'd0, eg_in[9:4]}; + 4'b1101: ar_sum0 = {1'd0, eg_in[9:3]}; + 4'b111?: ar_sum0 = eg_in[9:2]; + endcase + ar_sum1 = ar_sum0+9'd1; + if( rate[5:4] == 2'b11 ) + ar_sum = step ? { ar_sum1, 1'b0 } : { 1'b0, ar_sum1 }; + else + ar_sum = step ? { 1'b0, ar_sum1 } : 10'd0; + ar_result = eg_in-ar_sum; +end +/////////////////////////////////////////////////////////// +// rate not used below this point +reg [9:0] eg_pre_fastar; // pre fast attack rate +always @(*) begin + if(sum_up) begin + if( attack ) + eg_pre_fastar = ar_result[10] ? 10'd0: ar_result[9:0]; + else + eg_pre_fastar = dr_result[10] ? 10'h3FF : dr_result[9:0]; + end + else eg_pre_fastar = eg_in; + eg_pure = (attack&rate[5:1]==5'h1F) ? 10'd0 : eg_pre_fastar; +end + +endmodule // jt12_eg_pure \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_eg_step.v b/common/Sound/JT12/hdl/jt12_eg_step.v new file mode 100644 index 00000000..4225e4ef --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_eg_step.v @@ -0,0 +1,111 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-10-2018 + + */ + +module jt12_eg_step( + input attack, + input [ 4:0] base_rate, + input [ 4:0] keycode, + input [14:0] eg_cnt, + input cnt_in, + input [ 1:0] ks, + output cnt_lsb, + output reg step, + output reg [5:0] rate, + output reg sum_up +); + +reg [6:0] pre_rate; + +always @(*) begin : pre_rate_calc + if( base_rate == 5'd0 ) + pre_rate = 7'd0; + else + case( ks ) + 2'd3: pre_rate = { base_rate, 1'b0 } + { 1'b0, keycode }; + 2'd2: pre_rate = { base_rate, 1'b0 } + { 2'b0, keycode[4:1] }; + 2'd1: pre_rate = { base_rate, 1'b0 } + { 3'b0, keycode[4:2] }; + 2'd0: pre_rate = { base_rate, 1'b0 } + { 4'b0, keycode[4:3] }; + endcase +end + +always @(*) + rate = pre_rate[6] ? 6'd63 : pre_rate[5:0]; + +reg [2:0] cnt; + +reg [4:0] mux_sel; +always @(*) begin + mux_sel = attack ? (rate[5:2]+4'd1): {1'b0,rate[5:2]}; +end // always @(*) + +always @(*) + case( mux_sel ) + 5'h0: cnt = eg_cnt[14:12]; + 5'h1: cnt = eg_cnt[13:11]; + 5'h2: cnt = eg_cnt[12:10]; + 5'h3: cnt = eg_cnt[11: 9]; + 5'h4: cnt = eg_cnt[10: 8]; + 5'h5: cnt = eg_cnt[ 9: 7]; + 5'h6: cnt = eg_cnt[ 8: 6]; + 5'h7: cnt = eg_cnt[ 7: 5]; + 5'h8: cnt = eg_cnt[ 6: 4]; + 5'h9: cnt = eg_cnt[ 5: 3]; + 5'ha: cnt = eg_cnt[ 4: 2]; + 5'hb: cnt = eg_cnt[ 3: 1]; + default: cnt = eg_cnt[ 2: 0]; + endcase + +//////////////////////////////// +reg [7:0] step_idx; + +always @(*) begin : rate_step + if( rate[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x + if( rate[5:2]==4'hf && attack) + step_idx = 8'b11111111; // Maximum attack speed, rates 60&61 + else + case( rate[1:0] ) + 2'd0: step_idx = 8'b00000000; + 2'd1: step_idx = 8'b10001000; // 2 + 2'd2: step_idx = 8'b10101010; // 4 + 2'd3: step_idx = 8'b11101110; // 6 + endcase + end + else begin + if( rate[5:2]==4'd0 && !attack) + step_idx = 8'b11111110; // limit slowest decay rate + else + case( rate[1:0] ) + 2'd0: step_idx = 8'b10101010; // 4 + 2'd1: step_idx = 8'b11101010; // 5 + 2'd2: step_idx = 8'b11101110; // 6 + 2'd3: step_idx = 8'b11111110; // 7 + endcase + end + // a rate of zero keeps the level still + step = rate[5:1]==5'd0 ? 1'b0 : step_idx[ cnt ]; +end + +assign cnt_lsb = cnt[0]; +always @(*) begin + sum_up = cnt[0] != cnt_in; +end + +endmodule // eg_step \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_exprom.v b/common/Sound/JT12/hdl/jt12_exprom.v new file mode 100644 index 00000000..b50e4191 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_exprom.v @@ -0,0 +1,302 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +// altera message_off 10030 + +module jt12_exprom +( + input [7:0] addr, + input clk, + input clk_en /* synthesis direct_enable */, + output reg [9:0] exp +); + + reg [9:0] explut_jt51[255:0]; + initial + begin + explut_jt51[8'd000] = 10'd1018; + explut_jt51[8'd001] = 10'd1013; + explut_jt51[8'd002] = 10'd1007; + explut_jt51[8'd003] = 10'd1002; + explut_jt51[8'd004] = 10'd0996; + explut_jt51[8'd005] = 10'd0991; + explut_jt51[8'd006] = 10'd0986; + explut_jt51[8'd007] = 10'd0980; + explut_jt51[8'd008] = 10'd0975; + explut_jt51[8'd009] = 10'd0969; + explut_jt51[8'd010] = 10'd0964; + explut_jt51[8'd011] = 10'd0959; + explut_jt51[8'd012] = 10'd0953; + explut_jt51[8'd013] = 10'd0948; + explut_jt51[8'd014] = 10'd0942; + explut_jt51[8'd015] = 10'd0937; + explut_jt51[8'd016] = 10'd0932; + explut_jt51[8'd017] = 10'd0927; + explut_jt51[8'd018] = 10'd0921; + explut_jt51[8'd019] = 10'd0916; + explut_jt51[8'd020] = 10'd0911; + explut_jt51[8'd021] = 10'd0906; + explut_jt51[8'd022] = 10'd0900; + explut_jt51[8'd023] = 10'd0895; + explut_jt51[8'd024] = 10'd0890; + explut_jt51[8'd025] = 10'd0885; + explut_jt51[8'd026] = 10'd0880; + explut_jt51[8'd027] = 10'd0874; + explut_jt51[8'd028] = 10'd0869; + explut_jt51[8'd029] = 10'd0864; + explut_jt51[8'd030] = 10'd0859; + explut_jt51[8'd031] = 10'd0854; + explut_jt51[8'd032] = 10'd0849; + explut_jt51[8'd033] = 10'd0844; + explut_jt51[8'd034] = 10'd0839; + explut_jt51[8'd035] = 10'd0834; + explut_jt51[8'd036] = 10'd0829; + explut_jt51[8'd037] = 10'd0824; + explut_jt51[8'd038] = 10'd0819; + explut_jt51[8'd039] = 10'd0814; + explut_jt51[8'd040] = 10'd0809; + explut_jt51[8'd041] = 10'd0804; + explut_jt51[8'd042] = 10'd0799; + explut_jt51[8'd043] = 10'd0794; + explut_jt51[8'd044] = 10'd0789; + explut_jt51[8'd045] = 10'd0784; + explut_jt51[8'd046] = 10'd0779; + explut_jt51[8'd047] = 10'd0774; + explut_jt51[8'd048] = 10'd0770; + explut_jt51[8'd049] = 10'd0765; + explut_jt51[8'd050] = 10'd0760; + explut_jt51[8'd051] = 10'd0755; + explut_jt51[8'd052] = 10'd0750; + explut_jt51[8'd053] = 10'd0745; + explut_jt51[8'd054] = 10'd0741; + explut_jt51[8'd055] = 10'd0736; + explut_jt51[8'd056] = 10'd0731; + explut_jt51[8'd057] = 10'd0726; + explut_jt51[8'd058] = 10'd0722; + explut_jt51[8'd059] = 10'd0717; + explut_jt51[8'd060] = 10'd0712; + explut_jt51[8'd061] = 10'd0708; + explut_jt51[8'd062] = 10'd0703; + explut_jt51[8'd063] = 10'd0698; + explut_jt51[8'd064] = 10'd0693; + explut_jt51[8'd065] = 10'd0689; + explut_jt51[8'd066] = 10'd0684; + explut_jt51[8'd067] = 10'd0680; + explut_jt51[8'd068] = 10'd0675; + explut_jt51[8'd069] = 10'd0670; + explut_jt51[8'd070] = 10'd0666; + explut_jt51[8'd071] = 10'd0661; + explut_jt51[8'd072] = 10'd0657; + explut_jt51[8'd073] = 10'd0652; + explut_jt51[8'd074] = 10'd0648; + explut_jt51[8'd075] = 10'd0643; + explut_jt51[8'd076] = 10'd0639; + explut_jt51[8'd077] = 10'd0634; + explut_jt51[8'd078] = 10'd0630; + explut_jt51[8'd079] = 10'd0625; + explut_jt51[8'd080] = 10'd0621; + explut_jt51[8'd081] = 10'd0616; + explut_jt51[8'd082] = 10'd0612; + explut_jt51[8'd083] = 10'd0607; + explut_jt51[8'd084] = 10'd0603; + explut_jt51[8'd085] = 10'd0599; + explut_jt51[8'd086] = 10'd0594; + explut_jt51[8'd087] = 10'd0590; + explut_jt51[8'd088] = 10'd0585; + explut_jt51[8'd089] = 10'd0581; + explut_jt51[8'd090] = 10'd0577; + explut_jt51[8'd091] = 10'd0572; + explut_jt51[8'd092] = 10'd0568; + explut_jt51[8'd093] = 10'd0564; + explut_jt51[8'd094] = 10'd0560; + explut_jt51[8'd095] = 10'd0555; + explut_jt51[8'd096] = 10'd0551; + explut_jt51[8'd097] = 10'd0547; + explut_jt51[8'd098] = 10'd0542; + explut_jt51[8'd099] = 10'd0538; + explut_jt51[8'd100] = 10'd0534; + explut_jt51[8'd101] = 10'd0530; + explut_jt51[8'd102] = 10'd0526; + explut_jt51[8'd103] = 10'd0521; + explut_jt51[8'd104] = 10'd0517; + explut_jt51[8'd105] = 10'd0513; + explut_jt51[8'd106] = 10'd0509; + explut_jt51[8'd107] = 10'd0505; + explut_jt51[8'd108] = 10'd0501; + explut_jt51[8'd109] = 10'd0496; + explut_jt51[8'd110] = 10'd0492; + explut_jt51[8'd111] = 10'd0488; + explut_jt51[8'd112] = 10'd0484; + explut_jt51[8'd113] = 10'd0480; + explut_jt51[8'd114] = 10'd0476; + explut_jt51[8'd115] = 10'd0472; + explut_jt51[8'd116] = 10'd0468; + explut_jt51[8'd117] = 10'd0464; + explut_jt51[8'd118] = 10'd0460; + explut_jt51[8'd119] = 10'd0456; + explut_jt51[8'd120] = 10'd0452; + explut_jt51[8'd121] = 10'd0448; + explut_jt51[8'd122] = 10'd0444; + explut_jt51[8'd123] = 10'd0440; + explut_jt51[8'd124] = 10'd0436; + explut_jt51[8'd125] = 10'd0432; + explut_jt51[8'd126] = 10'd0428; + explut_jt51[8'd127] = 10'd0424; + explut_jt51[8'd128] = 10'd0420; + explut_jt51[8'd129] = 10'd0416; + explut_jt51[8'd130] = 10'd0412; + explut_jt51[8'd131] = 10'd0409; + explut_jt51[8'd132] = 10'd0405; + explut_jt51[8'd133] = 10'd0401; + explut_jt51[8'd134] = 10'd0397; + explut_jt51[8'd135] = 10'd0393; + explut_jt51[8'd136] = 10'd0389; + explut_jt51[8'd137] = 10'd0385; + explut_jt51[8'd138] = 10'd0382; + explut_jt51[8'd139] = 10'd0378; + explut_jt51[8'd140] = 10'd0374; + explut_jt51[8'd141] = 10'd0370; + explut_jt51[8'd142] = 10'd0367; + explut_jt51[8'd143] = 10'd0363; + explut_jt51[8'd144] = 10'd0359; + explut_jt51[8'd145] = 10'd0355; + explut_jt51[8'd146] = 10'd0352; + explut_jt51[8'd147] = 10'd0348; + explut_jt51[8'd148] = 10'd0344; + explut_jt51[8'd149] = 10'd0340; + explut_jt51[8'd150] = 10'd0337; + explut_jt51[8'd151] = 10'd0333; + explut_jt51[8'd152] = 10'd0329; + explut_jt51[8'd153] = 10'd0326; + explut_jt51[8'd154] = 10'd0322; + explut_jt51[8'd155] = 10'd0318; + explut_jt51[8'd156] = 10'd0315; + explut_jt51[8'd157] = 10'd0311; + explut_jt51[8'd158] = 10'd0308; + explut_jt51[8'd159] = 10'd0304; + explut_jt51[8'd160] = 10'd0300; + explut_jt51[8'd161] = 10'd0297; + explut_jt51[8'd162] = 10'd0293; + explut_jt51[8'd163] = 10'd0290; + explut_jt51[8'd164] = 10'd0286; + explut_jt51[8'd165] = 10'd0283; + explut_jt51[8'd166] = 10'd0279; + explut_jt51[8'd167] = 10'd0276; + explut_jt51[8'd168] = 10'd0272; + explut_jt51[8'd169] = 10'd0268; + explut_jt51[8'd170] = 10'd0265; + explut_jt51[8'd171] = 10'd0262; + explut_jt51[8'd172] = 10'd0258; + explut_jt51[8'd173] = 10'd0255; + explut_jt51[8'd174] = 10'd0251; + explut_jt51[8'd175] = 10'd0248; + explut_jt51[8'd176] = 10'd0244; + explut_jt51[8'd177] = 10'd0241; + explut_jt51[8'd178] = 10'd0237; + explut_jt51[8'd179] = 10'd0234; + explut_jt51[8'd180] = 10'd0231; + explut_jt51[8'd181] = 10'd0227; + explut_jt51[8'd182] = 10'd0224; + explut_jt51[8'd183] = 10'd0220; + explut_jt51[8'd184] = 10'd0217; + explut_jt51[8'd185] = 10'd0214; + explut_jt51[8'd186] = 10'd0210; + explut_jt51[8'd187] = 10'd0207; + explut_jt51[8'd188] = 10'd0204; + explut_jt51[8'd189] = 10'd0200; + explut_jt51[8'd190] = 10'd0197; + explut_jt51[8'd191] = 10'd0194; + explut_jt51[8'd192] = 10'd0190; + explut_jt51[8'd193] = 10'd0187; + explut_jt51[8'd194] = 10'd0184; + explut_jt51[8'd195] = 10'd0181; + explut_jt51[8'd196] = 10'd0177; + explut_jt51[8'd197] = 10'd0174; + explut_jt51[8'd198] = 10'd0171; + explut_jt51[8'd199] = 10'd0168; + explut_jt51[8'd200] = 10'd0164; + explut_jt51[8'd201] = 10'd0161; + explut_jt51[8'd202] = 10'd0158; + explut_jt51[8'd203] = 10'd0155; + explut_jt51[8'd204] = 10'd0152; + explut_jt51[8'd205] = 10'd0148; + explut_jt51[8'd206] = 10'd0145; + explut_jt51[8'd207] = 10'd0142; + explut_jt51[8'd208] = 10'd0139; + explut_jt51[8'd209] = 10'd0136; + explut_jt51[8'd210] = 10'd0133; + explut_jt51[8'd211] = 10'd0130; + explut_jt51[8'd212] = 10'd0126; + explut_jt51[8'd213] = 10'd0123; + explut_jt51[8'd214] = 10'd0120; + explut_jt51[8'd215] = 10'd0117; + explut_jt51[8'd216] = 10'd0114; + explut_jt51[8'd217] = 10'd0111; + explut_jt51[8'd218] = 10'd0108; + explut_jt51[8'd219] = 10'd0105; + explut_jt51[8'd220] = 10'd0102; + explut_jt51[8'd221] = 10'd0099; + explut_jt51[8'd222] = 10'd0096; + explut_jt51[8'd223] = 10'd0093; + explut_jt51[8'd224] = 10'd0090; + explut_jt51[8'd225] = 10'd0087; + explut_jt51[8'd226] = 10'd0084; + explut_jt51[8'd227] = 10'd0081; + explut_jt51[8'd228] = 10'd0078; + explut_jt51[8'd229] = 10'd0075; + explut_jt51[8'd230] = 10'd0072; + explut_jt51[8'd231] = 10'd0069; + explut_jt51[8'd232] = 10'd0066; + explut_jt51[8'd233] = 10'd0063; + explut_jt51[8'd234] = 10'd0060; + explut_jt51[8'd235] = 10'd0057; + explut_jt51[8'd236] = 10'd0054; + explut_jt51[8'd237] = 10'd0051; + explut_jt51[8'd238] = 10'd0048; + explut_jt51[8'd239] = 10'd0045; + explut_jt51[8'd240] = 10'd0042; + explut_jt51[8'd241] = 10'd0040; + explut_jt51[8'd242] = 10'd0037; + explut_jt51[8'd243] = 10'd0034; + explut_jt51[8'd244] = 10'd0031; + explut_jt51[8'd245] = 10'd0028; + explut_jt51[8'd246] = 10'd0025; + explut_jt51[8'd247] = 10'd0022; + explut_jt51[8'd248] = 10'd0020; + explut_jt51[8'd249] = 10'd0017; + explut_jt51[8'd250] = 10'd0014; + explut_jt51[8'd251] = 10'd0011; + explut_jt51[8'd252] = 10'd0008; + explut_jt51[8'd253] = 10'd0006; + explut_jt51[8'd254] = 10'd0003; + explut_jt51[8'd255] = 10'd0000; + end + + always @ (posedge clk) if(clk_en) + exp <= explut_jt51[addr]; + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_kon.v b/common/Sound/JT12/hdl/jt12_kon.v new file mode 100644 index 00000000..9444b999 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_kon.v @@ -0,0 +1,151 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +module jt12_kon( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input [3:0] keyon_op, + input [2:0] keyon_ch, + input [1:0] next_op, + input [2:0] next_ch, + input up_keyon, + input csm, + // input flag_A, + input overflow_A, + + output reg keyon_I +); + +parameter num_ch=6; + +wire csr_out; + +generate +if(num_ch==6) begin + // capture overflow signal so it lasts long enough + reg overflow2; + reg [4:0] overflow_cycle; + + always @(posedge clk) if( clk_en ) begin + if(overflow_A) begin + overflow2 <= 1'b1; + overflow_cycle <= { next_op, next_ch }; + end else begin + if(overflow_cycle == {next_op, next_ch}) overflow2<=1'b0; + end + end + + always @(posedge clk) if( clk_en ) + keyon_I <= (csm&&next_ch==3'd2&&overflow2) || csr_out; + + reg up_keyon_reg; + reg [3:0] tkeyon_op; + reg [2:0] tkeyon_ch; + wire key_upnow; + + assign key_upnow = up_keyon_reg && (tkeyon_ch==next_ch) && (next_op == 2'd3); + + always @(posedge clk) if( clk_en ) begin + if (rst) + up_keyon_reg <= 1'b0; + if (up_keyon) begin + up_keyon_reg <= 1'b1; + tkeyon_op <= keyon_op; + tkeyon_ch <= keyon_ch; end + else if (key_upnow) + up_keyon_reg <= 1'b0; + end + + + wire middle1; + wire middle2; + wire middle3; + wire din = key_upnow ? tkeyon_op[3] : csr_out; + wire mid_din2 = key_upnow ? tkeyon_op[1] : middle1; + wire mid_din3 = key_upnow ? tkeyon_op[2] : middle2; + wire mid_din4 = key_upnow ? tkeyon_op[0] : middle3; + + jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch0( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( din ), + .drop ( middle1 ) + ); + + jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch1( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( mid_din2 ), + .drop ( middle2 ) + ); + + jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch2( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( mid_din3 ), + .drop ( middle3 ) + ); + + jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch3( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( mid_din4 ), + .drop ( csr_out ) + ); +end +else begin // 3 channels + reg din; + reg [3:0] next_op_hot; + + always @(*) begin + case( next_op ) + 2'd0: next_op_hot = 4'b0001; // S1 + 2'd1: next_op_hot = 4'b0100; // S3 + 2'd2: next_op_hot = 4'b0010; // S2 + 2'd3: next_op_hot = 4'b1000; // S4 + endcase + din = keyon_ch[1:0]==next_ch[1:0] && up_keyon ? |(keyon_op&next_op_hot) : csr_out; + end + + always @(posedge clk) if( clk_en ) + keyon_I <= csr_out; // No CSM for YM2203 + + jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch1( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( din ), + .drop ( csr_out ) + ); +end +endgenerate + + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_lfo.v b/common/Sound/JT12/hdl/jt12_lfo.v new file mode 100644 index 00000000..3f3fa908 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_lfo.v @@ -0,0 +1,103 @@ +/* This file is part of jt12. + + jt12 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. + + jt12 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 jt12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 25-2-2017 + */ + +`timescale 1ns / 1ps + +/* + + Does the LFO frequency depend on the pre-scaler for YM2608 ? + + From spritesmind.net: + "That would be 7-bit LFO step counter (which is incremented on each LFO clock and reset when LFO enable bit is cleared). + LFO AM value indeed corresponds to LFO step counter bits 0:5 shifted left by one + and XORed with inversion of bit 6 (to generate an inverted triangle waveform) + + LFO AM sensitivity (2 bits) indicates to EG how much LFO AM value is shifted before adding to EG output + [...] + LFO PM step (0-31), which takes bits 2:6 of LFO step counter (0-127) and goes to LFO PM calcuation unit + " + + From Sauraen: + +The LFO seems to have 3 sections: + + [*] 7-bit linear prescaler. The test bit 0x21:1 goes into what looks like the carry-in or something similar; + it could go into the reset, I can't quite tell with more detailed analysis. The 7-bit output (plus maybe carry-out) + gets logiced together into 8 lines (evidently perform "== N" with N hardcoded for each line), and these go into a + little selector unit which is also fed by the LFO Speed and LFO Enable bits. I can't quite see the output of this, + but I do see there's some sort of feedback to the prescaler's reset. So this clearly seems like a divide-by-N prescaler. + I can try to read the eight N's for you if you want, but you should be able to reverse engineer them from knowing what the LFO speeds are. + + [*] 7-bit linear counter, with an 8-bit unit after the output (possibly inverts the output after each cycle to make a triangle wave?). + Bits 1:6 of the output of this go to the EG, and stick into its pipeline at the same place where the LFO->Amplitude two bits go. + (Elsewhere the operator LFO enable flag simply forces these two bits to zero for operators not affected by the LFO.) + Some modified version of the 8-bit signal between the counter and the inverter unit thing goes to the third unit of the LFO. + + [*] Highly complex unit which modifies the frequency data as it goes from the channel registers to the PG. The block bits bypass this, + but all the frequency bits get modified by it. There's a bitslice portion corresponding to bits 0:6, and then what appears to be + the same logic folded over to process bits 7:A. But the interesting part is that bits 4:A of the frequency data go into the + bitslices 0:6. That is, the bitslice unit for bit 0 has bit 0 enter at the middle and leave (to the PG) at the bottom. But it also has bit 4 enter at the top. + And so on through bit 6 having bit A enter at the top. It looks like the top portion is some sort of shifter for bits 4:A--the wires go diagonally + so that bit 4 only gets used once, bit 5 gets used in bitslice 1 and 0, bit 6 gets used in bitslices 2:0, and so on so that bit A gets used in all of them. + I'm guessing this whole unit is basically a multiplier, multiplying bits 4:A of the frequency value by bits 0:7 of the LFO state, and then adding the result + to bits 0:6 of the frequency value (with carry up to the higher bits). It looks like, between the multiplied output and the adder, there's another shifter + whose value is based on the the LFO->Frequency bits. But it looks like it's a bit more complex than I'm describing. + +*/ + +module jt12_lfo( + input rst, + input clk, + input clk_en, + input zero, + input lfo_rst, + input lfo_en, + input [2:0] lfo_freq, + output reg [6:0] lfo_mod // 7-bit width according to spritesmind.net +); + +reg [6:0] cnt, limit; + +always @(*) + case( lfo_freq ) // same values as in MAME + 3'd0: limit = 7'd108; + 3'd1: limit = 7'd77; + 3'd2: limit = 7'd71; + 3'd3: limit = 7'd67; + 3'd4: limit = 7'd62; + 3'd5: limit = 7'd44; + 3'd6: limit = 7'd8; + 3'd7: limit = 7'd5; + endcase + +always @(posedge clk) + if( rst || !lfo_en ) + { lfo_mod, cnt } <= 14'd0; + else if( clk_en && zero) begin + if( cnt == limit ) begin + cnt <= 7'd0; + lfo_mod <= lfo_mod + 1'b1; + end + else begin + cnt <= cnt + 1'b1; + end + end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_logsin.v b/common/Sound/JT12/hdl/jt12_logsin.v new file mode 100644 index 00000000..89743754 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_logsin.v @@ -0,0 +1,298 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +//altera message_off 10030 + +module jt12_logsin +( + input [7:0] addr, + input clk, + input clk_en, + output reg [11:0] logsin +); + +reg [11:0] sinelut[255:0]; +initial begin + sinelut[8'd000] = 12'h000; + sinelut[8'd001] = 12'h000; + sinelut[8'd002] = 12'h000; + sinelut[8'd003] = 12'h000; + sinelut[8'd004] = 12'h000; + sinelut[8'd005] = 12'h000; + sinelut[8'd006] = 12'h000; + sinelut[8'd007] = 12'h000; + sinelut[8'd008] = 12'h001; + sinelut[8'd009] = 12'h001; + sinelut[8'd010] = 12'h001; + sinelut[8'd011] = 12'h001; + sinelut[8'd012] = 12'h001; + sinelut[8'd013] = 12'h001; + sinelut[8'd014] = 12'h001; + sinelut[8'd015] = 12'h002; + sinelut[8'd016] = 12'h002; + sinelut[8'd017] = 12'h002; + sinelut[8'd018] = 12'h002; + sinelut[8'd019] = 12'h003; + sinelut[8'd020] = 12'h003; + sinelut[8'd021] = 12'h003; + sinelut[8'd022] = 12'h004; + sinelut[8'd023] = 12'h004; + sinelut[8'd024] = 12'h004; + sinelut[8'd025] = 12'h005; + sinelut[8'd026] = 12'h005; + sinelut[8'd027] = 12'h005; + sinelut[8'd028] = 12'h006; + sinelut[8'd029] = 12'h006; + sinelut[8'd030] = 12'h007; + sinelut[8'd031] = 12'h007; + sinelut[8'd032] = 12'h007; + sinelut[8'd033] = 12'h008; + sinelut[8'd034] = 12'h008; + sinelut[8'd035] = 12'h009; + sinelut[8'd036] = 12'h009; + sinelut[8'd037] = 12'h00a; + sinelut[8'd038] = 12'h00a; + sinelut[8'd039] = 12'h00b; + sinelut[8'd040] = 12'h00c; + sinelut[8'd041] = 12'h00c; + sinelut[8'd042] = 12'h00d; + sinelut[8'd043] = 12'h00d; + sinelut[8'd044] = 12'h00e; + sinelut[8'd045] = 12'h00f; + sinelut[8'd046] = 12'h00f; + sinelut[8'd047] = 12'h010; + sinelut[8'd048] = 12'h011; + sinelut[8'd049] = 12'h011; + sinelut[8'd050] = 12'h012; + sinelut[8'd051] = 12'h013; + sinelut[8'd052] = 12'h014; + sinelut[8'd053] = 12'h014; + sinelut[8'd054] = 12'h015; + sinelut[8'd055] = 12'h016; + sinelut[8'd056] = 12'h017; + sinelut[8'd057] = 12'h017; + sinelut[8'd058] = 12'h018; + sinelut[8'd059] = 12'h019; + sinelut[8'd060] = 12'h01a; + sinelut[8'd061] = 12'h01b; + sinelut[8'd062] = 12'h01c; + sinelut[8'd063] = 12'h01d; + sinelut[8'd064] = 12'h01e; + sinelut[8'd065] = 12'h01f; + sinelut[8'd066] = 12'h020; + sinelut[8'd067] = 12'h021; + sinelut[8'd068] = 12'h022; + sinelut[8'd069] = 12'h023; + sinelut[8'd070] = 12'h024; + sinelut[8'd071] = 12'h025; + sinelut[8'd072] = 12'h026; + sinelut[8'd073] = 12'h027; + sinelut[8'd074] = 12'h028; + sinelut[8'd075] = 12'h029; + sinelut[8'd076] = 12'h02a; + sinelut[8'd077] = 12'h02b; + sinelut[8'd078] = 12'h02d; + sinelut[8'd079] = 12'h02e; + sinelut[8'd080] = 12'h02f; + sinelut[8'd081] = 12'h030; + sinelut[8'd082] = 12'h031; + sinelut[8'd083] = 12'h033; + sinelut[8'd084] = 12'h034; + sinelut[8'd085] = 12'h035; + sinelut[8'd086] = 12'h037; + sinelut[8'd087] = 12'h038; + sinelut[8'd088] = 12'h039; + sinelut[8'd089] = 12'h03b; + sinelut[8'd090] = 12'h03c; + sinelut[8'd091] = 12'h03e; + sinelut[8'd092] = 12'h03f; + sinelut[8'd093] = 12'h040; + sinelut[8'd094] = 12'h042; + sinelut[8'd095] = 12'h043; + sinelut[8'd096] = 12'h045; + sinelut[8'd097] = 12'h046; + sinelut[8'd098] = 12'h048; + sinelut[8'd099] = 12'h04a; + sinelut[8'd100] = 12'h04b; + sinelut[8'd101] = 12'h04d; + sinelut[8'd102] = 12'h04e; + sinelut[8'd103] = 12'h050; + sinelut[8'd104] = 12'h052; + sinelut[8'd105] = 12'h053; + sinelut[8'd106] = 12'h055; + sinelut[8'd107] = 12'h057; + sinelut[8'd108] = 12'h059; + sinelut[8'd109] = 12'h05b; + sinelut[8'd110] = 12'h05c; + sinelut[8'd111] = 12'h05e; + sinelut[8'd112] = 12'h060; + sinelut[8'd113] = 12'h062; + sinelut[8'd114] = 12'h064; + sinelut[8'd115] = 12'h066; + sinelut[8'd116] = 12'h068; + sinelut[8'd117] = 12'h06a; + sinelut[8'd118] = 12'h06c; + sinelut[8'd119] = 12'h06e; + sinelut[8'd120] = 12'h070; + sinelut[8'd121] = 12'h072; + sinelut[8'd122] = 12'h074; + sinelut[8'd123] = 12'h076; + sinelut[8'd124] = 12'h078; + sinelut[8'd125] = 12'h07a; + sinelut[8'd126] = 12'h07d; + sinelut[8'd127] = 12'h07f; + sinelut[8'd128] = 12'h081; + sinelut[8'd129] = 12'h083; + sinelut[8'd130] = 12'h086; + sinelut[8'd131] = 12'h088; + sinelut[8'd132] = 12'h08a; + sinelut[8'd133] = 12'h08d; + sinelut[8'd134] = 12'h08f; + sinelut[8'd135] = 12'h092; + sinelut[8'd136] = 12'h094; + sinelut[8'd137] = 12'h097; + sinelut[8'd138] = 12'h099; + sinelut[8'd139] = 12'h09c; + sinelut[8'd140] = 12'h09f; + sinelut[8'd141] = 12'h0a1; + sinelut[8'd142] = 12'h0a4; + sinelut[8'd143] = 12'h0a7; + sinelut[8'd144] = 12'h0a9; + sinelut[8'd145] = 12'h0ac; + sinelut[8'd146] = 12'h0af; + sinelut[8'd147] = 12'h0b2; + sinelut[8'd148] = 12'h0b5; + sinelut[8'd149] = 12'h0b8; + sinelut[8'd150] = 12'h0bb; + sinelut[8'd151] = 12'h0be; + sinelut[8'd152] = 12'h0c1; + sinelut[8'd153] = 12'h0c4; + sinelut[8'd154] = 12'h0c7; + sinelut[8'd155] = 12'h0ca; + sinelut[8'd156] = 12'h0cd; + sinelut[8'd157] = 12'h0d1; + sinelut[8'd158] = 12'h0d4; + sinelut[8'd159] = 12'h0d7; + sinelut[8'd160] = 12'h0db; + sinelut[8'd161] = 12'h0de; + sinelut[8'd162] = 12'h0e2; + sinelut[8'd163] = 12'h0e5; + sinelut[8'd164] = 12'h0e9; + sinelut[8'd165] = 12'h0ec; + sinelut[8'd166] = 12'h0f0; + sinelut[8'd167] = 12'h0f4; + sinelut[8'd168] = 12'h0f8; + sinelut[8'd169] = 12'h0fb; + sinelut[8'd170] = 12'h0ff; + sinelut[8'd171] = 12'h103; + sinelut[8'd172] = 12'h107; + sinelut[8'd173] = 12'h10b; + sinelut[8'd174] = 12'h10f; + sinelut[8'd175] = 12'h114; + sinelut[8'd176] = 12'h118; + sinelut[8'd177] = 12'h11c; + sinelut[8'd178] = 12'h121; + sinelut[8'd179] = 12'h125; + sinelut[8'd180] = 12'h129; + sinelut[8'd181] = 12'h12e; + sinelut[8'd182] = 12'h133; + sinelut[8'd183] = 12'h137; + sinelut[8'd184] = 12'h13c; + sinelut[8'd185] = 12'h141; + sinelut[8'd186] = 12'h146; + sinelut[8'd187] = 12'h14b; + sinelut[8'd188] = 12'h150; + sinelut[8'd189] = 12'h155; + sinelut[8'd190] = 12'h15b; + sinelut[8'd191] = 12'h160; + sinelut[8'd192] = 12'h166; + sinelut[8'd193] = 12'h16b; + sinelut[8'd194] = 12'h171; + sinelut[8'd195] = 12'h177; + sinelut[8'd196] = 12'h17c; + sinelut[8'd197] = 12'h182; + sinelut[8'd198] = 12'h188; + sinelut[8'd199] = 12'h18f; + sinelut[8'd200] = 12'h195; + sinelut[8'd201] = 12'h19b; + sinelut[8'd202] = 12'h1a2; + sinelut[8'd203] = 12'h1a9; + sinelut[8'd204] = 12'h1b0; + sinelut[8'd205] = 12'h1b7; + sinelut[8'd206] = 12'h1be; + sinelut[8'd207] = 12'h1c5; + sinelut[8'd208] = 12'h1cd; + sinelut[8'd209] = 12'h1d4; + sinelut[8'd210] = 12'h1dc; + sinelut[8'd211] = 12'h1e4; + sinelut[8'd212] = 12'h1ec; + sinelut[8'd213] = 12'h1f5; + sinelut[8'd214] = 12'h1fd; + sinelut[8'd215] = 12'h206; + sinelut[8'd216] = 12'h20f; + sinelut[8'd217] = 12'h218; + sinelut[8'd218] = 12'h222; + sinelut[8'd219] = 12'h22c; + sinelut[8'd220] = 12'h236; + sinelut[8'd221] = 12'h240; + sinelut[8'd222] = 12'h24b; + sinelut[8'd223] = 12'h256; + sinelut[8'd224] = 12'h261; + sinelut[8'd225] = 12'h26d; + sinelut[8'd226] = 12'h279; + sinelut[8'd227] = 12'h286; + sinelut[8'd228] = 12'h293; + sinelut[8'd229] = 12'h2a0; + sinelut[8'd230] = 12'h2af; + sinelut[8'd231] = 12'h2bd; + sinelut[8'd232] = 12'h2cd; + sinelut[8'd233] = 12'h2dc; + sinelut[8'd234] = 12'h2ed; + sinelut[8'd235] = 12'h2ff; + sinelut[8'd236] = 12'h311; + sinelut[8'd237] = 12'h324; + sinelut[8'd238] = 12'h339; + sinelut[8'd239] = 12'h34e; + sinelut[8'd240] = 12'h365; + sinelut[8'd241] = 12'h37e; + sinelut[8'd242] = 12'h398; + sinelut[8'd243] = 12'h3b5; + sinelut[8'd244] = 12'h3d3; + sinelut[8'd245] = 12'h3f5; + sinelut[8'd246] = 12'h41a; + sinelut[8'd247] = 12'h443; + sinelut[8'd248] = 12'h471; + sinelut[8'd249] = 12'h4a6; + sinelut[8'd250] = 12'h4e4; + sinelut[8'd251] = 12'h52e; + sinelut[8'd252] = 12'h58b; + sinelut[8'd253] = 12'h607; + sinelut[8'd254] = 12'h6c3; + sinelut[8'd255] = 12'h859; +end + + always @ (posedge clk) if(clk_en) + logsin <= sinelut[addr]; + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_mmr.v b/common/Sound/JT12/hdl/jt12_mmr.v new file mode 100644 index 00000000..a6a70283 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_mmr.v @@ -0,0 +1,511 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2017 + */ + +`timescale 1ns / 1ps + +module jt12_mmr( + input rst, + input clk, + input cen /* synthesis direct_enable */, + output clk_en, + output clk_en_2, + output clk_en_ssg, + output clk_en_666, + output clk_en_111, + output clk_en_55, + input [7:0] din, + input write, + input [1:0] addr, + output reg busy, + output ch6op, + output [2:0] cur_ch, + output [1:0] cur_op, + // LFO + output reg [2:0] lfo_freq, + output reg lfo_en, + // Timers + output reg [9:0] value_A, + output reg [7:0] value_B, + output reg load_A, + output reg load_B, + output reg enable_irq_A, + output reg enable_irq_B, + output reg clr_flag_A, + output reg clr_flag_B, + output reg fast_timers, + input flag_A, + input overflow_A, + // PCM + output reg [8:0] pcm, + output reg pcm_en, + output reg pcm_wr, // high for one clock cycle when PCM is written + // ADPCM-A + output reg [ 7:0] aon_a, // ON + output reg [ 5:0] atl_a, // TL + output reg [15:0] addr_a, // address latch + output reg [ 7:0] lracl, // L/R ADPCM Channel Level + output reg up_start, // write enable start address latch + output reg up_end, // write enable end address latch + output reg [ 2:0] up_addr, // write enable end address latch + output reg [ 2:0] up_lracl, + output reg up_aon, // There was a write AON register + // ADPCM-B + output reg acmd_on_b, // Control - Process start, Key On + output reg acmd_rep_b, // Control - Repeat + output reg acmd_rst_b, // Control - Reset + output reg acmd_up_b, // Control - New cmd received + output reg [ 1:0] alr_b, // Left / Right + output reg [15:0] astart_b, // Start address + output reg [15:0] aend_b, // End address + output reg [15:0] adeltan_b, // Delta-N + output reg [ 7:0] aeg_b, // Envelope Generator Control + output reg [ 6:0] flag_ctl, + // Operator + output xuse_prevprev1, + output xuse_internal, + output yuse_internal, + output xuse_prev2, + output yuse_prev1, + output yuse_prev2, + // PG + output [10:0] fnum_I, + output [ 2:0] block_I, + output reg pg_stop, + // REG + output [ 1:0] rl, + output [ 2:0] fb_II, + output [ 2:0] alg_I, + output [ 2:0] pms_I, + output [ 1:0] ams_IV, + output amsen_IV, + output [ 2:0] dt1_I, + output [ 3:0] mul_II, + output [ 6:0] tl_IV, + output reg eg_stop, + + output [ 4:0] ar_I, + output [ 4:0] d1r_I, + output [ 4:0] d2r_I, + output [ 3:0] rr_I, + output [ 3:0] sl_I, + output [ 1:0] ks_II, + // SSG operation + output ssg_en_I, + output [2:0] ssg_eg_I, + + output keyon_I, + + // Operator + output zero, + output s1_enters, + output s2_enters, + output s3_enters, + output s4_enters, + + // PSG interace + output [3:0] psg_addr, + output [7:0] psg_data, + output reg psg_wr_n +); + +parameter use_ssg=0, num_ch=6, use_pcm=1, use_adpcm=0; + +reg [1:0] div_setting; + + +jt12_div #(.use_ssg(use_ssg)) u_div ( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), + .div_setting ( div_setting ), + .clk_en ( clk_en ), + .clk_en_2 ( clk_en_2 ), + .clk_en_ssg ( clk_en_ssg ), + .clk_en_666 ( clk_en_666 ), + .clk_en_111 ( clk_en_111 ), + .clk_en_55 ( clk_en_55 ) +); + +reg [7:0] selected_register; + +/* +reg irq_zero_en, irq_brdy_en, irq_eos_en, + irq_tb_en, irq_ta_en; + */ +reg [6:0] up_opreg; // hot-one encoding. tells which operator register gets updated next +reg [2:0] up_chreg; // hot-one encoding. tells which channel register gets updated next +reg up_keyon; + +localparam REG_TESTYM = 8'h21, + REG_LFO = 8'h22, + REG_CLKA1 = 8'h24, + REG_CLKA2 = 8'h25, + REG_CLKB = 8'h26, + REG_TIMER = 8'h27, + REG_KON = 8'h28, + REG_IRQMASK = 8'h29, + REG_PCM = 8'h2A, + REG_PCM_EN = 8'h2B, + REG_DACTEST = 8'h2C, + REG_CLK_N6 = 8'h2D, + REG_CLK_N3 = 8'h2E, + REG_CLK_N2 = 8'h2F, + // ADPCM (YM2610) + REG_ADPCMA_ON = 8'h00, + REG_ADPCMA_TL = 8'h01, + REG_ADPCMA_TEST = 8'h02; + +reg csm, effect; + +reg [ 2:0] block_ch3op2, block_ch3op3, block_ch3op1; +reg [10:0] fnum_ch3op2, fnum_ch3op3, fnum_ch3op1; +reg [ 5:0] latch_fnum; + + +reg [2:0] up_ch; +reg [1:0] up_op; + +reg old_write; +reg [7:0] din_copy; + +always @(posedge clk) + old_write <= write; + +generate + if( use_ssg ) begin + assign psg_addr = selected_register[3:0]; + assign psg_data = din_copy; + end else begin + assign psg_addr = 4'd0; + assign psg_data = 8'd0; + end +endgenerate + +reg part; + +// this runs at clk speed, no clock gating here +// if I try to make this an async rst it fails to map it +// as flip flops but uses latches instead. So I keep it as sync. reset +always @(posedge clk) begin : memory_mapped_registers + if( rst ) begin + selected_register <= 8'h0; + div_setting <= 2'b10; // FM=1/6, SSG=1/4 + up_ch <= 3'd0; + up_op <= 2'd0; + up_keyon <= 1'd0; + up_opreg <= 7'd0; + up_chreg <= 3'd0; + // IRQ Mask + /*{ irq_zero_en, irq_brdy_en, irq_eos_en, + irq_tb_en, irq_ta_en } = 5'h1f; */ + // timers + { value_A, value_B } <= 18'd0; + { clr_flag_B, clr_flag_A, + enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0; + fast_timers <= 1'b0; + // LFO + lfo_freq <= 3'd0; + lfo_en <= 1'b0; + csm <= 1'b0; + effect <= 1'b0; + // PCM + pcm <= 9'h0; + pcm_en <= 1'b0; + pcm_wr <= 1'b0; + // ADPCM-A + aon_a <= 'd0; + atl_a <= 'd0; + up_start <= 'd0; + up_end <= 'd0; + up_addr <= 3'd7; + up_lracl <= 3'd7; + up_aon <= 'd0; + lracl <= 'd0; + addr_a <= 'd0; + // ADPCM-B + acmd_on_b <= 'd0; + acmd_rep_b <= 'd0; + acmd_rst_b <= 'd0; + alr_b <= 'd0; + flag_ctl <= 'd0; + astart_b <= 'd0; + aend_b <= 'd0; + adeltan_b <= 'd0; + aeg_b <= 8'hff; + // Original test features + eg_stop <= 1'b0; + pg_stop <= 1'b0; + psg_wr_n <= 1'b1; + // + { block_ch3op1, fnum_ch3op1 } <= {3'd0, 11'd0 }; + { block_ch3op3, fnum_ch3op3 } <= {3'd0, 11'd0 }; + { block_ch3op2, fnum_ch3op2 } <= {3'd0, 11'd0 }; + latch_fnum <= 6'd0; + din_copy <= 8'd0; + part <= 1'b0; + end else begin + // WRITE IN REGISTERS + if( write ) begin + if( !addr[0] ) begin + selected_register <= din; + part <= addr[1]; + case(din) + // clock divider: should work only for ym2203 + // and ym2608. + // clock divider works just by selecting the register + REG_CLK_N6: div_setting[1] <= 1'b1; // 2D + REG_CLK_N3: div_setting[0] <= 1'b1; // 2E + REG_CLK_N2: div_setting <= 2'b0; // 2F + default:; + endcase + end else begin + // Global registers + din_copy <= din; + up_keyon <= selected_register == REG_KON && !part; + up_ch <= {part, selected_register[1:0]}; + up_op <= selected_register[3:2]; // 0=S1,1=S3,2=S2,3=S4 + + // General control (<0x20 registers and A0==0) + if(!part) begin + casez( selected_register) + //REG_TEST: lfo_rst <= 1'b1; // regardless of din + 8'h0?: psg_wr_n <= 1'b0; + REG_TESTYM: begin + eg_stop <= din[5]; + pg_stop <= din[3]; + fast_timers <= din[2]; + end + REG_CLKA1: value_A[9:2]<= din; + REG_CLKA2: value_A[1:0]<= din[1:0]; + REG_CLKB: value_B <= din; + REG_TIMER: begin + effect <= |din[7:6]; + csm <= din[7:6] == 2'b10; + { clr_flag_B, clr_flag_A, + enable_irq_B, enable_irq_A, + load_B, load_A } <= din[5:0]; + end + `ifndef NOLFO + REG_LFO: { lfo_en, lfo_freq } <= din[3:0]; + `endif + default:; + endcase + end + + // CH3 special registers + casez( selected_register) + 8'hA9: { block_ch3op1, fnum_ch3op1 } <= { latch_fnum, din }; + 8'hA8: { block_ch3op3, fnum_ch3op3 } <= { latch_fnum, din }; + 8'hAA: { block_ch3op2, fnum_ch3op2 } <= { latch_fnum, din }; + // According to http://www.mjsstuf.x10host.com/pages/vgmPlay/vgmPlay.htm + // There is a single fnum latch for all channels + 8'hA4, 8'hA5, 8'hA6, 8'hAD, 8'hAC, 8'hAE: latch_fnum <= din[5:0]; + default:; // avoid incomplete-case warning + endcase + + // YM2612 PCM support + if( use_pcm==1 ) begin + casez( selected_register) + REG_DACTEST: pcm[0] <= din[3]; + REG_PCM: + pcm <= { ~din[7], din[6:0], 1'b1 }; + REG_PCM_EN: pcm_en <= din[7]; + default:; + endcase + pcm_wr <= selected_register==REG_PCM; + end + if( use_adpcm==1 ) begin + // YM2610 ADPCM-A support, A1=1, regs 0-2D + if(part && selected_register[7:6]==2'b0) begin + casez( selected_register[5:0] ) + 6'h0: begin + aon_a <= din; + up_aon <= 1'b1; + end + 6'h1: atl_a <= din[5:0]; + // LRACL + 6'h8, 6'h9, 6'hA, 6'hB, 6'hC, 6'hD: begin + lracl <= din; + up_lracl <= selected_register[2:0]; + end + 6'b01_????, 6'b10_????: begin + if( !selected_register[3] ) addr_a[ 7:0] <= din; + if( selected_register[3] ) addr_a[15:8] <= din; + case( selected_register[5:4] ) + 2'b01, 2'b10: begin + {up_end, up_start } <= selected_register[5:4]; + up_addr <= selected_register[2:0]; + end + default: begin + up_start <= 1'b0; + up_end <= 1'b0; + end + endcase + end + default:; + endcase + end + if( !part && selected_register[7:4]==4'h1 ) begin + // YM2610 ADPCM-B support, A1=0, regs 1x + case(selected_register[3:0]) + 4'd0: {acmd_up_b, acmd_on_b, acmd_rep_b,acmd_rst_b} <= {1'd1,din[7],din[4],din[0]}; + 4'd1: alr_b <= din[7:6]; + 4'd2: astart_b [ 7:0] <= din; + 4'd3: astart_b [15:8] <= din; + 4'd4: aend_b [ 7:0] <= din; + 4'd5: aend_b [15:8] <= din; + 4'h9: adeltan_b[ 7:0] <= din; + 4'ha: adeltan_b[15:8] <= din; + 4'hb: aeg_b <= din; + 4'hc: flag_ctl <= {din[7],din[5:0]}; // this lasts a single clock cycle + default:; + endcase + end + end + if( selected_register[1:0]==2'b11 ) + { up_chreg, up_opreg } <= { 3'h0, 7'h0 }; + else + casez( selected_register ) + // channel registers + 8'hA0, 8'hA1, 8'hA2: { up_chreg, up_opreg } <= { 3'h1, 7'd0 }; // up_fnumlo + // FB + Algorithm + 8'hB0, 8'hB1, 8'hB2: { up_chreg, up_opreg } <= { 3'h2, 7'd0 }; // up_alg + 8'hB4, 8'hB5, 8'hB6: { up_chreg, up_opreg } <= { 3'h4, 7'd0 }; // up_pms + // operator registers + 8'h3?: { up_chreg, up_opreg } <= { 3'h0, 7'h01 }; // up_dt1 + 8'h4?: { up_chreg, up_opreg } <= { 3'h0, 7'h02 }; // up_tl + 8'h5?: { up_chreg, up_opreg } <= { 3'h0, 7'h04 }; // up_ks_ar + 8'h6?: { up_chreg, up_opreg } <= { 3'h0, 7'h08 }; // up_amen_dr + 8'h7?: { up_chreg, up_opreg } <= { 3'h0, 7'h10 }; // up_sr + 8'h8?: { up_chreg, up_opreg } <= { 3'h0, 7'h20 }; // up_sl + 8'h9?: { up_chreg, up_opreg } <= { 3'h0, 7'h40 }; // up_ssgeg + default: { up_chreg, up_opreg } <= { 3'h0, 7'h0 }; + endcase // selected_register + end + end + else if(clk_en) begin /* clear once-only bits */ + // lfo_rst <= 1'b0; + { clr_flag_B, clr_flag_A } <= 2'd0; + psg_wr_n <= 1'b1; + pcm_wr <= 1'b0; + flag_ctl <= 'd0; + up_aon <= 1'b0; + acmd_up_b <= 1'b0; + end + end +end + +reg [4:0] busy_cnt; // busy lasts for 32 synth clock cycles, like in real chip + +always @(posedge clk, posedge rst) + if( rst ) begin + busy <= 1'b0; + busy_cnt <= 5'd0; + end + else begin + if (!old_write && write && addr[0] ) begin // only set for data writes + busy <= 1'b1; + busy_cnt <= 5'd0; + end + else if(clk_en) begin + if( busy_cnt == 5'd31 ) busy <= 1'b0; + busy_cnt <= busy_cnt+5'd1; + end + end +/* verilator tracing_on */ +jt12_reg #(.num_ch(num_ch)) u_reg( + .rst ( rst ), + .clk ( clk ), // P1 + .clk_en ( clk_en ), + .din ( din_copy ), + + .up_keyon ( up_keyon ), + .up_fnumlo ( up_chreg[0] ), + .up_alg ( up_chreg[1] ), + .up_pms ( up_chreg[2] ), + .up_dt1 ( up_opreg[0] ), + .up_tl ( up_opreg[1] ), + .up_ks_ar ( up_opreg[2] ), + .up_amen_dr ( up_opreg[3] ), + .up_sr ( up_opreg[4] ), + .up_sl_rr ( up_opreg[5] ), + .up_ssgeg ( up_opreg[6] ), + + .op ( up_op ), // operator to update + .ch ( up_ch ), // channel to update + + .csm ( csm ), + .flag_A ( flag_A ), + .overflow_A ( overflow_A), + + .ch6op ( ch6op ), + .cur_ch ( cur_ch ), + .cur_op ( cur_op ), + // CH3 Effect-mode operation + .effect ( effect ), // allows independent freq. for CH 3 + .fnum_ch3op2( fnum_ch3op2 ), + .fnum_ch3op3( fnum_ch3op3 ), + .fnum_ch3op1( fnum_ch3op1 ), + .block_ch3op2( block_ch3op2 ), + .block_ch3op3( block_ch3op3 ), + .block_ch3op1( block_ch3op1 ), + .latch_fnum ( latch_fnum ), + // Operator + .xuse_prevprev1 ( xuse_prevprev1 ), + .xuse_internal ( xuse_internal ), + .yuse_internal ( yuse_internal ), + .xuse_prev2 ( xuse_prev2 ), + .yuse_prev1 ( yuse_prev1 ), + .yuse_prev2 ( yuse_prev2 ), + // PG + .fnum_I ( fnum_I ), + .block_I ( block_I ), + .mul_II ( mul_II ), + .dt1_I ( dt1_I ), + + // EG + .ar_I (ar_I ), // attack rate + .d1r_I (d1r_I ), // decay rate + .d2r_I (d2r_I ), // sustain rate + .rr_I (rr_I ), // release rate + .sl_I (sl_I ), // sustain level + .ks_II (ks_II ), // key scale + // SSG operation + .ssg_en_I ( ssg_en_I ), + .ssg_eg_I ( ssg_eg_I ), + // envelope number + .tl_IV (tl_IV ), + .pms_I (pms_I ), + .ams_IV (ams_IV ), + .amsen_IV (amsen_IV ), + // channel configuration + .rl ( rl ), + .fb_II ( fb_II ), + .alg_I ( alg_I ), + .keyon_I ( keyon_I ), + + .zero ( zero ), + .s1_enters ( s1_enters ), + .s2_enters ( s2_enters ), + .s3_enters ( s3_enters ), + .s4_enters ( s4_enters ) +); + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_mmr_sim.vh b/common/Sound/JT12/hdl/jt12_mmr_sim.vh new file mode 100644 index 00000000..96d60d8f --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_mmr_sim.vh @@ -0,0 +1,854 @@ +`ifdef SIMULATION +/* verilator lint_off PINMISSING */ + +reg [4:0] sep24_cnt; +reg mmr_dump; + +always @(posedge clk ) if(clk_en) + sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0; + +wire [10:0] fnum_ch0s1, fnum_ch1s1, fnum_ch2s1, fnum_ch3s1, + fnum_ch4s1, fnum_ch5s1, fnum_ch0s2, fnum_ch1s2, + fnum_ch2s2, fnum_ch3s2, fnum_ch4s2, fnum_ch5s2, + fnum_ch0s3, fnum_ch1s3, fnum_ch2s3, fnum_ch3s3, + fnum_ch4s3, fnum_ch5s3, fnum_ch0s4, fnum_ch1s4, + fnum_ch2s4, fnum_ch3s4, fnum_ch4s4, fnum_ch5s4; + +sep24 #( .width(11), .pos0(1) ) fnum_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( fnum_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (fnum_ch0s1), + .ch1s1 (fnum_ch1s1), + .ch2s1 (fnum_ch2s1), + .ch3s1 (fnum_ch3s1), + .ch4s1 (fnum_ch4s1), + .ch5s1 (fnum_ch5s1), + + .ch0s2 (fnum_ch0s2), + .ch1s2 (fnum_ch1s2), + .ch2s2 (fnum_ch2s2), + .ch3s2 (fnum_ch3s2), + .ch4s2 (fnum_ch4s2), + .ch5s2 (fnum_ch5s2), + + .ch0s3 (fnum_ch0s3), + .ch1s3 (fnum_ch1s3), + .ch2s3 (fnum_ch2s3), + .ch3s3 (fnum_ch3s3), + .ch4s3 (fnum_ch4s3), + .ch5s3 (fnum_ch5s3), + + .ch0s4 (fnum_ch0s4), + .ch1s4 (fnum_ch1s4), + .ch2s4 (fnum_ch2s4), + .ch3s4 (fnum_ch3s4), + .ch4s4 (fnum_ch4s4), + .ch5s4 (fnum_ch5s4) +); + +wire [2:0] block_ch0s1, block_ch1s1, block_ch2s1, block_ch3s1, + block_ch4s1, block_ch5s1, block_ch0s2, block_ch1s2, + block_ch2s2, block_ch3s2, block_ch4s2, block_ch5s2, + block_ch0s3, block_ch1s3, block_ch2s3, block_ch3s3, + block_ch4s3, block_ch5s3, block_ch0s4, block_ch1s4, + block_ch2s4, block_ch3s4, block_ch4s4, block_ch5s4; + +sep24 #( .width(3), .pos0(1) ) block_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( block_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (block_ch0s1), + .ch1s1 (block_ch1s1), + .ch2s1 (block_ch2s1), + .ch3s1 (block_ch3s1), + .ch4s1 (block_ch4s1), + .ch5s1 (block_ch5s1), + + .ch0s2 (block_ch0s2), + .ch1s2 (block_ch1s2), + .ch2s2 (block_ch2s2), + .ch3s2 (block_ch3s2), + .ch4s2 (block_ch4s2), + .ch5s2 (block_ch5s2), + + .ch0s3 (block_ch0s3), + .ch1s3 (block_ch1s3), + .ch2s3 (block_ch2s3), + .ch3s3 (block_ch3s3), + .ch4s3 (block_ch4s3), + .ch5s3 (block_ch5s3), + + .ch0s4 (block_ch0s4), + .ch1s4 (block_ch1s4), + .ch2s4 (block_ch2s4), + .ch3s4 (block_ch3s4), + .ch4s4 (block_ch4s4), + .ch5s4 (block_ch5s4) +); + +wire [1:0] rl_ch0s1, rl_ch1s1, rl_ch2s1, rl_ch3s1, + rl_ch4s1, rl_ch5s1, rl_ch0s2, rl_ch1s2, + rl_ch2s2, rl_ch3s2, rl_ch4s2, rl_ch5s2, + rl_ch0s3, rl_ch1s3, rl_ch2s3, rl_ch3s3, + rl_ch4s3, rl_ch5s3, rl_ch0s4, rl_ch1s4, + rl_ch2s4, rl_ch3s4, rl_ch4s4, rl_ch5s4; + +sep24 #( .width(2), .pos0(1) ) rl_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( rl ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (rl_ch0s1), + .ch1s1 (rl_ch1s1), + .ch2s1 (rl_ch2s1), + .ch3s1 (rl_ch3s1), + .ch4s1 (rl_ch4s1), + .ch5s1 (rl_ch5s1), + + .ch0s2 (rl_ch0s2), + .ch1s2 (rl_ch1s2), + .ch2s2 (rl_ch2s2), + .ch3s2 (rl_ch3s2), + .ch4s2 (rl_ch4s2), + .ch5s2 (rl_ch5s2), + + .ch0s3 (rl_ch0s3), + .ch1s3 (rl_ch1s3), + .ch2s3 (rl_ch2s3), + .ch3s3 (rl_ch3s3), + .ch4s3 (rl_ch4s3), + .ch5s3 (rl_ch5s3), + + .ch0s4 (rl_ch0s4), + .ch1s4 (rl_ch1s4), + .ch2s4 (rl_ch2s4), + .ch3s4 (rl_ch3s4), + .ch4s4 (rl_ch4s4), + .ch5s4 (rl_ch5s4) +); + +wire [2:0] fb_ch0s1, fb_ch1s1, fb_ch2s1, fb_ch3s1, + fb_ch4s1, fb_ch5s1, fb_ch0s2, fb_ch1s2, + fb_ch2s2, fb_ch3s2, fb_ch4s2, fb_ch5s2, + fb_ch0s3, fb_ch1s3, fb_ch2s3, fb_ch3s3, + fb_ch4s3, fb_ch5s3, fb_ch0s4, fb_ch1s4, + fb_ch2s4, fb_ch3s4, fb_ch4s4, fb_ch5s4; + +sep24 #( .width(3), .pos0(0) ) fb_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( fb_II ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (fb_ch0s1), + .ch1s1 (fb_ch1s1), + .ch2s1 (fb_ch2s1), + .ch3s1 (fb_ch3s1), + .ch4s1 (fb_ch4s1), + .ch5s1 (fb_ch5s1), + + .ch0s2 (fb_ch0s2), + .ch1s2 (fb_ch1s2), + .ch2s2 (fb_ch2s2), + .ch3s2 (fb_ch3s2), + .ch4s2 (fb_ch4s2), + .ch5s2 (fb_ch5s2), + + .ch0s3 (fb_ch0s3), + .ch1s3 (fb_ch1s3), + .ch2s3 (fb_ch2s3), + .ch3s3 (fb_ch3s3), + .ch4s3 (fb_ch4s3), + .ch5s3 (fb_ch5s3), + + .ch0s4 (fb_ch0s4), + .ch1s4 (fb_ch1s4), + .ch2s4 (fb_ch2s4), + .ch3s4 (fb_ch3s4), + .ch4s4 (fb_ch4s4), + .ch5s4 (fb_ch5s4) +); + +wire [2:0] alg_ch0s1, alg_ch1s1, alg_ch2s1, alg_ch3s1, + alg_ch4s1, alg_ch5s1, alg_ch0s2, alg_ch1s2, + alg_ch2s2, alg_ch3s2, alg_ch4s2, alg_ch5s2, + alg_ch0s3, alg_ch1s3, alg_ch2s3, alg_ch3s3, + alg_ch4s3, alg_ch5s3, alg_ch0s4, alg_ch1s4, + alg_ch2s4, alg_ch3s4, alg_ch4s4, alg_ch5s4; + +sep24 #( .width(3), .pos0(1) ) alg_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( alg ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (alg_ch0s1), + .ch1s1 (alg_ch1s1), + .ch2s1 (alg_ch2s1), + .ch3s1 (alg_ch3s1), + .ch4s1 (alg_ch4s1), + .ch5s1 (alg_ch5s1), + + .ch0s2 (alg_ch0s2), + .ch1s2 (alg_ch1s2), + .ch2s2 (alg_ch2s2), + .ch3s2 (alg_ch3s2), + .ch4s2 (alg_ch4s2), + .ch5s2 (alg_ch5s2), + + .ch0s3 (alg_ch0s3), + .ch1s3 (alg_ch1s3), + .ch2s3 (alg_ch2s3), + .ch3s3 (alg_ch3s3), + .ch4s3 (alg_ch4s3), + .ch5s3 (alg_ch5s3), + + .ch0s4 (alg_ch0s4), + .ch1s4 (alg_ch1s4), + .ch2s4 (alg_ch2s4), + .ch3s4 (alg_ch3s4), + .ch4s4 (alg_ch4s4), + .ch5s4 (alg_ch5s4) +); + +wire [2:0] dt1_ch0s1, dt1_ch1s1, dt1_ch2s1, dt1_ch3s1, + dt1_ch4s1, dt1_ch5s1, dt1_ch0s2, dt1_ch1s2, + dt1_ch2s2, dt1_ch3s2, dt1_ch4s2, dt1_ch5s2, + dt1_ch0s3, dt1_ch1s3, dt1_ch2s3, dt1_ch3s3, + dt1_ch4s3, dt1_ch5s3, dt1_ch0s4, dt1_ch1s4, + dt1_ch2s4, dt1_ch3s4, dt1_ch4s4, dt1_ch5s4; + +sep24 #( .width(3), .pos0(0) ) dt1_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( dt1_II ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (dt1_ch0s1), + .ch1s1 (dt1_ch1s1), + .ch2s1 (dt1_ch2s1), + .ch3s1 (dt1_ch3s1), + .ch4s1 (dt1_ch4s1), + .ch5s1 (dt1_ch5s1), + + .ch0s2 (dt1_ch0s2), + .ch1s2 (dt1_ch1s2), + .ch2s2 (dt1_ch2s2), + .ch3s2 (dt1_ch3s2), + .ch4s2 (dt1_ch4s2), + .ch5s2 (dt1_ch5s2), + + .ch0s3 (dt1_ch0s3), + .ch1s3 (dt1_ch1s3), + .ch2s3 (dt1_ch2s3), + .ch3s3 (dt1_ch3s3), + .ch4s3 (dt1_ch4s3), + .ch5s3 (dt1_ch5s3), + + .ch0s4 (dt1_ch0s4), + .ch1s4 (dt1_ch1s4), + .ch2s4 (dt1_ch2s4), + .ch3s4 (dt1_ch3s4), + .ch4s4 (dt1_ch4s4), + .ch5s4 (dt1_ch5s4) +); + +wire [3:0] mul_ch0s1, mul_ch1s1, mul_ch2s1, mul_ch3s1, + mul_ch4s1, mul_ch5s1, mul_ch0s2, mul_ch1s2, + mul_ch2s2, mul_ch3s2, mul_ch4s2, mul_ch5s2, + mul_ch0s3, mul_ch1s3, mul_ch2s3, mul_ch3s3, + mul_ch4s3, mul_ch5s3, mul_ch0s4, mul_ch1s4, + mul_ch2s4, mul_ch3s4, mul_ch4s4, mul_ch5s4; + +sep24 #( .width(4), .pos0(21) ) mul_sep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( mul_V ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (mul_ch0s1), + .ch1s1 (mul_ch1s1), + .ch2s1 (mul_ch2s1), + .ch3s1 (mul_ch3s1), + .ch4s1 (mul_ch4s1), + .ch5s1 (mul_ch5s1), + + .ch0s2 (mul_ch0s2), + .ch1s2 (mul_ch1s2), + .ch2s2 (mul_ch2s2), + .ch3s2 (mul_ch3s2), + .ch4s2 (mul_ch4s2), + .ch5s2 (mul_ch5s2), + + .ch0s3 (mul_ch0s3), + .ch1s3 (mul_ch1s3), + .ch2s3 (mul_ch2s3), + .ch3s3 (mul_ch3s3), + .ch4s3 (mul_ch4s3), + .ch5s3 (mul_ch5s3), + + .ch0s4 (mul_ch0s4), + .ch1s4 (mul_ch1s4), + .ch2s4 (mul_ch2s4), + .ch3s4 (mul_ch3s4), + .ch4s4 (mul_ch4s4), + .ch5s4 (mul_ch5s4) +); + +wire [6:0] tl_ch0s1, tl_ch1s1, tl_ch2s1, tl_ch3s1, + tl_ch4s1, tl_ch5s1, tl_ch0s2, tl_ch1s2, + tl_ch2s2, tl_ch3s2, tl_ch4s2, tl_ch5s2, + tl_ch0s3, tl_ch1s3, tl_ch2s3, tl_ch3s3, + tl_ch4s3, tl_ch5s3, tl_ch0s4, tl_ch1s4, + tl_ch2s4, tl_ch3s4, tl_ch4s4, tl_ch5s4; + +sep24 #( .width(7), .pos0(22) ) tl_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( tl_IV ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (tl_ch0s1), + .ch1s1 (tl_ch1s1), + .ch2s1 (tl_ch2s1), + .ch3s1 (tl_ch3s1), + .ch4s1 (tl_ch4s1), + .ch5s1 (tl_ch5s1), + + .ch0s2 (tl_ch0s2), + .ch1s2 (tl_ch1s2), + .ch2s2 (tl_ch2s2), + .ch3s2 (tl_ch3s2), + .ch4s2 (tl_ch4s2), + .ch5s2 (tl_ch5s2), + + .ch0s3 (tl_ch0s3), + .ch1s3 (tl_ch1s3), + .ch2s3 (tl_ch2s3), + .ch3s3 (tl_ch3s3), + .ch4s3 (tl_ch4s3), + .ch5s3 (tl_ch5s3), + + .ch0s4 (tl_ch0s4), + .ch1s4 (tl_ch1s4), + .ch2s4 (tl_ch2s4), + .ch3s4 (tl_ch3s4), + .ch4s4 (tl_ch4s4), + .ch5s4 (tl_ch5s4) +); + +wire [4:0] ar_ch0s1, ar_ch1s1, ar_ch2s1, ar_ch3s1, + ar_ch4s1, ar_ch5s1, ar_ch0s2, ar_ch1s2, + ar_ch2s2, ar_ch3s2, ar_ch4s2, ar_ch5s2, + ar_ch0s3, ar_ch1s3, ar_ch2s3, ar_ch3s3, + ar_ch4s3, ar_ch5s3, ar_ch0s4, ar_ch1s4, + ar_ch2s4, ar_ch3s4, ar_ch4s4, ar_ch5s4; + +sep24 #( .width(5), .pos0(1) ) ar_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( ar_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (ar_ch0s1), + .ch1s1 (ar_ch1s1), + .ch2s1 (ar_ch2s1), + .ch3s1 (ar_ch3s1), + .ch4s1 (ar_ch4s1), + .ch5s1 (ar_ch5s1), + + .ch0s2 (ar_ch0s2), + .ch1s2 (ar_ch1s2), + .ch2s2 (ar_ch2s2), + .ch3s2 (ar_ch3s2), + .ch4s2 (ar_ch4s2), + .ch5s2 (ar_ch5s2), + + .ch0s3 (ar_ch0s3), + .ch1s3 (ar_ch1s3), + .ch2s3 (ar_ch2s3), + .ch3s3 (ar_ch3s3), + .ch4s3 (ar_ch4s3), + .ch5s3 (ar_ch5s3), + + .ch0s4 (ar_ch0s4), + .ch1s4 (ar_ch1s4), + .ch2s4 (ar_ch2s4), + .ch3s4 (ar_ch3s4), + .ch4s4 (ar_ch4s4), + .ch5s4 (ar_ch5s4) +); + +wire [4:0] d1r_ch0s1, d1r_ch1s1, d1r_ch2s1, d1r_ch3s1, + d1r_ch4s1, d1r_ch5s1, d1r_ch0s2, d1r_ch1s2, + d1r_ch2s2, d1r_ch3s2, d1r_ch4s2, d1r_ch5s2, + d1r_ch0s3, d1r_ch1s3, d1r_ch2s3, d1r_ch3s3, + d1r_ch4s3, d1r_ch5s3, d1r_ch0s4, d1r_ch1s4, + d1r_ch2s4, d1r_ch3s4, d1r_ch4s4, d1r_ch5s4; + +sep24 #( .width(5), .pos0(1) ) d1r_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( d1r_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (d1r_ch0s1), + .ch1s1 (d1r_ch1s1), + .ch2s1 (d1r_ch2s1), + .ch3s1 (d1r_ch3s1), + .ch4s1 (d1r_ch4s1), + .ch5s1 (d1r_ch5s1), + + .ch0s2 (d1r_ch0s2), + .ch1s2 (d1r_ch1s2), + .ch2s2 (d1r_ch2s2), + .ch3s2 (d1r_ch3s2), + .ch4s2 (d1r_ch4s2), + .ch5s2 (d1r_ch5s2), + + .ch0s3 (d1r_ch0s3), + .ch1s3 (d1r_ch1s3), + .ch2s3 (d1r_ch2s3), + .ch3s3 (d1r_ch3s3), + .ch4s3 (d1r_ch4s3), + .ch5s3 (d1r_ch5s3), + + .ch0s4 (d1r_ch0s4), + .ch1s4 (d1r_ch1s4), + .ch2s4 (d1r_ch2s4), + .ch3s4 (d1r_ch3s4), + .ch4s4 (d1r_ch4s4), + .ch5s4 (d1r_ch5s4) +); + +wire [4:0] d2r_ch0s1, d2r_ch1s1, d2r_ch2s1, d2r_ch3s1, + d2r_ch4s1, d2r_ch5s1, d2r_ch0s2, d2r_ch1s2, + d2r_ch2s2, d2r_ch3s2, d2r_ch4s2, d2r_ch5s2, + d2r_ch0s3, d2r_ch1s3, d2r_ch2s3, d2r_ch3s3, + d2r_ch4s3, d2r_ch5s3, d2r_ch0s4, d2r_ch1s4, + d2r_ch2s4, d2r_ch3s4, d2r_ch4s4, d2r_ch5s4; + +sep24 #( .width(5), .pos0(1) ) d2r_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( d2r_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (d2r_ch0s1), + .ch1s1 (d2r_ch1s1), + .ch2s1 (d2r_ch2s1), + .ch3s1 (d2r_ch3s1), + .ch4s1 (d2r_ch4s1), + .ch5s1 (d2r_ch5s1), + + .ch0s2 (d2r_ch0s2), + .ch1s2 (d2r_ch1s2), + .ch2s2 (d2r_ch2s2), + .ch3s2 (d2r_ch3s2), + .ch4s2 (d2r_ch4s2), + .ch5s2 (d2r_ch5s2), + + .ch0s3 (d2r_ch0s3), + .ch1s3 (d2r_ch1s3), + .ch2s3 (d2r_ch2s3), + .ch3s3 (d2r_ch3s3), + .ch4s3 (d2r_ch4s3), + .ch5s3 (d2r_ch5s3), + + .ch0s4 (d2r_ch0s4), + .ch1s4 (d2r_ch1s4), + .ch2s4 (d2r_ch2s4), + .ch3s4 (d2r_ch3s4), + .ch4s4 (d2r_ch4s4), + .ch5s4 (d2r_ch5s4) +); + +wire [3:0] rr_ch0s1, rr_ch1s1, rr_ch2s1, rr_ch3s1, + rr_ch4s1, rr_ch5s1, rr_ch0s2, rr_ch1s2, + rr_ch2s2, rr_ch3s2, rr_ch4s2, rr_ch5s2, + rr_ch0s3, rr_ch1s3, rr_ch2s3, rr_ch3s3, + rr_ch4s3, rr_ch5s3, rr_ch0s4, rr_ch1s4, + rr_ch2s4, rr_ch3s4, rr_ch4s4, rr_ch5s4; + +sep24 #( .width(4), .pos0(1) ) rr_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( rr_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (rr_ch0s1), + .ch1s1 (rr_ch1s1), + .ch2s1 (rr_ch2s1), + .ch3s1 (rr_ch3s1), + .ch4s1 (rr_ch4s1), + .ch5s1 (rr_ch5s1), + + .ch0s2 (rr_ch0s2), + .ch1s2 (rr_ch1s2), + .ch2s2 (rr_ch2s2), + .ch3s2 (rr_ch3s2), + .ch4s2 (rr_ch4s2), + .ch5s2 (rr_ch5s2), + + .ch0s3 (rr_ch0s3), + .ch1s3 (rr_ch1s3), + .ch2s3 (rr_ch2s3), + .ch3s3 (rr_ch3s3), + .ch4s3 (rr_ch4s3), + .ch5s3 (rr_ch5s3), + + .ch0s4 (rr_ch0s4), + .ch1s4 (rr_ch1s4), + .ch2s4 (rr_ch2s4), + .ch3s4 (rr_ch3s4), + .ch4s4 (rr_ch4s4), + .ch5s4 (rr_ch5s4) +); + +wire [3:0] d1l_ch0s1, d1l_ch1s1, d1l_ch2s1, d1l_ch3s1, + d1l_ch4s1, d1l_ch5s1, d1l_ch0s2, d1l_ch1s2, + d1l_ch2s2, d1l_ch3s2, d1l_ch4s2, d1l_ch5s2, + d1l_ch0s3, d1l_ch1s3, d1l_ch2s3, d1l_ch3s3, + d1l_ch4s3, d1l_ch5s3, d1l_ch0s4, d1l_ch1s4, + d1l_ch2s4, d1l_ch3s4, d1l_ch4s4, d1l_ch5s4; + +sep24 #( .width(4), .pos0(1) ) d1l_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( sl_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (d1l_ch0s1), + .ch1s1 (d1l_ch1s1), + .ch2s1 (d1l_ch2s1), + .ch3s1 (d1l_ch3s1), + .ch4s1 (d1l_ch4s1), + .ch5s1 (d1l_ch5s1), + + .ch0s2 (d1l_ch0s2), + .ch1s2 (d1l_ch1s2), + .ch2s2 (d1l_ch2s2), + .ch3s2 (d1l_ch3s2), + .ch4s2 (d1l_ch4s2), + .ch5s2 (d1l_ch5s2), + + .ch0s3 (d1l_ch0s3), + .ch1s3 (d1l_ch1s3), + .ch2s3 (d1l_ch2s3), + .ch3s3 (d1l_ch3s3), + .ch4s3 (d1l_ch4s3), + .ch5s3 (d1l_ch5s3), + + .ch0s4 (d1l_ch0s4), + .ch1s4 (d1l_ch1s4), + .ch2s4 (d1l_ch2s4), + .ch3s4 (d1l_ch3s4), + .ch4s4 (d1l_ch4s4), + .ch5s4 (d1l_ch5s4) +); + +wire [1:0] ks_ch0s1, ks_ch1s1, ks_ch2s1, ks_ch3s1, + ks_ch4s1, ks_ch5s1, ks_ch0s2, ks_ch1s2, + ks_ch2s2, ks_ch3s2, ks_ch4s2, ks_ch5s2, + ks_ch0s3, ks_ch1s3, ks_ch2s3, ks_ch3s3, + ks_ch4s3, ks_ch5s3, ks_ch0s4, ks_ch1s4, + ks_ch2s4, ks_ch3s4, ks_ch4s4, ks_ch5s4; + +sep24 #( .width(2), .pos0(0) ) ks_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( ks_II ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (ks_ch0s1), + .ch1s1 (ks_ch1s1), + .ch2s1 (ks_ch2s1), + .ch3s1 (ks_ch3s1), + .ch4s1 (ks_ch4s1), + .ch5s1 (ks_ch5s1), + + .ch0s2 (ks_ch0s2), + .ch1s2 (ks_ch1s2), + .ch2s2 (ks_ch2s2), + .ch3s2 (ks_ch3s2), + .ch4s2 (ks_ch4s2), + .ch5s2 (ks_ch5s2), + + .ch0s3 (ks_ch0s3), + .ch1s3 (ks_ch1s3), + .ch2s3 (ks_ch2s3), + .ch3s3 (ks_ch3s3), + .ch4s3 (ks_ch4s3), + .ch5s3 (ks_ch5s3), + + .ch0s4 (ks_ch0s4), + .ch1s4 (ks_ch1s4), + .ch2s4 (ks_ch2s4), + .ch3s4 (ks_ch3s4), + .ch4s4 (ks_ch4s4), + .ch5s4 (ks_ch5s4) +); + +wire [3:0] ssg_I = {ssg_en_I, ssg_eg_I}; + +wire [3:0] ssg_ch0s1, ssg_ch1s1, ssg_ch2s1, ssg_ch3s1, + ssg_ch4s1, ssg_ch5s1, ssg_ch0s2, ssg_ch1s2, + ssg_ch2s2, ssg_ch3s2, ssg_ch4s2, ssg_ch5s2, + ssg_ch0s3, ssg_ch1s3, ssg_ch2s3, ssg_ch3s3, + ssg_ch4s3, ssg_ch5s3, ssg_ch0s4, ssg_ch1s4, + ssg_ch2s4, ssg_ch3s4, ssg_ch4s4, ssg_ch5s4; + +sep24 #( .width(4), .pos0(1) ) ssg_step +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( ssg_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (ssg_ch0s1), + .ch1s1 (ssg_ch1s1), + .ch2s1 (ssg_ch2s1), + .ch3s1 (ssg_ch3s1), + .ch4s1 (ssg_ch4s1), + .ch5s1 (ssg_ch5s1), + + .ch0s2 (ssg_ch0s2), + .ch1s2 (ssg_ch1s2), + .ch2s2 (ssg_ch2s2), + .ch3s2 (ssg_ch3s2), + .ch4s2 (ssg_ch4s2), + .ch5s2 (ssg_ch5s2), + + .ch0s3 (ssg_ch0s3), + .ch1s3 (ssg_ch1s3), + .ch2s3 (ssg_ch2s3), + .ch3s3 (ssg_ch3s3), + .ch4s3 (ssg_ch4s3), + .ch5s3 (ssg_ch5s3), + + .ch0s4 (ssg_ch0s4), + .ch1s4 (ssg_ch1s4), + .ch2s4 (ssg_ch2s4), + .ch3s4 (ssg_ch3s4), + .ch4s4 (ssg_ch4s4), + .ch5s4 (ssg_ch5s4) +); + +wire kon_ch0s1, kon_ch1s1, kon_ch2s1, kon_ch3s1, + kon_ch4s1, kon_ch5s1, kon_ch0s2, kon_ch1s2, + kon_ch2s2, kon_ch3s2, kon_ch4s2, kon_ch5s2, + kon_ch0s3, kon_ch1s3, kon_ch2s3, kon_ch3s3, + kon_ch4s3, kon_ch5s3, kon_ch0s4, kon_ch1s4, + kon_ch2s4, kon_ch3s4, kon_ch4s4, kon_ch5s4; + +sep24 #( .width(1), .pos0(1) ) konstep +( + .clk ( clk ), + .clk_en ( clk_en ), + .mixed ( keyon_I ), + .mask ( 24'd0 ), + .cnt ( sep24_cnt ), + + .ch0s1 (kon_ch0s1), + .ch1s1 (kon_ch1s1), + .ch2s1 (kon_ch2s1), + .ch3s1 (kon_ch3s1), + .ch4s1 (kon_ch4s1), + .ch5s1 (kon_ch5s1), + + .ch0s2 (kon_ch0s2), + .ch1s2 (kon_ch1s2), + .ch2s2 (kon_ch2s2), + .ch3s2 (kon_ch3s2), + .ch4s2 (kon_ch4s2), + .ch5s2 (kon_ch5s2), + + .ch0s3 (kon_ch0s3), + .ch1s3 (kon_ch1s3), + .ch2s3 (kon_ch2s3), + .ch3s3 (kon_ch3s3), + .ch4s3 (kon_ch4s3), + .ch5s3 (kon_ch5s3), + + .ch0s4 (kon_ch0s4), + .ch1s4 (kon_ch1s4), + .ch2s4 (kon_ch2s4), + .ch3s4 (kon_ch3s4), + .ch4s4 (kon_ch4s4), + .ch5s4 (kon_ch5s4) +); + +/* Dump all registers on request */ +integer fmmr; +initial begin + fmmr=$fopen("mmr_dump.log","w"); +end + +always @(posedge clk ) +if (mmr_dump ) begin + $fdisplay( fmmr, "-------------------------------"); + // Channel 0 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch0s1, fnum_ch0s1, rl_ch0s1, fb_ch0s1, alg_ch0s1, + dt1_ch0s1, mul_ch0s1, tl_ch0s1, ar_ch0s1, d1r_ch0s1, + d2r_ch0s1, rr_ch0s1, d1l_ch0s1, ks_ch0s1, ssg_ch0s1, + kon_ch0s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch0s2, fnum_ch0s2, rl_ch0s2, fb_ch0s2, alg_ch0s2, + dt1_ch0s2, mul_ch0s2, tl_ch0s2, ar_ch0s2, d1r_ch0s2, + d2r_ch0s2, rr_ch0s2, d1l_ch0s2, ks_ch0s2, ssg_ch0s2, + kon_ch0s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch0s1, fnum_ch0s3, rl_ch0s3, fb_ch0s3, alg_ch0s3, + dt1_ch0s3, mul_ch0s3, tl_ch0s3, ar_ch0s3, d1r_ch0s3, + d2r_ch0s3, rr_ch0s3, d1l_ch0s3, ks_ch0s3, ssg_ch0s3, + kon_ch0s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch0s4, fnum_ch0s4, rl_ch0s4, fb_ch0s4, alg_ch0s4, + dt1_ch0s4, mul_ch0s4, tl_ch0s4, ar_ch0s4, d1r_ch0s4, + d2r_ch0s4, rr_ch0s4, d1l_ch0s4, ks_ch0s4, ssg_ch0s4, + kon_ch0s4 ); + // Channel 1 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch1s1, fnum_ch1s1, rl_ch1s1, fb_ch1s1, alg_ch1s1, + dt1_ch1s1, mul_ch1s1, tl_ch1s1, ar_ch1s1, d1r_ch1s1, + d2r_ch1s1, rr_ch1s1, d1l_ch1s1, ks_ch1s1, ssg_ch1s1, + kon_ch1s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch1s2, fnum_ch1s2, rl_ch1s2, fb_ch1s2, alg_ch1s2, + dt1_ch1s2, mul_ch1s2, tl_ch1s2, ar_ch1s2, d1r_ch1s2, + d2r_ch1s2, rr_ch1s2, d1l_ch1s2, ks_ch1s2, ssg_ch1s2, + kon_ch1s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch1s3, fnum_ch1s3, rl_ch1s3, fb_ch1s3, alg_ch1s3, + dt1_ch1s3, mul_ch1s3, tl_ch1s3, ar_ch1s3, d1r_ch1s3, + d2r_ch1s3, rr_ch1s3, d1l_ch1s3, ks_ch1s3, ssg_ch1s3, + kon_ch1s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch1s4, fnum_ch1s4, rl_ch1s4, fb_ch1s4, alg_ch1s4, + dt1_ch1s4, mul_ch1s4, tl_ch1s4, ar_ch1s4, d1r_ch1s4, + d2r_ch1s4, rr_ch1s4, d1l_ch1s4, ks_ch1s4, ssg_ch1s4, + kon_ch1s4 ); + // Channel 2 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch2s1, fnum_ch2s1, rl_ch2s1, fb_ch2s1, alg_ch2s1, + dt1_ch2s1, mul_ch2s1, tl_ch2s1, ar_ch2s1, d1r_ch2s1, + d2r_ch2s1, rr_ch2s1, d1l_ch2s1, ks_ch2s1, ssg_ch2s1, + kon_ch2s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch2s2, fnum_ch2s2, rl_ch2s2, fb_ch2s2, alg_ch2s2, + dt1_ch2s2, mul_ch2s2, tl_ch2s2, ar_ch2s2, d1r_ch2s2, + d2r_ch2s2, rr_ch2s2, d1l_ch2s2, ks_ch2s2, ssg_ch2s2, + kon_ch2s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch2s3, fnum_ch2s3, rl_ch2s3, fb_ch2s3, alg_ch2s3, + dt1_ch2s3, mul_ch2s3, tl_ch2s3, ar_ch2s3, d1r_ch2s3, + d2r_ch2s3, rr_ch2s3, d1l_ch2s3, ks_ch2s3, ssg_ch2s3, + kon_ch2s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch2s4, fnum_ch2s4, rl_ch2s4, fb_ch2s4, alg_ch2s4, + dt1_ch2s4, mul_ch2s4, tl_ch2s4, ar_ch2s4, d1r_ch2s4, + d2r_ch2s4, rr_ch2s4, d1l_ch2s4, ks_ch2s4, ssg_ch2s4, + kon_ch2s4 ); + // Channel 3 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch3s1, fnum_ch3s1, rl_ch3s1, fb_ch3s1, alg_ch3s1, + dt1_ch3s1, mul_ch3s1, tl_ch3s1, ar_ch3s1, d1r_ch3s1, + d2r_ch3s1, rr_ch3s1, d1l_ch3s1, ks_ch3s1, ssg_ch3s1, + kon_ch3s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch3s2, fnum_ch3s2, rl_ch3s2, fb_ch3s2, alg_ch3s2, + dt1_ch3s2, mul_ch3s2, tl_ch3s2, ar_ch3s2, d1r_ch3s2, + d2r_ch3s2, rr_ch3s2, d1l_ch3s2, ks_ch3s2, ssg_ch3s2, + kon_ch3s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch3s3, fnum_ch3s3, rl_ch3s3, fb_ch3s3, alg_ch3s3, + dt1_ch3s3, mul_ch3s3, tl_ch3s3, ar_ch3s3, d1r_ch3s3, + d2r_ch3s3, rr_ch3s3, d1l_ch3s3, ks_ch3s3, ssg_ch3s3, + kon_ch3s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch3s4, fnum_ch3s4, rl_ch3s4, fb_ch3s4, alg_ch3s4, + dt1_ch3s4, mul_ch3s4, tl_ch3s4, ar_ch3s4, d1r_ch3s4, + d2r_ch3s4, rr_ch3s4, d1l_ch3s4, ks_ch3s4, ssg_ch3s4, + kon_ch3s4 ); + // Channel 4 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch4s1, fnum_ch4s1, rl_ch4s1, fb_ch4s1, alg_ch4s1, + dt1_ch4s1, mul_ch4s1, tl_ch4s1, ar_ch4s1, d1r_ch4s1, + d2r_ch4s1, rr_ch4s1, d1l_ch4s1, ks_ch4s1, ssg_ch4s1, + kon_ch4s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch4s2, fnum_ch4s2, rl_ch4s2, fb_ch4s2, alg_ch4s2, + dt1_ch4s2, mul_ch4s2, tl_ch4s2, ar_ch4s2, d1r_ch4s2, + d2r_ch4s2, rr_ch4s2, d1l_ch4s2, ks_ch4s2, ssg_ch4s2, + kon_ch4s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch4s3, fnum_ch4s3, rl_ch4s3, fb_ch4s3, alg_ch4s3, + dt1_ch4s3, mul_ch4s3, tl_ch4s3, ar_ch4s3, d1r_ch4s3, + d2r_ch4s3, rr_ch4s3, d1l_ch4s3, ks_ch4s3, ssg_ch4s3, + kon_ch4s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch4s4, fnum_ch4s4, rl_ch4s4, fb_ch4s4, alg_ch4s4, + dt1_ch4s4, mul_ch4s4, tl_ch4s4, ar_ch4s4, d1r_ch4s4, + d2r_ch4s4, rr_ch4s4, d1l_ch4s4, ks_ch4s4, ssg_ch4s4, + kon_ch4s4 ); + // Channel 5 + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch5s1, fnum_ch5s1, rl_ch5s1, fb_ch5s1, alg_ch5s1, + dt1_ch5s1, mul_ch5s1, tl_ch5s1, ar_ch5s1, d1r_ch5s1, + d2r_ch5s1, rr_ch5s1, d1l_ch5s1, ks_ch5s1, ssg_ch5s1, + kon_ch5s1 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch5s2, fnum_ch5s2, rl_ch5s2, fb_ch5s2, alg_ch5s2, + dt1_ch5s2, mul_ch5s2, tl_ch5s2, ar_ch5s2, d1r_ch5s2, + d2r_ch5s2, rr_ch5s2, d1l_ch5s2, ks_ch5s2, ssg_ch5s2, + kon_ch5s2 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch5s3, fnum_ch5s3, rl_ch5s3, fb_ch5s3, alg_ch5s3, + dt1_ch5s3, mul_ch5s3, tl_ch5s3, ar_ch5s3, d1r_ch5s3, + d2r_ch5s3, rr_ch5s3, d1l_ch5s3, ks_ch5s3, ssg_ch5s3, + kon_ch5s3 ); + $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x", + block_ch5s4, fnum_ch5s4, rl_ch5s4, fb_ch5s4, alg_ch5s4, + dt1_ch5s4, mul_ch5s4, tl_ch5s4, ar_ch5s4, d1r_ch5s4, + d2r_ch5s4, rr_ch5s4, d1l_ch5s4, ks_ch5s4, ssg_ch5s4, + kon_ch5s4 ); +end +/* verilator lint_on PINMISSING */ +`endif + diff --git a/common/Sound/JT12/hdl/jt12_mod.v b/common/Sound/JT12/hdl/jt12_mod.v new file mode 100644 index 00000000..93ac478b --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_mod.v @@ -0,0 +1,153 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +module jt12_mod( + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + + input [2:0] alg_I, + + output reg xuse_prevprev1, + output reg xuse_internal, + output reg yuse_internal, + output reg xuse_prev2, + output reg yuse_prev1, + output reg yuse_prev2 +); + +parameter num_ch=6; + +reg [7:0] alg_hot; + +always @(*) begin + case( alg_I ) + 3'd0: alg_hot = 8'h1; // D0 + 3'd1: alg_hot = 8'h2; // D1 + 3'd2: alg_hot = 8'h4; // D2 + 3'd3: alg_hot = 8'h8; // D3 + 3'd4: alg_hot = 8'h10; // D4 + 3'd5: alg_hot = 8'h20; // D5 + 3'd6: alg_hot = 8'h40; // D6 + 3'd7: alg_hot = 8'h80; // D7 + endcase +end + +// prev2 cannot modulate with prevprev1 at the same time +// x = prev2, prevprev1, internal_x +// y = prev1, internal_y + +generate + if( num_ch==6 ) begin + always @(*) begin + xuse_prevprev1 = s1_enters | (s3_enters&alg_hot[5]); + xuse_prev2 = (s3_enters&(|alg_hot[2:0])) | (s4_enters&alg_hot[3]); + xuse_internal = s4_enters & alg_hot[2]; + yuse_internal = s4_enters & (|{alg_hot[4:3],alg_hot[1:0]}); + yuse_prev1 = s1_enters | (s3_enters&alg_hot[1]) | + (s2_enters&(|{alg_hot[6:3],alg_hot[0]}) )| + (s4_enters&(|{alg_hot[5],alg_hot[2]})); + yuse_prev2 = 1'b0; // unused for 6 channels + end + end else begin + reg [2:0] xuse_s4, xuse_s3, xuse_s2, xuse_s1; + reg [2:0] yuse_s4, yuse_s3, yuse_s2, yuse_s1; + always @(*) begin // 3 ch + // S1 + { xuse_s1, yuse_s1 } = { 3'b001, 3'b100 }; + // S2 + casez( 1'b1 ) + // S2 modulated by S1 + alg_hot[6], alg_hot[5], alg_hot[4], alg_hot[3], alg_hot[0]: + { xuse_s2, yuse_s2 } = { 3'b000, 3'b100 }; // prev1 + default: { xuse_s2, yuse_s2 } = 6'd0; + endcase + // S3 + casez( 1'b1 ) + // S3 modulated by S1 + alg_hot[5]: + { xuse_s3, yuse_s3 } = { 3'b000, 3'b100 }; // prev1 + // S3 modulated by S2 + alg_hot[2], alg_hot[0]: + { xuse_s3, yuse_s3 } = { 3'b000, 3'b010 }; // prev2 + // S3 modulated by S2+S1 + alg_hot[1]: + { xuse_s3, yuse_s3 } = { 3'b010, 3'b100 }; // prev2 + prev1 + default: { xuse_s3, yuse_s3 } = 6'd0; + endcase + // S4 + casez( 1'b1 ) + // S4 modulated by S1 + alg_hot[5]: + { xuse_s4, yuse_s4 } = { 3'b000, 3'b100 }; // prev1 + // S4 modulated by S3 + alg_hot[4], alg_hot[1], alg_hot[0]: + { xuse_s4, yuse_s4 } = { 3'b100, 3'b000 }; // prevprev1 + // S4 modulated by S3+S2 + alg_hot[3]: + { xuse_s4, yuse_s4 } = { 3'b100, 3'b010 }; // prevprev1+prev2 + // S4 modulated by S3+S1 + alg_hot[2]: + { xuse_s4, yuse_s4 } = { 3'b100, 3'b100 }; // prevprev1+prev1 + default: { xuse_s4, yuse_s4 } = 6'd0; + endcase + case( {s4_enters, s3_enters, s2_enters, s1_enters}) + 4'b1000: begin + {xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s4; + {yuse_prev1, yuse_prev2, yuse_internal } = yuse_s4; + end + 4'b0100: begin + {xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s3; + {yuse_prev1, yuse_prev2, yuse_internal } = yuse_s3; + end + 4'b0010: begin + {xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s2; + {yuse_prev1, yuse_prev2, yuse_internal } = yuse_s2; + end + 4'b0001: begin + {xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s1; + {yuse_prev1, yuse_prev2, yuse_internal } = yuse_s1; + end + default: begin + {xuse_prevprev1, xuse_prev2, xuse_internal} = 3'b0; + {yuse_prev1, yuse_prev2, yuse_internal } = 3'b0; + end + endcase + end + end +endgenerate + +// Control signals for simulation: should be 2'b0 or 2'b1 +// wire [1:0] xusage = xuse_prevprev1+xuse_prev2+xuse_internal; +// wire [1:0] yusage = yuse_prev1+yuse_internal; +// +// always @(xusage,yusage) +// if( xusage>2'b1 || yusage>2'b1 ) begin +// $display("ERROR: x/y over use in jt12_mod"); +// $finish; +// end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_op.v b/common/Sound/JT12/hdl/jt12_op.v new file mode 100644 index 00000000..43e14542 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_op.v @@ -0,0 +1,332 @@ +`timescale 1ns / 1ps + + +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + + +module jt12_op( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input [9:0] pg_phase_VIII, + input [9:0] eg_atten_IX, // output from envelope generator + input [2:0] fb_II, // voice feedback + input xuse_prevprev1, + input xuse_prev2, + input xuse_internal, + input yuse_prev1, + input yuse_prev2, + input yuse_internal, + input test_214, + + input s1_enters, + input s2_enters, + input s3_enters, + input s4_enters, + input zero, + + output signed [ 8:0] op_result, + output signed [13:0] full_result +); + +parameter num_ch = 6; + +/* enters exits + S1 S2 + S3 S4 + S2 S1 + S4 S3 +*/ + +reg [13:0] op_result_internal, op_XII; +reg [11:0] atten_internal_IX; + +assign op_result = op_result_internal[13:5]; +assign full_result = op_result_internal; + +reg signbit_IX, signbit_X, signbit_XI; +reg [11:0] totalatten_X; + +wire [13:0] prev1, prevprev1, prev2; + +reg [13:0] prev1_din, prevprev1_din, prev2_din; + +always @(*) + if( num_ch==3 ) begin + prev1_din = s1_enters ? op_result_internal : prev1; + prevprev1_din = s3_enters ? op_result_internal : prevprev1; + prev2_din = s2_enters ? op_result_internal : prev2; + end else begin // 6 channels + prev1_din = s2_enters ? op_result_internal : prev1; + prevprev1_din = s2_enters ? prev1 : prevprev1; + prev2_din = s1_enters ? op_result_internal : prev2; + end + +jt12_sh #( .width(14), .stages(num_ch)) prev1_buffer( +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( prev1_din ), + .drop ( prev1 ) +); + +jt12_sh #( .width(14), .stages(num_ch)) prevprev1_buffer( +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( prevprev1_din ), + .drop ( prevprev1 ) +); + +jt12_sh #( .width(14), .stages(num_ch)) prev2_buffer( +// .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( prev2_din ), + .drop ( prev2 ) +); + + +reg [10:0] subtresult; + +reg [12:0] shifter, shifter_2, shifter_3; + +// REGISTER/CYCLE 1 +// Creation of phase modulation (FM) feedback signal, before shifting +reg [13:0] x, y; +reg [14:0] xs, ys, pm_preshift_II; +reg s1_II; + +always @(*) begin + casez( {xuse_prevprev1, xuse_prev2, xuse_internal }) + 3'b1??: x = prevprev1; + 3'b01?: x = prev2; + 3'b001: x = op_result_internal; + default: x = 14'd0; + endcase + casez( {yuse_prev1, yuse_prev2, yuse_internal }) + 3'b1??: y = prev1; + 3'b01?: y = prev2; + 3'b001: y = op_result_internal; + default: y = 14'd0; + endcase + xs = { x[13], x }; // sign-extend + ys = { y[13], y }; // sign-extend +end + +always @(posedge clk) if( clk_en ) begin + pm_preshift_II <= xs + ys; // carry is discarded + s1_II <= s1_enters; +end + +/* REGISTER/CYCLE 2-7 (also YM2612 extra cycles 1-6) + Shifting of FM feedback signal, adding phase from PG to FM phase + In YM2203, phasemod_II is not registered at all, it is latched on the first edge + in add_pg_phase and the second edge is the output of add_pg_phase. In the YM2612, there + are 6 cycles worth of registers between the generated (non-registered) phasemod_II signal + and the input to add_pg_phase. */ + +reg [9:0] phasemod_II; +wire [9:0] phasemod_VIII; + +always @(*) begin + // Shift FM feedback signal + if (!s1_II ) // Not S1 + phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used + else // S1 + case( fb_II ) + 3'd0: phasemod_II = 10'd0; + 3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] }; + 3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] }; + 3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] }; + 3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] }; + 3'd5: phasemod_II = pm_preshift_II[14:5]; + 3'd6: phasemod_II = pm_preshift_II[13:4]; + 3'd7: phasemod_II = pm_preshift_II[12:3]; + endcase +end + +// REGISTER/CYCLE 2-7 +//generate +// if( num_ch==6 ) + jt12_sh #( .width(10), .stages(6)) phasemod_sh( + .clk ( clk ), + .clk_en ( clk_en), + .din ( phasemod_II ), + .drop ( phasemod_VIII ) + ); +// else begin +// assign phasemod_VIII = phasemod_II; +// end +// endgenerate + +// REGISTER/CYCLE 8 +reg [ 9:0] phase; +// Sets the maximum number of fanouts for a register or combinational +// cell. The Quartus II software will replicate the cell and split +// the fanouts among the duplicates until the fanout of each cell +// is below the maximum. + +reg [ 7:0] aux_VIII; + +always @(*) begin + phase = phasemod_VIII + pg_phase_VIII; + aux_VIII= phase[7:0] ^ {8{~phase[8]}}; +end + +always @(posedge clk) if( clk_en ) begin + signbit_IX <= phase[9]; +end + +wire [11:0] logsin_IX; + +jt12_logsin u_logsin ( + .clk ( clk ), + .clk_en ( clk_en ), + .addr ( aux_VIII[7:0] ), + .logsin ( logsin_IX ) +); + + +// REGISTER/CYCLE 9 +// Sine table +// Main sine table body + +always @(*) begin + subtresult = eg_atten_IX + logsin_IX[11:2]; + atten_internal_IX = { subtresult[9:0], logsin_IX[1:0] } | {12{subtresult[10]}}; +end + +wire [9:0] mantissa_X; +reg [9:0] mantissa_XI; +reg [3:0] exponent_X, exponent_XI; + +jt12_exprom u_exprom( + .clk ( clk ), + .clk_en ( clk_en ), + .addr ( atten_internal_IX[7:0] ), + .exp ( mantissa_X ) +); + +always @(posedge clk) if( clk_en ) begin + exponent_X <= atten_internal_IX[11:8]; + signbit_X <= signbit_IX; +end + +always @(posedge clk) if( clk_en ) begin + mantissa_XI <= mantissa_X; + exponent_XI <= exponent_X; + signbit_XI <= signbit_X; +end + +// REGISTER/CYCLE 11 +// Introduce test bit as MSB, 2's complement & Carry-out discarded + +always @(*) begin + // Floating-point to integer, and incorporating sign bit + // Two-stage shifting of mantissa_XI by exponent_XI + shifter = { 3'b001, mantissa_XI }; + case( ~exponent_XI[1:0] ) + 2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded + 2'b01: shifter_2 = shifter; + 2'b10: shifter_2 = { shifter[11:0], 1'b0 }; + 2'b11: shifter_2 = { shifter[10:0], 2'b0 }; + endcase + case( ~exponent_XI[3:2] ) + 2'b00: shifter_3 = {12'b0, shifter_2[12] }; + 2'b01: shifter_3 = { 8'b0, shifter_2[12:8] }; + 2'b10: shifter_3 = { 4'b0, shifter_2[12:4] }; + 2'b11: shifter_3 = shifter_2; + endcase +end + +always @(posedge clk) if( clk_en ) begin + // REGISTER CYCLE 11 + op_XII <= ({ test_214, shifter_3 } ^ {14{signbit_XI}}) + {13'd0,signbit_XI}; + // REGISTER CYCLE 12 + // Extra register, take output after here + op_result_internal <= op_XII; +end + +`ifdef SIMULATION +reg signed [13:0] op_sep2_0; +reg signed [13:0] op_sep4_0; +reg signed [13:0] op_sep5_0; +reg signed [13:0] op_sep6_0; +reg signed [13:0] op_sep0_0; +reg signed [13:0] op_sep1_0; +reg signed [13:0] op_sep2_1; +reg signed [13:0] op_sep4_1; +reg signed [13:0] op_sep5_1; +reg signed [13:0] op_sep6_1; +reg signed [13:0] op_sep0_1; +reg signed [13:0] op_sep1_1; +reg signed [13:0] op_sep2_2; +reg signed [13:0] op_sep4_2; +reg signed [13:0] op_sep5_2; +reg signed [13:0] op_sep6_2; +reg signed [13:0] op_sep0_2; +reg signed [13:0] op_sep1_2; +reg signed [13:0] op_sep2_3; +reg signed [13:0] op_sep4_3; +reg signed [13:0] op_sep5_3; +reg signed [13:0] op_sep6_3; +reg signed [13:0] op_sep0_3; +reg signed [13:0] op_sep1_3; +reg [ 4:0] sepcnt; + +always @(posedge clk) if(clk_en) begin + sepcnt <= zero ? 5'd0 : sepcnt+5'd1; + case( (sepcnt+14)%24 ) + 0: op_sep0_0 <= op_XII; + 1: op_sep1_0 <= op_XII; + 2: op_sep2_0 <= op_XII; + 3: op_sep4_0 <= op_XII; + 4: op_sep5_0 <= op_XII; + 5: op_sep6_0 <= op_XII; + 6: op_sep0_2 <= op_XII; + 7: op_sep1_2 <= op_XII; + 8: op_sep2_2 <= op_XII; + 9: op_sep4_2 <= op_XII; + 10: op_sep5_2 <= op_XII; + 11: op_sep6_2 <= op_XII; + 12: op_sep0_1 <= op_XII; + 13: op_sep1_1 <= op_XII; + 14: op_sep2_1 <= op_XII; + 15: op_sep4_1 <= op_XII; + 16: op_sep5_1 <= op_XII; + 17: op_sep6_1 <= op_XII; + 18: op_sep0_3 <= op_XII; + 19: op_sep1_3 <= op_XII; + 20: op_sep2_3 <= op_XII; + 21: op_sep4_3 <= op_XII; + 22: op_sep5_3 <= op_XII; + 23: op_sep6_3 <= op_XII; + endcase +end + +`endif + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_pcm.v b/common/Sound/JT12/hdl/jt12_pcm.v new file mode 100644 index 00000000..b0d04f53 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pcm.v @@ -0,0 +1,109 @@ +module jt12_pcm( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input zero, + input signed [8:0] pcm, + input pcm_wr, + output reg signed [8:0] pcm_resampled +); + +// reg [2:0] ratesel; +// reg [3:0] cnt8; +// reg wrcnt, wrclr; +reg last_zero; +wire zero_edge = !last_zero && zero; +/* +always @(posedge clk) + if(rst) begin + cnt8 <= 4'd0; + wrclr <= 1'd0; + ratesel <= 3'd1; + wrcnt <= 1'b0; + end else if(clk_en) begin + if( pcm_wr ) begin + if( wrcnt ) begin + // case( cnt8[3:2] ) + // 2'd3: ratesel <= 3'b111; // x8 + // 2'd2: ratesel <= 3'b011; // x4 + // 2'd1: ratesel <= 3'b001; // x2 + // 2'd0: ratesel <= 3'b000; // x1 + // endcase + cnt8 <= 4'd0; + wrcnt <= 1'b0; + end + else wrcnt <= 1'b1; + end else + if( cnt8!=4'hf && zero ) cnt8 <= cnt8 + 4'd1; + end +*/ +// up-rate PCM samples +reg rate1, rate2; //, rate4, rate8; +reg cen1, cen2; //, cen4, cen8; + +always @(posedge clk, posedge rst) + if(rst) + rate2 <= 1'b0; + else begin + last_zero <= zero; + rate1 <= zero_edge; + if(zero_edge) begin + rate2 <= ~rate2; +// if(rate2) begin +// rate4 <= ~rate4; +// if(rate4) rate8<=~rate8; +// end + end + end + +always @(posedge clk) begin + cen1 <= rate1; + cen2 <= rate1 && rate2; +// cen4 <= rate1 && rate2 && rate4; +// cen8 <= rate1 && rate2 && rate4 && rate8; +end + +wire signed [8:0] pcm3; //,pcm2, pcm1; + +//always @(posedge clk) if( clk_en ) +// pcm_resampled <= ratesel[0] ? pcm3 : pcm; +always @(*) + pcm_resampled = pcm3; + +// rate x2 +//wire signed [8:0] pcm_in2 = ratesel[1] ? pcm2 : pcm; +jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2)) +u_uprate_3( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen2 ), + .cen_out( cen1 ), + // .snd_in ( pcm_in2 ), + .snd_in ( pcm ), + .snd_out( pcm3 ) +); +/* +// rate x2 +wire signed [8:0] pcm_in1 = ratesel[2] ? pcm1 : pcm; +jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2)) +u_uprate_2( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen4 ), + .cen_out( cen2 ), + .snd_in ( pcm_in1 ), + .snd_out( pcm2 ) +); + +// rate x2 +jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2)) +u_uprate_1( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen8 ), + .cen_out( cen4 ), + .snd_in ( pcm ), + .snd_out( pcm1 ) +); +*/ +endmodule // jt12_pcm \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_pcm_interpol.v b/common/Sound/JT12/hdl/jt12_pcm_interpol.v new file mode 100644 index 00000000..14cb1ad5 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pcm_interpol.v @@ -0,0 +1,109 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt12_pcm_interpol +#(parameter dw=9, stepw=5) +( + input rst_n, + input clk, + input cen, // 8MHz cen + input cen55, // clk & cen55 = 55 kHz + input pcm_wr, // advance to next sample + input signed [dw-1:0] pcmin, + output reg signed [dw-1:0] pcmout +); + +reg [stepw-1:0] dn, pre_dn={stepw{1'b1}}; +wire posedge_pcmwr = pcm_wr && !last_pcm_wr; +wire negedge_pcmwr = !pcm_wr && last_pcm_wr; + +reg start_div = 0; +wire working; + +reg signed [dw-1:0] pcmnew, dx, pcmlast, pcminter; +wire signed [dw:0] dx_ext = { pcmin[dw-1], pcmin } - { pcmnew[dw-1], pcmnew }; +reg sign, last_pcm_wr; + +// latch new data and compute the two deltas : dx and dn, slope = dx/dn +always @(posedge clk) begin + last_pcm_wr <= pcm_wr; + start_div <= posedge_pcmwr; + + if( posedge_pcmwr ) begin + pre_dn <= 1; + pcmnew <= pcmin; + pcmlast <= pcmnew; + dn <= pre_dn; + dx <= dx_ext[dw] ? ~dx_ext[dw-1:0] + 'd1 : dx_ext[dw-1:0]; + sign <= dx_ext[dw]; + start_div <= 1; + end + + if( !pcm_wr && cen55 ) begin + if( pre_dn != {stepw{1'b1}} ) pre_dn <= pre_dn + 'd1; + end +end + +// interpolate samples +wire [dw-1:0] step; +wire signed [dw-1:0] next_up = pcminter + step; +wire signed [dw-1:0] next_down = pcminter - step; +wire overflow_up = 0;//next_up[dw-1] != pcmnew[dw-1]; +wire overflow_down = 0;//next_down[dw-1] != pcmnew[dw-1]; + + +always @(posedge clk) begin + if( negedge_pcmwr ) begin + pcminter <= pcmlast; + end else if(cen55 && !working && !pcm_wr) begin // only advance if the divider has finished + if( sign ) begin // subtract + if( next_down > pcmnew && !overflow_down ) + pcminter <= next_down; + else + pcminter <= pcmnew; // done + end + else begin // add + if( next_up < pcmnew && !overflow_up ) + pcminter <= next_up; + else + pcminter <= pcmnew; // done + end + end +end + +// output only at cen55 + +always @(posedge clk) if(cen55) pcmout <= pcminter; + +jt10_adpcm_div #(.dw(dw)) u_div( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( 1'b1 ), + .start ( start_div ), + .a ( dx ), + .b ( { {dw-stepw{1'b0}}, dn } ), + .d ( step ), + .r ( ), + .working( working ) +); + + +endmodule // jt10_adpcmb_interpol \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_pg.v b/common/Sound/JT12/hdl/jt12_pg.v new file mode 100644 index 00000000..b1e5128b --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pg.v @@ -0,0 +1,114 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2016 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + Based on jt51_phasegen.v, from JT51 + + */ + +`timescale 1ns / 1ps + +/* + + tab size 4 + +*/ + +module jt12_pg( + input clk, + input clk_en /* synthesis direct_enable */, + input rst, + // Channel frequency + input [10:0] fnum_I, + input [ 2:0] block_I, + // Operator multiplying + input [ 3:0] mul_II, + // Operator detuning + input [ 2:0] dt1_I, // same as JT51's DT1 + // phase modulation from LFO + input [ 6:0] lfo_mod, + input [ 2:0] pms_I, + // phase operation + input pg_rst_II, + input pg_stop, // not implemented + + output reg [ 4:0] keycode_II, + output [ 9:0] phase_VIII +); + +parameter num_ch=6; + +wire [4:0] keycode_I; +wire signed [5:0] detune_mod_I; +reg signed [5:0] detune_mod_II; +wire [16:0] phinc_I; +reg [16:0] phinc_II; +wire [19:0] phase_drop, phase_in; +wire [ 9:0] phase_II; + +always @(posedge clk) if(clk_en) begin + keycode_II <= keycode_I; + detune_mod_II <= detune_mod_I; + phinc_II <= phinc_I; +end + +jt12_pg_comb u_comb( + .block ( block_I ), + .fnum ( fnum_I ), + // Phase Modulation + .lfo_mod ( lfo_mod[6:2] ), + .pms ( pms_I ), + + // Detune + .detune ( dt1_I ), + .keycode ( keycode_I ), + .detune_out ( detune_mod_I ), + // Phase increment + .phinc_out ( phinc_I ), + // Phase add + .mul ( mul_II ), + .phase_in ( phase_drop ), + .pg_rst ( pg_rst_II ), + .detune_in ( detune_mod_II ), + .phinc_in ( phinc_II ), + + .phase_out ( phase_in ), + .phase_op ( phase_II ) +); + +jt12_sh_rst #( .width(20), .stages(4*num_ch) ) u_phsh( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( phase_in ), + .drop ( phase_drop) +); + +jt12_sh_rst #( .width(10), .stages(6) ) u_pad( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( phase_II ), + .drop ( phase_VIII) +); + +endmodule + diff --git a/common/Sound/JT12/hdl/jt12_pg_comb.v b/common/Sound/JT12/hdl/jt12_pg_comb.v new file mode 100644 index 00000000..a8091d21 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pg_comb.v @@ -0,0 +1,90 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 2-11-2018 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + 100% compared with Alexey Khokholov (Nuke.YKT) work with identical results. +*/ + +module jt12_pg_comb( + input [ 2:0] block, + input [10:0] fnum, + // Phase Modulation + input [ 4:0] lfo_mod, + input [ 2:0] pms, + // output [ 7:0] pm_out, + + // Detune + input [ 2:0] detune, + + output [ 4:0] keycode, + output signed [5:0] detune_out, + // Phase increment + output [16:0] phinc_out, + // Phase add + input [ 3:0] mul, + input [19:0] phase_in, + input pg_rst, + // input signed [7:0] pm_in, + input signed [5:0] detune_in, + input [16:0] phinc_in, + + output [19:0] phase_out, + output [ 9:0] phase_op +); + +wire signed [8:0] pm_offset; + +/* pm, pg_dt and pg_inc operate in parallel */ +jt12_pm u_pm( + .lfo_mod ( lfo_mod ), + .fnum ( fnum ), + .pms ( pms ), + .pm_offset ( pm_offset ) +); + +jt12_pg_dt u_dt( + .block ( block ), + .fnum ( fnum ), + .detune ( detune ), + .keycode ( keycode ), + .detune_signed( detune_out ) +); + +jt12_pg_inc u_inc( + .block ( block ), + .fnum ( fnum ), + .pm_offset ( pm_offset ), + .phinc_pure ( phinc_out ) +); + +// pg_sum uses the output from the previous blocks + +jt12_pg_sum u_sum( + .mul ( mul ), + .phase_in ( phase_in ), + .pg_rst ( pg_rst ), + .detune_signed ( detune_in ), + .phinc_pure ( phinc_in ), + .phase_out ( phase_out ), + .phase_op ( phase_op ) +); + +endmodule // jt12_pg_comb \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_pg_dt.v b/common/Sound/JT12/hdl/jt12_pg_dt.v new file mode 100644 index 00000000..9b9e0f31 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pg_dt.v @@ -0,0 +1,82 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 2-11-2018 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + Note that detune produces an output even for fnum==0, is that correct? + + Based on jt51_phasegen.v, from JT51 + + */ + +module jt12_pg_dt( + input [ 2:0] block, + input [10:0] fnum, + input [ 2:0] detune, + + output reg [ 4:0] keycode, + output reg signed [5:0] detune_signed +); + +reg [5:0] detune_kf; +reg [4:0] pow2; +reg [5:0] detune_unlimited; +reg [4:0] detune_limit, detune_limited; + + +always @(*) begin + keycode = { block, fnum[10], fnum[10] ? (|fnum[9:7]) : (&fnum[9:7])}; + case( detune[1:0] ) + 2'd1: detune_kf = { 1'b0, keycode } - 6'd4; + 2'd2: detune_kf = { 1'b0, keycode } + 6'd4; + 2'd3: detune_kf = { 1'b0, keycode } + 6'd8; + default:detune_kf = { 1'b0, keycode }; + endcase + case( detune_kf[2:0] ) + 3'd0: pow2 = 5'd16; + 3'd1: pow2 = 5'd17; + 3'd2: pow2 = 5'd19; + 3'd3: pow2 = 5'd20; + 3'd4: pow2 = 5'd22; + 3'd5: pow2 = 5'd24; + 3'd6: pow2 = 5'd26; + 3'd7: pow2 = 5'd29; + endcase + case( detune[1:0] ) + 2'd0: detune_limit = 5'd0; + 2'd1: detune_limit = 5'd8; + 2'd2: detune_limit = 5'd16; + 2'd3: detune_limit = 5'd22; + endcase + case( detune_kf[5:3] ) + 3'd0: detune_unlimited = { 5'd0, pow2[4] }; // <2 + 3'd1: detune_unlimited = { 4'd0, pow2[4:3] }; // <4 + 3'd2: detune_unlimited = { 3'd0, pow2[4:2] }; // <8 + 3'd3: detune_unlimited = { 2'd0, pow2[4:1] }; + 3'd4: detune_unlimited = { 1'd0, pow2[4:0] }; + 3'd5: detune_unlimited = { pow2[4:0], 1'd0 }; + default:detune_unlimited = 6'd0; + endcase + detune_limited = detune_unlimited > {1'b0, detune_limit} ? + detune_limit : detune_unlimited[4:0]; + detune_signed = !detune[2] ? {1'b0,detune_limited} : (~{1'b0,detune_limited}+6'd1); +end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_pg_inc.v b/common/Sound/JT12/hdl/jt12_pg_inc.v new file mode 100644 index 00000000..bee1c8db --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pg_inc.v @@ -0,0 +1,50 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 2-11-2018 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + Based on jt51_phasegen.v, from JT51 + + */ + +module jt12_pg_inc ( + input [ 2:0] block, + input [10:0] fnum, + input signed [8:0] pm_offset, + output reg [16:0] phinc_pure +); + +reg [11:0] fnum_mod; + +always @(*) begin + fnum_mod = {fnum,1'b0} + {{3{pm_offset[8]}},pm_offset}; + case ( block ) + 3'd0: phinc_pure = { 7'd0, fnum_mod[11:2] }; + 3'd1: phinc_pure = { 6'd0, fnum_mod[11:1] }; + 3'd2: phinc_pure = { 5'd0, fnum_mod[11:0] }; + 3'd3: phinc_pure = { 4'd0, fnum_mod, 1'd0 }; + 3'd4: phinc_pure = { 3'd0, fnum_mod, 2'd0 }; + 3'd5: phinc_pure = { 2'd0, fnum_mod, 3'd0 }; + 3'd6: phinc_pure = { 1'd0, fnum_mod, 4'd0 }; + 3'd7: phinc_pure = { fnum_mod, 5'd0 }; + endcase +end + +endmodule // jt12_pg_inc \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_pg_sum.v b/common/Sound/JT12/hdl/jt12_pg_sum.v new file mode 100644 index 00000000..6369c53a --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pg_sum.v @@ -0,0 +1,49 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 2-11-2018 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + Based on jt51_phasegen.v, from JT51 + + */ + +module jt12_pg_sum ( + input [ 3:0] mul, + input [19:0] phase_in, + input pg_rst, + input signed [5:0] detune_signed, + input [16:0] phinc_pure, + + output reg [19:0] phase_out, + output reg [ 9:0] phase_op +); + +reg [16:0] phinc_premul; +reg [19:0] phinc_mul; + +always @(*) begin + phinc_premul = phinc_pure + {{11{detune_signed[5]}},detune_signed}; + phinc_mul = ( mul==4'd0 ) ? {4'b0,phinc_premul[16:1]} : ({3'd0,phinc_premul} * mul); + + phase_out = pg_rst ? 20'd0 : (phase_in + { phinc_mul}); + phase_op = phase_out[19:10]; +end + +endmodule // jt12_pg_sum \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_pm.v b/common/Sound/JT12/hdl/jt12_pm.v new file mode 100644 index 00000000..89179210 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_pm.v @@ -0,0 +1,186 @@ +/* This file is part of jt12. + + jt12 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. + + jt12 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 jt12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-10-2018 + */ + +`timescale 1ns / 1ps + +// This implementation follows that of Alexey Khokholov (Nuke.YKT) in C language. + +module jt12_pm ( + input [4:0] lfo_mod, + input [10:0] fnum, + input [2:0] pms, + output reg signed [8:0] pm_offset +); + + +reg [7:0] pm_unsigned; +reg [7:0] pm_base; +reg [9:0] pm_shifted; + +wire [2:0] index = lfo_mod[3] ? (~lfo_mod[2:0]) : lfo_mod[2:0]; + +reg [2:0] lfo_sh1_lut [0:63]; +reg [2:0] lfo_sh2_lut [0:63]; +reg [2:0] lfo_sh1, lfo_sh2; + +initial begin + lfo_sh1_lut[6'h00] = 3'd7; + lfo_sh1_lut[6'h01] = 3'd7; + lfo_sh1_lut[6'h02] = 3'd7; + lfo_sh1_lut[6'h03] = 3'd7; + lfo_sh1_lut[6'h04] = 3'd7; + lfo_sh1_lut[6'h05] = 3'd7; + lfo_sh1_lut[6'h06] = 3'd7; + lfo_sh1_lut[6'h07] = 3'd7; + lfo_sh1_lut[6'h08] = 3'd7; + lfo_sh1_lut[6'h09] = 3'd7; + lfo_sh1_lut[6'h0A] = 3'd7; + lfo_sh1_lut[6'h0B] = 3'd7; + lfo_sh1_lut[6'h0C] = 3'd7; + lfo_sh1_lut[6'h0D] = 3'd7; + lfo_sh1_lut[6'h0E] = 3'd7; + lfo_sh1_lut[6'h0F] = 3'd7; + lfo_sh1_lut[6'h10] = 3'd7; + lfo_sh1_lut[6'h11] = 3'd7; + lfo_sh1_lut[6'h12] = 3'd7; + lfo_sh1_lut[6'h13] = 3'd7; + lfo_sh1_lut[6'h14] = 3'd7; + lfo_sh1_lut[6'h15] = 3'd7; + lfo_sh1_lut[6'h16] = 3'd1; + lfo_sh1_lut[6'h17] = 3'd1; + lfo_sh1_lut[6'h18] = 3'd7; + lfo_sh1_lut[6'h19] = 3'd7; + lfo_sh1_lut[6'h1A] = 3'd7; + lfo_sh1_lut[6'h1B] = 3'd7; + lfo_sh1_lut[6'h1C] = 3'd1; + lfo_sh1_lut[6'h1D] = 3'd1; + lfo_sh1_lut[6'h1E] = 3'd1; + lfo_sh1_lut[6'h1F] = 3'd1; + lfo_sh1_lut[6'h20] = 3'd7; + lfo_sh1_lut[6'h21] = 3'd7; + lfo_sh1_lut[6'h22] = 3'd7; + lfo_sh1_lut[6'h23] = 3'd1; + lfo_sh1_lut[6'h24] = 3'd1; + lfo_sh1_lut[6'h25] = 3'd1; + lfo_sh1_lut[6'h26] = 3'd1; + lfo_sh1_lut[6'h27] = 3'd0; + lfo_sh1_lut[6'h28] = 3'd7; + lfo_sh1_lut[6'h29] = 3'd7; + lfo_sh1_lut[6'h2A] = 3'd1; + lfo_sh1_lut[6'h2B] = 3'd1; + lfo_sh1_lut[6'h2C] = 3'd0; + lfo_sh1_lut[6'h2D] = 3'd0; + lfo_sh1_lut[6'h2E] = 3'd0; + lfo_sh1_lut[6'h2F] = 3'd0; + lfo_sh1_lut[6'h30] = 3'd7; + lfo_sh1_lut[6'h31] = 3'd7; + lfo_sh1_lut[6'h32] = 3'd1; + lfo_sh1_lut[6'h33] = 3'd1; + lfo_sh1_lut[6'h34] = 3'd0; + lfo_sh1_lut[6'h35] = 3'd0; + lfo_sh1_lut[6'h36] = 3'd0; + lfo_sh1_lut[6'h37] = 3'd0; + lfo_sh1_lut[6'h38] = 3'd7; + lfo_sh1_lut[6'h39] = 3'd7; + lfo_sh1_lut[6'h3A] = 3'd1; + lfo_sh1_lut[6'h3B] = 3'd1; + lfo_sh1_lut[6'h3C] = 3'd0; + lfo_sh1_lut[6'h3D] = 3'd0; + lfo_sh1_lut[6'h3E] = 3'd0; + lfo_sh1_lut[6'h3F] = 3'd0; + lfo_sh2_lut[6'h00] = 3'd7; + lfo_sh2_lut[6'h01] = 3'd7; + lfo_sh2_lut[6'h02] = 3'd7; + lfo_sh2_lut[6'h03] = 3'd7; + lfo_sh2_lut[6'h04] = 3'd7; + lfo_sh2_lut[6'h05] = 3'd7; + lfo_sh2_lut[6'h06] = 3'd7; + lfo_sh2_lut[6'h07] = 3'd7; + lfo_sh2_lut[6'h08] = 3'd7; + lfo_sh2_lut[6'h09] = 3'd7; + lfo_sh2_lut[6'h0A] = 3'd7; + lfo_sh2_lut[6'h0B] = 3'd7; + lfo_sh2_lut[6'h0C] = 3'd2; + lfo_sh2_lut[6'h0D] = 3'd2; + lfo_sh2_lut[6'h0E] = 3'd2; + lfo_sh2_lut[6'h0F] = 3'd2; + lfo_sh2_lut[6'h10] = 3'd7; + lfo_sh2_lut[6'h11] = 3'd7; + lfo_sh2_lut[6'h12] = 3'd7; + lfo_sh2_lut[6'h13] = 3'd2; + lfo_sh2_lut[6'h14] = 3'd2; + lfo_sh2_lut[6'h15] = 3'd2; + lfo_sh2_lut[6'h16] = 3'd7; + lfo_sh2_lut[6'h17] = 3'd7; + lfo_sh2_lut[6'h18] = 3'd7; + lfo_sh2_lut[6'h19] = 3'd7; + lfo_sh2_lut[6'h1A] = 3'd2; + lfo_sh2_lut[6'h1B] = 3'd2; + lfo_sh2_lut[6'h1C] = 3'd7; + lfo_sh2_lut[6'h1D] = 3'd7; + lfo_sh2_lut[6'h1E] = 3'd2; + lfo_sh2_lut[6'h1F] = 3'd2; + lfo_sh2_lut[6'h20] = 3'd7; + lfo_sh2_lut[6'h21] = 3'd7; + lfo_sh2_lut[6'h22] = 3'd2; + lfo_sh2_lut[6'h23] = 3'd7; + lfo_sh2_lut[6'h24] = 3'd7; + lfo_sh2_lut[6'h25] = 3'd7; + lfo_sh2_lut[6'h26] = 3'd2; + lfo_sh2_lut[6'h27] = 3'd7; + lfo_sh2_lut[6'h28] = 3'd7; + lfo_sh2_lut[6'h29] = 3'd7; + lfo_sh2_lut[6'h2A] = 3'd7; + lfo_sh2_lut[6'h2B] = 3'd2; + lfo_sh2_lut[6'h2C] = 3'd7; + lfo_sh2_lut[6'h2D] = 3'd7; + lfo_sh2_lut[6'h2E] = 3'd2; + lfo_sh2_lut[6'h2F] = 3'd1; + lfo_sh2_lut[6'h30] = 3'd7; + lfo_sh2_lut[6'h31] = 3'd7; + lfo_sh2_lut[6'h32] = 3'd7; + lfo_sh2_lut[6'h33] = 3'd2; + lfo_sh2_lut[6'h34] = 3'd7; + lfo_sh2_lut[6'h35] = 3'd7; + lfo_sh2_lut[6'h36] = 3'd2; + lfo_sh2_lut[6'h37] = 3'd1; + lfo_sh2_lut[6'h38] = 3'd7; + lfo_sh2_lut[6'h39] = 3'd7; + lfo_sh2_lut[6'h3A] = 3'd7; + lfo_sh2_lut[6'h3B] = 3'd2; + lfo_sh2_lut[6'h3C] = 3'd7; + lfo_sh2_lut[6'h3D] = 3'd7; + lfo_sh2_lut[6'h3E] = 3'd2; + lfo_sh2_lut[6'h3F] = 3'd1; +end + +always @(*) begin + lfo_sh1 = lfo_sh1_lut[{pms,index}]; + lfo_sh2 = lfo_sh2_lut[{pms,index}]; + pm_base = ({1'b0,fnum[10:4]}>>lfo_sh1) + ({1'b0,fnum[10:4]}>>lfo_sh2); + case( pms ) + default: pm_shifted = { 2'b0, pm_base }; + 3'd6: pm_shifted = { 1'b0, pm_base, 1'b0 }; + 3'd7: pm_shifted = { pm_base, 2'b0 }; + endcase // pms + pm_offset = lfo_mod[4] ? (-{1'b0,pm_shifted[9:2]}) : {1'b0,pm_shifted[9:2]}; +end // always @(*) + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_reg.v b/common/Sound/JT12/hdl/jt12_reg.v new file mode 100644 index 00000000..89b2017c --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_reg.v @@ -0,0 +1,372 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2017 + +*/ + +module jt12_reg( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input [7:0] din, + + input [2:0] ch, // channel to update + input [1:0] op, + + input csm, + input flag_A, + input overflow_A, + + input up_keyon, + input up_alg, + input up_fnumlo, + input up_pms, + input up_dt1, + input up_tl, + input up_ks_ar, + input up_amen_dr, + input up_sr, + + input up_sl_rr, + input up_ssgeg, + + output reg ch6op, // 1 when the operator belongs to CH6 + output reg [2:0] cur_ch, + output reg [1:0] cur_op, + + // CH3 Effect-mode operation + input effect, + input [10:0] fnum_ch3op2, + input [10:0] fnum_ch3op3, + input [10:0] fnum_ch3op1, + input [ 2:0] block_ch3op2, + input [ 2:0] block_ch3op3, + input [ 2:0] block_ch3op1, + input [ 5:0] latch_fnum, + // Pipeline order + output reg zero, + output s1_enters, + output s2_enters, + output s3_enters, + output s4_enters, + + // Operator + output xuse_prevprev1, + output xuse_internal, + output yuse_internal, + output xuse_prev2, + output yuse_prev1, + output yuse_prev2, + + // PG + output [10:0] fnum_I, + output [ 2:0] block_I, + // channel configuration + output [1:0] rl, + output reg [2:0] fb_II, + output [2:0] alg_I, + // Operator multiplying + output [ 3:0] mul_II, + // Operator detuning + output [ 2:0] dt1_I, + + // EG + output [4:0] ar_I, // attack rate + output [4:0] d1r_I, // decay rate + output [4:0] d2r_I, // sustain rate + output [3:0] rr_I, // release rate + output [3:0] sl_I, // sustain level + output [1:0] ks_II, // key scale + output ssg_en_I, + output [2:0] ssg_eg_I, + output [6:0] tl_IV, + output [2:0] pms_I, + output [1:0] ams_IV, + output amsen_IV, + + // envelope operation + output keyon_I +); + +parameter num_ch=6; // Use only 3 (YM2203/YM2610) or 6 (YM2612/YM2608) + + +reg [1:0] next_op; +reg [2:0] next_ch; +reg last; + +`ifdef SIMULATION +// These signals need to operate during rst +// initial state is not relevant (or critical) in real life +// but we need a clear value during simulation +// This does not work with NCVERILOG +initial begin + cur_op = 2'd0; + cur_ch = 3'd0; + next_op = 2'd0; + next_ch = 3'd1; + last = 1'b0; + zero = 1'b1; +end +`endif + +assign s1_enters = cur_op == 2'b00; +assign s3_enters = cur_op == 2'b01; +assign s2_enters = cur_op == 2'b10; +assign s4_enters = cur_op == 2'b11; + +wire [4:0] next = { next_op, next_ch }; +wire [4:0] cur = { cur_op, cur_ch }; + +wire [2:0] fb_I; + +always @(posedge clk) if( clk_en ) begin + fb_II <= fb_I; + ch6op <= next_ch==3'd6; +end + +// FNUM and BLOCK +wire [10:0] fnum_I_raw; +wire [ 2:0] block_I_raw; +wire effect_on = effect && (cur_ch==3'd2); +wire effect_on_s1 = effect_on && (cur_op == 2'd0 ); +wire effect_on_s3 = effect_on && (cur_op == 2'd1 ); +wire effect_on_s2 = effect_on && (cur_op == 2'd2 ); +wire noeffect = ~|{effect_on_s1, effect_on_s3, effect_on_s2}; +assign fnum_I = ( {11{effect_on_s1}} & fnum_ch3op1 ) | + ( {11{effect_on_s2}} & fnum_ch3op2 ) | + ( {11{effect_on_s3}} & fnum_ch3op3 ) | + ( {11{noeffect}} & fnum_I_raw ); + +assign block_I =( {3{effect_on_s1}} & block_ch3op1 ) | + ( {3{effect_on_s2}} & block_ch3op2 ) | + ( {3{effect_on_s3}} & block_ch3op3 ) | + ( {3{noeffect}} & block_I_raw ); + +wire [4:0] req_opch_I = { op, ch }; +wire [4:0] req_opch_II, req_opch_III, + req_opch_IV, req_opch_V; //, req_opch_VI; + +jt12_sumch #(.num_ch(num_ch)) u_opch_II ( .chin(req_opch_I ), .chout(req_opch_II ) ); +jt12_sumch #(.num_ch(num_ch)) u_opch_III( .chin(req_opch_II ), .chout(req_opch_III) ); +jt12_sumch #(.num_ch(num_ch)) u_opch_IV ( .chin(req_opch_III), .chout(req_opch_IV ) ); +jt12_sumch #(.num_ch(num_ch)) u_opch_V ( .chin(req_opch_IV ), .chout(req_opch_V ) ); +// jt12_sumch #(.num_ch(num_ch)) u_opch_VI ( .chin(req_opch_V ), .chout(req_opch_VI) ); + +wire update_op_I = cur == req_opch_I; +wire update_op_II = cur == req_opch_II; +// wire update_op_III= cur == req_opch_III; +wire update_op_IV = cur == req_opch_IV; +// wire update_op_V = cur == req_opch_V; +// wire update_op_VI = cur == opch_VI; +// wire [2:0] op_plus1 = op+2'd1; +// wire update_op_VII= cur == { op_plus1[1:0], ch }; + +// key on/off +wire [3:0] keyon_op = din[7:4]; +wire [2:0] keyon_ch = din[2:0]; +// channel data +wire [2:0] fb_in = din[5:3]; +wire [2:0] alg_in = din[2:0]; +wire [2:0] pms_in = din[2:0]; +wire [1:0] ams_in = din[5:4]; +wire [7:0] fnlo_in = din; + + +wire update_ch_I = cur_ch == ch; +wire update_ch_IV = num_ch==6 ? + { ~cur_ch[2], cur_ch[1:0]} == ch : // 6 channels + cur[1:0] == ch[1:0]; // 3 channels + +wire up_alg_ch = up_alg & update_ch_I; +wire up_fnumlo_ch=up_fnumlo & update_ch_I; +wire up_pms_ch = up_pms & update_ch_I; +wire up_ams_ch = up_pms & update_ch_IV; + +always @(*) begin + // next = cur==5'd23 ? 5'd0 : cur +1'b1; + if( num_ch==6 ) begin + next_op = cur_ch==3'd6 ? cur_op+1'b1 : cur_op; + next_ch = cur_ch[1:0]==2'b10 ? cur_ch+2'd2 : cur_ch+1'd1; + end else begin // 3 channels + next_op = cur_ch==3'd2 ? cur_op+1'b1 : cur_op; + next_ch = cur_ch[1:0]==2'b10 ? 3'd0 : cur_ch+1'd1; + end +end + +always @(posedge clk) begin : up_counter + if( clk_en ) begin + { cur_op, cur_ch } <= { next_op, next_ch }; + zero <= next == 5'd0; + end +end + +`ifndef NOFM +jt12_kon #(.num_ch(num_ch)) u_kon( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .keyon_op ( keyon_op ), + .keyon_ch ( keyon_ch ), + .next_op ( next_op ), + .next_ch ( next_ch ), + .up_keyon ( up_keyon ), + .csm ( csm ), + // .flag_A ( flag_A ), + .overflow_A ( overflow_A), + + .keyon_I ( keyon_I ) +); + +jt12_mod #(.num_ch(num_ch)) u_mod( + .alg_I ( alg_I ), + .s1_enters ( s1_enters ), + .s3_enters ( s3_enters ), + .s2_enters ( s2_enters ), + .s4_enters ( s4_enters ), + + .xuse_prevprev1 ( xuse_prevprev1 ), + .xuse_internal ( xuse_internal ), + .yuse_internal ( yuse_internal ), + .xuse_prev2 ( xuse_prev2 ), + .yuse_prev1 ( yuse_prev1 ), + .yuse_prev2 ( yuse_prev2 ) +); + +wire [43:0] shift_out; + +generate + if( num_ch==6 ) begin + // YM2612 / YM3438: Two CSR. + wire [43:0] shift_middle; + + jt12_csr u_csr0( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( din ), + .shift_in ( shift_out ), + .shift_out ( shift_middle ), + .up_tl ( up_tl ), + .up_dt1 ( up_dt1 ), + .up_ks_ar ( up_ks_ar ), + .up_amen_dr ( up_amen_dr ), + .up_sr ( up_sr ), + .up_sl_rr ( up_sl_rr ), + .up_ssgeg ( up_ssgeg ), + .update_op_I ( update_op_I ), + .update_op_II ( update_op_II ), + .update_op_IV ( update_op_IV ) + ); + + wire up_midop_I = { ~cur[4], cur[3:0] } == req_opch_I; + wire up_midop_II = { ~cur[4], cur[3:0] } == req_opch_II; + wire up_midop_IV = { ~cur[4], cur[3:0] } == req_opch_IV; + + jt12_csr u_csr1( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( din ), + .shift_in ( shift_middle ), + .shift_out ( shift_out ), + .up_tl ( up_tl ), + .up_dt1 ( up_dt1 ), + .up_ks_ar ( up_ks_ar ), + .up_amen_dr ( up_amen_dr ), + .up_sr ( up_sr ), + .up_sl_rr ( up_sl_rr ), + .up_ssgeg ( up_ssgeg ), + // update in the middle: + .update_op_I ( up_midop_I ), + .update_op_II ( up_midop_II ), + .update_op_IV ( up_midop_IV ) + ); + end + else begin // YM2203 only has one CSR + jt12_csr u_csr0( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .din ( din ), + .shift_in ( shift_out ), + .shift_out ( shift_out ), + .up_tl ( up_tl ), + .up_dt1 ( up_dt1 ), + .up_ks_ar ( up_ks_ar ), + .up_amen_dr ( up_amen_dr ), + .up_sr ( up_sr ), + .up_sl_rr ( up_sl_rr ), + .up_ssgeg ( up_ssgeg ), + .update_op_I ( update_op_I ), + .update_op_II ( update_op_II ), + .update_op_IV ( update_op_IV ) + ); + end // else +endgenerate + +assign { tl_IV, dt1_I, mul_II, ks_II, + ar_I, amsen_IV, d1r_I, d2r_I, + sl_I, rr_I, ssg_en_I, ssg_eg_I } = shift_out; + + +// memory for CH registers +// Block/fnum data is latched until fnum low byte is written to +// Trying to synthesize this memory as M-9K RAM in Altera devices +// turns out worse in terms of resource utilization. Probably because +// this memory is already very small. It is better to leave it as it is. +localparam regch_width=25; +wire [regch_width-1:0] regch_out; +wire [regch_width-1:0] regch_in = { + up_fnumlo_ch? { latch_fnum, fnlo_in } : { block_I_raw, fnum_I_raw }, // 14 + up_alg_ch ? { fb_in, alg_in } : { fb_I, alg_I },//3+3 + up_ams_ch ? ams_in : ams_IV, //2 + up_pms_ch ? pms_in : pms_I //3 +}; + +assign { block_I_raw, fnum_I_raw, + fb_I, alg_I, ams_IV, pms_I } = regch_out; + +jt12_sh_rst #(.width(regch_width),.stages(num_ch)) u_regch( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( regch_in ), + .drop ( regch_out ) +); + +generate +if( num_ch==6 ) begin + // RL is on a different register to + // have the reset to 1 + wire [1:0] rl_in = din[7:6]; + jt12_sh_rst #(.width(2),.stages(num_ch),.rstval(1'b1)) u_regch_rl( + .clk ( clk ), + .clk_en ( clk_en ), + .rst ( rst ), + .din ( up_pms_ch ? rl_in : rl ), + .drop ( rl ) + ); +end else begin // YM2203 has no stereo output + assign rl=2'b11; +end + +endgenerate +`endif +endmodule diff --git a/common/Sound/JT12/hdl/jt12_rst.v b/common/Sound/JT12/hdl/jt12_rst.v new file mode 100644 index 00000000..01756580 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_rst.v @@ -0,0 +1,38 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 21-03-2019 +*/ + +module jt12_rst( + input rst, + input clk, + output reg rst_n +); + +reg r; + +always @(negedge clk) + if( rst ) begin + r <= 1'b0; + rst_n <= 1'b0; + end else begin + { rst_n, r } <= { r, 1'b1 }; + end + +endmodule // jt12_rst \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_sh.v b/common/Sound/JT12/hdl/jt12_sh.v new file mode 100644 index 00000000..5578f106 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_sh.v @@ -0,0 +1,44 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 1-31-2017 + */ + +`timescale 1ns / 1ps + +// stages must be greater than 2 +module jt12_sh #(parameter width=5, stages=24 ) +( + input clk, + input clk_en /* synthesis direct_enable */, + input [width-1:0] din, + output [width-1:0] drop +); + +reg [stages-1:0] bits[width-1:0]; + +genvar i; +generate + for (i=0; i < width; i=i+1) begin: bit_shifter + always @(posedge clk) if(clk_en) begin + bits[i] <= {bits[i][stages-2:0], din[i]}; + end + assign drop[i] = bits[i][stages-1]; + end +endgenerate + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_sh24.v b/common/Sound/JT12/hdl/jt12_sh24.v new file mode 100644 index 00000000..feb0cfa9 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_sh24.v @@ -0,0 +1,81 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 1-31-2017 + */ + +`timescale 1ns / 1ps + +module jt12_sh24 #(parameter width=5 ) +( + input clk, + input clk_en /* synthesis direct_enable */, + input [width-1:0] din, + output reg [width-1:0] st1, + output reg [width-1:0] st2, + output reg [width-1:0] st3, + output reg [width-1:0] st4, + output reg [width-1:0] st5, + output reg [width-1:0] st6, + output reg [width-1:0] st7, + output reg [width-1:0] st8, + output reg [width-1:0] st9, + output reg [width-1:0] st10, + output reg [width-1:0] st11, + output reg [width-1:0] st12, + output reg [width-1:0] st13, + output reg [width-1:0] st14, + output reg [width-1:0] st15, + output reg [width-1:0] st16, + output reg [width-1:0] st17, + output reg [width-1:0] st18, + output reg [width-1:0] st19, + output reg [width-1:0] st20, + output reg [width-1:0] st21, + output reg [width-1:0] st22, + output reg [width-1:0] st23, + output reg [width-1:0] st24 +); + +always @(posedge clk) if(clk_en) begin + st24<= st23; + st23<= st22; + st22<= st21; + st21<= st20; + st20<= st19; + st19<= st18; + st18<= st17; + st17<= st16; + st16<= st15; + st15<= st14; + st14<= st13; + st13<= st12; + st12<= st11; + st11<= st10; + st10<= st9; + st9 <= st8; + st8 <= st7; + st7 <= st6; + st6 <= st5; + st5 <= st4; + st4 <= st3; + st3 <= st2; + st2 <= st1; + st1 <= din; +end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_sh_rst.v b/common/Sound/JT12/hdl/jt12_sh_rst.v new file mode 100644 index 00000000..d50302e9 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_sh_rst.v @@ -0,0 +1,56 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 1-31-2017 + */ + +`timescale 1ns / 1ps + +// stages must be greater than 2 +module jt12_sh_rst #(parameter width=5, stages=32, rstval=1'b0 ) +( + input rst, + input clk, + input clk_en /* synthesis direct_enable */, + input [width-1:0] din, + output [width-1:0] drop +); + +reg [stages-1:0] bits[width-1:0]; + +genvar i; +integer k; +generate +initial + for (k=0; k < width; k=k+1) begin + bits[k] = { stages{rstval}}; + end +endgenerate + +generate + for (i=0; i < width; i=i+1) begin: bit_shifter + always @(posedge clk, posedge rst) + if( rst ) begin + bits[i] <= {stages{rstval}}; + end else if(clk_en) begin + bits[i] <= {bits[i][stages-2:0], din[i]}; + end + assign drop[i] = bits[i][stages-1]; + end +endgenerate + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_single_acc.v b/common/Sound/JT12/hdl/jt12_single_acc.v new file mode 100644 index 00000000..411adc2a --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_single_acc.v @@ -0,0 +1,63 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-1-2017 + +*/ + +// Accumulates an arbitrary number of inputs with saturation +// restart the sum when input "zero" is high + +`timescale 1ns / 1ps + +module jt12_single_acc #(parameter + win=14, // input data width + wout=16 // output data width +)( + input clk, + input clk_en /* synthesis direct_enable */, + input [win-1:0] op_result, + input sum_en, + input zero, + output reg [wout-1:0] snd +); + +// for full resolution use win=14, wout=16 +// for cut down resolution use win=9, wout=12 +// wout-win should be > 0 + +reg signed [wout-1:0] next, acc, current; +reg overflow; + +wire [wout-1:0] plus_inf = { 1'b0, {(wout-1){1'b1}} }; // maximum positive value +wire [wout-1:0] minus_inf = { 1'b1, {(wout-1){1'b0}} }; // minimum negative value + +always @(*) begin + current = sum_en ? { {(wout-win){op_result[win-1]}}, op_result } : {wout{1'b0}}; + next = zero ? current : current + acc; + overflow = !zero && + (current[wout-1] == acc[wout-1]) && + (acc[wout-1]!=next[wout-1]); +end + +always @(posedge clk) if( clk_en ) begin + acc <= overflow ? (acc[wout-1] ? minus_inf : plus_inf) : next; + if(zero) snd <= acc; +end + +endmodule // jt12_single_acc \ No newline at end of file diff --git a/common/Sound/JT12/hdl/jt12_sumch.v b/common/Sound/JT12/hdl/jt12_sumch.v new file mode 100644 index 00000000..75b1d4f5 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_sumch.v @@ -0,0 +1,47 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 1-31-2017 + */ + +`timescale 1ns / 1ps + +/* The input is {op[1:0], ch[2:0]} + it adds 1 to the channel and overflow to the operator correctly */ + +module jt12_sumch +( + input [4:0] chin, + output reg [4:0] chout +); + +parameter num_ch=6; + +reg [2:0] aux; + +always @(*) begin + aux = chin[2:0] + 3'd1; + if( num_ch==6 ) begin + chout[2:0] = aux[1:0]==2'b11 ? aux+3'd1 : aux; + chout[4:3] = chin[2:0]==3'd6 ? chin[4:3]+2'd1 : chin[4:3]; // next operator + end else begin // 3 channels + chout[2:0] = aux[1:0]==2'b11 ? 3'd0 : aux; + chout[4:3] = chin[2:0]==3'd2 ? chin[4:3]+2'd1 : chin[4:3]; // next operator + end +end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_timers.v b/common/Sound/JT12/hdl/jt12_timers.v new file mode 100644 index 00000000..fb5668d1 --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_timers.v @@ -0,0 +1,141 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2017 + + YM3438_APL.pdf + Timer A = 144*(1024-NA)/Phi M + Timer B = 2304*(256-NB)/Phi M + */ + +`timescale 1ns / 1ps + +module jt12_timers( + input clk, + input rst, + input clk_en /* synthesis direct_enable */, + input zero, + input [9:0] value_A, + input [7:0] value_B, + input load_A, + input load_B, + input clr_flag_A, + input clr_flag_B, + input enable_irq_A, + input enable_irq_B, + output flag_A, + output flag_B, + output overflow_A, + output irq_n +); + +parameter num_ch = 6; + +assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) ); + +/* +reg zero2; + +always @(posedge clk, posedge rst) begin + if( rst ) + zero2 <= 0; + else if(clk_en) begin + if( zero ) zero2 <= ~zero; + end +end + +wire zero = num_ch == 6 ? zero : (zero2&zero); +*/ +jt12_timer #(.CW(10)) timer_A( + .clk ( clk ), + .rst ( rst ), + .cen ( clk_en ), + .zero ( zero ), + .start_value( value_A ), + .load ( load_A ), + .clr_flag ( clr_flag_A ), + .flag ( flag_A ), + .overflow ( overflow_A ) +); + +jt12_timer #(.CW(8),.FREE_EN(1)) timer_B( + .clk ( clk ), + .rst ( rst ), + .cen ( clk_en ), + .zero ( zero ), + .start_value( value_B ), + .load ( load_B ), + .clr_flag ( clr_flag_B ), + .flag ( flag_B ), + .overflow ( ) +); + +endmodule + +module jt12_timer #(parameter + CW = 8, // counter bit width. This is the counter that can be loaded + FW = 4, // number of bits for the free-running counter + FREE_EN = 0 // enables a 4-bit free enable count +) ( + input rst, + input clk, + input cen, + input zero, + input [CW-1:0] start_value, + input load, + input clr_flag, + output reg flag, + output reg overflow +); + +reg last_load; +reg [CW-1:0] cnt, next; +reg [FW-1:0] free_cnt, free_next; +reg free_ov; + +always@(posedge clk, posedge rst) + if( rst ) + flag <= 1'b0; + else /*if(cen)*/ begin + if( clr_flag ) + flag <= 1'b0; + else if(overflow) flag<=1'b1; + end + +always @(*) begin + {free_ov, free_next} = { 1'b0, free_cnt} + 1'b1; + {overflow, next } = { 1'b0, cnt } + (FREE_EN ? free_ov : 1'b1); +end + +always @(posedge clk) if(cen && zero) begin : counter + last_load <= load; + if( (load && !last_load) || overflow ) begin + cnt <= start_value; + end + else if( last_load ) cnt <= next; +end + +// Free running counter +always @(posedge clk) begin + if( rst ) begin + free_cnt <= {FW{1'b0}}; + end else if( cen&&zero ) begin + free_cnt <= free_cnt+1'd1; + end +end + +endmodule diff --git a/common/Sound/JT12/hdl/jt12_top.v b/common/Sound/JT12/hdl/jt12_top.v new file mode 100644 index 00000000..32fb84cb --- /dev/null +++ b/common/Sound/JT12/hdl/jt12_top.v @@ -0,0 +1,671 @@ +/* This file is part of JT12. + + JT12 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. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 14-2-2016 + + Based on information posted by Nemesis on: +http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167 + + Based on jt51_phasegen.v, from JT51 + + */ + +module jt12_top ( + input rst, // rst should be at least 6 clk&cen cycles long + input clk, // CPU clock + input cen, // optional clock enable, it not needed leave as 1'b1 + input [7:0] din, + input [1:0] addr, + input cs_n, + input wr_n, + + output [7:0] dout, + output irq_n, + // Configuration + input en_hifi_pcm, // high to enable PCM interpolation on YM2612 mode + // ADPCM pins + output [19:0] adpcma_addr, // real hardware has 10 pins multiplexed through RMPX pin + output [ 3:0] adpcma_bank, + output adpcma_roe_n, // ADPCM-A ROM output enable + input [ 7:0] adpcma_data, // Data from RAM + output [23:0] adpcmb_addr, // real hardware has 12 pins multiplexed through PMPX pin + input [ 7:0] adpcmb_data, + output adpcmb_roe_n, // ADPCM-B ROM output enable + // I/O pins used by YM2203 embedded YM2149 chip + input [7:0] IOA_in, + input [7:0] IOB_in, + output [7:0] IOA_out, + output [7:0] IOB_out, + // Separated output + output [ 7:0] psg_A, + output [ 7:0] psg_B, + output [ 7:0] psg_C, + output signed [15:0] fm_snd_left, + output signed [15:0] fm_snd_right, + output signed [15:0] adpcmA_l, + output signed [15:0] adpcmA_r, + output signed [15:0] adpcmB_l, + output signed [15:0] adpcmB_r, + // combined output + output [ 9:0] psg_snd, + output signed [15:0] snd_right, // FM+PSG + output signed [15:0] snd_left, // FM+PSG + output snd_sample +); + +// parameters to select the features for each chip type +// defaults to YM2612 +parameter use_lfo=1, use_ssg=0, num_ch=6, use_pcm=1; +parameter use_adpcm=0; +parameter JT49_DIV=2; + +wire flag_A, flag_B, busy; + +wire write = !cs_n && !wr_n; +wire clk_en, clk_en_ssg; + +// Timers +wire [9:0] value_A; +wire [7:0] value_B; +wire load_A, load_B; +wire enable_irq_A, enable_irq_B; +wire clr_flag_A, clr_flag_B; +wire overflow_A; +wire fast_timers; + +wire zero; // Single-clock pulse at the begginig of s1_enters +// LFO +wire [2:0] lfo_freq; +wire lfo_en; +// Operators +wire amsen_IV; +wire [ 2:0] dt1_I; +wire [ 3:0] mul_II; +wire [ 6:0] tl_IV; + +wire [ 4:0] keycode_II; +wire [ 4:0] ar_I; +wire [ 4:0] d1r_I; +wire [ 4:0] d2r_I; +wire [ 3:0] rr_I; +wire [ 3:0] sl_I; +wire [ 1:0] ks_II; +// SSG operation +wire ssg_en_I; +wire [2:0] ssg_eg_I; +// envelope operation +wire keyon_I; +wire [9:0] eg_IX; +wire pg_rst_II; +// Channel +wire [10:0] fnum_I; +wire [ 2:0] block_I; +wire [ 1:0] rl; +wire [ 2:0] fb_II; +wire [ 2:0] alg_I; +wire [ 2:0] pms_I; +wire [ 1:0] ams_IV; +// PCM +wire pcm_en, pcm_wr; +wire [ 8:0] pcm; +// Test +wire pg_stop, eg_stop; + +wire ch6op; +wire [ 2:0] cur_ch; +wire [ 1:0] cur_op; + +// Operator +wire xuse_internal, yuse_internal; +wire xuse_prevprev1, xuse_prev2, yuse_prev1, yuse_prev2; +wire [ 9:0] phase_VIII; +wire s1_enters, s2_enters, s3_enters, s4_enters; +wire rst_int; +// LFO +wire [6:0] lfo_mod; +wire lfo_rst; +// PSG +wire [3:0] psg_addr; +wire [7:0] psg_data, psg_dout; +wire psg_wr_n; +// ADPCM-A +wire [15:0] addr_a; +wire [ 2:0] up_addr, up_lracl; +wire up_start, up_end; +wire [ 7:0] aon_a, lracl; +wire [ 5:0] atl_a; // ADPCM Total Level +wire up_aon; +// APDCM-B +wire acmd_on_b; // Control - Process start, Key On +wire acmd_rep_b; // Control - Repeat +wire acmd_rst_b; // Control - Reset +wire acmd_up_b; // Control - New cmd received +wire [ 1:0] alr_b; // Left / Right +wire [15:0] astart_b; // Start address +wire [15:0] aend_b; // End address +wire [15:0] adeltan_b; // Delta-N +wire [ 7:0] aeg_b; // Envelope Generator Control +wire [ 5:0] adpcma_flags; // ADPMC-A read over flags +wire adpcmb_flag; +wire [ 6:0] flag_ctl; + + +wire clk_en_2, clk_en_666, clk_en_111, clk_en_55; + +generate +if( use_adpcm==1 ) begin: gen_adpcm + wire rst_n; + + jt12_rst u_rst( + .rst ( rst ), + .clk ( clk ), + .rst_n ( rst_n ) + ); + + jt10_adpcm_drvA u_adpcm_a( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen ), + .cen6 ( clk_en_666 ), // clk & cen must be 666 kHz + .cen1 ( clk_en_111 ), // clk & cen must be 111 kHz + + .addr ( adpcma_addr ), // real hardware has 10 pins multiplexed through RMPX pin + .bank ( adpcma_bank ), + .roe_n ( adpcma_roe_n ), // ADPCM-A ROM output enable + .datain ( adpcma_data ), + + // Control Registers + .atl ( atl_a ), // ADPCM Total Level + .addr_in ( addr_a ), + .lracl_in ( lracl ), + .up_start ( up_start ), + .up_end ( up_end ), + .up_addr ( up_addr ), + .up_lracl ( up_lracl ), + + .aon_cmd ( aon_a ), // ADPCM ON equivalent to key on for FM + .up_aon ( up_aon ), + // Flags + .flags ( adpcma_flags ), + .clr_flags ( flag_ctl[5:0] ), + + .pcm55_l ( adpcmA_l ), + .pcm55_r ( adpcmA_r ) + ); + /* verilator tracing_on */ + jt10_adpcm_drvB u_adpcm_b( + .rst_n ( rst_n ), + .clk ( clk ), + .cen ( cen ), + .cen55 ( clk_en_55 ), + + // Control + .acmd_on_b ( acmd_on_b ), // Control - Process start, Key On + .acmd_rep_b ( acmd_rep_b ), // Control - Repeat + .acmd_rst_b ( acmd_rst_b ), // Control - Reset + //.acmd_up_b ( acmd_up_b ), // Control - New command received + .alr_b ( alr_b ), // Left / Right + .astart_b ( astart_b ), // Start address + .aend_b ( aend_b ), // End address + .adeltan_b ( adeltan_b ), // Delta-N + .aeg_b ( aeg_b ), // Envelope Generator Control + // Flag + .flag ( adpcmb_flag ), + .clr_flag ( flag_ctl[6] ), + // memory + .addr ( adpcmb_addr ), + .data ( adpcmb_data ), + .roe_n ( adpcmb_roe_n ), + + .pcm55_l ( adpcmB_l ), + .pcm55_r ( adpcmB_r ) + ); + + /* verilator tracing_on */ + assign snd_sample = zero; + jt10_acc u_acc( + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( op_result_hd ), + .rl ( rl ), + .zero ( zero ), + .s1_enters ( s2_enters ), + .s2_enters ( s1_enters ), + .s3_enters ( s4_enters ), + .s4_enters ( s3_enters ), + .cur_ch ( cur_ch ), + .cur_op ( cur_op ), + .alg ( alg_I ), + .adpcmA_l ( adpcmA_l ), + .adpcmA_r ( adpcmA_r ), + .adpcmB_l ( adpcmB_l ), + .adpcmB_r ( adpcmB_r ), + // combined output + .left ( fm_snd_left ), + .right ( fm_snd_right ) + ); +end else begin : gen_adpcm_no + assign adpcmA_l = 'd0; + assign adpcmA_r = 'd0; + assign adpcmB_l = 'd0; + assign adpcmB_r = 'd0; + assign adpcma_addr = 'd0; + assign adpcma_bank = 'd0; + assign adpcma_roe_n = 'b1; + assign adpcmb_addr = 'd0; + assign adpcmb_roe_n = 'd1; +end +endgenerate + +/* verilator tracing_on */ +jt12_dout #(.use_ssg(use_ssg),.use_adpcm(use_adpcm)) u_dout( +// .rst_n ( rst_n ), + .clk ( clk ), // CPU clock + .flag_A ( flag_A ), + .flag_B ( flag_B ), + .busy ( busy ), + .adpcma_flags ( adpcma_flags ), + .adpcmb_flag ( adpcmb_flag ), + .psg_dout ( psg_dout ), + .addr ( addr ), + .dout ( dout ) +); + + +/* verilator tracing_on */ +jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm), .use_adpcm(use_adpcm)) + u_mmr( + .rst ( rst ), + .clk ( clk ), + .cen ( cen ), // external clock enable + .clk_en ( clk_en ), // internal clock enable + .clk_en_2 ( clk_en_2 ), // input cen divided by 2 + .clk_en_ssg ( clk_en_ssg), // internal clock enable + .clk_en_666 ( clk_en_666), + .clk_en_111 ( clk_en_111), + .clk_en_55 ( clk_en_55 ), + .din ( din ), + .write ( write ), + .addr ( addr ), + .busy ( busy ), + .ch6op ( ch6op ), + .cur_ch ( cur_ch ), + .cur_op ( cur_op ), + // LFO + .lfo_freq ( lfo_freq ), + .lfo_en ( lfo_en ), + // Timers + .value_A ( value_A ), + .value_B ( value_B ), + .load_A ( load_A ), + .load_B ( load_B ), + .enable_irq_A ( enable_irq_A ), + .enable_irq_B ( enable_irq_B ), + .clr_flag_A ( clr_flag_A ), + .clr_flag_B ( clr_flag_B ), + .flag_A ( flag_A ), + .overflow_A ( overflow_A ), + .fast_timers( fast_timers ), + // PCM + .pcm ( pcm ), + .pcm_en ( pcm_en ), + .pcm_wr ( pcm_wr ), + // ADPCM-A + .aon_a ( aon_a ), // ON + .atl_a ( atl_a ), // TL + .addr_a ( addr_a ), // address latch + .lracl ( lracl ), // L/R ADPCM Channel Level + .up_start ( up_start ), // write enable start address latch + .up_end ( up_end ), // write enable end address latch + .up_addr ( up_addr ), // write enable end address latch + .up_lracl ( up_lracl ), + .up_aon ( up_aon ), + // ADPCM-B + .acmd_on_b ( acmd_on_b ), // Control - Process start, Key On + .acmd_rep_b ( acmd_rep_b ), // Control - Repeat + .acmd_rst_b ( acmd_rst_b ), // Control - Reset + .acmd_up_b ( acmd_up_b ), // Control - New command received + .alr_b ( alr_b ), // Left / Right + .astart_b ( astart_b ), // Start address + .aend_b ( aend_b ), // End address + .adeltan_b ( adeltan_b ), // Delta-N + .aeg_b ( aeg_b ), // Envelope Generator Control + .flag_ctl ( flag_ctl ), + // Operator + .xuse_prevprev1 ( xuse_prevprev1 ), + .xuse_internal ( xuse_internal ), + .yuse_internal ( yuse_internal ), + .xuse_prev2 ( xuse_prev2 ), + .yuse_prev1 ( yuse_prev1 ), + .yuse_prev2 ( yuse_prev2 ), + // PG + .fnum_I ( fnum_I ), + .block_I ( block_I ), + .pg_stop ( pg_stop ), + // EG + .rl ( rl ), + .fb_II ( fb_II ), + .alg_I ( alg_I ), + .pms_I ( pms_I ), + .ams_IV ( ams_IV ), + .amsen_IV ( amsen_IV ), + .dt1_I ( dt1_I ), + .mul_II ( mul_II ), + .tl_IV ( tl_IV ), + + .ar_I ( ar_I ), + .d1r_I ( d1r_I ), + .d2r_I ( d2r_I ), + .rr_I ( rr_I ), + .sl_I ( sl_I ), + .ks_II ( ks_II ), + + .eg_stop ( eg_stop ), + // SSG operation + .ssg_en_I ( ssg_en_I ), + .ssg_eg_I ( ssg_eg_I ), + + .keyon_I ( keyon_I ), + // Operator + .zero ( zero ), + .s1_enters ( s1_enters ), + .s2_enters ( s2_enters ), + .s3_enters ( s3_enters ), + .s4_enters ( s4_enters ), + // PSG interace + .psg_addr ( psg_addr ), + .psg_data ( psg_data ), + .psg_wr_n ( psg_wr_n ) +); + +/* verilator tracing_on */ +// YM2203 seems to use a fixed cen/3 clock for the timers, regardless +// of the prescaler setting +wire timer_cen = fast_timers ? cen : clk_en; +jt12_timers #(.num_ch(num_ch)) u_timers ( + .clk ( clk ), + .clk_en ( timer_cen ), + .rst ( rst ), + .zero ( zero ), + .value_A ( value_A ), + .value_B ( value_B ), + .load_A ( load_A ), + .load_B ( load_B ), + .enable_irq_A( enable_irq_A ), + .enable_irq_B( enable_irq_B ), + .clr_flag_A ( clr_flag_A ), + .clr_flag_B ( clr_flag_B ), + .flag_A ( flag_A ), + .flag_B ( flag_B ), + .overflow_A ( overflow_A ), + .irq_n ( irq_n ) +); + +// YM2203 does not have LFO +generate +if( use_lfo== 1) begin : gen_lfo + jt12_lfo u_lfo( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .zero ( zero ), + `ifdef NOLFO + .lfo_rst ( 1'b1 ), + `else + .lfo_rst ( 1'b0 ), + `endif + .lfo_en ( lfo_en ), + .lfo_freq ( lfo_freq ), + .lfo_mod ( lfo_mod ) + ); +end else begin : gen_nolfo + assign lfo_mod = 7'd0; +end +endgenerate + +// YM2203/YM2610 have a PSG + +`ifndef NOSSG +generate + if( use_ssg==1 ) begin : gen_ssg + jt49 #(.COMP(2'b00), .CLKDIV(JT49_DIV)) + u_psg( // note that input ports are not multiplexed + .rst_n ( ~rst ), + .clk ( clk ), // signal on positive edge + .clk_en ( clk_en_ssg), // clock enable on negative edge + .addr ( psg_addr ), + .cs_n ( 1'b0 ), + .wr_n ( psg_wr_n ), // write + .din ( psg_data ), + .sound ( psg_snd ), // combined output + .A ( psg_A ), + .B ( psg_B ), + .C ( psg_C ), + .dout ( psg_dout ), + .sel ( 1'b1 ), // half clock speed + // Unused: + .IOA_out ( IOA_out ), + .IOB_out ( IOB_out ), + .IOA_in ( IOA_in ), + .IOB_in ( IOB_in ), + .sample ( ) + ); + assign snd_left = fm_snd_left + { 1'b0, psg_snd[9:0],5'd0}; + assign snd_right = fm_snd_right + { 1'b0, psg_snd[9:0],5'd0}; + end else begin : gen_nossg + assign psg_snd = 10'd0; + assign snd_left = fm_snd_left; + assign snd_right= fm_snd_right; + assign psg_dout = 8'd0; + assign psg_A = 8'd0; + assign psg_B = 8'd0; + assign psg_C = 8'd0; + end +endgenerate +`else + assign psg_snd = 10'd0; + assign snd_left = fm_snd_left; + assign snd_right= fm_snd_right; + assign psg_dout = 8'd0; +`endif + +wire [ 8:0] op_result; +wire [13:0] op_result_hd; +`ifndef NOFM +/* verilator tracing_on */ +jt12_pg #(.num_ch(num_ch)) u_pg( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + // Channel frequency + .fnum_I ( fnum_I ), + .block_I ( block_I ), + // Operator multiplying + .mul_II ( mul_II ), + // Operator detuning + .dt1_I ( dt1_I ), // same as JT51's DT1 + // Phase modulation by LFO + .lfo_mod ( lfo_mod ), + .pms_I ( pms_I ), + // phase operation + .pg_rst_II ( pg_rst_II ), + .pg_stop ( pg_stop ), + .keycode_II ( keycode_II ), + .phase_VIII ( phase_VIII ) +); + +wire [9:0] eg_V; + +jt12_eg #(.num_ch(num_ch)) u_eg( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .zero ( zero ), + .eg_stop ( eg_stop ), + // envelope configuration + .keycode_II ( keycode_II ), + .arate_I ( ar_I ), // attack rate + .rate1_I ( d1r_I ), // decay rate + .rate2_I ( d2r_I ), // sustain rate + .rrate_I ( rr_I ), // release rate + .sl_I ( sl_I ), // sustain level + .ks_II ( ks_II ), // key scale + // SSG operation + .ssg_en_I ( ssg_en_I ), + .ssg_eg_I ( ssg_eg_I ), + // envelope operation + .keyon_I ( keyon_I ), + // envelope number + .lfo_mod ( lfo_mod ), + .tl_IV ( tl_IV ), + .ams_IV ( ams_IV ), + .amsen_IV ( amsen_IV ), + + .eg_V ( eg_V ), + .pg_rst_II ( pg_rst_II ) +); + +jt12_sh #(.width(10),.stages(4)) u_egpad( + .clk ( clk ), + .clk_en ( clk_en ), + .din ( eg_V ), + .drop ( eg_IX ) +); + +jt12_op #(.num_ch(num_ch)) u_op( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .pg_phase_VIII ( phase_VIII ), + .eg_atten_IX ( eg_IX ), + .fb_II ( fb_II ), + + .test_214 ( 1'b0 ), + .s1_enters ( s1_enters ), + .s2_enters ( s2_enters ), + .s3_enters ( s3_enters ), + .s4_enters ( s4_enters ), + .xuse_prevprev1 ( xuse_prevprev1), + .xuse_internal ( xuse_internal ), + .yuse_internal ( yuse_internal ), + .xuse_prev2 ( xuse_prev2 ), + .yuse_prev1 ( yuse_prev1 ), + .yuse_prev2 ( yuse_prev2 ), + .zero ( zero ), + .op_result ( op_result ), + .full_result ( op_result_hd ) +); +`else +assign op_result = 'd0; +assign op_result_hd = 'd0; +`endif + +/* verilator tracing_on */ + +generate + if( use_pcm==1 ) begin: gen_pcm_acc // YM2612 accumulator + assign fm_snd_right[3:0] = 4'd0; + assign fm_snd_left [3:0] = 4'd0; + assign snd_sample = zero; + reg signed [8:0] pcm2; + + // interpolate PCM samples with automatic sample rate detection + // this feature is not present in original YM2612 + // this improves PCM sample sound greatly + /* + jt12_pcm u_pcm( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .zero ( zero ), + .pcm ( pcm ), + .pcm_wr ( pcm_wr ), + .pcm_resampled ( pcm2 ) + ); + */ + wire rst_pcm_n; + + jt12_rst u_rst_pcm( + .rst ( rst ), + .clk ( clk ), + .rst_n ( rst_pcm_n ) + ); + + `ifndef NOPCMLINEAR + wire signed [10:0] pcm_full; + always @(*) + pcm2 = en_hifi_pcm ? pcm_full[9:1] : pcm; + + jt12_pcm_interpol #(.dw(11), .stepw(5)) u_pcm ( + .rst_n ( rst_pcm_n ), + .clk ( clk ), + .cen ( clk_en ), + .cen55 ( clk_en_55 ), + .pcm_wr( pcm_wr ), + .pcmin ( {pcm[8],pcm, 1'b0} ), + .pcmout( pcm_full ) + ); + `else + assign pcm2 = pcm; + `endif + + jt12_acc u_acc( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( op_result ), + .rl ( rl ), + // note that the order changes to deal + // with the operator pipeline delay + .zero ( zero ), + .s1_enters ( s2_enters ), + .s2_enters ( s1_enters ), + .s3_enters ( s4_enters ), + .s4_enters ( s3_enters ), + .ch6op ( ch6op ), + .pcm_en ( pcm_en ), // only enabled for channel 6 + .pcm ( pcm2 ), + .alg ( alg_I ), + // combined output + .left ( fm_snd_left [15:4] ), + .right ( fm_snd_right[15:4] ) + ); + end + if( use_pcm==0 && use_adpcm==0 ) begin : gen_2203_acc // YM2203 accumulator + wire signed [15:0] mono_snd; + assign fm_snd_left = mono_snd; + assign fm_snd_right = mono_snd; + assign snd_sample = zero; + jt03_acc u_acc( + .rst ( rst ), + .clk ( clk ), + .clk_en ( clk_en ), + .op_result ( op_result_hd ), + // note that the order changes to deal + // with the operator pipeline delay + .s1_enters ( s1_enters ), + .s2_enters ( s2_enters ), + .s3_enters ( s3_enters ), + .s4_enters ( s4_enters ), + .alg ( alg_I ), + .zero ( zero ), + // combined output + .snd ( mono_snd ) + ); + end +endgenerate +endmodule diff --git a/common/Sound/JT12/hdl/mixer/jt12_comb.v b/common/Sound/JT12/hdl/mixer/jt12_comb.v new file mode 100644 index 00000000..dfd390e6 --- /dev/null +++ b/common/Sound/JT12/hdl/mixer/jt12_comb.v @@ -0,0 +1,59 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-12-2018 + +*/ + +module jt12_comb #(parameter + w=16, // bit width + m=1 // depth of comb filter +)( + input rst, + input clk, +(* direct_enable *) input cen, + input signed [w-1:0] snd_in, + output reg signed [w-1:0] snd_out +); + +wire signed [w-1:0] prev; + +// m-delay stage +generate + genvar k; + reg signed [w-1:0] mem[0:m-1]; + assign prev=mem[m-1]; + for(k=0;k. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-12-2018 + +*/ + +module jt12_decim #(parameter calcw=18, inw=16, + n=2, // number of stages + m=1, // depth of comb filter + rate=2 // it will stuff with as many as (rate-1) zeros +)( + input rst, + input clk, +(* direct_enable *) input cen_in, +(* direct_enable *) input cen_out, + input signed [inw-1:0] snd_in, + output reg signed [inw-1:0] snd_out +); + +reg signed [calcw-1:0] inter6; +wire signed [calcw-1:0] integ_op, comb_op; +localparam wdiff = calcw - inw; + +// integrator at clk x cen sampling rate +generate + genvar k2; + reg [calcw-1:0] integ_data[0:n]; + assign integ_op = integ_data[n]; + always @(*) + integ_data[0] = { {wdiff{snd_in[inw-1]}}, snd_in }; + for(k2=1;k2<=n;k2=k2+1) begin : integ_gen + always @(posedge clk) + if(rst) begin + integ_data[k2] <= {calcw{1'b0}}; + end else if(cen_in) begin + integ_data[k2] <= integ_data[k2] + integ_data[k2-1]; + end + end +endgenerate + +// interpolator +always @(posedge clk) + if(rst) begin + inter6 <= {calcw{1'b0}}; + end else if(cen_out) begin + inter6 <= integ_op; + end + +generate + genvar k; + wire [calcw-1:0] comb_data[0:n]; + assign comb_data[0] = inter6; + assign comb_op = comb_data[n]; + for(k=0;k. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 11-12-2018 + + Each channel can use the full range of the DAC as they do not + get summed in the real chip. + + Operator data is summed up without adding extra bits. This is + the case of real YM3438, which was used on Megadrive 2 models. + +*/ + +/* rate up-scaler for FM+PSG channel +*/ + +module jt12_fm_uprate( + input rst, + input clk, + input signed [15:0] fm_snd, + input signed [11:0] psg_snd, + input fm_en, // enable FM + input cen_1008, + input cen_252, + input cen_63, + input cen_9, + output signed [15:0] snd // Mixed sound at clk sample rate +); + +wire signed [15:0] fm2,fm3,fm4; + +reg [15:0] mixed; +always @(posedge clk) + mixed <= (fm_en?fm_snd:16'd0) + {{1{psg_snd[11]}},psg_snd,3'b0}; + +// 1008 --> 252 x4 +jt12_interpol #(.calcw(17),.inw(16),.rate(4),.m(1),.n(1)) +u_fm2( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen_1008 ), + .cen_out( cen_252 ), + .snd_in ( mixed ), + .snd_out( fm2 ) +); + +// 252 --> 63 x4 +jt12_interpol #(.calcw(19),.inw(16),.rate(4),.m(1),.n(3)) +u_fm3( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen_252 ), + .cen_out( cen_63 ), + .snd_in ( fm2 ), + .snd_out( fm3 ) +); + +// 63 --> 9 x7 +jt12_interpol #(.calcw(21),.inw(16),.rate(7),.m(2),.n(2)) +u_fm4( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen_63 ), + .cen_out( cen_9 ), + .snd_in ( fm3 ), + .snd_out( fm4 ) +); + +// 9 --> 1 x9 +jt12_interpol #(.calcw(21),.inw(16),.rate(9),.m(2),.n(2)) +u_fm5( + .clk ( clk ), + .rst ( rst ), + .cen_in ( cen_9 ), + .cen_out( 1'b1 ), + .snd_in ( fm4 ), + .snd_out( snd ) +); + +endmodule // jt12_fm_uprate \ No newline at end of file diff --git a/common/Sound/JT12/hdl/mixer/jt12_genmix.v b/common/Sound/JT12/hdl/mixer/jt12_genmix.v new file mode 100644 index 00000000..1963fdcd --- /dev/null +++ b/common/Sound/JT12/hdl/mixer/jt12_genmix.v @@ -0,0 +1,180 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 11-12-2018 + + Each channel can use the full range of the DAC as they do not + get summed in the real chip. + + Operator data is summed up without adding extra bits. This is + the case of real YM3438, which was used on Megadrive 2 models. + +*/ + +/* Mixer for Megadrive/Genesis + cen_fm must be 1 over 7 of clk + psg_cen_240 must be 1 over 15 of clk + PSG and FM signals are interpolated up to clk sample rate. +*/ + +module jt12_genmix( + input rst, + input clk, + input signed [15:0] fm_left, + input signed [15:0] fm_right, + input signed [10:0] psg_snd, + input fm_en, // enable FM + input psg_en, // enable PSG + // Mixed sound at clk sample rate + output signed [15:0] snd_left, + output signed [15:0] snd_right +); + +///////////////////////////////////////////////// +// PSG +// x5 -> div 3 -> div 7 +// 54MHz count up to: +// orig -> 16*15 = 240 +// x5 -> 16*15/5 = 48 +// div 3 -> 48*3 = 144 +// div 7 -> 144*7 = 1008 <=> fm_sample +// 48 x 5 = 240, +reg [5:0] psgcnt48; +reg [2:0] psgcnt240, psgcnt1008; +reg [1:0] psgcnt144; + +always @(posedge clk) + if( rst ) begin + psgcnt48 <= 6'd0; + psgcnt240 <= 3'd0; + psgcnt144 <= 2'd0; + psgcnt1008<= 3'd0; + end else begin + psgcnt48 <= psgcnt48 ==6'd47 ? 6'd0 : psgcnt48 +6'd1; + if( psgcnt48 == 6'd47 ) begin + psgcnt240 <= psgcnt240==3'd4 ? 3'd0 : psgcnt240+3'd1; + psgcnt144 <= psgcnt144 ==2'd2 ? 2'd0 : psgcnt144+2'd1; + if( psgcnt144==2'd0 ) + psgcnt1008 <= psgcnt1008==3'd6 ? 3'd0 : psgcnt1008+3'd1; + end + end + +reg psg_cen_1008, psg_cen_240, psg_cen_48, psg_cen_144; +always @(posedge clk) begin + psg_cen_240 <= psgcnt48 ==6'd47 && psgcnt240 == 3'd0; + psg_cen_48 <= psgcnt48 ==6'd47; + psg_cen_144 <= psgcnt48 ==6'd47 && psgcnt144==2'd0; + psg_cen_1008<= psgcnt48 ==6'd47 && psgcnt144==2'd0 && psgcnt1008==3'd0; +end + +wire signed [11:0] psg0, psg1, psg2, psg3; +assign psg0 = psg_en ? { psg_snd[10], psg_snd } : 12'b0; + +// 48 +jt12_interpol #(.calcw(19),.inw(12),.rate(5),.m(4),.n(2)) +u_psg1( + .clk ( clk ), + .rst ( rst ), + .cen_in ( psg_cen_240 ), + .cen_out( psg_cen_48 ), + .snd_in ( psg0 ), + .snd_out( psg1 ) +); + +// 144 +jt12_decim #(.calcw(19),.inw(12),.rate(3),.m(2),.n(3) ) +u_psg2( + .clk ( clk ), + .rst ( rst ), + .cen_in ( psg_cen_48 ), + .cen_out( psg_cen_144 ), + .snd_in ( psg1 ), + .snd_out( psg2 ) +); + +// 1008 +jt12_decim #(.calcw(15),.inw(12),.rate(7),.m(1),.n(1) ) +u_psg3( + .clk ( clk ), + .rst ( rst ), + .cen_in ( psg_cen_144 ), + .cen_out( psg_cen_1008), + .snd_in ( psg2 ), + .snd_out( psg3 ) +); + +///////////////////////////////////////////////// +// FM +// x4 -> x4 -> x7 -> x9 +// 54MHz count up to: +// 252 -> 63 -> 9 -> 1 +reg [1:0] clkcnt252, clkcnt1008; +reg [2:0] clkcnt63; +reg [3:0] clkcnt9; +always @(posedge clk) + if( rst ) begin + clkcnt1008<= 2'd0; + clkcnt252 <= 2'd0; + clkcnt63 <= 3'd0; + clkcnt9 <= 4'd0; + end else begin + clkcnt9 <= clkcnt9 ==4'd8 ? 4'd0 : clkcnt9 +4'd1; + if( clkcnt9== 4'd8 ) begin + clkcnt63 <= clkcnt63 ==3'd6 ? 3'd0 : clkcnt63 +3'd1; + if( clkcnt63==3'd6 ) begin + clkcnt252 <= clkcnt252+2'd1; + if(clkcnt252==2'd3) clkcnt1008<=clkcnt1008+2'd1; + end + end + end +// evenly spaced clock enable signals +reg cen_1008, cen_252, cen_63, cen_9; +always @(posedge clk) begin + cen_9 <= clkcnt9 ==4'd8; + cen_63 <= clkcnt9 ==4'd8 && clkcnt63 ==3'd0; + cen_252 <= clkcnt9 ==4'd8 && clkcnt63 ==3'd0 && clkcnt252 ==2'd0; + cen_1008 <= clkcnt9 ==4'd8 && clkcnt63 ==3'd0 && clkcnt252 ==2'd0 && clkcnt1008==2'd0; +end + +jt12_fm_uprate u_left( + .rst ( rst ), + .clk ( clk ), + .fm_snd ( fm_left ), + .psg_snd ( psg3 ), + .fm_en ( fm_en ), + .cen_1008 ( cen_1008 ), + .cen_252 ( cen_252 ), + .cen_63 ( cen_63 ), + .cen_9 ( cen_9 ), + .snd ( snd_left ) // Mixed sound at clk sample rate +); + +jt12_fm_uprate u_right( + .rst ( rst ), + .clk ( clk ), + .fm_snd ( fm_right ), + .psg_snd ( psg3 ), + .fm_en ( fm_en ), + .cen_1008 ( cen_1008 ), + .cen_252 ( cen_252 ), + .cen_63 ( cen_63 ), + .cen_9 ( cen_9 ), + .snd ( snd_right ) // Mixed sound at clk sample rate +); + +endmodule // jt12_genmix \ No newline at end of file diff --git a/common/Sound/JT12/hdl/mixer/jt12_interpol.v b/common/Sound/JT12/hdl/mixer/jt12_interpol.v new file mode 100644 index 00000000..e5ff23ba --- /dev/null +++ b/common/Sound/JT12/hdl/mixer/jt12_interpol.v @@ -0,0 +1,92 @@ +/* This file is part of JT12. + + + JT12 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT12 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 JT12. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-12-2018 + +*/ + +module jt12_interpol #(parameter calcw=18, inw=16, + n=2, // number of stages + m=1, // depth of comb filter + rate=2 // it will stuff with as many as (rate-1) zeros +)( + input rst, + input clk, +(* direct_enable *) input cen_in, +(* direct_enable *) input cen_out, + input signed [inw-1:0] snd_in, + output reg signed [inw-1:0] snd_out +); + +reg signed [calcw-1:0] inter6; +wire signed [calcw-1:0] comb_op, integ_op; +localparam wdiff = calcw - inw; + +generate + genvar k; + wire [calcw-1:0] comb_data[0:n]; + assign comb_data[0] = { {wdiff{snd_in[inw-1]}}, snd_in }; + assign comb_op = comb_data[n]; + for(k=0;k. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 11-12-2018 + + Each channel can use the full range of the DAC as they do not + get summed in the real chip. + + Operator data is summed up without adding extra bits. This is + the case of real YM3438, which was used on Megadrive 2 models. + +*/ + +// Generic mixer +// wout should be larger or equal than any input (w0,w1,w2,w3) + +module jt12_mixer #(parameter w0=16,w1=16,w2=16,w3=16,wout=20) +( + input clk, + input cen, + // input signals + input signed [w0-1:0] ch0, + input signed [w1-1:0] ch1, + input signed [w2-1:0] ch2, + input signed [w3-1:0] ch3, + // gain for each channel in 4.4 fixed point format + input [7:0] gain0, + input [7:0] gain1, + input [7:0] gain2, + input [7:0] gain3, + output reg signed [wout-1:0] mixed +); + +reg signed [w0+7:0] ch0_amp; +reg signed [w1+7:0] ch1_amp; +reg signed [w2+7:0] ch2_amp; +reg signed [w3+7:0] ch3_amp; + +// rescale to wout+4+8 +wire signed [wout+11:0] scaled0 = { {wout+4-w0{ch0_amp[w0+7]}}, ch0_amp }; +wire signed [wout+11:0] scaled1 = { {wout+4-w1{ch1_amp[w1+7]}}, ch1_amp }; +wire signed [wout+11:0] scaled2 = { {wout+4-w2{ch2_amp[w2+7]}}, ch2_amp }; +wire signed [wout+11:0] scaled3 = { {wout+4-w3{ch3_amp[w3+7]}}, ch3_amp }; + +reg signed [wout+11:0] sum, limited; + +wire signed [wout+11:0] max_pos = { {12{1'b0}}, {(wout-1){1'b1}}}; + +wire signed [8:0] + g0 = {1'b0, gain0}, + g1 = {1'b0, gain1}, + g2 = {1'b0, gain2}, + g3 = {1'b0, gain3}; + +// Apply gain +always @(posedge clk) if(cen) begin + ch0_amp <= g0 * ch0; + ch1_amp <= g1 * ch1; + ch2_amp <= g2 * ch2; + ch3_amp <= g3 * ch3; + + // divides by 16 to take off the decimal part and leave only + // the integer part + sum <= (scaled0 + scaled1 + scaled2 + scaled3)>>>4; + limited <= sum>max_pos ? max_pos : (sum<~max_pos ? ~max_pos : sum); + mixed <= limited[wout-1:0]; +end + +endmodule // jt12_mixer From 485e09b3a512d33542f93a81af9e3d76b5c2ba5b Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sun, 2 Jan 2022 01:01:22 +0100 Subject: [PATCH 4/7] Konami Finalizer --- Arcade_MiST/Konami Finalizer/Finalizr.qpf | 31 + Arcade_MiST/Konami Finalizer/Finalizr.qsf | 259 +++++ Arcade_MiST/Konami Finalizer/Finalizr.sdc | 134 +++ Arcade_MiST/Konami Finalizer/README.md | 11 + ...nalizer - Super Transformation (Set 1).mra | 150 +++ ...er - Super Transformation (Set 2) [bl].mra | 78 ++ ...nalizer - Super Transformation (Set 2).mra | 150 +++ Arcade_MiST/Konami Finalizer/rtl/Finalizer.sv | 572 ++++++++++ .../Konami Finalizer/rtl/Finalizer_MiST.sv | 309 ++++++ Arcade_MiST/Konami Finalizer/rtl/KONAMI1.sv | 79 ++ .../Konami Finalizer/rtl/audio_iir_filter.v | 173 +++ Arcade_MiST/Konami Finalizer/rtl/build_id.tcl | 35 + Arcade_MiST/Konami Finalizer/rtl/dpram_dc.vhd | 136 +++ .../Konami Finalizer/rtl/finalizer_lpf.v | 60 ++ .../Konami Finalizer/rtl/finalizer_psg_lpf.sv | 60 ++ Arcade_MiST/Konami Finalizer/rtl/jt49_dcrm2.v | 62 ++ .../Konami Finalizer/rtl/jtframe_frac_cen.v | 58 + Arcade_MiST/Konami Finalizer/rtl/k005885.sv | 992 ++++++++++++++++++ Arcade_MiST/Konami Finalizer/rtl/pll.qip | 4 + Arcade_MiST/Konami Finalizer/rtl/pll.v | 348 ++++++ .../Konami Finalizer/rtl/rom_loader.sv | 433 ++++++++ Arcade_MiST/Konami Finalizer/rtl/sdram.sv | 340 ++++++ Arcade_MiST/Konami Finalizer/rtl/spram.vhd | 46 + .../Konami Finalizer/rtl/t8049_notri.vhd | 295 ++++++ 24 files changed, 4815 insertions(+) create mode 100644 Arcade_MiST/Konami Finalizer/Finalizr.qpf create mode 100644 Arcade_MiST/Konami Finalizer/Finalizr.qsf create mode 100644 Arcade_MiST/Konami Finalizer/Finalizr.sdc create mode 100644 Arcade_MiST/Konami Finalizer/README.md create mode 100644 Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 1).mra create mode 100644 Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2) [bl].mra create mode 100644 Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2).mra create mode 100644 Arcade_MiST/Konami Finalizer/rtl/Finalizer.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/Finalizer_MiST.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/KONAMI1.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Konami Finalizer/rtl/build_id.tcl create mode 100644 Arcade_MiST/Konami Finalizer/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Konami Finalizer/rtl/finalizer_lpf.v create mode 100644 Arcade_MiST/Konami Finalizer/rtl/finalizer_psg_lpf.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Konami Finalizer/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Konami Finalizer/rtl/k005885.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/pll.qip create mode 100644 Arcade_MiST/Konami Finalizer/rtl/pll.v create mode 100644 Arcade_MiST/Konami Finalizer/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/sdram.sv create mode 100644 Arcade_MiST/Konami Finalizer/rtl/spram.vhd create mode 100644 Arcade_MiST/Konami Finalizer/rtl/t8049_notri.vhd diff --git a/Arcade_MiST/Konami Finalizer/Finalizr.qpf b/Arcade_MiST/Konami Finalizer/Finalizr.qpf new file mode 100644 index 00000000..3b73c61b --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/Finalizr.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "00:21:03 December 03, 2019" + +# Revisions + +PROJECT_REVISION = "Finalizr" + diff --git a/Arcade_MiST/Konami Finalizer/Finalizr.qsf b/Arcade_MiST/Konami Finalizer/Finalizr.qsf new file mode 100644 index 00000000..41e89058 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/Finalizr.qsf @@ -0,0 +1,259 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Finalizr_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" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY Finalizer_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/tm.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(Finalizer_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Finalizer_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name FORCE_SYNCH_CLEAR ON +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Finalizer_MiST.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/KONAMI1.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/k005885.sv +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/finalizer_psg_lpf.sv +set_global_assignment -name VERILOG_FILE rtl/finalizer_lpf.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Finalizer.sv +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name VHDL_FILE rtl/t8049_notri.vhd +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v +set_global_assignment -name QIP_FILE ../../common/Sound/sn76489/sn76489.qip +set_global_assignment -name QIP_FILE ../../common/CPU/t48/i8039.qip +set_global_assignment -name SIGNALTAP_FILE output_files/sdram.stp +set_global_assignment -name SIGNALTAP_FILE output_files/tm.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/Finalizr.sdc b/Arcade_MiST/Konami Finalizer/Finalizr.sdc new file mode 100644 index 00000000..4a373c09 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/Finalizr.sdc @@ -0,0 +1,134 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Konami Finalizer/README.md b/Arcade_MiST/Konami Finalizer/README.md new file mode 100644 index 00000000..55eec1c8 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/README.md @@ -0,0 +1,11 @@ +# MiST port of Konami Finalizer: Super Transformation by ACE + +https://github.com/MiSTer-devel/Arcade-Finalizer_MiSTer + +## Usage + +- Create ROM and ARC files from the MRA files using the MRA utility. + Example: mra -A -z /path/to/mame/roms "Finalizer - Super Transformation (Set 1).mra" +- Copy the ROM files to the root of the SD Card +- Copy the RBF and ARC files to the same folder on the SD Card +- MRA utility: https://github.com/sebdel/mra-tools-c/ \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 1).mra b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 1).mra new file mode 100644 index 00000000..787468e2 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 1).mra @@ -0,0 +1,150 @@ + + Finalizer: Super Transformation + World + no + no + Set 1 + + + + 1985 + Konami + Shooter - Vertical + + finalizr + finalizr + 0224 + Finalizr + + + 15kHz + no + no + + 2 (alternating) + 8-way + + 3 + + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + 04 09 00 04 1E 00 00 04 E3 55 23 00 39 23 00 3A 23 80 3A 04 F3 BA 00 05 FA 04 C9 00 04 1B + C5 80 AA 23 00 3A 23 80 3A B8 08 23 18 A0 B8 09 23 00 A0 23 09 D7 04 36 93 8D 8F 91 93 95 + 97 97 97 97 97 97 97 97 97 97 97 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 9B 9D 9F + A1 A3 A5 A7 A9 AB AD AF B1 B3 B5 B7 B9 BB BD BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF + BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF C1 C3 C5 C7 24 1C 84 B6 84 C1 84 CB A4 + AD C4 DE 84 DD A4 04 24 84 A4 7E 24 26 84 00 24 55 44 68 A4 4D A4 B1 A4 08 A4 EA A4 DF A4 + E6 A4 45 84 D8 24 98 C4 6C C4 2A C4 C8 24 9C A4 EE 24 A0 44 EF B8 24 F0 C6 DA 18 F0 96 DC + FA 03 AA F6 1B 03 8D B3 24 00 24 DB 42 6A 62 58 A3 93 42 6E 62 53 3F A3 AB 93 42 6A 62 53 + 3F A3 93 23 00 AD AC A3 34 F3 96 F7 24 F8 FF FF FA C6 22 B8 27 F0 6A A0 18 F0 17 53 03 C6 + 12 A0 04 1B C8 F0 03 01 96 24 B8 24 B0 01 23 A0 3A 23 00 39 04 1B E4 FC B8 20 F0 AF 18 F0 + AB 23 06 AC AD A8 BE 00 BA 02 B9 02 54 66 FC 03 10 AC AD EA 38 BA 02 F8 03 01 A8 AC AD E9 + 38 B9 02 FF 17 AF 6B C6 22 24 38 23 12 AC AD A8 B9 20 F1 AF 19 F1 AB BE 00 BA 02 B9 02 54 + 66 FC 03 10 AC AD EA 67 BA 02 F8 03 02 A8 AC AD E9 67 B9 02 FF 17 AF 6B C6 22 24 67 B8 20 + F0 AF 18 F0 AB 23 06 AC AD A8 BE 00 BA 01 B9 02 44 D2 B8 22 84 C4 B8 22 84 CF C5 BE 00 B8 + 2C F0 AC AD D5 AC C5 18 F0 A9 18 F0 AA AB 18 F0 D5 AB C5 18 F0 AF B8 33 F0 D5 AF C5 B8 39 + F0 D5 AD C5 18 F0 D5 AA C5 18 F0 D5 AE C5 18 F0 D5 A8 C5 18 F0 D5 A9 E4 00 B8 26 F0 B9 2C + 69 A9 FA A1 F0 17 A0 03 EB C6 ED 04 1B B8 25 B0 00 04 1B 6D AD 1C FC 93 A3 34 F3 96 F8 44 + F8 FF 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E 40 42 44 46 48 4A 4C 4E 2E 30 50 52 54 2C 2E 30 + 56 50 58 36 5A 5C 5E 60 40 42 62 64 44 A8 44 AE 44 B2 44 B6 44 BA 44 BE 44 C2 44 C6 84 1E + 84 3B 84 48 84 52 84 5C 84 66 84 70 84 7A 44 CA 44 CE 84 04 A4 00 84 0C 84 10 84 08 C4 20 + C4 26 84 14 84 84 84 8E 84 98 84 A2 84 AC FF B3 B8 22 F0 AF 18 F0 AB 23 20 AC AD A8 BE 00 + BA 02 B9 02 54 66 FC 03 10 AC AD EA 7A BA 02 F8 03 04 A8 AC AD E9 7A B9 02 FF 17 AF 6B C6 + 97 44 7A 04 1B 39 ED 9A FC AD FE 17 53 0F AE 96 A6 93 44 66 23 10 6E E3 44 99 23 20 44 AA + 23 30 44 AA 23 40 44 AA 23 50 44 AA 23 60 44 AA 23 70 44 AA 23 80 44 AA 23 90 44 AA 23 A0 + 44 AA 54 66 FC 03 10 AC AD EA D2 BA 01 F8 03 00 A8 AC AD E9 D2 B9 02 FF 17 AF 6B C6 97 44 + D2 B8 25 B0 01 18 B0 00 04 1B A3 34 F3 96 F8 84 F2 FF 70 70 70 70 00 54 00 00 00 00 00 00 + 00 00 00 00 80 80 80 80 00 60 00 00 00 00 00 00 00 00 00 00 0E 1C 2A 38 46 54 62 70 70 62 + 54 46 38 2A 1C 0E 0C 18 24 30 3C 48 54 60 60 54 48 3C 30 24 18 0C 0A 14 1E 28 32 3C 46 50 + 50 46 3C 32 28 1E 14 0A 08 10 18 20 28 30 38 40 40 38 30 28 20 18 10 08 06 0C 12 18 1E 24 + 2A 30 30 2A 24 1E 18 12 0C 06 04 08 0C 10 14 18 1C 20 20 1C 18 14 10 0C 08 04 02 04 06 08 + 0A 0C 0E 10 10 0E 0C 0A 08 06 04 02 AA AA AA AA 00 80 00 00 00 00 00 00 00 00 00 00 12 25 + 38 4A 5D 70 82 95 95 82 70 5D 4A 38 25 12 10 20 30 40 50 60 70 80 80 70 60 50 40 30 20 10 + 0D 1A 28 35 42 50 5D 6A 6A 5D 50 42 35 28 1A 0D 05 0A 10 15 1A 20 25 2A 2A 25 20 1A 15 10 + 0A 05 02 05 08 0A 0D 10 12 15 15 12 10 0D 0A 08 05 02 FF FF FF FF FF FF FF FF FF FF FF FF + FF FF 10 57 23 0A 24 57 23 B0 44 AA 23 00 44 AA 23 D0 44 AA 23 E0 44 AA 14 E4 FB 53 7F AB + 23 00 84 43 14 E4 FB 53 7F AB 23 2B 6E A3 6B 44 99 40 40 40 40 00 20 00 00 00 00 00 00 00 + 00 00 00 14 E4 FB 53 7F AB 23 20 6E E3 6B 44 99 14 E4 FB 53 7F AB 23 30 84 43 14 E4 FB 53 + 3F AB 23 40 84 43 14 E4 FB 53 1F AB 23 50 84 43 14 E4 FB 53 0F AB 23 60 84 43 14 E4 FB 53 + 07 AB 23 70 84 43 14 E4 FB 53 03 AB 23 80 84 43 14 E4 FB 53 7F AB 23 A0 84 43 14 E4 FB 53 + 7F AB 23 B0 84 43 14 E4 FB 53 3F AB 23 C0 84 43 14 E4 FB 53 07 AB 23 D0 84 43 14 E4 FB 53 + 03 AB 23 E0 84 43 85 95 B8 20 23 18 A0 23 E0 84 D4 85 B8 20 23 00 A0 23 F8 84 D4 A5 B5 B8 + 20 23 10 A0 23 E8 18 A0 04 1B A5 B8 22 84 BA FA 53 0F AB B8 29 F0 AC B9 41 69 A9 FB A1 1C + FC 53 0F A0 04 1B A3 34 F3 96 F2 A4 F3 FF FF FF FF FF FF FF 23 C0 44 AA BF FF A4 0A BF 7F + 23 01 AC AD AE B9 04 BA 70 BB 70 14 EC 5F 39 ED 19 FC 17 53 07 C6 38 AC AD EE 15 F9 AE EB + 15 FA AB FF 77 53 7F AF C6 43 03 C1 C6 3C A4 15 23 04 A4 21 F9 03 10 A9 AE A4 15 04 1B BF + 08 D5 BB F0 C5 A4 53 BF 20 D5 BB D8 C5 BC 06 BD 06 BE 00 BA 02 B9 02 B8 05 54 66 FC 03 10 + AC AD EA 5F BA 03 F8 03 01 A8 AC AD E9 5F B9 01 FF 17 AF D5 6B C5 C6 43 A4 5F B8 20 F0 AF + 18 F0 AB 23 06 AC A8 AD BE 00 BA 02 B9 02 54 66 FC 03 02 AC AD EA 90 BA 02 F8 03 00 A8 AC + AD E9 90 B9 02 FF 17 AF 6B C6 43 A4 90 BF 7F A4 B3 BF 3F 23 01 AC AD AE BA 70 BB 70 14 EC + 5F 39 ED C0 FC 17 53 03 C6 DB AC AD EE BC BE 04 EB BC FA AB FF 77 53 7F AF C6 43 A4 BC 23 + 01 A4 C8 23 00 B8 2B A0 04 1B 23 01 A4 E1 23 02 A4 E1 23 A0 3A E4 EE A3 34 F3 96 F3 C4 E4 + FF FF FF FF FF FF 07 0E 15 1C 23 2A 31 38 38 31 2A 23 1C 15 0E 07 03 07 0A 0E 11 15 18 1C + 1C 18 15 11 0E 0A 07 03 23 00 6E A3 44 99 23 10 C4 22 23 F7 AC AD BA 18 B8 2A F0 AB AF BE + 00 B8 41 FE 68 A8 F0 A9 69 EB 3E A9 FF 37 53 0F 17 AB 69 EB 48 F9 39 ED 4D FC AD FF AB FE + 17 53 0F AE 96 37 EA 37 23 18 AA FF 03 FF C6 6A E6 6A AB AF C4 37 04 1B 23 F7 AC AD BA 10 + B8 2A F0 AB AF BE 00 B8 41 FE 68 A8 F0 A9 69 EB 80 A9 FF 37 53 0F 17 AB 69 EB 8A F9 39 ED + 8F FC AD FF AB FE 17 53 0F AE 96 79 EA 79 23 10 AA B8 2B F0 32 70 04 1B E7 D7 C9 BC B0 A4 + 98 8D 84 7A 71 6A 60 59 52 4B 45 3E 39 34 2F 2A 25 21 1D 19 16 13 10 0C 0A 07 FA 03 CE AB + 23 A8 6B A3 AD AC 23 A0 3A B8 2B F0 12 70 32 70 C4 2E FA B8 2A A0 04 1B A3 34 F3 96 E4 E4 + CE E3 6D AD 1C FC 03 10 C6 F7 FC C4 EB FD 03 67 96 FE E4 D5 E4 FC C5 B8 41 FE 68 A8 F0 47 + 69 E6 68 39 ED 0C FC AD FE 17 53 0F AE 96 00 EB 00 FA AB B6 9F FC 6F AC AD B8 3F F0 96 7C + D5 CF FF C5 96 00 B8 33 F0 D5 AF C5 B8 3E F0 96 8E F9 D5 6D C5 A9 D5 6A C6 6C 76 00 D5 FC + 6B AC C5 AC AD D5 C9 F9 C5 96 00 B8 3D F0 D5 A9 C5 F9 D5 6E C5 A9 D5 68 C5 C6 79 B8 2C F0 + AC AD D5 AC E4 00 23 00 E4 0B C5 B8 2D F0 D5 6E C5 A0 A9 D5 6A 96 42 C5 04 1B 18 F0 96 87 + FC D5 6F F6 31 E4 00 FC D5 6F E6 31 E4 00 B8 31 F0 6F AF B8 32 60 C6 79 E4 37 B8 34 60 E4 + A3 FC 76 9A 6F AC AD B8 35 F0 07 A0 96 00 18 F0 C8 A0 76 B5 B5 E4 00 A5 F9 D5 6D C5 A9 D5 + 6A C6 6C C5 B8 37 F0 07 A0 96 00 18 F0 C8 A0 E4 42 98 A3 34 F3 96 CE C4 EB B8 20 23 00 AC + AD A0 F0 6C 96 FC 18 F8 53 7F C6 EE 1D FD 37 17 AC FD E4 DB B8 20 B0 00 18 F8 53 7F C6 FA + E4 F0 04 15 15 00 E4 FC + + + + + + + + + + 09 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 10 00 + 00 00 3C 08 00 01 00 00 + 00 00 3C 09 00 01 03 03 + 00 00 3C 0A 00 02 00 00 + 00 00 3B C0 00 27 00 12 + + + + + + + + 20210817165502 + diff --git a/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2) [bl].mra b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2) [bl].mra new file mode 100644 index 00000000..7c94d4f9 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2) [bl].mra @@ -0,0 +1,78 @@ + + Finalizer: Super Transformation (bootleg) + World + no + yes + Set 2 + + + + 1986 + Konami + Shooter - Vertical + + finalizrb + finalizr + 0224 + Finalizr + + + 15kHz + no + no + + 2 (alternating) + 8-way + + 3 + + + + + + + + + + + + + + + + + 0F + + + + + + + + + + + + + + + + + + + + 09 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 10 00 + 00 00 3C 08 00 01 00 00 + 00 00 3C 09 00 01 02 02 + 00 00 3C 0A 00 02 00 00 + 00 00 3B C0 00 27 00 12 + + + + + + + + 20210817165502 + diff --git a/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2).mra b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2).mra new file mode 100644 index 00000000..5790dc64 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/meta/Finalizer - Super Transformation (Set 2).mra @@ -0,0 +1,150 @@ + + Finalizer: Super Transformation (Set 2) + World + no + no + Set 2 + + + + 1985 + Konami + Shooter - Vertical + + finalizra + finalizr + 0224 + Finalizr + + + 15kHz + no + no + + 2 (alternating) + 8-way + + 3 + + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + 04 09 00 04 1E 00 00 04 E3 55 23 00 39 23 00 3A 23 80 3A 04 F3 BA 00 05 FA 04 C9 00 04 1B + C5 80 AA 23 00 3A 23 80 3A B8 08 23 18 A0 B8 09 23 00 A0 23 09 D7 04 36 93 8D 8F 91 93 95 + 97 97 97 97 97 97 97 97 97 97 97 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 9B 9D 9F + A1 A3 A5 A7 A9 AB AD AF B1 B3 B5 B7 B9 BB BD BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF + BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF BF C1 C3 C5 C7 24 1C 84 B6 84 C1 84 CB A4 + AD C4 DE 84 DD A4 04 24 84 A4 7E 24 26 84 00 24 55 44 68 A4 4D A4 B1 A4 08 A4 EA A4 DF A4 + E6 A4 45 84 D8 24 98 C4 6C C4 2A C4 C8 24 9C A4 EE 24 A0 44 EF B8 24 F0 C6 DA 18 F0 96 DC + FA 03 AA F6 1B 03 8D B3 24 00 24 DB 42 6A 62 58 A3 93 42 6E 62 53 3F A3 AB 93 42 6A 62 53 + 3F A3 93 23 00 AD AC A3 34 F3 96 F7 24 F8 FF FF FA C6 22 B8 27 F0 6A A0 18 F0 17 53 03 C6 + 12 A0 04 1B C8 F0 03 01 96 24 B8 24 B0 01 23 A0 3A 23 00 39 04 1B E4 FC B8 20 F0 AF 18 F0 + AB 23 06 AC AD A8 BE 00 BA 02 B9 02 54 66 FC 03 10 AC AD EA 38 BA 02 F8 03 01 A8 AC AD E9 + 38 B9 02 FF 17 AF 6B C6 22 24 38 23 12 AC AD A8 B9 20 F1 AF 19 F1 AB BE 00 BA 02 B9 02 54 + 66 FC 03 10 AC AD EA 67 BA 02 F8 03 02 A8 AC AD E9 67 B9 02 FF 17 AF 6B C6 22 24 67 B8 20 + F0 AF 18 F0 AB 23 06 AC AD A8 BE 00 BA 01 B9 02 44 D2 B8 22 84 C4 B8 22 84 CF C5 BE 00 B8 + 2C F0 AC AD D5 AC C5 18 F0 A9 18 F0 AA AB 18 F0 D5 AB C5 18 F0 AF B8 33 F0 D5 AF C5 B8 39 + F0 D5 AD C5 18 F0 D5 AA C5 18 F0 D5 AE C5 18 F0 D5 A8 C5 18 F0 D5 A9 E4 00 B8 26 F0 B9 2C + 69 A9 FA A1 F0 17 A0 03 EB C6 ED 04 1B B8 25 B0 00 04 1B 6D AD 1C FC 93 A3 34 F3 96 F8 44 + F8 FF 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E 40 42 44 46 48 4A 4C 4E 2E 30 50 52 54 2C 2E 30 + 56 50 58 36 5A 5C 5E 60 40 42 62 64 44 A8 44 AE 44 B2 44 B6 44 BA 44 BE 44 C2 44 C6 84 1E + 84 3B 84 48 84 52 84 5C 84 66 84 70 84 7A 44 CA 44 CE 84 04 A4 00 84 0C 84 10 84 08 C4 20 + C4 26 84 14 84 84 84 8E 84 98 84 A2 84 AC FF B3 B8 22 F0 AF 18 F0 AB 23 20 AC AD A8 BE 00 + BA 02 B9 02 54 66 FC 03 10 AC AD EA 7A BA 02 F8 03 04 A8 AC AD E9 7A B9 02 FF 17 AF 6B C6 + 97 44 7A 04 1B 39 ED 9A FC AD FE 17 53 0F AE 96 A6 93 44 66 23 10 6E E3 44 99 23 20 44 AA + 23 30 44 AA 23 40 44 AA 23 50 44 AA 23 60 44 AA 23 70 44 AA 23 80 44 AA 23 90 44 AA 23 A0 + 44 AA 54 66 FC 03 10 AC AD EA D2 BA 01 F8 03 00 A8 AC AD E9 D2 B9 02 FF 17 AF 6B C6 97 44 + D2 B8 25 B0 01 18 B0 00 04 1B A3 34 F3 96 F8 84 F2 FF 70 70 70 70 00 54 00 00 00 00 00 00 + 00 00 00 00 80 80 80 80 00 60 00 00 00 00 00 00 00 00 00 00 0E 1C 2A 38 46 54 62 70 70 62 + 54 46 38 2A 1C 0E 0C 18 24 30 3C 48 54 60 60 54 48 3C 30 24 18 0C 0A 14 1E 28 32 3C 46 50 + 50 46 3C 32 28 1E 14 0A 08 10 18 20 28 30 38 40 40 38 30 28 20 18 10 08 06 0C 12 18 1E 24 + 2A 30 30 2A 24 1E 18 12 0C 06 04 08 0C 10 14 18 1C 20 20 1C 18 14 10 0C 08 04 02 04 06 08 + 0A 0C 0E 10 10 0E 0C 0A 08 06 04 02 AA AA AA AA 00 80 00 00 00 00 00 00 00 00 00 00 12 25 + 38 4A 5D 70 82 95 95 82 70 5D 4A 38 25 12 10 20 30 40 50 60 70 80 80 70 60 50 40 30 20 10 + 0D 1A 28 35 42 50 5D 6A 6A 5D 50 42 35 28 1A 0D 05 0A 10 15 1A 20 25 2A 2A 25 20 1A 15 10 + 0A 05 02 05 08 0A 0D 10 12 15 15 12 10 0D 0A 08 05 02 FF FF FF FF FF FF FF FF FF FF FF FF + FF FF 10 57 23 0A 24 57 23 B0 44 AA 23 00 44 AA 23 D0 44 AA 23 E0 44 AA 14 E4 FB 53 7F AB + 23 00 84 43 14 E4 FB 53 7F AB 23 2B 6E A3 6B 44 99 40 40 40 40 00 20 00 00 00 00 00 00 00 + 00 00 00 14 E4 FB 53 7F AB 23 20 6E E3 6B 44 99 14 E4 FB 53 7F AB 23 30 84 43 14 E4 FB 53 + 3F AB 23 40 84 43 14 E4 FB 53 1F AB 23 50 84 43 14 E4 FB 53 0F AB 23 60 84 43 14 E4 FB 53 + 07 AB 23 70 84 43 14 E4 FB 53 03 AB 23 80 84 43 14 E4 FB 53 7F AB 23 A0 84 43 14 E4 FB 53 + 7F AB 23 B0 84 43 14 E4 FB 53 3F AB 23 C0 84 43 14 E4 FB 53 07 AB 23 D0 84 43 14 E4 FB 53 + 03 AB 23 E0 84 43 85 95 B8 20 23 18 A0 23 E0 84 D4 85 B8 20 23 00 A0 23 F8 84 D4 A5 B5 B8 + 20 23 10 A0 23 E8 18 A0 04 1B A5 B8 22 84 BA FA 53 0F AB B8 29 F0 AC B9 41 69 A9 FB A1 1C + FC 53 0F A0 04 1B A3 34 F3 96 F2 A4 F3 FF FF FF FF FF FF FF 23 C0 44 AA BF FF A4 0A BF 7F + 23 01 AC AD AE B9 04 BA 70 BB 70 14 EC 5F 39 ED 19 FC 17 53 07 C6 38 AC AD EE 15 F9 AE EB + 15 FA AB FF 77 53 7F AF C6 43 03 C1 C6 3C A4 15 23 04 A4 21 F9 03 10 A9 AE A4 15 04 1B BF + 08 D5 BB F0 C5 A4 53 BF 20 D5 BB D8 C5 BC 06 BD 06 BE 00 BA 02 B9 02 B8 05 54 66 FC 03 10 + AC AD EA 5F BA 03 F8 03 01 A8 AC AD E9 5F B9 01 FF 17 AF D5 6B C5 C6 43 A4 5F B8 20 F0 AF + 18 F0 AB 23 06 AC A8 AD BE 00 BA 02 B9 02 54 66 FC 03 02 AC AD EA 90 BA 02 F8 03 00 A8 AC + AD E9 90 B9 02 FF 17 AF 6B C6 43 A4 90 BF 7F A4 B3 BF 3F 23 01 AC AD AE BA 70 BB 70 14 EC + 5F 39 ED C0 FC 17 53 03 C6 DB AC AD EE BC BE 04 EB BC FA AB FF 77 53 7F AF C6 43 A4 BC 23 + 01 A4 C8 23 00 B8 2B A0 04 1B 23 01 A4 E1 23 02 A4 E1 23 A0 3A E4 EE A3 34 F3 96 F3 C4 E4 + FF FF FF FF FF FF 07 0E 15 1C 23 2A 31 38 38 31 2A 23 1C 15 0E 07 03 07 0A 0E 11 15 18 1C + 1C 18 15 11 0E 0A 07 03 23 00 6E A3 44 99 23 10 C4 22 23 F7 AC AD BA 18 B8 2A F0 AB AF BE + 00 B8 41 FE 68 A8 F0 A9 69 EB 3E A9 FF 37 53 0F 17 AB 69 EB 48 F9 39 ED 4D FC AD FF AB FE + 17 53 0F AE 96 37 EA 37 23 18 AA FF 03 FF C6 6A E6 6A AB AF C4 37 04 1B 23 F7 AC AD BA 10 + B8 2A F0 AB AF BE 00 B8 41 FE 68 A8 F0 A9 69 EB 80 A9 FF 37 53 0F 17 AB 69 EB 8A F9 39 ED + 8F FC AD FF AB FE 17 53 0F AE 96 79 EA 79 23 10 AA B8 2B F0 32 70 04 1B E7 D7 C9 BC B0 A4 + 98 8D 84 7A 71 6A 60 59 52 4B 45 3E 39 34 2F 2A 25 21 1D 19 16 13 10 0C 0A 07 FA 03 CE AB + 23 A8 6B A3 AD AC 23 A0 3A B8 2B F0 12 70 32 70 C4 2E FA B8 2A A0 04 1B A3 34 F3 96 E4 E4 + CE E3 6D AD 1C FC 03 10 C6 F7 FC C4 EB FD 03 67 96 FE E4 D5 E4 FC C5 B8 41 FE 68 A8 F0 47 + 69 E6 68 39 ED 0C FC AD FE 17 53 0F AE 96 00 EB 00 FA AB B6 9F FC 6F AC AD B8 3F F0 96 7C + D5 CF FF C5 96 00 B8 33 F0 D5 AF C5 B8 3E F0 96 8E F9 D5 6D C5 A9 D5 6A C6 6C 76 00 D5 FC + 6B AC C5 AC AD D5 C9 F9 C5 96 00 B8 3D F0 D5 A9 C5 F9 D5 6E C5 A9 D5 68 C5 C6 79 B8 2C F0 + AC AD D5 AC E4 00 23 00 E4 0B C5 B8 2D F0 D5 6E C5 A0 A9 D5 6A 96 42 C5 04 1B 18 F0 96 87 + FC D5 6F F6 31 E4 00 FC D5 6F E6 31 E4 00 B8 31 F0 6F AF B8 32 60 C6 79 E4 37 B8 34 60 E4 + A3 FC 76 9A 6F AC AD B8 35 F0 07 A0 96 00 18 F0 C8 A0 76 B5 B5 E4 00 A5 F9 D5 6D C5 A9 D5 + 6A C6 6C C5 B8 37 F0 07 A0 96 00 18 F0 C8 A0 E4 42 98 A3 34 F3 96 CE C4 EB B8 20 23 00 AC + AD A0 F0 6C 96 FC 18 F8 53 7F C6 EE 1D FD 37 17 AC FD E4 DB B8 20 B0 00 18 F8 53 7F C6 FA + E4 F0 04 15 15 00 E4 FC + + + + + + + + + + 09 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 10 00 + 00 00 3C 08 00 01 00 00 + 00 00 3C 09 00 01 02 02 + 00 00 3C 0A 00 02 00 00 + 00 00 3B C0 00 27 00 12 + + + + + + + + 20210817165502 + diff --git a/Arcade_MiST/Konami Finalizer/rtl/Finalizer.sv b/Arcade_MiST/Konami Finalizer/rtl/Finalizer.sv new file mode 100644 index 00000000..fd8b84ee --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/Finalizer.sv @@ -0,0 +1,572 @@ +//============================================================================ +// +// Finalizer PCB model +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Module declaration, I/O ports +module Finalizer +( + input reset, + input clk_49m, //Actual frequency: 49.152MHz + input [1:0] coin, + input [1:0] btn_start, //1 = Player 2, 0 = Player 1 + input [3:0] p1_joystick, p2_joystick, //3 = down, 2 = up, 1 = right, 0 = left + input [1:0] p1_buttons, p2_buttons, //2 buttons per player + input btn_service, + input [23:0] dipsw, + + //The following flag is used to reconfigure the clock division applied to the Konami SND01 sound chip + //as while the original is clocked at 6.144MHz, bootleg boards clock this chip (replaced by a standard + //NEC uPD8749 MCU) at 9.216MHz + input [1:0] is_bootleg, + + //Screen centering (alters HSync and VSync timing in the Konami 005885 to reposition the video output) + input [3:0] h_center, v_center, + + output video_hsync, video_vsync, video_csync, + output video_vblank, video_hblank, + output [3:0] video_r, video_g, video_b, + output signed [15:0] sound, + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, + + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_read, + input hs_access_write, + + //SDRAM signals + output reg [15:0] main_cpu_rom_addr, + input [7:0] main_cpu_rom_do, + output reg [15:1] char1_rom_addr, + input [15:0] char1_rom_do, + output sp1_req, + input sp1_ack, + output [16:1] sp1_rom_addr, + input [15:0] sp1_rom_do +); + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i, ep6_cs_i, ep7_cs_i, ep8_cs_i, ep9_cs_i, snd01_cs_i; +wire prom1_cs_i, prom2_cs_i, prom3_cs_i, prom4_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .ep6_cs(ep6_cs_i), + .ep7_cs(ep7_cs_i), + .ep8_cs(ep8_cs_i), + .ep9_cs(ep9_cs_i), + .snd01_cs(snd01_cs_i), + .prom1_cs(prom1_cs_i), + .prom2_cs(prom2_cs_i), + .prom3_cs(prom3_cs_i), + .prom4_cs(prom4_cs_i) +); + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6.144MHz, 3.072MHz and 1.576MHz clock enables (clock division is normally handled inside the Konami 005885) +//Also generate an extra clock enable for DC offset removal in the sound section +reg [6:0] div = 7'd0; +always_ff @(posedge clk_49m) begin + div <= div + 7'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div[3:0]; +wire cen_1m5 = !div[4:0]; +wire dcrm_cen = !div; + +//Phase generator for KONAMI-1 (taken from MiSTer Vectrex core) +//Normally handled internally on the Konami 005885 +reg k1_E = 0; +reg k1_Q = 0; +always_ff @(posedge clk_49m) begin + reg [1:0] clk_phase = 0; + k1_E <= 0; + k1_Q <= 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b01: k1_E <= 1; + 2'b10: k1_Q <= 1; + endcase + end +end + +//Use Jotego's fractional clock divider to generate a 9.216MHz clock enable for the Konami SND01 custom chip (to be used by bootlegs +//only) +wire cen_9m; +jtframe_frac_cen #(2) snd01_cen +( + .clk(clk_49m), + .n(10'd48), + .m(10'd256), + .cen({1'bZ, cen_9m}) +); + +//Select whether to clock the SND01 at 6.144MHz or 9.216MHz depending on whether a bootleg ROM set is loaded +wire cen_snd01 = (is_bootleg == 2'b11) ? cen_9m : cen_6m; + +//------------------------------------------------------------ CPUs ------------------------------------------------------------// + +//Main CPU (KONAMI-1 custom encrypted MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by +//Sorgelig with a wrapper to decrypt XOR/XNOR-encrypted opcodes and a further modification to Greg's MC6809E to directly +//accept the opcodes) +wire k1_rw; +wire [15:0] k1_A; +wire [7:0] k1_Din, k1_Dout; +KONAMI1 u13A +( + .CLK(clk_49m), + .fallE_en(k1_E), + .fallQ_en(k1_Q), + .D(k1_Din), + .DOut(k1_Dout), + .ADDR(k1_A), + .RnW(k1_rw), + .nIRQ(k1_irq), + .nFIRQ(k1_firq), + .nNMI(k1_nmi), + .nHALT(pause), + .nRESET(reset) +); +//Address decoding for data inputs to KONAMI-1 +wire cs_k005885 = (k1_A[15:14] == 2'b00); +wire cs_dip3 = ~nioc & (k1_A[4:3] == 2'b00) & k1_rw; +wire cs_dip2 = ~nioc & (k1_A[4:3] == 2'b01) & k1_rw; +wire cs_controls_dip1 = ~nioc & (k1_A[4:3] == 2'b10) & k1_rw; +wire cs_sn76489 = ~nioc & (k1_A[4:0] == 5'b11010) & ~k1_rw; +wire cs_sn76489_latch = ~nioc & (k1_A[4:0] == 5'b11011) & ~k1_rw; +wire cs_snd01_irq = ~nioc & (k1_A[4:0] == 5'b11100) & ~k1_rw; +wire cs_snd01_latch = ~nioc & (k1_A[4:0] == 5'b11101) & ~k1_rw; +wire cs_rom1 = (k1_A[15:14] == 2'b01 & k1_rw); +wire cs_rom2 = (k1_A[15:14] == 2'b10 & k1_rw); +wire cs_rom3 = (k1_A[15:14] == 2'b11 & k1_rw); +//Multiplex data inputs to KONAMI-1 +assign k1_Din = (cs_k005885 & nioc) ? k005885_Dout: + cs_dip3 ? {4'hF, dipsw[19:16]}: + cs_dip2 ? dipsw[15:8]: + cs_controls_dip1 ? controls_dip1: + cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + cs_rom3 ? eprom3_D: + 8'hFF; + +//Game ROMs +`ifdef EXT_ROM +always_ff @(posedge clk_49m) + if (|k1_A[15:14] & k1_rw) + main_cpu_rom_addr <= k1_A[15:0] - 16'h4000; + +wire [7:0] eprom1_D = main_cpu_rom_do; +wire [7:0] eprom2_D = main_cpu_rom_do; +wire [7:0] eprom3_D = main_cpu_rom_do; +`else +wire [7:0] eprom1_D, eprom2_D, eprom3_D; +eprom_1 u9C +( + .ADDR(k1_A[13:0]), + .CLK(clk_49m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +eprom_2 u12C +( + .ADDR(k1_A[13:0]), + .CLK(clk_49m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +eprom_3 u13C +( + .ADDR(k1_A[13:0]), + .CLK(clk_49m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +`endif +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Multiplex player inputs and DIP switch bank 1 (Finalizer also expects to receive a VBlank on bit 7 along with the start buttons, +//service credit and coin inputs - invert as the game expects an active low VBlank here) +wire [7:0] controls_dip1 = (k1_A[1:0] == 2'b00) ? {~video_vblank, 2'b11, btn_start, btn_service, coin}: + (k1_A[1:0] == 2'b01) ? {2'b11, p1_buttons, p1_joystick}: + (k1_A[1:0] == 2'b10) ? {2'b11, p2_buttons, p2_joystick}: + (k1_A[1:0] == 2'b11) ? dipsw[7:0]: + 8'hFF; + +//--------------------------------------------------- Video timing & graphics --------------------------------------------------// + +//Konami 005885 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Finalizer's critical +//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites +wire [15:0] tiles_A, sprites_A; +wire [7:0] k005885_Dout, tilemap_lut_A, sprite_lut_A; +wire [4:0] color_A; +wire k1_firq, k1_irq, k1_nmi, nioc; +k005885 u11E +( + .CK49(clk_49m), + .NRD(~k1_rw), + .A(k1_A[13:0]), + .DBi(k1_Dout), + .DBo(k005885_Dout), + .R(tiles_A), + .RDU(tiles_D[15:8]), + .RDL(tiles_D[7:0]), + .S(sprites_A), + .S_req(sp1_req), + .S_ack(sp1_ack), + .SDU(sprites_D[15:8]), + .SDL(sprites_D[7:0]), + .VCF(tilemap_lut_A[7:4]), + .VCB(tilemap_lut_A[3:0]), + .VCD(tilemap_lut_D), + .OCF(sprite_lut_A[7:4]), + .OCB(sprite_lut_A[3:0]), + .OCD(sprite_lut_D), + .COL(color_A), + .NEXR(reset), + .NXCS(~cs_k005885), + .NCSY(video_csync), + .NHSY(video_hsync), + .NVSY(video_vsync), + .HBLK(video_hblank), + .VBLK(video_vblank), + .NFIR(k1_firq), + .NIRQ(k1_irq), + .NNMI(k1_nmi), + .NIOC(nioc), + .HCTR(h_center), + .VCTR(v_center) +`ifdef MISTER_HISCORE + , + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_read(hs_access_read), + .hs_access_write(hs_access_write) +`endif +); + +//Graphics ROMs +//Access tilemap ROMs for both the sprite and tilemap sections of the 005885 simultaneously as some of Finalizer's sprites fetch +//data from tilemap ROMs rather than sprite ROMs +//always_ff @(posedge clk_49m) +assign char1_rom_addr = tiles_A[13:0]; +assign sp1_rom_addr = {sprites_A[15], ~sprites_A[15] & sprites_A[14], sprites_A[13:0]}; +`ifdef EXT_ROM +wire [7:0] eprom4t_D = char1_rom_do[15:8]; +wire [7:0] eprom4s_D = sp1_rom_do[15:8]; +wire [7:0] eprom5t_D = char1_rom_do[7:0]; +wire [7:0] eprom5s_D = sp1_rom_do[7:0]; +wire [7:0] eprom6_D = sp1_rom_do[15:8]; +wire [7:0] eprom7_D = sp1_rom_do[7:0]; +wire [7:0] eprom8_D = sp1_rom_do[15:8]; +wire [7:0] eprom9_D = sp1_rom_do[7:0]; +`else +wire [7:0] eprom4t_D, eprom4s_D, eprom5t_D, eprom5s_D, eprom6_D, eprom7_D, eprom8_D, eprom9_D; +eprom_4 u5E +( + .ADDR_A(sprites_A[13:0]), + .CLK_A(~clk_49m), + .DATAOUT_A(eprom4s_D), + .ADDR_B(ep4_cs_i ? ioctl_addr : tiles_A[13:0]), + .CLK_B(clk_49m), + .DATA_IN(ioctl_data), + .DATAOUT_B(eprom4t_D), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); +eprom_5 u5F +( + .ADDR_A(sprites_A[13:0]), + .CLK_A(~clk_49m), + .DATAOUT_A(eprom5s_D), + .ADDR_B(ep5_cs_i ? ioctl_addr : tiles_A[13:0]), + .CLK_B(clk_49m), + .DATA_IN(ioctl_data), + .DATAOUT_B(eprom5t_D), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); +eprom_6 u6E +( + .ADDR(sprites_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom6_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep6_cs_i), + .WR(ioctl_wr) +); +eprom_7 u6F +( + .ADDR(sprites_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom7_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep7_cs_i), + .WR(ioctl_wr) +); +eprom_8 u7E +( + .ADDR(sprites_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom8_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep8_cs_i), + .WR(ioctl_wr) +); +eprom_9 u7F +( + .ADDR(sprites_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom9_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep9_cs_i), + .WR(ioctl_wr) +); +`endif +//Combine graphics ROM data outputs to 16 bits and multiplex sprite data +reg [15:0] tiles_D, sprites_D; +always @(*) begin + tiles_D <= {eprom4t_D, eprom5t_D}; + case(sprites_A[15:14]) + 2'b00: sprites_D <= {eprom4s_D, eprom5s_D}; + 2'b01: sprites_D <= {eprom6_D, eprom7_D}; + 2'b10: sprites_D <= {eprom8_D, eprom9_D}; + 2'b11: sprites_D <= {eprom8_D, eprom9_D}; + endcase +end + +//Tilemap LUT PROM +wire [3:0] tilemap_lut_D; +prom_1 u11F +( + .ADDR(tilemap_lut_A), + .CLK(clk_49m), + .DATA(tilemap_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom1_cs_i), + .WR(ioctl_wr) +); + +//Sprite LUT PROM +wire [3:0] sprite_lut_D; +prom_2 u10F +( + .ADDR(sprite_lut_A), + .CLK(clk_49m), + .DATA(sprite_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom2_cs_i), + .WR(ioctl_wr) +); + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Generate chip enable for SN76489 +wire n_sn76489_ce = (~cs_sn76489 & sn76489_ready); + +//Latch data from KONAMI-1 to Konami SND01 +reg [7:0] snd01_Din = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && cs_snd01_latch) + snd01_Din <= k1_Dout; +end + +//Latch data from KONAMI-1 to SN76489 +reg [7:0] sn76489_D = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && cs_sn76489_latch) + sn76489_D <= k1_Dout; +end + +//Sound chip 1 (Texas Instruments SN76489 - uses Arnim Laeuger's SN76489 implementation with bugfixes) +wire [7:0] sn76489_raw; +wire sn76489_ready; +sn76489_top u7C +( + .clock_i(clk_49m), + .clock_en_i(cen_1m5), + .res_n_i(reset), + .ce_n_i(n_sn76489_ce), + .we_n_i(sn76489_ready), + .ready_o(sn76489_ready), + .d_i(sn76489_D), + .aout_o(sn76489_raw) +); + +//Sound chip 2 (Konami SND01, a rebadged NEC uPD8749 MCU - uses a modified version of the t8049_notri variant of T48) +wire [7:0] snd01_raw; +wire [7:0] snd01_port2; +wire snd01_ale, n_snd01_psen, n_snd01_rd, n_snd01_irq_clr, snd01_timer_out; +t8049_notri u8A +( + .xtal_i(clk_49m), + .xtal_en_i(cen_snd01), + .reset_n_i(reset), + .t0_o(snd01_timer_out), + .int_n_i(n_snd01_irq), + .ea_i(0), + .db_i(snd01_Din), + .t1_i(snd01_timer_in), + .p2_o(snd01_port2), + .p1_o(snd01_raw), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(snd01_cs_i), + .WR(ioctl_wr) +); +assign n_snd01_irq_clr = snd01_port2[7]; + +//Divide SND01 timer 0 output by 16 for the bootleg MCU timer and connect to the input of timer 1, otherwise pull this input low +reg [3:0] snd01_timer = 4'd0; +reg old_timer; +always_ff @(posedge clk_49m) begin + old_timer <= snd01_timer_out; + if(!old_timer && snd01_timer_out) + snd01_timer <= snd01_timer + 4'd1; +end +wire snd01_timer_in = snd01_timer[3]; + +//Generate SND01 IRQ +reg n_snd01_irq = 1; +always_ff @(posedge clk_49m) begin + if(!n_snd01_irq_clr) + n_snd01_irq <= 1; + else if(cen_3m && cs_snd01_irq) + n_snd01_irq <= 0; +end + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Finalzer's video output consists of two color LUT PROMs providing 12-bit RGB, 4 bits per color +prom_3 u2F +( + .ADDR(color_A), + .CLK(clk_49m), + .DATA({video_g, video_r}), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom3_cs_i), + .WR(ioctl_wr) +); +prom_4 u3F +( + .ADDR(color_A), + .CLK(clk_49m), + .DATA({4'bZZZZ, video_b}), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(prom4_cs_i), + .WR(ioctl_wr) +); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Remove DC offset from SN76489 and SND01 and apply gain to both +wire signed [15:0] sn76489_gain, snd01_gain; +jt49_dcrm2 #(16) dcrm_sn76489 +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({1'd0, sn76489_raw, 7'd0}), + .dout(sn76489_gain) +); +jt49_dcrm2 #(16) dcrm_snd01 +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, snd01_raw, 5'd0}), + .dout(snd01_gain) +); + +//Finalizer - Super Transformation uses a 3.386KHz low-pass filter for its SN76489 - apply this filtering here +wire signed [15:0] sn76489_lpf; +finalizer_psg_lpf psg_lpf +( + .clk(clk_49m), + .reset(~reset), + .in(sn76489_gain), + .out(sn76489_lpf) +); + +//Mix the low-pass filtered output of the SN76489 with the SND01 and apply an extra low-pass filter on the mixed output to minimze +//aliasing +wire signed [15:0] sound_mix = sn76489_lpf + snd01_gain; +wire signed [15:0] sound_mix_aa; +finalizer_lpf lpf +( + .clk(clk_49m), + .reset(~reset), + .in(sound_mix), + .out(sound_mix_aa) +); + +//Output the anti-aliased audio signal (mute when game is paused) +assign sound = pause ? sound_mix_aa : 16'd0; + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/Finalizer_MiST.sv b/Arcade_MiST/Konami Finalizer/rtl/Finalizer_MiST.sv new file mode 100644 index 00000000..c6efaad0 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/Finalizer_MiST.sv @@ -0,0 +1,309 @@ +module Finalizer_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "FINALIZR;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "O1,Pause,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire pause = status[1]; + +wire [1:0] orientation = 2'b11; +wire [23:0] dip_sw = ~status[31:8]; + +wire [1:0] is_bootleg = core_mod[1:0]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_98; +assign SDRAM_CKE = 1; + +wire clock_98, clock_49, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_98), + .c1(clock_49),//49.152MHz + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_49 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + +wire [15:0] main_rom_addr; +wire [15:0] main_rom_do; +wire [15:1] ch1_addr; +wire [15:0] ch1_do; +wire sp1_req, sp1_ack; +wire [16:1] sp1_addr; +wire [15:0] sp1_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 16'hC000; + +reg port1_req, port2_req; +sdram #(98) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_98 ), + + // port1 for CPUs + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'h0000 : main_rom_addr[15:1] ), + .cpu1_q ( main_rom_do ), + + // port2 for graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( {bg_ioctl_addr[23:15], bg_ioctl_addr[13:0]} ), // merge gfx roms to 16-bit wide words + .port2_ds ( {~bg_ioctl_addr[14], bg_ioctl_addr[14]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ), + .ch1_q ( ch1_do ), + .sp1_req ( sp1_req ), + .sp1_ack ( sp1_ack ), + .sp1_addr ( ioctl_downl ? 16'hffff : sp1_addr ), + .sp1_q ( sp1_do ) +); + +// ROM download controller +always @(posedge clock_49) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_49) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +//Instantiate Finalizer top-level module +Finalizer Finalizer_inst +( + .reset(~reset), // input reset + + .clk_49m(clock_49), // input clk_49m + + .coin({~m_coin2, ~m_coin1}), // input coin + .btn_service(~service), // input btn_service + + .btn_start({~m_two_players, ~m_one_player}), // input [1:0] btn_start + + .p1_joystick({~m_down, ~m_up, ~m_right, ~m_left}), + .p2_joystick({~m_down2, ~m_up2, ~m_right2, ~m_left2}), + .p1_buttons({~m_fireB, ~m_fireA}), + .p2_buttons({~m_fire2B, ~m_fire2A}), + + .dipsw(dip_sw), // input [24:0] dipsw + + .is_bootleg(is_bootleg), // Flag to reconfigure core for differences + // present on bootleg Finalizer PCBs + + .sound(audio), // output [15:0] sound + + .h_center(), // Screen centering + .v_center(), + + .video_hsync(hs), // output video_hsync + .video_vsync(vs), // output video_vsync + .video_vblank(vblank), // output video_vblank + .video_hblank(hblank), // output video_hblank + + .video_r(r), // output [4:0] video_r + .video_g(g), // output [4:0] video_g + .video_b(b), // output [4:0] video_b + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(~pause), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_read(hs_access_read), + .hs_access_write(hs_access_write), + + .main_cpu_rom_addr(main_rom_addr), + .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]), + .char1_rom_addr(ch1_addr), + .char1_rom_do(ch1_do), + .sp1_req(sp1_req), + .sp1_ack(sp1_ack), + .sp1_rom_addr(sp1_addr), + .sp1_rom_do(sp1_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +wire audio_out; +assign AUDIO_L = audio_out; +assign AUDIO_R = audio_out; + +dac #(.C_bits(16))dac( + .clk_i(clock_49), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(audio_out) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_49 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/KONAMI1.sv b/Arcade_MiST/Konami Finalizer/rtl/KONAMI1.sv new file mode 100644 index 00000000..9126e795 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/KONAMI1.sv @@ -0,0 +1,79 @@ +//============================================================================ +// +// SystemVerilog implementation of the KONAMI-1 custom chip, a custom MC6809E +// variant with XOR/XNOR encryption +// Implements MC6809E core by Greg Miller (synchronous version modified by +// Sorgelig with further modifications to allow direct injection of opcodes) +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +module KONAMI1 +( + input CLK, + input fallE_en, + input fallQ_en, + + input [7:0] D, + output [7:0] DOut, + output [15:0] ADDR, + output RnW, + output BS, + output BA, + input nIRQ, + input nFIRQ, + input nNMI, + output AVMA, + output BUSY, + output LIC, + input nHALT, + input nRESET +); + +//Decrypt XOR/XNOR encrypted opcode +wire [7:0] opcode = D ^ {ADDR[1], 1'b0, ~ADDR[1], 1'b0, ADDR[3], 1'b0, ~ADDR[3], 1'b0}; + +//Passthrough to modified MC6809is core with direct opcode injection and IS_KONAMI1 parameter set +//to TRUE +mc6809is #(.IS_KONAMI1("TRUE")) cpucore +( + .CLK(CLK), + .fallE_en(fallE_en), + .fallQ_en(fallQ_en), + .OP(opcode), + .nHALT(nHALT), + .nRESET(nRESET), + .D(D), + .DOut(DOut), + .ADDR(ADDR), + .RnW(RnW), + .BS(BS), + .BA(BA), + .nIRQ(nIRQ), + .nFIRQ(nFIRQ), + .nNMI(nNMI), + .AVMA(AVMA), + .BUSY(BUSY), + .LIC(LIC), + .nDMABREQ(1) +); + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/audio_iir_filter.v b/Arcade_MiST/Konami Finalizer/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/rtl/build_id.tcl b/Arcade_MiST/Konami Finalizer/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/rtl/dpram_dc.vhd b/Arcade_MiST/Konami Finalizer/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Konami Finalizer/rtl/finalizer_lpf.v b/Arcade_MiST/Konami Finalizer/rtl/finalizer_lpf.v new file mode 100644 index 00000000..caafa3dd --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/finalizer_lpf.v @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to remove aliasing on Finalizer - Super Transformation. + +module finalizer_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 128; //Sample at 49.152MHz/128 = 384000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.045425748, 0.045425748 + //1.0000000, -0.90914850 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd18211; + B1 = 18'd7278; + B2 = 18'd7278; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/finalizer_psg_lpf.sv b/Arcade_MiST/Konami Finalizer/rtl/finalizer_psg_lpf.sv new file mode 100644 index 00000000..b688d9d8 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/finalizer_psg_lpf.sv @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to low-pass filter the SN76489 on Finalizer - Super Transformation. + +module finalizer_psg_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 128; //Sample at 49.152MHz/128 = 384000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.052545856, 0.052545856 + //1.0000000, -0.89490829 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd29324; + B1 = 18'd1722; + B2 = 18'd1722; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/jt49_dcrm2.v b/Arcade_MiST/Konami Finalizer/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami Finalizer/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Finalizer/rtl/k005885.sv b/Arcade_MiST/Konami Finalizer/rtl/k005885.sv new file mode 100644 index 00000000..f8dff57a --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/k005885.sv @@ -0,0 +1,992 @@ +//============================================================================ +// +// SystemVerilog implementation of the Konami 005885 custom tilemap +// generator +// Graphics logic based on the video section of the Green Beret core for +// MiSTer by MiSTer-X +// Copyright (C) 2020, 2022 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Note: This model of the 005885 cannot be used as-is to replace an original 005885. + +module k005885 +( + input CK49, //49.152MHz clock input + output NCK2, //6.144MHz clock output + output H1O, //3.072MHz clock output + output NCPE, //E clock for MC6809E + output NCPQ, //Q clock for MC6809E + output NEQ, //AND of E and Q clocks for MC6809E + input NRD, //Read enable (active low) + output NRES, //Reset passthrough + input [13:0] A, //Address bus from CPU + input [7:0] DBi, //Data bus input from CPU + output [7:0] DBo, //Data output to CPU + output [3:0] VCF, //Color address to tilemap LUT PROM + output [3:0] VCB, //Tile index to tilemap LUT PROM + input [3:0] VCD, //Data input from tilemap LUT PROM + output [3:0] OCF, //Color address to sprite LUT PROM + output [3:0] OCB, //Sprite index to sprite LUT PROM + input [3:0] OCD, //Data input from sprite LUT PROM + output [4:0] COL, //Color data output from color mixer + input NEXR, //Reset input (active low) + input NXCS, //Chip select (active low) + output NCSY, //Composite sync (active low) + output NHSY, //HSync (active low) - Not exposed on the original chip + output NVSY, //VSync (active low) + output HBLK, //HBlank (active high) - Not exposed on the original chip + output VBLK, //VBlank (active high) - Not exposed on the original chip + input NBUE, //Unknown + output NFIR, //Fast IRQ (FIRQ) output for MC6809E + output NIRQ, //IRQ output for MC6809E (VBlank IRQ) + output NNMI, //Non-maskable IRQ (NMI) for MC6809E + output NIOC, //Inverse of address line A11 for external address decoding logic + output NRMW, + + //Split I/O for tile and sprite data + output [15:0] R, //Address output to graphics ROMs (tiles) + input [7:0] RDU, //Upper 8 bits of graphics ROM data (tiles) + input [7:0] RDL, //Lower 8 bits of graphics ROM data (tiles) + output [15:0] S, //Address output to graphics ROMs (sprites) + output reg S_req = 0, + input S_ack, + input [7:0] SDU, //Upper 8 bits of graphics ROM data (sprites) + input [7:0] SDL, //Lower 8 bits of graphics ROM data (sprites) + + //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] HCTR, VCTR, + + //Special flag for reconfiguring the chip to mimic the anomalies found on bootlegs of games that use the 005885 + //Valid values: + //-00: Original behavior + //-01: Jackal bootleg (faster video timings, missing 4 lines from the video signal, misplaced HBlank, altered screen + // centering, sprite layer is missing one line per sprite, sprite layer is misplaced by one line when the screen is + // flipped) + //-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is + // offset vertically by 1 line, sprite limit significantly lower than normal) + input [1:0] BTLG, + //Extra data outputs for graphics ROMs + output reg ATR4, //Tilemap attribute bit 4 + output reg ATR5 //Tilemap attribute bit 5 + + `ifdef MISTER_HISCORE + //MiSTer high score system I/O (to be used only with Iron Horse) + , + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_read, + input hs_access_write + `endif +); + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Reset line passthrough +assign NRES = NEXR; + +//Generate NIOC output (active low) +assign NIOC = ~(~NXCS & (A[13:11] == 3'b001)); + +//TODO: The timing of the NRMW output is currently unknown - set to 1 for now +assign NRMW = 1; + +//Output bits 4 and 5 of tilemap attributes for graphics ROM addressing +/* +assign ATR4 = tile_ctrl[2] ? tile_attrib_D[4] : tile0_attrib_D[4]; +assign ATR5 = tile_ctrl[2] ? tile_attrib_D[5] : tile0_attrib_D[5]; +*/ +//Data output to CPU +assign DBo = (ram_cs & ~NRD) ? ram_Dout: + (zram0_cs & ~NRD) ? zram0_Dout: + (zram1_cs & ~NRD) ? zram1_Dout: + (zram2_cs & ~NRD) ? zram2_Dout: + (tile_attrib_cs & ~NRD) ? tile0_attrib_Dout: + (tile_cs & ~NRD) ? tile0_Dout: + (tile1_attrib_cs & ~NRD) ? tile1_attrib_Dout: + (tile1_cs & ~NRD) ? tile1_Dout: + (spriteram_cs & ~NRD) ? spriteram_Dout: + 8'hFF; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz +reg [3:0] div = 4'd0; +always_ff @(posedge CK49) begin + div <= div + 4'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div; +assign NCK2 = div[2]; +assign H1O = div[3]; + +//The MC6809E requires two identical clocks with a 90-degree offset - assign these here +reg mc6809e_E = 0; +reg mc6809e_Q = 0; +always_ff @(posedge CK49) begin + reg [1:0] clk_phase = 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b00: mc6809e_E <= 0; + 2'b01: mc6809e_Q <= 1; + 2'b10: mc6809e_E <= 1; + 2'b11: mc6809e_Q <= 0; + endcase + end +end +assign NCPQ = mc6809e_Q; +assign NCPE = mc6809e_E; + +//Output NEQ combines NCPE and NCPQ together via an AND gate - assign this here +assign NEQ = NCPE & NCPQ; + +//-------------------------------------------------------- Video timings -------------------------------------------------------// + +//The 005885's video output has 384 horziontal lines and 262 vertical lines with an active resolution of 240x224. Declare both +//counters as 9-bit registers. +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter +//rolls over +reg hblank = 0; +reg vblank = 0; +reg frame_odd_even = 0; +//Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical +//counter if a bootleg Jackal ROM set is loaded +reg [8:0] vcnt_end = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + if(BTLG == 2'b01) + vcnt_end <= 9'd252; + else if(BTLG == 2'b10) + vcnt_end <= 9'd271; + else + vcnt_end <= 9'd261; + end +end +//Reposition HSync and VSync if a bootleg Iron Horse or Jackal ROM set is loaded +reg [8:0] hsync_start = 9'd0; +reg [8:0] hsync_end = 9'd0; +reg [8:0] vsync_start = 9'd0; +reg [8:0] vsync_end = 9'd0; +always_ff @(posedge CK49) begin + if(BTLG == 2'b01) begin + hsync_start <= HCTR[3] ? 9'd287 : 9'd295; + hsync_end <= HCTR[3] ? 9'd318 : 9'd326; + vsync_start <= 9'd244; + vsync_end <= 9'd251; + end + else if(BTLG == 2'b10) begin + hsync_start <= HCTR[3] ? 9'd290 : 9'd310; + hsync_end <= HCTR[3] ? 9'd321 : 9'd341; + vsync_start <= 9'd255; + vsync_end <= 9'd262; + end + else if(tile_ctrl[2]) begin + hsync_start <= HCTR[3] ? 9'd312 : 9'd320; + hsync_end <= HCTR[3] ? 9'd343 : 9'd351; + vsync_start <= 9'd254; + vsync_end <= 9'd261; + end + else begin + hsync_start <= HCTR[3] ? 9'd288 : 9'd296; + hsync_end <= HCTR[3] ? 9'd319 : 9'd327; + vsync_start <= 9'd254; + vsync_end <= 9'd261; + end +end +always_ff @(posedge CK49) begin + if(cen_6m) begin + case(h_cnt) + //HBlank ends two lines earlier than normal on bootleg Jackal PCBs + 10: begin + if(BTLG == 2'b01) + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + 12: begin + if(BTLG != 2'b01) + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + //Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded + 250: begin + if(BTLG == 2'b01 && !tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 252: begin + if(BTLG != 2'b01 && !tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + //Shift the start of HBlank 40 lines later when using the wider 280x224 video mode + 292: begin + if(tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 383: begin + h_cnt <= 0; + case(v_cnt) + 15: begin + vblank <= 0; + v_cnt <= v_cnt + 9'd1; + end + 239: begin + vblank <= 1; + frame_odd_even <= ~frame_odd_even; + v_cnt <= v_cnt + 9'd1; + end + vcnt_end: begin + v_cnt <= 9'd0; + end + default: v_cnt <= v_cnt + 9'd1; + endcase + end + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Output HBlank and VBlank (both active high) +assign HBLK = hblank; +assign VBLK = vblank; + +//Generate horizontal sync and vertical sync (both active low) +assign NHSY = HCTR[3] ? ~(h_cnt >= hsync_start - ~HCTR[2:0] && h_cnt <= hsync_end - ~HCTR[2:0]): + ~(h_cnt >= hsync_start + HCTR[2:0] && h_cnt <= hsync_end + HCTR[2:0]); +assign NVSY = ~(v_cnt >= vsync_start - VCTR && v_cnt <= vsync_end - VCTR); +assign NCSY = NHSY ^ NVSY; + +//------------------------------------------------------------- IRQs -----------------------------------------------------------// + +//Edge detection for VBlank and vertical counter bits 4 and 5 for IRQ generation +reg old_vblank, old_vcnt4, old_vcnt5; +always_ff @(posedge CK49) begin + old_vcnt4 <= v_cnt[4]; + old_vcnt5 <= v_cnt[5]; + old_vblank <= vblank; +end + +//IRQ (triggers every VBlank) +reg vblank_irq = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !irq_mask) + vblank_irq <= 1; + else if(!old_vblank && vblank) + vblank_irq <= 0; +end +assign NIRQ = vblank_irq; + +//NMI (triggers on the falling edge of vertical counter bits 4 or 5 based on the state of tile control register bit 2) +reg nmi = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !nmi_mask) + nmi <= 1; + else begin + if(tile_ctrl[2]) begin + if(old_vcnt4 && !v_cnt[4]) + nmi <= 0; + end + else begin + if(old_vcnt5 && !v_cnt[5]) + nmi <= 0; + end + end +end +assign NNMI = nmi; + +//FIRQ (triggers every second VBlank) +reg firq = 1; +always_ff @(posedge CK49) begin + if(!NEXR || !firq_mask) + firq <= 1; + else begin + if(frame_odd_even && !old_vblank && vblank) + firq <= 0; + end +end +assign NFIR = firq; + +//----------------------------------------------------- Internal registers -----------------------------------------------------// + +//The 005885 has five 8-bit registers set up as follows according to information in konamiic.txt found in MAME's source code: +/* +control registers +000: scroll y +001: scroll x (low 8 bits) +002: -------x scroll x (high bit) + ----xxx- row/colscroll control + 000 = solid scroll (finalizr, ddribble bg) + 100 = solid scroll (jackal) + 001 = ? (ddribble fg) + 011 = colscroll (jackal high scores) + 101 = rowscroll (ironhors, jackal map) +003: ------xx high bits of the tile code + -----x-- unknown (finalizr) + ----x--- selects sprite buffer (and makes a copy to a private buffer?) + --x----- unknown (ironhors) + -x------ unknown (ironhors) + x------- unknown (ironhors, jackal) +004: -------x nmi enable + ------x- irq enable + -----x-- firq enable + ----x--- flip screen +*/ + +wire regs_cs = ~NXCS & (A[13:11] == 2'b00) & (A[6:3] == 4'd0); + +reg [7:0] scroll_y, scroll_x, scroll_ctrl, tile_ctrl; +reg nmi_mask = 0; +reg irq_mask = 0; +reg firq_mask = 0; +reg flipscreen = 0; + +//Write to the appropriate register +always_ff @(posedge CK49) begin + reg rightD, leftD, upD; + if(cen_3m) begin + if(regs_cs && NRD) + case(A[2:0]) + 3'b000: scroll_y <= DBi; + 3'b001: scroll_x <= DBi; + 3'b010: scroll_ctrl <= DBi; + 3'b011: tile_ctrl <= DBi; + 3'b100: begin + nmi_mask <= DBi[0]; + irq_mask <= DBi[1]; + firq_mask <= DBi[2]; + flipscreen <= DBi[3]; + end + default; + endcase + end +end + +//--------------------------------------------------------- Unknown RAM --------------------------------------------------------// + +wire ram_cs = ~NXCS & (A >= 14'h0005 && A <= 14'h001F); + +wire [7:0] ram_Dout; +spram #(8, 5) RAM +( + .clk(CK49), + .we(ram_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(ram_Dout) +); + +//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------// + +wire zram0_cs = ~NXCS & (A >= 16'h0020 && A <= 16'h003F); +wire zram1_cs = ~NXCS & (A >= 16'h0040 && A <= 16'h005F); +wire zram2_cs = ~NXCS & (A >= 16'h0060 && A <= 16'h00DF); + +//The 005885 addresses ZRAM with either horizontal or vertical position bits depending on whether its scroll mode is set to +//line scroll or column scroll - use vertical position bits for line scroll and horizontal position bits for column scroll, +//otherwise don't address it +wire [4:0] zram_A = (scroll_ctrl[3:1] == 3'b101) ? tilemap_vpos[7:3]: + (scroll_ctrl[3:1] == 3'b011) ? tilemap_hpos[7:3]: + 5'h00; +wire [7:0] zram0_D, zram1_D, zram2_D, zram0_Dout, zram1_Dout, zram2_Dout; +dpram_dc #(.widthad_a(5)) ZRAM0 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram0_Dout), + .wren_a(zram0_cs & NRD), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram0_D) +); +spram #(8, 5) ZRAM1 +( + .clk(CK49), + .we(zram1_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(zram1_Dout) +); +spram #(8, 5) ZRAM2 +( + .clk(CK49), + .we(zram2_cs & NRD), + .addr(A[4:0]), + .data(DBi), + .q(zram2_Dout) +); + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//VRAM is external to the 005885 and combines multiple banks into a single 8KB RAM chip for tile attributes and data (two layers), +//and two sprite banks. For simplicity, this RAM has been made internal to the 005885 implementation and split into its +//constituent components. +wire tile_attrib_cs = ~NXCS & (A[13:10] == 4'b1000); +wire tile_cs = ~NXCS & (A[13:10] == 4'b1001); +wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010); +wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011); +wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11); + +wire [7:0] tile0_attrib_Dout, tile0_Dout, tile1_attrib_Dout, tile1_Dout, spriteram_Dout; +wire [7:0] tile0_attrib_D, tile0_D, tile1_attrib_D, tile1_D, spriteram_D; +//Tilemap layer 0 +dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile0_attrib_Dout), + .wren_a(tile_attrib_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile0_attrib_D) +); +dpram_dc #(.widthad_a(10)) VRAM_TILECODE0 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile0_Dout), + .wren_a(tile_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile0_D) +); +//Tilemap layer 1 +dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile1_attrib_Dout), + .wren_a(tile1_attrib_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile1_attrib_D) +); +dpram_dc #(.widthad_a(10)) VRAM_TILECODE1 +( + .clock_a(CK49), + .address_a(A[9:0]), + .data_a(DBi), + .q_a(tile1_Dout), + .wren_a(tile1_cs & NRD), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tile1_D) +); + + + +`ifndef MISTER_HISCORE +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(A[11:0]), + .data_a(DBi), + .q_a(spriteram_Dout), + .wren_a(spriteram_cs & NRD), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +`else +// Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM) +// - Mirrored sprite RAM used to protect against corruption while retrieving highscore data +wire [11:0] VRAM_SPR_AD = hs_access_write ? hs_address : A[11:0]; +wire [7:0] VRAM_SPR_DIN = hs_access_write ? hs_data_in : DBi; +wire VRAM_SPR_WE = hs_access_write ? hs_write_enable : (spriteram_cs & NRD); +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .q_a(spriteram_Dout), + .wren_a(VRAM_SPR_WE), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +//Sprite RAM shadow for highscore read access +dpram_dc #(.widthad_a(12)) VRAM_SPR_SHADOW +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .wren_a(VRAM_SPR_WE), + + .clock_b(CK49), + .address_b(hs_address), + .q_b(hs_data_out) +); +`endif + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//The Konami 005885 contains two tilemap layers. Finalizer - Super Transformation uses the second layer to draw the HUD at the +//top of the screen. Latch tilemap data out of bank 0 or bank 1 of the tilemap section of VRAM based on how far the game has +//drawn the tilemap layer when tile control bit 2 is set, otherwise grab tilemap data from bank 0 of the tilemap section of VRAM +//at all times + +//Loosely based on TimePilot 84's schematics +reg [7:0] tile_attrib_D, tile_D; +wire tile1_en = flipscreen ? h_cnt > 9'd243 : h_cnt < 9'd40; +wire [5:0] tile_hoffset = tile_ctrl[2] ? (~tile1_en ? (flipscreen ? 6'd4 : 6'd32) : 6'd0) : (flipscreen ? 6'd4 : 6'd0); + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if(h_cnt[1:0] == 2'b01) begin // posedge of h_cnt[1] + if(tile_ctrl[2] && tile1_en) begin + tile_D <= tile1_D; + tile_attrib_D <= tile1_attrib_D; + end + else begin + tile_D <= tile0_D; + tile_attrib_D <= tile0_attrib_D; + end + end + end +end + +//XOR horizontal and vertical counter bits with flipscreen bit +wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}}; +wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}}; + +//Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on +//whether row scroll or column scroll is enabled (do not allow scrolling when drawing Finalizer - Super Transformation's HUD +//and offset the tilemap layer with this game) +wire [8:0] row_scroll = (tile_ctrl[2] & !flipscreen & tile1_en) ? 9'd0: + (tile_ctrl[2] & flipscreen & tile1_en) ? 9'd28: + (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x}; +wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y; +wire [7:2] tilemap_hpos = hcnt_x[7:2] + row_scroll[7:2] - tile_hoffset[5:2] + {!tile_ctrl[2] & !flipscreen, 1'b0}/* synthesis keep */; +wire [8:0] tilemap_vpos = vcnt_x + col_scroll; + +//Address output to tilemap section of VRAM +wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]}; + +//Assign tile index as bits 5 and 6 of tilemap attributes and the tile code +wire [9:0] tile_index = {tile_attrib_D[7:6], tile_D} /* synthesis keep */; + +//XOR tile H/V flip bits with the flipscreen bit +wire tile_hflip = tile_attrib_D[4]; +wire tile_vflip = tile_attrib_D[5]; + +//Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position +//bit 1 (direct for Finalizer) +reg [15:0] RD_lat = 16'd0; +reg [3:0] tile_color, tile_color_r; +reg tile_hflip_lat, tile_hflip_lat_r; +reg tile_vflip_lat; +reg hpos2_lat; +reg [2:0] yscroll_lat; +reg [1:0] xscroll_lat, xscroll_lat_r, xscroll_lat_rr; + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if(h_cnt[1:0] == 2'b11) begin // negedge of h_cnt[1] + hpos2_lat <= tilemap_hpos[2]; + xscroll_lat <= row_scroll[1:0]; + xscroll_lat_r <= xscroll_lat; + yscroll_lat <= tilemap_vpos[2:0]; + tile_color <= tile_attrib_D[3:0]; + tile_color_r <= tile_color; + tile_hflip_lat <= tile_hflip; + tile_hflip_lat_r <= tile_hflip_lat; + tile_vflip_lat <= tile_vflip; + //Address output to graphics ROMs + R[15:4] <= {tile_ctrl[1:0], tile_index}; + //Latch graphics ROM output + RD_lat <= {RDU, RDL}; + //Output bits 4 and 5 of tilemap attributes for graphics ROM addressing + ATR4 <= tile_attrib_D[4]; + ATR5 <= tile_attrib_D[5]; + end + xscroll_lat_rr <= xscroll_lat_r; + end +end +assign R[3:0] = {yscroll_lat[2:0] ^ {3{tile_vflip_lat}}, hpos2_lat ^ tile_hflip_lat}; + +reg [3:0] tile_pixel /* synthesis keep */; +always @(*) begin + case (hcnt_x[1:0] ^ {2{tile_hflip_lat_r}}) + 2'b00: tile_pixel = RD_lat[15:12]; + 2'b01: tile_pixel = RD_lat[11: 8]; + 2'b10: tile_pixel = RD_lat[ 7: 4]; + 2'b11: tile_pixel = RD_lat[ 3: 0]; + default: ; + endcase +end + +//Address output to tilemap LUT PROM +assign VCF = tile_color_r; +assign VCB = tile_pixel; + +// latch pixel data, and generate 4 shifted pixel positions for fine scroll +reg [3:0] pix0, pix1, pix2, pix3; +always_ff @(posedge CK49) begin + if (cen_6m) begin + pix0 <= VCD; + pix1 <= pix0; + pix2 <= pix1; + pix3 <= pix2; + end +end + +// select the appropriate shifted pixel according to scroll value +reg [3:0] tilemap_D /* synthesis keep */; +wire hud_left = !flipscreen && tile_ctrl[2] && h_cnt < 52; +wire hud_right = flipscreen && tile_ctrl[2] && h_cnt > 252; +always @(*) begin + case ({2{flipscreen}} ^ xscroll_lat_rr) + 2'b00: tilemap_D = pix3; + 2'b01: tilemap_D = pix2; + 2'b10: tilemap_D = pix1; + 2'b11: tilemap_D = pix0; + default: ; + endcase + if (hud_left ) tilemap_D = pix3; + if (hud_right) tilemap_D = pix0; +end + +//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register +wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5]; +//Prioritize the tilemap layer when using the extended 280x224 mode for Finalizer in the score display area, otherwise give priority +//to sprites +wire tilemap_en = tile_ctrl[2] ? (hud_left | hud_right) : tile_sel; + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//The following code is an adaptation of the sprite renderer from MiSTer-X's Green Beret core tweaked for the 005885's sprite format +reg [8:0] sprite_hpos = 9'd0; +reg [8:0] sprite_vpos = 9'd0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + sprite_hpos <= h_cnt; + //If a bootleg Iron Horse ROM set is loaded, apply a vertical offset of 65 lines (66 when flipped) to recreate the + //bootleg hardware's 1-line downward vertical offset between the sprite and tilemap layers, otherwise apply a + //vertical offset of 66 lines (65 lines when flipped) + if(BTLG == 2'b10) + if(flipscreen) + sprite_vpos <= v_cnt + 9'd66; + else + sprite_vpos <= v_cnt + 9'd65; + else + if(flipscreen) + sprite_vpos <= v_cnt + 9'd65; + else + sprite_vpos <= v_cnt + 9'd66; + end +end + +//Sprite state machine +reg [8:0] sprite_index; +reg [2:0] sprite_offset; +reg [2:0] sprite_fsm_state; +reg [11:0] sprite_code; +reg [8:0] sprite_limit; +reg [8:0] sprite_x; +reg [7:0] sprite_y; +reg [5:0] sprite_width; +reg [3:0] sprite_color; +reg [2:0] sprite_size; +reg sprite_hflip, sprite_vflip, sprite_x8_sel, sprite_x8_vram; +wire [8:0] sprite_fsm_reset = tile_ctrl[2] ? 9'd40 : 9'd0; +always_ff @(posedge CK49) begin + //Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit + //to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of + //5, otherwise) + sprite_limit <= (BTLG == 2'b10) ? 9'd155 : 9'd485; + //Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0 + //Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse + //ROM sets to prevent graphical garbage from occurring on the top-most line + if(sprite_hpos == sprite_fsm_reset || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin + sprite_width <= 0; + sprite_index <= 0; + sprite_offset <= 3'd4; + sprite_fsm_state <= 1; + end + else + case(sprite_fsm_state) + 0: /* empty */ ; + 1: begin + //If the sprite limit is reached, hold the state machine in an empty state, otherwise latch the sprite H/V flip + //bits, sprite size, bit 8 of the sprite X position and its select bit + if(sprite_index > sprite_limit) + sprite_fsm_state <= 0; + else begin + sprite_vflip <= spriteram_D[6] ^ ~flipscreen; + sprite_hflip <= spriteram_D[5] ^ flipscreen; + sprite_size <= spriteram_D[4:2]; + sprite_x8_sel <= spriteram_D[1]; + sprite_x8_vram <= spriteram_D[0]; + sprite_offset <= 3'd3; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + end + 2: begin + //Latch sprite X position and set the 9th bit as either the one latched previously from VRAM or the AND of position + //bits [7:3] based on the state of the select bit + if(sprite_x8_sel) + sprite_x[8] <= sprite_x8_vram ^ flipscreen; + else + sprite_x[8] <= (&spriteram_D[7:3]) ^ flipscreen; + sprite_x[7:0] <= spriteram_D ^ {8{flipscreen}}; + sprite_offset <= 3'd2; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 3: begin + //Latch sprite Y position + sprite_y <= spriteram_D; + sprite_offset <= 3'd1; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 4: begin + //Skip the current sprite if it's inactive, otherwise latch sprite color and the upper/lower 2 bits of the sprite + //code, and continue scanning out the rest of the sprite attributes + if(sprite_active) begin + sprite_color <= spriteram_D[7:4]; + sprite_code[1:0] <= spriteram_D[3:2]; + sprite_code[11:10] <= spriteram_D[1:0]; + sprite_offset <= 3'd0; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + else begin + sprite_index <= sprite_index + 9'd5; + sprite_offset <= 3'd4; + sprite_fsm_state <= 3'd1; + end + end + 5: begin + //Latch bits [9:2] of the sprite code and set up the sprite width based on the sprite size + sprite_code[9:2] <= spriteram_D; + sprite_offset <= 3'd4; + sprite_index <= sprite_index + 9'd5; + case(sprite_size) + 3'b000: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen); + 3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen); + 3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); + 3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); + default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen); + endcase + sprite_fsm_state <= sprite_fsm_state + 3'd1; + S_req <= !S_req; + end + 6: if (S_req == S_ack) begin + //Skip the last line of a sprite if a bootleg Jackal ROM set is loaded (the hardware on such bootlegs fails + //to render the last line of sprites), otherwise write sprites as normal + if(BTLG == 2'b01 && !flipscreen) + if(sprite_width == 6'b111110) + sprite_width <= sprite_width + 6'd2; + else + sprite_width <= sprite_width + 6'd1; + else + sprite_width <= sprite_width + 6'd1; + sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1; + S_req <= (wre & sprite_width[1:0] == 2'b11) ? !S_req : S_req; + + end + default:; + endcase +end + +//Adjust sprite code based on sprite size +wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16 + sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8 + sprite_size == 3'b010 ? {sprite_code[11:2], ly[3], sprite_code[0]}: //8x16 + sprite_size == 3'b011 ? sprite_code: //8x8 + {sprite_code[11:2] + {ly[4], lx[4]}, ly[3], lx[3]}; //32x32 + +//Subtract vertical sprite position from sprite Y parameter to obtain sprite height +wire [8:0] sprite_height = {(sprite_y[7:4] == 4'hF), sprite_y ^ {8{flipscreen}}} - sprite_vpos; + +//Set when a sprite is active depending on whether it is 8, 16 or 32 pixels tall +reg sprite_active; +always @(*) begin + case(sprite_size) + 3'b000: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen); + 3'b001: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen); + 3'b010: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen); + 3'b011: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen) + & (sprite_height[4] ^ flipscreen) & (sprite_height[3] ^ flipscreen); + 3'b100: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen); + default: sprite_active = (sprite_height[8:7] == 2'b11) & (sprite_height[6] ^ ~flipscreen) & (sprite_height[5] ^ flipscreen); + endcase +end + +wire [4:0] lx = sprite_width[4:0] ^ {5{sprite_hflip}}; +wire [4:0] ly = sprite_height[4:0] ^ {5{sprite_vflip}}; + +//Assign address outputs to sprite ROMs +assign S = {sprite_code_sized, ly[2:0], lx[2]}; + +//Multiplex sprite ROM data down from 16 bits to 8 using bit 1 of the horizontal position +wire [7:0] SD = lx[1] ? SDL : SDU; + +//Further multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4]; + +//Sum the sprite index with the sprite offset and address sprite RAM with it along with tile control register bit 3 +wire [8:0] sprite_address = (sprite_index + sprite_offset); +reg sprite_bank = 0; +reg old_vsync; +//Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes +//jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded +//Finalizer - Super Transformation only reads sprite information from the lower sprite bank +always_ff @(posedge CK49) begin + old_vsync <= NVSY; + if(!NEXR) + sprite_bank <= 0; + else if(!old_vsync && NVSY) + sprite_bank <= tile_ctrl[3]; +end +wire [11:0] spriteram_A = {(BTLG == 2'b01) ? tile_ctrl[3] : sprite_bank, 2'b00, sprite_address}; + +//Address output to sprite LUT PROM +assign OCF = sprite_color; +assign OCB = sprite_pixel; + +//----------------------------------------------------- Sprite line buffer -----------------------------------------------------// + +//The sprite line buffer is external to the 005885 and consists of two 4464 DRAM chips. For simplicity, both the logic for the +//sprite line buffer and the sprite line buffer itself are internal to the 005885 implementation. + +//Enable writing to sprite line buffer when bit 5 of the sprite width is 1 +wire wre = sprite_width[5]; + +//Set sprite line buffer bank as bit 0 of the sprite vertical position +wire sprite_lbuff_bank = sprite_vpos[0]; + +//Sum sprite X position with the following bits of the sprite width to address the sprite line buffer based on sprite size: +//32 pixels wide: bits [4:0] +//16 pixels wide: bits [3:0] +//8 pixels wide: bits [2:0] +//XOR the upper bits for screen flipping on 16 pixel and 8 pixel wide sprites +reg [4:0] final_sprite_width; +always @(*) begin + case(sprite_size) + 3'b000: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]}; + 3'b001: final_sprite_width = {sprite_width[4] ^ ~flipscreen, sprite_width[3:0]}; + 3'b010: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]}; + 3'b011: final_sprite_width = {sprite_width[4:3] ^ {2{~flipscreen}}, sprite_width[2:0]}; + 3'b100: final_sprite_width = sprite_width[4:0]; + default: final_sprite_width = sprite_width[4:0]; + endcase +end +wire [8:0] wpx = sprite_x + final_sprite_width; + +//Generate sprite line buffer write addresses +reg [9:0] lbuff_A; +reg lbuff_we; +wire [3:0] lbuff_Din = OCD; +always_ff @(posedge CK49) begin + lbuff_A <= {~sprite_lbuff_bank, wpx}; + lbuff_we <= wre & S_req == S_ack; +end + +//Generate read address for sprite line buffer on the rising edge of the pixel clock (apply a -225 offset when the screen +//is flipped) +reg [9:0] radr0 = 10'd0; +reg [9:0] radr1 = 10'd1; +always_ff @(posedge CK49) begin + if(cen_6m) + radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : tile_ctrl[2] ? sprite_hpos - 9'd40 : sprite_hpos}; +end + +//Sprite line buffer +wire [3:0] lbuff_Dout; +dpram_dc #(.widthad_a(10)) LBUFF +( + .clock_a(CK49), + .address_a(lbuff_A), + .data_a({4'd0, lbuff_Din}), + .wren_a(lbuff_we & (lbuff_Din != 0)), + + .clock_b(CK49), + .address_b(radr0), + .data_b(8'h0), + .wren_b(radr0 == radr1), + .q_b({4'bZZZZ, lbuff_Dout}) +); + +//Latch sprite data from the sprite line buffer +wire lbuff_read_en = (div[2:0] == 3'b100); +reg [3:0] lbuff_read = 4'd0; +always_ff @(posedge CK49) begin + if(lbuff_read_en) begin + if(radr0 != radr1) + lbuff_read <= lbuff_Dout; + radr1 <= radr0; + end +end + +//Delay sprite layer by 2 horizontal lines (1 line if a bootleg Jackal ROM set is loaded and the screen is flipped) +reg [7:0] sprite_dly = 8'd0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + if(BTLG == 2'b01 && flipscreen) + sprite_dly <= {4'd0, lbuff_read}; + else + sprite_dly <= {lbuff_read, sprite_dly[7:4]}; + end +end +//Jackal bootlegs fail to render the last two vertical lines of the sprite layer - model this behavior here +wire [3:0] sprite_D = (BTLG == 2'b01 && ((h_cnt >= 244 && ~flipscreen) || (h_cnt >= 248 && flipscreen))) ? 4'd0 : sprite_dly[3:0]; + +//--------------------------------------------------------- Color mixer --------------------------------------------------------// + +//Multiplex tile and sprite data, then output the final result +wire tile_sprite_sel = (tilemap_en | ~(|sprite_D)); +wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D; + +//Latch and output pixel data +reg [4:0] pixel_D; +always_ff @(posedge CK49) begin + if(cen_6m) + pixel_D <= {tile_sprite_sel, tile_sprite_D}; +end +assign COL = (BTLG == 2'b01 && ((h_cnt >= 247 && ~flipscreen) || (h_cnt <= 14 && flipscreen))) || + (BTLG == 2'b10 && ((h_cnt <= 20 && ~flipscreen) || ((h_cnt <= 18 || h_cnt >= 251) && flipscreen))) ? 5'd0 : pixel_D; +//The above condition blacks out the last 4 lines on the right side of the screen (left when flipped) when a bootleg Jackal ROM set +//is loaded and blacks out the left-most 8 lines (7 when flipped plus an extra 2 lines on the right side) when a bootleg Iron Horse +//ROM set is loaded - this simulates the earlier-than-normal start of HBlank for Jackal bootlegs and later-than-normal end of +//HBlank for Iron Horse bootlegs while maintaining the usual 240x224 display area + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/pll.qip b/Arcade_MiST/Konami Finalizer/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Konami Finalizer/rtl/pll.v b/Arcade_MiST/Konami Finalizer/rtl/pll.v new file mode 100644 index 00000000..1960b7f8 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 105, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 382, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 105, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 191, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Konami Finalizer/rtl/rom_loader.sv b/Arcade_MiST/Konami Finalizer/rtl/rom_loader.sv new file mode 100644 index 00000000..a5d288df --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/rom_loader.sv @@ -0,0 +1,433 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019, 2020 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Finalizer: +// 0x0000 - 0x3FFF = eprom_1 +// 0x4000 - 0x7FFF = eprom_2 +// 0x8000 - 0xBFFF = eprom_3 +// 0xC000 - 0xFFFF = eprom_4 +// 0x10000 - 0x13FFF = eprom_5 +// 0x14000 - 0x17FFF = eprom_6 +// 0x18000 - 0x1BFFF = eprom_7 +// 0x1C000 - 0x1FFFF = eprom_8 +// 0x20000 - 0x23FFF = eprom_9 +// 0x24000 - 0x247FF = snd01 +// 0x24800 - 0x248FF = prom_1 +// 0x24900 - 0x249FF = prom_2 +// 0x24A00 - 0x24A1F = prom_3 +// 0x24A20 - 0x24A3F = prom_4 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs, ep9_cs, snd01_cs, + prom1_cs, prom2_cs, prom3_cs, prom4_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs, ep9_cs, snd01_cs, + prom1_cs, prom2_cs, prom3_cs, prom4_cs} = 0; + if(ioctl_addr < 'h4000) + ep1_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h8000) + ep2_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'hC000) + ep3_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h10000) + ep4_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h14000) + ep5_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h18000) + ep6_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h1C000) + ep7_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h20000) + ep8_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h24000) + ep9_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h24800) + snd01_cs = 1; // 0x800 11 + else if(ioctl_addr < 'h24900) + prom1_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h24A00) + prom2_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h24A20) + prom3_cs = 1; // 0x20 5 + else + prom4_cs = 1; // 0x20 5 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK_A, + input logic CLK_B, + input logic [13:0] ADDR_A, + input logic [24:0] ADDR_B, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATAOUT_A, + output logic [7:0] DATAOUT_B +); + dpram_dc #(.widthad_a(14)) eprom_4 + ( + .clock_a(CLK_A), + .address_a(ADDR_A[13:0]), + .q_a(DATAOUT_A[7:0]), + + .clock_b(CLK_B), + .address_b(ADDR_B[13:0]), + .data_b(DATA_IN), + .q_b(DATAOUT_B[7:0]), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK_A, + input logic CLK_B, + input logic [13:0] ADDR_A, + input logic [24:0] ADDR_B, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATAOUT_A, + output logic [7:0] DATAOUT_B +); + dpram_dc #(.widthad_a(14)) eprom_5 + ( + .clock_a(CLK_A), + .address_a(ADDR_A[13:0]), + .q_a(DATAOUT_A[7:0]), + + .clock_b(CLK_B), + .address_b(ADDR_B[13:0]), + .data_b(DATA_IN), + .q_b(DATAOUT_B[7:0]), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_6 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_6 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_7 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_7 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_8 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_8 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_9 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_9 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////////////// +// EMBEDDED ROMS // +/////////////////// + +module kSND01_ROM +( + input logic CLK, + input logic CLK_DL, + input logic [10:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(11)) kSND01_ROM + ( + .clock_a(CLK), + .address_a(ADDR[10:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[10:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_1 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) prom_2 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [4:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(5)) prom_3 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module prom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [4:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(5)) prom_4 + ( + .clock_a(CLK), + .address_a(ADDR), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/sdram.sv b/Arcade_MiST/Konami Finalizer/rtl/sdram.sv new file mode 100644 index 00000000..0145475c --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/sdram.sv @@ -0,0 +1,340 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [15:1] cpu1_addr, + output reg [15:0] cpu1_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [15:0] port2_q, + input [16:1] ch1_addr, + output reg [15:0] ch1_q, + input sp1_req, + input [16:1] sp1_addr, + output reg [15:0] sp1_q, + output reg sp1_ack +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 + 1 ras0 + 2 data1 returned + 3 CAS0 + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [15:1] addr_last[4]; +reg [16:1] addr_last2[4]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CH1 = 2'd1; +localparam PORT_SP1 = 2'd2; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 9'd0, cpu1_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (ch1_addr != addr_last2[PORT_CH1]) begin + next_port[1] = PORT_CH1; + addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, ch1_addr }; + end else if (sp1_req != sp1_ack) begin + next_port[1] = PORT_SP1; + addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, sp1_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][15:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][16:1]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end + PORT_CH1 : ch1_q <= sd_din; + PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end + default: ; + endcase; + end + + end +end + +endmodule diff --git a/Arcade_MiST/Konami Finalizer/rtl/spram.vhd b/Arcade_MiST/Konami Finalizer/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl; diff --git a/Arcade_MiST/Konami Finalizer/rtl/t8049_notri.vhd b/Arcade_MiST/Konami Finalizer/rtl/t8049_notri.vhd new file mode 100644 index 00000000..88022abb --- /dev/null +++ b/Arcade_MiST/Konami Finalizer/rtl/t8049_notri.vhd @@ -0,0 +1,295 @@ +------------------------------------------------------------------------------- +-- +-- T8048 Microcontroller System +-- 8048 toplevel without tri-states +-- +-- $Id: t8048_notri.vhd,v 1.7 2006/07/14 01:13:32 arniml Exp $ +-- $Name: $ +-- +-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t48/ +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity t8049_notri is + + generic ( + gate_port_input_g : integer := 1 + ); + + port ( + xtal_i : in std_logic; + xtal_en_i : in std_logic; + reset_n_i : in std_logic; + t0_i : in std_logic; + t0_o : out std_logic; + t0_dir_o : out std_logic; + int_n_i : in std_logic; + ea_i : in std_logic; + rd_n_o : out std_logic; + psen_n_o : out std_logic; + wr_n_o : out std_logic; + ale_o : out std_logic; + db_i : in std_logic_vector( 7 downto 0); + db_o : out std_logic_vector( 7 downto 0); + db_dir_o : out std_logic; + t1_i : in std_logic; + p2_i : in std_logic_vector( 7 downto 0); + p2_o : out std_logic_vector( 7 downto 0); + p2l_low_imp_o : out std_logic; + p2h_low_imp_o : out std_logic; + p1_i : in std_logic_vector( 7 downto 0); + p1_o : out std_logic_vector( 7 downto 0); + p1_low_imp_o : out std_logic; + prog_n_o : out std_logic; + --Extra inputs for MiSTer ROM loader to load embedded ROM + ADDR_DL : in std_logic_vector(24 downto 0); + CLK_DL : in std_logic; + CS_DL : in std_logic; + DATA_IN : in std_logic_vector( 7 downto 0); + WR : in std_logic + ); + +end t8049_notri; + + +library ieee; +use ieee.numeric_std.all; + +use work.t48_core_comp_pack.t48_core; +--use work.t48_core_comp_pack.kSND01_ROM; +use work.t48_core_comp_pack.generic_ram_ena; + +architecture struct of t8049_notri is + + component kSND01_ROM + port ( + CLK : in std_logic; + CLK_DL : in std_logic; + ADDR : in std_logic_vector(10 downto 0); + ADDR_DL : in std_logic_vector(24 downto 0); + DATA_IN : in std_logic_vector( 7 downto 0); + CS_DL : in std_logic; + WR : in std_logic; + DATA : out std_logic_vector( 7 downto 0) + ); + end component; + + -- Address width of internal ROM + constant rom_addr_width_c : natural := 11; + + signal xtal3_s : std_logic; + signal dmem_addr_s : std_logic_vector( 7 downto 0); + signal dmem_we_s : std_logic; + signal dmem_data_from_s : std_logic_vector( 7 downto 0); + signal dmem_data_to_s : std_logic_vector( 7 downto 0); + signal pmem_addr_s : std_logic_vector(11 downto 0); + signal pmem_data_s : std_logic_vector( 7 downto 0); + + signal ea_s : std_logic; + + signal p1_in_s, + p1_out_s : std_logic_vector( 7 downto 0); + signal p2_in_s, + p2_out_s : std_logic_vector( 7 downto 0); + + signal vdd_s : std_logic; + +begin + + vdd_s <= '1'; + + ----------------------------------------------------------------------------- + -- Check generics for valid values. + ----------------------------------------------------------------------------- + -- pragma translate_off + assert gate_port_input_g = 0 or gate_port_input_g = 1 + report "gate_port_input_g must be either 1 or 0!" + severity failure; + -- pragma translate_on + + + t48_core_b : t48_core + generic map ( + xtal_div_3_g => 1, + register_mnemonic_g => 1, + include_port1_g => 1, + include_port2_g => 1, + include_bus_g => 1, + include_timer_g => 1, + sample_t1_state_g => 4 + ) + port map ( + xtal_i => xtal_i, + xtal_en_i => xtal_en_i, + reset_i => reset_n_i, + t0_i => t0_i, + t0_o => t0_o, + t0_dir_o => t0_dir_o, + int_n_i => int_n_i, + ea_i => ea_s, + rd_n_o => rd_n_o, + psen_n_o => psen_n_o, + wr_n_o => wr_n_o, + ale_o => ale_o, + db_i => db_i, + db_o => db_o, + db_dir_o => db_dir_o, + t1_i => t1_i, + p2_i => p2_in_s, + p2_o => p2_out_s, + p2l_low_imp_o => p2l_low_imp_o, + p2h_low_imp_o => p2h_low_imp_o, + p1_i => p1_in_s, + p1_o => p1_out_s, + p1_low_imp_o => p1_low_imp_o, + prog_n_o => prog_n_o, + clk_i => xtal_i, + en_clk_i => xtal3_s, + xtal3_o => xtal3_s, + dmem_addr_o => dmem_addr_s, + dmem_we_o => dmem_we_s, + dmem_data_i => dmem_data_from_s, + dmem_data_o => dmem_data_to_s, + pmem_addr_o => pmem_addr_s, + pmem_data_i => pmem_data_s + ); + + + ----------------------------------------------------------------------------- + -- Gate port 1 and 2 input bus with respetive output value + ----------------------------------------------------------------------------- + gate_ports: if gate_port_input_g = 1 generate + p1_in_s <= p1_i and p1_out_s; + p2_in_s <= p2_i and p2_out_s; + end generate; + + pass_ports: if gate_port_input_g = 0 generate + p1_in_s <= p1_i; + p2_in_s <= p2_i; + end generate; + + p1_o <= p1_out_s; + p2_o <= p2_out_s; + + + ----------------------------------------------------------------------------- + -- Process ea + -- + -- Purpose: + -- Detects access to external program memory. + -- Either by ea_i = '1' or when program memory address leaves address + -- range of internal ROM. + -- + ea: process (ea_i, + pmem_addr_s) + begin + if ea_i = '1' then + -- Forced external access + ea_s <= '1'; + + elsif unsigned(pmem_addr_s(11 downto rom_addr_width_c)) = 0 then + -- Internal access + ea_s <= '0'; + + else + -- Access to program memory out of internal range + ea_s <= '1'; + + end if; + + end process ea; + -- + ----------------------------------------------------------------------------- + + + rom_2k_b : kSND01_ROM + port map ( + CLK => xtal_i, + CLK_DL => CLK_DL, + ADDR => pmem_addr_s(rom_addr_width_c-1 downto 0), + ADDR_DL => ADDR_DL, + DATA_IN => DATA_IN, + CS_DL => CS_DL, + WR => WR, + DATA => pmem_data_s + ); + + ram_64_b : generic_ram_ena + generic map ( + addr_width_g => 7, + data_width_g => 8 + ) + port map ( + clk_i => xtal_i, + a_i => dmem_addr_s(6 downto 0), + we_i => dmem_we_s, + ena_i => vdd_s, + d_i => dmem_data_to_s, + d_o => dmem_data_from_s + ); + +end struct; + + +------------------------------------------------------------------------------- +-- File History: +-- +-- $Log: t8048_notri.vhd,v $ +-- Revision 1.7 2006/07/14 01:13:32 arniml +-- name keyword added +-- +-- Revision 1.6 2006/06/21 01:02:16 arniml +-- replaced syn_rom and syn_ram with t48_rom and generic_ram_ena +-- +-- Revision 1.5 2006/06/20 00:47:08 arniml +-- new input xtal_en_i +-- +-- Revision 1.4 2005/11/01 21:38:48 arniml +-- wire signals for P2 low impedance marker issue +-- +-- Revision 1.3 2004/12/02 22:08:42 arniml +-- introduced generic gate_port_input_g +-- forces masking of P1 and P2 input bus +-- +-- Revision 1.2 2004/12/01 23:08:08 arniml +-- update +-- +------------------------------------------------------------------------------- From aee4f9b84fae037cd7eb02669ae0066f5519f145 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sun, 2 Jan 2022 21:16:12 +0100 Subject: [PATCH 5/7] Konami Scooter Shooter --- Arcade_MiST/Konami ScooterShooter/README.md | 11 + .../Konami ScooterShooter/Scotrsht.qpf | 31 + .../Konami ScooterShooter/Scotrsht.qsf | 258 +++++++ .../Konami ScooterShooter/Scotrsht.sdc | 137 ++++ .../meta/Scooter Shooter.mra | 69 ++ .../rtl/ScooterShooter.sv | 623 ++++++++++++++++ .../rtl/ScooterShooter_MiST.sv | 316 +++++++++ .../rtl/audio_iir_filter.v | 173 +++++ .../Konami ScooterShooter/rtl/build_id.tcl | 35 + .../Konami ScooterShooter/rtl/dpram_dc.vhd | 136 ++++ .../Konami ScooterShooter/rtl/jt49_dcrm2.v | 62 ++ .../rtl/jtframe_frac_cen.v | 58 ++ .../Konami ScooterShooter/rtl/k005849.sv | 670 ++++++++++++++++++ Arcade_MiST/Konami ScooterShooter/rtl/pll.qip | 4 + Arcade_MiST/Konami ScooterShooter/rtl/pll.v | 348 +++++++++ .../Konami ScooterShooter/rtl/rom_loader.sv | 344 +++++++++ .../Konami ScooterShooter/rtl/sdram.sv | 347 +++++++++ .../Konami ScooterShooter/rtl/spram.vhd | 46 ++ .../rtl/sshooter_fm_lpf.sv | 60 ++ .../rtl/sshooter_ssg_lpf.sv | 61 ++ 20 files changed, 3789 insertions(+) create mode 100644 Arcade_MiST/Konami ScooterShooter/README.md create mode 100644 Arcade_MiST/Konami ScooterShooter/Scotrsht.qpf create mode 100644 Arcade_MiST/Konami ScooterShooter/Scotrsht.qsf create mode 100644 Arcade_MiST/Konami ScooterShooter/Scotrsht.sdc create mode 100644 Arcade_MiST/Konami ScooterShooter/meta/Scooter Shooter.mra create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter_MiST.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/build_id.tcl create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/k005849.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/pll.qip create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/pll.v create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/sdram.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/spram.vhd create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/sshooter_fm_lpf.sv create mode 100644 Arcade_MiST/Konami ScooterShooter/rtl/sshooter_ssg_lpf.sv diff --git a/Arcade_MiST/Konami ScooterShooter/README.md b/Arcade_MiST/Konami ScooterShooter/README.md new file mode 100644 index 00000000..37744952 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/README.md @@ -0,0 +1,11 @@ +# MiST port of Konami Scooter Shooter by ACE + +https://github.com/MiSTer-devel/Arcade-ScooterShooter_MiSTer + +## Usage + +- Create ROM and ARC files from the MRA files using the MRA utility. + Example: mra -A -z /path/to/mame/roms "Scooter Shooter.mra" +- Copy the ROM files to the root of the SD Card +- Copy the RBF and ARC files to the same folder on the SD Card +- MRA utility: https://github.com/sebdel/mra-tools-c/ \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/Scotrsht.qpf b/Arcade_MiST/Konami ScooterShooter/Scotrsht.qpf new file mode 100644 index 00000000..6eb1f1a5 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/Scotrsht.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "00:21:03 December 03, 2019" + +# Revisions + +PROJECT_REVISION = "Scotrsht" + diff --git a/Arcade_MiST/Konami ScooterShooter/Scotrsht.qsf b/Arcade_MiST/Konami ScooterShooter/Scotrsht.qsf new file mode 100644 index 00000000..47ece6e6 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/Scotrsht.qsf @@ -0,0 +1,258 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Scotrsht_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" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY ScooterShooter_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/sdram.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(Finalizer_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Finalizer_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name FORCE_SYNCH_CLEAR ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ScooterShooter_MiST.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ScooterShooter.sv +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sshooter_fm_lpf.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sshooter_ssg_lpf.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/k005849.sv +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/build_id.v +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v +set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip +set_global_assignment -name QIP_FILE ../../common/Sound/JT12/hdl/jt03.qip +set_global_assignment -name QIP_FILE ../../common/Sound/JT49/jt49.qip +set_global_assignment -name SIGNALTAP_FILE output_files/sdram.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/Scotrsht.sdc b/Arcade_MiST/Konami ScooterShooter/Scotrsht.sdc new file mode 100644 index 00000000..8ca54672 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/Scotrsht.sdc @@ -0,0 +1,137 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +set_multicycle_path -from {ScooterShooter:ScooterShooter_inst|mc6809is:u12A|*} -setup 2 +set_multicycle_path -from {ScooterShooter:ScooterShooter_inst|mc6809is:u12A|*} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Konami ScooterShooter/meta/Scooter Shooter.mra b/Arcade_MiST/Konami ScooterShooter/meta/Scooter Shooter.mra new file mode 100644 index 00000000..7d7b0fa8 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/meta/Scooter Shooter.mra @@ -0,0 +1,69 @@ + + Scooter Shooter + World + no + no + + + + + 1986 + Konami + Shooter - Horizontal + + scotrsht + scotrsht + 0224 + ScotrSht + + 15kHz + no + no + + 2 (simultaneous) + 8-way + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0E 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 10 00 + 00 00 1C A0 00 46 01 1D + 00 00 19 9C 00 03 01 40 + + + + + + + + + 20210910141626 + diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter.sv b/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter.sv new file mode 100644 index 00000000..994abf19 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter.sv @@ -0,0 +1,623 @@ +//============================================================================ +// +// Scooter Shooter PCB model +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +module ScooterShooter +( + input reset, + input clk_49m, //Actual frequency: 49.152MHz + input [1:0] coin, + input btn_service, + input [1:0] btn_start, //1 = Player 2, 0 = Player 1 + input [3:0] p1_joystick, p2_joystick, //3 = up, 2 = down, 1 = right, 0 = left + input p1_fire, + input p2_fire, + + input [19:0] dipsw, + + //This input serves to select a fractional divider to acheive 3.072MHz for the YM2203 depending on whether Scooter Shooter + //runs with original or underclocked timings to normalize sync frequencies + input underclock, + + //Screen centering (alters HSync and VSync timing of the Konami 005849 to reposition the video output) + input [3:0] h_center, v_center, + + output signed [15:0] sound, + output video_csync, + output video_hsync, video_vsync, + output video_vblank, video_hblank, + output ce_pix, + output [3:0] video_r, video_g, video_b, //12-bit RGB, 4 bits per color + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, + + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_write, + //SDRAM signals + output reg [15:0] main_cpu_rom_addr, + input [7:0] main_cpu_rom_do, + output reg [14:0] sub_cpu_rom_addr, + input [7:0] sub_cpu_rom_do, + output reg [14:1] char1_rom_addr, + input [15:0] char1_rom_do, + output sp1_req, + input sp1_ack, + output [15:0] sp1_rom_addr, + input [15:0] sp1_rom_do +); + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Output pixel clock enable +assign ce_pix = cen_6m; + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i, ep6_cs_i; +wire cp1_cs_i, cp2_cs_i, cp3_cs_i, tl_cs_i, sl_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .ep6_cs(ep6_cs_i), + .tl_cs(tl_cs_i), + .sl_cs(sl_cs_i), + .cp1_cs(cp1_cs_i), + .cp2_cs(cp2_cs_i), + .cp3_cs(cp3_cs_i) +); + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6.144MHz and (inverted) 3.072MHz clock enables (clock division is normally handled inside the Konami 005849) +//Also generate an extra clock enable for DC offset removal in the sound section +reg [6:0] div = 7'd0; +always_ff @(posedge clk_49m) begin + div <= div + 7'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div[3:0]; +wire dcrm_cen = !div; + +//Generate E and Q clock enables for MC6809E (code adapted from Sorgelig's phase generator used in the MiSTer Vectrex core) +reg E, Q; +always_ff @(posedge clk_49m) begin + reg [1:0] clk_phase = 0; + E <= 0; + Q <= 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b01: E <= 1; + 2'b10: Q <= 1; + endcase + end +end + +//Generate 3.072MHz clock enable for YM2203 to maintain consistent sound pitch when underclocked to normalize video timings +//(uses Jotego's fractional clock divider from JTFRAME) +wire cen_3m_adjust; +jtframe_frac_cen sound_cen +( + .clk(clk_49m), + .n(10'd50), + .m(10'd786), + .cen({1'bZ, cen_3m_adjust}) +); + +//------------------------------------------------------------ CPU -------------------------------------------------------------// + +//Main CPU (Motorola MC6809E - uses synchronous version of Greg Miller's cycle-accurate MC6809E made by Sorgelig) +wire [15:0] mc6809e_A; +wire [7:0] mc6809e_Dout; +wire mc6809e_rw, mc6809e_avma; + +`ifdef CPU09 +wire vma; +cpu09 u12G +( + .clk(~clk_49m), + .ce(E), + .rst(~reset), + .rw(mc6809e_rw), + .addr(mc6809e_A), + .vma(vma), + .data_in(mc6809e_Din), + .data_out(mc6809e_Dout), + .halt(0), + .irq(~irq), + .firq(~firq), + .nmi(~nmi) +); +`else +mc6809is u12A +( + .CLK(clk_49m), + .fallE_en(E), + .fallQ_en(Q), + .D(mc6809e_Din), + .DOut(mc6809e_Dout), + .ADDR(mc6809e_A), + .RnW(mc6809e_rw), + .AVMA(mc6809e_avma), + .nIRQ(irq), + .nFIRQ(firq), + .nNMI(nmi), + .nHALT(~pause), + .nRESET(reset), + .nDMABREQ(1) +); +reg vma; +always @(posedge clk_49m) if (E) vma <= mc6809e_avma; +`endif + +//Address decoding for MC6809E +wire cs_dip2 = ~n_iocs & (mc6809e_A[10:8] == 3'b001) & mc6809e_rw; +wire cs_dip3 = ~n_iocs & (mc6809e_A[10:8] == 3'b010) & mc6809e_rw; +wire cs_palettelatch = ~n_iocs & (mc6809e_A[10:8] == 3'b000) & ~mc6809e_rw; +wire cs_soundlatch = ~n_iocs & (mc6809e_A[10:8] == 3'b001) & ~mc6809e_rw; +wire cs_controls_dip1 = ~n_iocs & (mc6809e_A[10:8] == 3'b011) & mc6809e_rw; +wire cs_k005849 = (mc6809e_A[15:14] == 2'b00); +wire cs_rom1 = (mc6809e_A[15:14] == 2'b01 || mc6809e_A[15:14] == 2'b10) & mc6809e_rw; +wire cs_rom2 = (mc6809e_A[15:14] == 2'b11) & mc6809e_rw; +//Multiplex data inputs to MC6809E +wire [7:0] mc6809e_Din = cs_dip2 ? dipsw[15:8]: + cs_dip3 ? {4'hF, dipsw[19:16]}: + cs_controls_dip1 ? controls_dip1: + (cs_k005849 & n_iocs & mc6809e_rw) ? k005849_D: + cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + 8'hFF; + +//Game ROMs +`ifdef EXT_ROM +always_ff @(negedge clk_49m) + if (|mc6809e_A[15:14] & mc6809e_rw & vma) + main_cpu_rom_addr <= {&mc6809e_A[15:14], ~mc6809e_A[15] & mc6809e_A[14], mc6809e_A[13:0]}; + +wire [7:0] eprom1_D = main_cpu_rom_do; +wire [7:0] eprom2_D = main_cpu_rom_do; +`else +wire [7:0] eprom1_D; +eprom_1 u12C +( + .ADDR(mc6809e_A[14:0]), + .CLK(clk_49m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +wire [7:0] eprom2_D; +eprom_2 u10C +( + .ADDR(mc6809e_A[13:0]), + .CLK(clk_49m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +`endif + +//Palette latch +reg [7:0] pal_latch = 8'd0; +always_ff @(posedge clk_49m) begin + if(!reset) + pal_latch <= 8'd0; + else if(cen_3m) begin + if(cs_palettelatch) + pal_latch <= mc6809e_Dout; + end +end +wire [2:0] palette_bank = pal_latch[6:4]; + +//Sound latch +reg [7:0] sound_data = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && cs_soundlatch) + sound_data <= mc6809e_Dout; +end + +//Sound IRQ trigger +reg sound_irq = 1; +always_ff @(posedge clk_49m) begin + if(cen_3m) begin + if(cs_soundlatch) + sound_irq <= 1; + else + sound_irq <= 0; + end +end + +//Sound CPU - Zilog Z80 (uses T80s variant of the T80 soft core) +wire z80_n_m1, z80_n_mreq, z80_n_iorq, z80_n_rfsh, z80_n_rd, z80_n_wr; +wire [15:0] z80_A; +wire [7:0] z80_Din, z80_Dout; +T80s u7A +( + .RESET_n(reset), + .CLK(clk_49m), + .CEN(cen_sound), + .INT_n(z80_n_int), + .MREQ_n(z80_n_mreq), + .IORQ_n(z80_n_iorq), + .RD_n(z80_n_rd), + .WR_n(z80_n_wr), + .M1_n(z80_n_m1), + .RFSH_n(z80_n_rfsh), + .A(z80_A), + .DI(z80_Din), + .DO(z80_Dout) +); +//Address decoding for data inputs to Z80 +wire z80_decode_en = (z80_n_rfsh & ~z80_n_mreq); +wire soundrom_cs = z80_decode_en & (z80_A[15:14] == 2'b00); +wire soundram_cs = z80_decode_en & (z80_A[15:14] == 2'b01); +wire sounddata_cs = z80_decode_en & (z80_A[15:14] == 2'b10); +//Multiplex data inputs to Z80 +assign z80_Din = soundrom_cs ? eprom3_D: + (soundram_cs & ~z80_n_rd) ? soundram_D: + sounddata_cs ? sound_data: + (~z80_n_iorq & ~z80_n_rd) ? ym2203_D: + 8'hFF; + +//Sound ROM +`ifdef EXT_ROM +wire [7:0] eprom3_D = sub_cpu_rom_do; +always_ff @(posedge clk_49m) + if (soundrom_cs) sub_cpu_rom_addr <= z80_A[13:0]; +`else +wire [7:0] eprom3_D; +eprom_3 u8C +( + .ADDR(z80_A[13:0]), + .CLK(clk_49m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +`endif + +//Sound RAM +wire [7:0] soundram_D; +spram #(8, 11) u9C +( + .clk(clk_49m), + .we(soundram_cs & ~z80_n_wr), + .addr(z80_A[10:0]), + .data(z80_Dout), + .q(soundram_D) +); + +//Generate sound IRQ +wire sirq_clr = (~reset | ~(z80_n_m1 | z80_n_iorq)); +reg z80_n_int = 1; +always_ff @(posedge clk_49m or posedge sirq_clr) begin + if(sirq_clr) + z80_n_int <= 1; + else if(cen_sound && sound_irq) + z80_n_int <= 0; +end + + +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Multiplex player inputs and DIP switch bank 1 +wire [7:0] controls_dip1 = (mc6809e_A[1:0] == 2'b00) ? {3'b111, btn_start, btn_service, coin}: + (mc6809e_A[1:0] == 2'b01) ? {3'b111, p1_fire, p1_joystick}: + (mc6809e_A[1:0] == 2'b10) ? {3'b111, p2_fire, p2_joystick}: + (mc6809e_A[1:0] == 2'b11) ? dipsw[7:0]: + 8'hFF; + +//--------------------------------------------------- Video timing & graphics --------------------------------------------------// + +//Konami 005849 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Scooter Shooter's critical +//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites +wire [15:0] spriterom_A; +wire [15:0] tilerom_A; +wire [7:0] k005849_D, tilemap_lut_A, sprite_lut_A; +wire [4:0] color_A; +wire [1:0] h_cnt; +wire n_iocs, irq, firq, nmi; +k005849 u8E +( + .CK49(clk_49m), + .RES(reset), + .READ(~mc6809e_rw), + .A(mc6809e_A[13:0]), + .DBi(mc6809e_Dout), + .DBo(k005849_D), + .VCF(tilemap_lut_A[7:4]), + .VCB(tilemap_lut_A[3:0]), + .VCD(tilemap_lut_D), + .OCF(sprite_lut_A[7:4]), + .OCB(sprite_lut_A[3:0]), + .OCD(sprite_lut_D), + .COL(color_A), + .XCS(~cs_k005849), + .BUSE(0), + .SYNC(video_csync), + .HSYC(video_hsync), + .VSYC(video_vsync), + .HBLK(video_hblank), + .VBLK(video_vblank), + .FIRQ(firq), + .IRQ(irq), + .NMI(nmi), + .IOCS(n_iocs), + .R(tilerom_A), + .S(spriterom_A), + .S_req(sp1_req), + .S_ack(sp1_ack), + .RD(eprom4_D), + .SD(spriterom_D), + .HCTR(h_center), + .VCTR(v_center), + .SPFL(1), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_write(hs_access_write) +); + +//Graphics ROMs +`ifdef EXT_ROM +assign sp1_rom_addr = spriterom_A[15:0]; +wire [7:0] spriterom_D = spriterom_A[0] ? sp1_rom_do[15:8] : sp1_rom_do[7:0]; +assign char1_rom_addr = {tilerom_A[15], tilerom_A[13:1]}; +wire [7:0] eprom4_D = tilerom_A[0] ? char1_rom_do[15:8] : char1_rom_do[7:0]; +`else +wire [7:0] eprom4_D; +eprom_4 u5F +( + .ADDR({tilerom_A[15], tilerom_A[13:0]}), + .CLK(clk_49m), + .DATA(eprom4_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); +wire [7:0] eprom5_D, eprom6_D; + +eprom_5 u6F +( + .ADDR(spriterom_A[14:0]), + .CLK(~clk_49m), + .DATA(eprom5_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); + +eprom_6 u4F +( + .ADDR(spriterom_A[14:0]), + .CLK(~clk_49m), + .DATA(eprom6_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep6_cs_i), + .WR(ioctl_wr) +); + +//Multiplex sprite ROMs +wire [7:0] spriterom_D = spriterom_A[15] ? eprom6_D : eprom5_D; +`endif + +//Tilemap LUT PROM +wire [3:0] tilemap_lut_D; +tile_lut_prom u7F +( + .ADDR(tilemap_lut_A), + .CLK(clk_49m), + .DATA(tilemap_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(tl_cs_i), + .WR(ioctl_wr) +); + +//Sprite LUT PROM +wire [3:0] sprite_lut_D; +sprite_lut_prom u8F +( + .ADDR(sprite_lut_A), + .CLK(clk_49m), + .DATA(sprite_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(sl_cs_i), + .WR(ioctl_wr) +); + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Select whether to use a fractional or integer clock divider for the YM2203 to maintain consistent sound pitch at both original +//and underclocked timings +wire cen_sound = underclock ? cen_3m_adjust : cen_3m; + +//Sound chip (Yamaha YM2203 - uses JT03 implementation by Jotego) +wire [2:0] filter_en; +wire [7:0] ym2203_D; +wire [7:0] ym2203_ssgA_raw, ym2203_ssgB_raw, ym2203_ssgC_raw; +wire signed [15:0] ym2203_fm_raw; + +jt03 u4D +( + .rst(~reset), + .clk(clk_49m), + .cen(cen_sound), + .din(z80_Dout), + .dout(ym2203_D), + .IOA_out({5'bZZZZZ, filter_en}), + .addr(z80_A[0]), + .cs_n(z80_n_iorq), + .wr_n(z80_n_wr), + .psg_A(ym2203_ssgA_raw), + .psg_B(ym2203_ssgB_raw), + .psg_C(ym2203_ssgC_raw), + .fm_snd(ym2203_fm_raw) +); + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Scooter Shooter's final video output consists of three PROMs, one per color, addressed by the 005849 custom tilemap generator +//and palette latch +color_prom_1 u1F +( + .ADDR({color_A[4], palette_bank, color_A[3:0]}), + .CLK(clk_49m), + .DATA(video_r), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(cp1_cs_i), + .WR(ioctl_wr) +); +color_prom_2 u2F +( + .ADDR({color_A[4], palette_bank, color_A[3:0]}), + .CLK(clk_49m), + .DATA(video_g), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(cp2_cs_i), + .WR(ioctl_wr) +); +color_prom_3 u3F +( + .ADDR({color_A[4], palette_bank, color_A[3:0]}), + .CLK(clk_49m), + .DATA(video_b), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(cp3_cs_i), + .WR(ioctl_wr) +); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Scooter Shooter uses a 4.823KHz low-pass filter for the FM side of its YM2203 - filter the audio accordingly here. +wire signed [15:0] ym2203_fm_lpf; +sshooter_fm_lpf lpf_fm +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_fm_raw), + .out(ym2203_fm_lpf) +); + +//Scooter Shooter also uses 3 switchable low-pass filters on the SSG side of its YM2203 with a cutoff frequency of +//723.432Hz (actually closer to 492.130Hz due to internal resistance inside the 74HC4066 handling the filter switching). +//Model the switchable filters here. +wire signed [15:0] ym2203_ssgA_lpf, ym2203_ssgB_lpf, ym2203_ssgC_lpf; +sshooter_ssg_lpf lpf_ssgA +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgA_dcrm), + .out(ym2203_ssgA_lpf) +); +sshooter_ssg_lpf lpf_ssgB +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgB_dcrm), + .out(ym2203_ssgB_lpf) +); +sshooter_ssg_lpf lpf_ssgC +( + .clk(clk_49m), + .reset(~reset), + .in(ym2203_ssgC_dcrm), + .out(ym2203_ssgC_lpf) +); + +//Remove DC offset from SSG outputs and apply gain to prevent losing quiet sounds after low-pass filtering +wire signed [15:0] ym2203_ssgA_dcrm, ym2203_ssgB_dcrm, ym2203_ssgC_dcrm; +jt49_dcrm2 #(16) dcrm_ssgA +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgA_raw, 5'd0}), + .dout(ym2203_ssgA_dcrm) +); +jt49_dcrm2 #(16) dcrm_ssgB +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgB_raw, 5'd0}), + .dout(ym2203_ssgB_dcrm) +); +jt49_dcrm2 #(16) dcrm_ssgC +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, ym2203_ssgC_raw, 5'd0}), + .dout(ym2203_ssgC_dcrm) +); + +//Apply the switchable low-pass filters and attenuate SSG outputs back to raw levels +wire signed [15:0] ym2203_ssgA = filter_en[2] ? ym2203_ssgA_lpf >>> 15'd5 : ym2203_ssgA_dcrm >>> 15'd5; +wire signed [15:0] ym2203_ssgB = filter_en[1] ? ym2203_ssgB_lpf >>> 15'd5 : ym2203_ssgB_dcrm >>> 15'd5; +wire signed [15:0] ym2203_ssgC = filter_en[0] ? ym2203_ssgC_lpf >>> 15'd5 : ym2203_ssgC_dcrm >>> 15'd5; + +//Mix all audio sources for the final output +assign sound = (ym2203_fm_lpf + (ym2203_ssgA * 15'd21) + (ym2203_ssgB * 15'd21) + (ym2203_ssgC * 15'd21)) <<< 15'd1; + +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter_MiST.sv b/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter_MiST.sv new file mode 100644 index 00000000..cbeb58f9 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/ScooterShooter_MiST.sv @@ -0,0 +1,316 @@ +module ScooterShooter_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "SCOTRSHT;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "O1,Pause,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire pause = status[1]; + +wire [1:0] orientation = 2'b11; +wire [23:0] dip_sw = ~status[31:8]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_98; +assign SDRAM_CKE = 1; + +wire clock_98, clock_49, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_98), + .c1(clock_49),//49.152MHz + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_49 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + +wire [15:0] main_rom_addr; +wire [15:0] main_rom_do; +wire [14:0] sub_rom_addr; +wire [15:0] sub_rom_do; +wire [15:1] ch1_addr; +wire [15:0] ch1_do; +wire sp1_req, sp1_ack; +wire [15:0] sp1_addr; +wire [15:0] sp1_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 17'h10000; + +reg port1_req, port2_req; +sdram #(98) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_98 ), + + // port1 for CPUs + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'h0000 : main_rom_addr[15:1] ), + .cpu1_q ( main_rom_do ), + .cpu2_addr ( ioctl_downl ? 16'h0000 : sub_rom_addr[14:1] + 16'h6000 ), + .cpu2_q ( sub_rom_do ), + + // port2 for graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( bg_ioctl_addr[23:1] ), + .port2_ds ( {bg_ioctl_addr[0], ~bg_ioctl_addr[0]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ), + .ch1_q ( ch1_do ), + .sp1_req ( sp1_req ), + .sp1_ack ( sp1_ack ), + .sp1_addr ( ioctl_downl ? 16'hffff : 16'h4000 + sp1_addr[15:1] ), + .sp1_q ( sp1_do ) +); + +// ROM download controller +always @(posedge clock_49) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_49) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +//Instantiate Scooter Shooter top-level module +ScooterShooter ScooterShooter_inst +( + .reset(~reset), // input reset + + .clk_49m(clock_49), // input clk_49m + + .coin({~m_coin2, ~m_coin1}), // input coin + .btn_service(~service), // input btn_service + + .btn_start({~m_two_players, ~m_one_player}), // input [1:0] btn_start + + // The game crashes when two opposite direction controls are held down. + // It's not possible with a physical controller, but it is via keyboard, + // so protect against this here. + .p1_joystick({~m_down | m_up, ~m_up, ~m_right | m_left, ~m_left}), + .p2_joystick({~m_down2 | m_up2, ~m_up2, ~m_right2 | m_left2, ~m_left2}), + .p1_fire(~m_fireA), + .p2_fire(~m_fire2A), + + .dipsw(dip_sw), // input [19:0] dipsw + + //Flag to signal that Scooter Shooter has been underclocked to normalize video timings in order to maintain consistent sound timings and pitch + .underclock(1'b0), + + .sound(audio), // output [15:0] sound + + .h_center(), // Screen centering + .v_center(), + + .video_hsync(hs), // output video_hsync + .video_vsync(vs), // output video_vsync + .video_vblank(vblank), // output video_vblank + .video_hblank(hblank), // output video_hblank + .ce_pix(ce_pix), // output ce_pix + + .video_r(r), // output [2:0] video_r + .video_g(g), // output [2:0] video_g + .video_b(b), // output [1:0] video_b + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(pause), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_write(hs_access_write), + + .main_cpu_rom_addr(main_rom_addr), + .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]), + .sub_cpu_rom_addr(sub_rom_addr), + .sub_cpu_rom_do(sub_rom_addr[0] ? sub_rom_do[15:8] : sub_rom_do[7:0]), + .char1_rom_addr(ch1_addr), + .char1_rom_do(ch1_do), + .sp1_req(sp1_req), + .sp1_ack(sp1_ack), + .sp1_rom_addr(sp1_addr), + .sp1_rom_do(sp1_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +wire audio_out; +assign AUDIO_L = audio_out; +assign AUDIO_R = audio_out; + +dac #(.C_bits(16))dac( + .clk_i(clock_49), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(audio_out) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_49 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/audio_iir_filter.v b/Arcade_MiST/Konami ScooterShooter/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/build_id.tcl b/Arcade_MiST/Konami ScooterShooter/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/dpram_dc.vhd b/Arcade_MiST/Konami ScooterShooter/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/jt49_dcrm2.v b/Arcade_MiST/Konami ScooterShooter/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami ScooterShooter/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/k005849.sv b/Arcade_MiST/Konami ScooterShooter/rtl/k005849.sv new file mode 100644 index 00000000..70458ede --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/k005849.sv @@ -0,0 +1,670 @@ +//============================================================================ +// +// SystemVerilog implementation of the Konami 005849 custom tilemap +// generator +// Adapted from Green Beret core Copyright (C) 2013, 2019 MiSTer-X +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Note: This model of the 005849 cannot be used to replace an original 005849. + +module k005849 +( + input CK49, //49.152MHz clock input + output NCK2, //6.144MHz clock output + output X1S, //3.072MHz clock output + output H2, //1.576MHz clock output + output ER, //E clock for MC6809E + output QR, //Q clock for MC6809E + output EQ, //AND of E and Q clocks for MC6809E + input RES, //Reset input (actually an output on the original chip - active low) + input READ, //Read enable (active low) + input [13:0] A, //Address bus from CPU + input [7:0] DBi, //Data bus input from CPU + output [7:0] DBo, //Data output to CPU + output [3:0] VCF, //Color address to tilemap LUT PROM + output [3:0] VCB, //Tile index to tilemap LUT PROM + input [3:0] VCD, //Data input from tilemap LUT PROM + output [3:0] OCF, //Color address to sprite LUT PROM + output [3:0] OCB, //Sprite index to sprite LUT PROM + input [3:0] OCD, //Data input from sprite LUT PROM + output [4:0] COL, //Color data output from color mixer + input XCS, //Chip select (active low) + input BUSE, //Data bus enable (active low) + output SYNC, //Composite sync (active low) + output HSYC, //HSync (active low) - Not exposed on the original chip + output VSYC, //VSync (active low) + output HBLK, //HBlank (active high) - Not exposed on the original chip + output VBLK, //VBlank (active high) - Not exposed on the original chip + output FIRQ, //Fast IRQ output + output IRQ, //VBlank IRQ + output NMI, //Non-maskable IRQ + output IOCS, //I/O decoder enable (active low) + output CS80, //Chip select output for Konami 501 custom chip (active low) + + //Split sprite/tile busses + output reg [15:0] R, //Address output to graphics ROMs (tiles) + output [15:0] S, //Address output to graphics ROMs (sprites) + output reg S_req = 0, + input S_ack, + input [7:0] RD, //Tilemap ROM data + input [7:0] SD, //Sprite ROM data + + //Extra input for flipping the sprite bank bit (active low) + input SPFL, + + //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] HCTR, VCTR, + + //MiSTer high score system I/O + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_write +); + + + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Generate IOCS output (active low) +assign IOCS = ~(~XCS & (A[13:12] == 2'b11)); + +//Generate chip enable for Konami 501 (active low) +assign CS80 = XCS; + +//Data output to CPU +assign DBo = BUSE ? 8'hFF: + cs_regs ? regs: + zram0_cs ? zram0_Dout: + zram1_cs ? zram1_Dout: + tileram_attrib_cs ? tileram_attrib_Dout: + tileram_code_cs ? tileram_code_Dout: + spriteram_cs ? spriteram_Dout: + 8'hFF; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz +reg [4:0] div = 4'd0; +always_ff @(posedge CK49) begin + div <= div + 4'd1; +end +wire cen_6m = !div[2:0]; +assign NCK2 = div[2]; +assign X1S = h_cnt[0]; +assign H2 = h_cnt[1]; + +//The MC6809E requires two identical clocks with a 90-degree offset - assign these here +reg mc6809e_E = 0; +reg mc6809e_Q = 0; +always_ff @(posedge CK49) begin + reg [1:0] clk_phase = 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b00: mc6809e_E <= 0; + 2'b01: mc6809e_Q <= 1; + 2'b10: mc6809e_E <= 1; + 2'b11: mc6809e_Q <= 0; + endcase + end +end +assign QR = mc6809e_Q; +assign ER = mc6809e_E; + +//Output EQ combines ER and QR together via an AND gate - assign this here +assign EQ = ER & QR; + +//-------------------------------------------------------- Video timings -------------------------------------------------------// + +//The horizontal and vertical counters are 9 bits wide - delcare them here +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter +//rolls over +reg hblank = 0; +reg vblank = 0; + +reg frame_odd_even = 0; +reg hmask = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + case(h_cnt) + 5: begin + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + 13: begin + hmask <= 0; + h_cnt <= h_cnt + 9'd1; + end + //Blank the left-most and right-most 8 lines when the 005849's horizontal mask register bit + //(register 3 bit 7) is active + 253: begin + if(hmask_en) + hmask <= 1; + h_cnt <= h_cnt + 9'd1; + end + 261: begin + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 383: begin + h_cnt <= 0; + case(v_cnt) + 15: begin + vblank <= 0; + v_cnt <= v_cnt + 9'd1; + end + 239: begin + vblank <= 1; + frame_odd_even <= ~frame_odd_even; + v_cnt <= v_cnt + 9'd1; + end + 263: begin + v_cnt <= 9'd0; + end + default: v_cnt <= v_cnt + 9'd1; + endcase + end + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Output HBlank and VBlank (both active high) +assign HBLK = hblank; +assign VBLK = vblank; + +//Generate horizontal sync and vertical sync (both active low) +assign HSYC = HCTR[3] ? ~(h_cnt >= 285 - ~HCTR[2:0] && h_cnt <= 316 - ~HCTR[2:0]) : ~(h_cnt >= 293 + HCTR[2:0] && h_cnt <= 324 + HCTR[2:0]); +assign VSYC = ~(v_cnt >= 254 - VCTR && v_cnt <= 261 - VCTR); +assign SYNC = HSYC ^ VSYC; + +//------------------------------------------------------------- IRQs -----------------------------------------------------------// +//Edge detection for VBlank and vertical counter bit 5 for IRQ generation +reg old_vblank, old_vcnt5; +always_ff @(posedge CK49) begin + old_vcnt5 <= v_cnt[5]; + old_vblank <= vblank; +end + +//IRQ (triggers every VBlank) +reg vblank_irq = 1; +always_ff @(posedge CK49) begin + if(!RES || !irq_mask) + vblank_irq <= 1; + else if(!old_vblank && vblank) + vblank_irq <= 0; +end + +assign IRQ = vblank_irq; + +//NMI (triggers every 32 scanlines) +reg nmi = 1; +always_ff @(posedge CK49) begin + if(!RES || !nmi_mask) + nmi <= 1; + else begin + if(old_vcnt5 && !v_cnt[5]) + nmi <= 0; + end +end +assign NMI = nmi; + +//FIRQ (triggers every second VBlank) +reg firq = 1; +always_ff @(posedge CK49) begin + if(!RES || !firq_mask) + firq <= 1; + else begin + if(frame_odd_even && !old_vblank && vblank) + firq <= 0; + end +end +assign FIRQ = firq; + +//----------------------------------------------------- Internal registers -----------------------------------------------------// + +//The 005849 has five 8-bit registers - handle these here +wire cs_regs = ~XCS & (A[13:12] == 2'b10) & (A[7:3] == 5'b01000); +reg [7:0] reg0, reg1, reg2, reg3, reg4; +//Write to the appropriate register +always_ff @(posedge CK49) begin + if(cs_regs && READ) begin + case(A[2:0]) + 3'b000: reg0 <= DBi; + 3'b001: reg1 <= DBi; + 3'b010: reg2 <= DBi; + 3'b011: reg3 <= DBi; + 3'b100: reg4 <= DBi; + default:; + endcase + end +end + +//Assign ZRAM scroll direction as bit 2 of register 2 +wire zram_scroll_dir = reg2[2]; + +//Assign tilemap bank as bit 0 of register 3 +wire tilemap_bank = reg3[0]; + +//Assign tile priority override as bit 6 of register 3 (this is used by Jailbreak to give full priority to sprites and override +//the layer priority set by bit 7 of the tilemap attribute) +wire tile_priority_override = reg3[6]; + +//Assign horizontal mask enable as bit 7 of register 3 (this bit, when enabled, masks the left-most and right-most 8 columns to +//reduce the active area from 256x224 to 240x224 +wire hmask_en = reg3[7]; + +//Assign IRQ masks and flipscreen from the lower 4 bits of register 4 +wire nmi_mask = reg4[0]; +wire irq_mask = reg4[1]; +wire firq_mask = reg4[2]; +wire flipscreen = reg4[3]; + +wire [7:0] regs = (A == 14'h2040) ? reg0: + (A == 14'h2041) ? reg1: + (A == 14'h2042) ? reg2: + (A == 14'h2043) ? reg3: + 8'hFF; + +//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------// + +wire zram0_cs = ~XCS & (A[13:12] == 2'b10) & (A[7:0] >= 8'h00 && A[7:0] <= 8'h1F); +wire zram1_cs = ~XCS & (A[13:12] == 2'b10) & (A[7:0] >= 8'h20 && A[7:0] <= 8'h3F); + +//Address ZRAM with bits [7:3] of the tilemap horizontal or vertical position depending on whether line scroll or column scroll +//is in use +wire [4:0] zram_A = zram_scroll_dir ? tilemap_hpos[7:3] : tilemap_vpos[7:3]; +wire [7:0] zram0_D, zram1_D, zram0_Dout, zram1_Dout; +dpram_dc #(.widthad_a(5)) ZRAM0 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram0_Dout), + .wren_a(zram0_cs & READ), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram0_D) +); +dpram_dc #(.widthad_a(5)) ZRAM1 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram1_Dout), + .wren_a(zram1_cs & READ), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram1_D) +); + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//VRAM is external to the 005849 and combines multiple banks into a single 8KB RAM chip for tile attributes and data, and two sprite +//banks. For simplicity, this RAM has been made internal to the 005849 implementation and split into its constituent components. +wire tileram_attrib_cs = ~XCS & (A[13:11] == 3'b000); +wire tileram_code_cs = ~XCS & (A[13:11] == 3'b001); +wire spriteram_cs = ~XCS & (A[13:12] == 2'b01); + +wire [7:0] tileram_attrib_Dout, tileram_code_Dout, spriteram_Dout, tileram_attrib_D, tileram_code_D, spriteram_D; +//Tilemap +dpram_dc #(.widthad_a(11)) VRAM_TILEATTRIB +( + .clock_a(CK49), + .address_a(A[10:0]), + .data_a(DBi), + .q_a(tileram_attrib_Dout), + .wren_a(tileram_attrib_cs & READ), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tileram_attrib_D) +); +dpram_dc #(.widthad_a(11)) VRAM_TILECODE +( + .clock_a(CK49), + .address_a(A[10:0]), + .data_a(DBi), + .q_a(tileram_code_Dout), + .wren_a(tileram_code_cs & READ), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tileram_code_D) +); + +`ifndef MISTER_HISCORE +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(A[11:0]), + .data_a(DBi), + .q_a(spriteram_Dout), + .wren_a(spriteram_cs & READ), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +`else +// Hiscore mux (this is only to be used with Jailbreak as its high scores are stored in sprite RAM) +// - Mirrored sprite RAM used to protect against corruption while retrieving highscore data +wire [11:0] VRAM_SPR_AD = hs_access_write ? hs_address : A[11:0]; +wire [7:0] VRAM_SPR_DIN = hs_access_write ? hs_data_in : DBi; +wire VRAM_SPR_WE = hs_access_write ? hs_write_enable : (spriteram_cs & READ); +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .q_a(spriteram_Dout), + .wren_a(VRAM_SPR_WE), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +//Sprite RAM shadow for highscore read access +dpram_dc #(.widthad_a(12)) VRAM_SPR_SHADOW +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .wren_a(VRAM_SPR_WE), + + .clock_b(CK49), + .address_b(hs_address), + .q_b(hs_data_out) +); +`endif + + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//**The following code is the original tilemap renderer from MiSTerX's Green Beret core with some minor tweaks**// +//XOR horizontal and vertical counter bits with flipscreen bit +wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}}; +wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}}; + +//Generate tilemap position - horizontal position is the sum of the horizontal counter, vertical position is the vertical counter +// +wire [8:0] tilemap_hpos = {h_cnt[8], hcnt_x[7:0]} + (~zram_scroll_dir ? {zram1_D[0], zram0_D} : 9'd0); +wire [8:0] tilemap_vpos = vcnt_x + (zram_scroll_dir ? {zram1_D[0], zram0_D} : 9'd0); + +//Address output to tile section of VRAM +wire [10:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[8:3]}; + +//Tile index is a combination of the tilemap bank bit from the 005849's internal registers, attribute bits [7:6] and the actual +//tile code +wire [10:0] tile_index = {tilemap_bank, tileram_attrib_D[7:6], tileram_code_D}; + +//Tile color is held in the lower 4 bits of tileram attributes +wire [3:0] tile_color = tileram_attrib_D[3:0]; +reg [3:0] tile_color_r, tile_color_rr; +reg tile_attrib7_r, tile_attrib7_rr; +reg tile_hflip_r; +reg [7:0] RD_r; + +//Tile flip attributes are stored in bits 4 (horizontal) and 5 (vertical) +wire tile_hflip = tileram_attrib_D[4]; +wire tile_vflip = tileram_attrib_D[5]; + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if (h_cnt[0]) begin + //Assign address outputs to tile ROM + R <= {tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2:1] ^ {2{tile_hflip}})}; + // Apply appropriate delay to flags + tile_hflip_r <= tile_hflip; + tile_color_r <= tile_color; + tile_color_rr <= tile_color_r; + tile_attrib7_r <= tileram_attrib_D[7]; + tile_attrib7_rr <= tile_attrib7_r; + RD_r <= RD; + end + end +end + +//Multiplex tilemap ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_r) ? RD_r[3:0] : RD_r[7:4]; + +//Retrieve tilemap select bit from the NOR of bit 7 of the tile attributes with the priority override bit +reg tilemap_en = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + tilemap_en <= ~(tile_attrib7_rr | tile_priority_override); + end +end + +//Address output to tilemap LUT PROM +assign VCF = tile_color_rr; +assign VCB = tile_pixel; + +//Delay tilemap data by one horizontal line +reg [3:0] tilemap_D = 4'd0; +always_ff @(posedge CK49) begin + if(cen_6m) + tilemap_D <= VCD; +end + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//The following code is the original sprite renderer from MiSTerX's Green Beret core with additional screen flipping support and +//some extra tweaks + +//Generate sprite position - horizontal position is the horizontal counter, vertical position is the vertical counter (offset by +//18, 17 when flipped, to properly position the sprite layer) +wire [8:0] sprite_hpos = h_cnt; +wire [8:0] sprite_vpos = flipscreen ? v_cnt + 9'd17 : v_cnt + 9'd18; + +//Sprite state machine +reg [5:0] sprite_index; +reg [1:0] sprite_offset; +reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3; +reg [2:0] sprite_fsm_state; +always_ff @(posedge CK49) begin + if(sprite_hpos == 9'd0) begin + xcnt <= 0; + sprite_index <= 0; + sprite_offset <= 3; + sprite_fsm_state <= 1; + end + else + case(sprite_fsm_state) + 0: /* empty */ ; + 1: begin + if(sprite_index > 8'd47) //Render up to 48 sprites at once (index 0 - 47) + sprite_fsm_state <= 0; + //When the sprite Y attribute is set to 0, skip the current sprite, otherwise obtain the sprite Y attribute + //and scan out the other sprite attributes + else begin + if(hy) begin + sprite_attrib3 <= spriteram_D; + sprite_offset <= 2; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + else sprite_index <= sprite_index + 6'd1; + end + end + 2: begin + sprite_attrib2 <= spriteram_D; + sprite_offset <= 1; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 3: begin + sprite_attrib1 <= spriteram_D; + sprite_offset <= 0; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 4: begin + sprite_attrib0 <= spriteram_D; + sprite_offset <= 3; + sprite_index <= sprite_index + 6'd1; + xcnt <= 5'b10000; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + S_req <= !S_req; + end + 5: if (S_req == S_ack) begin + xcnt <= xcnt + 5'd1; + sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1; + S_req <= (wre & xcnt[0]) ? !S_req : S_req; + end + default:; + endcase +end + +//Subtract sprite attribute byte 2 with bit 7 of sprite attribute byte 1 to obtain sprite X position and XOR with the +//flipscreen bit +wire [8:0] sprite_x = ({1'b0, sprite_attrib2} - {sprite_attrib1[7], 8'h00}) ^ {9{flipscreen}}; + +//If the sprite state machine is in state 1, obtain sprite Y position directly from sprite RAM, otherwise obtain it from +//sprite attribute byte 3 and XOR with the flipscreen bit +wire [7:0] sprite_y = (sprite_fsm_state == 3'd1) ? spriteram_D ^ {8{flipscreen}} : sprite_attrib3 ^ {8{flipscreen}}; + +//Sprite flip attributes are stored in bits 4 (horizontal) and 5 (vertical) of sprite attribute byte 1 +wire sprite_hflip = sprite_attrib1[4] ^ flipscreen; +wire sprite_vflip = sprite_attrib1[5] ^ flipscreen; + +//Sprite code is bit 6 of sprite attribute byte 1 appended to sprite attribute byte 0 +wire [8:0] sprite_code = {sprite_attrib1[6], sprite_attrib0}; + +//Sprite color is the lower 4 bits of sprite attribute byte 1 +wire [3:0] sprite_color = sprite_attrib1[3:0]; + +wire [8:0] ht = {1'b0, sprite_y} - sprite_vpos; +wire hy = (sprite_y != 0) & (ht[8:5] == 4'b1111) & (ht[4] ^ ~flipscreen); + +reg [4:0] xcnt; +wire [3:0] lx = xcnt[3:0] ^ {4{sprite_hflip}}; +wire [3:0] ly = ht[3:0] ^ {4{~sprite_vflip}}; + +//Assign address outputs to sprite ROMs +assign S = {sprite_code, ly[3], lx[3], ly[2:0], lx[2:1]}; + +//Multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4]; + +//Latch the sprite bank from bit 3 of register 3 on the rising edge of VSync and XNOR with the added SPFL signal to flip this bit +//for Green Beret +//TODO: Find the actual internal register bit (if any) on the 005849 to properly handle this +reg sprite_bank = 0; +reg old_vsync; +always_ff @(posedge CK49) begin + old_vsync <= VSYC; + if(!VSYC) + sprite_bank <= 0; + else if(!old_vsync && VSYC) + sprite_bank <= ~(reg3[3] ^ SPFL); +end + +wire [11:0] spriteram_A = {3'b000, sprite_bank, sprite_index, sprite_offset}; + +//Address output to sprite LUT PROM +assign OCF = sprite_color; +assign OCB = sprite_pixel; + +//----------------------------------------------------- Sprite line buffer -----------------------------------------------------// + +//The sprite line buffer is external to the 005849 and consists of four 4416 DRAM chips. For simplicity, both the logic for the +//sprite line buffer and the sprite line buffer itself has been made internal to the 005849 implementation. + +//Enable writing to sprite line buffer when bit 4 of xcnt is 1 +wire wre = xcnt[4]; + +//Set sprite ID as bit 0 of the sprite vertical position +wire sprite_id = sprite_vpos[0]; + +//Sum sprite X position with the lower 4 bits of xcnt to address the sprite line buffer +wire [8:0] wpx = sprite_x + xcnt[3:0]; + +//Generate sprite line buffer write addresses +reg [9:0] lbuff_A; +reg lbuff_we; +wire [3:0] lbuff_Din = OCD; + +always_ff @(posedge CK49) begin + lbuff_A <= {~sprite_id, wpx}; + lbuff_we <= wre & S_req == S_ack; +end + +//Generate read address for sprite line buffer on the rising edge of the pixel clock +reg [9:0] radr0 = 10'd0; +reg [9:0] radr1 = 10'd1; +always_ff @(posedge CK49) begin + if(cen_6m) + radr0 <= {sprite_id, flipscreen ? sprite_hpos - 9'd241 : sprite_hpos}; +end + +//Sprite line buffer +wire [3:0] lbuff_Dout; +dpram_dc #(.widthad_a(10)) LBUFF +( + .clock_a(CK49), + .address_a(lbuff_A), + .data_a({4'd0, lbuff_Din}), + .wren_a(lbuff_we & (lbuff_Din != 0)), + + .clock_b(CK49), + .address_b(radr0), + .data_b(8'h0), + .wren_b(radr0 == radr1), + .q_b({4'bZZZZ, lbuff_Dout}) +); + +//Latch sprite data from the sprite line buffer +wire lbuff_read_en = (div[2:0] == 3'b100); +reg [3:0] sprite_D = 4'd0; +always_ff @(posedge CK49) begin + if(lbuff_read_en) begin + if(radr0 != radr1) + sprite_D <= lbuff_Dout; + radr1 <= radr0; + end +end + +//--------------------------------------------------------- Color mixer --------------------------------------------------------// + +//Multiplex tile and sprite data, then output the final result +wire tile_sprite_sel = (tilemap_en | ~(|sprite_D)); +wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D; + +//Latch and output pixel data +reg [4:0] pixel_D; +always_ff @(posedge CK49) begin + if(cen_6m) + pixel_D <= {tile_sprite_sel, tile_sprite_D}; +end +//If the horizontal mask is active, black out the left-most and right-most 8 columns to limit the display area to 240x224, otherwise +//output the full 256x224 +assign COL = hmask ? 5'd0 : pixel_D; + +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/pll.qip b/Arcade_MiST/Konami ScooterShooter/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/pll.v b/Arcade_MiST/Konami ScooterShooter/rtl/pll.v new file mode 100644 index 00000000..1960b7f8 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 105, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 382, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 105, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 191, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/rom_loader.sv b/Arcade_MiST/Konami ScooterShooter/rtl/rom_loader.sv new file mode 100644 index 00000000..5e1c2907 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/rom_loader.sv @@ -0,0 +1,344 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019, 2020 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Scooter Shooter: +// 0x0000 - 0x3FFF = eprom_1 +// 0x4000 - 0x7FFF = eprom_2 +// 0x8000 - 0xBFFF = eprom_3 +// 0xC000 - 0xFFFF = eprom_4 +// 0x10000 - 0x13FFF = eprom_5 +// 0x14000 - 0x17FFF = eprom_6 +// 0x18000 - 0x1BFFF = eprom_7 +// 0x1C000 - 0x1FFFF = eprom_8 +// 0x20000 - 0x23FFF = eprom_9 +// 0x24000 - 0x240FF = sprite_lut_prom +// 0x24100 - 0x241FF = tile_lut_prom +// 0x24200 - 0x2421F = color_prom_1 +// 0x24220 - 0x2423F = color_prom_2 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, cp1_cs, cp2_cs, cp3_cs, tl_cs, sl_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, cp1_cs, cp2_cs, cp3_cs, tl_cs, sl_cs} = 0; + if(ioctl_addr < 'h8000) + ep1_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'hC000) + ep2_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h10000) + ep3_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h18000) + ep4_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h20000) + ep5_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28000) + ep6_cs = 1; // 0x8000 15 + else if(ioctl_addr < 'h28100) + cp1_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h28200) + cp2_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h28300) + cp3_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h28400) + tl_cs = 1; // 0x100 8 + else + sl_cs = 1; // 0x100 8 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_4 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_5 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_6 +( + input logic CLK, + input logic CLK_DL, + input logic [14:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(15)) eprom_6 + ( + .clock_a(CLK), + .address_a(ADDR[14:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[14:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module color_prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) color_prom_1 + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) color_prom_2 + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) color_prom_3 + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module tile_lut_prom +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) tile_lut_prom + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module sprite_lut_prom +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) sprite_lut_prom + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/sdram.sv b/Arcade_MiST/Konami ScooterShooter/rtl/sdram.sv new file mode 100644 index 00000000..328e7e58 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/sdram.sv @@ -0,0 +1,347 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [15:1] cpu1_addr, + output reg [15:0] cpu1_q, + input [15:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [15:0] port2_q, + input [15:1] ch1_addr, + output reg [15:0] ch1_q, + input sp1_req, + input [16:1] sp1_addr, + output reg [15:0] sp1_q, + output reg sp1_ack +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 + 1 ras0 + 2 data1 returned + 3 CAS0 + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [15:1] addr_last[4]; +reg [16:1] addr_last2[4]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CPU2 = 2'd2; +localparam PORT_CH1 = 2'd1; +localparam PORT_SP1 = 2'd2; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 9'd0, cpu1_addr }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 9'd0, cpu2_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (ch1_addr != addr_last2[PORT_CH1]) begin + next_port[1] = PORT_CH1; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b000, ch1_addr }; + end else if (sp1_req != sp1_ack) begin + next_port[1] = PORT_SP1; + addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, sp1_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][15:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][16:1]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end + PORT_CH1 : ch1_q <= sd_din; + PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end + default: ; + endcase; + end + + end +end + +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/spram.vhd b/Arcade_MiST/Konami ScooterShooter/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl; diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_fm_lpf.sv b/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_fm_lpf.sv new file mode 100644 index 00000000..84759c87 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_fm_lpf.sv @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to low-pass filter the FM part of the YM2203 on Scooter Shooter. + +module sshooter_fm_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 128; //Sample at 49.152MHz/128 = 384000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.037979203, 0.037979203 + //1.0000000, -0.92404159 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd30278; + B1 = 18'd1245; + B2 = 18'd1245; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_ssg_lpf.sv b/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_ssg_lpf.sv new file mode 100644 index 00000000..64db75b4 --- /dev/null +++ b/Arcade_MiST/Konami ScooterShooter/rtl/sshooter_ssg_lpf.sv @@ -0,0 +1,61 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned for the switchable low-pass filters the SSG part of the YM2203 on +//Scooter Shooter. + +module sshooter_ssg_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 49.152MHz/96 = 192000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.0079883055, 0.0079883055 + //1.0000000, -0.98402339 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd32244; + B1 = 18'd262; + B2 = 18'd262; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule From 4eea204e63b9a1b0e31d23bf2ef3e81a04f83d83 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sun, 2 Jan 2022 21:27:16 +0100 Subject: [PATCH 6/7] Konami Jailbreak --- Arcade_MiST/Konami Jailbreak/Jailbrek.qpf | 31 + Arcade_MiST/Konami Jailbreak/Jailbrek.qsf | 261 ++ Arcade_MiST/Konami Jailbreak/Jailbrek.sdc | 134 + Arcade_MiST/Konami Jailbreak/README.md | 11 + .../Konami Jailbreak/meta/Jailbreak.mra | 75 + .../meta/Manhattan 24 Bunsyo (J).mra | 75 + Arcade_MiST/Konami Jailbreak/rtl/Jailbreak.sv | 575 ++++ .../Konami Jailbreak/rtl/Jailbreak_MiST.sv | 308 +++ Arcade_MiST/Konami Jailbreak/rtl/KONAMI1.sv | 79 + .../rtl/VLM5030/vlm5030_gl.vhd | 2304 +++++++++++++++++ .../rtl/VLM5030/vlm5030_pack.vhd | 217 ++ .../rtl/VLM5030/vlm5030_subcircuits.vhd | 204 ++ .../Konami Jailbreak/rtl/audio_iir_filter.v | 173 ++ Arcade_MiST/Konami Jailbreak/rtl/build_id.tcl | 35 + Arcade_MiST/Konami Jailbreak/rtl/dpram_dc.vhd | 136 + .../Konami Jailbreak/rtl/jailbreak_psg_lpf.v | 60 + .../rtl/jailbreak_speech_lpf.v | 60 + Arcade_MiST/Konami Jailbreak/rtl/jt49_dcrm2.v | 62 + .../Konami Jailbreak/rtl/jtframe_frac_cen.v | 58 + Arcade_MiST/Konami Jailbreak/rtl/k005849.sv | 670 +++++ Arcade_MiST/Konami Jailbreak/rtl/pll.qip | 4 + Arcade_MiST/Konami Jailbreak/rtl/pll.v | 348 +++ .../Konami Jailbreak/rtl/rom_loader.sv | 398 +++ Arcade_MiST/Konami Jailbreak/rtl/sdram.sv | 347 +++ Arcade_MiST/Konami Jailbreak/rtl/spram.vhd | 46 + 25 files changed, 6671 insertions(+) create mode 100644 Arcade_MiST/Konami Jailbreak/Jailbrek.qpf create mode 100644 Arcade_MiST/Konami Jailbreak/Jailbrek.qsf create mode 100644 Arcade_MiST/Konami Jailbreak/Jailbrek.sdc create mode 100644 Arcade_MiST/Konami Jailbreak/README.md create mode 100755 Arcade_MiST/Konami Jailbreak/meta/Jailbreak.mra create mode 100755 Arcade_MiST/Konami Jailbreak/meta/Manhattan 24 Bunsyo (J).mra create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/Jailbreak.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/Jailbreak_MiST.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/KONAMI1.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_gl.vhd create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_pack.vhd create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_subcircuits.vhd create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/audio_iir_filter.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/build_id.tcl create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/dpram_dc.vhd create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/jailbreak_psg_lpf.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/jailbreak_speech_lpf.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/jt49_dcrm2.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/jtframe_frac_cen.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/k005849.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/pll.qip create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/pll.v create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/rom_loader.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/sdram.sv create mode 100644 Arcade_MiST/Konami Jailbreak/rtl/spram.vhd diff --git a/Arcade_MiST/Konami Jailbreak/Jailbrek.qpf b/Arcade_MiST/Konami Jailbreak/Jailbrek.qpf new file mode 100644 index 00000000..f5c5c98b --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/Jailbrek.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 00:21:03 December 03, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "00:21:03 December 03, 2019" + +# Revisions + +PROJECT_REVISION = "Jailbrek" + diff --git a/Arcade_MiST/Konami Jailbreak/Jailbrek.qsf b/Arcade_MiST/Konami Jailbreak/Jailbrek.qsf new file mode 100644 index 00000000..0c7d3935 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/Jailbrek.qsf @@ -0,0 +1,261 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.4 Build 182 03/12/2014 SJ Full Version +# Date created = 19:54:12 November 22, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Jailbrek_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" + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY Jailbreak_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/jailbrk.stp + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# ------------------------------ +# start ENTITY(Finalizer_MiST) + + # Pin & Location Assignments + # ========================== + + # Fitter Assignments + # ================== + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(Finalizer_MiST) +# ---------------------------- +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name VERILOG_MACRO "EXT_ROM=" +set_global_assignment -name FORCE_SYNCH_CLEAR ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jailbreak_MiST.sv +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/k005849.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom_loader.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/KONAMI1.sv +set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v +set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/Jailbreak.sv +set_global_assignment -name VHDL_FILE rtl/dpram_dc.vhd +set_global_assignment -name VERILOG_FILE rtl/audio_iir_filter.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/jailbreak_speech_lpf.v +set_global_assignment -name VERILOG_FILE rtl/jailbreak_psg_lpf.v +set_global_assignment -name VHDL_FILE rtl/VLM5030/vlm5030_subcircuits.vhd +set_global_assignment -name VHDL_FILE rtl/VLM5030/vlm5030_pack.vhd +set_global_assignment -name VHDL_FILE rtl/VLM5030/vlm5030_gl.vhd +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name QIP_FILE ../../common/mist/mist.qip +set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v +set_global_assignment -name QIP_FILE ../../common/Sound/sn76489/sn76489.qip +set_global_assignment -name SIGNALTAP_FILE output_files/sdram.stp +set_global_assignment -name SIGNALTAP_FILE output_files/tm.stp +set_global_assignment -name SIGNALTAP_FILE output_files/jailbrk.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/Jailbrek.sdc b/Arcade_MiST/Konami Jailbreak/Jailbrek.sdc new file mode 100644 index 00000000..4a373c09 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/Jailbrek.sdc @@ -0,0 +1,134 @@ +## Generated SDC file "vectrex_MiST.out.sdc" + +## Copyright (C) 1991-2013 Altera Corporation +## Your use of Altera Corporation's design tools, logic functions +## and other software and tools, and its AMPP partner logic +## functions, and any output files from any of the foregoing +## (including device programming or simulation files), and any +## associated documentation or information are expressly subject +## to the terms and conditions of the Altera Program License +## Subscription Agreement, Altera MegaCore Function License +## Agreement, or other applicable license agreement, including, +## without limitation, that your use is for the sole purpose of +## programming logic devices manufactured by Altera and sold by +## Altera or its authorized distributors. Please refer to the +## applicable agreement for further details. + + +## VENDOR "Altera" +## PROGRAM "Quartus II" +## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition" + +## DATE "Sun Jun 24 12:53:00 2018" + +## +## DEVICE "EP3C25E144C8" +## + +# Clock constraints + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + +#************************************************************** +# Time Information +#************************************************************** + +set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}] + +set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]" +set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]" +#************************************************************** +# Create Generated Clock +#************************************************************** + + +#************************************************************** +# Set Clock Latency +#************************************************************** + + + +#************************************************************** +# Set Clock Uncertainty +#************************************************************** + +#************************************************************** +# Set Input Delay +#************************************************************** + +set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}] +set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}] + +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]] +set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]] + +#************************************************************** +# Set Output Delay +#************************************************************** + +set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}] +set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}] + +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +#************************************************************** +# Set Clock Groups +#************************************************************** + +set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}] + +#************************************************************** +# Set False Path +#************************************************************** + + + +#************************************************************** +# Set Multicycle Path +#************************************************************** + +set_multicycle_path -to {VGA_*[*]} -setup 2 +set_multicycle_path -to {VGA_*[*]} -hold 1 + +#************************************************************** +# Set Maximum Delay +#************************************************************** + + + +#************************************************************** +# Set Minimum Delay +#************************************************************** + + + +#************************************************************** +# Set Input Transition +#************************************************************** + diff --git a/Arcade_MiST/Konami Jailbreak/README.md b/Arcade_MiST/Konami Jailbreak/README.md new file mode 100644 index 00000000..92b3397b --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/README.md @@ -0,0 +1,11 @@ +# MiST port of Konami Jailbreak by ACE + +https://github.com/MiSTer-devel/Arcade-Jailbreak_MiSTer + +## Usage + +- Create ROM and ARC files from the MRA files using the MRA utility. + Example: mra -A -z /path/to/mame/roms "Jailbreak.mra" +- Copy the ROM files to the root of the SD Card +- Copy the RBF and ARC files to the same folder on the SD Card +- MRA utility: https://github.com/sebdel/mra-tools-c/ \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/meta/Jailbreak.mra b/Arcade_MiST/Konami Jailbreak/meta/Jailbreak.mra new file mode 100755 index 00000000..86af1f2b --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/meta/Jailbreak.mra @@ -0,0 +1,75 @@ + + Jailbreak + World + no + no + + + + + 1986 + Konami + Army / Fighter + + jailbrek + jailbrek + 0224 + Jailbrek + + 15kHz + no + no + + 2 (alternating) + 8-way + + 2 + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + 00 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 02 00 + 00 00 16 20 00 50 00 11 + 00 00 15 7E 00 03 00 30 + + + + + + + + + 20210910141626 + diff --git a/Arcade_MiST/Konami Jailbreak/meta/Manhattan 24 Bunsyo (J).mra b/Arcade_MiST/Konami Jailbreak/meta/Manhattan 24 Bunsyo (J).mra new file mode 100755 index 00000000..19236281 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/meta/Manhattan 24 Bunsyo (J).mra @@ -0,0 +1,75 @@ + + Manhattan 24 Bunsyo + Japan + no + no + + + + + 1986 + Konami + Army / Fighter + + manhatan + jailbrek + 0224 + Jailbrek + + 15kHz + no + no + + 2 (alternating) + 8-way + + 2 + + + + + + + + + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + 00 00 00 00 00 FF 00 02 + 00 02 00 01 00 FF 02 00 + 00 00 16 20 00 50 00 11 + 00 00 15 7E 00 03 00 30 + + + + + + + + + 20210910154606 + diff --git a/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak.sv b/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak.sv new file mode 100644 index 00000000..d25927ad --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak.sv @@ -0,0 +1,575 @@ +//============================================================================ +// +// Jailbreak PCB model +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +module Jailbreak +( + input reset, + input clk_49m, //Actual frequency: 49.152MHz + input [1:0] coin, + input btn_service, + input [1:0] btn_start, //1 = Player 2, 0 = Player 1 + input [3:0] p1_joystick, p2_joystick, //3 = up, 2 = down, 1 = right, 0 = left + input [1:0] p1_buttons, p2_buttons, //2 buttons per player + + input [19:0] dipsw, + + //This input serves to select a fractional divider to acheive 3.072MHz for the YM2203 depending on whether Scooter Shooter + //runs with original or underclocked timings to normalize sync frequencies + input underclock, + + //Screen centering (alters HSync and VSync timing of the Konami 005849 to reposition the video output) + input [3:0] h_center, v_center, + + output signed [15:0] sound, + output video_csync, + output video_hsync, video_vsync, + output video_vblank, video_hblank, + output ce_pix, + output [3:0] video_r, video_g, video_b, //12-bit RGB, 4 bits per color + + input [24:0] ioctl_addr, + input [7:0] ioctl_data, + input ioctl_wr, + + input pause, + + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_write, + + //SDRAM signals + output reg [15:0] main_cpu_rom_addr, + input [7:0] main_cpu_rom_do, + output reg [15:1] char1_rom_addr, + input [15:0] char1_rom_do, + output sp1_req, + input sp1_ack, + output [16:1] sp1_rom_addr, + input [15:0] sp1_rom_do +); + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Output pixel clock enable +assign ce_pix = cen_6m; + +//------------------------------------------------- MiSTer data write selector -------------------------------------------------// + +//Instantiate MiSTer data write selector to generate write enables for loading ROMs into the FPGA's BRAM +wire ep1_cs_i, ep2_cs_i, ep3_cs_i, ep4_cs_i, ep5_cs_i, ep6_cs_i, ep7_cs_i, ep8_cs_i, ep9_cs_i; +wire tl_cs_i, sl_cs_i, cp1_cs_i, cp2_cs_i; +selector DLSEL +( + .ioctl_addr(ioctl_addr), + .ep1_cs(ep1_cs_i), + .ep2_cs(ep2_cs_i), + .ep3_cs(ep3_cs_i), + .ep4_cs(ep4_cs_i), + .ep5_cs(ep5_cs_i), + .ep6_cs(ep6_cs_i), + .ep7_cs(ep7_cs_i), + .ep8_cs(ep8_cs_i), + .ep9_cs(ep9_cs_i), + .tl_cs(tl_cs_i), + .sl_cs(sl_cs_i), + .cp1_cs(cp1_cs_i), + .cp2_cs(cp2_cs_i) +); + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Generate 6.144MHz, (inverted) 3.072MHz and 1.576MHz clock enables (clock division is normally handled inside the Konami 005849) +//Also generate an extra clock enable for DC offset removal in the sound section +reg [6:0] div = 7'd0; +always_ff @(posedge clk_49m) begin + div <= div + 7'd1; +end +wire cen_6m = !div[2:0]; +wire cen_3m = !div[3:0]; +wire cen_1m5 = !div[4:0]; +wire dcrm_cen = !div; + +//Generate E and Q clock enables for KONAMI-1 (code adapted from Sorgelig's phase generator used in the MiSTer Vectrex core) +reg k1_E, k1_Q; +always_ff @(posedge clk_49m) begin + reg [1:0] clk_phase = 0; + k1_E <= 0; + k1_Q <= 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b01: k1_Q <= 1; + 2'b10: k1_E <= 1; + endcase + end +end + +//Fractional divider to obtain 3.579545MHz clock for the VLM5030 +wire [9:0] vlm5030_cen_n = underclock ? 10'd62 : 10'd60; +wire [9:0] vlm5030_cen_m = underclock ? 10'd843 : 10'd824; +wire cen_3m58; +jtframe_frac_cen vlm5030_cen +( + .clk(clk_49m), + .n(vlm5030_cen_n), + .m(vlm5030_cen_m), + .cen({1'bZ, cen_3m58}) +); + +//Extra fractional divider to maintain a steady 1.536MHz for the SN76489 when Jailbreak runs at underclocked timings +wire cen_1m5_adjust; +jtframe_frac_cen sn76489_cen +( + .clk(clk_49m), + .n(10'd25), + .m(10'd786), + .cen({1'bZ, cen_1m5_adjust}) +); + +//------------------------------------------------------------ CPU -------------------------------------------------------------// + +//CPU - KONAMI-1 custom encrypted MC6809E (uses synchronous version of Greg Miller's cycle-accurate MC6809E made by +//Sorgelig with a wrapper to decrypt XOR/XNOR-encrypted opcodes and a further modification to Greg's MC6809E to directly +//accept the opcodes) +wire k1_rw; +wire [15:0] k1_A; +wire [7:0] k1_Dout; +KONAMI1 u18F +( + .CLK(clk_49m), + .fallE_en(k1_E), + .fallQ_en(k1_Q), + .D(k1_Din), + .DOut(k1_Dout), + .ADDR(k1_A), + .RnW(k1_rw), + .nIRQ(irq), + .nFIRQ(firq), + .nNMI(nmi), + .nHALT(~pause), + .nRESET(reset) +); +//Address decoding for KONAMI-1 +wire cs_dip2 = ~n_iocs & (k1_A[10:8] == 3'b001) & k1_rw; +wire cs_dip3 = ~n_iocs & (k1_A[10:8] == 3'b010) & k1_rw; +wire cs_controls_dip1 = ~n_iocs & (k1_A[10:8] == 3'b011) & k1_rw; +wire cs_snlatch = ~n_iocs & (k1_A[10:8] == 3'b001) & ~k1_rw; +wire cs_sn76489 = ~n_iocs & (k1_A[10:8] == 3'b010) & ~k1_rw; +wire cs_k005849 = (k1_A[15:14] == 2'b00); +wire cs_vlm5030_busy = (k1_A[15:12] == 4'b0110); +wire cs_rom1 = (k1_A[15:14] == 2'b10) & k1_rw; +wire cs_rom2 = (k1_A[15:14] == 2'b11) & k1_rw; +//Multiplex data inputs to KONAMI-1 +wire [7:0] k1_Din = cs_dip2 ? dipsw[15:8]: + cs_dip3 ? {4'hF, dipsw[19:16]}: + cs_controls_dip1 ? controls_dip1: + (cs_k005849 & n_iocs & k1_rw) ? k005849_D: + cs_vlm5030_busy ? {7'h7F, vlm5030_busy}: + cs_rom1 ? eprom1_D: + cs_rom2 ? eprom2_D: + 8'hFF; + +//KONAMI-1 ROMs +`ifdef EXT_ROM +always_ff @(posedge clk_49m) + if (k1_A[15] & k1_rw) + main_cpu_rom_addr <= k1_A[14:0]; + +wire [7:0] eprom1_D = main_cpu_rom_do; +wire [7:0] eprom2_D = main_cpu_rom_do; +`else +//ROM 1/2 +wire [7:0] eprom1_D; +eprom_1 u11D +( + .ADDR(k1_A[13:0]), + .CLK(clk_49m), + .DATA(eprom1_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep1_cs_i), + .WR(ioctl_wr) +); +//ROM 2/2 +wire [7:0] eprom2_D; +eprom_2 u9D +( + .ADDR(k1_A[13:0]), + .CLK(clk_49m), + .DATA(eprom2_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep2_cs_i), + .WR(ioctl_wr) +); +`endif + +//Sound latch +reg [7:0] sound_data = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && cs_snlatch) + sound_data <= k1_Dout; +end + +//--------------------------------------------------- Controls & DIP switches --------------------------------------------------// + +//Multiplex player inputs and DIP switch bank 1 +wire [7:0] controls_dip1 = (k1_A[1:0] == 2'b00) ? {3'b111, btn_start, btn_service, coin}: + (k1_A[1:0] == 2'b01) ? {2'b11, p1_buttons, p1_joystick}: + (k1_A[1:0] == 2'b10) ? {2'b11, p2_buttons, p2_joystick}: + (k1_A[1:0] == 2'b11) ? dipsw[7:0]: + 8'hFF; + +//--------------------------------------------------- Video timing & graphics --------------------------------------------------// + +//Konami 005849 custom chip - this is a large ceramic pin-grid array IC responsible for the majority of Jailbreak's critical +//functions: IRQ generation, clock dividers and all video logic for generating tilemaps and sprites +wire [15:0] spriterom_A; +wire [14:0] tilerom_A; +wire [7:0] k005849_D, tilemap_lut_A, sprite_lut_A; +wire [4:0] color_A; +wire [1:0] h_cnt; +wire n_iocs, irq, firq, nmi; +k005849 u8E +( + .CK49(clk_49m), + .RES(reset), + .READ(~k1_rw), + .A(k1_A[13:0]), + .DBi(k1_Dout), + .DBo(k005849_D), + .VCF(tilemap_lut_A[7:4]), + .VCB(tilemap_lut_A[3:0]), + .VCD(tilemap_lut_D), + .OCF(sprite_lut_A[7:4]), + .OCB(sprite_lut_A[3:0]), + .OCD(sprite_lut_D), + .COL(color_A), + .XCS(~cs_k005849), + .BUSE(0), + .SYNC(video_csync), + .HSYC(video_hsync), + .VSYC(video_vsync), + .HBLK(video_hblank), + .VBLK(video_vblank), + .FIRQ(firq), + .IRQ(irq), + .NMI(nmi), + .IOCS(n_iocs), + .R(tilerom_A), + .S(spriterom_A), + .S_req(sp1_req), + .S_ack(sp1_ack), + .RD(tilerom_D), + .SD(spriterom_D), + .HCTR(h_center), + .VCTR(v_center), + .SPFL(1), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_write(hs_access_write) +); + +//Graphics ROMs +`ifdef EXT_ROM +assign sp1_rom_addr = spriterom_A[15:1]; +wire [7:0] spriterom_D = spriterom_A[0] ? sp1_rom_do[15:8] : sp1_rom_do[7:0]; +assign char1_rom_addr = tilerom_A[14:1]; +wire [7:0] tilerom_D = tilerom_A[0] ? char1_rom_do[15:8] : char1_rom_do[7:0]; +`else +wire [7:0] eprom3_D, eprom4_D, eprom5_D, eprom6_D, eprom7_D, eprom8_D; +eprom_3 u4F +( + .ADDR(tilerom_A[13:0]), + .CLK(clk_49m), + .DATA(eprom3_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep3_cs_i), + .WR(ioctl_wr) +); +eprom_4 u5F +( + .ADDR(tilerom_A[13:0]), + .CLK(clk_49m), + .DATA(eprom4_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep4_cs_i), + .WR(ioctl_wr) +); +eprom_5 u3E +( + .ADDR(spriterom_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom5_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep5_cs_i), + .WR(ioctl_wr) +); +eprom_6 u4E +( + .ADDR(spriterom_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom6_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep6_cs_i), + .WR(ioctl_wr) +); +eprom_7 u5E +( + .ADDR(spriterom_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom7_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep7_cs_i), + .WR(ioctl_wr) +); +eprom_8 u3F +( + .ADDR(spriterom_A[13:0]), + .CLK(~clk_49m), + .DATA(eprom8_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep8_cs_i), + .WR(ioctl_wr) +); + +//Multiplex tilemap ROMs +wire [7:0] tilerom_D = tilerom_A[14] ? eprom4_D : eprom3_D; + +//Multiplex sprite ROMs +wire [7:0] spriterom_D = (spriterom_A[15:14] == 2'b00) ? eprom5_D: + (spriterom_A[15:14] == 2'b01) ? eprom6_D: + (spriterom_A[15:14] == 2'b10) ? eprom7_D: + (spriterom_A[15:14] == 2'b11) ? eprom8_D: + 8'hFF; +`endif + +//Tilemap LUT PROM +wire [3:0] tilemap_lut_D; +tile_lut_prom u7F +( + .ADDR(tilemap_lut_A), + .CLK(clk_49m), + .DATA(tilemap_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(tl_cs_i), + .WR(ioctl_wr) +); + +//Sprite LUT PROM +wire [3:0] sprite_lut_D; +sprite_lut_prom u6F +( + .ADDR(sprite_lut_A), + .CLK(clk_49m), + .DATA(sprite_lut_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(sl_cs_i), + .WR(ioctl_wr) +); + +//--------------------------------------------------------- Sound chips --------------------------------------------------------// + +//Generate chip enable for SN76489 +wire n_sn76489_ce = (~cs_sn76489 & sn76489_ready); + +//Select whether to use a fractional or integer clock divider for the YM2203 to maintain consistent sound pitch at both original +//and underclocked timings +wire cen_sn76489 = underclock ? cen_1m5_adjust : cen_1m5; + +//Sound chip 1 (Texas Instruments SN76489 - uses Arnim Laeuger's SN76489 implementation with bugfixes) +wire [7:0] sn76489_raw; +wire sn76489_ready; +sn76489_top u6D +( + .clock_i(clk_49m), + .clock_en_i(cen_sn76489), + .res_n_i(reset), + .ce_n_i(n_sn76489_ce), + .we_n_i(sn76489_ready), + .ready_o(sn76489_ready), + .d_i(sound_data), + .aout_o(sn76489_raw) +); + +//Sound chip 2 (VLM5030 - uses Arnim Laeuger's gate-level VLM5030 implementation) +//Sourced from https://github.com/FPGAArcade/replay_common/tree/master/lib/sound/vlm5030 +wire [12:0] vlm5030_rom_A; +wire signed [9:0] vlm5030_raw; +wire vlm5030_busy, n_vlm5030_rom_en; +vlm5030_gl u6A +( + .i_clk(clk_49m), + .i_oscen(cen_3m58), + .i_rst(vlm5030_reset), + .i_start(vlm5030_start), + .i_vcu(0), + .i_tst1(0), + .i_d(vlm5030_Din), + .o_a({3'bZZZ, vlm5030_rom_A}), + .o_me_l(n_vlm5030_rom_en), + .o_bsy(vlm5030_busy), + .o_audio(vlm5030_raw) +); + +//VLM5030 ROM +wire [7:0] eprom9_D; +eprom_9 u8C +( + .ADDR(vlm5030_rom_A), + .CLK(clk_49m), + .DATA(eprom9_D), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(ep9_cs_i), + .WR(ioctl_wr) +); + +//Generate VLM5030 latch signals +wire vlm5030_ctrl_latch = (k1_A[15:12] == 4'b0100); +wire vlm5030_latch = (k1_A[15:12] == 4'b0101); + +//Latch VLM5030 control lines from KONAMI-1 +reg vlm5030_reset = 0; +reg vlm5030_start = 0; +reg vlm5030_enable = 0; +always_ff @(posedge clk_49m) begin + if(cen_3m && vlm5030_ctrl_latch) begin + vlm5030_enable <= k1_Dout[0]; + vlm5030_start <= k1_Dout[1]; + vlm5030_reset <= k1_Dout[2]; + end +end + +//Latch data from KONAMI-1 to VLM5030 +reg [7:0] vlm5030_sound_D = 8'd0; +always_ff @(posedge clk_49m) begin + if(cen_3m && vlm5030_latch) + vlm5030_sound_D <= k1_Dout; +end + +//Multiplex data inputs from the ROM and KONAMI-1 to the VLM5030's data input +wire [7:0] vlm5030_Din = vlm5030_enable ? vlm5030_sound_D: + ~n_vlm5030_rom_en ? eprom9_D: + 8'hFF; + +//----------------------------------------------------- Final video output -----------------------------------------------------// + +//Jailbreak's final video output consists of two PROMs addressed by the 005849 custom tilemap generator +color_prom_1 u1F +( + .ADDR(color_A), + .CLK(clk_49m), + .DATA({video_g, video_r}), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(cp1_cs_i), + .WR(ioctl_wr) +); + +color_prom_2 u2F +( + .ADDR(color_A), + .CLK(clk_49m), + .DATA(video_b), + .ADDR_DL(ioctl_addr), + .CLK_DL(clk_49m), + .DATA_IN(ioctl_data), + .CS_DL(cp2_cs_i), + .WR(ioctl_wr) +); + +//----------------------------------------------------- Final audio output -----------------------------------------------------// + +//Apply gain and remove DC offset from SN76489 (uses jt49_dcrm2 from JT49 by Jotego for DC offset removal) +wire signed [15:0] sn76489_dcrm; +jt49_dcrm2 #(16) dcrm_sn76489 +( + .clk(clk_49m), + .cen(dcrm_cen), + .rst(~reset), + .din({3'd0, sn76489_raw, 5'd0}), + .dout(sn76489_dcrm) +); + +//Apply gain to the VLM5030 +wire signed [15:0] vlm5030_gain = vlm5030_raw <<< 16'd6; + +//Jailbreak uses a 3.386KHz low-pass filter for its SN76489 - filter the audio accordingly here. +wire signed [15:0] sn76489_lpf; +jailbreak_psg_lpf psg_lpf +( + .clk(clk_49m), + .reset(~reset), + .in(sn76489_dcrm), + .out(sn76489_lpf) +); + +//Jailbreak also uses a 338.628Hz low-pass filter for its VLM5030 - filter the audio accordingly here. +wire signed [15:0] vlm5030_lpf; +jailbreak_speech_lpf speech_lpf +( + .clk(clk_49m), + .reset(~reset), + .in(vlm5030_gain), + .out(vlm5030_lpf) +); + +//The output of the VLM5030 is phase-inverted - apply this inversion here +//Also lower the volume for mixing with the SN76489 +wire signed [15:0] vlm5030_inv = (16'hFFFF - vlm5030_lpf) >>> 16'd5; + +//Lower SN76489 volume to balance out with the VLM5030 +wire signed [15:0] sn76489_gain = sn76489_lpf >>> 16'd3; + +//Output final audio signal (mute when game is paused) +assign sound = pause ? 16'd0 : (sn76489_gain + vlm5030_inv) <<< 16'd5; + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak_MiST.sv b/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak_MiST.sv new file mode 100644 index 00000000..ce2529ff --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/Jailbreak_MiST.sv @@ -0,0 +1,308 @@ +module Jailbreak_MiST ( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27, + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE + +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "JAILBREK;;", + "O2,Rotate Controls,Off,On;", + "O34,Scanlines,Off,25%,50%,75%;", + "O5,Blend,Off,On;", + "O6,Joystick Swap,Off,On;", + "O7,Service,Off,On;", + "O1,Pause,Off,On;", + "DIP;", + "T0,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire rotate = status[2]; +wire [1:0] scanlines = status[4:3]; +wire blend = status[5]; +wire joyswap = status[6]; +wire service = status[7]; +wire pause = status[1]; + +wire [1:0] orientation = 2'b10; +wire [23:0] dip_sw = ~status[31:8]; + +assign LED = ~ioctl_downl; +assign SDRAM_CLK = clock_98; +assign SDRAM_CKE = 1; + +wire clock_98, clock_49, pll_locked; +pll pll( + .inclk0(CLOCK_27), + .c0(clock_98), + .c1(clock_49),//49.152MHz + .locked(pll_locked) + ); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire scandoublerD; +wire ypbpr; +wire no_csync; +wire [6:0] core_mod; +wire key_strobe; +wire key_pressed; +wire [7:0] key_code; + +user_io #(.STRLEN(($size(CONF_STR)>>3)))user_io( + .clk_sys (clock_49 ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD), + .ypbpr (ypbpr ), + .no_csync (no_csync ), + .core_mod (core_mod ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_code (key_code ), + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ), + .status (status ) + ); + +wire [15:0] main_rom_addr; +wire [15:0] main_rom_do; +wire [15:1] ch1_addr; +wire [15:0] ch1_do; +wire sp1_req, sp1_ack; +wire [16:1] sp1_addr; +wire [15:0] sp1_do; + +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [24:0] ioctl_addr; +wire [7:0] ioctl_dout; + +data_io data_io( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DI ( SPI_DI ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) +); +wire [24:0] bg_ioctl_addr = ioctl_addr - 16'h8000; + +reg port1_req, port2_req; +sdram #(98) sdram( + .*, + .init_n ( pll_locked ), + .clk ( clock_98 ), + + // port1 for CPUs + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 16'h0000 : main_rom_addr[15:1] ), + .cpu1_q ( main_rom_do ), + .cpu2_addr ( ), + .cpu2_q ( ), + + // port2 for graphics + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( bg_ioctl_addr[23:1] ), + .port2_ds ( {bg_ioctl_addr[0], ~bg_ioctl_addr[0]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .ch1_addr ( ioctl_downl ? 16'hffff : ch1_addr ), + .ch1_q ( ch1_do ), + .sp1_req ( sp1_req ), + .sp1_ack ( sp1_ack ), + .sp1_addr ( ioctl_downl ? 16'hffff : 16'h4000 + sp1_addr[15:1] ), + .sp1_q ( sp1_do ) +); + +// ROM download controller +always @(posedge clock_49) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + +reg reset = 1; +reg rom_loaded = 0; +always @(posedge clock_49) begin + reg ioctl_downlD; + ioctl_downlD <= ioctl_downl; + + if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; + reset <= status[0] | buttons[1] | ~rom_loaded; +end + +wire [15:0] audio; +wire hs, vs, cs; +wire hblank, vblank; +wire blankn = ~(hblank | vblank); +wire [3:0] r, g, b; + +//Instantiate Jailbreak top-level module +Jailbreak Jailbreak_inst +( + .reset(~reset), // input reset + + .clk_49m(clock_49), // input clk_49m + + .coin({~m_coin2, ~m_coin1}), // input coin + .btn_service(~service), // input btn_service + + .btn_start({~m_two_players, ~m_one_player}), // input [1:0] btn_start + + // The game crashes when two opposite direction controls are held down. + // It's not possible with a physical controller, but it is via keyboard, + // so protect against this here. + .p1_joystick({~m_down | m_up, ~m_up, ~m_right | m_left, ~m_left}), + .p2_joystick({~m_down2 | m_up2, ~m_up2, ~m_right2 | m_left2, ~m_left2}), + .p1_buttons({~m_fireB, ~m_fireA}), + .p2_buttons({~m_fire2B, ~m_fire2A}), + + .dipsw(dip_sw), // input [24:0] dipsw + + .sound(audio), // output [15:0] sound + + .h_center(), // Screen centering + .v_center(), + + .video_hsync(hs), // output video_hsync + .video_vsync(vs), // output video_vsync + .video_vblank(vblank), // output video_vblank + .video_hblank(hblank), // output video_hblank + + .video_r(r), // output [4:0] video_r + .video_g(g), // output [4:0] video_g + .video_b(b), // output [4:0] video_b + + .ioctl_addr(ioctl_addr), + .ioctl_wr(ioctl_wr && ioctl_index == 0), + .ioctl_data(ioctl_dout), + + .pause(pause), + + .hs_address(hs_address), + .hs_data_out(hs_data_out), + .hs_data_in(hs_data_in), + .hs_write_enable(hs_write_enable), + .hs_access_write(hs_access_write), + + .main_cpu_rom_addr(main_rom_addr), + .main_cpu_rom_do(main_rom_addr[0] ? main_rom_do[15:8] : main_rom_do[7:0]), + .char1_rom_addr(ch1_addr), + .char1_rom_do(ch1_do), + .sp1_req(sp1_req), + .sp1_ack(sp1_ack), + .sp1_rom_addr(sp1_addr), + .sp1_rom_do(sp1_do) +); + +mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video( + .clk_sys ( clock_49 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : 0 ), + .G ( blankn ? g : 0 ), + .B ( blankn ? b : 0 ), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .ce_divider ( 0 ), + .rotate ( { orientation[1], rotate } ), + .blend ( blend ), + .scandoubler_disable( scandoublerD ), + .scanlines ( scanlines ), + .ypbpr ( ypbpr ), + .no_csync ( no_csync ) + ); + +wire audio_out; +assign AUDIO_L = audio_out; +assign AUDIO_R = audio_out; + +dac #(.C_bits(16))dac( + .clk_i(clock_49), + .res_n_i(1'b1), + .dac_i({~audio[15], audio[14:0]}), + .dac_o(audio_out) + ); + +wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF; +wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F; +wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players; + +arcade_inputs inputs ( + .clk ( clock_49 ), + .key_strobe ( key_strobe ), + .key_pressed ( key_pressed ), + .key_code ( key_code ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .rotate ( rotate ), + .orientation ( orientation ), + .joyswap ( joyswap ), + .oneplayer ( 1'b0 ), + .controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ), + .player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ), + .player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ) +); + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/KONAMI1.sv b/Arcade_MiST/Konami Jailbreak/rtl/KONAMI1.sv new file mode 100644 index 00000000..9126e795 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/KONAMI1.sv @@ -0,0 +1,79 @@ +//============================================================================ +// +// SystemVerilog implementation of the KONAMI-1 custom chip, a custom MC6809E +// variant with XOR/XNOR encryption +// Implements MC6809E core by Greg Miller (synchronous version modified by +// Sorgelig with further modifications to allow direct injection of opcodes) +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +module KONAMI1 +( + input CLK, + input fallE_en, + input fallQ_en, + + input [7:0] D, + output [7:0] DOut, + output [15:0] ADDR, + output RnW, + output BS, + output BA, + input nIRQ, + input nFIRQ, + input nNMI, + output AVMA, + output BUSY, + output LIC, + input nHALT, + input nRESET +); + +//Decrypt XOR/XNOR encrypted opcode +wire [7:0] opcode = D ^ {ADDR[1], 1'b0, ~ADDR[1], 1'b0, ADDR[3], 1'b0, ~ADDR[3], 1'b0}; + +//Passthrough to modified MC6809is core with direct opcode injection and IS_KONAMI1 parameter set +//to TRUE +mc6809is #(.IS_KONAMI1("TRUE")) cpucore +( + .CLK(CLK), + .fallE_en(fallE_en), + .fallQ_en(fallQ_en), + .OP(opcode), + .nHALT(nHALT), + .nRESET(nRESET), + .D(D), + .DOut(DOut), + .ADDR(ADDR), + .RnW(RnW), + .BS(BS), + .BA(BA), + .nIRQ(nIRQ), + .nFIRQ(nFIRQ), + .nNMI(nNMI), + .AVMA(AVMA), + .BUSY(BUSY), + .LIC(LIC), + .nDMABREQ(1) +); + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_gl.vhd b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_gl.vhd new file mode 100644 index 00000000..996b98e0 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_gl.vhd @@ -0,0 +1,2304 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- +------------------------------------------------------------------------------- +-- +-- Sanyo VLM5030 speech snythesizer +-- +-- Gate-level recreation extracted from the die image at +-- https://siliconpr0n.org/archive/doku.php?id=ogoun:vlm5030 +-- +------------------------------------------------------------------------------- +-- +-- +-------,_,-------+ +-- GND -- | 1 40 | <- RST +-- TST1 -> | 2 39 | -> TST4 +-- OSC2 ck | 3 _ 38 | <- TST3 +-- OSC1 ck | 4 (_) 37 | -> TST2 +-- D0 -> | 5 36 | -> DAO +-- D1 -> | 6 35 | <- VREF +-- D2 -> | 7 34 | -> MTE +-- D3 -> | 8 V 33 | -> /ME +-- D4 -> | 9 L 32 | <- VCU +-- D5 -> | 10 M 31 | <- START +-- D6 -> | 11 5 30 | -> BSY +-- D7 -> | 12 0 29 | -- Vdd +-- A0 <- | 13 3 28 | -> A15 +-- A1 <- | 14 0 27 | -> A14 +-- A2 <- | 15 26 | -> A13 +-- A3 <- | 16 _ 25 | -> A12 +-- A4 <- | 17 (_) 24 | -> A11 +-- A5 <- | 18 23 | -> A10 +-- A6 <- | 19 22 | -> A9 +-- A7 <- | 20 21 | -> A8 +-- +-----------------+ +-- +-- Clocking +-- ======== +-- +-- This model requires overclocking of OSC1/OSC2 by 2x or higher. +-- Violating this requirement results in undefined behaviour. +-- +-- i_clk is supplied with a free-running clock at >= 2x OSC frequency. +-- +-- i_oscen acts as clock enable for i_clk to define the 3.58 MHz clock +-- at OSC1/OSC2 of a real chip. +-- +-- +-- Test pins +-- ========= +-- +-- i_tst1 must be tied to '0' for mission mode operation. +-- Other unused test pins can be left unconnected: +-- * i_vref +-- * o_tst2 +-- * i_tst3 +-- * o_tst4 +-- +-- +-- Audio output +-- ============ +-- +-- The VLM5030 internally generates 12 bit signed PCM audio with ~8136 Hz +-- sample rate. +-- +-- During /ME=1 this PCM data is available at A[13:12], A[9:0]. +-- Note that A[9] has to be inverted externally if A[9:0] is to be used as a +-- standard signed vector. +-- +-- Typical applications use audio from the DAO pin. It is fed by a combination +-- of a 5 bit parallel DAC (tapping A[9:5]) and overlaid with a PWM signal +-- (controlled by A[4:2]). Bits A[1:0] are not used for DAO generation +-- +-- DAO characteristics +-- ------------------- +-- +-- DAO is an overlay of the 8136 Hz PCM data with high frequency PWM. +-- The PWM overlay periodically increases the DAO output voltage to the next +-- higher value with a duty cycle controlled by A[4:2]. +-- +-- ^ new PCM value new PCM value +-- | . PWM overlay . +-- | .+---+ +---+ +---+ +---+ +---+ +-+ +-- | ++ +------+ +------+ +------+ +------+ +------+ + +-- | | | +-- | | +-- +-- |---+ +-- +------------------------------------------------------------------> +-- +-- When fed through an external low-pass filter, this PWM overlay augments +-- the discreete PCM DAC voltages with fractional levels. +-- +-- PWM period approx. 24.581 us, 40.682 kHz +-- PWM | high | low +-- -----+--------+-------- +-- 7 | 20.112 | 4.470 +-- 6 | 17.318 | 7.263 +-- 5 | 13.966 | 10.615 +-- 4 | 11.173 | 13.408 +-- 3 | 7.821 | 16.760 +-- 2 | 4.670 | 19.553 +-- 1 | 1.676 | 22.905 +-- 0 | 0.000 | 24.581 +-- +-- Direct PCM output +-- ----------------- +-- +-- This model outputs signed 10 bit audio at o_audio in addition to DAO. +-- o_audio is equivalent to A[9:0] during /ME=1 with corrected sign bit. +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity vlm5030_gl is + + port ( + i_clk : in std_logic; + i_oscen : in std_logic; + i_rst : in std_logic; + i_start : in std_logic; + i_vcu : in std_logic; + i_vref : in std_logic := '1'; + i_tst1 : in std_logic; + o_tst2 : out std_logic; + i_tst3 : in std_logic := '1'; + o_tst4 : out std_logic; + i_d : in std_logic_vector( 7 downto 0); + o_a : out std_logic_vector(15 downto 0); + o_me_l : out std_logic; + o_mte : out std_logic; + o_bsy : out std_logic; + + -- o_dao: unsigned audio, sample rate ~8136Hz, PWM ~40.682 kHz + o_dao : out std_logic_vector( 5 downto 0); + + -- o_audio: signed audio, sample rate ~8136Hz + o_audio : out std_logic_vector(9 downto 0) + ); + +end; + +use work.vlm5030_pack.all; + +architecture gl of vlm5030_gl is + + signal osc : t_clk; + signal clk2 : t_clk := z_clk; + signal nclk2 : t_clk; + + signal rst : std_logic; + + + signal dq : std_logic_vector(7 downto 0); + signal maskdq53 : std_logic; + + signal starttst : std_logic; + signal tststopclk2, tstend2ID, tstend2IE, + tstenID2A, tstenIE2A, tstenctrl2A, + tstenIE2DAC : std_logic; + + signal clk2divq : std_logic_vector(10 downto 0) := (others => '0'); + signal c2d0, c2d1, c2d2, + c2d3, c2d4, c2d5, + c2d6, c2d7, c2d8, + c2d9, c2d10 : t_clk; + signal c2d5fin : t_clk; + signal c2d7fin, nc2d7fin : t_clk; + signal c2d9fin, nc2d9fin : t_clk; + signal clk2gd5 : t_clk; + signal nc2d1, nc2d6, + nc2d8, nc2d10 : t_clk; + signal c2d3gated : t_clk; + + + signal fsromevalout : std_logic; + signal fsromdo : std_logic_vector(13 downto 0); + signal fsromnorhigh, + fsromnorlow : std_logic; + -- + signal clk2ctrl : t_clk; + signal ncen1, cen3 : std_logic; + signal eaoen : std_logic; + signal xromdo7nq : std_logic := '0'; + signal xromdo7q : std_logic; + signal xromdo : std_logic_vector(36 downto 0); + signal yromdo : std_logic_vector( 4 downto 0); + signal c2d3gate : std_logic; + + + signal cntdn0 : std_logic; + + + signal dinalq : std_logic_vector(7 downto 0) := (others => '0'); + signal aq : std_logic_vector(o_a'range); + + + signal startrise : std_logic; + signal clkcntdn : t_clk; + signal ncntdnload : std_logic; + signal ncntdn : std_logic; + + signal eavcu : std_logic; + signal ealatchh : std_logic; + signal neaload : std_logic; + signal eainc : std_logic; + signal clrdinal : std_logic; + signal clkdin : std_logic; + signal nvcufinal : std_logic; + signal vcufinal12 : std_logic; + signal nbsy : std_logic; + signal me : std_logic; + signal rflatchwen : std_logic; + signal asshift2 : std_logic; + signal updtpitch : std_logic; + signal enrf2ID : std_logic; + signal clkksa : t_clk; + signal ensum2ID : std_logic; + + + signal clk2ena, clk2enb : t_clk; + + signal rstdel : std_logic; + + + signal ksa : std_logic_vector(4 downto 0); + signal nkdo : std_logic_vector(9 downto 0); + + + signal rfdo : std_logic_vector(nkdo'range); + signal rfdo97zero : std_logic; + + + signal nID : std_logic_vector(9 downto 0); + + signal assum : std_logic_vector(nID'range); + + signal nIE : std_logic_vector(11 downto 0); + + signal idlat : std_logic_vector(7 downto 0); + signal idlatall1 : std_logic; + signal enIDlinv2ID : std_logic; + signal enIDl2IE : std_logic; + signal enIDlinv2IE : std_logic; + + + signal pitchoverflow : std_logic; + signal enpitchlat : t_clk; + + + signal enmem02ID : std_logic; + signal nmem0do, + mem0do : std_logic_vector(nID'range); + signal enmem12IE : std_logic; + signal mem1do2IE : std_logic_vector(nIE'range); + signal enmem22IE : std_logic; + signal mem2do2IE : std_logic_vector(nIE'range); + + signal ieregdrv, + ieregdrv4IE : std_logic_vector(nIE'range); + signal ieregload : t_clk; + + signal enieregfa2IE : std_logic; + + signal c2d10xr9 : t_clk; + signal enIE2A : std_logic; + signal ieaddrreg : std_logic_vector(nIE'range); + + signal pitchmod : std_logic; + + signal random : std_logic; + + signal pwmsr : std_logic; + +begin + + -- MSB K-slice address bit + -- logic exists that generates it but output is not used (patched wiring) + ksa(4) <= '0'; + + -- main clock, corresponds to oscillator output + osc <= (base => i_clk, + val => i_clk, + rise => i_oscen, + fall => '0'); + + clk2ena <= clk2 or (cen3 nor tstenctrl2A) or ncen1; + clk2enb <= clk2 or (cen3 nor tstenctrl2A) or ncen1 or (fsromdo(6) nor tstenctrl2A); + + + + ----------------------------------------------------------------------------- + -- RST / POR generation + -- + rstdel_block : block + signal porcnt : unsigned(7 downto 0) := (others => '1'); + signal npor : std_logic := '0'; + signal del : std_logic_vector(1 downto 0) := (others => '0'); + begin + por_p : process (osc) + begin + if rising_edge(osc) then + if porcnt > 0 then + porcnt <= porcnt - 1; + end if; + if porcnt = 0 then -- TODO: measure POR hold time + npor <= '1'; + end if; + end if; + end process; + + o_tst4 <= not npor; + + rst <= '1' when npor = '0' and i_tst3 = '1' else i_rst; + + rstdel_p : process (clk2) + begin + if rising_edge(clk2) then + del <= del(0) & rst; + end if; + end process; + -- + rstdel <= del(1); + end block; + + + + ----------------------------------------------------------------------------- + -- DQ registers + -- + dq_block : block + signal rstq : std_logic := '0'; + signal rstclk : t_clk; + signal ldq : std_logic_vector(dq'range); + signal maskdq53m, maskdq53s : std_logic := '1'; + + begin + rstclk_p : process (osc.base) + begin + if rising_edge(osc.base) then + rstq <= rst; + end if; + end process; + -- + rstclk <= (base => osc.base, + val => rstq, + rise => not rstq and rst, + fall => rstq and not rst); + + dq_p : process (rstclk) + begin + if falling_edge(rstclk) then + ldq <= i_d; + end if; + end process; + + maskqm_p : process(startrise, enpitchlat) + begin + if startrise = '1' then + maskdq53m <= '1'; + elsif rising_edge(enpitchlat) then + maskdq53m <= rfdo97zero; + end if; + end process; + maskqs_p : process(startrise, enpitchlat) + begin + if startrise = '1' then + maskdq53s <= '1'; + elsif falling_edge(enpitchlat) then + maskdq53s <= maskdq53m; + end if; + end process; + maskdq53 <= maskdq53s; + + dqmask_p : process(maskdq53, ldq) + begin + dq <= ldq; + if maskdq53 = '1' then + dq(5 downto 3) <= (others => '0'); + end if; + end process; + + end block; + + + + ----------------------------------------------------------------------------- + -- TST logic + -- + -- + -- TST1 VREF VCU START Function + -- 0 X X X Mission mode + -- 1 0 1 1 Clock stopped + -- 1 1 1 0 D to ID + -- 1 1 0 0 D to IE + -- 1 1 1 1 ID to A + -- 1 1 0 1 IE to A + -- 1 0 0 1 CTRL to A + -- 1 0 X 0 IE to DAC, forces D to IE + -- VCU controls pwmsel + -- + tst_block : block + signal ntst1, nstart, nvcu : std_logic; + signal ntst1vref : std_logic; + begin + ntst1 <= not i_tst1; + nstart <= not i_start; + nvcu <= not i_vcu; + + starttst <= nstart nor i_tst1; + + ntst1vref <= i_tst1 nand i_vref; + + tststopclk2 <= not( ntst1 or i_vref or nvcu or nstart ); + tstend2ID <= not( ntst1vref or nvcu or i_start ); + tstend2IE <= not( ntst1vref or i_vcu or i_start ) or tstenIE2DAC; + tstenID2A <= not( ntst1vref or nvcu or nstart ); + tstenIE2A <= not( ntst1vref or i_vcu or nstart ); + tstenctrl2A <= not( ntst1 or i_vref or i_vcu or nstart ); + tstenIE2DAC <= not( ntst1 or i_vref or i_start ); + end block; + + + + ----------------------------------------------------------------------------- + -- CLK2 generation + -- + clk2_block : block + begin + + clk2.base <= osc.base; + + process (osc) + begin + if rising_edge(osc) then + if tststopclk2 = '1' then + clk2.val <= '0'; + + else + clk2.val <= not clk2.val; + end if; + end if; + end process; + + clk2.rise <= '0' when tststopclk2 = '1' else + osc.rise when clk2 = '0' else + '0'; + clk2.fall <= '0' when tststopclk2 = '1' else + osc.rise when clk2 = '1' else + '0'; + + nclk2 <= not clk2; + + end block; + + + + ----------------------------------------------------------------------------- + -- CLK2 divider + -- + clk2div_block : block + signal c2qnor : std_logic; + signal feedback : std_logic; + + -- edge detection for val that will change to preval on the rising refclk edge + function rising_edge_detect(refclk : t_clk; val, preval : std_logic) return t_clk is + begin + return (base => refclk.base, + val => val, + rise => refclk.rise and not val and preval, + fall => refclk.rise and val and not preval); + end; + + begin + -- the 10 bit shift register chain for CLK2DIV + process (clk2) + begin + if rising_edge(clk2) then + clk2divq <= clk2divq(9 downto 0) & feedback; + end if; + end process; + + c2qnor <= norf(clk2divq(9 downto 0)); + + -- feedback signal for the CLK2DIV shifter + feedback <= '0' when rstdel = '1' else c2qnor; + + c2d0 <= rising_edge_detect(refclk => clk2, val => clk2divq( 0), preval => feedback); + c2d1 <= rising_edge_detect(refclk => clk2, val => clk2divq( 1), preval => clk2divq(0)); + c2d2 <= rising_edge_detect(refclk => clk2, val => clk2divq( 2), preval => clk2divq(1)); + c2d3 <= rising_edge_detect(refclk => clk2, val => clk2divq( 3), preval => clk2divq(2)); + c2d4 <= rising_edge_detect(refclk => clk2, val => clk2divq( 4), preval => clk2divq(3)); + c2d5 <= rising_edge_detect(refclk => clk2, val => clk2divq( 5), preval => clk2divq(4)); + c2d6 <= rising_edge_detect(refclk => clk2, val => clk2divq( 6), preval => clk2divq(5)); + c2d7 <= rising_edge_detect(refclk => clk2, val => clk2divq( 7), preval => clk2divq(6)); + c2d8 <= rising_edge_detect(refclk => clk2, val => clk2divq( 8), preval => clk2divq(7)); + c2d9 <= rising_edge_detect(refclk => clk2, val => clk2divq( 9), preval => clk2divq(8)); + c2d10 <= rising_edge_detect(refclk => clk2, val => clk2divq(10), preval => clk2divq(9)); + + + -- SR-latches + c2d5fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d5, + o_q => c2d5fin + ); + c2d7fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d7, + o_q => c2d7fin + ); + nc2d7fin <= not c2d7fin; + + c2d9fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d9, + o_q => c2d9fin + ); + nc2d9fin <= not c2d9fin; + + clk2gd5 <= c2d0 nor (c2d5 and nclk2); + nc2d1 <= not c2d1; + c2d3gated <= (not c2d3) nor c2d3gate; + nc2d6 <= not c2d6; + nc2d8 <= not c2d8; + nc2d10 <= not c2d10; + end block; + + + + ----------------------------------------------------------------------------- + -- FSROM + -- + fsrom_block : block + signal fsroma : std_logic_vector(5 downto 0); + begin + + agen_block : block + begin + process (clk2ena) + begin + if rising_edge(clk2ena) then + if (fsromnorlow nand nvcufinal) = '0' then + -- shift chain + fsroma <= fsroma(4 downto 0) & (fsroma(0) xor fsroma(5)); + else + -- reset chain + fsroma <= (3 => not rstdel, + others => '0'); + end if; + + end if; + end process; + + fsromevalout <= not( (fsromdo( 9) and (xromdo(0) or xromdo(4))) + or (fsromdo(10) and (xromdo(1) or xromdo(4))) + or (fsromdo(11) and (xromdo(6) or xromdo(3) or xromdo(0))) + or (fsromdo(12) and (xromdo(5) or xromdo(2))) + or (fsromdo(13) and xromdo(5)) + or (fsromdo( 8) and (xromdo(7) or xromdo(1))) ); + end block; + + rom_block : block + alias a : std_logic_vector(fsroma'range) is fsroma; + signal na : std_logic_vector(a'range); + signal ndq : std_logic_vector(5 downto 3); + + -- NOTE: vectors for norf must be range 0 to N! + signal wl : std_logic_vector(0 to 17); + + begin + na <= not a; + ndq <= not dq(5 downto 3); + + ------------------------------------------------------------------------- + -- FSROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + wl <= a(5)&na(5) & na(4)&a(4) & a(3)&na(3) & na(2)&a(2) & a(1)&na(1) & na(0)&a(0) & dq(3)&ndq(3) & ndq(4)&dq(4) & dq(5)&ndq(5); + + -- wl(0) wl(17) + -- a(5) ndq(5) + -- | | + fsromdo <= (-- | | + 00 => norf(wl, "100110011001000000"), + 01 => norf(wl, "011010010110001010"), + 02 => norf(wl, "101001010101010110"), + 03 => norf(wl, "011001011001100100"), + 04 => norf(wl, "011010010101001001"), + 05 => norf(wl, "011010011001010101"), + 06 => norf(wl, "010110011001000000"), + -- + 07 => norf(wl, "101010011001000000"), + 08 => norf(wl, "011001100110000000"), + 09 => norf(wl, "101001100110000000"), + 10 => norf(wl, "100101100110000000"), + 11 => norf(wl, "100110100110000000"), + 12 => norf(wl, "100110010110000000"), + 13 => norf(wl, "100110011010000000"), + others => '1'); + -- + ------------------------------------------------------------------------- + + fsromnorhigh <= norf(fsromdo(13 downto 8)); + fsromnorlow <= norf(fsromdo( 5 downto 0)); + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- Sequencer ROM + -- + seqrom_block : block + signal gseqroma : std_logic_vector(4 downto 0); + begin + + agen_block : block + signal ncen3 : std_logic; + signal nclk2ctrlcen3, nclk2ctrlncen3 : std_logic; + signal seqroma : std_logic_vector(4 downto 0) := "11110"; + + begin + ncen1 <= tstenctrl2A nor c2d10; + + clk2ctrl <= clk2 or ncen1; + + ncen3 <= rstdel nor xromdo(7); + cen3 <= not ncen3; + + nclk2ctrlcen3 <= cen3 nor clk2ctrl; + nclk2ctrlncen3 <= ncen3 nor clk2ctrl; + + + process (clk2ctrl) + begin + if rising_edge(clk2ctrl) then + seqroma(0) <= rstdel nor not (cen3 or xromdo(36) or not (seqroma(4) xor not seqroma(1))); + + if cen3 = '0' then + seqroma(1) <= not seqroma(0); + seqroma(2) <= seqroma(1); + seqroma(3) <= seqroma(2); + seqroma(4) <= seqroma(3); + end if; + if ncen3 = '0' then + seqroma(4 downto 1) <= (others => '1'); + end if; + + xromdo7nq <= xromdo(7); -- unclear circuit extraction + end if; + + end process; + + xromdo7q <= not xromdo7nq; + + gseqroma <= seqroma(4 downto 1) & not seqroma(0); + + eaoen <= i_tst1 nor xromdo7nq; + + end block; + + rom_block : block + alias a0 : std_logic is gseqroma(0); + alias a1 : std_logic is gseqroma(1); + alias a2 : std_logic is gseqroma(2); + alias a3 : std_logic is gseqroma(3); + alias a4 : std_logic is gseqroma(4); + alias xa5 : std_logic is nc2d9fin.val; + alias xa6 : std_logic is c2d9fin.val; + signal na : std_logic_vector(gseqroma'range); + alias na0 : std_logic is na(0); + alias na1 : std_logic is na(1); + alias na2 : std_logic is na(2); + alias na3 : std_logic is na(3); + alias na4 : std_logic is na(4); + + signal ny : std_logic_vector(yromdo'range); + + -- NOTE: vectors for norf must be range 0 to N! + signal xwl : std_logic_vector(0 to 11); + signal ywl : std_logic_vector(0 to 35); + + begin + na <= not gseqroma; + + ------------------------------------------------------------------------- + -- XROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + xwl <= na0 & a0 & a1 & na1 & na2 & a2 & a3 & na3 & na4 & a4 & xa5 & xa6; + + -- xwl(0) xwl(11) + -- na0 xa6 + -- | | + xromdo <= (-- | | + 00 => norf(xwl, "100110100100"), + 01 => norf(xwl, "010110010100"), + 02 => norf(xwl, "011010011000"), + 03 => norf(xwl, "011001011000"), + 04 => norf(xwl, "011001101000"), + 05 => norf(xwl, "011001100100"), + 06 => norf(xwl, "101001100100"), + 07 => norf(xwl, "100101100100"), + -- + 08 => norf(xwl, "100110100100"), + 09 => norf(xwl, "011010100100"), + 10 => norf(xwl, "101001101000"), + 11 => norf(xwl, "011001010100"), + 12 => norf(xwl, "011001101010"), + 13 => norf(xwl, "011010011010"), + 14 => norf(xwl, "100110100110"), + -- + 15 => norf(xwl, "101001000110"), + 16 => norf(xwl, "011001100101"), + 17 => norf(xwl, "011001011001"), + 18 => norf(xwl, "010110010101"), + 19 => norf(xwl, "010001010100"), + 20 => norf(xwl, "010101000000"), + 21 => norf(xwl, "011001100010"), + -- + 22 => norf(xwl, "000110000110"), + 23 => norf(xwl, "011001001001"), + 24 => norf(xwl, "010110011000"), + 25 => norf(xwl, "101000101000"), + 26 => norf(xwl, "010101011000"), + 27 => norf(xwl, "011000011010"), + 28 => norf(xwl, "100101101001"), + -- + 29 => norf(xwl, "000110000100"), + 30 => norf(xwl, "011010011000"), + 31 => norf(xwl, "001010101000"), + 32 => norf(xwl, "010101010000"), + 33 => norf(xwl, "100101101010"), + 34 => norf(xwl, "101001010100"), + 35 => norf(xwl, "101010011000"), + 36 => norf(xwl, "100110011000"), + others => '1'); + -- + ------------------------------------------------------------------------- + + + ------------------------------------------------------------------------- + -- YROM data out + -- + x_to_ywl : for idx in ywl'range generate + ywl(idx) <= xromdo(idx); + end generate; + + -- The sequence of the word lines must match the ROM bitmap below: + -- Leftmost word line is x0, rightmost word line is x35 + -- + -- ywl(0) ywl(35) + -- x0 x35 + -- | | + ny <= (-- | | + 04 => norf(ywl, "000000000100000000011000110000010001"), + 03 => norf(ywl, "000000000000111111111000100010000000"), + 02 => norf(ywl, "000000001001000000000111011010000000"), + 01 => norf(ywl, "000000000000000000000000000111111000"), + 00 => norf(ywl, "000000000000000000000000100000000111"), + others => '1'); + + c2d3gate <= norf(xromdo(7 downto 0)); + + yromdo <= not ny; + -- + ------------------------------------------------------------------------- + + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- COUNT DOWN + -- + cntdown_block : block + signal cntq : unsigned(7 downto 3) := (others => '0'); + begin + process (clkcntdn) + begin + if rising_edge(clkcntdn) then + if ncntdnload = '0' then + cntq(7 downto 4) <= unsigned(dinalq(7 downto 4)); + cntq(3) <= '1'; + + else + if ncntdn = '0' then + cntq <= cntq - 1; + end if; + + end if; + end if; + end process; + + cntdn0 <= '1' when cntq = 0 else '0'; + + end block; + + + + ----------------------------------------------------------------------------- + -- DIN ALIGNMENT + -- + din_block : block + signal dinlat : std_logic_vector(i_d'range) := (others => '0'); + signal ndincom : std_logic; + + signal latchhq, latchh : std_logic_vector(15 downto 8); + + begin + process (osc.base) + begin + if rising_edge(osc.base) then + if clkdin = '0' then + dinlat <= i_d; + end if; + end if; + end process; + + ndincom <= norf(dinlat and xromdo(7 downto 0)); + + process (clrdinal, c2d3gated) + begin + if clrdinal = '1' then + dinalq <= (others => '0'); + elsif rising_edge(c2d3gated) then + dinalq <= not ndincom & dinalq(7 downto 1); + end if; + end process; + + process (osc.base) + begin + if rising_edge(osc.base) then + if ealatchh = '1' then + latchhq <= dinalq; + end if; + end if; + end process; + + latchh(8) <= dinalq(0) when eavcu = '1' else + latchhq(8); + latchh(15 downto 9) <= (others => '0') when eavcu = '1' else + latchhq(15 downto 9); + + process (clk2ena) + begin + if rising_edge(clk2ena) then + if neaload = '0' then + -- parallel load + aq( 0) <= eavcu nor (not dinalq(0)); + aq( 7 downto 1) <= dinalq(7 downto 1); + aq(15 downto 8) <= latchh; + else + if eainc = '1' then + -- toggle/ripple + aq <= std_logic_vector(unsigned(aq) + 1); + end if; + end if; + end if; + end process; + + end block; + + + + ----------------------------------------------------------------------------- + -- Random data source + -- + random_block : block + signal lfsr : std_logic_vector(9 downto 0) := (others => '0'); + signal all0 : std_logic; + signal feedback : std_logic; + begin + + all0 <= norf(lfsr(lfsr'high-1 downto 0)); + + feedback <= (lfsr(9) xor lfsr(2)) nor all0; + + process (clk2ena) + begin + if rising_edge(clk2ena) then + lfsr <= lfsr(8 downto 0) & (rstdel nor feedback); + end if; + end process; + + random <= lfsr(9); + + end block; + + + + ----------------------------------------------------------------------------- + -- START control logic + -- + start_block : block + alias vcu : std_logic is i_vcu; + signal nvcu : std_logic; + + signal startq : std_logic_vector(2 downto 0); + alias startq0 : std_logic is startq(0); + alias startq1 : std_logic is startq(1); + alias startq2 : std_logic is startq(2); + signal startriseq : std_logic; + signal startriseqvcu : std_logic; + + signal ffsset : std_logic; + signal ffsloop : std_logic; + signal ffs1q, ffs2q, + ffs3q, ffs4q : std_logic := '1'; + signal ffs1nq, ffs2nq, + ffs3nq, ffs4nq : std_logic; + signal ffs5q : std_logic := '0'; + signal ffs5nq : std_logic; + signal vcumode : std_logic; + alias nvcumode : std_logic is ffs1q; + + signal vcufinal : std_logic; + signal vcufinal1q, + vcufinal2q : std_logic; + signal nvcufinal12 : std_logic; + + signal xromdo7nqdel : std_logic; + + signal msff1q, msff2q, + pmsff3q : std_logic := '1'; + signal msff1nq, msff2nq, + pmsff3nq : std_logic; + signal msffset : std_logic; + + signal n001x, n002x, n003x, n004x, n005x, n006x, + n007x, n008x, n009x, n014x, n015x, + n016x, n017x : std_logic; + signal n012x : t_clk; + + signal busy1q, + busy2q : std_logic; + signal setbusy1 : std_logic; + + begin + nvcu <= not vcu; + vcumode <= not nvcumode; + + vcufinal <= not nvcufinal; + + process (rstdel, clk2ena) + begin + if rstdel = '1' then + startq <= (others => '0'); + startriseq <= '1'; + + elsif rising_edge(clk2ena) then + startq <= startq(1 downto 0) & starttst; + startriseq <= startrise nand vcu; + + end if; + end process; + + startrise <= (not startq1) nor startq2; + startriseqvcu <= not startriseq; + + + ffsset <= rstdel or n005x; + process (ffsset, clk2ena) + begin + if ffsset = '1' then + ffs1q <= '1'; + ffs1q <= '1'; + ffs4q <= '1'; + ffs5q <= '0'; + elsif rising_edge(clk2ena) then + ffs1q <= (ffs1nq and ffsloop) nor (nvcu and startrise); -- async set + ffs2q <= (ffs2nq and ffsloop) nor ( vcu and startrise); -- async set + ffs4q <= (ffs4q nor startrise) nor (startq1 nor ffs3nq); -- async set + ffs5q <= ffs5nq nand ffsloop; -- async clr + + end if; + end process; + process (clk2ena) + begin + if rising_edge(clk2ena) then + ffs3q <= ffs1nq; -- no async set/clr + end if; + end process; + ffs1nq <= not ffs1q; + ffs2nq <= not ffs2q; + ffs3nq <= not ffs3q; + ffs4nq <= not ffs4q; + ffs5nq <= not ffs5q; + -- + ffsloop <= ffs1q or (not ffs3q) or (not fsromdo(6)); + + + process (vcufinal, clk2enb) + begin + if vcufinal = '1' then + vcufinal1q <= '1'; + vcufinal2q <= '1'; + + elsif rising_edge(clk2enb) then + vcufinal1q <= not vcufinal1q; + + if vcufinal1q = '1' then + vcufinal2q <= not vcufinal2q; + end if; + end if; + + end process; + + vcufinal12 <= (not vcufinal1q) nor (not vcufinal2q); + nvcufinal12 <= not vcufinal12; + nvcufinal <= rstdel nor (nvcumode nor (not ffs4q)); + + eavcu <= ffs2nq xor (ffs3q nor nvcumode); + + neaload <= (nvcumode or (ffs3q and (ffs2nq or (not fsromdo(6)) or nvcufinal12))); + + xromdo7nqdel_b : entity work.vlm5030_delay_inv + generic map ( + -- delay by ~558ns = 2 clocks + g_numclks => 2 + ) + port map ( + i_clk => osc, + i_in => xromdo7q, + o_out => xromdo7nqdel + ); + + clkdin <= (xromdo7nq and xromdo7nqdel and (vcumode or startriseqvcu)) nor ffs4nq; + + ealatchh <= startriseqvcu or (fsromdo(7) and ffs3q and vcufinal12); + + + msffset <= rstdel or startrise; + -- + process (msffset, c2d0) + begin + if msffset = '1' then + msff1q <= '1'; + elsif rising_edge(c2d0) then + msff1q <= n008x nor (pmsff3nq and xromdo(7)); + end if; + end process; + msff1nq <= not msff1q; + -- + process (msffset, c2d6) + begin + if msffset = '1' then + msff2q <= '1'; + elsif rising_edge(c2d6) then + msff2q <= msff2nq nor (xromdo(1) and n007x and pmsff3nq); + end if; + end process; + msff2nq <= not msff2q; + -- + process (c2d6) + begin + if rising_edge(c2d6) then + pmsff3q <= (n007x and xromdo(0)) nor (pmsff3nq and msff1q); + end if; + end process; + pmsff3nq <= not pmsff3q; + + + n001x <= not( (not fsromdo(7)) or nvcufinal12 or ffs2nq or ffs3nq ); + n002x <= not( dq(0) or vcufinal2q or vcufinal1q ); + n003x <= not( n002x or dq(1) or n004x ); + n004x <= vcufinal1q nor (not dq(0)); + n005x <= not( msff2q or n006x or nc2d6 ); + n006x <= n009x nand cntdn0; + n007x <= not( n003x or ffs5nq or (fsromdo(13) nand dinalq(7)) ); + n008x <= not( msff1q or rstdel or (not n006x) ); + n009x <= not( nvcufinal12 or (not fsromdo(6)) or (not xromdo(7)) ); + n012x <= not( nc2d10 or n003x or fsromevalout or ffs5nq ); + n014x <= n001x nor not( n003x or ffs5nq or fsromnorhigh ); + n015x <= not( dq(1) or n004x or (not ( vcufinal2q or (not vcufinal1q) or dq(0)) ) ); + n016x <= (not fsromdo(6)) nor (not( dq(1) or n017x or (dq(0) and vcufinal1q) )); + n017x <= not( dq(0) or (not vcufinal12) or (not vcufinal1q) ); + + ncntdn <= not( msff1nq and n009x and (not cntdn0) ); + + ncntdnload <= xromdo(5) nand pmsff3nq; + clkcntdn <= (c2d0 and msff1nq) or (c2d6 and (xromdo(5) and pmsff3nq)); + + clrdinal <= msff1nq or n012x; + + eainc <= n014x nor msff1nq; + + + setbusy1 <= startq1 nor startriseqvcu; + process (setbusy1, clk2ctrl) + begin + if setbusy1 = '1' then + busy1q <= '1'; + elsif rising_edge(clk2ctrl) then + busy1q <= startriseqvcu nor (not busy1q); + end if; + end process; + + process (ffsset, clk2ctrl) + begin + if ffsset = '1' then + busy2q <= '1'; + elsif rising_edge(clk2ctrl) then + busy2q <= vcumode nor (not busy2q); + end if; + end process; + + nbsy <= (not busy1q) nor (not busy2q); + + me <= not( ffs4q or i_start or xromdo7nq ); + + rflatchwen <= not( fsromevalout or n003x or nc2d6 ); + + asshift2 <= not( vcufinal2q or dq(1) or dq(0) ); + + updtpitch <= not( n015x or (not fsromdo(6)) or (not xromdo(11)) ); + + enrf2ID <= (not( n016x and (tstend2ID nor ffs5nq) )) nor nc2d8; + + clkksa <= n012x; + + ensum2ID <= not( ffs5nq or tstend2ID or ((n016x nor nc2d8) nor c2d4) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- K-Factor ROM + -- + krom_block : block + signal ka : std_logic_vector(4 downto 0); + begin + + agen_block : block + signal nfsrdo6 : std_logic; + signal ksaq : std_logic_vector(3 downto 0); + begin + + ka <= dinalq(7 downto 3); + + process (fsromdo(6), clkksa) + variable toggle : std_logic_vector(ksaq'high+1 downto 0); + begin + if fsromdo(6) = '1' then + ksaq <= "1011"; + + elsif rising_edge(clkksa) then + toggle(0) := '1'; + for idx in 0 to ksaq'high loop + if toggle(idx) = '1' then + ksaq(idx) <= not ksaq(idx); + end if; + + toggle(idx+1) := ksaq(idx) nor (not toggle(idx)); + end loop; + + end if; + end process; + + nfsrdo6 <= not fsromdo(6); + + ksa(3 downto 0) <= ( + 0 => ((not ksaq(0)) and nfsrdo6) nor (nfsrdo6 nor yromdo(3)), + 1 => ((not ksaq(1)) and nfsrdo6) nor (nfsrdo6 nor yromdo(2)), + 2 => ((not ksaq(2)) and nfsrdo6) nor (nfsrdo6 nor yromdo(1)), + 3 => ((not ksaq(3)) and nfsrdo6) nor (fsromdo(6) and (yromdo(0) xor (xromdo(10) nor xromdo(11)))) + ); + + end block; + + rom_block : block + signal kslice0, kslice1, kslice2, kslice3, kslice4, kslice5 : std_logic_vector(9 downto 0); + + -- NOTE: vectors for norf must be range 0 to N! + signal wl : std_logic_vector(0 to 31); + signal wl_slice : std_logic_vector(0 to 5); + + alias kaodd : std_logic is dinalq(2); + signal nkaodd : std_logic; + alias ksa0 : std_logic is ksa(0); + signal nksa0 : std_logic; + signal range_s0s1s2, range_s3s4 : std_logic; + + signal kout : std_logic_vector(nkdo'range); + begin + + process (ka) + begin + wl <= (others => '0'); + wl(to_integer(unsigned(ka))) <= '1'; + end process; + + --------------------------------------------------------------------------- + -- KROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + + -- wl(0) wl(31) + -- | | + kslice0 <= (-- | | + 00 => orf(wl, "11110111110000101101000111000101"), + 01 => orf(wl, "00000001001010110101010111101111"), + 02 => orf(wl, "00110111010011001110111111000001"), + 03 => orf(wl, "10110010011100000001101111010010"), + 04 => orf(wl, "10011011100000000001011111001011"), + 05 => orf(wl, "11011100000000000100111111000110"), + 06 => orf(wl, "11100000000000000110101010010100"), + 07 => orf(wl, "00000000000000001000110011100111"), + 08 => orf(wl, "00000000000000001111000011111000"), + 09 => orf(wl, "11111111111111110000000011111111"), + others => '0'); + + kslice1 <= ( + 00 => orf(wl, "00000100101110101100000110000011"), + 01 => orf(wl, "01011010100100111100111110001111"), + 02 => orf(wl, "11110001110111001101001110110111"), + 03 => orf(wl, "10001010111000000000011110011100"), + 04 => orf(wl, "01010011000000001110111110001000"), + 05 => orf(wl, "10011100000000001010000001111010"), + 06 => orf(wl, "11100000000000001100101010101100"), + 07 => orf(wl, "00000000000000000000110011001111"), + 08 => orf(wl, "00000000000000001111000011110000"), + 09 => orf(wl, "11111111111111110000000011111111"), + others => '0'); + + kslice2 <= ( + 00 => orf(wl, "11101010111101111111011110101011"), + 01 => orf(wl, "10111111010110001000010100101010"), + 02 => orf(wl, "11000100101011001110000001000100"), + 03 => orf(wl, "11111101000100101101101110100000"), + 04 => orf(wl, "10101001111101001110100000110101"), + 05 => orf(wl, "10011011010110001111001010010011"), + 06 => orf(wl, "11010010011000001111110011011010"), + 07 => orf(wl, "11100011100000001111111100011100"), + 08 => orf(wl, "11111100000000001111111111100000"), + 09 => orf(wl, "11111111111111111000000000000000"), + others => '0'); + + kslice3 <= ( + 00 => orf(wl, "10100100000001100111000110101010"), + 01 => orf(wl, "11001001010100100000001010010010"), + 02 => orf(wl, "11110001100110110101011001111100"), + 03 => orf(wl, "11111110000111000110010010101010"), + 04 => orf(wl, "11111111111000000111100011001100"), + 05 => orf(wl, "11111111111111111000000011110000"), + 06 => orf(wl, "11111111111111111111111100000000"), + others => '0'); + + kslice4 <= ( + 03 => orf(wl, "10101010100000000000000000000000"), + 04 => orf(wl, "11001100110101010111111111111111"), + 05 => orf(wl, "10001111000110011010101010000000"), + 06 => orf(wl, "11110000000111100011001100101010"), + 07 => orf(wl, "10000000000111111100001111001100"), + 08 => orf(wl, "11111111111000000000001111110000"), + 09 => orf(wl, "11111111111111111111110000000000"), + others => '0'); + + kslice5 <= ( + 06 => not ka(1), + 07 => not ka(2), + 08 => not ka(3), + 09 => not ka(4), + others => '0'); + -- + --------------------------------------------------------------------------- + + ------------------------------------------------------------------------- + -- Output mux + -- + range_s0s1s2 <= norf(ksa(3 downto 1)); + range_s3s4 <= ksa(2) nor (ksa(3) nand ksa(1)); + nkaodd <= not kaodd; + nksa0 <= not ksa0; + + -- NOTE: Each bitline forms a distributed complex gate: (enable) AND (OR'ed wl-transistors) + -- Bitlines from each slice are then NORed together to the data lines. + -- + -- 1. Wordlines are OR'ed on each bitline by the transistors + -- 2. The enable lines gate the effect of the bitline: + -- - enabled: can pull data line to 0 if result of OR is 1 + -- - not enabled: data line remains 1 + -- 3. Bitline result is visible as a NOR on the data line if enabled + -- + -- This model pre-calculates the bitlines above using OR and NORs + -- their results (enabled by the slice wls) onto the data lines. + -- + -- --> kout represents the data lines + + wl_slice <= (range_s0s1s2 and nksa0 and nkaodd) & -- enable kslice0 + (range_s0s1s2 and nksa0 and kaodd) & -- enable kslice1 + (range_s0s1s2 and ksa0 ) & -- enable kslice2 + (range_s3s4 and nksa0 ) & -- enable kslice3 + (range_s3s4 and ksa0 ) & -- enable kslice4 + (range_s0s1s2 nor range_s3s4 ) ; -- enable kslice5 + kout_gen : for idx in kout'range generate + kout(idx) <= norf(wl_slice, + kslice0(idx) & + kslice1(idx) & + kslice2(idx) & + kslice3(idx) & + kslice4(idx) & + kslice5(idx)); + end generate; + -- data lines are subsequently inverted by the INVBUFs + nkdo <= not kout; + + end block; + end block; + + + + ----------------------------------------------------------------------------- + -- Register file + -- + -- Memory map + -- + -- 9 8 7 6 5 4 3 2 1 0 + -- ksa[3..0] +---------------------+ + -- 11 | Pitch |XXXXXX| + -- +---------------------+ + -- 10 |XXXXXX| Energy | + -- +---------------------+ + -- 9 | K10 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 8 | K9 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 7 | K8 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 6 | K7 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 5 | K6 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 4 | K5 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 3 | K4 |XXXXXXXXXXXX| + -- +---------------------+ + -- 2 | K3 |XXXXXXXXXXXX| + -- +---------------------+ + -- 1 | K2 | + -- +---------------------+ + -- 0 | K1 | + -- +---------------------+ + -- + -- + regfile_block : block + signal rf0, rf1 : std_logic_vector(9 downto 0) := (others => '0'); + signal rf2, rf3 : std_logic_vector(9 downto 6) := (others => '0'); + signal rf4, rf5, + rf6, rf7, + rf8, rf9 : std_logic_vector(9 downto 7) := (others => '0'); + signal rf10 : std_logic_vector(6 downto 0) := (others => '0'); + signal rf11 : std_logic_vector(9 downto 3) := (others => '0'); + signal a : natural; + signal al : std_logic_vector(0 to 11); + signal nrfdo : std_logic_vector(rfdo'range); + + begin + a <= to_integer(unsigned(ksa)); + + process (osc.base) + begin + if rising_edge(osc.base) then + if rflatchwen = '1' then + case a is + when 0 => rf0 <= nkdo; + when 1 => rf1 <= nkdo; + when 2 => rf2 <= nkdo( rf2'range); + when 3 => rf3 <= nkdo( rf3'range); + when 4 => rf4 <= nkdo( rf4'range); + when 5 => rf5 <= nkdo( rf5'range); + when 6 => rf6 <= nkdo( rf6'range); + when 7 => rf7 <= nkdo( rf7'range); + when 8 => rf8 <= nkdo( rf8'range); + when 9 => rf9 <= nkdo( rf9'range); + when 10 => rf10 <= nkdo(rf10'range); + when 11 => rf11 <= nkdo(rf11'range); + when others => null; + end case; + end if; + end if; + end process; + + process (a) + begin + al <= (others => '0'); + if a <= al'high then + al(a) <= '1'; + end if; + end process; + + -- unimplemented bits read as '0' + -- they're coded with '1' here because the norif function inverts the vec operand + nrfdo(0) <= norif(al, rf0(0) & rf1(0) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(0) & '1' ); + nrfdo(1) <= norif(al, rf0(1) & rf1(1) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(1) & '1' ); + nrfdo(2) <= norif(al, rf0(2) & rf1(2) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(2) & '1' ); + nrfdo(3) <= norif(al, rf0(3) & rf1(3) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(3) & rf11(3) ); + nrfdo(4) <= norif(al, rf0(4) & rf1(4) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(4) & rf11(4) ); + nrfdo(5) <= norif(al, rf0(5) & rf1(5) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(5) & rf11(5) ); + nrfdo(6) <= norif(al, rf0(6) & rf1(6) & rf2(6) & rf3(6) & '1' & '1' & '1' & '1' & '1' & '1' & rf10(6) & rf11(6) ); + nrfdo(7) <= norif(al, rf0(7) & rf1(7) & rf2(7) & rf3(7) & rf4(7) & rf5(7) & rf6(7) & rf7(7) & rf8(7) & rf9(7) & '1' & rf11(7) ); + nrfdo(8) <= norif(al, rf0(8) & rf1(8) & rf2(8) & rf3(8) & rf4(8) & rf5(8) & rf6(8) & rf7(8) & rf8(8) & rf9(8) & '1' & rf11(8) ); + nrfdo(9) <= norif(al, rf0(9) & rf1(9) & rf2(9) & rf3(9) & rf4(9) & rf5(9) & rf6(9) & rf7(9) & rf8(9) & rf9(9) & '1' & rf11(9) ); + -- register file ouputs are subsequently inverted by the INVBUFs + rfdo <= not nrfdo; + + rfdo97zero <= norf(rfdo(9 downto 7)); + + end block; + + + + ----------------------------------------------------------------------------- + -- ADDSHIFT + -- + addshift_block : block + signal nIDlat, port_nID, + port_rf : std_logic_vector(nID'range); + signal sumlat : std_logic_vector(nID'high+2 downto 0); + signal cin, sum : std_logic_vector(nID'high+1 downto 0); + signal idpos : std_logic; + begin + + idpos <= not( (dq(6) and updtpitch) nor c2d5fin); + + cin(0) <= not idpos; + + -- + -- Generate adder/shifter slices + -- + addshift_slice : for idx in nID'high downto 0 generate + + -- nID bus latch cell + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d1 = '1' then + nIDlat(idx) <= nID(idx); + end if; + end if; + end process; + + -- adder port: nID bus + port_nID(idx) <= not nIDlat(idx) when idpos = '1' else nIDlat(idx); + -- adder port: registerfile or shift + port_rf(idx) <= rfdo(idx) when c2d5fin = '0' else + sumlat(idx+1) when asshift2 = '0' else + sumlat(idx+2); + -- xor3 cell + sum(idx) <= port_nID(idx) xor port_rf(idx) xor cin(idx); + -- carry cell + cin(idx+1) <= (port_nID(idx) and port_rf(idx)) or ((port_nID(idx) or port_rf(idx)) and cin(idx)); + + -- sum latch cell + -- note: sumlat[0] is omitted on the die + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d4 = '1' then + sumlat(idx) <= sum(idx); + end if; + end if; + end process; + end generate; + + -- extra cells + sum(nID'high+1) <= cin(nID'high+1) xor port_nID(nID'high) xor port_rf(nID'high); + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d4 = '1' then + sumlat(nID'high+1) <= sum(nID'high+1); + end if; + end if; + end process; + sumlat(nID'high+2) <= sumlat(nID'high+1); + + assum <= sum(nID'range); + + end block; + + + + ----------------------------------------------------------------------------- + -- Pitch incrementer + -- + pitchinc_block : block + signal pitchlat, + pitchreg : std_logic_vector(9 downto 3) := (others => '0'); + signal toggle : std_logic_vector(pitchreg'high+1 downto pitchreg'low); + begin + + enpitchlat <= not (c2d4 nand updtpitch); + + process (osc.base) + begin + if rising_edge(osc.base) then + if enpitchlat = '1' then + pitchlat <= nID(pitchlat'range); + end if; + end if; + end process; + + process (rstdel, clk2ena) + begin + if rstdel = '1' then + pitchreg <= (others => '0'); + + elsif rising_edge(clk2ena) then + if pitchoverflow = '1' then + -- load + pitchreg <= pitchlat; + else + -- toggle reg + for idx in pitchreg'range loop + if toggle(idx) = '1' then + pitchreg(idx) <= not pitchreg(idx); + end if; + end loop; + end if; + + end if; + end process; + + toggle(3) <= '1'; + gen_toggle: for idx in 4 to toggle'high generate + toggle(idx) <= (not pitchreg(idx-1)) nor (not toggle(idx-1)); + end generate; + + pitchoverflow <= toggle(toggle'high); + + end block; + + + pitchmod <= not( (not(dq(6) xor dq(7))) or tstend2ID or nc2d1 ); + + + + ----------------------------------------------------------------------------- + -- nID bus + -- + nID_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= tstend2ID & enrf2ID & ensum2ID & updtpitch & enIDlinv2ID & enmem02ID ; + -- | | | | | | | + nID(0) <= norf(wl, i_d(0) & rfdo(0) & assum(0) & '0' & not idlat(0) & nmem0do(0) ); + nID(1) <= norf(wl, i_d(1) & rfdo(1) & assum(1) & '0' & not idlat(1) & nmem0do(1) ); + nID(2) <= norf(wl, i_d(2) & rfdo(2) & assum(2) & '0' & not idlat(2) & nmem0do(2) ); + nID(3) <= norf(wl, i_d(3) & rfdo(3) & assum(3) & '0' & not idlat(3) & nmem0do(3) ); + nID(4) <= norf(wl, i_d(4) & rfdo(4) & assum(4) & '0' & not idlat(4) & nmem0do(4) ); + nID(5) <= norf(wl, i_d(5) & rfdo(5) & assum(5) & '0' & not idlat(5) & nmem0do(5) ); + nID(6) <= norf(wl, i_d(6) & rfdo(6) & assum(6) & pitchmod & not idlat(6) & nmem0do(6) ); + nID(7) <= norf(wl, i_d(7) & rfdo(7) & assum(7) & '0' & not idlat(7) & nmem0do(7) ); + nID(8) <= norf(wl, i_d(0) & rfdo(8) & assum(8) & '0' & '0' & nmem0do(8) ); + nID(9) <= norf(wl, i_d(1) & rfdo(9) & assum(9) & '0' & '0' & nmem0do(9) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- ID Latch + -- + idlat_block : block + signal idlaten : std_logic; + signal n : std_logic; + begin + + idlaten <= not( (not fsromdo(6)) or (not xromdo(10)) or nc2d8 ); + enIDlinv2ID <= not( (not xromdo(10)) or tstend2ID or nc2d1 ); + + n <= xromdo7q or tstend2IE or c2d7fin; + enIDlinv2IE <= (not( (maskdq53 and random) or ((not maskdq53) and pitchoverflow) )) nor n; + enIDl2IE <= not( n or random or idlatall1 or (not maskdq53) ); + + process (osc.base) + begin + if rising_edge(osc.base) then + if idlaten = '1' then + idlat <= nID(7 downto 0); + end if; + end if; + end process; + + idlatall1 <= norf(not idlat); + + end block; + + + + ----------------------------------------------------------------------------- + -- Memories + -- + mem_block : block + signal swapa : unsigned(3 downto 0); + signal a : natural; + + signal clkmem0, clkmem1, clkmem2 : std_logic; + + type t_mem0 is array(0 to 9) of std_logic_vector(nID'range); + signal mem0 : t_mem0 := (others => (others => '0')); + type t_mem1 is array(0 to 9) of std_logic_vector(nIE'range); + signal mem1 : t_mem1 := (others => (others => '0')); + type t_mem2 is array(0 to 8) of std_logic_vector(nIE'range); + signal mem2 : t_mem2 := (others => (others => '0')); + begin + + yswap_gen : for idx in 3 downto 0 generate + swapa(idx) <= yromdo(3-idx); + end generate; + a <= to_integer(swapa); + + -- + -- MEM0 + -- + clkmem0 <= not( xromdo(7) or (not fsromdo(6)) or (xromdo7q and yromdo(4)) or nc2d8 ); + enmem02ID <= not( tstend2ID or (xromdo7q and yromdo(4)) or nc2d1 ); + + mem0_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem0 = '1' then + if a <= t_mem0'high then + mem0(a) <= nID; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + nmem0do <= not mem0(a) when a <= t_mem0'high else (others => '1'); + mem0do <= not nmem0do; + + + -- + -- MEM1 + -- + clkmem1 <= yromdo(4) nor nc2d10; + enmem12IE <= not( yromdo(4) or tstend2IE or c2d7fin ); + + mem1_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem1 = '1' then + if a <= t_mem1'high then + mem1(a) <= nIE; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + mem1do2IE <= not mem1(a) when a <= t_mem1'high else (others => '1'); + + + -- + -- MEM2 + -- + clkmem2 <= yromdo(4) and c2d10; + enmem22IE <= not( tstend2IE or (not xromdo(7)) or nc2d10 ); + + mem2_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem2 = '1' then + if a <= t_mem2'high then + mem2(a) <= nIE; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + mem2do2IE <= not mem2(a) when a <= t_mem2'high else (others => '1'); + + + end block; + + + ----------------------------------------------------------------------------- + -- Arithmetic block + -- + arithmetic_block : block + signal memxdo : std_logic_vector(nIE'range); + signal wl : std_logic_vector(0 to 1); + constant num_slices : natural := nIE'high+2; -- 13 slices + + type r_row is record + line1 : std_logic; + line2 : std_logic; + line3 : std_logic; + line4in : std_logic_vector(num_slices-1+1 downto 0); + lxor : std_logic_vector(num_slices-1 downto 0); + sum : std_logic_vector(num_slices-1 downto 0); + carry : std_logic_vector(num_slices-1 downto 0); + rowcarry1, rowcarry2 : std_logic; + end record; + signal row0, row1, row2, row3, row4 : r_row; + + -- map the slice index to the memxdo index + function map_slice_memxdo_f (slice : natural) return natural is + begin + if slice <= 9 then + -- slices 0 to 9 are supplied by memxdo(9) downto (0) + return 9-slice; + elsif slice = 10 then + -- slice 10 is supplied by memxdo(11) + return 11; + elsif slice = 11 then + -- slice 11 is supplied by memxdo(10) + return 10; + else + -- invalid slice + return 100; + end if; + end; + -- + function line1_f(odd_prev : std_logic; + even : std_logic) return std_logic is + begin + return not (odd_prev xor (not even)); + end; + -- + function line2_f(odd_prev : std_logic; + even : std_logic; + odd : std_logic) return std_logic is + begin + return ( + (not odd_prev) + and (not even) + and odd + ) or ( + odd_prev + and even + and (not odd) + ); + end; + -- + function xor_f (line4_upper : std_logic; + line1 : std_logic; + line2 : std_logic; + line3 : std_logic; + line4_lower : std_logic) return std_logic is + begin + return line3 xor not((line4_upper and line2) or (line4_lower and line1)); + end; + -- + function sum_f (porta : std_logic; + portb : std_logic; + carry : std_logic) return std_logic is + begin + return porta xor portb xor carry; + end; + -- + function carry_f (porta : std_logic; + portb : std_logic; + carry : std_logic) return std_logic is + begin + return ( + carry and (porta or portb) + ) or ( + porta and portb + ); + end; + -- + function map_slice_ie_f (slice : natural) return natural is + begin + return map_slice_memxdo_f(slice); + end; + + signal oeq, oenq : std_logic; + signal memlatmuxq : std_logic_vector(nIE'range); + type r_memlatmux is record + sum : std_logic_vector(nIE'range); + carry : std_logic_vector(nIE'range); + end record; + signal memlatmux : r_memlatmux; + + type r_iereg is record + q : std_logic_vector(nIE'range); + portb : std_logic_vector(nIE'range); + cout : std_logic_vector(nIE'high+1 downto 0); + sum : std_logic_vector(nIE'range); + end record; + signal iereg : r_iereg; + + begin + + wl <= yromdo(4) & not yromdo(4); + memxdo_gen : for idx in memxdo'range generate + memxdo(idx) <= norf(wl, mem1do2IE(idx) & mem2do2IE(idx)); + end generate; + + + -- + -- Row 0 + -- + row0.line1 <= line1_f(odd_prev => '1', + even => mem0do(0)); + row0.line2 <= (not mem0do(0)) nor mem0do(1); -- line2_f with odd_prev='1' + row0.line3 <= mem0do(1); + row0.line4in(0) <= row0.line4in(1); -- metal short between upper and lower line4 + -- preset with 0 to replicate unimplemented left half of MUXI + row0.line4in(13) <= '0'; + -- + row0_gen_low : for slice in 0 to 11 generate + row0.line4in(slice+1) <= not memxdo(map_slice_memxdo_f(slice)); + row0.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row0.line1, + line2 => row0.line2, + line3 => row0.line3, + line4_lower => row0.line4in(slice)); + row0.sum(slice) <= sum_f(porta => row0.lxor(slice), + portb => '0', + carry => '0'); + row0.carry(slice) <= '0'; + end generate; + + -- rowcarry is built based on slice 11 + row0.rowcarry1 <= not( (row0.line1 and row0.line4in(12)) or (row0.line3 or (not row0.sum(11))) ); + row0.rowcarry2 <= row0.rowcarry1; + + -- + -- Row 1 + -- + row1.line1 <= line1_f(odd_prev => mem0do(1), + even => mem0do(2)); + row1.line2 <= line2_f(odd_prev => mem0do(1), + even => mem0do(2), + odd => mem0do(3)); + row1.line3 <= mem0do(3); + row1.line4in <= (others => '0'); + -- slices 0 and 1 + row1_gen_0_1 : for slice in 0 to 1 generate + row1.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(slice)); + row1.sum(slice) <= not row1.lxor(slice); + row1.carry(slice) <= '0' when slice = 0 else + row1.lxor(slice); + end generate; + -- slice 2 has special carry calculation + row1.lxor(2) <= xor_f(line4_upper => row0.line4in(2+1), + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(2)); + row1.sum(2) <= sum_f(porta => row1.lxor(2), + portb => row0.sum(2-2), + carry => '0'); -- just XOR lxor with sum-2 + row1.carry(2) <= (not row1.lxor(2)) nand row0.sum(2-2); -- special operator in slice 2 + -- slices 3 to 12 + row1_gen_upper : for slice in 3 to num_slices-1 generate + row1.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(slice)); + row1.sum(slice) <= sum_f(porta => row1.lxor(slice), + portb => row0.sum(slice-2), + carry => '0'); -- just XOR lxor with sum-2 + row1.carry(slice) <= carry_f(porta => row1.lxor(slice), + portb => row0.sum(slice-2), + carry => '0'); -- just AND lxor with sum-2 + end generate; + + -- rowcarry chain + row1.rowcarry1 <= carry_f(porta => not row1.line3, + portb => row1.sum(12), + carry => row0.rowcarry2); + row1.rowcarry2 <= carry_f(porta => row1.carry(12), + portb => row1.sum(11), + carry => row1.rowcarry1); + + + -- + -- Row 2 + -- + row2.line1 <= line1_f(odd_prev => mem0do(3), + even => mem0do(4)); + row2.line2 <= line2_f(odd_prev => mem0do(3), + even => mem0do(4), + odd => mem0do(5)); + row2.line3 <= mem0do(5); + row2.line4in <= (others => '0'); + -- slices 0 and 1 + row2_gen_0_1 : for slice in 0 to 1 generate + row2.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row2.line1, + line2 => row2.line2, + line3 => row2.line3, + line4_lower => row0.line4in(slice)); + row2.sum(slice) <= not row2.lxor(slice); + row2.carry(slice) <= '0' when slice = 0 else + row2.lxor(slice); + end generate; + -- slices 2 to 12 + row2_gen_upper : for slice in 2 to num_slices-1 generate + row2.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row2.line1, + line2 => row2.line2, + line3 => row2.line3, + line4_lower => row0.line4in(slice)); + row2.sum(slice) <= sum_f(porta => row2.lxor(slice), + portb => row1.sum(slice-2), + carry => row1.carry(slice-1)); + row2.carry(slice) <= carry_f(porta => row2.lxor(slice), + portb => row1.sum(slice-2), + carry => row1.carry(slice-1)); + end generate; + + -- rowcarry chain + row2.rowcarry1 <= carry_f(porta => not row2.line3, + portb => row2.sum(12), + carry => row1.rowcarry2); + row2.rowcarry2 <= carry_f(porta => row2.carry(12), + portb => row2.sum(11), + carry => row2.rowcarry1); + + -- + -- Row 3 + -- + row3.line1 <= line1_f(odd_prev => mem0do(5), + even => mem0do(6)); + row3.line2 <= line2_f(odd_prev => mem0do(5), + even => mem0do(6), + odd => mem0do(7)); + row3.line3 <= mem0do(7); + row3.line4in <= (others => '0'); + -- slices 0 and 1 + row3_gen_0_1 : for slice in 0 to 1 generate + row3.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row3.line1, + line2 => row3.line2, + line3 => row3.line3, + line4_lower => row0.line4in(slice)); + row3.sum(slice) <= not row3.lxor(slice); + row3.carry(slice) <= '0' when slice = 0 else + row3.lxor(slice); + end generate; + -- slices 2 to 12 + row3_gen_upper : for slice in 2 to num_slices-1 generate + row3.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row3.line1, + line2 => row3.line2, + line3 => row3.line3, + line4_lower => row0.line4in(slice)); + row3.sum(slice) <= sum_f(porta => row3.lxor(slice), + portb => row2.sum(slice-2), + carry => row2.carry(slice-1)); + row3.carry(slice) <= carry_f(porta => row3.lxor(slice), + portb => row2.sum(slice-2), + carry => row2.carry(slice-1)); + end generate; + + -- rowcarry chain + row3.rowcarry1 <= carry_f(porta => not row3.line3, + portb => row3.sum(12), + carry => row2.rowcarry2); + row3.rowcarry2 <= carry_f(porta => row3.carry(12), + portb => row3.sum(11), + carry => row3.rowcarry1); + + -- + -- Row 4 + -- + row4.line1 <= line1_f(odd_prev => mem0do(7), + even => mem0do(8)); + row4.line2 <= line2_f(odd_prev => mem0do(7), + even => mem0do(8), + odd => mem0do(9)); + row4.line3 <= mem0do(9); + row4.line4in <= (others => '0'); + -- slices 0 and 1 + row4_gen_0_1 : for slice in 0 to 1 generate + row4.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row4.line1, + line2 => row4.line2, + line3 => row4.line3, + line4_lower => row0.line4in(slice)); + row4.sum(slice) <= not row4.lxor(slice); + row4.carry(slice) <= '0' when slice = 0 else + row4.lxor(slice); + end generate; + -- slices 2 to 12 + row4_gen_upper : for slice in 2 to num_slices-1 generate + row4.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row4.line1, + line2 => row4.line2, + line3 => row4.line3, + line4_lower => row0.line4in(slice)); + row4.sum(slice) <= sum_f(porta => row4.lxor(slice), + portb => row3.sum(slice-2), + carry => row3.carry(slice-1)); + row4.carry(slice) <= carry_f(porta => row4.lxor(slice), + portb => row3.sum(slice-2), + carry => row3.carry(slice-1)); + end generate; + + -- rowcarry chain + row4.rowcarry1 <= carry_f(porta => not row4.line3, + portb => row4.sum(12), + carry => row3.rowcarry2); + row4.rowcarry2 <= row4.rowcarry1; + + + -- + -- MEMLATMUX + -- + memlatmux_p : process (c2d7fin) + begin + if rising_edge(c2d7fin) then + memlatmuxq <= not ieregdrv; + end if; + end process; + -- + gen_memlatmux : for slice in 0 to memlatmuxq'high generate + memlatmux.sum(slice) <= row4.carry(slice+1) when c2d7fin = '0' else + memlatmuxq(slice) when yromdo(4) = '0' else -- OEQ /c2d7fin nor yromdo(4) = '1' + not memlatmuxq(slice); -- OEnQ /c2d7fin nor /yromdo(4) = '1' + memlatmux.carry(slice) <= row4.sum(slice); + end generate; + + + -- + -- IEREG level + -- + + -- represents MUX on output of ROWCARRY chain + iereg.cout(iereg.cout'high) <= not yromdo(4) when c2d7fin = '1' else + row4.rowcarry2; + iereg_gen : for slice in 0 to nIE'high generate + + -- IEREG + iereg_p : process (ieregload) + begin + if falling_edge(ieregload) then + iereg.q(slice) <= nIE(map_slice_ie_f(slice)); + end if; + end process; + + iereg.portb(slice) <= not iereg.q(slice) when c2d7fin = '1' else + memlatmux.carry(slice); + iereg.cout(slice) <= carry_f(porta => memlatmux.sum(slice), + portb => iereg.portb(slice), + carry => iereg.cout(slice+1)); + iereg.sum(slice) <= sum_f(porta => memlatmux.sum(slice), + portb => iereg.portb(slice), + carry => iereg.cout(slice+1)); + end generate; + + ieregdrv <= iereg.sum when ( ((not iereg.cout(0)) xor (not iereg.cout(1))) nand c2d7fin ) = '1' else + (others => '1') when not( iereg.cout(1) or (not iereg.cout(0)) or nc2d7fin ) = '1' else + (others => '0') when not( (not iereg.cout(1)) or iereg.cout(0) or nc2d7fin ) = '1' else + (others => 'X'); -- invalid + iregdrv_gen : for slice in 0 to nIE'high generate + ieregdrv4IE(slice) <= ieregdrv(map_slice_ie_f(slice)); + end generate; + + ieregload <= ( (c2d10 and yromdo(4)) or ( c2d6 and (xromdo7q nand yromdo(4) ) ) ); + enieregfa2IE <= not( tstend2IE or xromdo(7) or nc2d10 ); + + + -- + -- nIE distribution to ABUS and DAC + -- + c2d10xr9 <= c2d10 and xromdo(9); + enIE2A <= i_tst1 nor xromdo7q; + + ieaddr_p : process (c2d10xr9) + begin + if falling_edge(c2d10xr9) then + ieaddrreg <= not nIE; + end if; + end process; + + end block; + + + ----------------------------------------------------------------------------- + -- nIE bus + -- + nIE_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= enIDlinv2IE & enIDl2IE & enmem12IE & enmem22IE & enieregfa2IE & tstend2IE; + -- | | | | | | | + nIE( 0) <= norf(wl, '0' & '1' & mem1do2IE( 0) & mem2do2IE( 0) & ieregdrv4IE( 0) & i_d(0) ); + nIE( 1) <= norf(wl, not idlat(0) & idlat(0) & mem1do2IE( 1) & mem2do2IE( 1) & ieregdrv4IE( 1) & i_d(1) ); + nIE( 2) <= norf(wl, not idlat(1) & idlat(1) & mem1do2IE( 2) & mem2do2IE( 2) & ieregdrv4IE( 2) & i_d(2) ); + nIE( 3) <= norf(wl, not idlat(2) & idlat(2) & mem1do2IE( 3) & mem2do2IE( 3) & ieregdrv4IE( 3) & i_d(3) ); + nIE( 4) <= norf(wl, not idlat(3) & idlat(3) & mem1do2IE( 4) & mem2do2IE( 4) & ieregdrv4IE( 4) & i_d(4) ); + nIE( 5) <= norf(wl, not idlat(4) & idlat(4) & mem1do2IE( 5) & mem2do2IE( 5) & ieregdrv4IE( 5) & i_d(5) ); + nIE( 6) <= norf(wl, not idlat(5) & idlat(5) & mem1do2IE( 6) & mem2do2IE( 6) & ieregdrv4IE( 6) & i_d(6) ); + nIE( 7) <= norf(wl, not idlat(6) & idlat(6) & mem1do2IE( 7) & mem2do2IE( 7) & ieregdrv4IE( 7) & i_d(7) ); + nIE( 8) <= norf(wl, not idlat(7) & idlat(7) & mem1do2IE( 8) & mem2do2IE( 8) & ieregdrv4IE( 8) & i_d(0) ); + nIE( 9) <= norf(wl, '0' & '1' & mem1do2IE( 9) & mem2do2IE( 9) & ieregdrv4IE( 9) & i_d(1) ); + nIE(10) <= norf(wl, '0' & '1' & mem1do2IE(10) & mem2do2IE(10) & ieregdrv4IE(10) & i_d(2) ); + nIE(11) <= norf(wl, '0' & '1' & mem1do2IE(11) & mem2do2IE(11) & ieregdrv4IE(11) & i_d(3) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- DAC block + -- + dac_block : block + signal pwmsel : std_logic; + begin + + pwm_block : block + signal pwm0, pwm1, pwm2 : std_logic; + + signal nc2d10xr9del : std_logic; + signal nclk2gd5hi, + nclk2gd5lo : std_logic; + + signal pwmreg1toggle, + pwmreg2toggle : std_logic; + signal pwmreg0, pwmreg1, + pwmreg2 : std_logic; + + signal pwmcomm, + pwmcommdel, + pwmcommand : std_logic; + signal pwmcomp : std_logic; + + begin + + pwm2 <= ieaddrreg(4) when tstenIE2DAC = '0' else nIE(4); + pwm1 <= ieaddrreg(3) when tstenIE2DAC = '0' else nIE(3); + pwm0 <= ieaddrreg(2) when tstenIE2DAC = '0' else nIE(2); + + nc2d10xr9del_b : entity work.vlm5030_delay_inv + generic map ( + -- delay by ~1.1us = 4 osc clocks + g_numclks => 4 + ) + port map ( + i_clk => osc, + i_in => c2d10xr9.val, + o_out => nc2d10xr9del + ); + nclk2gd5hi <= nc2d10xr9del nor clk2gd5; + nclk2gd5lo <= (not nc2d10xr9del) nor clk2gd5; + + pwmreg1toggle <= pwmreg0; + pwmreg2toggle <= (not pwmreg1) nor (not pwmreg0); + + process (clk2gd5) + begin + if rising_edge(clk2gd5) then + if nc2d10xr9del = '0' then + -- clear + pwmreg0 <= '0'; + pwmreg1 <= '0'; + pwmreg2 <= '0'; + + else + pwmreg0 <= not pwmreg0; + if pwmreg1toggle = '1' then + pwmreg1 <= not pwmreg1; + end if; + if pwmreg2toggle = '1' then + pwmreg2 <= not pwmreg2; + end if; + end if; + end if; + + end process; + + pwmcomm <= norf(pwmreg0 & pwmreg1 & pwmreg2); + pwmcommdel_b : entity work.vlm5030_delay + generic map ( + -- delay by ~1.1us = 4 osc clocks + g_numclks => 4 + ) + port map ( + i_clk => osc, + i_in => pwmcomm, + o_out => pwmcommdel + ); + pwmcommand <= pwmcomm and pwmcommdel; + + pwmcomp <= norif(pwm2 & pwm1 & pwm0, pwmreg2 & pwmreg1 & pwmreg0); + + pwmsr_b : entity work.vlm5030_srlatch + port map ( + i_clk => osc.base, + i_res => pwmcomp, + i_set => pwmcommand, + o_q => pwmsr + ); + pwmsel <= not i_vcu when tstenIE2DAC = '1' else + not pwmsr; + + end block; + + dacrom_block : block + signal ndac : std_logic_vector(4 downto 0); + signal dacval, dacpwm : signed(o_dao'high+1 downto 0); + begin + + ndac <= not ieaddrreg(9 downto 5) when tstenIE2DAC = '0' else + not nIE(9 downto 5); + + -- The R-ladder between GND and VREF has 34 segments. + -- * the lowest setting (-16 & pwmsel=1) generates 33 over 1 + -- * the highest setting (15 & pwmsel=0) generates 1 over 33 + -- TODO: check absolute resistance value of segments + + -- dacval is range 1 to 32 + dacval <= RESIZE(signed(not ndac), dacval'length) + 16+1; + -- dacpwm is range 1 to 33 + dacpwm <= dacval when pwmsel = '1' else dacval + 1; + + o_dao <= std_logic_vector(dacpwm(o_dao'range)); + -- TST2 not modelled + o_tst2 <= '0'; + + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- Address bus block + -- + abus_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= eaoen & enIE2A & tstenID2A & tstenIE2A & tstenctrl2A & tstenIE2DAC; + -- | | | | | | | + o_a( 0) <= not norf(wl, aq( 0) & ieaddrreg(0) & not nID(0) & not nIE( 0) & '0' & '0' ); + o_a( 1) <= not norf(wl, aq( 1) & ieaddrreg(1) & not nID(1) & not nIE( 1) & '0' & '0' ); + o_a( 2) <= not norf(wl, aq( 2) & ieaddrreg(2) & not nID(2) & not nIE( 2) & '0' & '0' ); + o_a( 3) <= not norf(wl, aq( 3) & ieaddrreg(3) & not nID(3) & not nIE( 3) & '0' & '0' ); + o_a( 4) <= not norf(wl, aq( 4) & ieaddrreg(4) & not nID(4) & not nIE( 4) & '0' & '0' ); + o_a( 5) <= not norf(wl, aq( 5) & ieaddrreg(5) & not nID(5) & not nIE( 5) & '0' & '0' ); + o_a( 6) <= not norf(wl, aq( 6) & ieaddrreg(6) & not nID(6) & not nIE( 6) & '0' & '0' ); + o_a( 7) <= not norf(wl, aq( 7) & ieaddrreg(7) & not nID(7) & not nIE( 7) & '0' & '0' ); + o_a( 8) <= not norf(wl, aq( 8) & ieaddrreg(8) & not nID(8) & not nIE( 8) & '0' & '0' ); + o_a( 9) <= not norf(wl, aq( 9) & not ieaddrreg(9) & not nID(9) & not nIE( 9) & '0' & '0' ); + o_a(10) <= not norf(wl, aq(10) & pitchoverflow & '0' & '0' & c2d0.val & pwmsr ); + o_a(11) <= not norf(wl, aq(11) & random & '0' & '0' & xromdo7nq & '0' ); + o_a(12) <= not norf(wl, aq(12) & ieaddrreg(10) & '0' & not nIE(10) & fsromdo(13) & '0' ); + o_a(13) <= not norf(wl, aq(13) & ieaddrreg(11) & '0' & not nIE(11) & vcufinal12 & '0' ); + o_a(14) <= not norf(wl, aq(14) & '0' & '0' & '0' & cntdn0 & '0' ); + o_a(15) <= not norf(wl, aq(15) & '0' & '0' & '0' & '0' & '0' ); + + end block; + + + o_audio <= ieaddrreg(9 downto 0); + + o_bsy <= not nbsy; + + o_me_l <= not me; + + mte_delay_b : entity work.vlm5030_delay + generic map ( + -- delay for ~6us ==> 21 osc clocks + g_numclks => 21 + ) + port map ( + i_clk => osc, + i_in => xromdo(35), + o_out => o_mte + ); + +end; diff --git a/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_pack.vhd b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_pack.vhd new file mode 100644 index 00000000..fdf0771f --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_pack.vhd @@ -0,0 +1,217 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- + + +library ieee; +use ieee.std_logic_1164.all; + +package vlm5030_pack is + + ----------------------------------------------------------------------------- + -- Verctorized NOR and OR functions + ----------------------------------------------------------------------------- + function norf(i : std_logic_vector) return std_logic; + function norf(wl, vec : std_logic_vector) return std_logic; + function norif(wl, vec : std_logic_vector) return std_logic; + function orf(wl, vec : std_logic_vector) return std_logic; + + ----------------------------------------------------------------------------- + -- Transparent handling of clock enables + -- + -- Basic type def + type t_clk is record + base : std_logic; + val : std_logic; + rise : std_logic; + fall : std_logic; + end record; + constant z_clk : t_clk := ( + base => '0', + val => '0', + rise => '0', + fall => '0'); + + -- Overloaded functions for synchronous process template + function rising_edge(signal clk : t_clk) return boolean; + function falling_edge(signal clk : t_clk) return boolean; + + -- Overloaded functions for boolean arithmetic on clocks + function "not" (clk : t_clk) return t_clk; + -- + function "and" (clk1, clk2 : t_clk) return t_clk; + function "and" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "and" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "nand" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "nand" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "or" (clk1, clk2 : t_clk) return t_clk; + function "or" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "or" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "nor" (clk1, clk2 : t_clk) return t_clk; + function "nor" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "nor" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "=" (clk1 : t_clk; op2 : std_logic) return boolean; + +end; + +package body vlm5030_pack is + + function norf(i : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in i'range loop + lorf := lorf or i(idx); + end loop; + return not lorf; + end; + + function norf(wl, vec : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in wl'range loop + lorf := lorf or (wl(idx) and vec(idx)); + end loop; + return not lorf; + end; + + function norif(wl, vec : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in wl'range loop + lorf := lorf or (wl(idx) and not vec(idx)); + end loop; + return not lorf; + end; + + function orf(wl, vec : std_logic_vector) return std_logic is + begin + return not norf(wl, vec); + end; + + ----------------------------------------------------------------------------- + + function rising_edge(signal clk : t_clk) return boolean is + begin + return rising_edge(clk.base) and clk.rise = '1'; + end; + + function falling_edge(signal clk : t_clk) return boolean is + begin + return rising_edge(clk.base) and clk.fall = '1'; + end; + + function "not" (clk : t_clk) return t_clk is + begin + return (base => clk.base, + val => not clk.val, + rise => clk.fall, + fall => clk.rise); + end; + + function "and" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val and clk2.val, + rise => (clk1.rise and clk2.val and not clk2.fall) or + (clk2.rise and clk1.val and not clk1.fall), + fall => (clk1.fall and clk2.val) or + (clk2.fall and clk1.val)); + end; + + function "and" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val and op2, + rise => clk1.rise and op2, + fall => clk1.fall and op2); + end; + + function "and" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 and clk2.val; + end; + + function "nand" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nand op2, + rise => clk1.fall and op2, + fall => clk1.rise and op2); + end; + + function "nand" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 nand clk2.val; + end; + + function "or" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val or clk2.val, + rise => (clk1.rise and not clk2.val) or + (clk2.rise and not clk1.val), + fall => (clk1.fall and not clk2.val and not clk2.rise) or + (clk2.fall and not clk1.val and not clk1.rise)); + end; + + function "or" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val or op2, + rise => clk1.rise and not op2, + fall => clk1.fall and not op2); + end; + + function "or" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 or clk2.val; + end; + + function "nor" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nor clk2.val, + rise => (clk1.fall and not clk2.val and not clk2.rise) or + (clk2.fall and not clk1.val and not clk1.rise), + fall => (clk1.rise and not clk2.val) or + (clk2.rise and not clk1.val)); + end; + + function "nor" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nor op2, + rise => clk1.fall and not op2, + fall => clk1.rise and not op2); + end; + + function "nor" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 nor clk2.val; + end; + + function "=" (clk1 : t_clk; op2 : std_logic) return boolean is + begin + return clk1.val = op2; + end; + +end; diff --git a/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_subcircuits.vhd b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_subcircuits.vhd new file mode 100644 index 00000000..2dda7607 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/VLM5030/vlm5030_subcircuits.vhd @@ -0,0 +1,204 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- + + +------------------------------------------------------------------------------- +-- SR-latch, synchronous to common clock +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity vlm5030_srlatch is + + port ( + i_clk : in std_logic; + i_res : in std_logic; + i_set : in std_logic; + o_q : out std_logic + ); + +end; + +architecture rtl of vlm5030_srlatch is + signal q : std_logic := '0'; +begin + + process (i_clk) + begin + if rising_edge(i_clk) then + if i_res = '1' then + q <= '0'; + elsif i_set = '1' then + q <= '1'; + end if; + end if; + end process; + + o_q <= q; + +end; + + +------------------------------------------------------------------------------- +-- SR-latch, synchronous to common clock, t_clk version +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vlm5030_pack.t_clk; +use work.vlm5030_pack.rising_edge; + +entity vlm5030_srlatchclk is + + port ( + i_clk : in t_clk; + i_res : in t_clk; + i_set : in t_clk; + o_q : out t_clk + ); + +end; + +architecture rtl of vlm5030_srlatchclk is + signal q : std_logic := '0'; +begin + + process (i_clk) + begin + if rising_edge(i_clk) then + if i_res.val = '1' then + q <= '0'; + elsif i_set.val = '1' then + q <= '1'; + end if; + end if; + end process; + + o_q <= (base => i_clk.base, + val => q, + rise => not q and i_set.val, + fall => q and i_res.val); + +end; + + +------------------------------------------------------------------------------- +-- vlm5030_delay +-- +-- Delay input signal by the specified number of clocks. +-- +-- NOTE: This is inertial delay. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.vlm5030_pack.all; + +entity vlm5030_delay is + + generic ( + g_numclks : integer := 3 + ); + port ( + i_clk : in t_clk; + i_in : in std_logic; + o_out : out std_logic + ); + +end; + +architecture rtl of vlm5030_delay is +begin + + delay_p : process (i_clk) + variable cnt : natural := 0; + variable inq : std_logic := '0'; + begin + if rising_edge(i_clk) then + if i_in /= inq then + cnt := g_numclks-2; + inq := i_in; + else + if cnt > 0 then + cnt := cnt - 1; + else + o_out <= i_in; + end if; + end if; + end if; + end process; + +end; + + +------------------------------------------------------------------------------- +-- vlm5030_delay_inv +-- +-- Invert input signal and delay falling edge of input. +-- The input's rising edge is not delayed. +-- +-- NOTE: This is inertial delay. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.vlm5030_pack.all; + +entity vlm5030_delay_inv is + + generic ( + g_numclks : integer := 3 + ); + port ( + i_clk : in t_clk; + i_in : in std_logic; + o_out : out std_logic + ); + +end; + +architecture rtl of vlm5030_delay_inv is + signal outq : std_logic; +begin + + delay_p : process (i_clk) + variable cnt : natural := 0; + variable inq : std_logic := '0'; + begin + if rising_edge(i_clk) then + if i_in /= inq then + cnt := g_numclks-2; + inq := i_in; + if i_in = '1' then + outq <= '1'; + end if; + else + if cnt > 0 then + cnt := cnt - 1; + else + outq <= i_in; + end if; + end if; + end if; + end process; + + o_out <= '0' when i_in = '1' else not outq; + +end; diff --git a/Arcade_MiST/Konami Jailbreak/rtl/audio_iir_filter.v b/Arcade_MiST/Konami Jailbreak/rtl/audio_iir_filter.v new file mode 100644 index 00000000..ad324f04 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/audio_iir_filter.v @@ -0,0 +1,173 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +module iir_1st_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 15, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2, + input signed [DATA_WIDTH - 1 :0] in, + output [DATA_WIDTH - 1:0] out +); + + reg signed [DATA_WIDTH-1:0] x0,x1,y0; + reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32; + reg [COUNT_BITS - 1:0] count; + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass + // assuming 106528Hz sample rate. + // + // The Matlab output is: + // B = [0.093863 0.093863] + // A = [1.00000 -0.81227] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // + // B = [3076 3076] + // A = [32768 -26616] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076 + // B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768 + // + // Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0 + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + y0 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]}; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_1st_order + +module iir_2nd_order +#( + parameter COEFF_WIDTH = 18, + parameter COEFF_SCALE = 14, + parameter DATA_WIDTH = 16, + parameter COUNT_BITS = 10 +) +( + input clk, + input reset, + input [COUNT_BITS - 1 : 0] div, + input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3, + input signed [DATA_WIDTH - 1 : 0] in, + output [DATA_WIDTH - 1 : 0] out +); + + reg signed [DATA_WIDTH-1 : 0] x0,x1,x2; + reg signed [DATA_WIDTH-1 : 0] y0,y1; + reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32; + reg [COUNT_BITS : 0] count; + + + // Usage: + // Design your 1st order iir low/high-pass with a tool that will give you the + // filter coefficients for the difference equation. Filter coefficients can + // be generated in Octave/matlab/scipy using a command similar to + // [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass + // assuming 48000Hz sample rate. + // + // Output is: + // B = [ 0.072231 0.144462 0.072231] + // A = [1.00000 -1.10923 0.39815] + // + // Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer + // Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits. + // + // B = [1183 2367 1183] + // A = [16384 -18174 6523] + // + // Discard A(1) because it is assumed 1.0 before scaling + // + // This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183 + // B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384 + // + // Sample frequency is "clk rate/div" + // + // COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to + // handle temporary overflow during this computation: + // out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); + + assign out = y0; + + always @ (*) begin + out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1 + end + + always @ (posedge clk) begin + if(reset) begin + count <= 0; + x0 <= 0; + x1 <= 0; + x2 <= 0; + y0 <= 0; + y1 <= 0; + end + else begin + count <= count + 1'd1; + if (count == div - 1) begin + count <= 0; + y1 <= y0; + y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]}; + x2 <= x1; + x1 <= x0; + x0 <= in; + end + end + end + +endmodule //iir_2nd_order \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/rtl/build_id.tcl b/Arcade_MiST/Konami Jailbreak/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/rtl/dpram_dc.vhd b/Arcade_MiST/Konami Jailbreak/rtl/dpram_dc.vhd new file mode 100644 index 00000000..69d4c5fb --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/dpram_dc.vhd @@ -0,0 +1,136 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY dpram_dc IS + GENERIC + ( + init_file : string := " "; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED"; + outdata_reg_b : string := "UNREGISTERED" + ); + PORT + ( + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0'); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0'); + wren_a : IN STD_LOGIC := '0'; + wren_b : IN STD_LOGIC := '0'; + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1'); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END dpram_dc; + + +ARCHITECTURE SYN OF dpram_dc IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + read_during_write_mode_port_b : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ; + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(width_a-1 DOWNTO 0); + q_b <= sub_wire1(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => width_a/8, + width_byteena_b => width_a/8, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1, + byteena_a => byteena_a, + byteena_b => byteena_b + ); + + + +END SYN; diff --git a/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_psg_lpf.v b/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_psg_lpf.v new file mode 100644 index 00000000..2c9ce01c --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_psg_lpf.v @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to match the RC low-pass filter for Jailbreak's SN76489. + +module jailbreak_psg_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 49.152/256 = 192000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.045425748, 0.045425748 + //1.0000000, -0.90914850 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd29791; + B1 = 18'd1488; + B2 = 18'd1488; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_speech_lpf.v b/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_speech_lpf.v new file mode 100644 index 00000000..695ae60f --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/jailbreak_speech_lpf.v @@ -0,0 +1,60 @@ +/*MIT License + +Copyright (c) 2019 Gregory Hogan (Soltan_G42) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//This is a variation of Gregory Hogan's MISTer Genesis core low-pass filter +//tuned to match the RC low-pass filter for Jailbreak's VLM5030. + +module jailbreak_speech_lpf( + input clk, + input reset, + input signed [15:0] in, + output signed [15:0] out); + + localparam [9:0] div = 256; //Sample at 49.152/256 = 192000Hz + + //Coefficients computed with Octave/Matlab/Online filter calculators. + //or with scipy.signal.bessel or similar tools + + //0.010747920, 0.010747920 + //1.0000000, -0.97850416 + reg signed [17:0] A2; + reg signed [17:0] B2; + reg signed [17:0] B1; + + wire signed [15:0] audio_post_lpf1; + + always @ (*) begin + A2 = -18'd32064; + B1 = 18'd352; + B2 = 18'd352; + end + + iir_1st_order lpf6db(.clk(clk), + .reset(reset), + .div(div), + .A2(A2), + .B1(B1), + .B2(B2), + .in(in), + .out(audio_post_lpf1)); + + assign out = audio_post_lpf1; + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/jt49_dcrm2.v b/Arcade_MiST/Konami Jailbreak/rtl/jt49_dcrm2.v new file mode 100644 index 00000000..4b434aec --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/jt49_dcrm2.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // widht of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/rtl/jtframe_frac_cen.v b/Arcade_MiST/Konami Jailbreak/rtl/jtframe_frac_cen.v new file mode 100644 index 00000000..8707e766 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/jtframe_frac_cen.v @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// Fractional clock enable signal +// W refers to the number of divided down cen signals available +// each one is divided by 2 + +module jtframe_frac_cen #(parameter W=2)( + input clk, + input [9:0] n, // numerator + input [9:0] m, // denominator + output reg [W-1:0] cen, + output reg [W-1:0] cenb // 180 shifted +); + +wire [10:0] step={1'b0,n}; +wire [10:0] lim ={1'b0,m}; +wire [10:0] absmax = lim+step; + +reg [10:0] cencnt=11'd0; +reg [10:0] next; +reg [10:0] next2; + +always @(*) begin + next = cencnt+step; + next2 = next-lim; +end + +reg half = 1'b0; +wire over = next>=lim; +wire halfway = next >= (lim>>1) && !half; + +reg [W-1:0] edgecnt = {W{1'b0}}; +wire [W-1:0] next_edgecnt = edgecnt + 1'b1; +wire [W-1:0] toggle = next_edgecnt & ~edgecnt; + +always @(posedge clk) begin + cen <= {W{1'b0}}; + cenb <= {W{1'b0}}; + + if( cencnt >= absmax ) begin + // something went wrong: restart + cencnt <= 11'd0; + end else + if( halfway ) begin + half <= 1'b1; + cenb[0] <= 1'b1; + end + if( over ) begin + cencnt <= next2; + half <= 1'b0; + edgecnt <= next_edgecnt; + cen <= { toggle[W-2:0], 1'b1 }; + end else begin + cencnt <= next; + end +end + + +endmodule \ No newline at end of file diff --git a/Arcade_MiST/Konami Jailbreak/rtl/k005849.sv b/Arcade_MiST/Konami Jailbreak/rtl/k005849.sv new file mode 100644 index 00000000..70458ede --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/k005849.sv @@ -0,0 +1,670 @@ +//============================================================================ +// +// SystemVerilog implementation of the Konami 005849 custom tilemap +// generator +// Adapted from Green Beret core Copyright (C) 2013, 2019 MiSTer-X +// Copyright (C) 2021 Ace +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +//Note: This model of the 005849 cannot be used to replace an original 005849. + +module k005849 +( + input CK49, //49.152MHz clock input + output NCK2, //6.144MHz clock output + output X1S, //3.072MHz clock output + output H2, //1.576MHz clock output + output ER, //E clock for MC6809E + output QR, //Q clock for MC6809E + output EQ, //AND of E and Q clocks for MC6809E + input RES, //Reset input (actually an output on the original chip - active low) + input READ, //Read enable (active low) + input [13:0] A, //Address bus from CPU + input [7:0] DBi, //Data bus input from CPU + output [7:0] DBo, //Data output to CPU + output [3:0] VCF, //Color address to tilemap LUT PROM + output [3:0] VCB, //Tile index to tilemap LUT PROM + input [3:0] VCD, //Data input from tilemap LUT PROM + output [3:0] OCF, //Color address to sprite LUT PROM + output [3:0] OCB, //Sprite index to sprite LUT PROM + input [3:0] OCD, //Data input from sprite LUT PROM + output [4:0] COL, //Color data output from color mixer + input XCS, //Chip select (active low) + input BUSE, //Data bus enable (active low) + output SYNC, //Composite sync (active low) + output HSYC, //HSync (active low) - Not exposed on the original chip + output VSYC, //VSync (active low) + output HBLK, //HBlank (active high) - Not exposed on the original chip + output VBLK, //VBlank (active high) - Not exposed on the original chip + output FIRQ, //Fast IRQ output + output IRQ, //VBlank IRQ + output NMI, //Non-maskable IRQ + output IOCS, //I/O decoder enable (active low) + output CS80, //Chip select output for Konami 501 custom chip (active low) + + //Split sprite/tile busses + output reg [15:0] R, //Address output to graphics ROMs (tiles) + output [15:0] S, //Address output to graphics ROMs (sprites) + output reg S_req = 0, + input S_ack, + input [7:0] RD, //Tilemap ROM data + input [7:0] SD, //Sprite ROM data + + //Extra input for flipping the sprite bank bit (active low) + input SPFL, + + //Extra inputs for screen centering (alters HSync and VSync timing to reposition the video output) + input [3:0] HCTR, VCTR, + + //MiSTer high score system I/O + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_write +); + + + +//------------------------------------------------------- Signal outputs -------------------------------------------------------// + +//Generate IOCS output (active low) +assign IOCS = ~(~XCS & (A[13:12] == 2'b11)); + +//Generate chip enable for Konami 501 (active low) +assign CS80 = XCS; + +//Data output to CPU +assign DBo = BUSE ? 8'hFF: + cs_regs ? regs: + zram0_cs ? zram0_Dout: + zram1_cs ? zram1_Dout: + tileram_attrib_cs ? tileram_attrib_Dout: + tileram_code_cs ? tileram_code_Dout: + spriteram_cs ? spriteram_Dout: + 8'hFF; + +//------------------------------------------------------- Clock division -------------------------------------------------------// + +//Divide the incoming 49.152MHz clock to 6.144MHz and 3.072MHz +reg [4:0] div = 4'd0; +always_ff @(posedge CK49) begin + div <= div + 4'd1; +end +wire cen_6m = !div[2:0]; +assign NCK2 = div[2]; +assign X1S = h_cnt[0]; +assign H2 = h_cnt[1]; + +//The MC6809E requires two identical clocks with a 90-degree offset - assign these here +reg mc6809e_E = 0; +reg mc6809e_Q = 0; +always_ff @(posedge CK49) begin + reg [1:0] clk_phase = 0; + if(cen_6m) begin + clk_phase <= clk_phase + 1'd1; + case(clk_phase) + 2'b00: mc6809e_E <= 0; + 2'b01: mc6809e_Q <= 1; + 2'b10: mc6809e_E <= 1; + 2'b11: mc6809e_Q <= 0; + endcase + end +end +assign QR = mc6809e_Q; +assign ER = mc6809e_E; + +//Output EQ combines ER and QR together via an AND gate - assign this here +assign EQ = ER & QR; + +//-------------------------------------------------------- Video timings -------------------------------------------------------// + +//The horizontal and vertical counters are 9 bits wide - delcare them here +reg [8:0] h_cnt = 9'd0; +reg [8:0] v_cnt = 9'd0; + +//Increment horizontal counter on every falling edge of the pixel clock and increment vertical counter when horizontal counter +//rolls over +reg hblank = 0; +reg vblank = 0; + +reg frame_odd_even = 0; +reg hmask = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + case(h_cnt) + 5: begin + hblank <= 0; + h_cnt <= h_cnt + 9'd1; + end + 13: begin + hmask <= 0; + h_cnt <= h_cnt + 9'd1; + end + //Blank the left-most and right-most 8 lines when the 005849's horizontal mask register bit + //(register 3 bit 7) is active + 253: begin + if(hmask_en) + hmask <= 1; + h_cnt <= h_cnt + 9'd1; + end + 261: begin + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + 383: begin + h_cnt <= 0; + case(v_cnt) + 15: begin + vblank <= 0; + v_cnt <= v_cnt + 9'd1; + end + 239: begin + vblank <= 1; + frame_odd_even <= ~frame_odd_even; + v_cnt <= v_cnt + 9'd1; + end + 263: begin + v_cnt <= 9'd0; + end + default: v_cnt <= v_cnt + 9'd1; + endcase + end + default: h_cnt <= h_cnt + 9'd1; + endcase + end +end + +//Output HBlank and VBlank (both active high) +assign HBLK = hblank; +assign VBLK = vblank; + +//Generate horizontal sync and vertical sync (both active low) +assign HSYC = HCTR[3] ? ~(h_cnt >= 285 - ~HCTR[2:0] && h_cnt <= 316 - ~HCTR[2:0]) : ~(h_cnt >= 293 + HCTR[2:0] && h_cnt <= 324 + HCTR[2:0]); +assign VSYC = ~(v_cnt >= 254 - VCTR && v_cnt <= 261 - VCTR); +assign SYNC = HSYC ^ VSYC; + +//------------------------------------------------------------- IRQs -----------------------------------------------------------// +//Edge detection for VBlank and vertical counter bit 5 for IRQ generation +reg old_vblank, old_vcnt5; +always_ff @(posedge CK49) begin + old_vcnt5 <= v_cnt[5]; + old_vblank <= vblank; +end + +//IRQ (triggers every VBlank) +reg vblank_irq = 1; +always_ff @(posedge CK49) begin + if(!RES || !irq_mask) + vblank_irq <= 1; + else if(!old_vblank && vblank) + vblank_irq <= 0; +end + +assign IRQ = vblank_irq; + +//NMI (triggers every 32 scanlines) +reg nmi = 1; +always_ff @(posedge CK49) begin + if(!RES || !nmi_mask) + nmi <= 1; + else begin + if(old_vcnt5 && !v_cnt[5]) + nmi <= 0; + end +end +assign NMI = nmi; + +//FIRQ (triggers every second VBlank) +reg firq = 1; +always_ff @(posedge CK49) begin + if(!RES || !firq_mask) + firq <= 1; + else begin + if(frame_odd_even && !old_vblank && vblank) + firq <= 0; + end +end +assign FIRQ = firq; + +//----------------------------------------------------- Internal registers -----------------------------------------------------// + +//The 005849 has five 8-bit registers - handle these here +wire cs_regs = ~XCS & (A[13:12] == 2'b10) & (A[7:3] == 5'b01000); +reg [7:0] reg0, reg1, reg2, reg3, reg4; +//Write to the appropriate register +always_ff @(posedge CK49) begin + if(cs_regs && READ) begin + case(A[2:0]) + 3'b000: reg0 <= DBi; + 3'b001: reg1 <= DBi; + 3'b010: reg2 <= DBi; + 3'b011: reg3 <= DBi; + 3'b100: reg4 <= DBi; + default:; + endcase + end +end + +//Assign ZRAM scroll direction as bit 2 of register 2 +wire zram_scroll_dir = reg2[2]; + +//Assign tilemap bank as bit 0 of register 3 +wire tilemap_bank = reg3[0]; + +//Assign tile priority override as bit 6 of register 3 (this is used by Jailbreak to give full priority to sprites and override +//the layer priority set by bit 7 of the tilemap attribute) +wire tile_priority_override = reg3[6]; + +//Assign horizontal mask enable as bit 7 of register 3 (this bit, when enabled, masks the left-most and right-most 8 columns to +//reduce the active area from 256x224 to 240x224 +wire hmask_en = reg3[7]; + +//Assign IRQ masks and flipscreen from the lower 4 bits of register 4 +wire nmi_mask = reg4[0]; +wire irq_mask = reg4[1]; +wire firq_mask = reg4[2]; +wire flipscreen = reg4[3]; + +wire [7:0] regs = (A == 14'h2040) ? reg0: + (A == 14'h2041) ? reg1: + (A == 14'h2042) ? reg2: + (A == 14'h2043) ? reg3: + 8'hFF; + +//-------------------------------------------------------- Internal ZRAM -------------------------------------------------------// + +wire zram0_cs = ~XCS & (A[13:12] == 2'b10) & (A[7:0] >= 8'h00 && A[7:0] <= 8'h1F); +wire zram1_cs = ~XCS & (A[13:12] == 2'b10) & (A[7:0] >= 8'h20 && A[7:0] <= 8'h3F); + +//Address ZRAM with bits [7:3] of the tilemap horizontal or vertical position depending on whether line scroll or column scroll +//is in use +wire [4:0] zram_A = zram_scroll_dir ? tilemap_hpos[7:3] : tilemap_vpos[7:3]; +wire [7:0] zram0_D, zram1_D, zram0_Dout, zram1_Dout; +dpram_dc #(.widthad_a(5)) ZRAM0 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram0_Dout), + .wren_a(zram0_cs & READ), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram0_D) +); +dpram_dc #(.widthad_a(5)) ZRAM1 +( + .clock_a(CK49), + .address_a(A[4:0]), + .data_a(DBi), + .q_a(zram1_Dout), + .wren_a(zram1_cs & READ), + + .clock_b(CK49), + .address_b(zram_A), + .q_b(zram1_D) +); + +//------------------------------------------------------------ VRAM ------------------------------------------------------------// + +//VRAM is external to the 005849 and combines multiple banks into a single 8KB RAM chip for tile attributes and data, and two sprite +//banks. For simplicity, this RAM has been made internal to the 005849 implementation and split into its constituent components. +wire tileram_attrib_cs = ~XCS & (A[13:11] == 3'b000); +wire tileram_code_cs = ~XCS & (A[13:11] == 3'b001); +wire spriteram_cs = ~XCS & (A[13:12] == 2'b01); + +wire [7:0] tileram_attrib_Dout, tileram_code_Dout, spriteram_Dout, tileram_attrib_D, tileram_code_D, spriteram_D; +//Tilemap +dpram_dc #(.widthad_a(11)) VRAM_TILEATTRIB +( + .clock_a(CK49), + .address_a(A[10:0]), + .data_a(DBi), + .q_a(tileram_attrib_Dout), + .wren_a(tileram_attrib_cs & READ), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tileram_attrib_D) +); +dpram_dc #(.widthad_a(11)) VRAM_TILECODE +( + .clock_a(CK49), + .address_a(A[10:0]), + .data_a(DBi), + .q_a(tileram_code_Dout), + .wren_a(tileram_code_cs & READ), + + .clock_b(CK49), + .address_b(vram_A), + .q_b(tileram_code_D) +); + +`ifndef MISTER_HISCORE +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(A[11:0]), + .data_a(DBi), + .q_a(spriteram_Dout), + .wren_a(spriteram_cs & READ), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +`else +// Hiscore mux (this is only to be used with Jailbreak as its high scores are stored in sprite RAM) +// - Mirrored sprite RAM used to protect against corruption while retrieving highscore data +wire [11:0] VRAM_SPR_AD = hs_access_write ? hs_address : A[11:0]; +wire [7:0] VRAM_SPR_DIN = hs_access_write ? hs_data_in : DBi; +wire VRAM_SPR_WE = hs_access_write ? hs_write_enable : (spriteram_cs & READ); +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .q_a(spriteram_Dout), + .wren_a(VRAM_SPR_WE), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +//Sprite RAM shadow for highscore read access +dpram_dc #(.widthad_a(12)) VRAM_SPR_SHADOW +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .wren_a(VRAM_SPR_WE), + + .clock_b(CK49), + .address_b(hs_address), + .q_b(hs_data_out) +); +`endif + + +//-------------------------------------------------------- Tilemap layer -------------------------------------------------------// + +//**The following code is the original tilemap renderer from MiSTerX's Green Beret core with some minor tweaks**// +//XOR horizontal and vertical counter bits with flipscreen bit +wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}}; +wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}}; + +//Generate tilemap position - horizontal position is the sum of the horizontal counter, vertical position is the vertical counter +// +wire [8:0] tilemap_hpos = {h_cnt[8], hcnt_x[7:0]} + (~zram_scroll_dir ? {zram1_D[0], zram0_D} : 9'd0); +wire [8:0] tilemap_vpos = vcnt_x + (zram_scroll_dir ? {zram1_D[0], zram0_D} : 9'd0); + +//Address output to tile section of VRAM +wire [10:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[8:3]}; + +//Tile index is a combination of the tilemap bank bit from the 005849's internal registers, attribute bits [7:6] and the actual +//tile code +wire [10:0] tile_index = {tilemap_bank, tileram_attrib_D[7:6], tileram_code_D}; + +//Tile color is held in the lower 4 bits of tileram attributes +wire [3:0] tile_color = tileram_attrib_D[3:0]; +reg [3:0] tile_color_r, tile_color_rr; +reg tile_attrib7_r, tile_attrib7_rr; +reg tile_hflip_r; +reg [7:0] RD_r; + +//Tile flip attributes are stored in bits 4 (horizontal) and 5 (vertical) +wire tile_hflip = tileram_attrib_D[4]; +wire tile_vflip = tileram_attrib_D[5]; + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if (h_cnt[0]) begin + //Assign address outputs to tile ROM + R <= {tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2:1] ^ {2{tile_hflip}})}; + // Apply appropriate delay to flags + tile_hflip_r <= tile_hflip; + tile_color_r <= tile_color; + tile_color_rr <= tile_color_r; + tile_attrib7_r <= tileram_attrib_D[7]; + tile_attrib7_rr <= tile_attrib7_r; + RD_r <= RD; + end + end +end + +//Multiplex tilemap ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_r) ? RD_r[3:0] : RD_r[7:4]; + +//Retrieve tilemap select bit from the NOR of bit 7 of the tile attributes with the priority override bit +reg tilemap_en = 0; +always_ff @(posedge CK49) begin + if(cen_6m) begin + tilemap_en <= ~(tile_attrib7_rr | tile_priority_override); + end +end + +//Address output to tilemap LUT PROM +assign VCF = tile_color_rr; +assign VCB = tile_pixel; + +//Delay tilemap data by one horizontal line +reg [3:0] tilemap_D = 4'd0; +always_ff @(posedge CK49) begin + if(cen_6m) + tilemap_D <= VCD; +end + +//-------------------------------------------------------- Sprite layer --------------------------------------------------------// + +//The following code is the original sprite renderer from MiSTerX's Green Beret core with additional screen flipping support and +//some extra tweaks + +//Generate sprite position - horizontal position is the horizontal counter, vertical position is the vertical counter (offset by +//18, 17 when flipped, to properly position the sprite layer) +wire [8:0] sprite_hpos = h_cnt; +wire [8:0] sprite_vpos = flipscreen ? v_cnt + 9'd17 : v_cnt + 9'd18; + +//Sprite state machine +reg [5:0] sprite_index; +reg [1:0] sprite_offset; +reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3; +reg [2:0] sprite_fsm_state; +always_ff @(posedge CK49) begin + if(sprite_hpos == 9'd0) begin + xcnt <= 0; + sprite_index <= 0; + sprite_offset <= 3; + sprite_fsm_state <= 1; + end + else + case(sprite_fsm_state) + 0: /* empty */ ; + 1: begin + if(sprite_index > 8'd47) //Render up to 48 sprites at once (index 0 - 47) + sprite_fsm_state <= 0; + //When the sprite Y attribute is set to 0, skip the current sprite, otherwise obtain the sprite Y attribute + //and scan out the other sprite attributes + else begin + if(hy) begin + sprite_attrib3 <= spriteram_D; + sprite_offset <= 2; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + else sprite_index <= sprite_index + 6'd1; + end + end + 2: begin + sprite_attrib2 <= spriteram_D; + sprite_offset <= 1; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 3: begin + sprite_attrib1 <= spriteram_D; + sprite_offset <= 0; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 4: begin + sprite_attrib0 <= spriteram_D; + sprite_offset <= 3; + sprite_index <= sprite_index + 6'd1; + xcnt <= 5'b10000; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + S_req <= !S_req; + end + 5: if (S_req == S_ack) begin + xcnt <= xcnt + 5'd1; + sprite_fsm_state <= wre ? sprite_fsm_state : 3'd1; + S_req <= (wre & xcnt[0]) ? !S_req : S_req; + end + default:; + endcase +end + +//Subtract sprite attribute byte 2 with bit 7 of sprite attribute byte 1 to obtain sprite X position and XOR with the +//flipscreen bit +wire [8:0] sprite_x = ({1'b0, sprite_attrib2} - {sprite_attrib1[7], 8'h00}) ^ {9{flipscreen}}; + +//If the sprite state machine is in state 1, obtain sprite Y position directly from sprite RAM, otherwise obtain it from +//sprite attribute byte 3 and XOR with the flipscreen bit +wire [7:0] sprite_y = (sprite_fsm_state == 3'd1) ? spriteram_D ^ {8{flipscreen}} : sprite_attrib3 ^ {8{flipscreen}}; + +//Sprite flip attributes are stored in bits 4 (horizontal) and 5 (vertical) of sprite attribute byte 1 +wire sprite_hflip = sprite_attrib1[4] ^ flipscreen; +wire sprite_vflip = sprite_attrib1[5] ^ flipscreen; + +//Sprite code is bit 6 of sprite attribute byte 1 appended to sprite attribute byte 0 +wire [8:0] sprite_code = {sprite_attrib1[6], sprite_attrib0}; + +//Sprite color is the lower 4 bits of sprite attribute byte 1 +wire [3:0] sprite_color = sprite_attrib1[3:0]; + +wire [8:0] ht = {1'b0, sprite_y} - sprite_vpos; +wire hy = (sprite_y != 0) & (ht[8:5] == 4'b1111) & (ht[4] ^ ~flipscreen); + +reg [4:0] xcnt; +wire [3:0] lx = xcnt[3:0] ^ {4{sprite_hflip}}; +wire [3:0] ly = ht[3:0] ^ {4{~sprite_vflip}}; + +//Assign address outputs to sprite ROMs +assign S = {sprite_code, ly[3], lx[3], ly[2:0], lx[2:1]}; + +//Multiplex sprite ROM data down from 8 bits to 4 using bit 0 of the horizontal position +wire [3:0] sprite_pixel = lx[0] ? SD[3:0] : SD[7:4]; + +//Latch the sprite bank from bit 3 of register 3 on the rising edge of VSync and XNOR with the added SPFL signal to flip this bit +//for Green Beret +//TODO: Find the actual internal register bit (if any) on the 005849 to properly handle this +reg sprite_bank = 0; +reg old_vsync; +always_ff @(posedge CK49) begin + old_vsync <= VSYC; + if(!VSYC) + sprite_bank <= 0; + else if(!old_vsync && VSYC) + sprite_bank <= ~(reg3[3] ^ SPFL); +end + +wire [11:0] spriteram_A = {3'b000, sprite_bank, sprite_index, sprite_offset}; + +//Address output to sprite LUT PROM +assign OCF = sprite_color; +assign OCB = sprite_pixel; + +//----------------------------------------------------- Sprite line buffer -----------------------------------------------------// + +//The sprite line buffer is external to the 005849 and consists of four 4416 DRAM chips. For simplicity, both the logic for the +//sprite line buffer and the sprite line buffer itself has been made internal to the 005849 implementation. + +//Enable writing to sprite line buffer when bit 4 of xcnt is 1 +wire wre = xcnt[4]; + +//Set sprite ID as bit 0 of the sprite vertical position +wire sprite_id = sprite_vpos[0]; + +//Sum sprite X position with the lower 4 bits of xcnt to address the sprite line buffer +wire [8:0] wpx = sprite_x + xcnt[3:0]; + +//Generate sprite line buffer write addresses +reg [9:0] lbuff_A; +reg lbuff_we; +wire [3:0] lbuff_Din = OCD; + +always_ff @(posedge CK49) begin + lbuff_A <= {~sprite_id, wpx}; + lbuff_we <= wre & S_req == S_ack; +end + +//Generate read address for sprite line buffer on the rising edge of the pixel clock +reg [9:0] radr0 = 10'd0; +reg [9:0] radr1 = 10'd1; +always_ff @(posedge CK49) begin + if(cen_6m) + radr0 <= {sprite_id, flipscreen ? sprite_hpos - 9'd241 : sprite_hpos}; +end + +//Sprite line buffer +wire [3:0] lbuff_Dout; +dpram_dc #(.widthad_a(10)) LBUFF +( + .clock_a(CK49), + .address_a(lbuff_A), + .data_a({4'd0, lbuff_Din}), + .wren_a(lbuff_we & (lbuff_Din != 0)), + + .clock_b(CK49), + .address_b(radr0), + .data_b(8'h0), + .wren_b(radr0 == radr1), + .q_b({4'bZZZZ, lbuff_Dout}) +); + +//Latch sprite data from the sprite line buffer +wire lbuff_read_en = (div[2:0] == 3'b100); +reg [3:0] sprite_D = 4'd0; +always_ff @(posedge CK49) begin + if(lbuff_read_en) begin + if(radr0 != radr1) + sprite_D <= lbuff_Dout; + radr1 <= radr0; + end +end + +//--------------------------------------------------------- Color mixer --------------------------------------------------------// + +//Multiplex tile and sprite data, then output the final result +wire tile_sprite_sel = (tilemap_en | ~(|sprite_D)); +wire [3:0] tile_sprite_D = tile_sprite_sel ? tilemap_D : sprite_D; + +//Latch and output pixel data +reg [4:0] pixel_D; +always_ff @(posedge CK49) begin + if(cen_6m) + pixel_D <= {tile_sprite_sel, tile_sprite_D}; +end +//If the horizontal mask is active, black out the left-most and right-most 8 columns to limit the display area to 240x224, otherwise +//output the full 256x224 +assign COL = hmask ? 5'd0 : pixel_D; + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/pll.qip b/Arcade_MiST/Konami Jailbreak/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Arcade_MiST/Konami Jailbreak/rtl/pll.v b/Arcade_MiST/Konami Jailbreak/rtl/pll.v new file mode 100644 index 00000000..1960b7f8 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/pll.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire6 = 1'h0; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 105, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 382, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 105, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 191, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Arcade_MiST/Konami Jailbreak/rtl/rom_loader.sv b/Arcade_MiST/Konami Jailbreak/rtl/rom_loader.sv new file mode 100644 index 00000000..71b2d098 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/rom_loader.sv @@ -0,0 +1,398 @@ +//============================================================================ +// +// SD card ROM loader and ROM selector for MISTer. +// Copyright (C) 2019, 2020 Kitrinx (aka Rysha) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//============================================================================ + +// Rom layout for Jailbreak: +// 0x0000 - 0x3FFF = eprom_1 +// 0x4000 - 0x7FFF = eprom_2 +// 0x8000 - 0xBFFF = eprom_3 +// 0xC000 - 0xFFFF = eprom_4 +// 0x10000 - 0x13FFF = eprom_5 +// 0x14000 - 0x17FFF = eprom_6 +// 0x18000 - 0x1BFFF = eprom_7 +// 0x1C000 - 0x1FFFF = eprom_8 +// 0x20000 - 0x23FFF = eprom_9 +// 0x24000 - 0x240FF = sprite_lut_prom +// 0x24100 - 0x241FF = tile_lut_prom +// 0x24200 - 0x2421F = color_prom_1 +// 0x24220 - 0x2423F = color_prom_2 + +module selector +( + input logic [24:0] ioctl_addr, + output logic ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs, ep9_cs, + cp1_cs, cp2_cs, tl_cs, sl_cs +); + + always_comb begin + {ep1_cs, ep2_cs, ep3_cs, ep4_cs, ep5_cs, ep6_cs, ep7_cs, ep8_cs, ep9_cs, cp1_cs, + cp2_cs, tl_cs, sl_cs} = 0; + if(ioctl_addr < 'h4000) + ep1_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h8000) + ep2_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'hC000) + ep3_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h10000) + ep4_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h14000) + ep5_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h18000) + ep6_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h1C000) + ep7_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h20000) + ep8_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h24000) + ep9_cs = 1; // 0x4000 14 + else if(ioctl_addr < 'h24100) + sl_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h24200) + tl_cs = 1; // 0x100 8 + else if(ioctl_addr < 'h24220) + cp1_cs = 1; // 0x20 5 + else + cp2_cs = 1; // 0x20 5 + end +endmodule + +//////////// +// EPROMS // +//////////// + +module eprom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_1 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_2 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_3 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_3 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_4 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_4 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_5 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_5 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_6 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_6 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_7 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_7 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_8 +( + input logic CLK, + input logic CLK_DL, + input logic [13:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(14)) eprom_8 + ( + .clock_a(CLK), + .address_a(ADDR[13:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[13:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module eprom_9 +( + input logic CLK, + input logic CLK_DL, + input logic [12:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(13)) eprom_9 + ( + .clock_a(CLK), + .address_a(ADDR[12:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[12:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +/////////// +// PROMS // +/////////// + +module color_prom_1 +( + input logic CLK, + input logic CLK_DL, + input logic [4:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(5)) color_prom_1 + ( + .clock_a(CLK), + .address_a(ADDR[4:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[4:0]), + .data_b(DATA_IN[7:0]), + .wren_b(WR & CS_DL) + ); +endmodule + +module color_prom_2 +( + input logic CLK, + input logic CLK_DL, + input logic [4:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [7:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [7:0] DATA +); + dpram_dc #(.widthad_a(5)) color_prom_2 + ( + .clock_a(CLK), + .address_a(ADDR[4:0]), + .q_a(DATA[7:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[4:0]), + .data_b(DATA_IN[7:0]), + .wren_b(WR & CS_DL) + ); +endmodule + +module tile_lut_prom +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) tile_lut_prom + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule + +module sprite_lut_prom +( + input logic CLK, + input logic CLK_DL, + input logic [7:0] ADDR, + input logic [24:0] ADDR_DL, + input logic [3:0] DATA_IN, + input logic CS_DL, + input logic WR, + output logic [3:0] DATA +); + dpram_dc #(.widthad_a(8)) sprite_lut_prom + ( + .clock_a(CLK), + .address_a(ADDR[7:0]), + .q_a(DATA[3:0]), + + .clock_b(CLK_DL), + .address_b(ADDR_DL[7:0]), + .data_b(DATA_IN), + .wren_b(WR & CS_DL) + ); +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/sdram.sv b/Arcade_MiST/Konami Jailbreak/rtl/sdram.sv new file mode 100644 index 00000000..328e7e58 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/sdram.sv @@ -0,0 +1,347 @@ +// +// sdram.v +// +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output reg [15:0] port1_q, + + input [15:1] cpu1_addr, + output reg [15:0] cpu1_q, + input [15:1] cpu2_addr, + output reg [15:0] cpu2_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output reg [15:0] port2_q, + input [15:1] ch1_addr, + output reg [15:0] ch1_q, + input sp1_req, + input [16:1] sp1_addr, + output reg [15:0] sp1_q, + output reg sp1_ack +); + +parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + +// 64ms/8192 rows = 7.8us +localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10; + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 + 1 ras0 + 2 data1 returned + 3 CAS0 + 4 RAS1 cas0 + 5 ras1 + 6 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd4; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 6 +localparam STATE_READ0 = 3'd0;// STATE_CAS0 + CAS_LATENCY + 2'd2; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_LAST = 3'd6; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; + +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [15:1] addr_last[4]; +reg [16:1] addr_last2[4]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; + +reg port1_state; +reg port2_state; + +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_CPU2 = 2'd2; +localparam PORT_CH1 = 2'd1; +localparam PORT_SP1 = 2'd2; +localparam PORT_REQ = 2'd3; + +reg [1:0] next_port[2]; +reg [1:0] port[2]; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 9'd0, cpu1_addr }; + end else if (cpu2_addr != addr_last[PORT_CPU2]) begin + next_port[0] = PORT_CPU2; + addr_latch_next[0] = { 9'd0, cpu2_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT1: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (ch1_addr != addr_last2[PORT_CH1]) begin + next_port[1] = PORT_CH1; + addr_latch_next[1] = { 1'b1, 5'd0, 3'b000, ch1_addr }; + end else if (sp1_req != sp1_ack) begin + next_port[1] = PORT_SP1; + addr_latch_next[1] = { 1'b1, 5'd0, 2'b00, sp1_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end + +always @(posedge clk) begin + + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; + + if(init) begin + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][15:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + port1_state <= port1_req; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][16:1]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + port2_state <= port2_req; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + PORT_CPU2: begin cpu2_q <= sd_din; end + default: ; + endcase; + end + + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end + PORT_CH1 : ch1_q <= sd_din; + PORT_SP1 : begin sp1_q <= sd_din; sp1_ack <= sp1_req; end + default: ; + endcase; + end + + end +end + +endmodule diff --git a/Arcade_MiST/Konami Jailbreak/rtl/spram.vhd b/Arcade_MiST/Konami Jailbreak/rtl/spram.vhd new file mode 100644 index 00000000..38302277 --- /dev/null +++ b/Arcade_MiST/Konami Jailbreak/rtl/spram.vhd @@ -0,0 +1,46 @@ +library ieee; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.ALL; +use IEEE.numeric_std.all; + +entity spram is + + generic + ( + DATA_WIDTH : natural := 8; + ADDR_WIDTH : natural := 10 + ); + + port + ( + clk : in std_logic; + addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0); + data : in std_logic_vector((DATA_WIDTH - 1) downto 0); + q : out std_logic_vector((DATA_WIDTH - 1) downto 0); + we : in std_logic := '0' + ); + +end spram; + +architecture rtl of spram is + + subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); + type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; + + shared variable ram : memory_t; + +begin + + process(clk) + begin + if(rising_edge(clk)) then + if(we = '1') then + ram(to_integer(unsigned(addr))) := data; + q <= data; + else + q <= ram(to_integer(unsigned(addr))); + end if; + end if; + end process; + +end rtl; From 6084ab1c56ceae853c5498a85ea63c782611bf30 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sun, 2 Jan 2022 21:45:05 +0100 Subject: [PATCH 7/7] Konami custom chip unifications --- Arcade_MiST/Konami Gyruss/Gyruss.qsf | 4 +- .../rtl/{custom/KONAMI-1 => }/KONAMI1.sv | 0 .../rtl/custom/KONAMI-1/mc6809isk.v | 4162 ----------------- .../rtl/custom/gyruss_custom.qip | 2 - .../Konami Jackal/rtl/custom/k005885.sv | 430 +- .../Konami TimePilot84/rtl/TimePilot84_CPU.sv | 14 +- .../Konami TimePilot84/rtl/custom/k082.sv | 127 +- 7 files changed, 342 insertions(+), 4397 deletions(-) rename Arcade_MiST/Konami Gyruss/rtl/{custom/KONAMI-1 => }/KONAMI1.sv (100%) delete mode 100644 Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v diff --git a/Arcade_MiST/Konami Gyruss/Gyruss.qsf b/Arcade_MiST/Konami Gyruss/Gyruss.qsf index 88e7856c..58c6e146 100644 --- a/Arcade_MiST/Konami Gyruss/Gyruss.qsf +++ b/Arcade_MiST/Konami Gyruss/Gyruss.qsf @@ -225,6 +225,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss_MiST.sv set_global_assignment -name QIP_FILE rtl/pll.qip set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss.sv @@ -234,6 +235,7 @@ set_global_assignment -name VERILOG_FILE rtl/jt49_dcrm2.v set_global_assignment -name VERILOG_FILE rtl/hiscore.v set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss_SND.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/Gyruss_CPU.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/KONAMI1.sv set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf.v set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf_medium.v set_global_assignment -name VERILOG_FILE rtl/Filters/gyruss_lpf_light.v @@ -249,5 +251,5 @@ set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip set_global_assignment -name QIP_FILE ../../common/CPU/t48/i8039.qip set_global_assignment -name QIP_FILE ../../common/Sound/JT49/jt49.qip set_global_assignment -name SIGNALTAP_FILE output_files/sndcpu.stp -set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name VERILOG_FILE ../../common/CPU/MC6809/mc6809is.v set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/KONAMI1.sv b/Arcade_MiST/Konami Gyruss/rtl/KONAMI1.sv similarity index 100% rename from Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/KONAMI1.sv rename to Arcade_MiST/Konami Gyruss/rtl/KONAMI1.sv diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v b/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v deleted file mode 100644 index 18467022..00000000 --- a/Arcade_MiST/Konami Gyruss/rtl/custom/KONAMI-1/mc6809isk.v +++ /dev/null @@ -1,4162 +0,0 @@ -`timescale 1ns / 1ns -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: Greg Miller -// Copyright (c) 2016, Greg Miller -// -// Create Date: 14:26:59 08/13/2016 -// Design Name: -// Module Name: mc6809 -// Project Name: Cycle-Accurate 6809 Core -// Target Devices: -// Tool versions: -// Description: -// -// Dependencies: Intended to be standalone Vanilla Verilog. -// -// Revision: -// Revision 1.0 - Initial Release -// Revision 1.0s - Sinchronous version (by Sorgelig) -// Revision 1.0sk - Add direct injection of KONAMI-1 encrypted opcodes (by Ace) -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - - -// -// The 6809 has incomplete instruction decoding. A collection of instructions, if met, end up actually behaving like -// a binary-adjacent neighbor. -// -// The soft core permits three different behaviors for this situation, controlled by the instantiation parameter -// ILLEGAL_INSTRUCTIONS -// -// "GHOST" - Mimic the 6809's incomplete decoding. This is as similar to a hard 6809 as is practical. [DEFAULT] -// -// "STOP" - Cause the soft core to cease execution, placing $DEAD on the address bus and R/W to 'read'. Interrupts, -// bus control (/HALT, /DMABREQ), etc. are ignored. The core intentionally seizes in this instance. -// (Frankly, this is useful when making changes to the core and you have a logic analyzer connected.) -// -// "IGNORE"- Cause the soft core to merely ignore illegal instructions. It will consider them 1-byte instructions and -// attempt to fetch and run an exception 1 byte later. -// - -module mc6809is -#( - parameter ILLEGAL_INSTRUCTIONS="GHOST", - parameter IS_KONAMI1="FALSE" -) -( - input CLK, - input fallE_en, - input fallQ_en, - input [7:0] OP, - - input [7:0] D, - output [7:0] DOut, - output [15:0] ADDR, - output RnW, - output BS, - output BA, - input nIRQ, - input nFIRQ, - input nNMI, - output AVMA, - output BUSY, - output LIC, - input nHALT, - input nRESET, - input nDMABREQ, - output [111:0] RegData -); - -reg [7:0] DOutput; - -assign DOut = DOutput; - -reg RnWOut; // Combinatorial - -reg rLIC; -assign LIC = rLIC; - -reg rAVMA; -assign AVMA = rAVMA; - -reg rBUSY; -assign BUSY = rBUSY; - -// Bus control -// BS BA -// 0 0 normal (CPU running, CPU is master) -// 0 1 Interrupt Ack -// 1 0 Sync Ack -// 1 1 CPU has gone high-Z on A, D, R/W -// - -assign RnW = RnWOut; - - -///////////////////////////////////////////////// -// Vectors -`define RESET_VECTOR 16'HFFFE -`define NMI_VECTOR 16'HFFFC -`define SWI_VECTOR 16'HFFFA -`define IRQ_VECTOR 16'HFFF8 -`define FIRQ_VECTOR 16'HFFF6 -`define SWI2_VECTOR 16'HFFF4 -`define SWI3_VECTOR 16'HFFF2 -`define Reserved_VECTOR 16'HFFF0 - -////////////////////////////////////////////////////// -// Latched registers -// - -// The last-latched copy. -reg [7:0] a; -reg [7:0] b; -reg [15:0] x; -reg [15:0] y; -reg [15:0] u; -reg [15:0] s; -reg [15:0] pc; -reg [7:0] dp; -reg [7:0] cc; -reg [15:0] tmp; -reg [15:0] addr; -reg [15:0] ea; - - -// Debug ability to export register contents -assign RegData[7:0] = a; -assign RegData[15:8] = b; -assign RegData[31:16] = x; -assign RegData[47:32] = y; -assign RegData[63:48] = s; -assign RegData[79:64] = u; -assign RegData[87:80] = cc; -assign RegData[95:88] = dp; -assign RegData[111:96] = pc; - - - -// The values as being calculated -reg [7:0] a_nxt; -reg [7:0] b_nxt; -reg [15:0] x_nxt; -reg [15:0] y_nxt; -reg [15:0] u_nxt; -reg [15:0] s_nxt; -reg [15:0] pc_nxt; -reg [7:0] dp_nxt; -reg [7:0] cc_nxt; -reg [15:0] addr_nxt; -reg [15:0] ea_nxt; -reg [15:0] tmp_nxt; - -reg BS_nxt; -reg BA_nxt; - -// for ADDR, BS/BA, assign them to the flops -assign BS = BS_nxt; -assign BA = BA_nxt; -assign ADDR=addr_nxt; - -localparam CC_E= 8'H80; -localparam CC_F= 8'H40; -localparam CC_H= 8'H20; -localparam CC_I= 8'H10; -localparam CC_N= 8'H08; -localparam CC_Z= 8'H04; -localparam CC_V= 8'H02; -localparam CC_C= 8'H01; - -localparam CC_E_BIT= 3'd7; -localparam CC_F_BIT= 3'd6; -localparam CC_H_BIT= 3'd5; -localparam CC_I_BIT= 3'd4; -localparam CC_N_BIT= 3'd3; -localparam CC_Z_BIT= 3'd2; -localparam CC_V_BIT= 3'd1; -localparam CC_C_BIT= 3'd0; - -// Convenience calculations -reg [15:0] pc_p1; -reg [15:0] pc_p2; -reg [15:0] pc_p3; -reg [15:0] s_p1; -reg [15:0] s_m1; -reg [15:0] u_p1; -reg [15:0] u_m1; -reg [15:0] addr_p1; -reg [15:0] ea_p1; - -////////////////////////////////////////////////////// -// NMI Mask -// -// NMI is supposed to be masked - despite the name - until the 6809 loads a value into S. -// Frankly, I'm cheating slightly. If someone does a LDS #$0, it won't disable the mask. Pretty much anything else -// that changes the value of S from the default (which is currently $0) will clear the mask. A reset will set the mask again. -reg NMIMask; - -reg NMILatched; -reg NMISample; -reg NMISample2; -reg NMIClear; -reg NMIClear_nxt; -wire wNMIClear = NMIClear; - -reg IRQLatched; - -reg IRQSample; -reg IRQSample2; -reg FIRQLatched; -reg FIRQSample; -reg FIRQSample2; -reg HALTLatched; -reg HALTSample; -reg HALTSample2; -reg DMABREQLatched; -reg DMABREQSample; -reg DMABREQSample2; - -// Interrupt types -localparam INTTYPE_NMI = 3'H0 ; -localparam INTTYPE_IRQ = 3'H1 ; -localparam INTTYPE_FIRQ = 3'H2 ; -localparam INTTYPE_SWI = 3'H3 ; -localparam INTTYPE_SWI2 = 3'H4 ; -localparam INTTYPE_SWI3 = 3'H5 ; - -reg [2:0] IntType; -reg [2:0] IntType_nxt; - -////////////////////////////////////////////////////// -// Instruction Fetch Details -// -reg InstPage2; -reg InstPage3; -reg InstPage2_nxt; -reg InstPage3_nxt; - -reg [7:0] Inst1; -reg [7:0] Inst2; -reg [7:0] Inst3; -reg [7:0] Inst1_nxt; -reg [7:0] Inst2_nxt; -reg [7:0] Inst3_nxt; - - -localparam CPUSTATE_RESET = 7'd0; -localparam CPUSTATE_RESET0 = 7'd1; - -localparam CPUSTATE_RESET2 = 7'd3; -localparam CPUSTATE_FETCH_I1 = 7'd4; -localparam CPUSTATE_FETCH_I1V2 = 7'd5; -localparam CPUSTATE_FETCH_I2 = 7'd8; - -localparam CPUSTATE_LBRA_OFFSETLOW = 7'd17; -localparam CPUSTATE_LBRA_DONTCARE = 7'd18; -localparam CPUSTATE_LBRA_DONTCARE2 = 7'd19; - - - -localparam CPUSTATE_BRA_DONTCARE = 7'd20; - -localparam CPUSTATE_BSR_DONTCARE1 = 7'd21; -localparam CPUSTATE_BSR_DONTCARE2 = 7'd22; -localparam CPUSTATE_BSR_RETURNLOW = 7'd23; -localparam CPUSTATE_BSR_RETURNHIGH = 7'd24; - -localparam CPUSTATE_TFR_DONTCARE1 = 7'd26; -localparam CPUSTATE_TFR_DONTCARE2 = 7'd27; -localparam CPUSTATE_TFR_DONTCARE3 = 7'd28; -localparam CPUSTATE_TFR_DONTCARE4 = 7'd29; - -localparam CPUSTATE_EXG_DONTCARE1 = 7'd30; -localparam CPUSTATE_EXG_DONTCARE2 = 7'd31; -localparam CPUSTATE_EXG_DONTCARE3 = 7'd32; -localparam CPUSTATE_EXG_DONTCARE4 = 7'd33; -localparam CPUSTATE_EXG_DONTCARE5 = 7'd34; -localparam CPUSTATE_EXG_DONTCARE6 = 7'd35; - -localparam CPUSTATE_ABX_DONTCARE = 7'd36; - -localparam CPUSTATE_RTS_HI = 7'd38; -localparam CPUSTATE_RTS_LO = 7'd39; -localparam CPUSTATE_RTS_DONTCARE2 = 7'd40; - -localparam CPUSTATE_16IMM_LO = 7'd41; -localparam CPUSTATE_ALU16_DONTCARE = 7'd42; -localparam CPUSTATE_DIRECT_DONTCARE = 7'd43; - -localparam CPUSTATE_ALU_EA = 7'd44; - -localparam CPUSTATE_ALU_DONTCARE = 7'd46; -localparam CPUSTATE_ALU_WRITEBACK = 7'd47; - -localparam CPUSTATE_LD16_LO = 7'd48; - -localparam CPUSTATE_ST16_LO = 7'd49; -localparam CPUSTATE_ALU16_LO = 7'd50; - - - - -localparam CPUSTATE_JSR_DONTCARE = 7'd53; -localparam CPUSTATE_JSR_RETLO = 7'd54; -localparam CPUSTATE_JSR_RETHI = 7'd55; -localparam CPUSTATE_EXTENDED_ADDRLO = 7'd56; -localparam CPUSTATE_EXTENDED_DONTCARE = 7'd57; -localparam CPUSTATE_INDEXED_BASE = 7'd58; - - -localparam CPUSTATE_IDX_DONTCARE3 = 7'd60; - -localparam CPUSTATE_IDX_OFFSET_LO = 7'd61; -localparam CPUSTATE_IDX_16OFFSET_LO = 7'd62; - -localparam CPUSTATE_IDX_16OFF_DONTCARE0= 7'd63; -localparam CPUSTATE_IDX_16OFF_DONTCARE1= 7'd64; -localparam CPUSTATE_IDX_16OFF_DONTCARE2= 7'd65; -localparam CPUSTATE_IDX_16OFF_DONTCARE3= 7'd66; - -localparam CPUSTATE_IDX_DOFF_DONTCARE1 = 7'd68; -localparam CPUSTATE_IDX_DOFF_DONTCARE2 = 7'd69; -localparam CPUSTATE_IDX_DOFF_DONTCARE3 = 7'd70; -localparam CPUSTATE_IDX_PC16OFF_DONTCARE = 7'd71; - -localparam CPUSTATE_IDX_EXTIND_LO = 7'd72; -localparam CPUSTATE_IDX_EXTIND_DONTCARE = 7'd73; - -localparam CPUSTATE_INDIRECT_HI = 7'd74; -localparam CPUSTATE_INDIRECT_LO = 7'd75; -localparam CPUSTATE_INDIRECT_DONTCARE = 7'd76; -localparam CPUSTATE_MUL_ACTION = 7'd77; - -localparam CPUSTATE_PSH_DONTCARE1 = 7'd80; -localparam CPUSTATE_PSH_DONTCARE2 = 7'd81; -localparam CPUSTATE_PSH_DONTCARE3 = 7'd82; -localparam CPUSTATE_PSH_ACTION = 7'd83; - -localparam CPUSTATE_PUL_DONTCARE1 = 7'd84; -localparam CPUSTATE_PUL_DONTCARE2 = 7'd85; -localparam CPUSTATE_PUL_ACTION = 7'd86; - -localparam CPUSTATE_NMI_START = 7'd87; -localparam CPUSTATE_IRQ_DONTCARE = 7'd88; -localparam CPUSTATE_IRQ_START = 7'd89; -localparam CPUSTATE_IRQ_DONTCARE2 = 7'd90; -localparam CPUSTATE_IRQ_VECTOR_HI = 7'd91; -localparam CPUSTATE_IRQ_VECTOR_LO = 7'd92; -localparam CPUSTATE_FIRQ_START = 7'd93; -localparam CPUSTATE_CC_DONTCARE = 7'd94; -localparam CPUSTATE_SWI_START = 7'd95; - -localparam CPUSTATE_TST_DONTCARE1 = 7'd96; -localparam CPUSTATE_TST_DONTCARE2 = 7'd97; - -localparam CPUSTATE_DEBUG = 7'd98; - -localparam CPUSTATE_16IMM_DONTCARE = 7'd99; - -localparam CPUSTATE_HALTED = 7'd100; - -localparam CPUSTATE_HALT_EXIT2 = 7'd102; -localparam CPUSTATE_STOP = 7'd105; -localparam CPUSTATE_STOP2 = 7'd106; -localparam CPUSTATE_STOP3 = 7'd107; - - -localparam CPUSTATE_CWAI = 7'd108; -localparam CPUSTATE_CWAI_DONTCARE1 = 7'd109; -localparam CPUSTATE_CWAI_POST = 7'd110; - -localparam CPUSTATE_DMABREQ = 7'd111; -localparam CPUSTATE_DMABREQ_EXIT = 7'd112; -localparam CPUSTATE_SYNC = 7'd113; -localparam CPUSTATE_SYNC_EXIT = 7'd114; - -localparam CPUSTATE_INT_DONTCARE = 7'd115; - - -reg [6:0] CpuState = CPUSTATE_RESET; -reg [6:0] CpuState_nxt = CPUSTATE_RESET; - -reg [6:0] NextState = CPUSTATE_RESET; -reg [6:0] NextState_nxt = CPUSTATE_RESET; - -wire [6:0] PostIllegalState; - -// If we encounter something like an illegal addressing mode (an index mode that's illegal for instance) -// What state should we go to? -generate -if (ILLEGAL_INSTRUCTIONS=="STOP") -begin : postillegal - assign PostIllegalState = CPUSTATE_STOP; -end -else -begin - assign PostIllegalState = CPUSTATE_FETCH_I1; -end -endgenerate - - - -/////////////////////////////////////////////////////////////////////// - -// -// MapInstruction - Considering how the core was instantiated, this -// will either directly return D[7:0] *or* remap values from D[7:0] -// that relate to undefined instructions in the 6809 to the instructions -// that the 6809 actually executed when these were encountered, due to -// incomplete decoding. -// -// NEG, COM, LSR, DEC - these four instructions, in Direct, Inherent (A or B) -// Indexed, or Extended addressing do not actually decode bit 0 on the instruction. -// Thus, for instance, a $51 encountered will be executed as a $50, which is a NEGB. -// - -// Specifically, the input is an instruction; if it matches an unknown instruction that the -// 6809 is known to ghost to another instruction, the output of the function -// is the the instruction that actually gets executed. Otherwise, the output is the -// input. - -function [7:0] MapInstruction(input [7:0] i); -reg [3:0] topnyb; -reg [3:0] btmnyb; -reg [7:0] newinst; -begin - newinst = i; - - topnyb = i[7:4]; - btmnyb = i[3:0]; - - if ( (topnyb == 4'H0) || - (topnyb == 4'H4) || - (topnyb == 4'H5) || - (topnyb == 4'H6) || - (topnyb == 4'H7) - ) - begin - if (btmnyb == 4'H1) - newinst = {topnyb, 4'H0}; - if (btmnyb == 4'H2) - newinst = {topnyb, 4'H3}; - if (btmnyb == 4'H5) - newinst = {topnyb, 4'H4}; - if (btmnyb == 4'HB) - newinst = {topnyb, 4'HA}; - end - MapInstruction = newinst; -end -endfunction - - -wire [7:0] MappedInstruction; -generate -if (ILLEGAL_INSTRUCTIONS=="GHOST") -begin : ghost - if(IS_KONAMI1=="FALSE") //Modification by Ace: accept opcodes directly for KONAMI-1 CPU - assign MappedInstruction = MapInstruction(D); - else - assign MappedInstruction = MapInstruction(OP); -end -else -begin - assign MappedInstruction = D; -end -endgenerate - - - -/////////////////////////////////////////////////////////////////////// - -function IllegalInstruction(input [7:0] i); -reg [3:0] hi; -reg [3:0] lo; -reg illegal; -begin - illegal = 1'b0; - hi = i[7:4]; - lo = i[3:0]; - if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) ) - begin - if ( (lo == 4'H1) || (lo == 4'H2) || (lo == 4'H5) || (lo == 4'HB) ) - illegal = 1'b1; - if (lo == 4'HE) - if ( (hi == 4'H4) || (hi == 4'H5) ) - illegal = 1'b1; - end - if (hi == 4'H3) - begin - if ( (lo == 4'H8) || (lo == 4'HE) ) - illegal = 1'b1; - end - if (hi == 4'H1) - begin - if ( (lo == 4'H4) || (lo == 4'H5) || (lo == 4'H8) || (lo == 4'HB) ) - illegal = 1'b1; - end - if ( (hi == 4'H8) || (hi == 4'HC) ) - begin - if ( (lo == 4'H7) || (lo == 4'HF) ) - illegal = 1'b1; - if ( lo == 4'HD ) - if (hi == 4'HC) - illegal = 1'b1; - end - IllegalInstruction = illegal; -end -endfunction - -wire IsIllegalInstruction; - -generate -if (ILLEGAL_INSTRUCTIONS=="GHOST") -begin : never_illegal - assign IsIllegalInstruction = 1'b0; -end -else -begin - assign IsIllegalInstruction = IllegalInstruction(Inst1); -end -endgenerate - -wire [6:0] IllegalInstructionState; -generate -if (ILLEGAL_INSTRUCTIONS=="IGNORE") -begin : illegal_state - assign IllegalInstructionState = CPUSTATE_FETCH_I1; -end -else if (ILLEGAL_INSTRUCTIONS=="STOP") -begin - assign IllegalInstructionState = CPUSTATE_STOP; -end -else -begin - assign IllegalInstructionState = 7'd0; -end -endgenerate - - -/////////////////////////////////////////////////////////////////////// - - -always @(posedge CLK) -begin - reg old_sample; - old_sample <= NMISample2; - - if (wNMIClear == 1) NMILatched <= 1; - else if(old_sample & ~NMISample2) NMILatched <= NMIMask; -end - -// -// The 6809 specs say that the CPU control signals are sampled on the falling edge of Q. -// It also says that the interrupts require 1 cycle of synchronization time. -// That's vague, as it doesn't say where "1 cycle" starts or ends. Starting from the -// falling edge of Q, the next cycle notices an assertion. From checking a hard 6809 on -// an analyzer, what they really mean is that it's sampled on the falling edge of Q, -// but there's a one cycle delay from the falling edge of E (0.25 clocks from the falling edge of Q -// where the signals were sampled) before it can be noticed. -// So, SIGNALSample is the latched value at the falling edge of Q -// SIGNALSample2 is the latched value at the falling edge of E (0.25 clocks after the line above) -// SIGNALLatched is the latched value at the falling edge of E (1 cycle after the line above) -// -// /HALT and /DMABREQ are delayed one cycle less than interrupts. The 6809 specs infer these details, -// but don't list the point-of-reference they're written from (for instance, they say that an interrupt requires -// a cycle for synchronization; however, it isn't clear whether that's from the falling Q to the next falling Q, -// a complete intermediate cycle, the falling E to the next falling E, etc.) - which, in the end, required an -// analyzer on the 6809 to determine how many cycles before a new instruction an interrupt (or /HALT & /DMABREQ) -// had to be asserted to be noted instead of the next instruction running start to finish. -// -always @(posedge CLK) -begin - if(fallQ_en) begin - NMISample <= nNMI; - IRQSample <= nIRQ; - FIRQSample <= nFIRQ; - HALTSample <= nHALT; - DMABREQSample <= nDMABREQ; - end -end - - -reg rnRESET=0; // The latched version of /RESET, useful 1 clock after it's latched -always @(posedge CLK) -begin - if(fallE_en) begin - rnRESET <= nRESET; - - NMISample2 <= NMISample; - - IRQSample2 <= IRQSample; - IRQLatched <= IRQSample2; - - FIRQSample2 <= FIRQSample; - FIRQLatched <= FIRQSample2; - - HALTSample2 <= HALTSample; - HALTLatched <= HALTSample2; - - DMABREQSample2 <= DMABREQSample; - DMABREQLatched <= DMABREQSample2; - - - if (rnRESET == 1) - begin - CpuState <= CpuState_nxt; - - // Don't interpret this next item as "The Next State"; it's a special case 'after this - // generic state, go to this programmable state', so that a single state - // can be shared for many tasks. [Specifically, the stack push/pull code, which is used - // for PSH, PUL, Interrupts, RTI, etc. - NextState <= NextState_nxt; - - // CPU registers latch from the combinatorial circuit - a <= a_nxt; - b <= b_nxt; - x <= x_nxt; - y <= y_nxt; - s <= s_nxt; - u <= u_nxt; - cc <= cc_nxt; - dp <= dp_nxt; - pc <= pc_nxt; - tmp <= tmp_nxt; - addr <= addr_nxt; - ea <= ea_nxt; - - InstPage2 <= InstPage2_nxt; - InstPage3 <= InstPage3_nxt; - Inst1 <= Inst1_nxt; - Inst2 <= Inst2_nxt; - Inst3 <= Inst3_nxt; - NMIClear <= NMIClear_nxt; - - IntType <= IntType_nxt; - - // Once S changes at all (default is '0'), release the NMI Mask. - if (s != s_nxt) NMIMask <= 1'b0; - end - else - begin - CpuState <= CPUSTATE_RESET; - NMIMask <= 1'b1; // Mask NMI until S is loaded. - NMIClear <= 1'b0; // Mark us as not having serviced NMI - end - end -end - - -///////////////////////////////////////////////////////////////// -// Decode the Index byte - -localparam IDX_REG_X = 3'd0; -localparam IDX_REG_Y = 3'd1; -localparam IDX_REG_U = 3'd2; -localparam IDX_REG_S = 3'd3; -localparam IDX_REG_PC = 3'd4; - -localparam IDX_MODE_POSTINC1 = 4'd0; -localparam IDX_MODE_POSTINC2 = 4'd1; -localparam IDX_MODE_PREDEC1 = 4'd2; -localparam IDX_MODE_PREDEC2 = 4'd3; -localparam IDX_MODE_NOOFFSET = 4'd4; -localparam IDX_MODE_B_OFFSET = 4'd5; -localparam IDX_MODE_A_OFFSET = 4'd6; -localparam IDX_MODE_5BIT_OFFSET= 4'd7; // Special case, not bit pattern 7; the offset sits in the bit pattern -localparam IDX_MODE_8BIT_OFFSET= 4'd8; -localparam IDX_MODE_16BIT_OFFSET = 4'd9; -localparam IDX_MODE_D_OFFSET = 4'd11; -localparam IDX_MODE_8BIT_OFFSET_PC = 4'd12; -localparam IDX_MODE_16BIT_OFFSET_PC= 4'd13; -localparam IDX_MODE_EXTENDED_INDIRECT = 4'd15; - -// Return: -// Register base [3 bits] -// Indirect [1 bit] -// Mode [4 bits] - -function [7:0] IndexDecode(input [7:0] postbyte); -reg [2:0] regnum; -reg indirect; -reg [3:0] mode; -begin - indirect = 0; - mode = 0; - - if (postbyte[7] == 0) // 5-bit - begin - mode = IDX_MODE_5BIT_OFFSET; - end - else - begin - mode = postbyte[3:0]; - indirect = postbyte[4]; - end - if ((mode != IDX_MODE_8BIT_OFFSET_PC) && (mode != IDX_MODE_16BIT_OFFSET_PC)) - regnum[2:0] = postbyte[6:5]; - else - regnum[2:0] = IDX_REG_PC; - - IndexDecode = {indirect, mode, regnum}; -end -endfunction - -wire [3:0] IndexedMode; -wire IndexedIndirect; -wire [2:0] IndexedRegister; - -assign {IndexedIndirect, IndexedMode, IndexedRegister} = IndexDecode(Inst2); - -///////////////////////////////////////////////////////////////// -// Is this a JMP instruction? (irrespective of addressing mode) -function IsJMP(input [7:0] inst); -reg [3:0] hi; -reg [3:0] lo; -begin - hi = inst[7:4]; - lo = inst[3:0]; - - IsJMP = 0; - if ((hi == 4'H0) || (hi == 4'H6) || (hi == 4'H7)) - if (lo == 4'HE) - IsJMP = 1; -end -endfunction - -/////////////////////////////////////////////////////////////////// -// Is this an 8-bit Store? - -localparam ST8_REG_A = 1'b0; -localparam ST8_REG_B = 1'b1; - -function [1:0] IsST8(input [7:0] inst); -reg regnum; -reg IsStore; -begin - - IsStore = 1'b0; - regnum = 1'b1; - - if ( (Inst1 == 8'H97) || (Inst1 == 8'HA7) || (Inst1 == 8'HB7) ) - begin - IsStore = 1'b1; - regnum = 1'b0; - end - else if ( (Inst1 == 8'HD7) || (Inst1 == 8'HE7) || (Inst1 == 8'HF7) ) - begin - IsStore = 1'b1; - regnum = 1'b1; - end - IsST8 = {IsStore, regnum}; -end -endfunction - -wire IsStore8; -wire Store8RegisterNum; - -assign {IsStore8, Store8RegisterNum} = IsST8(Inst1); - - -///////////////////////////////////////////////////////////////// -// Is this a 16-bit Store? - -localparam ST16_REG_X = 3'd0; -localparam ST16_REG_Y = 3'd1; -localparam ST16_REG_U = 3'd2; -localparam ST16_REG_S = 3'd3; -localparam ST16_REG_D = 3'd4; - - -function [3:0] IsST16(input [7:0] inst); -reg [3:0] hi; -reg [3:0] lo; -reg [2:0] regnum; -reg IsStore; -begin - hi = inst[7:4]; - lo = inst[3:0]; - IsStore = 1'b0; - regnum = 3'b111; - - if ((inst == 8'H9F) || (inst == 8'HAF) || (inst == 8'HBF)) - begin - IsStore = 1; - if (~InstPage2) - regnum = ST16_REG_X; - else - regnum = ST16_REG_Y; - end - else if ((inst == 8'HDF) || (inst == 8'HEF) || (inst == 8'HFF)) - begin - IsStore = 1; - if (~InstPage2) - regnum = ST16_REG_U; - else - regnum = ST16_REG_S; - end - else if ((inst == 8'HDD) || (inst == 8'HED) || (inst == 8'HFD)) - begin - IsStore = 1; - regnum = ST16_REG_D; - end - - IsST16 = {IsStore, regnum}; -end -endfunction - -wire IsStore16; -wire [2:0] StoreRegisterNum; - -assign {IsStore16, StoreRegisterNum} = IsST16(Inst1); - -///////////////////////////////////////////////////////////////// -// Is this a special Immediate mode instruction, ala -// PSH, PUL, EXG, TFR, ANDCC, ORCC -function IsSpecialImm(input [7:0] inst); -reg is; -reg [3:0] hi; -reg [3:0] lo; -begin - hi = inst[7:4]; - lo = inst[3:0]; - is = 0; - - if (hi == 4'H1) - begin - if ( (lo == 4'HA) || (lo == 4'HC) || (lo == 4'HE) || (lo == 4'HF) ) // ORCC, ANDCC, EXG, TFR - is = 1; - end - else if (hi == 4'H3) - begin - if ( (lo >= 4'H3) && (lo <= 4'H7) ) // PSHS, PULS, PSHU, PULU - is = 1; - end - else - is = 0; - - IsSpecialImm = is; -end -endfunction -wire IsSpecialImmediate = IsSpecialImm(Inst1); - -///////////////////////////////////////////////////////////////// -// Is this a one-byte instruction? [The 6809 reads 2 bytes for every instruction, minimum (it can read more). On a one-byte, we have to ensure that we haven't skipped the PC ahead. -function IsOneByteInstruction(input [7:0] inst); -reg is; -reg [3:0] hi; -reg [3:0] lo; -begin - hi = inst[7:4]; - lo = inst[3:0]; - is = 1'b0; - - if ( (hi == 4'H4) || (hi == 4'H5) ) - is = 1'b1; - else if ( hi == 4'H1) - begin - if ( (lo == 4'H2) || (lo == 4'H3) || (lo == 4'H9) || (lo == 4'HD) ) - is = 1'b1; - end - else if (hi == 4'H3) - begin - if ( (lo >= 4'H9) && (lo != 4'HC) ) - is = 1'b1; - end - else - is = 1'b0; - - IsOneByteInstruction = is; -end -endfunction - -///////////////////////////////////////////////////////////////// -// ALU16 - Simpler than the 8 bit ALU - -localparam ALU16_REG_X = 3'd0; -localparam ALU16_REG_Y = 3'd1; -localparam ALU16_REG_U = 3'd2; -localparam ALU16_REG_S = 3'd3; -localparam ALU16_REG_D = 3'd4; - -function [2:0] ALU16RegFromInst(input Page2, input Page3, input [7:0] inst); -reg [2:0] srcreg; -begin - srcreg = 3'b111; // default - casex ({Page2, Page3, inst}) // Note pattern for the matching below - 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD - srcreg = ALU16_REG_D; - 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY - srcreg = ALU16_REG_Y; - 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU - srcreg = ALU16_REG_U; - 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS - srcreg = ALU16_REG_S; - 10'b0010xx1100: // 8C,9C,AC,BC CMPX - srcreg = ALU16_REG_X; - - 10'b0011xx0011: // C3, D3, E3, F3 ADDD - srcreg = ALU16_REG_D; - - 10'b0011xx1100: // CC, DC, EC, FC LDD - srcreg = ALU16_REG_D; - 10'b0010xx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX - srcreg = ALU16_REG_X; - 10'b0011xx1110: // CE LDU, DE LDU, EE LDU, FE LDU - srcreg = ALU16_REG_U; - 10'b1010xx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY - srcreg = ALU16_REG_Y; - 10'b1011xx1110: // 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS - srcreg = ALU16_REG_S; - 10'b0010xx0011: // 83, 93, A3, B3 SUBD - srcreg = ALU16_REG_D; - - 10'H03A: // 3A ABX - srcreg = ALU16_REG_X; - 10'H030: // 30 LEAX - srcreg = ALU16_REG_X; - 10'H031: // 31 LEAY - srcreg = ALU16_REG_Y; - 10'H032: // 32 LEAS - srcreg = ALU16_REG_S; - 10'H033: // 32 LEAU - srcreg = ALU16_REG_U; - default: - srcreg = 3'b111; - endcase - ALU16RegFromInst = srcreg; -end -endfunction - -wire [2:0] ALU16Reg = ALU16RegFromInst(InstPage2, InstPage3, Inst1); - -localparam ALUOP16_SUB = 3'H0; -localparam ALUOP16_ADD = 3'H1; -localparam ALUOP16_LD = 3'H2; -localparam ALUOP16_CMP = 3'H3; -localparam ALUOP16_LEA = 3'H4; -localparam ALUOP16_INVALID = 3'H7; - -function [3:0] ALU16OpFromInst(input Page2, input Page3, input [7:0] inst); -reg [2:0] aluop; -reg writeback; -begin - aluop = 3'b111; - writeback = 1'b1; - casex ({Page2, Page3, inst}) - 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD - begin - aluop = ALUOP16_CMP; - writeback = 1'b0; - end - 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY - begin - aluop = ALUOP16_CMP; - writeback = 1'b0; - end - 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU - begin - aluop = ALUOP16_CMP; - writeback = 1'b0; - end - 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS - begin - aluop = ALUOP16_CMP; - writeback = 1'b0; - end - 10'b0010xx1100: // 8C,9C,AC,BC CMPX - begin - aluop = ALUOP16_CMP; - writeback = 1'b0; - end - - 10'b0011xx0011: // C3, D3, E3, F3 ADDD - aluop = ALUOP16_ADD; - - 10'b0011xx1100: // CC, DC, EC, FC LDD - aluop = ALUOP16_LD; - 10'b001xxx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX, CE LDU, DE LDU, EE LDU, FE LDU - aluop = ALUOP16_LD; - 10'b101xxx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY, 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS - aluop = ALUOP16_LD; - - 10'b0010xx0011: // 83, 93, A3, B3 SUBD - aluop = ALUOP16_SUB; - - 10'H03A: // 3A ABX - aluop = ALUOP16_ADD; - - 10'b00001100xx: // $30-$33, LEAX, LEAY, LEAS, LEAU - aluop = ALUOP16_LEA; - - default: - aluop = ALUOP16_INVALID; - endcase - ALU16OpFromInst = {writeback, aluop}; -end -endfunction - -wire ALU16OpWriteback; -wire [2:0] ALU16Opcode; - -assign {ALU16OpWriteback, ALU16Opcode} = ALU16OpFromInst(InstPage2, InstPage3, Inst1); - -wire IsALU16Opcode = (ALU16Opcode != 3'b111); - -function [23:0] ALU16Inst(input [2:0] operation16, input [15:0] a_arg, input [15:0] b_arg, input [7:0] cc_arg); -reg [7:0] cc_out; -reg [15:0] ALUFn; -reg carry; -reg borrow; -begin - cc_out = cc_arg; - case (operation16) - ALUOP16_ADD: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + b_arg; - cc_out[CC_V_BIT] = (a_arg[15] & b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & ~b_arg[15] & ALUFn[15]); - end - - ALUOP16_SUB: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; - cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]); - end - - ALUOP16_LD: - begin - ALUFn = b_arg; - cc_out[CC_V_BIT] = 1'b0; - end - - ALUOP16_CMP: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; - cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]); - end - - ALUOP16_LEA: - begin - ALUFn = a_arg; - end - - default: - ALUFn = 16'H0000; - - endcase - cc_out[CC_Z_BIT] = (ALUFn[15:0] == 16'H0000); - if (operation16 != ALUOP16_LEA) - cc_out[CC_N_BIT] = ALUFn[15]; - ALU16Inst = {cc_out, ALUFn}; -end -endfunction - -reg [2:0] ALU16_OP; -reg [15:0] ALU16_A; -reg [15:0] ALU16_B; -reg [7:0] ALU16_CC; - -// Top 8 bits == CC, bottom 8 bits = output value -wire [23:0] ALU16 = ALU16Inst(ALU16_OP, ALU16_A, ALU16_B, ALU16_CC); - - -///////////////////////////////////////////////////////////////// -// ALU - -// The ops are organized from the 4 low-order bits of the instructions for the first set of ops, then 16-31 are the second set - even though bit 4 isn't representative. -localparam ALUOP_NEG = 5'd0; -localparam ALUOP_COM = 5'd3; -localparam ALUOP_LSR = 5'd4; -localparam ALUOP_ROR = 5'd6; -localparam ALUOP_ASR = 5'd7; -localparam ALUOP_ASL = 5'd8; -localparam ALUOP_LSL = 5'd8; -localparam ALUOP_ROL = 5'd9; -localparam ALUOP_DEC = 5'd10; -localparam ALUOP_INC = 5'd12; -localparam ALUOP_TST = 5'd13; -localparam ALUOP_CLR = 5'd15; - -localparam ALUOP_SUB = 5'd16; -localparam ALUOP_CMP = 5'd17; -localparam ALUOP_SBC = 5'd18; -localparam ALUOP_AND = 5'd20; -localparam ALUOP_BIT = 5'd21; -localparam ALUOP_LD = 5'd22; -localparam ALUOP_EOR = 5'd24; -localparam ALUOP_ADC = 5'd25; -localparam ALUOP_OR = 5'd26; -localparam ALUOP_ADD = 5'd27; - -function [5:0] ALUOpFromInst(input [7:0] inst); -reg [4:0] op; -reg writeback; -begin - // Okay, this turned out to be simpler than I expected ... - op = {inst[7], inst[3:0]}; - case (op) - ALUOP_CMP: - writeback = 0; - ALUOP_TST: - writeback = 0; - ALUOP_BIT: - writeback = 0; - default: - writeback = 1; - endcase - ALUOpFromInst = {writeback, op}; -end -endfunction - -wire [4:0] ALU8Op; -wire ALU8Writeback; - -assign {ALU8Writeback, ALU8Op} = ALUOpFromInst(Inst1); - -reg [7:0] ALU_A; -reg [7:0] ALU_B; -reg [7:0] ALU_CC; -reg [4:0] ALU_OP; - - -function [15:0] ALUInst(input [4:0] operation, input [7:0] a_arg, input [7:0] b_arg, input [7:0] cc_arg); -reg [7:0] cc_out; -reg [7:0] ALUFn; -reg borrow; -begin - cc_out = cc_arg; - case (operation) - ALUOP_NEG: - begin - ALUFn = ~a_arg + 1'b1; - cc_out[CC_C_BIT] = (ALUFn != 8'H00); - cc_out[CC_V_BIT] = (a_arg == 8'H80); - end - - ALUOP_LSL: - begin - {cc_out[CC_C_BIT], ALUFn} = {a_arg, 1'b0}; - cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6]; - end - - ALUOP_LSR: - begin - {ALUFn, cc_out[CC_C_BIT]} = {1'b0, a_arg}; - end - - ALUOP_ASR: - begin - {ALUFn, cc_out[CC_C_BIT]} = {a_arg[7], a_arg}; - end - - ALUOP_ROL: - begin - {cc_out[CC_C_BIT], ALUFn} = {a_arg, cc_arg[CC_C_BIT]}; - cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6]; - end - - ALUOP_ROR: - begin - {ALUFn, cc_out[CC_C_BIT]} = {cc_arg[CC_C_BIT], a_arg}; - end - - ALUOP_OR: - begin - ALUFn = (a_arg | b_arg); - cc_out[CC_V_BIT] = 0; - end - - ALUOP_ADD: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg}; - cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]); - cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4]; - end - - ALUOP_SUB: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; - cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); - end - - ALUOP_AND: - begin - ALUFn = (a_arg & b_arg); - cc_out[CC_V_BIT] = 0; - end - - ALUOP_BIT: - begin - ALUFn = (a_arg & b_arg); - cc_out[CC_V_BIT] = 0; - end - - ALUOP_EOR: - begin - ALUFn = (a_arg ^ b_arg); - cc_out[CC_V_BIT] = 0; - end - - ALUOP_CMP: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg}; - cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); - end - - ALUOP_COM: - begin - ALUFn = ~a_arg; - cc_out[CC_V_BIT] = 0; - cc_out[CC_C_BIT] = 1; - end - - ALUOP_ADC: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg} + cc_arg[CC_C_BIT]; - cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]); - cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4]; - end - - ALUOP_LD: - begin - ALUFn = b_arg; - cc_out[CC_V_BIT] = 0; - end - - ALUOP_INC: - begin - ALUFn = a_arg + 1'b1; - cc_out[CC_V_BIT] = (~a_arg[7] & ALUFn[7]); - end - - ALUOP_DEC: - begin - ALUFn = a_arg - 1'b1; - cc_out[CC_V_BIT] = (a_arg[7] & ~ALUFn[7]); - end - - ALUOP_CLR: - begin - ALUFn = 0; - cc_out[CC_V_BIT] = 0; - cc_out[CC_C_BIT] = 0; - end - - ALUOP_TST: - begin - ALUFn = a_arg; - cc_out[CC_V_BIT] = 0; - end - - ALUOP_SBC: - begin - {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg} - cc_arg[CC_C_BIT]; - cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]); - end - - default: - ALUFn = 0; - - endcase - - cc_out[CC_N_BIT] = ALUFn[7]; - cc_out[CC_Z_BIT] = !ALUFn; - ALUInst = {cc_out[7:0], ALUFn}; -end -endfunction - - -// Top 8 bits == CC, bottom 8 bits = output value -wire [15:0] ALU = ALUInst(ALU_OP, ALU_A, ALU_B, ALU_CC); - -//////////////////////////////////////////////////////////// - -localparam TYPE_INHERENT = 3'd0; -localparam TYPE_IMMEDIATE = 3'd1; -localparam TYPE_DIRECT = 3'd2; -localparam TYPE_RELATIVE = 3'd3; -localparam TYPE_INDEXED = 3'd4; -localparam TYPE_EXTENDED = 3'd5; - -localparam TYPE_INVALID = 3'd7; - -// Function to decode the addressing mode the instruction uses -function [2:0] addressing_mode_type(input [7:0] inst); -begin - casex (inst) - 8'b0000???? : addressing_mode_type = TYPE_DIRECT; - 8'b0001???? : - begin - casex (inst[3:0]) - 4'b0010: - addressing_mode_type = TYPE_INHERENT; - - 4'b0011: - addressing_mode_type = TYPE_INHERENT; - - 4'b1001: - addressing_mode_type = TYPE_INHERENT; - - 4'b1101: - addressing_mode_type = TYPE_INHERENT; - - 4'b0110: - addressing_mode_type = TYPE_RELATIVE; - - 4'b0111: - addressing_mode_type = TYPE_RELATIVE; - - 4'b1010: - addressing_mode_type = TYPE_IMMEDIATE; - - 4'b1100: - addressing_mode_type = TYPE_IMMEDIATE; - - 4'b1110: - addressing_mode_type = TYPE_IMMEDIATE; - - 4'b1111: - addressing_mode_type = TYPE_IMMEDIATE; - - default: - addressing_mode_type = TYPE_INVALID; - endcase - end - - 8'b0010????: addressing_mode_type = TYPE_RELATIVE; - 8'b0011????: - begin - casex(inst[3:0]) - 4'b00??: - addressing_mode_type = TYPE_INDEXED; - - 4'b01??: - addressing_mode_type = TYPE_IMMEDIATE; - - 4'b1001: - addressing_mode_type = TYPE_INHERENT; - - 4'b101?: - addressing_mode_type = TYPE_INHERENT; - - 4'b1100: - addressing_mode_type = TYPE_INHERENT; - - 4'b1101: - addressing_mode_type = TYPE_INHERENT; - - 4'b1111: - addressing_mode_type = TYPE_INHERENT; - - default: - addressing_mode_type = TYPE_INVALID; - endcase - end - - 8'b010?????: addressing_mode_type = TYPE_INHERENT; - - 8'b0110????: addressing_mode_type = TYPE_INDEXED; - - 8'b0111????: addressing_mode_type = TYPE_EXTENDED; - - 8'b1000????: - begin - casex (inst[3:0]) - 4'b0111: addressing_mode_type = TYPE_INVALID; - 4'b1111: addressing_mode_type = TYPE_INVALID; - 4'b1101: addressing_mode_type = TYPE_RELATIVE; - default: addressing_mode_type = TYPE_IMMEDIATE; - endcase - end - - 8'b1001????: addressing_mode_type = TYPE_DIRECT; - 8'b1010????: addressing_mode_type = TYPE_INDEXED; - 8'b1011????: addressing_mode_type = TYPE_EXTENDED; - 8'b1100????: addressing_mode_type = TYPE_IMMEDIATE; - 8'b1101????: addressing_mode_type = TYPE_DIRECT; - 8'b1110????: addressing_mode_type = TYPE_INDEXED; - 8'b1111????: addressing_mode_type = TYPE_EXTENDED; - - endcase -end -endfunction - -wire [2:0] AddrModeType = addressing_mode_type(Inst1); - -////////////////////////////////////////////////// - -// Individual opcodes that are the top of a column of states. - -localparam OPCODE_INH_ABX = 8'H3A; -localparam OPCODE_INH_RTS = 8'H39; -localparam OPCODE_INH_RTI = 8'H3B; -localparam OPCODE_INH_CWAI = 8'H3C; -localparam OPCODE_INH_MUL = 8'H3D; -localparam OPCODE_INH_SWI = 8'H3F; -localparam OPCODE_INH_SEX = 8'H1D; -localparam OPCODE_INH_NOP = 8'H12; -localparam OPCODE_INH_SYNC = 8'H13; -localparam OPCODE_INH_DAA = 8'H19; - -localparam OPCODE_IMM_ORCC = 8'H1A; -localparam OPCODE_IMM_ANDCC = 8'H1C; -localparam OPCODE_IMM_EXG = 8'H1E; -localparam OPCODE_IMM_TFR = 8'H1F; -localparam OPCODE_IMM_PSHS = 8'H34; -localparam OPCODE_IMM_PULS = 8'H35; -localparam OPCODE_IMM_PSHU = 8'H36; -localparam OPCODE_IMM_PULU = 8'H37; - -localparam OPCODE_IMM_SUBD = 8'H83; -localparam OPCODE_IMM_CMPX = 8'H8C; -localparam OPCODE_IMM_LDX = 8'H8E; -localparam OPCODE_IMM_ADDD = 8'HC3; -localparam OPCODE_IMM_LDD = 8'HCC; -localparam OPCODE_IMM_LDU = 8'HCE; -localparam OPCODE_IMM_CMPD = 8'H83; // Page2 -localparam OPCODE_IMM_CMPY = 8'H8C; // Page2 -localparam OPCODE_IMM_LDY = 8'H8E; // Page2 -localparam OPCODE_IMM_LDS = 8'HCE; // Page2 -localparam OPCODE_IMM_CMPU = 8'H83; // Page3 -localparam OPCODE_IMM_CMPS = 8'H8C; // Page3 - -localparam EXGTFR_REG_D = 4'H0; -localparam EXGTFR_REG_X = 4'H1; -localparam EXGTFR_REG_Y = 4'H2; -localparam EXGTFR_REG_U = 4'H3; -localparam EXGTFR_REG_S = 4'H4; -localparam EXGTFR_REG_PC = 4'H5; -localparam EXGTFR_REG_A = 4'H8; -localparam EXGTFR_REG_B = 4'H9; -localparam EXGTFR_REG_CC = 4'HA; -localparam EXGTFR_REG_DP = 4'HB; - -function IsALU8Set0(input [7:0] instr); -reg result; -reg [3:0] hi; -reg [3:0] lo; -begin - hi = instr[7:4]; - lo = instr[3:0]; - if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) ) - begin - if ( (lo != 4'H1) && (lo != 4'H2) && (lo != 4'H5) && (lo != 4'HB) && (lo != 4'HE) ) // permit NEG, COM, LSR, ROR, ASR, ASL/LSL, ROL, DEC, INC, TST, CLR - result = 1; - else - result = 0; - end - else - result = 0; - IsALU8Set0 = result; -end -endfunction - -function IsALU8Set1(input [7:0] instr); -reg result; -reg [3:0] hi; -reg [3:0] lo; -begin - hi = instr[7:4]; - lo = instr[3:0]; - if ( (hi >= 4'H8) ) - begin - if ( (lo <= 4'HB) && (lo != 4'H3) && (lo != 4'H7) ) // 8-bit SUB, CMP, SBC, AND, BIT, LD, EOR, ADC, OR, ADD - result = 1; - else - result = 0; - end - else - result = 0; - IsALU8Set1 = result; -end -endfunction - -// Determine if the instruction is performing an 8-bit op (ALU only) -function ALU8BitOp(input [7:0] instr); -begin - ALU8BitOp = IsALU8Set0(instr) | IsALU8Set1(instr); -end -endfunction - -wire Is8BitInst = ALU8BitOp(Inst1); - -function IsRegA(input [7:0] instr); -reg result; -reg [3:0] hi; -begin - hi = instr[7:4]; - if ((hi == 4'H4) || (hi == 4'H8) || (hi == 4'H9) || (hi == 4'HA) || (hi == 4'HB) ) - result = 1; - else - result = 0; - IsRegA = result; -end -endfunction - -wire IsTargetRegA = IsRegA(Inst1); - -// -// -// Decode -// 00-0F = DIRECT -// 10-1F = INHERENT, RELATIVE, IMMEDIATE -// 20-2F = RELATIVE -// 30-3F = INDEXED, IMMEDIATE (pus, pul), INHERENT -// 40-4F = INHERENT -// 50-5F = INHERENT -// 60-6F = INDEXED -// 70-7F = EXTENDED -// 80-8F = IMMEDIATE, RELATIVE (BSR) -// 90-9F = DIRECT -// A0-AF = INDEXED -// B0-BF = EXTENDED -// C0-CF = IMMEDIATE -// D0-DF = DIRECT -// E0-EF = INDEXED -// F0-FF = EXTENDED - -// DIRECT; 00-0F, 90-9F, D0-DF -// INHERENT; 10-1F (12, 13, 19, 1D), 30-3F (39-3F), 40-4F, 50-5F, -// RELATIVE: 10-1F (16, 17), 20-2F, 80-8F (8D) -// IMMEDIATE: 10-1F (1A, 1C, 1E, 1F), 30-3F (34-37), 80-8F (80-8C, 8E), C0-CF -// INDEXED: 60-6F, A0-AF, E0-EF -// EXTENDED: 70-7F, B0-Bf, F0-FF - -localparam INST_LBRA = 8'H16; // always -- shitty numbering, damnit -localparam INST_LBSR = 8'H17; // - -localparam INST_BRA = 8'H20; // always -localparam INST_BRN = 8'H21; // never -localparam INST_BHI = 8'H22; // CC.Z = 0 && CC.C = 0 -localparam INST_BLS = 8'H23; // CC.Z != 0 && CC.C != 0 -localparam INST_BCC = 8'H24; // CC.C = 0 -localparam INST_BHS = 8'H24; // same as BCC -localparam INST_BCS = 8'H25; // CC.C = 1 -localparam INST_BLO = 8'H25; // same as BCS -localparam INST_BNE = 8'H26; // CC.Z = 0 -localparam INST_BEQ = 8'H27; // CC.Z = 1 -localparam INST_BVC = 8'H28; // V = 1 -localparam INST_BVS = 8'H29; // V = 0 -localparam INST_BPL = 8'H2A; // CC.N = 0 -localparam INST_BMI = 8'H2B; // CC.N = 1 -localparam INST_BGE = 8'H2C; // CC.N = CC.V -localparam INST_BLT = 8'H2D; // CC.N != CC.V -localparam INST_BGT = 8'H2E; // CC.N = CC.V && CC.Z = 0 -localparam INST_BLE = 8'H2F; // CC.N != CC.V && CC.Z = 1 -localparam INST_BSR = 8'H8D; // always - -localparam NYB_BRA = 4'H0; // always -localparam NYB_BRN = 4'H1; // never -localparam NYB_BHI = 4'H2; // CC.Z = 0 && CC.C = 0 -localparam NYB_BLS = 4'H3; // CC.Z != 0 && CC.C != 0 -localparam NYB_BCC = 4'H4; // CC.C = 0 -localparam NYB_BHS = 4'H4; // same as BCC -localparam NYB_BCS = 4'H5; // CC.C = 1 -localparam NYB_BLO = 4'H5; // same as BCS -localparam NYB_BNE = 4'H6; // CC.Z = 0 -localparam NYB_BEQ = 4'H7; // CC.Z = 1 -localparam NYB_BVC = 4'H8; // V = 0 -localparam NYB_BVS = 4'H9; // V = 1 -localparam NYB_BPL = 4'HA; // CC.N = 0 -localparam NYB_BMI = 4'HB; // CC.N = 1 -localparam NYB_BGE = 4'HC; // CC.N = CC.V -localparam NYB_BLT = 4'HD; // CC.N != CC.V -localparam NYB_BGT = 4'HE; // CC.N = CC.V && CC.Z = 0 -localparam NYB_BLE = 4'HF; // CC.N != CC.V && CC.Z = 1 - - - -function take_branch(input [7:0] Inst1, input [7:0] cc); -begin - take_branch = 0; //default - if ( (Inst1 == INST_BSR) || (Inst1 == INST_LBSR) || (Inst1 == INST_LBRA) ) - take_branch = 1; - else - case (Inst1[3:0]) - NYB_BRA: - take_branch = 1; - NYB_BRN: - take_branch = 0; - NYB_BHI: - if ( ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) == 0) - take_branch = 1; - NYB_BLS: - if ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) - take_branch = 1; - NYB_BCC: - if ( cc[CC_C_BIT] == 0 ) - take_branch = 1; - NYB_BCS: - if ( cc[CC_C_BIT] == 1 ) - take_branch = 1; - NYB_BNE: - if ( cc[CC_Z_BIT] == 0 ) - take_branch = 1; - NYB_BEQ: - if ( cc[CC_Z_BIT] == 1 ) - take_branch = 1; - NYB_BVC: - if ( cc[CC_V_BIT] == 0) - take_branch = 1; - NYB_BVS: - if ( cc[CC_V_BIT] == 1) - take_branch = 1; - NYB_BPL: - if ( cc[CC_N_BIT] == 0 ) - take_branch = 1; - NYB_BMI: - if (cc[CC_N_BIT] == 1) - take_branch = 1; - NYB_BGE: - if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) - take_branch = 1; - NYB_BLT: - if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) - take_branch = 1; - NYB_BGT: - if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) & (cc[CC_Z_BIT] == 0) ) - take_branch = 1; - NYB_BLE: - if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) | (cc[CC_Z_BIT] == 1) ) - take_branch = 1; - endcase -end -endfunction - -wire TakeBranch = take_branch(Inst1, cc); - -///////////////////////////////////////////////////////////////////// -// Convenience function for knowing the contents for TFR, EXG -function [15:0] EXGTFRRegister(input [3:0] regid); -begin - case (regid) - EXGTFR_REG_D: - EXGTFRRegister = {a, b}; - EXGTFR_REG_X: - EXGTFRRegister = x; - EXGTFR_REG_Y: - EXGTFRRegister = y; - EXGTFR_REG_U: - EXGTFRRegister = u; - EXGTFR_REG_S: - EXGTFRRegister = s; - EXGTFR_REG_PC: - EXGTFRRegister = pc_p1; // For both EXG and TFR, this is used on the 2nd byte in the instruction's cycle. The PC intended to transfer is actually the next byte. - EXGTFR_REG_DP: - EXGTFRRegister = {8'HFF, dp}; - EXGTFR_REG_A: - EXGTFRRegister = {8'HFF, a}; - EXGTFR_REG_B: - EXGTFRRegister = {8'HFF, b}; - EXGTFR_REG_CC: - EXGTFRRegister = {8'HFF, cc}; - default: - EXGTFRRegister = 16'H0; - endcase -end -endfunction -wire [15:0] EXGTFRRegA = EXGTFRRegister(D[7:4]); -wire [15:0] EXGTFRRegB = EXGTFRRegister(D[3:0]); - -// CPU state machine -always @(*) -begin - rLIC = 1'b0; - rAVMA = 1'b1; - rBUSY = 1'b0; - - addr_nxt = 16'HFFFF; - pc_p1 = (pc+16'H1); - pc_p2 = (pc+16'H2); - pc_p3 = (pc+16'H3); - s_p1 = (s+16'H1); - s_m1 = (s-16'H1); - u_p1 = (u+16'H1); - u_m1 = (u-16'H1); - addr_p1 = (addr+16'H1); - ea_p1 = (ea+16'H1); - BS_nxt = 1'b0; - BA_nxt = 1'b0; - - // These may be overridden below, but the "next" version by default should be - // the last latched version. - IntType_nxt = IntType; - NMIClear_nxt = NMIClear; - NextState_nxt = NextState; - a_nxt = a; - b_nxt = b; - x_nxt = x; - y_nxt = y; - s_nxt = s; - u_nxt = u; - cc_nxt = cc; - dp_nxt = dp; - pc_nxt = pc; - tmp_nxt = tmp; - ea_nxt = ea; - - ALU_A = 8'H00; - ALU_B = 8'H00; - ALU_CC = 8'H00; - ALU_OP = 5'H00; - - ALU16_OP = 3'H0; - ALU16_A = 16'H0000; - ALU16_B = 16'H0000; - ALU16_CC = 8'H00; - - DOutput = 8'H00; - RnWOut = 1'b1; // read - - Inst1_nxt = Inst1; - Inst2_nxt = Inst2; - Inst3_nxt = Inst3; - InstPage2_nxt = InstPage2; - InstPage3_nxt = InstPage3; - - CpuState_nxt = CpuState; - - case (CpuState) - CPUSTATE_RESET: - begin - addr_nxt = 16'HFFFF; - a_nxt = 0; - b_nxt = 0; - x_nxt = 0; - y_nxt = 0; - s_nxt = 16'HFFFD; // Take care about removing the reset of S. There's logic depending on the delta between s and s_nxt to clear NMIMask. - u_nxt = 0; - cc_nxt = CC_F | CC_I; // reset disables interrupts - dp_nxt = 0; - ea_nxt = 16'HFFFF; - - RnWOut = 1; // read - rLIC = 1'b0; // Instruction incomplete - NMIClear_nxt= 1'b0; - IntType_nxt = 3'b111; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_RESET0; - end - - CPUSTATE_RESET0: - begin - addr_nxt = `RESET_VECTOR; - rBUSY = 1'b1; - pc_nxt[15:8] = D[7:0]; - BS_nxt = 1'b1; // ACK RESET - rAVMA = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_RESET2; - end - - CPUSTATE_RESET2: - begin - addr_nxt = addr_p1; - BS_nxt = 1'b1; // ACK RESET - pc_nxt[7:0] = D[7:0]; - rAVMA = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_FETCH_I1: - begin - if (~DMABREQLatched) - begin - addr_nxt = pc; - RnWOut = 1'b1; - rAVMA = 1'b0; - tmp_nxt = {tmp[15:4], 4'b1111}; - BS_nxt = 1'b1; - BA_nxt = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_DMABREQ; - end - else if (~HALTLatched) - begin - addr_nxt = pc; - RnWOut = 1'b1; - rAVMA = 1'b0; - BS_nxt = 1'b1; - BA_nxt = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_HALTED; - end - else // not halting, run the inst byte fetch - begin - addr_nxt = pc; // Set the address bus for the next instruction, first byte - pc_nxt = pc_p1; - RnWOut = 1; // Set for a READ - Inst1_nxt = MappedInstruction; - InstPage2_nxt = 0; - InstPage3_nxt = 0; - - // New instruction fetch; service interrupts pending - if (NMILatched == 0) - begin - pc_nxt = pc; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_NMI_START; - end - else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0)) - begin - pc_nxt = pc; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FIRQ_START; - end - else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0)) - begin - pc_nxt = pc; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_START; - end - - // The actual 1st byte checks - else if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10. - begin - InstPage2_nxt = 1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1V2; - end - else if (Inst1_nxt == 8'H11) // Page 3 - begin - InstPage3_nxt = 1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1V2; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I2; - end - end // if not halting - end - - CPUSTATE_FETCH_I1V2: - begin - addr_nxt = pc; // Set the address bus for the next instruction, first byte - pc_nxt = pc_p1; - RnWOut = 1; // Set for a READ - Inst1_nxt = MappedInstruction; - - if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10. - begin - if (InstPage3 == 0) // $11 $11 $11 $11 ... $11 $10 still = Page 3 - InstPage2_nxt = 1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1V2; - end - else if (Inst1_nxt == 8'H11) // Page 3 - begin - if (InstPage2 == 0) // $10 $10 ... $10 $11 still = Page 2 - InstPage3_nxt = 1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1V2; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I2; - end - end - - - CPUSTATE_FETCH_I2: // We've fetched the first byte. If a $10 or $11 (page select), mark those flags and fetch the next byte as instruction byte 1. - begin - addr_nxt = addr_p1; // Address bus++ - pc_nxt = pc_p1; - Inst2_nxt = D[7:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - - if (IsIllegalInstruction) // Skip illegal instructions - begin - - rAVMA = 1'b1; - CpuState_nxt = IllegalInstructionState; - rLIC = 1'b1; - end - else - begin - // First byte Decode for this stage - case (AddrModeType) - TYPE_INDEXED: - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_INDEXED_BASE; - end - - - TYPE_EXTENDED: - begin - ea_nxt[15:8] = Inst2_nxt; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_EXTENDED_ADDRLO; - end - TYPE_DIRECT: - begin - ea_nxt = {dp, Inst2_nxt}; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_DIRECT_DONTCARE; - end - - TYPE_INHERENT: - begin - if (Inst1 == OPCODE_INH_NOP) - begin - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else if (Inst1 == OPCODE_INH_DAA) // Bcd lunacy - begin - if ( ((cc[CC_C_BIT]) || (a[7:4] > 4'H9)) || - ((a[7:4] > 4'H8) && (a[3:0] > 4'H9)) ) - tmp_nxt[7:4] = 4'H6; - else - tmp_nxt[7:4] = 4'H0; - - if ((cc[CC_H_BIT]) || (a[3:0] > 4'H9)) - tmp_nxt[3:0] = 4'H6; - else - tmp_nxt[3:0] = 4'H0; - - // DAA handles carry in the weirdest way. - // If it's already set, it remains set, even if carry-out is 0. - // If it wasn't set, but the output of the operation is set, carry-out gets set. - {tmp_nxt[8], a_nxt} = {1'b0, a} + tmp_nxt[7:0]; - - cc_nxt[CC_C_BIT] = cc_nxt[CC_C_BIT] | tmp_nxt[8]; - - cc_nxt[CC_N_BIT] = a_nxt[7]; - cc_nxt[CC_Z_BIT] = (a_nxt == 8'H00); - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else if (Inst1 == OPCODE_INH_SYNC) - begin - CpuState_nxt = CPUSTATE_SYNC; - rLIC = 1'b1; - rAVMA = 1'b0; - end - else if (Inst1 == OPCODE_INH_MUL) - begin - tmp_nxt = 16'H0000; - ea_nxt[15:8] = 8'H00; - ea_nxt[7:0] = a; - a_nxt = 8; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_MUL_ACTION; - end - else if (Inst1 == OPCODE_INH_RTS) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_RTS_HI; - end - else if (Inst1 == OPCODE_INH_RTI) - begin - rAVMA = 1'b1; - tmp_nxt = 16'H1001; // Set tmp[12] to indicate an RTI being processed, and at least pull CC. - CpuState_nxt = CPUSTATE_PUL_ACTION; - NextState_nxt = CPUSTATE_FETCH_I1; - end - else if (Inst1 == OPCODE_INH_SWI) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_SWI_START; - end - else if (Inst1 == OPCODE_INH_CWAI) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_CWAI; - end - else if (Inst1 == OPCODE_INH_SEX) - begin - a_nxt = {8{b[7]}}; - cc_nxt[CC_N_BIT] = b[7]; - cc_nxt[CC_Z_BIT] = {b == 8'H00}; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else if (Inst1 == OPCODE_INH_ABX) - begin - x_nxt = x + b; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_ABX_DONTCARE; - end - else - begin - ALU_OP = ALU8Op; - if (IsTargetRegA) - ALU_A = a; - else - ALU_A = b; - - ALU_B = 0; - ALU_CC = cc; - cc_nxt = ALU[15:8]; - - if (ALU8Writeback) - begin - if (IsTargetRegA) - a_nxt = ALU[7:0]; - else - b_nxt = ALU[7:0]; - end - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - if (IsOneByteInstruction(Inst1)) // This check is probably superfluous. Every inherent instruction is 1 byte on the 6809. - pc_nxt = pc; // The 6809 auto-reads 2 bytes for every instruction. :( Adjust by not incrementing PC on the 2nd byte read. - end - - TYPE_IMMEDIATE: - begin - if (IsSpecialImmediate) - begin - if (Inst1 == OPCODE_IMM_ANDCC) - begin - pc_nxt = pc_p1; - cc_nxt = cc & D; //cc_nxt & Inst2_nxt; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_CC_DONTCARE; - end - else if (Inst1 == OPCODE_IMM_ORCC) - begin - pc_nxt = pc_p1; - cc_nxt = cc | D; //cc_nxt | Inst2_nxt; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_CC_DONTCARE; - end - else if ( (Inst1 == OPCODE_IMM_PSHS) | (Inst1 == OPCODE_IMM_PSHU) ) - begin - pc_nxt = pc_p1; - tmp_nxt[15] = 1'b0; - tmp_nxt[14] = Inst1[1]; // Mark whether to save to U or S. - tmp_nxt[13] = 1'b0; // Not pushing due to an interrupt. - tmp_nxt[13:8] = 6'H00; - tmp_nxt[7:0] = Inst2_nxt; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_PSH_DONTCARE1; - NextState_nxt = CPUSTATE_FETCH_I1; - end - else if ( (Inst1 == OPCODE_IMM_PULS) | (Inst1 == OPCODE_IMM_PULU) ) - begin - pc_nxt = pc_p1; - tmp_nxt[15] = 1'b0; - tmp_nxt[14] = Inst1[1]; // S (0) or U (1) stack in use. - tmp_nxt[13:8] = 6'H00; - tmp_nxt[7:0] = Inst2_nxt; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_PUL_DONTCARE1; - NextState_nxt = CPUSTATE_FETCH_I1; - end - else if (Inst1 == OPCODE_IMM_TFR) - begin - // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2. - - case (Inst2_nxt[3:0]) - EXGTFR_REG_D: - {a_nxt,b_nxt} = EXGTFRRegA; - EXGTFR_REG_X: - x_nxt = EXGTFRRegA; - EXGTFR_REG_Y: - y_nxt = EXGTFRRegA; - EXGTFR_REG_U: - u_nxt = EXGTFRRegA; - EXGTFR_REG_S: - s_nxt = EXGTFRRegA; - EXGTFR_REG_PC: - pc_nxt = EXGTFRRegA; - EXGTFR_REG_DP: - dp_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_A: - a_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_B: - b_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_CC: - cc_nxt = EXGTFRRegA[7:0]; - default: - begin - end - endcase - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TFR_DONTCARE1; - - end - else if (Inst1 == OPCODE_IMM_EXG) - begin - // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2. - - case (Inst2_nxt[7:4]) - EXGTFR_REG_D: - {a_nxt,b_nxt} = EXGTFRRegB; - EXGTFR_REG_X: - x_nxt = EXGTFRRegB; - EXGTFR_REG_Y: - y_nxt = EXGTFRRegB; - EXGTFR_REG_U: - u_nxt = EXGTFRRegB; - EXGTFR_REG_S: - s_nxt = EXGTFRRegB; - EXGTFR_REG_PC: - pc_nxt = EXGTFRRegB; - EXGTFR_REG_DP: - dp_nxt = EXGTFRRegB[7:0]; - EXGTFR_REG_A: - a_nxt = EXGTFRRegB[7:0]; - EXGTFR_REG_B: - b_nxt = EXGTFRRegB[7:0]; - EXGTFR_REG_CC: - cc_nxt = EXGTFRRegB[7:0]; - default: - begin - end - endcase - case (Inst2_nxt[3:0]) - EXGTFR_REG_D: - {a_nxt,b_nxt} = EXGTFRRegA; - EXGTFR_REG_X: - x_nxt = EXGTFRRegA; - EXGTFR_REG_Y: - y_nxt = EXGTFRRegA; - EXGTFR_REG_U: - u_nxt = EXGTFRRegA; - EXGTFR_REG_S: - s_nxt = EXGTFRRegA; - EXGTFR_REG_PC: - pc_nxt = EXGTFRRegA; - EXGTFR_REG_DP: - dp_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_A: - a_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_B: - b_nxt = EXGTFRRegA[7:0]; - EXGTFR_REG_CC: - cc_nxt = EXGTFRRegA[7:0]; - default: - begin - end - endcase - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXG_DONTCARE1; - end - end - // Determine if this is an 8-bit ALU operation. - else if (Is8BitInst) - begin - ALU_OP = ALU8Op; - if (IsTargetRegA) - ALU_A = a; - else - ALU_A = b; - - ALU_B = Inst2_nxt; - ALU_CC = cc; - cc_nxt = ALU[15:8]; - - if (ALU8Writeback) - begin - if (IsTargetRegA) - a_nxt = ALU[7:0]; - else - b_nxt = ALU[7:0]; - end - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else // Then it must be a 16 bit instruction - begin - // 83 SUBD - // 8C CMPX - // 8E LDX - // C3 ADDD - // CC LDD - // CE LDU - // 108E CMPD - // 108C CMPY - // 108E LDY - // 10CE LDS - // 1183 CMPU - // 118C CMPS - // Wow, they were just stuffing them in willy-nilly ... - - // LD* 16 bit immediate - if (IsALU16Opcode) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_16IMM_LO; - end - // there's a dead zone here; I need an else to take us back to CPUSTATE_FETCHI1 if we want to ignore illegal instructions, to CPUSTATE_DEAD if we want to catch them. - - end - - end - - TYPE_RELATIVE: - begin - // Is this a LB** or a B**? - // If InstPage2 is set, it's a long branch; if clear, a normal branch. - if ( (InstPage2) || (Inst1 == INST_LBRA) || (Inst1 == INST_LBSR) ) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_LBRA_OFFSETLOW; - end - else - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_BRA_DONTCARE; - end - - end - default: - begin - CpuState_nxt = CPUSTATE_FETCH_I1; - end - endcase - end - end - - - CPUSTATE_LBRA_OFFSETLOW: - begin - addr_nxt = pc; - pc_nxt = pc_p1; - Inst3_nxt = D[7:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_LBRA_DONTCARE; - end - - CPUSTATE_LBRA_DONTCARE: - begin - addr_nxt = 16'HFFFF; - if ( TakeBranch ) - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_LBRA_DONTCARE2; - end - else - begin - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - end - - CPUSTATE_BRA_DONTCARE: - begin - addr_nxt = 16'HFFFF; - tmp_nxt = pc; - if (TakeBranch) - begin - pc_nxt = pc + { {8{Inst2[7]}}, Inst2[7:0]}; // Sign-extend the 8 bit offset to 16. - - if (Inst1 == INST_BSR) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_BSR_DONTCARE1; - end - else - begin - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - end - else - begin - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - end - - CPUSTATE_LBRA_DONTCARE2: - begin - tmp_nxt= pc; - addr_nxt = 16'HFFFF; - - // Take branch - pc_nxt = pc + {Inst2[7:0], Inst3[7:0]}; - if (Inst1 == INST_LBSR) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_BSR_DONTCARE1; - end - else - begin - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - end - - CPUSTATE_BSR_DONTCARE1: - begin - addr_nxt = pc; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_BSR_DONTCARE2; - end - - CPUSTATE_BSR_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_BSR_RETURNLOW; - end - - CPUSTATE_BSR_RETURNLOW: - begin - addr_nxt = s_m1; - s_nxt = s_m1; - DOutput[7:0] = tmp[7:0]; - RnWOut = 0; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_BSR_RETURNHIGH; - end - - CPUSTATE_BSR_RETURNHIGH: - begin - addr_nxt = s_m1; - s_nxt = s_m1; - DOutput[7:0] = tmp[15:8]; - RnWOut = 0; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; // after this, RnWOut must go to 1, and the bus needs the PC placed on it. - end - - CPUSTATE_TFR_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TFR_DONTCARE2; - end - - CPUSTATE_TFR_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TFR_DONTCARE3; - end - - CPUSTATE_TFR_DONTCARE3: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TFR_DONTCARE4; - end - - CPUSTATE_TFR_DONTCARE4: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - rLIC = 1'b1; // Instruction done! - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_EXG_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXG_DONTCARE2; - end - - CPUSTATE_EXG_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXG_DONTCARE3; - end - - CPUSTATE_EXG_DONTCARE3: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXG_DONTCARE4; - end - - CPUSTATE_EXG_DONTCARE4: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXG_DONTCARE5; - end - - CPUSTATE_EXG_DONTCARE5: - begin - rAVMA = 1'b0; - addr_nxt = 16'HFFFF; - CpuState_nxt = CPUSTATE_EXG_DONTCARE6; - end - - CPUSTATE_EXG_DONTCARE6: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - rLIC = 1'b1; // Instruction done! - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_ABX_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - rLIC = 1'b1; // Instruction done! - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_RTS_HI: - begin - addr_nxt = s; - s_nxt = s_p1; - pc_nxt[15:8] = D[7:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_RTS_LO; - end - - CPUSTATE_RTS_LO: - begin - addr_nxt = s; - s_nxt = s_p1; - pc_nxt[7:0] = D[7:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_RTS_DONTCARE2; - end - - CPUSTATE_RTS_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_16IMM_LO: - begin - addr_nxt = pc; - pc_nxt = pc_p1; - - ALU16_OP = ALU16Opcode; - ALU16_CC = cc; - ALU16_B = {Inst2, D[7:0]}; - - case (ALU16Reg) - ALU16_REG_X: - ALU16_A = x; - ALU16_REG_D: - ALU16_A = {a, b}; - ALU16_REG_Y: - ALU16_A = y; - ALU16_REG_U: - ALU16_A = u; - ALU16_REG_S: - ALU16_A = s; - default: - ALU16_A = 16'H0; - endcase - - if (ALU16OpWriteback) - begin - case (ALU16Reg) - ALU16_REG_X: - {cc_nxt, x_nxt} = ALU16; - ALU16_REG_D: - {cc_nxt, a_nxt, b_nxt} = ALU16; - ALU16_REG_Y: - {cc_nxt, y_nxt} = ALU16; - ALU16_REG_U: - {cc_nxt, u_nxt} = ALU16; - ALU16_REG_S: - {cc_nxt, s_nxt} = ALU16; - default: - begin - end - endcase - end - else - cc_nxt = ALU16[23:16]; - - if (ALU16_OP == ALUOP16_LD) - begin - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_16IMM_DONTCARE; - end - end - - CPUSTATE_DIRECT_DONTCARE: - begin - addr_nxt = 16'HFFFF; - - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - - CPUSTATE_ALU_EA: - begin - - // Is Figure 18/5 Column 2? JMP (not Immediate Mode) - // This actually isn't done here. All checks passing in to ALU_EA should check for a JMP; FIXME EVERYWHERE - - // Is Figure 18/5 Column 8? TST (not immediate mode) - // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. - - // Is Figure 18/5 Column 3? - if (IsALU8Set1(Inst1)) - begin - addr_nxt = ea; - - ALU_OP = ALU8Op; - ALU_B = D[7:0]; - ALU_CC = cc; - - if (IsTargetRegA) - ALU_A = a; - else - ALU_A = b; - - cc_nxt = ALU[15:8]; - - if ( (ALU8Writeback) ) - begin - if (IsTargetRegA) - a_nxt = ALU[7:0]; - else - b_nxt = ALU[7:0]; - end - - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - // Is Figure 18/5 Column 4? (Store, 8 bits) - else if (IsStore8) - begin - addr_nxt = ea; - RnWOut = 0; // write - - ALU_OP = ALUOP_LD; // load has the same CC characteristics as store - ALU_A = 8'H00; - ALU_CC = cc; - - case (Store8RegisterNum) - ST8_REG_A: - begin - DOutput = a; - ALU_B = a; - end - ST8_REG_B: - begin - DOutput = b; - ALU_B = b; - end - - - endcase - - cc_nxt = ALU[15:8]; - - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - // Is Figure 18/5 Column 5? (Load, 16 bits) - else if (IsALU16Opcode & (ALU16Opcode == ALUOP16_LD)) - begin - addr_nxt = ea; - ea_nxt = ea_p1; - - case (ALU16Reg) - ALU16_REG_X: - x_nxt[15:8] = D[7:0]; - ALU16_REG_D: - a_nxt = D[7:0]; - ALU16_REG_Y: - y_nxt[15:8] = D[7:0]; - ALU16_REG_S: - s_nxt[15:8] = D[7:0]; - ALU16_REG_U: - u_nxt[15:8] = D[7:0]; - default: - begin - end - endcase - rAVMA = 1'b1; - rBUSY = 1'b1; - CpuState_nxt = CPUSTATE_LD16_LO; - - end - - // Is Figure 18/5 Column 6? (Store, 16 bits) - else if (IsStore16) - begin - addr_nxt = ea; - ea_nxt = ea_p1; - - ALU16_OP = ALUOP16_LD; // LD and ST have the same CC characteristics - ALU16_CC = cc; - ALU16_A = 8'H00; - - case (StoreRegisterNum) - ST16_REG_X: - begin - DOutput[7:0] = x[15:8]; - ALU16_B = x; - end - ST16_REG_Y: - begin - DOutput[7:0] = y[15:8]; - ALU16_B = y; - end - ST16_REG_U: - begin - DOutput[7:0] = u[15:8]; - ALU16_B = u; - end - ST16_REG_S: - begin - DOutput[7:0] = s[15:8]; - ALU16_B = s; - end - ST16_REG_D: - begin - DOutput[7:0] = a[7:0]; - ALU16_B = {a,b}; - end - default: - begin - end - endcase - - cc_nxt = ALU16[23:16]; - - RnWOut = 0; // Write - rAVMA = 1'b1; - rBUSY = 1'b1; - CpuState_nxt = CPUSTATE_ST16_LO; - end - - // Is Figure 18/5 Column 7? - else if (IsALU8Set0(Inst1)) - begin - // These are registerless instructions, ala - // ASL, ASR, CLR, COM, DEC, INC, (LSL), LSR, NEG, ROL, ROR - // and TST (special!) - // They require READ, Modify (the operation above), WRITE. Between the Read and the Write cycles, there's actually a /VMA - // cycle where the 6809 likely did the operation. We'll include a /VMA cycle for accuracy, but we'll do the work primarily in the first cycle. - addr_nxt = ea; - - ALU_OP = ALU8Op; - ALU_A = D[7:0]; - ALU_CC = cc; - tmp_nxt[15:8] = cc; // for debug only - tmp_nxt[7:0] = ALU[7:0]; - cc_nxt = ALU[15:8]; - if (ALU8Op == ALUOP_TST) - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TST_DONTCARE1; - end - else - begin - rAVMA = 1'b0; - rBUSY = 1'b1; - CpuState_nxt = CPUSTATE_ALU_DONTCARE; - end - - end - - // Is Figure 18/5 Column 8? TST - // NOTE: - // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. [Directly above.] - - - // Is Figure 18/5 Column 9? (16-bit ALU ops, non-load) - else if (IsALU16Opcode && (ALU16Opcode != ALUOP16_LD) && ((Inst1 < 8'H30) || (Inst1 > 8'H33)) ) // 30-33 = LEAX, LEAY, LEAS, LEAU; don't include them here. - begin - addr_nxt = ea; - ea_nxt = ea_p1; - - tmp_nxt[15:8] = D[7:0]; - rAVMA = 1'b1; - rBUSY = 1'b1; - CpuState_nxt = CPUSTATE_ALU16_LO; - - end - - // Is Figure 18/5 Column 10? JSR (not Immediate Mode) - else if ((Inst1 == 8'H9D) || (Inst1 == 8'HAD) || (Inst1 == 8'HBD)) // JSR - begin - pc_nxt = ea; - addr_nxt = ea; - tmp_nxt = pc; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_JSR_DONTCARE; - end - // Is Figure 18/5 Column 11? LEA(X,Y,S,U) - else if ((Inst1 >= 8'H30) && (Inst1<= 8'H33)) - begin - addr_nxt = 16'HFFFF; // Ack, actually a valid cycle, this isn't a dontcare (/VMA) cycle! - - ALU16_OP = ALU16Opcode; - ALU16_CC = cc; - ALU16_A = ea; - - case (ALU16Reg) - ALU16_REG_X: - {cc_nxt, x_nxt} = ALU16; - ALU16_REG_Y: - {cc_nxt, y_nxt} = ALU16; - ALU16_REG_U: - u_nxt = ALU16[15:0]; - ALU16_REG_S: - s_nxt = ALU16[15:0]; - default: - begin - end - endcase - - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - - end - - end - - - CPUSTATE_ALU_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - rBUSY = 1'b1; // We do nothing here, but on the real 6809, they did the modify phase here. :| - CpuState_nxt = CPUSTATE_ALU_WRITEBACK; - end - - CPUSTATE_ALU_WRITEBACK: - begin - addr_nxt = ea; - RnWOut = 0; // Write - DOutput = tmp[7:0]; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_LD16_LO: - begin - addr_nxt = ea; - - case (ALU16Reg) - ALU16_REG_X: - begin - x_nxt[7:0] = D[7:0]; - ALU16_B[15:8] = x[15:8]; - end - ALU16_REG_D: - begin - b_nxt = D[7:0]; - ALU16_B[15:8] = a; - end - ALU16_REG_Y: - begin - y_nxt[7:0] = D[7:0]; - ALU16_B[15:8] = y[15:8]; - end - ALU16_REG_S: - begin - s_nxt[7:0] = D[7:0]; - ALU16_B[15:8] = s[15:8]; - end - ALU16_REG_U: - begin - u_nxt[7:0] = D[7:0]; - ALU16_B[15:8] = u[15:8]; - end - default: - begin - end - - endcase - - ALU16_OP = ALU16Opcode; - ALU16_CC = cc; - ALU16_A = 8'H00; - ALU16_B[7:0] = D[7:0]; - cc_nxt = ALU16[23:16]; - - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_ST16_LO: - begin - addr_nxt = ea; - ea_nxt = ea_p1; - case (StoreRegisterNum) - ST16_REG_X: - DOutput[7:0] = x[7:0]; - ST16_REG_Y: - DOutput[7:0] = y[7:0]; - ST16_REG_U: - DOutput[7:0] = u[7:0]; - ST16_REG_S: - DOutput[7:0] = s[7:0]; - ST16_REG_D: - DOutput[7:0] = b[7:0]; - default: - begin - end - endcase - RnWOut = 0; // write - - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_ALU16_LO: - begin - addr_nxt = ea; - - ALU16_OP = ALU16Opcode; - ALU16_CC = cc; - - ALU16_B = {tmp[15:8], D[7:0]}; - - case (ALU16Reg) - ALU16_REG_X: - ALU16_A = x; - ALU16_REG_D: - ALU16_A = {a, b}; - ALU16_REG_Y: - ALU16_A = y; - ALU16_REG_S: - ALU16_A = s; - ALU16_REG_U: - ALU16_A = u; - default: - ALU16_A = 16'H0; - - endcase - - if (ALU16OpWriteback) - begin - case (ALU16Reg) - ALU16_REG_X: - {cc_nxt, x_nxt} = ALU16; - ALU16_REG_D: - {cc_nxt, a_nxt, b_nxt} = ALU16; - ALU16_REG_Y: - {cc_nxt, y_nxt} = ALU16; - ALU16_REG_U: - {cc_nxt, u_nxt} = ALU16; - ALU16_REG_S: - {cc_nxt, s_nxt} = ALU16; - default: - begin - end - endcase - end - else - cc_nxt = ALU16[23:16]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_ALU16_DONTCARE; - end - - CPUSTATE_ALU16_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - - CPUSTATE_JSR_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_JSR_RETLO; - end - - CPUSTATE_JSR_RETLO: - begin - addr_nxt = s_m1; - s_nxt = s_m1; - RnWOut = 0; - DOutput = tmp[7:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_JSR_RETHI; - end - - CPUSTATE_JSR_RETHI: - begin - addr_nxt = s_m1; - s_nxt = s_m1; - RnWOut = 0; - DOutput = tmp[15:8]; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_EXTENDED_ADDRLO: - begin - addr_nxt = pc; - pc_nxt = pc_p1; - ea_nxt[7:0] = D[7:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_EXTENDED_DONTCARE; - end - - CPUSTATE_EXTENDED_DONTCARE: - begin - addr_nxt = 16'HFFFF; - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - - CPUSTATE_INDEXED_BASE: - begin - addr_nxt = pc; - - Inst3_nxt = D[7:0]; - - case (IndexedRegister) - IDX_REG_X: - ALU16_A = x; - IDX_REG_Y: - ALU16_A = y; - IDX_REG_U: - ALU16_A = u; - IDX_REG_S: - ALU16_A = s; - IDX_REG_PC: - ALU16_A = pc_p1; - default: - ALU16_A = 16'H0; - endcase - ALU16_OP = ALUOP16_ADD; - - case (IndexedMode) - IDX_MODE_NOOFFSET: - begin - case (IndexedRegister) - IDX_REG_X: - ea_nxt = x; - IDX_REG_Y: - ea_nxt = y; - IDX_REG_U: - ea_nxt = u; - IDX_REG_S: - ea_nxt = s; - default: - ea_nxt = 16'H0; - endcase - - if (IndexedIndirect) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_INDIRECT_HI; - end - else - begin - if (IsJMP(Inst1)) - begin - pc_nxt = ea_nxt; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - end - - IDX_MODE_5BIT_OFFSET: - begin - // The offset is the bottom 5 bits of the Index Postbyte, which is Inst2 here. - // We'll sign-extend it to 16 bits. - ALU16_B = { {11{Inst2[4]}}, Inst2[4:0] }; - ea_nxt = ALU16[15:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_DONTCARE3; - end - - - IDX_MODE_8BIT_OFFSET_PC: - begin - ALU16_B = { {8{D[7]}}, D[7:0] }; - pc_nxt = pc_p1; - ea_nxt = ALU16[15:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_DONTCARE3; - end - - IDX_MODE_8BIT_OFFSET: - begin - ALU16_B = { {8{D[7]}}, D[7:0] }; - pc_nxt = pc_p1; - ea_nxt = ALU16[15:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_DONTCARE3; - end - - IDX_MODE_A_OFFSET: - begin - ALU16_B = { {8{a[7]}}, a[7:0] }; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_DONTCARE3; - ea_nxt = ALU16[15:0]; - end - - IDX_MODE_B_OFFSET: - begin - ALU16_B = { {8{b[7]}}, b[7:0] }; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_DONTCARE3; - ea_nxt = ALU16[15:0]; - end - - IDX_MODE_D_OFFSET: - begin - ALU16_B = {a, b}; - - ea_nxt = ALU16[15:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE1; - end - - IDX_MODE_POSTINC1: - begin - ALU16_B = 16'H1; - ea_nxt = ALU16_A; - case (IndexedRegister) - IDX_REG_X: - x_nxt = ALU16[15:0]; - IDX_REG_Y: - y_nxt = ALU16[15:0]; - IDX_REG_U: - u_nxt = ALU16[15:0]; - IDX_REG_S: - s_nxt = ALU16[15:0]; - default: - begin - end - endcase - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; - end - - IDX_MODE_POSTINC2: - begin - ALU16_B = 16'H2; - ea_nxt = ALU16_A; - case (IndexedRegister) - IDX_REG_X: - x_nxt = ALU16[15:0]; - IDX_REG_Y: - y_nxt = ALU16[15:0]; - IDX_REG_U: - u_nxt = ALU16[15:0]; - IDX_REG_S: - s_nxt = ALU16[15:0]; - default: - begin - end - endcase - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0; - end - - IDX_MODE_PREDEC1: - begin - ALU16_B = 16'HFFFF; // -1 - case (IndexedRegister) - IDX_REG_X: - x_nxt = ALU16[15:0]; - IDX_REG_Y: - y_nxt = ALU16[15:0]; - IDX_REG_U: - u_nxt = ALU16[15:0]; - IDX_REG_S: - s_nxt = ALU16[15:0]; - default: - begin - end - endcase - ea_nxt = ALU16[15:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; - end - - IDX_MODE_PREDEC2: - begin - ALU16_B = 16'HFFFE; // -2 - case (IndexedRegister) - IDX_REG_X: - x_nxt = ALU16[15:0]; - IDX_REG_Y: - y_nxt = ALU16[15:0]; - IDX_REG_U: - u_nxt = ALU16[15:0]; - IDX_REG_S: - s_nxt = ALU16[15:0]; - default: - begin - end - endcase - ea_nxt = ALU16[15:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0; - end - - IDX_MODE_16BIT_OFFSET_PC: - begin - tmp_nxt[15:8] = D[7:0]; - pc_nxt = pc_p1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO; - end - - IDX_MODE_16BIT_OFFSET: - begin - tmp_nxt[15:8] = D[7:0]; - pc_nxt = pc_p1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO; - end - - IDX_MODE_EXTENDED_INDIRECT: - begin - ea_nxt[15:8] = D[7:0]; - pc_nxt = pc_p1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_EXTIND_LO; - end - - default: - begin - rLIC = 1'b1; - CpuState_nxt = PostIllegalState; - end - - endcase - end - - CPUSTATE_IDX_OFFSET_LO: - begin - tmp_nxt[7:0] = D[7:0]; - addr_nxt = pc; - pc_nxt = pc_p1; - ALU16_B = tmp_nxt; - - case (IndexedRegister) - IDX_REG_X: - ALU16_A = x; - IDX_REG_Y: - ALU16_A = y; - IDX_REG_U: - ALU16_A = u; - IDX_REG_S: - ALU16_A = s; - IDX_REG_PC: - ALU16_A = pc; - default: - ALU16_A = 16'H0; - endcase - ALU16_OP = ALUOP16_ADD; - - ea_nxt = ALU16[15:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1; - end - - - CPUSTATE_IDX_DONTCARE3: - begin - addr_nxt = 16'HFFFF; - if (IndexedIndirect) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_INDIRECT_HI; - end - else - begin - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - - end - - CPUSTATE_IDX_16OFFSET_LO: - begin - addr_nxt = pc; - pc_nxt = pc_p1; - - case (IndexedRegister) - IDX_REG_X: - ALU16_A = x; - IDX_REG_Y: - ALU16_A = y; - IDX_REG_U: - ALU16_A = u; - IDX_REG_S: - ALU16_A = s; - IDX_REG_PC: - ALU16_A = pc_nxt; // Whups; tricky; not part of the actual pattern - default: - ALU16_A = x; // Default to something - endcase - - ALU16_OP = ALUOP16_ADD; - - ALU16_B = {tmp[15:8], D[7:0]}; - - ea_nxt = ALU16[15:0]; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1; - end - - CPUSTATE_IDX_16OFF_DONTCARE1: - begin - addr_nxt = pc; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; - end - - CPUSTATE_IDX_16OFF_DONTCARE0: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; - end - - CPUSTATE_IDX_16OFF_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - if (IndexedRegister == IDX_REG_PC) - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_PC16OFF_DONTCARE; - end - else - begin - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3; - end - end - - CPUSTATE_IDX_PC16OFF_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3; - end - - - CPUSTATE_IDX_16OFF_DONTCARE3: - begin - addr_nxt = 16'HFFFF; - if (IndexedIndirect) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_INDIRECT_HI; - end - else - begin - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - end - - CPUSTATE_IDX_DOFF_DONTCARE1: - begin - addr_nxt = pc_p1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2; - end - - CPUSTATE_IDX_DOFF_DONTCARE2: - begin - addr_nxt = pc_p2; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2; - end - - CPUSTATE_IDX_DOFF_DONTCARE3: - begin - addr_nxt = pc_p3; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2; - end - - CPUSTATE_IDX_EXTIND_LO: - begin - ea_nxt[7:0] = D[7:0]; - addr_nxt = pc; - pc_nxt = pc_p1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IDX_EXTIND_DONTCARE; - end - - CPUSTATE_IDX_EXTIND_DONTCARE: - begin - addr_nxt = pc; - if (IndexedIndirect) - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_INDIRECT_HI; - end - else - begin - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - end - - CPUSTATE_INDIRECT_HI: - begin - addr_nxt = ea; - tmp_nxt[15:8] = D[7:0]; - rAVMA = 1'b1; - rBUSY = 1'b1; - CpuState_nxt = CPUSTATE_INDIRECT_LO; - end - - CPUSTATE_INDIRECT_LO: - begin - addr_nxt = ea_p1; - ea_nxt[15:8] = tmp_nxt[15:8]; - ea_nxt[7:0] = D[7:0]; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_INDIRECT_DONTCARE; - end - - CPUSTATE_INDIRECT_DONTCARE: - begin - addr_nxt = 16'HFFFF; - if (IsJMP(Inst1)) - begin - pc_nxt = ea; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - else - begin - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_ALU_EA; - end - end - - CPUSTATE_MUL_ACTION: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - // tmp = result - // ea = additor (the shifted multiplicand) - // a = counter - // b is the multiplier (which gets shifted right) - if (a != 8'H00) - begin - if (b[0]) - begin - tmp_nxt = tmp + ea; - end - ea_nxt = {ea[14:0], 1'b0}; - b_nxt = {1'b0, b[7:1]}; - a_nxt = a - 8'H1; - end - else - begin - {a_nxt, b_nxt} = tmp; - - cc_nxt[CC_Z_BIT] = (tmp == 0); - cc_nxt[CC_C_BIT] = tmp[7]; - rLIC = 1'b1; // Instruction done! - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - end - - CPUSTATE_PSH_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_PSH_DONTCARE2; - end - - CPUSTATE_PSH_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_PSH_DONTCARE3; - end - - CPUSTATE_PSH_DONTCARE3: - begin - addr_nxt = (Inst1[1]) ? u : s; - - CpuState_nxt = CPUSTATE_PSH_ACTION; - end - - CPUSTATE_PSH_ACTION: - begin - rAVMA = 1'b1; - if (tmp[7] & ~(tmp[15])) // PC_LO - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = pc[7:0]; - RnWOut = 1'b0; // write - tmp_nxt[15] = 1'b1; - end - else if (tmp[7] & (tmp[15])) // PC_HI - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = pc[15:8]; - RnWOut = 1'b0; // write - tmp_nxt[7] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[6] & ~(tmp[15])) // U/S_LO - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = (tmp[14]) ? s[7:0] : u[7:0]; - RnWOut = 1'b0; // write - tmp_nxt[15] = 1'b1; - end - else if (tmp[6] & (tmp[15])) // U/S_HI - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = (tmp[14]) ? s[15:8] : u[15:8]; - RnWOut = 1'b0; // write - tmp_nxt[6] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[5] & ~(tmp[15])) // Y_LO - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = y[7:0]; - RnWOut = 1'b0; // write - tmp_nxt[15] = 1'b1; - end - else if (tmp[5] & (tmp[15])) // Y_HI - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = y[15:8]; - RnWOut = 1'b0; // write - tmp_nxt[5] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[4] & ~(tmp[15])) // X_LO - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = x[7:0]; - RnWOut = 1'b0; // write - tmp_nxt[15] = 1'b1; - end - else if (tmp[4] & (tmp[15])) // X_HI - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = x[15:8]; - RnWOut = 1'b0; // write - tmp_nxt[4] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[3]) // DP - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = dp; - RnWOut = 1'b0; // write - tmp_nxt[3] = 1'b0; - end - else if (tmp[2]) // B - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = b; - RnWOut = 1'b0; // write - tmp_nxt[2] = 1'b0; - end - else if (tmp[1]) // A - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = a; - RnWOut = 1'b0; // write - tmp_nxt[1] = 1'b0; - end - else if (tmp[0]) // CC - begin - addr_nxt = (tmp[14]) ? u_m1 : s_m1; - if (tmp[14]) - u_nxt = u_m1; - else - s_nxt = s_m1; - DOutput = cc; - RnWOut = 1'b0; // write - tmp_nxt[0] = 1'b0; - end - if (tmp[13]) // Then we're pushing for an IRQ, and LIC is supposed to be set. - rLIC = 1'b1; - if (tmp_nxt[7:0] == 8'H00) - begin - if (NextState == CPUSTATE_FETCH_I1) - begin - rAVMA = 1'b1; - rLIC = 1'b1; - end - else - rAVMA = 1'b0; - CpuState_nxt = NextState; - end - end - - CPUSTATE_PUL_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_PUL_DONTCARE2; - end - - CPUSTATE_PUL_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_PUL_ACTION; - end - - CPUSTATE_PUL_ACTION: - begin - rAVMA = 1'b1; - if (tmp[0]) // CC - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - cc_nxt = D[7:0]; - if (tmp[12] == 1'b1) // This pull is from an RTI, the E flag comes from the retrieved CC, and set the tmp_nxt accordingly, indicating what other registers to retrieve - begin - if (D[CC_E_BIT]) - tmp_nxt[7:0] = 8'HFE; // Retrieve all registers (ENTIRE) [CC is already retrieved] - else - tmp_nxt[7:0] = 8'H80; // Retrieve PC and CC [CC is already retrieved] - end - else - tmp_nxt[0] = 1'b0; - end - else if (tmp[1]) // A - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - a_nxt = D[7:0]; - tmp_nxt[1] = 1'b0; - end - else if (tmp[2]) // B - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - b_nxt = D[7:0]; - tmp_nxt[2] = 1'b0; - end - else if (tmp[3]) // DP - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - dp_nxt = D[7:0]; - tmp_nxt[3] = 1'b0; - end - else if (tmp[4] & (~tmp[15])) // X_HI - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - x_nxt[15:8] = D[7:0]; - tmp_nxt[15] = 1'b1; - end - else if (tmp[4] & tmp[15]) // X_LO - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - x_nxt[7:0] = D[7:0]; - tmp_nxt[4] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[5] & (~tmp[15])) // Y_HI - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - y_nxt[15:8] = D[7:0]; - tmp_nxt[15] = 1'b1; - end - else if (tmp[5] & tmp[15]) // Y_LO - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - y_nxt[7:0] = D[7:0]; - tmp_nxt[5] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[6] & (~tmp[15])) // U/S_HI - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - if (tmp[14]) - s_nxt[15:8] = D[7:0]; - else - u_nxt[15:8] = D[7:0]; - tmp_nxt[15] = 1'b1; - end - else if (tmp[6] & tmp[15]) // U/S_LO - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - if (tmp[14]) - s_nxt[7:0] = D[7:0]; - else - u_nxt[7:0] = D[7:0]; - tmp_nxt[6] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else if (tmp[7] & (~tmp[15])) // PC_HI - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - pc_nxt[15:8] = D[7:0]; - tmp_nxt[15] = 1'b1; - end - else if (tmp[7] & tmp[15]) // PC_LO - begin - addr_nxt = (tmp[14]) ? u : s; - if (tmp[14]) - u_nxt = u_p1; - else - s_nxt = s_p1; - pc_nxt[7:0] = D[7:0]; - tmp_nxt[7] = 1'b0; - tmp_nxt[15] = 1'b0; - end - else - begin - addr_nxt = (tmp[14]) ? u : s; - if (NextState == CPUSTATE_FETCH_I1) - begin - rAVMA = 1'b1; - rLIC = 1'b1; - end - else - rAVMA = 1'b0; - CpuState_nxt = NextState; - end - end - - CPUSTATE_NMI_START: - begin - NMIClear_nxt = 1'b1; - addr_nxt = pc; - // tmp stands as the bits to push to the stack - tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push - NextState_nxt = CPUSTATE_IRQ_DONTCARE2; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_IRQ_DONTCARE; - IntType_nxt = INTTYPE_NMI; - cc_nxt[CC_E_BIT] = 1'b1; - end - - CPUSTATE_IRQ_START: - begin - addr_nxt = pc; - tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push - NextState_nxt = CPUSTATE_IRQ_DONTCARE2; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_DONTCARE; - IntType_nxt = INTTYPE_IRQ; - cc_nxt[CC_E_BIT] = 1'b1; - end - - CPUSTATE_FIRQ_START: - begin - addr_nxt = pc; - tmp_nxt = 16'H2081; // Save to the S stack, PC, CC; set LIC on every push - NextState_nxt = CPUSTATE_IRQ_DONTCARE2; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_DONTCARE; - IntType_nxt = INTTYPE_FIRQ; - cc_nxt[CC_E_BIT] = 1'b0; - end - - CPUSTATE_SWI_START: - begin - addr_nxt = pc; - tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC - - NextState_nxt = CPUSTATE_IRQ_DONTCARE2; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_DONTCARE; - if (InstPage3) - IntType_nxt = INTTYPE_SWI3; - if (InstPage2) - IntType_nxt = INTTYPE_SWI2; - else - IntType_nxt = INTTYPE_SWI; - - cc_nxt[CC_E_BIT] = 1'b1; - end - - CPUSTATE_IRQ_DONTCARE: - begin - NMIClear_nxt = 1'b0; - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_PSH_ACTION; - end - - - CPUSTATE_IRQ_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; - rLIC = 1'b1; - end - - CPUSTATE_IRQ_VECTOR_HI: - begin - case (IntType) - INTTYPE_NMI: - begin - addr_nxt = `NMI_VECTOR; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_IRQ: - begin - addr_nxt = `IRQ_VECTOR; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_SWI: - begin - addr_nxt = `SWI_VECTOR; - end - INTTYPE_FIRQ: - begin - addr_nxt = `FIRQ_VECTOR; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_SWI2: - begin - addr_nxt = `SWI2_VECTOR; - end - INTTYPE_SWI3: - begin - addr_nxt = `SWI3_VECTOR; - end - default: // make the default an IRQ, even though it really should never happen - begin - addr_nxt = `IRQ_VECTOR; - BS_nxt = 1'b1; // ACK Interrupt - end - endcase - - pc_nxt[15:8] = D[7:0]; - rAVMA = 1'b1; - rBUSY = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_VECTOR_LO; - - - end - - CPUSTATE_IRQ_VECTOR_LO: - begin - case (IntType) - INTTYPE_NMI: - begin - addr_nxt = `NMI_VECTOR+16'H1; - cc_nxt[CC_I_BIT] = 1'b1; - cc_nxt[CC_F_BIT] = 1'b1; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_IRQ: - begin - addr_nxt = `IRQ_VECTOR+16'H1; - cc_nxt[CC_I_BIT] = 1'b1; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_SWI: - begin - addr_nxt = `SWI_VECTOR+16'H1; - cc_nxt[CC_F_BIT] = 1'b1; - cc_nxt[CC_I_BIT] = 1'b1; - rLIC = 1'b1; - end - INTTYPE_FIRQ: - begin - addr_nxt = `FIRQ_VECTOR+16'H1; - cc_nxt[CC_F_BIT] = 1'b1; - cc_nxt[CC_I_BIT] = 1'b1; - BS_nxt = 1'b1; // ACK Interrupt - end - INTTYPE_SWI2: - begin - addr_nxt = `SWI2_VECTOR+16'H1; - rLIC = 1'b1; - end - INTTYPE_SWI3: - begin - addr_nxt = `SWI3_VECTOR+16'H1; - rLIC = 1'b1; - end - default: - begin - end - endcase - - pc_nxt[7:0] = D[7:0]; - rAVMA = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_INT_DONTCARE; - end - - CPUSTATE_INT_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - rLIC = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_CC_DONTCARE: - begin - addr_nxt = pc; - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_TST_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_TST_DONTCARE2; - end - - CPUSTATE_TST_DONTCARE2: - begin - addr_nxt = 16'HFFFF; - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_DEBUG: - begin - addr_nxt = tmp; - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_16IMM_DONTCARE: - begin - addr_nxt = 16'HFFFF; - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_SYNC: - begin - addr_nxt = 16'HFFFF; - BA_nxt = 1'b1; - rLIC = 1'b1; - rAVMA = 1'b0; - - if (~(NMILatched & FIRQLatched & IRQLatched)) - begin - CpuState_nxt = CPUSTATE_SYNC_EXIT; - end - end - - CPUSTATE_SYNC_EXIT: - begin - addr_nxt = 16'HFFFF; - BA_nxt = 1'b1; - rLIC = 1'b1; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - - CPUSTATE_DMABREQ: - begin - rAVMA = 1'b0; - addr_nxt = 16'HFFFF; - BS_nxt = 1'b1; - BA_nxt = 1'b1; - rLIC = 1'b1; - tmp_nxt[3:0] = tmp[3:0] - 1'b1; - if ( (tmp[3:0] == 4'H0) | (DMABREQSample2) ) - begin - CpuState_nxt = CPUSTATE_DMABREQ_EXIT; - end - end - - CPUSTATE_DMABREQ_EXIT: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_HALTED: - begin - rAVMA = 1'b0; - addr_nxt = 16'HFFFF; - BS_nxt = 1'b1; - BA_nxt = 1'b1; - rLIC = 1'b1; - if (HALTSample2) - begin - CpuState_nxt = CPUSTATE_HALT_EXIT2; - end - end - - - CPUSTATE_HALT_EXIT2: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_FETCH_I1; - end - - CPUSTATE_STOP: - begin - addr_nxt = 16'HDEAD; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_STOP2; - end - - CPUSTATE_STOP2: - begin - addr_nxt = pc; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_STOP3; - end - - CPUSTATE_STOP3: - begin - addr_nxt = 16'H0000; //{Inst1, Inst2}; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_STOP; - end - - // The otherwise critically useful Figure 18 in the 6809 datasheet contains an error; - // it lists that CWAI has a tri-stated bus while it waits for an interrupt. - // That is not true. SYNC tristates the bus, as do things like /HALT and /DMABREQ. - // CWAI does not. It waits with /VMA cycles on the bus until an interrupt occurs. - // The implementation here fits with the 6809 Programming Manual and other Motorola - // sources, not with that typo in Figure 18. - CPUSTATE_CWAI: - begin - addr_nxt = pc; - cc_nxt = {1'b1, (cc[6:0] & Inst2[6:0])}; // Set E flag, AND CC with CWAI argument - tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC - - NextState_nxt = CPUSTATE_CWAI_POST; - rAVMA = 1'b0; - CpuState_nxt = CPUSTATE_CWAI_DONTCARE1; - end - - CPUSTATE_CWAI_DONTCARE1: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b1; - CpuState_nxt = CPUSTATE_PSH_ACTION; - end - - CPUSTATE_CWAI_POST: - begin - addr_nxt = 16'HFFFF; - rAVMA = 1'b0; - - CpuState_nxt = CPUSTATE_CWAI_POST; - - // Wait for an interrupt - if (NMILatched == 0) - begin - rAVMA = 1'b1; - IntType_nxt = INTTYPE_NMI; - cc_nxt[CC_F_BIT] = 1'b1; - cc_nxt[CC_I_BIT] = 1'b1; - CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; - end - else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0)) - begin - rAVMA = 1'b1; - cc_nxt[CC_F_BIT] = 1'b1; - cc_nxt[CC_I_BIT] = 1'b1; - IntType_nxt = INTTYPE_FIRQ; - CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; - end - else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0)) - begin - rAVMA = 1'b1; - cc_nxt[CC_I_BIT] = 1'b1; - IntType_nxt = INTTYPE_IRQ; - CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI; - end - end - - default: // Picky darned Verilog. - begin - CpuState_nxt = PostIllegalState; - end - - endcase -end - -endmodule - diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip b/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip index 67c0410c..0f1fb21f 100644 --- a/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip +++ b/Arcade_MiST/Konami Gyruss/rtl/custom/gyruss_custom.qip @@ -3,5 +3,3 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k083.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k501.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k502.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/k503.sv -set_global_assignment -name SYSTEMVERILOG_FILE rtl/custom/KONAMI-1/KONAMI1.sv -set_global_assignment -name VERILOG_FILE rtl/custom/KONAMI-1/mc6809isk.v diff --git a/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv index f49fe4a5..f8dff57a 100644 --- a/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv +++ b/Arcade_MiST/Konami Jackal/rtl/custom/k005885.sv @@ -4,7 +4,7 @@ // generator // Graphics logic based on the video section of the Green Beret core for // MiSTer by MiSTer-X -// Copyright (C) 2020, 2021 Ace +// Copyright (C) 2020, 2022 Ace // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -84,17 +84,20 @@ module k005885 //-10: Iron Horse bootleg (10 extra vertical lines resulting in slower VSync, altered screen centering, sprite layer is // offset vertically by 1 line, sprite limit significantly lower than normal) input [1:0] BTLG, - //Extra data outputs for graphics ROMs - output ATR4, //Tilemap attribute bit 4 - output ATR5, //Tilemap attribute bit 5 - + output reg ATR4, //Tilemap attribute bit 4 + output reg ATR5 //Tilemap attribute bit 5 + + `ifdef MISTER_HISCORE //MiSTer high score system I/O (to be used only with Iron Horse) - input [11:0] hs_address, - input [7:0] hs_data_in, - output [7:0] hs_data_out, - input hs_write, - input hs_access + , + input [11:0] hs_address, + input [7:0] hs_data_in, + output [7:0] hs_data_out, + input hs_write_enable, + input hs_access_read, + input hs_access_write + `endif ); //------------------------------------------------------- Signal outputs -------------------------------------------------------// @@ -109,18 +112,19 @@ assign NIOC = ~(~NXCS & (A[13:11] == 3'b001)); assign NRMW = 1; //Output bits 4 and 5 of tilemap attributes for graphics ROM addressing -assign ATR4 = tileram_attrib_D[4]; -assign ATR5 = tileram_attrib_D[5]; - +/* +assign ATR4 = tile_ctrl[2] ? tile_attrib_D[4] : tile0_attrib_D[4]; +assign ATR5 = tile_ctrl[2] ? tile_attrib_D[5] : tile0_attrib_D[5]; +*/ //Data output to CPU assign DBo = (ram_cs & ~NRD) ? ram_Dout: (zram0_cs & ~NRD) ? zram0_Dout: (zram1_cs & ~NRD) ? zram1_Dout: (zram2_cs & ~NRD) ? zram2_Dout: - (tile_attrib_cs & ~NRD) ? tileram_attrib_Dout: - (tile_cs & ~NRD) ? tileram_Dout: - (tile1_attrib_cs & ~NRD) ? tileram1_attrib_Dout: - (tile1_cs & ~NRD) ? tileram1_Dout: + (tile_attrib_cs & ~NRD) ? tile0_attrib_Dout: + (tile_cs & ~NRD) ? tile0_Dout: + (tile1_attrib_cs & ~NRD) ? tile1_attrib_Dout: + (tile1_cs & ~NRD) ? tile1_Dout: (spriteram_cs & ~NRD) ? spriteram_Dout: 8'hFF; @@ -131,12 +135,7 @@ reg [3:0] div = 4'd0; always_ff @(posedge CK49) begin div <= div + 4'd1; end -reg [2:0] n_div = 3'd0; -always_ff @(negedge CK49) begin - n_div <= n_div + 3'd1; -end wire cen_6m = !div[2:0]; -wire n_cen_6m = !n_div; wire cen_3m = !div; assign NCK2 = div[2]; assign H1O = div[3]; @@ -173,7 +172,6 @@ reg [8:0] v_cnt = 9'd0; //rolls over reg hblank = 0; reg vblank = 0; -reg vblank_irq_en = 0; reg frame_odd_even = 0; //Add an extra 10 lines to the vertical counter if a bootleg Iron Horse ROM set is loaded or remove 9 lines from the vertical //counter if a bootleg Jackal ROM set is loaded @@ -206,6 +204,12 @@ always_ff @(posedge CK49) begin vsync_start <= 9'd255; vsync_end <= 9'd262; end + else if(tile_ctrl[2]) begin + hsync_start <= HCTR[3] ? 9'd312 : 9'd320; + hsync_end <= HCTR[3] ? 9'd343 : 9'd351; + vsync_start <= 9'd254; + vsync_end <= 9'd261; + end else begin hsync_start <= HCTR[3] ? 9'd288 : 9'd296; hsync_end <= HCTR[3] ? 9'd319 : 9'd327; @@ -216,29 +220,31 @@ end always_ff @(posedge CK49) begin if(cen_6m) begin case(h_cnt) - 0: begin - vblank_irq_en <= 0; - h_cnt <= h_cnt + 9'd1; - end //HBlank ends two lines earlier than normal on bootleg Jackal PCBs - 11: begin + 10: begin if(BTLG == 2'b01) hblank <= 0; h_cnt <= h_cnt + 9'd1; end - 13: begin + 12: begin if(BTLG != 2'b01) hblank <= 0; h_cnt <= h_cnt + 9'd1; end //Shift the start of HBlank two lines earlier when bootleg Jackal ROMs are loaded - 251: begin - if(BTLG == 2'b01) + 250: begin + if(BTLG == 2'b01 && !tile_ctrl[2]) hblank <= 1; h_cnt <= h_cnt + 9'd1; end - 253: begin - if(BTLG != 2'b01) + 252: begin + if(BTLG != 2'b01 && !tile_ctrl[2]) + hblank <= 1; + h_cnt <= h_cnt + 9'd1; + end + //Shift the start of HBlank 40 lines later when using the wider 280x224 video mode + 292: begin + if(tile_ctrl[2]) hblank <= 1; h_cnt <= h_cnt + 9'd1; end @@ -251,7 +257,6 @@ always_ff @(posedge CK49) begin end 239: begin vblank <= 1; - vblank_irq_en <= 1; frame_odd_even <= ~frame_odd_even; v_cnt <= v_cnt + 9'd1; end @@ -278,43 +283,49 @@ assign NCSY = NHSY ^ NVSY; //------------------------------------------------------------- IRQs -----------------------------------------------------------// +//Edge detection for VBlank and vertical counter bits 4 and 5 for IRQ generation +reg old_vblank, old_vcnt4, old_vcnt5; +always_ff @(posedge CK49) begin + old_vcnt4 <= v_cnt[4]; + old_vcnt5 <= v_cnt[5]; + old_vblank <= vblank; +end + //IRQ (triggers every VBlank) reg vblank_irq = 1; -always_ff @(posedge CK49 or negedge NEXR) begin - if(!NEXR) +always_ff @(posedge CK49) begin + if(!NEXR || !irq_mask) vblank_irq <= 1; - else if(cen_6m) begin - if(!irq_mask) - vblank_irq <= 1; - else if(vblank_irq_en) - vblank_irq <= 0; - end + else if(!old_vblank && vblank) + vblank_irq <= 0; end assign NIRQ = vblank_irq; -//NMI (triggers every 64 scanlines starting from scanline 48) +//NMI (triggers on the falling edge of vertical counter bits 4 or 5 based on the state of tile control register bit 2) reg nmi = 1; -always_ff @(posedge CK49 or negedge NEXR) begin - if(!NEXR) +always_ff @(posedge CK49) begin + if(!NEXR || !nmi_mask) nmi <= 1; - else if(cen_3m) begin - if(!nmi_mask) - nmi <= 1; - else if((v_cnt[7:0] + 9'd16) % 9'd64 == 0) - nmi <= 0; + else begin + if(tile_ctrl[2]) begin + if(old_vcnt4 && !v_cnt[4]) + nmi <= 0; + end + else begin + if(old_vcnt5 && !v_cnt[5]) + nmi <= 0; + end end end assign NNMI = nmi; //FIRQ (triggers every second VBlank) reg firq = 1; -always_ff @(posedge CK49 or negedge NEXR) begin - if(!NEXR) +always_ff @(posedge CK49) begin + if(!NEXR || !firq_mask) firq <= 1; - else if(cen_3m) begin - if(!firq_mask) - firq <= 1; - else if(!frame_odd_even && v_cnt == 9'd239) + else begin + if(frame_odd_even && !old_vblank && vblank) firq <= 0; end end @@ -355,13 +366,9 @@ reg firq_mask = 0; reg flipscreen = 0; //Write to the appropriate register -always_ff @(posedge CK49, negedge NEXR) begin - if(!NEXR) begin - nmi_mask <= 1; - irq_mask <= 1; - firq_mask <= 1; - flipscreen <= 0; - end else if(cen_3m) begin +always_ff @(posedge CK49) begin + reg rightD, leftD, upD; + if(cen_3m) begin if(regs_cs && NRD) case(A[2:0]) 3'b000: scroll_y <= DBi; @@ -446,32 +453,32 @@ wire tile1_attrib_cs = ~NXCS & (A[13:10] == 4'b1010); wire tile1_cs = ~NXCS & (A[13:10] == 4'b1011); wire spriteram_cs = ~NXCS & (A[13:12] == 2'b11); -wire [7:0] tileram_attrib_Dout, tileram_Dout, tileram1_attrib_Dout, tileram1_Dout, spriteram_Dout; -wire [7:0] tileram_attrib_D, tileram_D, tileram1_attrib_D, tileram1_D, spriteram_D; +wire [7:0] tile0_attrib_Dout, tile0_Dout, tile1_attrib_Dout, tile1_Dout, spriteram_Dout; +wire [7:0] tile0_attrib_D, tile0_D, tile1_attrib_D, tile1_D, spriteram_D; //Tilemap layer 0 dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB0 ( .clock_a(CK49), .address_a(A[9:0]), .data_a(DBi), - .q_a(tileram_attrib_Dout), + .q_a(tile0_attrib_Dout), .wren_a(tile_attrib_cs & NRD), .clock_b(CK49), .address_b(vram_A), - .q_b(tileram_attrib_D) + .q_b(tile0_attrib_D) ); dpram_dc #(.widthad_a(10)) VRAM_TILECODE0 ( .clock_a(CK49), .address_a(A[9:0]), .data_a(DBi), - .q_a(tileram_Dout), + .q_a(tile0_Dout), .wren_a(tile_cs & NRD), .clock_b(CK49), .address_b(vram_A), - .q_b(tileram_D) + .q_b(tile0_D) ); //Tilemap layer 1 dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1 @@ -479,118 +486,208 @@ dpram_dc #(.widthad_a(10)) VRAM_TILEATTRIB1 .clock_a(CK49), .address_a(A[9:0]), .data_a(DBi), - .q_a(tileram1_attrib_Dout), + .q_a(tile1_attrib_Dout), .wren_a(tile1_attrib_cs & NRD), .clock_b(CK49), .address_b(vram_A), - .q_b(tileram1_attrib_D) + .q_b(tile1_attrib_D) ); dpram_dc #(.widthad_a(10)) VRAM_TILECODE1 ( .clock_a(CK49), .address_a(A[9:0]), .data_a(DBi), - .q_a(tileram1_Dout), + .q_a(tile1_Dout), .wren_a(tile1_cs & NRD), .clock_b(CK49), .address_b(vram_A), - .q_b(tileram1_D) + .q_b(tile1_D) ); + + +`ifndef MISTER_HISCORE +//Sprites +dpram_dc #(.widthad_a(12)) VRAM_SPR +( + .clock_a(CK49), + .address_a(A[11:0]), + .data_a(DBi), + .q_a(spriteram_Dout), + .wren_a(spriteram_cs & NRD), + + .clock_b(~CK49), + .address_b(spriteram_A), + .q_b(spriteram_D) +); +`else // Hiscore mux (this is only to be used with Iron Horse as its high scores are stored in sprite RAM) -wire [11:0] VRAM_SPR_AD = hs_access ? hs_address : A[11:0]; -wire [7:0] VRAM_SPR_DIN = hs_access ? hs_data_in : DBi; -wire VRAM_SPR_WE = hs_access ? hs_write : (spriteram_cs & NRD); -wire [7:0] VRAM_SPR_DOUT; - -assign hs_data_out = hs_access ? VRAM_SPR_DOUT : 8'h00; -assign spriteram_Dout = hs_access ? 8'h00 : VRAM_SPR_DOUT; - +// - Mirrored sprite RAM used to protect against corruption while retrieving highscore data +wire [11:0] VRAM_SPR_AD = hs_access_write ? hs_address : A[11:0]; +wire [7:0] VRAM_SPR_DIN = hs_access_write ? hs_data_in : DBi; +wire VRAM_SPR_WE = hs_access_write ? hs_write_enable : (spriteram_cs & NRD); //Sprites dpram_dc #(.widthad_a(12)) VRAM_SPR ( .clock_a(CK49), .address_a(VRAM_SPR_AD), .data_a(VRAM_SPR_DIN), - .q_a(VRAM_SPR_DOUT), + .q_a(spriteram_Dout), .wren_a(VRAM_SPR_WE), .clock_b(~CK49), .address_b(spriteram_A), .q_b(spriteram_D) ); +//Sprite RAM shadow for highscore read access +dpram_dc #(.widthad_a(12)) VRAM_SPR_SHADOW +( + .clock_a(CK49), + .address_a(VRAM_SPR_AD), + .data_a(VRAM_SPR_DIN), + .wren_a(VRAM_SPR_WE), + + .clock_b(CK49), + .address_b(hs_address), + .q_b(hs_data_out) +); +`endif //-------------------------------------------------------- Tilemap layer -------------------------------------------------------// -//TODO: The current implementation only handles one of the 005885's two tilemap layers - add logic to handle both layers +//The Konami 005885 contains two tilemap layers. Finalizer - Super Transformation uses the second layer to draw the HUD at the +//top of the screen. Latch tilemap data out of bank 0 or bank 1 of the tilemap section of VRAM based on how far the game has +//drawn the tilemap layer when tile control bit 2 is set, otherwise grab tilemap data from bank 0 of the tilemap section of VRAM +//at all times + +//Loosely based on TimePilot 84's schematics +reg [7:0] tile_attrib_D, tile_D; +wire tile1_en = flipscreen ? h_cnt > 9'd243 : h_cnt < 9'd40; +wire [5:0] tile_hoffset = tile_ctrl[2] ? (~tile1_en ? (flipscreen ? 6'd4 : 6'd32) : 6'd0) : (flipscreen ? 6'd4 : 6'd0); + +always_ff @(posedge CK49) begin + if (cen_6m) begin + if(h_cnt[1:0] == 2'b01) begin // posedge of h_cnt[1] + if(tile_ctrl[2] && tile1_en) begin + tile_D <= tile1_D; + tile_attrib_D <= tile1_attrib_D; + end + else begin + tile_D <= tile0_D; + tile_attrib_D <= tile0_attrib_D; + end + end + end +end //XOR horizontal and vertical counter bits with flipscreen bit wire [8:0] hcnt_x = h_cnt ^ {9{flipscreen}}; wire [8:0] vcnt_x = v_cnt ^ {9{flipscreen}}; //Generate tilemap position by summing the XORed counter bits with their respective scroll registers or ZRAM bank 0 based on -//whether row scroll or column scroll is enabled -wire [8:0] row_scroll = (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x}; +//whether row scroll or column scroll is enabled (do not allow scrolling when drawing Finalizer - Super Transformation's HUD +//and offset the tilemap layer with this game) +wire [8:0] row_scroll = (tile_ctrl[2] & !flipscreen & tile1_en) ? 9'd0: + (tile_ctrl[2] & flipscreen & tile1_en) ? 9'd28: + (scroll_ctrl[3:1] == 3'b101) ? zram0_D : {scroll_ctrl[0], scroll_x}; wire [8:0] col_scroll = (scroll_ctrl[3:1] == 3'b011) ? zram0_D : scroll_y; -wire [8:0] tilemap_hpos = hcnt_x + row_scroll; +wire [7:2] tilemap_hpos = hcnt_x[7:2] + row_scroll[7:2] - tile_hoffset[5:2] + {!tile_ctrl[2] & !flipscreen, 1'b0}/* synthesis keep */; wire [8:0] tilemap_vpos = vcnt_x + col_scroll; //Address output to tilemap section of VRAM wire [9:0] vram_A = {tilemap_vpos[7:3], tilemap_hpos[7:3]}; //Assign tile index as bits 5 and 6 of tilemap attributes and the tile code -wire [9:0] tile_index = {tileram_attrib_D[7:6], tileram_D}; +wire [9:0] tile_index = {tile_attrib_D[7:6], tile_D} /* synthesis keep */; //XOR tile H/V flip bits with the flipscreen bit -wire tile_hflip = tileram_attrib_D[4]; -wire tile_vflip = tileram_attrib_D[5]; - -//Address output to graphics ROMs -assign R = {tile_ctrl[1:0], tile_index, (tilemap_vpos[2:0] ^ {3{tile_vflip}}), (tilemap_hpos[2] ^ tile_hflip)}; +wire tile_hflip = tile_attrib_D[4]; +wire tile_vflip = tile_attrib_D[5]; //Latch tile data from graphics ROMs, tile colors and tile H flip bit from VRAM on the falling edge of tilemap horizontal position -//bit 1 +//bit 1 (direct for Finalizer) reg [15:0] RD_lat = 16'd0; -reg [3:0] tile_color = 4'd0; -reg tile_hflip_lat = 0; -reg old_tilehpos1; +reg [3:0] tile_color, tile_color_r; +reg tile_hflip_lat, tile_hflip_lat_r; +reg tile_vflip_lat; +reg hpos2_lat; +reg [2:0] yscroll_lat; +reg [1:0] xscroll_lat, xscroll_lat_r, xscroll_lat_rr; + always_ff @(posedge CK49) begin - old_tilehpos1 <= tilemap_hpos[1]; - if(old_tilehpos1 && !tilemap_hpos[1]) begin - tile_color <= tileram_attrib_D[3:0]; - RD_lat <= flipscreen ? {RDL, RDU} : {RDU, RDL}; - tile_hflip_lat <= tileram_attrib_D[4]; + if (cen_6m) begin + if(h_cnt[1:0] == 2'b11) begin // negedge of h_cnt[1] + hpos2_lat <= tilemap_hpos[2]; + xscroll_lat <= row_scroll[1:0]; + xscroll_lat_r <= xscroll_lat; + yscroll_lat <= tilemap_vpos[2:0]; + tile_color <= tile_attrib_D[3:0]; + tile_color_r <= tile_color; + tile_hflip_lat <= tile_hflip; + tile_hflip_lat_r <= tile_hflip_lat; + tile_vflip_lat <= tile_vflip; + //Address output to graphics ROMs + R[15:4] <= {tile_ctrl[1:0], tile_index}; + //Latch graphics ROM output + RD_lat <= {RDU, RDL}; + //Output bits 4 and 5 of tilemap attributes for graphics ROM addressing + ATR4 <= tile_attrib_D[4]; + ATR5 <= tile_attrib_D[5]; + end + xscroll_lat_rr <= xscroll_lat_r; end end +assign R[3:0] = {yscroll_lat[2:0] ^ {3{tile_vflip_lat}}, hpos2_lat ^ tile_hflip_lat}; -//Multiplex graphics ROM data down from 16 bits to 8 using bit 1 of the horizontal position -wire [7:0] RD = (tilemap_hpos[1] ^ tile_hflip_lat) ? RD_lat[7:0] : RD_lat[15:8]; - -//Further multiplex graphics ROM data down from 8 bits to 4 using bit 0 of the horizontal position -wire [3:0] tile_pixel = (tilemap_hpos[0] ^ tile_hflip_lat) ? RD[3:0] : RD[7:4]; - -//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register -wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5]; -reg tilemap_en = 0; -always_ff @(posedge CK49) begin - if(n_cen_6m) begin - tilemap_en <= tile_sel; - end +reg [3:0] tile_pixel /* synthesis keep */; +always @(*) begin + case (hcnt_x[1:0] ^ {2{tile_hflip_lat_r}}) + 2'b00: tile_pixel = RD_lat[15:12]; + 2'b01: tile_pixel = RD_lat[11: 8]; + 2'b10: tile_pixel = RD_lat[ 7: 4]; + 2'b11: tile_pixel = RD_lat[ 3: 0]; + default: ; + endcase end //Address output to tilemap LUT PROM -assign VCF = tile_color; +assign VCF = tile_color_r; assign VCB = tile_pixel; -//Shift the tilemap layer left by two lines when the screen is flipped -reg [7:0] tilemap_shift; +// latch pixel data, and generate 4 shifted pixel positions for fine scroll +reg [3:0] pix0, pix1, pix2, pix3; always_ff @(posedge CK49) begin - if(cen_6m) - tilemap_shift <= {VCD, tilemap_shift[7:4]}; + if (cen_6m) begin + pix0 <= VCD; + pix1 <= pix0; + pix2 <= pix1; + pix3 <= pix2; + end end -wire [3:0] tilemap_D = flipscreen ? tilemap_shift[3:0] : VCD; + +// select the appropriate shifted pixel according to scroll value +reg [3:0] tilemap_D /* synthesis keep */; +wire hud_left = !flipscreen && tile_ctrl[2] && h_cnt < 52; +wire hud_right = flipscreen && tile_ctrl[2] && h_cnt > 252; +always @(*) begin + case ({2{flipscreen}} ^ xscroll_lat_rr) + 2'b00: tilemap_D = pix3; + 2'b01: tilemap_D = pix2; + 2'b10: tilemap_D = pix1; + 2'b11: tilemap_D = pix0; + default: ; + endcase + if (hud_left ) tilemap_D = pix3; + if (hud_right) tilemap_D = pix0; +end + +//Retrieve tilemap select bit from bit 1 of the tile control register XORed with bit 5 of the same register +wire tile_sel = tile_ctrl[1] ^ tile_ctrl[5]; +//Prioritize the tilemap layer when using the extended 280x224 mode for Finalizer in the score display area, otherwise give priority +//to sprites +wire tilemap_en = tile_ctrl[2] ? (hud_left | hud_right) : tile_sel; //-------------------------------------------------------- Sprite layer --------------------------------------------------------// @@ -619,18 +716,25 @@ end //Sprite state machine reg [8:0] sprite_index; reg [2:0] sprite_offset; -reg [7:0] sprite_attrib0, sprite_attrib1, sprite_attrib2, sprite_attrib3, sprite_attrib4; reg [2:0] sprite_fsm_state; +reg [11:0] sprite_code; +reg [8:0] sprite_limit; +reg [8:0] sprite_x; +reg [7:0] sprite_y; reg [5:0] sprite_width; -//Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit -//to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of -//5, otherwise) -wire [8:0] sprite_limit = (BTLG == 2'b10) ? 9'd155 : 9'd485; +reg [3:0] sprite_color; +reg [2:0] sprite_size; +reg sprite_hflip, sprite_vflip, sprite_x8_sel, sprite_x8_vram; +wire [8:0] sprite_fsm_reset = tile_ctrl[2] ? 9'd40 : 9'd0; always_ff @(posedge CK49) begin + //Bootleg Iron Horse PCBs have a lower-than-normal sprite limit causing noticeable sprite flickering - reduce the sprite limit + //to 32 sprites (0 - 155 in increments of 5) if one such ROM set is loaded (render 96 sprites at once, 0 - 485 in increments of + //5, otherwise) + sprite_limit <= (BTLG == 2'b10) ? 9'd155 : 9'd485; //Reset the sprite state machine whenever the sprite horizontal postion, and in turn the horziontal counter, returns to 0 //Also hold the sprite state machine in this initial state for the first line while drawing sprites for bootleg Iron Horse //ROM sets to prevent graphical garbage from occurring on the top-most line - if(sprite_hpos == 9'd0 || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin + if(sprite_hpos == sprite_fsm_reset || (BTLG == 2'b10 && (!flipscreen && sprite_vpos <= 9'd80) || (flipscreen && sprite_vpos >= 9'd304))) begin sprite_width <= 0; sprite_index <= 0; sprite_offset <= 3'd4; @@ -640,25 +744,45 @@ always_ff @(posedge CK49) begin case(sprite_fsm_state) 0: /* empty */ ; 1: begin + //If the sprite limit is reached, hold the state machine in an empty state, otherwise latch the sprite H/V flip + //bits, sprite size, bit 8 of the sprite X position and its select bit if(sprite_index > sprite_limit) sprite_fsm_state <= 0; else begin - sprite_attrib4 <= spriteram_D; + sprite_vflip <= spriteram_D[6] ^ ~flipscreen; + sprite_hflip <= spriteram_D[5] ^ flipscreen; + sprite_size <= spriteram_D[4:2]; + sprite_x8_sel <= spriteram_D[1]; + sprite_x8_vram <= spriteram_D[0]; sprite_offset <= 3'd3; sprite_fsm_state <= sprite_fsm_state + 3'd1; end end 2: begin - sprite_attrib3 <= spriteram_D; + //Latch sprite X position and set the 9th bit as either the one latched previously from VRAM or the AND of position + //bits [7:3] based on the state of the select bit + if(sprite_x8_sel) + sprite_x[8] <= sprite_x8_vram ^ flipscreen; + else + sprite_x[8] <= (&spriteram_D[7:3]) ^ flipscreen; + sprite_x[7:0] <= spriteram_D ^ {8{flipscreen}}; sprite_offset <= 3'd2; sprite_fsm_state <= sprite_fsm_state + 3'd1; end 3: begin - //Skip the current sprite if it's inactive, otherwise obtain the sprite Y attribute and continue - //scanning out the rest of the sprite attributes + //Latch sprite Y position + sprite_y <= spriteram_D; + sprite_offset <= 3'd1; + sprite_fsm_state <= sprite_fsm_state + 3'd1; + end + 4: begin + //Skip the current sprite if it's inactive, otherwise latch sprite color and the upper/lower 2 bits of the sprite + //code, and continue scanning out the rest of the sprite attributes if(sprite_active) begin - sprite_attrib2 <= spriteram_D; - sprite_offset <= 3'd1; + sprite_color <= spriteram_D[7:4]; + sprite_code[1:0] <= spriteram_D[3:2]; + sprite_code[11:10] <= spriteram_D[1:0]; + sprite_offset <= 3'd0; sprite_fsm_state <= sprite_fsm_state + 3'd1; end else begin @@ -667,13 +791,9 @@ always_ff @(posedge CK49) begin sprite_fsm_state <= 3'd1; end end - 4: begin - sprite_attrib1 <= spriteram_D; - sprite_offset <= 3'd0; - sprite_fsm_state <= sprite_fsm_state + 3'd1; - end 5: begin - sprite_attrib0 <= spriteram_D; + //Latch bits [9:2] of the sprite code and set up the sprite width based on the sprite size + sprite_code[9:2] <= spriteram_D; sprite_offset <= 3'd4; sprite_index <= sprite_index + 9'd5; case(sprite_size) @@ -681,7 +801,6 @@ always_ff @(posedge CK49) begin 3'b001: sprite_width <= 6'b110000 + (BTLG == 2'b01 && flipscreen); 3'b010: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); 3'b011: sprite_width <= 6'b111000 + (BTLG == 2'b01 && flipscreen); - 3'b100: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen); default: sprite_width <= 6'b100000 + (BTLG == 2'b01 && flipscreen); endcase sprite_fsm_state <= sprite_fsm_state + 3'd1; @@ -705,36 +824,6 @@ always_ff @(posedge CK49) begin endcase end -//Obtain sprite X position from sprite attribute byte 3 - append a 9th bit based on the state of bit 1 sprite attribute byte 4, -//bit 0 of sprite attribute byte 4 if high or the AND of the upper 5 bits of the horizontal position if low -reg sprite_x8; -always_ff @(posedge CK49) begin - if(sprite_attrib4[1]) - sprite_x8 <= sprite_attrib4[0]; - else - sprite_x8 <= &sprite_attrib3[7:3]; -end -wire [8:0] sprite_x = {sprite_x8 ^ flipscreen, sprite_attrib3 ^ {8{flipscreen}}}; - -//If the sprite state machine is in state 3, obtain sprite Y position directly from sprite RAM, otherwise obtain it from -//sprite attribute byte 2 -wire [7:0] sprite_y = (sprite_fsm_state == 3'd3) ? spriteram_D : sprite_attrib2; - -//Sprite flip attributes are stored in bits 5 (horizontal) and 6 (vertical) of sprite attribute byte 4 -//Also XOR these attributes with the flipscreen bit (XOR with the inverse for vertical flip) -wire sprite_hflip = sprite_attrib4[5] ^ flipscreen; -wire sprite_vflip = sprite_attrib4[6] ^ ~flipscreen; - -//Sprite code is sprite attribute byte 0 sandwiched between bits 1 and 0 and bits 3 and 2 of sprite attribute byte 1 -wire [11:0] sprite_code = {sprite_attrib1[1:0], sprite_attrib0, sprite_attrib1[3:2]}; - -//Sprite color is the upper 4 bits of sprite attribute byte 1 -wire [3:0] sprite_color = sprite_attrib1[7:4]; - -//The 005885 supports 5 different sprite sizes: 8x8, 8x16, 16x8, 16x16 and 32x32. Retrieve this attribute from bits [4:2] of -//sprite attribute byte 4 -wire [2:0] sprite_size = sprite_attrib4[4:2]; - //Adjust sprite code based on sprite size wire [11:0] sprite_code_sized = sprite_size == 3'b000 ? {sprite_code[11:2], ly[3], lx[3]}: //16x16 sprite_size == 3'b001 ? {sprite_code[11:1], lx[3]}: //16x8 @@ -780,6 +869,7 @@ reg sprite_bank = 0; reg old_vsync; //Normally, the 005885 latches the sprite bank from bit 3 of the tile control register on the rising edge of VSync, though this causes //jerky scrolling with sprites for bootleg Jackal ROM sets - bypass this latch if such ROM sets are loaded +//Finalizer - Super Transformation only reads sprite information from the lower sprite bank always_ff @(posedge CK49) begin old_vsync <= NVSY; if(!NEXR) @@ -837,7 +927,7 @@ reg [9:0] radr0 = 10'd0; reg [9:0] radr1 = 10'd1; always_ff @(posedge CK49) begin if(cen_6m) - radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : sprite_hpos}; + radr0 <= {sprite_lbuff_bank, flipscreen ? sprite_hpos - 9'd225 : tile_ctrl[2] ? sprite_hpos - 9'd40 : sprite_hpos}; end //Sprite line buffer diff --git a/Arcade_MiST/Konami TimePilot84/rtl/TimePilot84_CPU.sv b/Arcade_MiST/Konami TimePilot84/rtl/TimePilot84_CPU.sv index 4c397bdf..f5b30bf7 100644 --- a/Arcade_MiST/Konami TimePilot84/rtl/TimePilot84_CPU.sv +++ b/Arcade_MiST/Konami TimePilot84/rtl/TimePilot84_CPU.sv @@ -140,11 +140,12 @@ end //Konami 082 custom chip - responsible for all video timings wire vblk, h1, h2, h4, h8, h16, h32, h64, h128, n_h256, v1, v2, v4, v8, v16, v32, v64, v128; -wire h1_en, h2_en, h4_en, h8_en, h16_en, h32_en, h64_en, h128_en, n_h256_en; +wire n_h256_en; k082 u6A ( + .reset(1'b1), .clk(clk_49m), - .clk_en(pixel_clk_en), + .cen(pixel_clk_en), .n_vsync(video_vsync), .sync(video_csync), .n_hsync(video_hsync), @@ -160,15 +161,6 @@ k082 u6A .h64(h64), .h128(h128), .n_h256(n_h256), - - .h1_en(h1_en), - .h2_en(h2_en), - .h4_en(h4_en), - .h8_en(h8_en), - .h16_en(h16_en), - .h32_en(h32_en), - .h64_en(h64_en), - .h128_en(h128_en), .n_h256_en(n_h256_en), .v1(v1), diff --git a/Arcade_MiST/Konami TimePilot84/rtl/custom/k082.sv b/Arcade_MiST/Konami TimePilot84/rtl/custom/k082.sv index 169a8ad8..caf95491 100644 --- a/Arcade_MiST/Konami TimePilot84/rtl/custom/k082.sv +++ b/Arcade_MiST/Konami TimePilot84/rtl/custom/k082.sv @@ -2,7 +2,7 @@ // // SystemVerilog implementation of the Konami 082 custom chip, used by // several Konami arcade PCBs to generate video timings -// Copyright (C) 2020 Ace +// Copyright (C) 2020, 2021 Ace // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -27,7 +27,7 @@ //Chip pinout: /* _____________ _| |_ -VCC |_|1 28|_| VCC +reset |_|1 28|_| VCC _| |_ h1 |_|2 27|_| GND _| |_ @@ -56,60 +56,94 @@ clk |_|13 16|_| vblk GND |_|14 15|_| n_vblk |_____________| -Note: Pins 1, 12 and 27 may control other features of the 082 - these, if any, have not +Note: Pins 12 and 27 may control other features of the 082 - these, if any, have not been modelled yet. */ module k082 ( - input clk, - input clk_en, - output n_vsync, sync, - output n_hsync, //Not exposed on the original chip - output reg vblk = 1, - output n_vblk, - output h1, h2, h4, h8, h16, h32, h64, h128, h256, n_h256, - output v1, v2, v4, v8, v16, v32, v64, v128, - output h1_en, h2_en, h4_en, h8_en, h16_en, h32_en, h64_en, h128_en, h256_en, n_h256_en + input reset, //Active low + input clk, + input cen, //Set to 1 if using this code to replace a real 082 + input [3:0] h_center, v_center, //These inputs are additions for screen centering and don't exist on the actual 082 + output n_vsync, sync, + output n_hsync, //Not exposed on the original chip + output reg vblk = 1, + output n_vblk, + output reg vblk_irq_en = 0, //This is an extra output not present on the real 082 to signal when to + //trigger a VBlank IRQ (signal is active high) + output h1, h2, h4, h8, h16, h32, h64, h128, h256, n_h256, n_h256_en, + output v1, v2, v4, v8, v16, v32, v64, v128 ); +//The horizontal and vertical counters are 9 bits wide - delcare them here reg [8:0] h_cnt = 9'd0; reg [8:0] v_cnt = 9'd0; -always_ff @(posedge clk) if (clk_en) begin - h_cnt <= h_cnt + 9'd1; - case(h_cnt) - 48: begin - v_cnt <= v_cnt + 9'd1; - end - 176: begin - case(v_cnt) - 16: begin - vblk <= 0; - v_cnt <= v_cnt + 9'd1; - end - 271: begin - vblk <= 0; - v_cnt <= v_cnt + 9'd1; - end - 495: begin - vblk <= 1; - v_cnt <= v_cnt + 9'd1; - end - 511: v_cnt <= 9'd248; - default: v_cnt <= v_cnt + 9'd1; - endcase - end - 511: h_cnt <= 9'd128; - default: ; - endcase +//Define the range of values the vertical counter will count between based on the additional vertical center signal +//Shift the screen up by 1 line when horizontal centering shifts the screen left +wire [8:0] vcnt_start = 9'd248 - v_center; +wire [8:0] vcnt_end = 9'd511 - v_center; + +//The horizontal and vertical counters behave as follows at every rising edge of the pixel clock: +//-Start at 0, then count to 511 (both counters increment by 1 when the horizontal counter is set to 48) +//-Horizontal counter resets to 128 for a total of 383 horizontal lines +//-Vertical counter resets to 248 for a total of 263 vertical lines (adjustable with added vertical center signal) +//-Vertical counter increments when the horizontal counter equals 176 +//-VBlank is active when the horizontal counter is between 495 - 511 and 248 - 270 +//Model this behavior here +always_ff @(posedge clk or negedge reset) begin + if(!reset) begin + h_cnt <= 9'd0; + v_cnt <= 9'd0; + end + else if(cen) begin + case(h_cnt) + 48: begin + v_cnt <= v_cnt + 9'd1; + h_cnt <= h_cnt + 9'd1; + end + 176: begin + h_cnt <= h_cnt + 9'd1; + case(v_cnt) + 16: begin + vblk <= 0; + v_cnt <= v_cnt + 9'd1; + end + 271: begin + vblk <= 0; + v_cnt <= v_cnt + 9'd1; + end + 495: begin + vblk <= 1; + vblk_irq_en <= 1; + v_cnt <= v_cnt + 9'd1; + end + vcnt_end: v_cnt <= vcnt_start; + default: v_cnt <= v_cnt + 9'd1; + endcase + end + 177: begin + vblk_irq_en <= 0; + h_cnt <= h_cnt + 9'd1; + end + 511: h_cnt <= 9'd128; + default: h_cnt <= h_cnt + 9'd1; + endcase + end end +//The Konami 082 has both an active low VBlank and an active high VBlank - generate the active low VBlank by inverting +//the active high VBlank generated in the previous sequential block assign n_vblk = ~vblk; -assign n_hsync = ~(h_cnt > 175 && h_cnt < 208); -assign n_vsync = v_cnt[8]; + +//Generate active low HSync, VSync and composite sync +assign n_hsync = h_center[3] ? ~(h_cnt > (182 - h_center[2:0]) && h_cnt < (215 - h_center[2:0])): + ~(h_cnt > (175 - h_center[2:0]) && h_cnt < (208 - h_center[2:0])); +assign n_vsync = h_center[3] ? ~(v_cnt >= vcnt_start + 9'd1 && v_cnt <= vcnt_start + 9'd9) : ~(v_cnt >= vcnt_start && v_cnt <= vcnt_start + 9'd8); assign sync = n_hsync ^ n_vsync; +//Assign the individual horizontal counter bits to their respective outputs (also invert bit 8 of the horizontal counter for H256) assign h1 = h_cnt[0]; assign h2 = h_cnt[1]; assign h4 = h_cnt[2]; @@ -120,18 +154,9 @@ assign h64 = h_cnt[6]; assign h128 = h_cnt[7]; assign h256 = ~h_cnt[8]; assign n_h256 = h_cnt[8]; - -assign h1_en = !h_cnt[0]; -assign h2_en = h_cnt[1:0] == 2'b01; -assign h4_en = h_cnt[2:0] == 3'b011; -assign h8_en = h_cnt[3:0] == 4'b0111; -assign h16_en = h_cnt[4:0] == 5'b01111; -assign h32_en = h_cnt[5:0] == 6'b011111; -assign h64_en = h_cnt[6:0] == 7'b0111111; -assign h128_en = h_cnt[7:0] == 8'b01111111; -assign h256_en = h_cnt[8:0] == 9'b111111111; assign n_h256_en = h_cnt[8:0] == 9'b011111111; +//Assign the individual vertical counter bits to their respective outputs assign v1 = v_cnt[0]; assign v2 = v_cnt[1]; assign v4 = v_cnt[2];