mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-04-09 22:19:00 +00:00
Merge pull request #26 from gyurco/master
Demolition Derby: add the sound board for controls
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
# ========================
|
||||
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 LAST_QUARTUS_VERSION "13.1 SP4.26"
|
||||
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
||||
|
||||
# Pin & Location Assignments
|
||||
@@ -231,8 +231,12 @@ set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/dderby_bg_bits_2.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/dderby_bg_bits_1.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/midssio_82s123.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/super_sound_board.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
|
||||
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@@ -172,6 +172,28 @@ always @(posedge clk_sys) begin
|
||||
|
||||
end
|
||||
|
||||
wire [5:0] wheel1;
|
||||
spinner spinner1 (
|
||||
.clock_40(clk_sys),
|
||||
.reset(reset),
|
||||
.btn_acc(),
|
||||
.btn_left(m_left1),
|
||||
.btn_right(m_right1),
|
||||
.ctc_zc_to_2(vs),
|
||||
.spin_angle(wheel1)
|
||||
);
|
||||
|
||||
wire [5:0] wheel2;
|
||||
spinner spinner2 (
|
||||
.clock_40(clk_sys),
|
||||
.reset(reset),
|
||||
.btn_acc(),
|
||||
.btn_left(m_left2),
|
||||
.btn_right(m_right2),
|
||||
.ctc_zc_to_2(vs),
|
||||
.spin_angle(wheel2)
|
||||
);
|
||||
|
||||
dderby dderby(
|
||||
.clock_40(clk_sys),
|
||||
.reset(reset),
|
||||
@@ -204,10 +226,10 @@ dderby dderby(
|
||||
.p3_fire2(m_fire1b),
|
||||
.p4_fire1(m_fire2),
|
||||
.p4_fire2(m_fire2b),
|
||||
/*
|
||||
.wheel1 : in std_logic_vector(5 downto 0);
|
||||
.wheel2 : in std_logic_vector(5 downto 0);
|
||||
*/
|
||||
|
||||
.wheel1(wheel1),
|
||||
.wheel2(wheel2),
|
||||
|
||||
.service(status[6]),
|
||||
|
||||
.cpu_rom_addr ( rom_addr ),
|
||||
@@ -290,17 +312,13 @@ wire [7:0] joystick_0 = status[7] ? joy_1 : joy_0;
|
||||
wire [7:0] joystick_1 = status[7] ? joy_0 : joy_1;
|
||||
|
||||
// Rotated Normal
|
||||
wire m_up1 = status[2] ? btn_left | joystick_0[1] : btn_up | joystick_0[3];
|
||||
wire m_down1 = status[2] ? btn_right | joystick_0[0] : btn_down | joystick_0[2];
|
||||
wire m_left1 = status[2] ? btn_down | joystick_0[2] : btn_left | joystick_0[1];
|
||||
wire m_right1 = status[2] ? btn_up | joystick_0[3] : btn_right | joystick_0[0];
|
||||
wire m_left1 = btn_left | joystick_0[1];
|
||||
wire m_right1 = btn_right | joystick_0[0];
|
||||
wire m_fire1 = btn_fire1 | joystick_0[4];
|
||||
wire m_fire1b = btn_fire2 | joystick_0[5];
|
||||
|
||||
wire m_up2 = status[2] ? joystick_1[1] : joystick_1[3];
|
||||
wire m_down2 = status[2] ? joystick_1[0] : joystick_1[2];
|
||||
wire m_left2 = status[2] ? joystick_1[2] : joystick_1[1];
|
||||
wire m_right2 = status[2] ? joystick_1[3] : joystick_1[0];
|
||||
wire m_left2 = joystick_1[1];
|
||||
wire m_right2 = joystick_1[0];
|
||||
wire m_fire2 = joystick_1[4];
|
||||
wire m_fire2b = joystick_1[5];
|
||||
|
||||
@@ -308,8 +326,8 @@ reg btn_one_player = 0;
|
||||
reg btn_two_players = 0;
|
||||
reg btn_left = 0;
|
||||
reg btn_right = 0;
|
||||
reg btn_down = 0;
|
||||
reg btn_up = 0;
|
||||
//reg btn_down = 0;
|
||||
//reg btn_up = 0;
|
||||
reg btn_fire1 = 0;
|
||||
reg btn_fire2 = 0;
|
||||
//reg btn_fire3 = 0;
|
||||
@@ -321,8 +339,8 @@ wire key_strobe;
|
||||
always @(posedge clk_sys) begin
|
||||
if(key_strobe) begin
|
||||
case(key_code)
|
||||
'h75: btn_up <= key_pressed; // up
|
||||
'h72: btn_down <= key_pressed; // down
|
||||
// 'h75: btn_up <= key_pressed; // up
|
||||
// 'h72: btn_down <= key_pressed; // down
|
||||
'h6B: btn_left <= key_pressed; // left
|
||||
'h74: btn_right <= key_pressed; // right
|
||||
'h76: btn_coin <= key_pressed; // ESC
|
||||
|
||||
@@ -0,0 +1,574 @@
|
||||
-- changes for seperate audio outputs and enable now enables cpu access as well
|
||||
--
|
||||
-- A simulation model of YM2149 (AY-3-8910 with bells on)
|
||||
|
||||
-- Copyright (c) MikeJ - Jan 2005
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- You are responsible for any legal issues arising from your use of this code.
|
||||
--
|
||||
-- The latest version of this file can be found at: www.fpgaarcade.com
|
||||
--
|
||||
-- Email support@fpgaarcade.com
|
||||
--
|
||||
-- Revision list
|
||||
--
|
||||
-- version 001 initial release
|
||||
--
|
||||
-- Clues from MAME sound driver and Kazuhiro TSUJIKAWA
|
||||
--
|
||||
-- These are the measured outputs from a real chip for a single Isolated channel into a 1K load (V)
|
||||
-- vol 15 .. 0
|
||||
-- 3.27 2.995 2.741 2.588 2.452 2.372 2.301 2.258 2.220 2.198 2.178 2.166 2.155 2.148 2.141 2.132
|
||||
-- As the envelope volume is 5 bit, I have fitted a curve to the not quite log shape in order
|
||||
-- to produced all the required values.
|
||||
-- (The first part of the curve is a bit steeper and the last bit is more linear than expected)
|
||||
--
|
||||
-- NOTE, this component uses LINEAR mixing of the three analogue channels, and is only
|
||||
-- accurate for designs where the outputs are buffered and not simply wired together.
|
||||
-- The ouput level is more complex in that case and requires a larger table.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity YM2149 is
|
||||
port (
|
||||
-- data bus
|
||||
I_DA : in std_logic_vector(7 downto 0);
|
||||
O_DA : out std_logic_vector(7 downto 0);
|
||||
O_DA_OE_L : out std_logic;
|
||||
-- control
|
||||
I_A9_L : in std_logic;
|
||||
I_A8 : in std_logic;
|
||||
I_BDIR : in std_logic;
|
||||
I_BC2 : in std_logic;
|
||||
I_BC1 : in std_logic;
|
||||
I_SEL_L : in std_logic;
|
||||
|
||||
O_AUDIO : out std_logic_vector(7 downto 0);
|
||||
O_CHAN : out std_logic_vector(1 downto 0);
|
||||
-- port a
|
||||
I_IOA : in std_logic_vector(7 downto 0);
|
||||
O_IOA : out std_logic_vector(7 downto 0);
|
||||
O_IOA_OE_L : out std_logic;
|
||||
-- port b
|
||||
I_IOB : in std_logic_vector(7 downto 0);
|
||||
O_IOB : out std_logic_vector(7 downto 0);
|
||||
O_IOB_OE_L : out std_logic;
|
||||
|
||||
ENA : in std_logic; -- clock enable for higher speed operation
|
||||
RESET_L : in std_logic;
|
||||
CLK : in std_logic -- note 6 Mhz
|
||||
);
|
||||
end;
|
||||
|
||||
architecture RTL of YM2149 is
|
||||
type array_16x8 is array (0 to 15) of std_logic_vector( 7 downto 0);
|
||||
type array_3x12 is array (1 to 3) of std_logic_vector(11 downto 0);
|
||||
|
||||
signal cnt_div : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal cnt_div_t1 : std_logic_vector(3 downto 0);
|
||||
signal noise_div : std_logic := '0';
|
||||
signal ena_div : std_logic;
|
||||
signal ena_div_noise : std_logic;
|
||||
signal poly17 : std_logic_vector(16 downto 0) := (others => '0');
|
||||
|
||||
-- registers
|
||||
signal addr : std_logic_vector(7 downto 0);
|
||||
signal busctrl_addr : std_logic;
|
||||
signal busctrl_we : std_logic;
|
||||
signal busctrl_re : std_logic;
|
||||
|
||||
signal reg : array_16x8;
|
||||
signal env_reset : std_logic;
|
||||
signal ioa_inreg : std_logic_vector(7 downto 0);
|
||||
signal iob_inreg : std_logic_vector(7 downto 0);
|
||||
|
||||
signal noise_gen_cnt : std_logic_vector(4 downto 0);
|
||||
signal noise_gen_op : std_logic;
|
||||
signal tone_gen_cnt : array_3x12 := (others => (others => '0'));
|
||||
signal tone_gen_op : std_logic_vector(3 downto 1) := "000";
|
||||
|
||||
signal env_gen_cnt : std_logic_vector(15 downto 0);
|
||||
signal env_ena : std_logic;
|
||||
signal env_hold : std_logic;
|
||||
signal env_inc : std_logic;
|
||||
signal env_vol : std_logic_vector(4 downto 0);
|
||||
|
||||
signal tone_ena_l : std_logic;
|
||||
signal tone_src : std_logic;
|
||||
signal noise_ena_l : std_logic;
|
||||
signal chan_vol : std_logic_vector(4 downto 0);
|
||||
|
||||
signal dac_amp : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
-- cpu i/f
|
||||
p_busdecode : process(I_BDIR, I_BC2, I_BC1, addr, I_A9_L, I_A8)
|
||||
variable cs : std_logic;
|
||||
variable sel : std_logic_vector(2 downto 0);
|
||||
begin
|
||||
-- BDIR BC2 BC1 MODE
|
||||
-- 0 0 0 inactive
|
||||
-- 0 0 1 address
|
||||
-- 0 1 0 inactive
|
||||
-- 0 1 1 read
|
||||
-- 1 0 0 address
|
||||
-- 1 0 1 inactive
|
||||
-- 1 1 0 write
|
||||
-- 1 1 1 read
|
||||
busctrl_addr <= '0';
|
||||
busctrl_we <= '0';
|
||||
busctrl_re <= '0';
|
||||
|
||||
cs := '0';
|
||||
if (I_A9_L = '0') and (I_A8 = '1') and (addr(7 downto 4) = "0000") then
|
||||
cs := '1';
|
||||
end if;
|
||||
|
||||
sel := (I_BDIR & I_BC2 & I_BC1);
|
||||
case sel is
|
||||
when "000" => null;
|
||||
when "001" => busctrl_addr <= '1';
|
||||
when "010" => null;
|
||||
when "011" => busctrl_re <= cs;
|
||||
when "100" => busctrl_addr <= '1';
|
||||
when "101" => null;
|
||||
when "110" => busctrl_we <= cs;
|
||||
when "111" => busctrl_addr <= '1';
|
||||
when others => null;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
p_oe : process(busctrl_re)
|
||||
begin
|
||||
-- if we are emulating a real chip, maybe clock this to fake up the tristate typ delay of 100ns
|
||||
O_DA_OE_L <= not (busctrl_re);
|
||||
end process;
|
||||
|
||||
--
|
||||
-- CLOCKED
|
||||
--
|
||||
p_waddr : process(RESET_L, CLK)
|
||||
begin
|
||||
-- looks like registers are latches in real chip, but the address is caught at the end of the address state.
|
||||
if (RESET_L = '0') then
|
||||
addr <= (others => '0');
|
||||
elsif rising_edge(CLK) then
|
||||
if (ENA = '1') then
|
||||
if (busctrl_addr = '1') then
|
||||
addr <= I_DA;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_wdata : process(RESET_L, CLK)
|
||||
begin
|
||||
if (RESET_L = '0') then
|
||||
reg <= (others => (others => '0'));
|
||||
env_reset <= '1';
|
||||
elsif rising_edge(CLK) then
|
||||
if (ENA = '1') then
|
||||
env_reset <= '0';
|
||||
if (busctrl_we = '1') then
|
||||
case addr(3 downto 0) is
|
||||
when x"0" => reg(0) <= I_DA;
|
||||
when x"1" => reg(1) <= I_DA;
|
||||
when x"2" => reg(2) <= I_DA;
|
||||
when x"3" => reg(3) <= I_DA;
|
||||
when x"4" => reg(4) <= I_DA;
|
||||
when x"5" => reg(5) <= I_DA;
|
||||
when x"6" => reg(6) <= I_DA;
|
||||
when x"7" => reg(7) <= I_DA;
|
||||
when x"8" => reg(8) <= I_DA;
|
||||
when x"9" => reg(9) <= I_DA;
|
||||
when x"A" => reg(10) <= I_DA;
|
||||
when x"B" => reg(11) <= I_DA;
|
||||
when x"C" => reg(12) <= I_DA;
|
||||
when x"D" => reg(13) <= I_DA; env_reset <= '1';
|
||||
when x"E" => reg(14) <= I_DA;
|
||||
when x"F" => reg(15) <= I_DA;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_rdata : process(busctrl_re, addr, reg, ioa_inreg, iob_inreg)
|
||||
begin
|
||||
O_DA <= (others => '0'); -- 'X'
|
||||
if (busctrl_re = '1') then -- not necessary, but useful for putting 'X's in the simulator
|
||||
case addr(3 downto 0) is
|
||||
when x"0" => O_DA <= reg(0) ;
|
||||
when x"1" => O_DA <= "0000" & reg(1)(3 downto 0) ;
|
||||
when x"2" => O_DA <= reg(2) ;
|
||||
when x"3" => O_DA <= "0000" & reg(3)(3 downto 0) ;
|
||||
when x"4" => O_DA <= reg(4) ;
|
||||
when x"5" => O_DA <= "0000" & reg(5)(3 downto 0) ;
|
||||
when x"6" => O_DA <= "000" & reg(6)(4 downto 0) ;
|
||||
when x"7" => O_DA <= reg(7) ;
|
||||
when x"8" => O_DA <= "000" & reg(8)(4 downto 0) ;
|
||||
when x"9" => O_DA <= "000" & reg(9)(4 downto 0) ;
|
||||
when x"A" => O_DA <= "000" & reg(10)(4 downto 0) ;
|
||||
when x"B" => O_DA <= reg(11);
|
||||
when x"C" => O_DA <= reg(12);
|
||||
when x"D" => O_DA <= "0000" & reg(13)(3 downto 0);
|
||||
when x"E" => if (reg(7)(6) = '0') then -- input
|
||||
O_DA <= ioa_inreg;
|
||||
else
|
||||
O_DA <= reg(14); -- read output reg
|
||||
end if;
|
||||
when x"F" => if (Reg(7)(7) = '0') then
|
||||
O_DA <= iob_inreg;
|
||||
else
|
||||
O_DA <= reg(15);
|
||||
end if;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
--
|
||||
p_divider : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
-- / 8 when SEL is high and /16 when SEL is low
|
||||
if (ENA = '1') then
|
||||
ena_div <= '0';
|
||||
ena_div_noise <= '0';
|
||||
if (cnt_div = "0000") then
|
||||
cnt_div <= (not I_SEL_L) & "111";
|
||||
ena_div <= '1';
|
||||
|
||||
noise_div <= not noise_div;
|
||||
if (noise_div = '1') then
|
||||
ena_div_noise <= '1';
|
||||
end if;
|
||||
else
|
||||
cnt_div <= cnt_div - "1";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_noise_gen : process
|
||||
variable noise_gen_comp : std_logic_vector(4 downto 0);
|
||||
variable poly17_zero : std_logic;
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (reg(6)(4 downto 0) = "00000") then
|
||||
noise_gen_comp := "00000";
|
||||
else
|
||||
noise_gen_comp := (reg(6)(4 downto 0) - "1");
|
||||
end if;
|
||||
|
||||
poly17_zero := '0';
|
||||
if (poly17 = "00000000000000000") then poly17_zero := '1'; end if;
|
||||
|
||||
if (ENA = '1') then
|
||||
if (ena_div_noise = '1') then -- divider ena
|
||||
|
||||
if (noise_gen_cnt >= noise_gen_comp) then
|
||||
noise_gen_cnt <= "00000";
|
||||
poly17 <= (poly17(0) xor poly17(2) xor poly17_zero) & poly17(16 downto 1);
|
||||
else
|
||||
noise_gen_cnt <= (noise_gen_cnt + "1");
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
noise_gen_op <= poly17(0);
|
||||
|
||||
p_tone_gens : process
|
||||
variable tone_gen_freq : array_3x12;
|
||||
variable tone_gen_comp : array_3x12;
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
-- looks like real chips count up - we need to get the Exact behaviour ..
|
||||
tone_gen_freq(1) := reg(1)(3 downto 0) & reg(0);
|
||||
tone_gen_freq(2) := reg(3)(3 downto 0) & reg(2);
|
||||
tone_gen_freq(3) := reg(5)(3 downto 0) & reg(4);
|
||||
-- period 0 = period 1
|
||||
for i in 1 to 3 loop
|
||||
if (tone_gen_freq(i) = x"000") then
|
||||
tone_gen_comp(i) := x"000";
|
||||
else
|
||||
tone_gen_comp(i) := (tone_gen_freq(i) - "1");
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
if (ENA = '1') then
|
||||
for i in 1 to 3 loop
|
||||
if (ena_div = '1') then -- divider ena
|
||||
|
||||
if (tone_gen_cnt(i) >= tone_gen_comp(i)) then
|
||||
tone_gen_cnt(i) <= x"000";
|
||||
tone_gen_op(i) <= not tone_gen_op(i);
|
||||
else
|
||||
tone_gen_cnt(i) <= (tone_gen_cnt(i) + "1");
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_envelope_freq : process
|
||||
variable env_gen_freq : std_logic_vector(15 downto 0);
|
||||
variable env_gen_comp : std_logic_vector(15 downto 0);
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
env_gen_freq := reg(12) & reg(11);
|
||||
-- envelope freqs 1 and 0 are the same.
|
||||
if (env_gen_freq = x"0000") then
|
||||
env_gen_comp := x"0000";
|
||||
else
|
||||
env_gen_comp := (env_gen_freq - "1");
|
||||
end if;
|
||||
|
||||
if (ENA = '1') then
|
||||
env_ena <= '0';
|
||||
if (ena_div = '1') then -- divider ena
|
||||
if (env_gen_cnt >= env_gen_comp) then
|
||||
env_gen_cnt <= x"0000";
|
||||
env_ena <= '1';
|
||||
else
|
||||
env_gen_cnt <= (env_gen_cnt + "1");
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_envelope_shape : process(env_reset, reg, CLK)
|
||||
variable is_bot : boolean;
|
||||
variable is_bot_p1 : boolean;
|
||||
variable is_top_m1 : boolean;
|
||||
variable is_top : boolean;
|
||||
begin
|
||||
-- envelope shapes
|
||||
-- C AtAlH
|
||||
-- 0 0 x x \___
|
||||
--
|
||||
-- 0 1 x x /___
|
||||
--
|
||||
-- 1 0 0 0 \\\\
|
||||
--
|
||||
-- 1 0 0 1 \___
|
||||
--
|
||||
-- 1 0 1 0 \/\/
|
||||
-- ___
|
||||
-- 1 0 1 1 \
|
||||
--
|
||||
-- 1 1 0 0 ////
|
||||
-- ___
|
||||
-- 1 1 0 1 /
|
||||
--
|
||||
-- 1 1 1 0 /\/\
|
||||
--
|
||||
-- 1 1 1 1 /___
|
||||
if (env_reset = '1') then
|
||||
-- load initial state
|
||||
if (reg(13)(2) = '0') then -- attack
|
||||
env_vol <= "11111";
|
||||
env_inc <= '0'; -- -1
|
||||
else
|
||||
env_vol <= "00000";
|
||||
env_inc <= '1'; -- +1
|
||||
end if;
|
||||
env_hold <= '0';
|
||||
|
||||
elsif rising_edge(CLK) then
|
||||
is_bot := (env_vol = "00000");
|
||||
is_bot_p1 := (env_vol = "00001");
|
||||
is_top_m1 := (env_vol = "11110");
|
||||
is_top := (env_vol = "11111");
|
||||
|
||||
if (ENA = '1') then
|
||||
if (env_ena = '1') then
|
||||
if (env_hold = '0') then
|
||||
if (env_inc = '1') then
|
||||
env_vol <= (env_vol + "00001");
|
||||
else
|
||||
env_vol <= (env_vol + "11111");
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- envelope shape control.
|
||||
if (reg(13)(3) = '0') then
|
||||
if (env_inc = '0') then -- down
|
||||
if is_bot_p1 then env_hold <= '1'; end if;
|
||||
else
|
||||
if is_top then env_hold <= '1'; end if;
|
||||
end if;
|
||||
else
|
||||
if (reg(13)(0) = '1') then -- hold = 1
|
||||
if (env_inc = '0') then -- down
|
||||
if (reg(13)(1) = '1') then -- alt
|
||||
if is_bot then env_hold <= '1'; end if;
|
||||
else
|
||||
if is_bot_p1 then env_hold <= '1'; end if;
|
||||
end if;
|
||||
else
|
||||
if (reg(13)(1) = '1') then -- alt
|
||||
if is_top then env_hold <= '1'; end if;
|
||||
else
|
||||
if is_top_m1 then env_hold <= '1'; end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
elsif (reg(13)(1) = '1') then -- alternate
|
||||
if (env_inc = '0') then -- down
|
||||
if is_bot_p1 then env_hold <= '1'; end if;
|
||||
if is_bot then env_hold <= '0'; env_inc <= '1'; end if;
|
||||
else
|
||||
if is_top_m1 then env_hold <= '1'; end if;
|
||||
if is_top then env_hold <= '0'; env_inc <= '0'; end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_chan_mixer : process(cnt_div, reg, tone_gen_op)
|
||||
begin
|
||||
tone_ena_l <= '1'; tone_src <= '1';
|
||||
noise_ena_l <= '1'; chan_vol <= "00000";
|
||||
case cnt_div(1 downto 0) is
|
||||
when "00" =>
|
||||
tone_ena_l <= reg(7)(0); tone_src <= tone_gen_op(1); chan_vol <= reg(8)(4 downto 0);
|
||||
noise_ena_l <= reg(7)(3);
|
||||
when "01" =>
|
||||
tone_ena_l <= reg(7)(1); tone_src <= tone_gen_op(2); chan_vol <= reg(9)(4 downto 0);
|
||||
noise_ena_l <= reg(7)(4);
|
||||
when "10" =>
|
||||
tone_ena_l <= reg(7)(2); tone_src <= tone_gen_op(3); chan_vol <= reg(10)(4 downto 0);
|
||||
noise_ena_l <= reg(7)(5);
|
||||
when "11" => null; -- tone gen outputs become valid on this clock
|
||||
when others => null;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
p_op_mixer : process
|
||||
variable chan_mixed : std_logic;
|
||||
variable chan_amp : std_logic_vector(4 downto 0);
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then
|
||||
|
||||
chan_mixed := (tone_ena_l or tone_src) and (noise_ena_l or noise_gen_op);
|
||||
|
||||
chan_amp := (others => '0');
|
||||
if (chan_mixed = '1') then
|
||||
if (chan_vol(4) = '0') then
|
||||
if (chan_vol(3 downto 0) = "0000") then -- nothing is easy ! make sure quiet is quiet
|
||||
chan_amp := "00000";
|
||||
else
|
||||
chan_amp := chan_vol(3 downto 0) & '1'; -- make sure level 31 (env) = level 15 (tone)
|
||||
end if;
|
||||
else
|
||||
chan_amp := env_vol(4 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
dac_amp <= x"00";
|
||||
case chan_amp is
|
||||
when "11111" => dac_amp <= x"FF";
|
||||
when "11110" => dac_amp <= x"D9";
|
||||
when "11101" => dac_amp <= x"BA";
|
||||
when "11100" => dac_amp <= x"9F";
|
||||
when "11011" => dac_amp <= x"88";
|
||||
when "11010" => dac_amp <= x"74";
|
||||
when "11001" => dac_amp <= x"63";
|
||||
when "11000" => dac_amp <= x"54";
|
||||
when "10111" => dac_amp <= x"48";
|
||||
when "10110" => dac_amp <= x"3D";
|
||||
when "10101" => dac_amp <= x"34";
|
||||
when "10100" => dac_amp <= x"2C";
|
||||
when "10011" => dac_amp <= x"25";
|
||||
when "10010" => dac_amp <= x"1F";
|
||||
when "10001" => dac_amp <= x"1A";
|
||||
when "10000" => dac_amp <= x"16";
|
||||
when "01111" => dac_amp <= x"13";
|
||||
when "01110" => dac_amp <= x"10";
|
||||
when "01101" => dac_amp <= x"0D";
|
||||
when "01100" => dac_amp <= x"0B";
|
||||
when "01011" => dac_amp <= x"09";
|
||||
when "01010" => dac_amp <= x"08";
|
||||
when "01001" => dac_amp <= x"07";
|
||||
when "01000" => dac_amp <= x"06";
|
||||
when "00111" => dac_amp <= x"05";
|
||||
when "00110" => dac_amp <= x"04";
|
||||
when "00101" => dac_amp <= x"03";
|
||||
when "00100" => dac_amp <= x"03";
|
||||
when "00011" => dac_amp <= x"02";
|
||||
when "00010" => dac_amp <= x"02";
|
||||
when "00001" => dac_amp <= x"01";
|
||||
when "00000" => dac_amp <= x"00";
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
cnt_div_t1 <= cnt_div;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_audio_output : process(RESET_L, CLK)
|
||||
begin
|
||||
if (RESET_L = '0') then
|
||||
O_AUDIO <= (others => '0');
|
||||
O_CHAN <= (others => '0');
|
||||
elsif rising_edge(CLK) then
|
||||
|
||||
if (ENA = '1') then
|
||||
O_AUDIO <= dac_amp(7 downto 0);
|
||||
O_CHAN <= cnt_div_t1(1 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
p_io_ports : process(reg)
|
||||
begin
|
||||
O_IOA <= reg(14);
|
||||
O_IOA_OE_L <= not reg(7)(6);
|
||||
O_IOB <= reg(15);
|
||||
O_IOB_OE_L <= not reg(7)(7);
|
||||
end process;
|
||||
|
||||
p_io_ports_inreg : process
|
||||
begin
|
||||
wait until rising_edge(CLK);
|
||||
if (ENA = '1') then -- resync
|
||||
ioa_inreg <= I_IOA;
|
||||
iob_inreg <= I_IOB;
|
||||
end if;
|
||||
end process;
|
||||
end architecture RTL;
|
||||
@@ -936,4 +936,32 @@ port map(
|
||||
q => palette_do
|
||||
);
|
||||
|
||||
-- Midway Super Sound board
|
||||
sound_board : entity work.super_sound_board
|
||||
port map(
|
||||
clock_40 => clock_40,
|
||||
reset => reset,
|
||||
|
||||
main_cpu_addr => cpu_addr(7 downto 0),
|
||||
|
||||
ssio_iowe => ssio_iowe,
|
||||
ssio_di => cpu_do,
|
||||
ssio_do => ssio_do,
|
||||
|
||||
input_0 => input_0,
|
||||
input_1 => input_1,
|
||||
input_2 => input_2,
|
||||
input_3 => input_3,
|
||||
input_4 => input_4,
|
||||
|
||||
separate_audio => separate_audio,
|
||||
audio_out_l => audio_out_l,
|
||||
audio_out_r => audio_out_r,
|
||||
|
||||
-- ROM sockets are unpopulated
|
||||
cpu_rom_addr => open,
|
||||
cpu_rom_do => x"FF",
|
||||
|
||||
dbg_cpu_addr => open --dbg_cpu_addr
|
||||
);
|
||||
end struct;
|
||||
@@ -0,0 +1,24 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all,ieee.numeric_std.all;
|
||||
|
||||
entity midssio_82s123 is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector(4 downto 0);
|
||||
data : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture prom of midssio_82s123 is
|
||||
type rom is array(0 to 31) of std_logic_vector(7 downto 0);
|
||||
signal rom_data: rom := (
|
||||
X"FF",X"FF",X"FF",X"FF",X"FF",X"7F",X"FF",X"FF",X"FE",X"FF",X"FF",X"FD",X"FF",X"FE",X"FF",X"F7",
|
||||
X"FB",X"EF",X"6D",X"07",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF");
|
||||
begin
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
data <= rom_data(to_integer(unsigned(addr)));
|
||||
end if;
|
||||
end process;
|
||||
end architecture;
|
||||
@@ -0,0 +1,46 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity spinner is
|
||||
port(
|
||||
clock_40 : in std_logic;
|
||||
reset : in std_logic;
|
||||
btn_left : in std_logic;
|
||||
btn_right : in std_logic;
|
||||
btn_acc : in std_logic; -- speed up button
|
||||
ctc_zc_to_2 : in std_logic;
|
||||
spin_angle : out std_logic_vector(6 downto 0)
|
||||
);
|
||||
end spinner;
|
||||
|
||||
architecture rtl of spinner is
|
||||
|
||||
signal ctc_zc_to_2_r : std_logic;
|
||||
signal spin_count : std_logic_vector(9 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
spin_angle <= spin_count(9 downto 3);
|
||||
|
||||
process (clock_40, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
spin_count <= (others => '0');
|
||||
elsif rising_edge(clock_40) then
|
||||
ctc_zc_to_2_r <= ctc_zc_to_2;
|
||||
|
||||
if ctc_zc_to_2_r ='0' and ctc_zc_to_2 = '1' then
|
||||
if btn_acc = '0' then -- space -- speed up
|
||||
if btn_left = '1' then spin_count <= spin_count - 40; end if; -- left
|
||||
if btn_right = '1' then spin_count <= spin_count + 40; end if; -- right
|
||||
else
|
||||
if btn_left = '1' then spin_count <= spin_count - 55; end if;
|
||||
if btn_right = '1' then spin_count <= spin_count + 55; end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
@@ -0,0 +1,556 @@
|
||||
---------------------------------------------------------------------------------
|
||||
-- Midway Super Sound Board by Dar (darfpga@aol.fr) (19/10/2019)
|
||||
-- http://darfpga.blogspot.fr
|
||||
---------------------------------------------------------------------------------
|
||||
-- gen_ram.vhd & io_ps2_keyboard
|
||||
--------------------------------
|
||||
-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
|
||||
-- http://www.syntiac.com/fpga64.html
|
||||
---------------------------------------------------------------------------------
|
||||
-- T80/T80se - Version : 304
|
||||
-----------------------------
|
||||
-- Z80 compatible microprocessor core
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
---------------------------------------------------------------------------------
|
||||
-- YM2149 (AY-3-8910)
|
||||
-- Copyright (c) MikeJ - Jan 2005
|
||||
---------------------------------------------------------------------------------
|
||||
-- Educational use only
|
||||
-- Do not redistribute synthetized file with roms
|
||||
-- Do not redistribute roms whatever the form
|
||||
-- Use at your own risk
|
||||
---------------------------------------------------------------------------------
|
||||
--
|
||||
-- SOUND : 1xZ80 @ 2.0MHz CPU accessing its program rom, working ram, 2x-AY3-8910
|
||||
-- 8Kx8bits program rom
|
||||
-- 1Kx8bits working ram
|
||||
--
|
||||
-- 1xAY-3-8910
|
||||
-- 3 sound channels
|
||||
--
|
||||
-- 1xAY-3-8910
|
||||
-- 3 sound channels
|
||||
--
|
||||
-- 6 sound modulation (required 8MHz signal => 40MHz/5)
|
||||
-- 2 global volume control (not activated - not sure it was used for kick )
|
||||
--
|
||||
-- I/O :
|
||||
-- 4x8bits command registers from main cpu board (IRAM)
|
||||
-- 1x8bits status registers to main cpu board (STAT)
|
||||
-- 5x8bits input buffers to main cpu board (IP0-IP5)
|
||||
-- 2x8bits output registers from main cpu board (OP0/OP4)
|
||||
--
|
||||
---------------------------------------------------------------------------------
|
||||
-- Schematics remarks :
|
||||
-- Not sure global volume are used => both deactivated
|
||||
-- Not sure if global channels are mixed together or not => allow for
|
||||
-- external control mixed/separated
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity super_sound_board is
|
||||
port(
|
||||
clock_40 : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
main_cpu_addr : in std_logic_vector(7 downto 0);
|
||||
|
||||
ssio_iowe : in std_logic;
|
||||
ssio_di : in std_logic_vector(7 downto 0);
|
||||
ssio_do : out std_logic_vector(7 downto 0);
|
||||
|
||||
input_0 : in std_logic_vector(7 downto 0);
|
||||
input_1 : in std_logic_vector(7 downto 0);
|
||||
input_2 : in std_logic_vector(7 downto 0);
|
||||
input_3 : in std_logic_vector(7 downto 0);
|
||||
input_4 : in std_logic_vector(7 downto 0);
|
||||
|
||||
separate_audio : in std_logic;
|
||||
|
||||
audio_out_l : out std_logic_vector(15 downto 0);
|
||||
audio_out_r : out std_logic_vector(15 downto 0);
|
||||
|
||||
cpu_rom_addr : out std_logic_vector(13 downto 0);
|
||||
cpu_rom_do : in std_logic_vector(7 downto 0);
|
||||
|
||||
dbg_cpu_addr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end super_sound_board;
|
||||
|
||||
architecture struct of super_sound_board is
|
||||
|
||||
signal reset_n : std_logic;
|
||||
signal clock_snd : std_logic;
|
||||
signal clock_sndn: std_logic;
|
||||
|
||||
signal clock_cnt1 : std_logic_vector(4 downto 0) := "00000";
|
||||
|
||||
signal cpu_ena : std_logic;
|
||||
signal ena_4Mhz : std_logic;
|
||||
signal clk_8Mhz : std_logic;
|
||||
|
||||
signal cpu_addr : std_logic_vector(15 downto 0);
|
||||
signal cpu_di : std_logic_vector( 7 downto 0);
|
||||
signal cpu_do : std_logic_vector( 7 downto 0);
|
||||
signal cpu_wr_n : std_logic;
|
||||
signal cpu_rd_n : std_logic;
|
||||
signal cpu_mreq_n : std_logic;
|
||||
signal cpu_ioreq_n : std_logic;
|
||||
signal cpu_irq_n : std_logic;
|
||||
signal cpu_m1_n : std_logic;
|
||||
|
||||
-- signal cpu_rom_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal wram_we : std_logic;
|
||||
signal wram_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal iram_0_do : std_logic_vector( 7 downto 0);
|
||||
signal iram_1_do : std_logic_vector( 7 downto 0);
|
||||
signal iram_2_do : std_logic_vector( 7 downto 0);
|
||||
signal iram_3_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal ssio_status : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal div_E11 : std_logic_vector(2 downto 0); -- binary counter 3msb of E11 - 74161
|
||||
signal div_D11 : std_logic_vector(3 downto 0); -- decade counter - D11 - 74160
|
||||
signal div_C12 : std_logic_vector(6 downto 0); -- stage ripple counter - C12 - MC140247
|
||||
signal clr_int : std_logic;
|
||||
|
||||
signal ay1_audio_chan : std_logic_vector( 1 downto 0);
|
||||
signal ay1_audio_muxed: std_logic_vector( 7 downto 0);
|
||||
signal ay1_bc1 : std_logic;
|
||||
signal ay1_bdir : std_logic;
|
||||
signal ay1_do : std_logic_vector( 7 downto 0);
|
||||
signal ay1_cs : std_logic;
|
||||
signal ay1_port_a : std_logic_vector( 7 downto 0);
|
||||
signal ay1_port_b : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal ay2_audio_chan : std_logic_vector( 1 downto 0);
|
||||
signal ay2_audio_muxed: std_logic_vector( 7 downto 0);
|
||||
signal ay2_bc1 : std_logic;
|
||||
signal ay2_bdir : std_logic;
|
||||
signal ay2_do : std_logic_vector( 7 downto 0);
|
||||
signal ay2_cs : std_logic;
|
||||
signal ay2_port_a : std_logic_vector( 7 downto 0);
|
||||
signal ay2_port_b : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal ssio_82s123_addr : std_logic_vector(4 downto 0);
|
||||
signal ssio_82s123_do : std_logic_vector(7 downto 0);
|
||||
signal ssio_modulation_clock : std_logic;
|
||||
signal ssio_modulation_clock_r : std_logic;
|
||||
signal ssio_modulation_load : std_logic;
|
||||
signal modulation_counter_a1 : std_logic_vector(3 downto 0);
|
||||
signal modulation_counter_b1 : std_logic_vector(3 downto 0);
|
||||
signal modulation_counter_c1 : std_logic_vector(3 downto 0);
|
||||
signal modulation_counter_a2 : std_logic_vector(3 downto 0);
|
||||
signal modulation_counter_b2 : std_logic_vector(3 downto 0);
|
||||
signal modulation_counter_c2 : std_logic_vector(3 downto 0);
|
||||
|
||||
signal ch_a1 : std_logic_vector(7 downto 0);
|
||||
signal ch_b1 : std_logic_vector(7 downto 0);
|
||||
signal ch_c1 : std_logic_vector(7 downto 0);
|
||||
signal ch_a2 : std_logic_vector(7 downto 0);
|
||||
signal ch_b2 : std_logic_vector(7 downto 0);
|
||||
signal ch_c2 : std_logic_vector(7 downto 0);
|
||||
|
||||
-- K volume data : 148 138 127 112 95 72 42 0
|
||||
type bytes_array is array(0 to 7) of std_logic_vector(7 downto 0);
|
||||
signal K_volume : bytes_array := (X"94",X"8A",X"7F",X"70",X"5F",X"48",X"2A",X"00");
|
||||
|
||||
signal volume_ch1 : std_logic_vector(7 downto 0);
|
||||
signal volume_ch2 : std_logic_vector(7 downto 0);
|
||||
|
||||
signal snd_1 : std_logic_vector(17 downto 0);
|
||||
signal snd_2 : std_logic_vector(17 downto 0);
|
||||
signal snd_mono : std_logic_vector(18 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
clock_snd <= clock_40;
|
||||
clock_sndn <= not clock_40;
|
||||
reset_n <= not reset;
|
||||
|
||||
-- debug
|
||||
process (reset, clock_snd)
|
||||
begin
|
||||
if rising_edge(clock_snd) and cpu_ena ='1' and cpu_mreq_n ='0' then
|
||||
dbg_cpu_addr <= cpu_addr;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- make enables clock from clock_snd
|
||||
process (clock_snd, reset)
|
||||
begin
|
||||
if reset='1' then
|
||||
clock_cnt1 <= (others=>'0');
|
||||
clk_8Mhz <= '0';
|
||||
else
|
||||
if rising_edge(clock_snd) then
|
||||
if clock_cnt1 = "10011" then -- divide by 20
|
||||
clock_cnt1 <= (others=>'0');
|
||||
else
|
||||
clock_cnt1 <= clock_cnt1 + 1;
|
||||
end if;
|
||||
|
||||
if clock_cnt1 = "10011" or
|
||||
clock_cnt1 = "00100" or
|
||||
clock_cnt1 = "01001" or
|
||||
clock_cnt1 = "01110" then
|
||||
|
||||
clk_8Mhz <= not clk_8Mhz; -- (50% duty cycle)
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
--
|
||||
cpu_ena <= '1' when clock_cnt1 = "00000" else '0'; -- (2.0MHz)
|
||||
|
||||
ena_4Mhz <= '1' when clock_cnt1 = "00000" or
|
||||
clock_cnt1 = "01010" else '0'; -- (4.0MHz)
|
||||
|
||||
------------------------------------------
|
||||
-- cpu data input with address decoding --
|
||||
------------------------------------------
|
||||
cpu_di <= cpu_rom_do when cpu_mreq_n = '0' and cpu_addr(15 downto 14) = "00" else -- 0x0000-0x3FFF
|
||||
wram_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12) = X"8" else -- 0x8000-0x83FF
|
||||
iram_0_do when cpu_mreq_n = '0' and cpu_addr(15 downto 0)= X"9000" else
|
||||
iram_1_do when cpu_mreq_n = '0' and cpu_addr(15 downto 0)= X"9001" else
|
||||
iram_2_do when cpu_mreq_n = '0' and cpu_addr(15 downto 0)= X"9002" else
|
||||
iram_3_do when cpu_mreq_n = '0' and cpu_addr(15 downto 0)= X"9003" else
|
||||
ay1_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12)= X"A" else
|
||||
ay2_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12)= X"B" else
|
||||
x"FF" when cpu_mreq_n = '0' and cpu_addr(15 downto 12)= X"F" else -- 0xF000 (sw3 dip - D14)
|
||||
X"FF";
|
||||
|
||||
------------------------------------------
|
||||
-- write enable to working ram from CPU --
|
||||
-- clear interrupt, cs for AY3-8910 --
|
||||
-- ssio output to main cpu (read input) --
|
||||
-- ssio status to main cpu --
|
||||
------------------------------------------
|
||||
wram_we <= '1' when cpu_mreq_n = '0' and cpu_wr_n = '0' and cpu_addr(15 downto 12) = X"8" else '0'; -- 0x8000-0x83FF
|
||||
clr_int <= '1' when cpu_mreq_n = '0' and cpu_rd_n = '0' and cpu_addr(15 downto 12) = X"E" else '0'; -- 0xE000-0xEFFF
|
||||
|
||||
ay1_cs <= '1' when cpu_mreq_n = '0' and (cpu_rd_n = '0' or cpu_wr_n = '0') and cpu_addr(15 downto 12) = X"A" else '0'; -- 0xA000-0xAFFF
|
||||
ay2_cs <= '1' when cpu_mreq_n = '0' and (cpu_rd_n = '0' or cpu_wr_n = '0') and cpu_addr(15 downto 12) = X"B" else '0'; -- 0xB000-0xBFFF
|
||||
|
||||
ay1_bdir <= not (not ay1_cs or cpu_addr(0) );
|
||||
ay1_bc1 <= not (not ay1_cs or cpu_addr(1) );
|
||||
ay2_bdir <= not (not ay2_cs or cpu_addr(0) );
|
||||
ay2_bc1 <= not (not ay2_cs or cpu_addr(1) );
|
||||
|
||||
ssio_do <= input_0 when main_cpu_addr(2 downto 0) = "000" else -- Input 0 -- players, coins, ...
|
||||
input_1 when main_cpu_addr(2 downto 0) = "001" else -- Input 1
|
||||
input_2 when main_cpu_addr(2 downto 0) = "010" else -- Input 2
|
||||
input_3 when main_cpu_addr(2 downto 0) = "011" else -- Input 3 -- sw1 dip
|
||||
input_4 when main_cpu_addr(2 downto 0) = "100" else -- Input 4
|
||||
ssio_status when main_cpu_addr(2 downto 0) = "111" else -- ssio status
|
||||
x"FF";
|
||||
|
||||
process (clock_snd)
|
||||
begin
|
||||
if rising_edge(clock_snd) then
|
||||
if cpu_wr_n = '0' and cpu_addr(15 downto 12) = X"C" then ssio_status <= cpu_do; end if; -- 0xC000-0xCFFF
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Misc registers : interrupt, counters E11/D11/C12
|
||||
------------------------------------------------------------------------
|
||||
process (clock_snd, reset, clr_int, ena_4Mhz)
|
||||
begin
|
||||
if reset = '1' then
|
||||
div_E11 <= (others => '0'); -- 3msb of E11
|
||||
div_D11 <= (others => '0'); -- decade counter
|
||||
div_C12 <= (others => '0'); -- MC14024
|
||||
else
|
||||
if rising_edge(clock_snd) then
|
||||
|
||||
if ena_4Mhz = '1' then
|
||||
|
||||
div_E11 <= div_E11 + 1;
|
||||
|
||||
if div_E11 = "111" then
|
||||
if div_D11 = "1001" then
|
||||
div_D11 <= (others => '0');
|
||||
else
|
||||
div_D11 <= div_D11 + 1;
|
||||
end if;
|
||||
|
||||
if div_D11 = "0100" then
|
||||
div_C12 <= div_C12 + 1;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
if clr_int = '1' then
|
||||
div_C12 <= (others => '0');
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_irq_n <= not div_C12(6);
|
||||
|
||||
-------------------------------
|
||||
-- sound modulation / volume --
|
||||
-------------------------------
|
||||
|
||||
ssio_82s123_addr <= div_D11 & div_E11(2);
|
||||
|
||||
--74166 8 bits shift register (D13)
|
||||
ssio_modulation_clock <= ssio_82s123_do(7-to_integer(unsigned(div_E11(1 downto 0) & clk_8Mhz)));
|
||||
ssio_modulation_load <= '1' when div_D11 = "1001" else '0';
|
||||
|
||||
-- AY-3-8910 #1
|
||||
-- ch A (pin 4) modulated by counter controled by port A3-0 (pin 18->21)
|
||||
-- ch B (pin 3) modulated by counter controled by port A7-4 (pin 14->17)
|
||||
-- ch C (pin 38) modulated by counter controled by port B3-0 (pin 10->13)
|
||||
-- mute left and right port B7 (pin 6)
|
||||
-- volume#1 contoled by port B6-4 (pin 7->9)
|
||||
|
||||
-- AY-3-8910 #2
|
||||
-- ch A (pin 4) modulated by counter controled by port A3-0 (pin 18->21)
|
||||
-- ch B (pin 3) modulated by counter controled by port A7-4 (pin 14->17)
|
||||
-- ch C (pin 38) modulated by counter controled by port B3-0 (pin 10->13)
|
||||
-- mute global port B7 (pin 6)
|
||||
-- volume#2 contoled by port B6-4 (pin 7->9)
|
||||
|
||||
-- 4051 cmos mux (D5 and E3)
|
||||
-- CBA
|
||||
-- 000 => switch X0 (pin 13) ON others OFF
|
||||
-- 001 => switch X1 (pin 14) ON others OFF
|
||||
-- ...
|
||||
-- 111 => switch X7 (pin 4) ON others OFF
|
||||
|
||||
-- Assuming R179 to R187 equivalent to
|
||||
--
|
||||
-- --------
|
||||
-- --------| R2 |-------- -- with R1 = 24k + n*4.7k
|
||||
-- ^ | -------- | ^ -- R2 = 24k
|
||||
-- | --- --- | -- R3 = (7-n)*4.7
|
||||
-- | | | | | | --
|
||||
-- Vin | | | R1 R3 | | | Vout -- n being 4051 CBA value
|
||||
-- | | | | | | --
|
||||
-- | --- --- | -- which gives
|
||||
-- | | | | -- Vout = Vin * (7-n)*4.7/(24+(7-n)*4.7)
|
||||
-- ------------------------
|
||||
--
|
||||
-- let : Vout = Vin * K(n) = Vin * (7-n)*4.7/(24+(7-n)*4.7) * 256
|
||||
--
|
||||
-- with K(n) = [148 138 127 112 95 72 42 0]
|
||||
--
|
||||
|
||||
process (clock_snd, ssio_modulation_clock, ssio_modulation_load)
|
||||
begin
|
||||
if rising_edge(clock_snd) then
|
||||
ssio_modulation_clock_r <= ssio_modulation_clock;
|
||||
|
||||
if ssio_modulation_load = '1' then
|
||||
modulation_counter_a1 <= ay1_port_a(3 downto 0);
|
||||
modulation_counter_b1 <= ay1_port_a(7 downto 4);
|
||||
modulation_counter_c1 <= ay1_port_b(3 downto 0);
|
||||
modulation_counter_a2 <= ay2_port_a(3 downto 0);
|
||||
modulation_counter_b2 <= ay2_port_a(7 downto 4);
|
||||
modulation_counter_c2 <= ay2_port_b(3 downto 0);
|
||||
else
|
||||
if ssio_modulation_clock = '1' and ssio_modulation_clock_r = '0' then
|
||||
if modulation_counter_a1 > X"0" then modulation_counter_a1 <= modulation_counter_a1 - 1; end if;
|
||||
if modulation_counter_b1 > X"0" then modulation_counter_b1 <= modulation_counter_b1 - 1; end if;
|
||||
if modulation_counter_c1 > X"0" then modulation_counter_c1 <= modulation_counter_c1 - 1; end if;
|
||||
if modulation_counter_a2 > X"0" then modulation_counter_a2 <= modulation_counter_a2 - 1; end if;
|
||||
if modulation_counter_b2 > X"0" then modulation_counter_b2 <= modulation_counter_b2 - 1; end if;
|
||||
if modulation_counter_c2 > X"0" then modulation_counter_c2 <= modulation_counter_c2 - 1; end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
case ay1_audio_chan is
|
||||
when "00" => if modulation_counter_a1 = x"0" then ch_a1 <= ay1_audio_muxed; else ch_a1 <= (others => '0'); end if;
|
||||
when "01" => if modulation_counter_b1 = x"0" then ch_b1 <= ay1_audio_muxed; else ch_b1 <= (others => '0'); end if;
|
||||
when "10" => if modulation_counter_c1 = x"0" then ch_c1 <= ay1_audio_muxed; else ch_c1 <= (others => '0'); end if;
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
case ay2_audio_chan is
|
||||
when "00" => if modulation_counter_a2 = x"0" then ch_a2 <= ay2_audio_muxed; else ch_a2 <= (others => '0'); end if;
|
||||
when "01" => if modulation_counter_b2 = x"0" then ch_b2 <= ay2_audio_muxed; else ch_b2 <= (others => '0'); end if;
|
||||
when "10" => if modulation_counter_c2 = x"0" then ch_c2 <= ay2_audio_muxed; else ch_c2 <= (others => '0'); end if;
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
-- volume_ch1 <= K_volume(to_integer(unsigned(ay1_port_b(6 downto 4))));
|
||||
-- volume_ch2 <= K_volume(to_integer(unsigned(ay2_port_b(6 downto 4))));
|
||||
-- volume_ch2 <= K_volume(to_integer(unsigned(ay1_port_b(6 downto 4)))); -- use ch1 control otherwise ch2 is always OFF!
|
||||
|
||||
volume_ch1 <= X"FF"; -- finaly don't use volume controls
|
||||
volume_ch2 <= X"FF";
|
||||
|
||||
if ay1_audio_chan = "00" then
|
||||
snd_1 <= (("00"&ch_a1) + ("00"&ch_b1) + ("00"&ch_c1)) * volume_ch1;
|
||||
end if;
|
||||
|
||||
if ay2_audio_chan = "00" then
|
||||
snd_2 <= (("00"&ch_a2) + ("00"&ch_b2) + ("00"&ch_c2)) * volume_ch2;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
snd_mono <= ('0'&snd_1) + ('0'&snd_2);
|
||||
|
||||
audio_out_l <= snd_1(17 downto 2) when separate_audio = '1' else snd_mono(18 downto 3);
|
||||
audio_out_r <= snd_2(17 downto 2) when separate_audio = '1' else snd_mono(18 downto 3);
|
||||
|
||||
------------------------------
|
||||
-- components & sound board --
|
||||
------------------------------
|
||||
|
||||
-- microprocessor Z80
|
||||
cpu : entity work.T80se
|
||||
generic map(Mode => 0, T2Write => 1, IOWait => 1)
|
||||
port map(
|
||||
RESET_n => reset_n,
|
||||
CLK_n => clock_snd,
|
||||
CLKEN => cpu_ena,
|
||||
WAIT_n => '1',
|
||||
INT_n => cpu_irq_n,
|
||||
NMI_n => '1', --cpu_nmi_n,
|
||||
BUSRQ_n => '1',
|
||||
M1_n => cpu_m1_n,
|
||||
MREQ_n => cpu_mreq_n,
|
||||
IORQ_n => cpu_ioreq_n,
|
||||
RD_n => cpu_rd_n,
|
||||
WR_n => cpu_wr_n,
|
||||
RFSH_n => open,
|
||||
HALT_n => open,
|
||||
BUSAK_n => open,
|
||||
A => cpu_addr,
|
||||
DI => cpu_di,
|
||||
DO => cpu_do
|
||||
);
|
||||
|
||||
-- cpu program ROM 0x0000-0x3FFF
|
||||
--rom_cpu : entity work.timber_sound_cpu
|
||||
--port map(
|
||||
-- clk => clock_sndn,
|
||||
-- addr => cpu_addr(13 downto 0),
|
||||
-- data => cpu_rom_do
|
||||
--);
|
||||
cpu_rom_addr <= cpu_addr(13 downto 0);
|
||||
|
||||
-- working RAM 0x8000-0x83FF
|
||||
wram : entity work.gen_ram
|
||||
generic map( dWidth => 8, aWidth => 10)
|
||||
port map(
|
||||
clk => clock_sndn,
|
||||
we => wram_we,
|
||||
addr => cpu_addr(9 downto 0),
|
||||
d => cpu_do,
|
||||
q => wram_do
|
||||
);
|
||||
|
||||
-- iram (command from main cpu to sound cpu)
|
||||
process (clock_snd, reset, ssio_iowe)
|
||||
begin
|
||||
if reset = '1' then
|
||||
iram_0_do <= (others => '0');
|
||||
iram_1_do <= (others => '0');
|
||||
iram_2_do <= (others => '0');
|
||||
iram_3_do <= (others => '0');
|
||||
else
|
||||
if rising_edge(clock_snd) then
|
||||
if ssio_iowe = '1' and main_cpu_addr(7 downto 2) = "000111" then -- 0x1C - 0x1F
|
||||
case main_cpu_addr(1 downto 0) is
|
||||
when "00" => iram_0_do <= ssio_di;
|
||||
when "01" => iram_1_do <= ssio_di;
|
||||
when "10" => iram_2_do <= ssio_di;
|
||||
when "11" => iram_3_do <= ssio_di;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- AY-3-8910 # 1
|
||||
ay_3_8910_1 : entity work.YM2149
|
||||
port map(
|
||||
-- data bus
|
||||
I_DA => cpu_do, -- in std_logic_vector(7 downto 0); -- pin 37 to 30
|
||||
O_DA => ay1_do, -- out std_logic_vector(7 downto 0); -- pin 37 to 30
|
||||
O_DA_OE_L => open, -- out std_logic;
|
||||
-- control
|
||||
I_A9_L => '0', -- in std_logic; -- pin 24
|
||||
I_A8 => '1', -- in std_logic; -- pin 25
|
||||
I_BDIR => ay1_bdir, -- in std_logic; -- pin 27
|
||||
I_BC2 => '1', -- in std_logic; -- pin 28
|
||||
I_BC1 => ay1_bc1, -- in std_logic; -- pin 29
|
||||
I_SEL_L => '0', -- in std_logic;
|
||||
|
||||
O_AUDIO => ay1_audio_muxed, -- out std_logic_vector(7 downto 0);
|
||||
O_CHAN => ay1_audio_chan, -- out std_logic_vector(1 downto 0);
|
||||
|
||||
-- port a
|
||||
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0); -- pin 21 to 14
|
||||
O_IOA => ay1_port_a, -- out std_logic_vector(7 downto 0); -- pin 21 to 14
|
||||
O_IOA_OE_L => open, -- out std_logic;
|
||||
-- port b
|
||||
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0); -- pin 13 to 6
|
||||
O_IOB => ay1_port_b, -- out std_logic_vector(7 downto 0); -- pin 13 to 6
|
||||
O_IOB_OE_L => open, -- out std_logic;
|
||||
|
||||
ENA => cpu_ena, -- in std_logic; -- clock enable for higher speed operation
|
||||
RESET_L => reset_n, -- in std_logic;
|
||||
CLK => clock_snd -- in std_logic -- note 6 Mhz
|
||||
);
|
||||
|
||||
|
||||
-- AY-3-8910 # 2
|
||||
ay_3_8910_2 : entity work.YM2149
|
||||
port map(
|
||||
-- data bus
|
||||
I_DA => cpu_do, -- in std_logic_vector(7 downto 0); -- pin 37 to 30
|
||||
O_DA => ay2_do, -- out std_logic_vector(7 downto 0); -- pin 37 to 30
|
||||
O_DA_OE_L => open, -- out std_logic;
|
||||
-- control
|
||||
I_A9_L => '0', -- in std_logic; -- pin 24
|
||||
I_A8 => '1', -- in std_logic; -- pin 25
|
||||
I_BDIR => ay2_bdir, -- in std_logic; -- pin 27
|
||||
I_BC2 => '1', -- in std_logic; -- pin 28
|
||||
I_BC1 => ay2_bc1, -- in std_logic; -- pin 29
|
||||
I_SEL_L => '0', -- in std_logic;
|
||||
|
||||
O_AUDIO => ay2_audio_muxed, -- out std_logic_vector(7 downto 0);
|
||||
O_CHAN => ay2_audio_chan, -- out std_logic_vector(1 downto 0);
|
||||
|
||||
-- port a
|
||||
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0); -- pin 21 to 14
|
||||
O_IOA => ay2_port_a, -- out std_logic_vector(7 downto 0); -- pin 21 to 14
|
||||
O_IOA_OE_L => open, -- out std_logic;
|
||||
-- port b
|
||||
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0); -- pin 13 to 6
|
||||
O_IOB => ay2_port_b, -- out std_logic_vector(7 downto 0); -- pin 13 to 6
|
||||
O_IOB_OE_L => open, -- out std_logic;
|
||||
|
||||
ENA => cpu_ena, -- in std_logic; -- clock enable for higher speed operation
|
||||
RESET_L => reset_n, -- in std_logic;
|
||||
CLK => clock_snd -- in std_logic -- note 6 Mhz
|
||||
);
|
||||
|
||||
-- midway ssio sound modulation prom
|
||||
midssio : entity work.midssio_82s123
|
||||
port map(
|
||||
clk => clock_sndn,
|
||||
addr => ssio_82s123_addr,
|
||||
data => ssio_82s123_do
|
||||
);
|
||||
|
||||
end struct;
|
||||
Reference in New Issue
Block a user