mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-03-04 18:33:50 +00:00
Konami Iron Horse
This commit is contained in:
31
Arcade_MiST/Konami Iron Horse/IronHors.qpf
Normal file
31
Arcade_MiST/Konami Iron Horse/IronHors.qpf
Normal file
@@ -0,0 +1,31 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Copyright (C) 1991-2013 Altera Corporation
|
||||
# Your use of Altera Corporation's design tools, logic functions
|
||||
# and other software and tools, and its AMPP partner logic
|
||||
# functions, and any output files from any of the foregoing
|
||||
# (including device programming or simulation files), and any
|
||||
# associated documentation or information are expressly subject
|
||||
# to the terms and conditions of the Altera Program License
|
||||
# Subscription Agreement, Altera MegaCore Function License
|
||||
# Agreement, or other applicable license agreement, including,
|
||||
# without limitation, that your use is for the sole purpose of
|
||||
# programming logic devices manufactured by Altera and sold by
|
||||
# Altera or its authorized distributors. Please refer to the
|
||||
# applicable agreement for further details.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus II 64-Bit
|
||||
# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
|
||||
# Date created = 00:21:03 December 03, 2019
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "13.1"
|
||||
DATE = "00:21:03 December 03, 2019"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "IronHors"
|
||||
|
||||
257
Arcade_MiST/Konami Iron Horse/IronHors.qsf
Normal file
257
Arcade_MiST/Konami Iron Horse/IronHors.qsf
Normal file
@@ -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=<None>"
|
||||
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
|
||||
134
Arcade_MiST/Konami Iron Horse/IronHors.sdc
Normal file
134
Arcade_MiST/Konami Iron Horse/IronHors.sdc
Normal file
@@ -0,0 +1,134 @@
|
||||
## Generated SDC file "vectrex_MiST.out.sdc"
|
||||
|
||||
## Copyright (C) 1991-2013 Altera Corporation
|
||||
## Your use of Altera Corporation's design tools, logic functions
|
||||
## and other software and tools, and its AMPP partner logic
|
||||
## functions, and any output files from any of the foregoing
|
||||
## (including device programming or simulation files), and any
|
||||
## associated documentation or information are expressly subject
|
||||
## to the terms and conditions of the Altera Program License
|
||||
## Subscription Agreement, Altera MegaCore Function License
|
||||
## Agreement, or other applicable license agreement, including,
|
||||
## without limitation, that your use is for the sole purpose of
|
||||
## programming logic devices manufactured by Altera and sold by
|
||||
## Altera or its authorized distributors. Please refer to the
|
||||
## applicable agreement for further details.
|
||||
|
||||
|
||||
## VENDOR "Altera"
|
||||
## PROGRAM "Quartus II"
|
||||
## VERSION "Version 13.1.0 Build 162 10/23/2013 SJ Web Edition"
|
||||
|
||||
## DATE "Sun Jun 24 12:53:00 2018"
|
||||
|
||||
##
|
||||
## DEVICE "EP3C25E144C8"
|
||||
##
|
||||
|
||||
# Clock constraints
|
||||
|
||||
# Automatically constrain PLL and other generated clocks
|
||||
derive_pll_clocks -create_base_clocks
|
||||
|
||||
# Automatically calculate clock uncertainty to jitter and other effects.
|
||||
derive_clock_uncertainty
|
||||
|
||||
# tsu/th constraints
|
||||
|
||||
# tco constraints
|
||||
|
||||
# tpd constraints
|
||||
|
||||
#**************************************************************
|
||||
# Time Information
|
||||
#**************************************************************
|
||||
|
||||
set_time_format -unit ns -decimal_places 3
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Create Clock
|
||||
#**************************************************************
|
||||
|
||||
create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}]
|
||||
|
||||
set sdram_clk "pll|altpll_component|auto_generated|pll1|clk[0]"
|
||||
set sys_clk "pll|altpll_component|auto_generated|pll1|clk[1]"
|
||||
#**************************************************************
|
||||
# Create Generated Clock
|
||||
#**************************************************************
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Latency
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Uncertainty
|
||||
#**************************************************************
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Delay
|
||||
#**************************************************************
|
||||
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {CLOCK_27}] 1.000 [get_ports {CLOCK_27}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {CONF_DATA0}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DI}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SCK}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS2}]
|
||||
set_input_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_SS3}]
|
||||
|
||||
set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 6.6 [get_ports SDRAM_DQ[*]]
|
||||
set_input_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min 3.5 [get_ports SDRAM_DQ[*]]
|
||||
|
||||
#**************************************************************
|
||||
# Set Output Delay
|
||||
#**************************************************************
|
||||
|
||||
set_output_delay -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_L}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {AUDIO_R}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {LED}]
|
||||
set_output_delay -clock [get_clocks $sys_clk] 1.000 [get_ports {VGA_*}]
|
||||
|
||||
set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
set_output_delay -clock [get_clocks $sdram_clk] -reference_pin [get_ports {SDRAM_CLK}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Groups
|
||||
#**************************************************************
|
||||
|
||||
set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll|altpll_component|auto_generated|pll1|clk[*]}]
|
||||
|
||||
#**************************************************************
|
||||
# Set False Path
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Multicycle Path
|
||||
#**************************************************************
|
||||
|
||||
set_multicycle_path -to {VGA_*[*]} -setup 2
|
||||
set_multicycle_path -to {VGA_*[*]} -hold 1
|
||||
|
||||
#**************************************************************
|
||||
# Set Maximum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Minimum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Transition
|
||||
#**************************************************************
|
||||
|
||||
11
Arcade_MiST/Konami Iron Horse/README.md
Normal file
11
Arcade_MiST/Konami Iron Horse/README.md
Normal file
@@ -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/
|
||||
84
Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra
Normal file
84
Arcade_MiST/Konami Iron Horse/meta/Iron Horse (Ver. K).mra
Normal file
@@ -0,0 +1,84 @@
|
||||
<misterromdescription>
|
||||
<name>Iron Horse</name>
|
||||
<region>World</region>
|
||||
<homebrew>no</homebrew>
|
||||
<bootleg>no</bootleg>
|
||||
<version>Version K</version>
|
||||
<alternative></alternative>
|
||||
<platform></platform>
|
||||
<series></series>
|
||||
<year>1986</year>
|
||||
<manufacturer>Konami</manufacturer>
|
||||
<category>Platformer</category>
|
||||
|
||||
<setname>ironhors</setname>
|
||||
<parent>ironhors</parent>
|
||||
<mameversion>0224</mameversion>
|
||||
<rbf>IronHors</rbf>
|
||||
<about author="Ace" twitter="@Ace9921Tweets"></about>
|
||||
|
||||
<resolution>15kHz</resolution>
|
||||
<rotation>no</rotation>
|
||||
<flip>no</flip>
|
||||
|
||||
<players>2 (alternating)</players>
|
||||
<joystick>8-way</joystick>
|
||||
<special_controls></special_controls>
|
||||
<num_buttons>3</num_buttons>
|
||||
<buttons default="Y,B,A,Start,R,Select,L" names="Power,Attack,Crouch,Start P1,Coin,Start P2,Pause"></buttons>
|
||||
|
||||
<switches default="00,45,00" base="8" page_id="1" page_name="Switches">
|
||||
<dip bits="0,3" name="Credits A" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/7cr,1c/6cr,2c/1cr,2c/3cr,3c/1cr,2c/5cr,3c/2cr,3c/4cr,4c/3cr,4c/1cr,Free Play"/>
|
||||
<dip bits="4,7" name="Credits B" ids="1c/1cr,1c/2cr,1c/3cr,1c/4cr,1c/5cr,1c/6cr,1c/7cr,2c/1cr,2c/3cr,2c/5cr,3c/1cr,3c/2cr,3c/4cr,4c/1cr,4c/3cr,Free Play"/>
|
||||
<dip bits="8,9" name="Lives" ids="2,3,5,7"/>
|
||||
<dip bits="10" name="Cabinet Type" ids="Cocktail,Upright"/>
|
||||
<dip bits="11,12" name="Bonus" ids="30K/70K+,40K/80K+,40K only,50K only"/>
|
||||
<dip bits="13,14" name="Difficulty" ids="Easy,Normal,Hard,Hardest"/>
|
||||
<dip bits="15" name="Attract Mode Sound" ids="Off,On"/>
|
||||
<dip bits="16" name="Flip Screen" ids="Off,On"/>
|
||||
<dip bits="17" name="Upright Controls" ids="Single,Dual"/>
|
||||
<dip bits="18" name="Swap Power/Crouch" ids="Off,On"/>
|
||||
</switches>
|
||||
|
||||
<rom index="1">
|
||||
<part>00</part>
|
||||
</rom>
|
||||
<rom index='0' md5="None" type='merged' zip='ironhors.zip'>
|
||||
<part crc="395351b4" name="560_k03.13c"/>
|
||||
<part crc="1cff3d59" name="560_k02.12c"/>
|
||||
<part crc="2b17930f" name="560_h01.10c"/>
|
||||
<part crc="f21d8c93" name="560_h06.08f"/>
|
||||
<part crc="60107859" name="560_h05.07f"/>
|
||||
<part crc="c761ec73" name="560_h07.09f"/>
|
||||
<part crc="c1486f61" name="560_h04.06f"/>
|
||||
<part crc="9f6ddf83" name="03f_h08.bin"/>
|
||||
<part crc="e6773825" name="04f_h09.bin"/>
|
||||
<part crc="30a57860" name="05f_h10.bin"/>
|
||||
<part crc="5eb33e73" name="10f_h12.bin"/>
|
||||
<part crc="a63e37d8" name="10f_h11.bin"/>
|
||||
</rom>
|
||||
<rom index="2"></rom>
|
||||
<rom index="3" md5="none">
|
||||
<part>
|
||||
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
|
||||
</part>
|
||||
</rom>
|
||||
<rom index="4">
|
||||
<part>
|
||||
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
|
||||
</part>
|
||||
</rom>
|
||||
|
||||
<nvram index="4" size="67"></nvram>
|
||||
|
||||
<remark></remark>
|
||||
|
||||
<mratimestamp>20210803143815</mratimestamp>
|
||||
</misterromdescription>
|
||||
627
Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv
Normal file
627
Arcade_MiST/Konami Iron Horse/rtl/IronHorse.sv
Normal file
@@ -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
|
||||
323
Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv
Normal file
323
Arcade_MiST/Konami Iron Horse/rtl/IronHorse_MiST.sv
Normal file
@@ -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
|
||||
173
Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v
Normal file
173
Arcade_MiST/Konami Iron Horse/rtl/audio_iir_filter.v
Normal file
@@ -0,0 +1,173 @@
|
||||
/*MIT License
|
||||
|
||||
Copyright (c) 2019 Gregory Hogan (Soltan_G42)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.*/
|
||||
|
||||
module iir_1st_order
|
||||
#(
|
||||
parameter COEFF_WIDTH = 18,
|
||||
parameter COEFF_SCALE = 15,
|
||||
parameter DATA_WIDTH = 16,
|
||||
parameter COUNT_BITS = 10
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
input [COUNT_BITS - 1 : 0] div,
|
||||
input signed [COEFF_WIDTH - 1 : 0] A2, B1, B2,
|
||||
input signed [DATA_WIDTH - 1 :0] in,
|
||||
output [DATA_WIDTH - 1:0] out
|
||||
);
|
||||
|
||||
reg signed [DATA_WIDTH-1:0] x0,x1,y0;
|
||||
reg signed [DATA_WIDTH + COEFF_WIDTH - 1 : 0] out32;
|
||||
reg [COUNT_BITS - 1:0] count;
|
||||
|
||||
// Usage:
|
||||
// Design your 1st order iir low/high-pass with a tool that will give you the
|
||||
// filter coefficients for the difference equation. Filter coefficients can
|
||||
// be generated in Octave/matlab/scipy using a command similar to
|
||||
// [B, A] = butter( 1, 3500/(106528/2), 'low') for a 3500 hz 1st order low-pass
|
||||
// assuming 106528Hz sample rate.
|
||||
//
|
||||
// The Matlab output is:
|
||||
// B = [0.093863 0.093863]
|
||||
// A = [1.00000 -0.81227]
|
||||
//
|
||||
// Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
|
||||
//
|
||||
// B = [3076 3076]
|
||||
// A = [32768 -26616]
|
||||
//
|
||||
// Discard A(1) because it is assumed 1.0 before scaling
|
||||
//
|
||||
// This leaves you with A2 = -26616 , B1 = 3076 , B2 = 3076
|
||||
// B1 + B2 - A2 should sum to 2^COEFF_SCALE = 32768
|
||||
//
|
||||
// Sample frequency is "clk rate/div": for Genesis this is 53.69mhz/504 = 106528hz
|
||||
//
|
||||
// COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
|
||||
// handle temporary overflow during this computation: out32 <= (B1*x0 + B2*x1) - A2*y0
|
||||
|
||||
assign out = y0;
|
||||
|
||||
always @ (*) begin
|
||||
out32 <= (B1*x0 + B2*x1) - A2*y0; //Previous output is y0 not y1
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if(reset) begin
|
||||
count <= 0;
|
||||
x0 <= 0;
|
||||
x1 <= 0;
|
||||
y0 <= 0;
|
||||
end
|
||||
else begin
|
||||
count <= count + 1'd1;
|
||||
if (count == div - 1) begin
|
||||
count <= 0;
|
||||
y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[COEFF_SCALE + DATA_WIDTH - 2 : COEFF_SCALE]};
|
||||
x1 <= x0;
|
||||
x0 <= in;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //iir_1st_order
|
||||
|
||||
module iir_2nd_order
|
||||
#(
|
||||
parameter COEFF_WIDTH = 18,
|
||||
parameter COEFF_SCALE = 14,
|
||||
parameter DATA_WIDTH = 16,
|
||||
parameter COUNT_BITS = 10
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input reset,
|
||||
input [COUNT_BITS - 1 : 0] div,
|
||||
input signed [COEFF_WIDTH - 1 : 0] A2, A3, B1, B2, B3,
|
||||
input signed [DATA_WIDTH - 1 : 0] in,
|
||||
output [DATA_WIDTH - 1 : 0] out
|
||||
);
|
||||
|
||||
reg signed [DATA_WIDTH-1 : 0] x0,x1,x2;
|
||||
reg signed [DATA_WIDTH-1 : 0] y0,y1;
|
||||
reg signed [(DATA_WIDTH + COEFF_WIDTH - 1) : 0] out32;
|
||||
reg [COUNT_BITS : 0] count;
|
||||
|
||||
|
||||
// Usage:
|
||||
// Design your 1st order iir low/high-pass with a tool that will give you the
|
||||
// filter coefficients for the difference equation. Filter coefficients can
|
||||
// be generated in Octave/matlab/scipy using a command similar to
|
||||
// [B, A] = butter( 2, 5000/(48000/2), 'low') for a 5000 hz 2nd order low-pass
|
||||
// assuming 48000Hz sample rate.
|
||||
//
|
||||
// Output is:
|
||||
// B = [ 0.072231 0.144462 0.072231]
|
||||
// A = [1.00000 -1.10923 0.39815]
|
||||
//
|
||||
// Then scale coefficients by multiplying by 2^COEFF_SCALE and round to nearest integer
|
||||
// Make sure your coefficients can be stored as a signed number with COEFF_WIDTH bits.
|
||||
//
|
||||
// B = [1183 2367 1183]
|
||||
// A = [16384 -18174 6523]
|
||||
//
|
||||
// Discard A(1) because it is assumed 1.0 before scaling
|
||||
//
|
||||
// This leaves you with A2 = -18174 , A3 = 6523, B1 = 1183 , B2 = 2367 , B3 = 1183
|
||||
// B1 + B2 + B3 - A2 - A3 should sum to 2^COEFF_SCALE = 16384
|
||||
//
|
||||
// Sample frequency is "clk rate/div"
|
||||
//
|
||||
// COEFF_WIDTH must be at least COEFF_SCALE+1 and must be large enough to
|
||||
// handle temporary overflow during this computation:
|
||||
// out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1);
|
||||
|
||||
assign out = y0;
|
||||
|
||||
always @ (*) begin
|
||||
out32 <= (B1*x0 + B2*x1 + B3*x2) - (A2*y0 + A3*y1); //Previous output is y0 not y1
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if(reset) begin
|
||||
count <= 0;
|
||||
x0 <= 0;
|
||||
x1 <= 0;
|
||||
x2 <= 0;
|
||||
y0 <= 0;
|
||||
y1 <= 0;
|
||||
end
|
||||
else begin
|
||||
count <= count + 1'd1;
|
||||
if (count == div - 1) begin
|
||||
count <= 0;
|
||||
y1 <= y0;
|
||||
y0 <= {out32[DATA_WIDTH + COEFF_WIDTH - 1] , out32[(DATA_WIDTH + COEFF_SCALE - 2) : COEFF_SCALE]};
|
||||
x2 <= x1;
|
||||
x1 <= x0;
|
||||
x0 <= in;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //iir_2nd_order
|
||||
35
Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl
Normal file
35
Arcade_MiST/Konami Iron Horse/rtl/build_id.tcl
Normal file
@@ -0,0 +1,35 @@
|
||||
# ================================================================================
|
||||
#
|
||||
# Build ID Verilog Module Script
|
||||
# Jeff Wiencrot - 8/1/2011
|
||||
#
|
||||
# Generates a Verilog module that contains a timestamp,
|
||||
# from the current build. These values are available from the build_date, build_time,
|
||||
# physical_address, and host_name output ports of the build_id module in the build_id.v
|
||||
# Verilog source file.
|
||||
#
|
||||
# ================================================================================
|
||||
|
||||
proc generateBuildID_Verilog {} {
|
||||
|
||||
# Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
|
||||
set buildDate [ clock format [ clock seconds ] -format %y%m%d ]
|
||||
set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
|
||||
|
||||
# Create a Verilog file for output
|
||||
set outputFileName "rtl/build_id.v"
|
||||
set outputFile [open $outputFileName "w"]
|
||||
|
||||
# Output the Verilog source
|
||||
puts $outputFile "`define BUILD_DATE \"$buildDate\""
|
||||
puts $outputFile "`define BUILD_TIME \"$buildTime\""
|
||||
close $outputFile
|
||||
|
||||
# Send confirmation message to the Messages window
|
||||
post_message "Generated build identification Verilog module: [pwd]/$outputFileName"
|
||||
post_message "Date: $buildDate"
|
||||
post_message "Time: $buildTime"
|
||||
}
|
||||
|
||||
# Comment out this line to prevent the process from automatically executing when the file is sourced:
|
||||
generateBuildID_Verilog
|
||||
136
Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd
Normal file
136
Arcade_MiST/Konami Iron Horse/rtl/dpram_dc.vhd
Normal file
@@ -0,0 +1,136 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY dpram_dc IS
|
||||
GENERIC
|
||||
(
|
||||
init_file : string := " ";
|
||||
widthad_a : natural;
|
||||
width_a : natural := 8;
|
||||
outdata_reg_a : string := "UNREGISTERED";
|
||||
outdata_reg_b : string := "UNREGISTERED"
|
||||
);
|
||||
PORT
|
||||
(
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0) := (others => '0');
|
||||
clock_a : IN STD_LOGIC ;
|
||||
clock_b : IN STD_LOGIC ;
|
||||
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
|
||||
data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) := (others => '0');
|
||||
wren_a : IN STD_LOGIC := '0';
|
||||
wren_b : IN STD_LOGIC := '0';
|
||||
byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
|
||||
byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) := (others => '1');
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END dpram_dc;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram_dc IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
|
||||
|
||||
|
||||
COMPONENT altsyncram
|
||||
GENERIC (
|
||||
address_reg_b : STRING;
|
||||
clock_enable_input_a : STRING;
|
||||
clock_enable_input_b : STRING;
|
||||
clock_enable_output_a : STRING;
|
||||
clock_enable_output_b : STRING;
|
||||
indata_reg_b : STRING;
|
||||
init_file : STRING;
|
||||
intended_device_family : STRING;
|
||||
lpm_type : STRING;
|
||||
numwords_a : NATURAL;
|
||||
numwords_b : NATURAL;
|
||||
operation_mode : STRING;
|
||||
outdata_aclr_a : STRING;
|
||||
outdata_aclr_b : STRING;
|
||||
outdata_reg_a : STRING;
|
||||
outdata_reg_b : STRING;
|
||||
power_up_uninitialized : STRING;
|
||||
read_during_write_mode_port_a : STRING;
|
||||
read_during_write_mode_port_b : STRING;
|
||||
widthad_a : NATURAL;
|
||||
widthad_b : NATURAL;
|
||||
width_a : NATURAL;
|
||||
width_b : NATURAL;
|
||||
width_byteena_a : NATURAL;
|
||||
width_byteena_b : NATURAL;
|
||||
wrcontrol_wraddress_reg_b : STRING
|
||||
);
|
||||
PORT (
|
||||
wren_a : IN STD_LOGIC ;
|
||||
clock0 : IN STD_LOGIC ;
|
||||
wren_b : IN STD_LOGIC ;
|
||||
clock1 : IN STD_LOGIC ;
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
address_b : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
q_b : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
byteena_a : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
|
||||
byteena_b : IN STD_LOGIC_VECTOR (width_a/8-1 DOWNTO 0) ;
|
||||
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
data_b : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
q_a <= sub_wire0(width_a-1 DOWNTO 0);
|
||||
q_b <= sub_wire1(width_a-1 DOWNTO 0);
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "BYPASS",
|
||||
clock_enable_input_b => "BYPASS",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
init_file => init_file,
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**widthad_a,
|
||||
numwords_b => 2**widthad_a,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => outdata_reg_a,
|
||||
outdata_reg_b => outdata_reg_a,
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
widthad_a => widthad_a,
|
||||
widthad_b => widthad_a,
|
||||
width_a => width_a,
|
||||
width_b => width_a,
|
||||
width_byteena_a => width_a/8,
|
||||
width_byteena_b => width_a/8,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
wren_a => wren_a,
|
||||
clock0 => clock_a,
|
||||
wren_b => wren_b,
|
||||
clock1 => clock_b,
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
q_a => sub_wire0,
|
||||
q_b => sub_wire1,
|
||||
byteena_a => byteena_a,
|
||||
byteena_b => byteena_b
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
60
Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv
Normal file
60
Arcade_MiST/Konami Iron Horse/rtl/ironhorse_fm_lpf.sv
Normal file
@@ -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
|
||||
61
Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv
Normal file
61
Arcade_MiST/Konami Iron Horse/rtl/ironhorse_ssg_lpf.sv
Normal file
@@ -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
|
||||
62
Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v
Normal file
62
Arcade_MiST/Konami Iron Horse/rtl/jt49_dcrm2.v
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This file is part of JT49.
|
||||
|
||||
JT49 is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JT49 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT49. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 15-Jan-2019
|
||||
|
||||
*/
|
||||
|
||||
// DC removal filter
|
||||
// input is unsigned
|
||||
// output is signed
|
||||
|
||||
module jt49_dcrm2 #(parameter sw=8) (
|
||||
input clk,
|
||||
input cen,
|
||||
input rst,
|
||||
input [sw-1:0] din,
|
||||
output signed [sw-1:0] dout
|
||||
);
|
||||
|
||||
localparam dw=10; // widht of the decimal portion
|
||||
|
||||
reg signed [sw+dw:0] integ, exact, error;
|
||||
//reg signed [2*(9+dw)-1:0] mult;
|
||||
// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1};
|
||||
reg signed [sw:0] pre_dout;
|
||||
// reg signed [sw+dw:0] dout_ext;
|
||||
reg signed [sw:0] q;
|
||||
|
||||
always @(*) begin
|
||||
exact = integ+error;
|
||||
q = exact[sw+dw:dw];
|
||||
pre_dout = { 1'b0, din } - q;
|
||||
//dout_ext = { pre_dout, {dw{1'b0}} };
|
||||
//mult = dout_ext;
|
||||
end
|
||||
|
||||
assign dout = pre_dout[sw-1:0];
|
||||
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
integ <= {sw+dw+1{1'b0}};
|
||||
error <= {sw+dw+1{1'b0}};
|
||||
end else if( cen ) begin
|
||||
integ <= integ + pre_dout; //mult[sw+dw*2:dw];
|
||||
error <= exact-{q, {dw{1'b0}}};
|
||||
end
|
||||
|
||||
endmodule
|
||||
58
Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v
Normal file
58
Arcade_MiST/Konami Iron Horse/rtl/jtframe_frac_cen.v
Normal file
@@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Fractional clock enable signal
|
||||
// W refers to the number of divided down cen signals available
|
||||
// each one is divided by 2
|
||||
|
||||
module jtframe_frac_cen #(parameter W=2)(
|
||||
input clk,
|
||||
input [9:0] n, // numerator
|
||||
input [9:0] m, // denominator
|
||||
output reg [W-1:0] cen,
|
||||
output reg [W-1:0] cenb // 180 shifted
|
||||
);
|
||||
|
||||
wire [10:0] step={1'b0,n};
|
||||
wire [10:0] lim ={1'b0,m};
|
||||
wire [10:0] absmax = lim+step;
|
||||
|
||||
reg [10:0] cencnt=11'd0;
|
||||
reg [10:0] next;
|
||||
reg [10:0] next2;
|
||||
|
||||
always @(*) begin
|
||||
next = cencnt+step;
|
||||
next2 = next-lim;
|
||||
end
|
||||
|
||||
reg half = 1'b0;
|
||||
wire over = next>=lim;
|
||||
wire halfway = next >= (lim>>1) && !half;
|
||||
|
||||
reg [W-1:0] edgecnt = {W{1'b0}};
|
||||
wire [W-1:0] next_edgecnt = edgecnt + 1'b1;
|
||||
wire [W-1:0] toggle = next_edgecnt & ~edgecnt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cen <= {W{1'b0}};
|
||||
cenb <= {W{1'b0}};
|
||||
|
||||
if( cencnt >= absmax ) begin
|
||||
// something went wrong: restart
|
||||
cencnt <= 11'd0;
|
||||
end else
|
||||
if( halfway ) begin
|
||||
half <= 1'b1;
|
||||
cenb[0] <= 1'b1;
|
||||
end
|
||||
if( over ) begin
|
||||
cencnt <= next2;
|
||||
half <= 1'b0;
|
||||
edgecnt <= next_edgecnt;
|
||||
cen <= { toggle[W-2:0], 1'b1 };
|
||||
end else begin
|
||||
cencnt <= next;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
992
Arcade_MiST/Konami Iron Horse/rtl/k005885.sv
Normal file
992
Arcade_MiST/Konami Iron Horse/rtl/k005885.sv
Normal file
@@ -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
|
||||
4
Arcade_MiST/Konami Iron Horse/rtl/pll.qip
Normal file
4
Arcade_MiST/Konami Iron Horse/rtl/pll.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
|
||||
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]
|
||||
348
Arcade_MiST/Konami Iron Horse/rtl/pll.v
Normal file
348
Arcade_MiST/Konami Iron Horse/rtl/pll.v
Normal file
@@ -0,0 +1,348 @@
|
||||
// megafunction wizard: %ALTPLL%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altpll
|
||||
|
||||
// ============================================================
|
||||
// File Name: pll.v
|
||||
// Megafunction Name(s):
|
||||
// altpll
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module pll (
|
||||
areset,
|
||||
inclk0,
|
||||
c0,
|
||||
c1,
|
||||
locked);
|
||||
|
||||
input areset;
|
||||
input inclk0;
|
||||
output c0;
|
||||
output c1;
|
||||
output locked;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri0 areset;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [4:0] sub_wire0;
|
||||
wire sub_wire2;
|
||||
wire [0:0] sub_wire6 = 1'h0;
|
||||
wire [0:0] sub_wire3 = sub_wire0[0:0];
|
||||
wire [1:1] sub_wire1 = sub_wire0[1:1];
|
||||
wire c1 = sub_wire1;
|
||||
wire locked = sub_wire2;
|
||||
wire c0 = sub_wire3;
|
||||
wire sub_wire4 = inclk0;
|
||||
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
|
||||
|
||||
altpll altpll_component (
|
||||
.areset (areset),
|
||||
.inclk (sub_wire5),
|
||||
.clk (sub_wire0),
|
||||
.locked (sub_wire2),
|
||||
.activeclock (),
|
||||
.clkbad (),
|
||||
.clkena ({6{1'b1}}),
|
||||
.clkloss (),
|
||||
.clkswitch (1'b0),
|
||||
.configupdate (1'b0),
|
||||
.enable0 (),
|
||||
.enable1 (),
|
||||
.extclk (),
|
||||
.extclkena ({4{1'b1}}),
|
||||
.fbin (1'b1),
|
||||
.fbmimicbidir (),
|
||||
.fbout (),
|
||||
.fref (),
|
||||
.icdrclk (),
|
||||
.pfdena (1'b1),
|
||||
.phasecounterselect ({4{1'b1}}),
|
||||
.phasedone (),
|
||||
.phasestep (1'b1),
|
||||
.phaseupdown (1'b1),
|
||||
.pllena (1'b1),
|
||||
.scanaclr (1'b0),
|
||||
.scanclk (1'b0),
|
||||
.scanclkena (1'b1),
|
||||
.scandata (1'b0),
|
||||
.scandataout (),
|
||||
.scandone (),
|
||||
.scanread (1'b0),
|
||||
.scanwrite (1'b0),
|
||||
.sclkout0 (),
|
||||
.sclkout1 (),
|
||||
.vcooverrange (),
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 105,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 382,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.clk1_divide_by = 105,
|
||||
altpll_component.clk1_duty_cycle = 50,
|
||||
altpll_component.clk1_multiply_by = 191,
|
||||
altpll_component.clk1_phase_shift = "0",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 37037,
|
||||
altpll_component.intended_device_family = "Cyclone III",
|
||||
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
|
||||
altpll_component.lpm_type = "altpll",
|
||||
altpll_component.operation_mode = "NORMAL",
|
||||
altpll_component.pll_type = "AUTO",
|
||||
altpll_component.port_activeclock = "PORT_UNUSED",
|
||||
altpll_component.port_areset = "PORT_USED",
|
||||
altpll_component.port_clkbad0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkloss = "PORT_UNUSED",
|
||||
altpll_component.port_clkswitch = "PORT_UNUSED",
|
||||
altpll_component.port_configupdate = "PORT_UNUSED",
|
||||
altpll_component.port_fbin = "PORT_UNUSED",
|
||||
altpll_component.port_inclk0 = "PORT_USED",
|
||||
altpll_component.port_inclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_locked = "PORT_USED",
|
||||
altpll_component.port_pfdena = "PORT_UNUSED",
|
||||
altpll_component.port_phasecounterselect = "PORT_UNUSED",
|
||||
altpll_component.port_phasedone = "PORT_UNUSED",
|
||||
altpll_component.port_phasestep = "PORT_UNUSED",
|
||||
altpll_component.port_phaseupdown = "PORT_UNUSED",
|
||||
altpll_component.port_pllena = "PORT_UNUSED",
|
||||
altpll_component.port_scanaclr = "PORT_UNUSED",
|
||||
altpll_component.port_scanclk = "PORT_UNUSED",
|
||||
altpll_component.port_scanclkena = "PORT_UNUSED",
|
||||
altpll_component.port_scandata = "PORT_UNUSED",
|
||||
altpll_component.port_scandataout = "PORT_UNUSED",
|
||||
altpll_component.port_scandone = "PORT_UNUSED",
|
||||
altpll_component.port_scanread = "PORT_UNUSED",
|
||||
altpll_component.port_scanwrite = "PORT_UNUSED",
|
||||
altpll_component.port_clk0 = "PORT_USED",
|
||||
altpll_component.port_clk1 = "PORT_USED",
|
||||
altpll_component.port_clk2 = "PORT_UNUSED",
|
||||
altpll_component.port_clk3 = "PORT_UNUSED",
|
||||
altpll_component.port_clk4 = "PORT_UNUSED",
|
||||
altpll_component.port_clk5 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena2 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena3 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena4 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena5 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk0 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk2 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk3 = "PORT_UNUSED",
|
||||
altpll_component.self_reset_on_loss_lock = "OFF",
|
||||
altpll_component.width_clock = 5;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "105"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "105"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "98.228569"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "49.114285"
|
||||
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
|
||||
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
|
||||
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
|
||||
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
|
||||
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
|
||||
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
|
||||
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
|
||||
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
|
||||
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "382"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "191"
|
||||
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "49.15200000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
|
||||
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
|
||||
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
|
||||
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
|
||||
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
|
||||
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
|
||||
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
|
||||
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
|
||||
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
|
||||
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
|
||||
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "105"
|
||||
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "382"
|
||||
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "105"
|
||||
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "191"
|
||||
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
|
||||
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
|
||||
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
|
||||
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
|
||||
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
|
||||
// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
|
||||
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
|
||||
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
|
||||
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
|
||||
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
|
||||
// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
|
||||
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
|
||||
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
|
||||
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
|
||||
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
|
||||
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
// Retrieval info: CBX_MODULE_PREFIX: ON
|
||||
366
Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv
Normal file
366
Arcade_MiST/Konami Iron Horse/rtl/rom_loader.sv
Normal file
@@ -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
|
||||
363
Arcade_MiST/Konami Iron Horse/rtl/sdram.sv
Normal file
363
Arcade_MiST/Konami Iron Horse/rtl/sdram.sv
Normal file
@@ -0,0 +1,363 @@
|
||||
//
|
||||
// sdram.v
|
||||
//
|
||||
// sdram controller implementation for the MiST board
|
||||
// https://github.com/mist-devel/mist-board
|
||||
//
|
||||
// Copyright (c) 2013 Till Harbaum <till@harbaum.org>
|
||||
// Copyright (c) 2019 Gyorgy Szombathelyi
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module sdram (
|
||||
|
||||
// interface to the MT48LC16M16 chip
|
||||
inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
|
||||
output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
|
||||
output reg SDRAM_DQML, // two byte masks
|
||||
output reg SDRAM_DQMH, // two byte masks
|
||||
output reg [1:0] SDRAM_BA, // two banks
|
||||
output SDRAM_nCS, // a single chip select
|
||||
output SDRAM_nWE, // write enable
|
||||
output SDRAM_nRAS, // row address select
|
||||
output SDRAM_nCAS, // columns address select
|
||||
|
||||
// cpu/chipset interface
|
||||
input init_n, // init signal after FPGA config to initialize RAM
|
||||
input clk, // sdram clock
|
||||
|
||||
input port1_req,
|
||||
output reg port1_ack,
|
||||
input port1_we,
|
||||
input [23:1] port1_a,
|
||||
input [1:0] port1_ds,
|
||||
input [15:0] port1_d,
|
||||
output reg [15:0] port1_q,
|
||||
|
||||
input [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
|
||||
46
Arcade_MiST/Konami Iron Horse/rtl/spram.vhd
Normal file
46
Arcade_MiST/Konami Iron Horse/rtl/spram.vhd
Normal file
@@ -0,0 +1,46 @@
|
||||
library ieee;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.std_logic_unsigned.ALL;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity spram is
|
||||
|
||||
generic
|
||||
(
|
||||
DATA_WIDTH : natural := 8;
|
||||
ADDR_WIDTH : natural := 10
|
||||
);
|
||||
|
||||
port
|
||||
(
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector((ADDR_WIDTH - 1) downto 0);
|
||||
data : in std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
q : out std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
we : in std_logic := '0'
|
||||
);
|
||||
|
||||
end spram;
|
||||
|
||||
architecture rtl of spram is
|
||||
|
||||
subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
|
||||
type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
|
||||
|
||||
shared variable ram : memory_t;
|
||||
|
||||
begin
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if(rising_edge(clk)) then
|
||||
if(we = '1') then
|
||||
ram(to_integer(unsigned(addr))) := data;
|
||||
q <= data;
|
||||
else
|
||||
q <= ram(to_integer(unsigned(addr)));
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
@@ -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
|
||||
|
||||
674
common/Sound/JT12/LICENSE
Normal file
674
common/Sound/JT12/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
43
common/Sound/JT12/README.md
Normal file
43
common/Sound/JT12/README.md
Normal file
@@ -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)
|
||||
14
common/Sound/JT12/hdl/adpcm/gen_lingain.py
Normal file
14
common/Sound/JT12/hdl/adpcm/gen_lingain.py
Normal file
@@ -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
|
||||
132
common/Sound/JT12/hdl/adpcm/jt10_adpcm.v
Normal file
132
common/Sound/JT12/hdl/adpcm/jt10_adpcm.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
90
common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v
Normal file
90
common/Sound/JT12/hdl/adpcm/jt10_adpcm_acc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
181
common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v
Normal file
181
common/Sound/JT12/hdl/adpcm/jt10_adpcm_cnt.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
134
common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v
Normal file
134
common/Sound/JT12/hdl/adpcm/jt10_adpcm_comb.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
54
common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v
Normal file
54
common/Sound/JT12/hdl/adpcm/jt10_adpcm_dbrom.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
62
common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v
Normal file
62
common/Sound/JT12/hdl/adpcm/jt10_adpcm_div.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
335
common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v
Normal file
335
common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvA.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
124
common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v
Normal file
124
common/Sound/JT12/hdl/adpcm/jt10_adpcm_drvB.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
130
common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v
Normal file
130
common/Sound/JT12/hdl/adpcm/jt10_adpcm_dt.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
176
common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v
Normal file
176
common/Sound/JT12/hdl/adpcm/jt10_adpcm_gain.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
142
common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v
Normal file
142
common/Sound/JT12/hdl/adpcm/jt10_adpcma_lut.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
112
common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v
Normal file
112
common/Sound/JT12/hdl/adpcm/jt10_adpcmb.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
108
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v
Normal file
108
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_cnt.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
39
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v
Normal file
39
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_gain.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
96
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v
Normal file
96
common/Sound/JT12/hdl/adpcm/jt10_adpcmb_interpol.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
59
common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v
Normal file
59
common/Sound/JT12/hdl/adpcm/jt10_cen_burst.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
84
common/Sound/JT12/hdl/alt/eg_cnt.v
Normal file
84
common/Sound/JT12/hdl/alt/eg_cnt.v
Normal file
@@ -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
|
||||
184
common/Sound/JT12/hdl/alt/eg_comb.v
Normal file
184
common/Sound/JT12/hdl/alt/eg_comb.v
Normal file
@@ -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
|
||||
79
common/Sound/JT12/hdl/alt/eg_mux.v
Normal file
79
common/Sound/JT12/hdl/alt/eg_mux.v
Normal file
@@ -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
|
||||
46
common/Sound/JT12/hdl/alt/eg_step.v
Normal file
46
common/Sound/JT12/hdl/alt/eg_step.v
Normal file
@@ -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
|
||||
45
common/Sound/JT12/hdl/alt/eg_step_ram.v
Normal file
45
common/Sound/JT12/hdl/alt/eg_step_ram.v
Normal file
@@ -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
|
||||
56
common/Sound/JT12/hdl/dac/jt12_dac.v
Normal file
56
common/Sound/JT12/hdl/dac/jt12_dac.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 9th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
input sampling rate must be the same as clk frequency
|
||||
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
|
||||
63
common/Sound/JT12/hdl/dac/jt12_dac2.v
Normal file
63
common/Sound/JT12/hdl/dac/jt12_dac2.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: March, 9th 2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
input sampling rate must be the same as clk frequency
|
||||
interpolate input signal accordingly to get the
|
||||
right sampling rate.
|
||||
|
||||
Refer to sigmadelta.ods to see how the internal width (int_w)
|
||||
was determined.
|
||||
|
||||
*/
|
||||
|
||||
module 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
|
||||
172
common/Sound/JT12/hdl/deprecated/jt12_amp.v
Normal file
172
common/Sound/JT12/hdl/deprecated/jt12_amp.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
14
common/Sound/JT12/hdl/deprecated/jt12_mod24.v
Normal file
14
common/Sound/JT12/hdl/deprecated/jt12_mod24.v
Normal file
@@ -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
|
||||
52
common/Sound/JT12/hdl/deprecated/jt12_mod6.v
Normal file
52
common/Sound/JT12/hdl/deprecated/jt12_mod6.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
45
common/Sound/JT12/hdl/deprecated/jt12_opram.v
Normal file
45
common/Sound/JT12/hdl/deprecated/jt12_opram.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 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
|
||||
35
common/Sound/JT12/hdl/jt03.qip
Normal file
35
common/Sound/JT12/hdl/jt03.qip
Normal file
@@ -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 ]
|
||||
|
||||
97
common/Sound/JT12/hdl/jt03.v
Normal file
97
common/Sound/JT12/hdl/jt03.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
73
common/Sound/JT12/hdl/jt03_acc.v
Normal file
73
common/Sound/JT12/hdl/jt03_acc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
33
common/Sound/JT12/hdl/jt03_fm.qip
Normal file
33
common/Sound/JT12/hdl/jt03_fm.qip
Normal file
@@ -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 ]
|
||||
63
common/Sound/JT12/hdl/jt10.qip
Normal file
63
common/Sound/JT12/hdl/jt10.qip
Normal file
@@ -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 ]
|
||||
97
common/Sound/JT12/hdl/jt10.v
Normal file
97
common/Sound/JT12/hdl/jt10.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
173
common/Sound/JT12/hdl/jt10_acc.v
Normal file
173
common/Sound/JT12/hdl/jt10_acc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
42
common/Sound/JT12/hdl/jt12.qip
Normal file
42
common/Sound/JT12/hdl/jt12.qip
Normal file
@@ -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 ]
|
||||
80
common/Sound/JT12/hdl/jt12.v
Normal file
80
common/Sound/JT12/hdl/jt12.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
44
common/Sound/JT12/hdl/jt12.vhd
Normal file
44
common/Sound/JT12/hdl/jt12.vhd
Normal file
@@ -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;
|
||||
107
common/Sound/JT12/hdl/jt12_acc.v
Normal file
107
common/Sound/JT12/hdl/jt12_acc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
82
common/Sound/JT12/hdl/jt12_csr.v
Normal file
82
common/Sound/JT12/hdl/jt12_csr.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
141
common/Sound/JT12/hdl/jt12_div.v
Normal file
141
common/Sound/JT12/hdl/jt12_div.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
47
common/Sound/JT12/hdl/jt12_dout.v
Normal file
47
common/Sound/JT12/hdl/jt12_dout.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
203
common/Sound/JT12/hdl/jt12_eg.v
Normal file
203
common/Sound/JT12/hdl/jt12_eg.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
50
common/Sound/JT12/hdl/jt12_eg_cnt.v
Normal file
50
common/Sound/JT12/hdl/jt12_eg_cnt.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
139
common/Sound/JT12/hdl/jt12_eg_comb.v
Normal file
139
common/Sound/JT12/hdl/jt12_eg_comb.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
122
common/Sound/JT12/hdl/jt12_eg_ctrl.v
Normal file
122
common/Sound/JT12/hdl/jt12_eg_ctrl.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
57
common/Sound/JT12/hdl/jt12_eg_final.v
Normal file
57
common/Sound/JT12/hdl/jt12_eg_final.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
81
common/Sound/JT12/hdl/jt12_eg_pure.v
Normal file
81
common/Sound/JT12/hdl/jt12_eg_pure.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
111
common/Sound/JT12/hdl/jt12_eg_step.v
Normal file
111
common/Sound/JT12/hdl/jt12_eg_step.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
302
common/Sound/JT12/hdl/jt12_exprom.v
Normal file
302
common/Sound/JT12/hdl/jt12_exprom.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 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
|
||||
151
common/Sound/JT12/hdl/jt12_kon.v
Normal file
151
common/Sound/JT12/hdl/jt12_kon.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
103
common/Sound/JT12/hdl/jt12_lfo.v
Normal file
103
common/Sound/JT12/hdl/jt12_lfo.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
298
common/Sound/JT12/hdl/jt12_logsin.v
Normal file
298
common/Sound/JT12/hdl/jt12_logsin.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 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
|
||||
511
common/Sound/JT12/hdl/jt12_mmr.v
Normal file
511
common/Sound/JT12/hdl/jt12_mmr.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
854
common/Sound/JT12/hdl/jt12_mmr_sim.vh
Normal file
854
common/Sound/JT12/hdl/jt12_mmr_sim.vh
Normal file
@@ -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
|
||||
|
||||
153
common/Sound/JT12/hdl/jt12_mod.v
Normal file
153
common/Sound/JT12/hdl/jt12_mod.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
332
common/Sound/JT12/hdl/jt12_op.v
Normal file
332
common/Sound/JT12/hdl/jt12_op.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 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
|
||||
109
common/Sound/JT12/hdl/jt12_pcm.v
Normal file
109
common/Sound/JT12/hdl/jt12_pcm.v
Normal file
@@ -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
|
||||
109
common/Sound/JT12/hdl/jt12_pcm_interpol.v
Normal file
109
common/Sound/JT12/hdl/jt12_pcm_interpol.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
114
common/Sound/JT12/hdl/jt12_pg.v
Normal file
114
common/Sound/JT12/hdl/jt12_pg.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
|
||||
90
common/Sound/JT12/hdl/jt12_pg_comb.v
Normal file
90
common/Sound/JT12/hdl/jt12_pg_comb.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
82
common/Sound/JT12/hdl/jt12_pg_dt.v
Normal file
82
common/Sound/JT12/hdl/jt12_pg_dt.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
50
common/Sound/JT12/hdl/jt12_pg_inc.v
Normal file
50
common/Sound/JT12/hdl/jt12_pg_inc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
49
common/Sound/JT12/hdl/jt12_pg_sum.v
Normal file
49
common/Sound/JT12/hdl/jt12_pg_sum.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
186
common/Sound/JT12/hdl/jt12_pm.v
Normal file
186
common/Sound/JT12/hdl/jt12_pm.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
372
common/Sound/JT12/hdl/jt12_reg.v
Normal file
372
common/Sound/JT12/hdl/jt12_reg.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
38
common/Sound/JT12/hdl/jt12_rst.v
Normal file
38
common/Sound/JT12/hdl/jt12_rst.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
44
common/Sound/JT12/hdl/jt12_sh.v
Normal file
44
common/Sound/JT12/hdl/jt12_sh.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
81
common/Sound/JT12/hdl/jt12_sh24.v
Normal file
81
common/Sound/JT12/hdl/jt12_sh24.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
56
common/Sound/JT12/hdl/jt12_sh_rst.v
Normal file
56
common/Sound/JT12/hdl/jt12_sh_rst.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
63
common/Sound/JT12/hdl/jt12_single_acc.v
Normal file
63
common/Sound/JT12/hdl/jt12_single_acc.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
47
common/Sound/JT12/hdl/jt12_sumch.v
Normal file
47
common/Sound/JT12/hdl/jt12_sumch.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
141
common/Sound/JT12/hdl/jt12_timers.v
Normal file
141
common/Sound/JT12/hdl/jt12_timers.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
671
common/Sound/JT12/hdl/jt12_top.v
Normal file
671
common/Sound/JT12/hdl/jt12_top.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
59
common/Sound/JT12/hdl/mixer/jt12_comb.v
Normal file
59
common/Sound/JT12/hdl/mixer/jt12_comb.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<m;k=k+1) begin : mem_gen
|
||||
always @(posedge clk)
|
||||
if(rst) begin
|
||||
mem[k] <= {w{1'b0}};
|
||||
end else if(cen) begin
|
||||
mem[k] <= k==0 ? snd_in : mem[k-1];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Comb filter at synthesizer sampling rate
|
||||
always @(posedge clk)
|
||||
if(rst) begin
|
||||
snd_out <= {w{1'b0}};
|
||||
end else if(cen) begin
|
||||
snd_out <= snd_in - prev;
|
||||
end
|
||||
|
||||
endmodule // jt12_comb
|
||||
90
common/Sound/JT12/hdl/mixer/jt12_decim.v
Normal file
90
common/Sound/JT12/hdl/mixer/jt12_decim.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<n;k=k+1) begin : com_gen
|
||||
jt12_comb #(.w(calcw),.m(m)) u_comb(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen_out ),
|
||||
.snd_in ( comb_data[k] ),
|
||||
.snd_out( comb_data[k+1] )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Comb filter at synthesizer sampling rate
|
||||
always @(posedge clk)
|
||||
if(rst) begin
|
||||
snd_out <= {inw{1'b0}};
|
||||
end else if(cen_out) begin
|
||||
snd_out<= comb_op[calcw-1:wdiff];
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
95
common/Sound/JT12/hdl/mixer/jt12_fm_uprate.v
Normal file
95
common/Sound/JT12/hdl/mixer/jt12_fm_uprate.v
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user