1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-10 12:28:26 +00:00

Merge pull request #90 from gyurco/master

Midway MCR: sound pitch fix
This commit is contained in:
Marcel
2020-05-31 22:42:54 +02:00
committed by GitHub
29 changed files with 557 additions and 5605 deletions

View File

@@ -196,6 +196,8 @@ set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/scr.stp
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_global_assignment -name SYSTEMVERILOG_FILE rtl/ScrambleMist.sv
@@ -205,7 +207,6 @@ set_global_assignment -name VHDL_FILE rtl/scramble_top.vhd
set_global_assignment -name VHDL_FILE rtl/scramble_video.vhd
set_global_assignment -name VHDL_FILE rtl/scramble_audio.vhd
set_global_assignment -name VHDL_FILE rtl/scramble_pack.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/MULT18X18.vhd
set_global_assignment -name VHDL_FILE rtl/i82c55.vhd
set_global_assignment -name QIP_FILE rtl/pll.qip

View File

@@ -143,21 +143,13 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end ENTITY(TheEnd)
# ------------------
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_global_assignment -name SYSTEMVERILOG_FILE rtl/TheEnd.sv
set_global_assignment -name VHDL_FILE rtl/scramble_top.vhd
set_global_assignment -name VHDL_FILE rtl/scramble.vhd
set_global_assignment -name VHDL_FILE rtl/scramble_video.vhd
set_global_assignment -name VHDL_FILE rtl/scramble_audio.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/MULT18X18.vhd
set_global_assignment -name VHDL_FILE rtl/i82c55.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80sed.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80_Reg.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80_Pack.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80_MCode.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80_ALU.vhd
set_global_assignment -name VHDL_FILE rtl/cpu/T80.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/ROM_SND_1.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/ROM_SND_0.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/ROM_PGM.vhd
@@ -166,4 +158,8 @@ set_global_assignment -name VHDL_FILE rtl/ROM/ROM_OBJ_0.vhd
set_global_assignment -name VHDL_FILE rtl/ROM/ROM_LUT.vhd
set_global_assignment -name QIP_FILE rtl/pll.qip
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -45,7 +45,7 @@ localparam CONF_STR = {
"O2,Rotate Controls,Off,On;",
"O34,Scanlines,Off,25%,50%,75%;",
"O5,Blending,Off,On;",
"T6,Reset;",
"T0,Reset;",
"V,v1.20.",`BUILD_DATE
};
@@ -82,13 +82,15 @@ end
wire [31:0] status;
wire [1:0] buttons;
wire [1:0] switches;
wire [9:0] kbjoy;
wire [7:0] joystick_0;
wire [7:0] joystick_1;
wire [7:0] key_code;
wire key_strobe;
wire key_pressed;
wire scandoublerD;
wire ypbpr;
wire [10:0] ps2_key;
wire [9:0] audio;
wire no_csync;
wire [9:0] audio;
wire hs, vs;
wire blankn = ~(hb | vb);
wire hb, vb;
@@ -100,11 +102,11 @@ scramble_top theend(
.O_VIDEO_B(b),
.O_HSYNC(hs),
.O_VSYNC(vs),
.O_HBLANK(hb),
.O_VBLANK(vb),
.O_HBLANK(hb),
.O_VBLANK(vb),
.O_AUDIO(audio),
.button_in(~{btn_two_players, m_fire, btn_coin, btn_one_player, m_right, m_left, m_down, m_up}),
.RESET(status[0] | status[6] | buttons[1]),
.button_in(~{m_two_players, m_fireA, m_coin1, m_one_player, m_right, m_left, m_down, m_up}),
.RESET(status[0] | buttons[1]),
.clk(clk_sys),
.ena_star(ce_star),
.ena_6(ce_6p),
@@ -131,7 +133,8 @@ mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video(
.blend(status[5]),
.scandoubler_disable(scandoublerD),
.scanlines(status[4:3]),
.ypbpr(ypbpr)
.ypbpr(ypbpr),
.no_csync(no_csync)
);
user_io #(
@@ -147,6 +150,7 @@ user_io(
.switches (switches ),
.scandoubler_disable (scandoublerD ),
.ypbpr (ypbpr ),
.no_csync (no_csync ),
.key_strobe (key_strobe ),
.key_pressed (key_pressed ),
.key_code (key_code ),
@@ -161,44 +165,25 @@ dac #(10) dac(
.dac_i(audio),
.dac_o(AUDIO_L)
);
// Rotated Normal
wire m_up = ~status[2] ? btn_left | joystick_0[1] | joystick_1[1] : btn_up | joystick_0[3] | joystick_1[3];
wire m_down = ~status[2] ? btn_right | joystick_0[0] | joystick_1[0] : btn_down | joystick_0[2] | joystick_1[2];
wire m_left = ~status[2] ? btn_down | joystick_0[2] | joystick_1[2] : btn_left | joystick_0[1] | joystick_1[1];
wire m_right = ~status[2] ? btn_up | joystick_0[3] | joystick_1[3] : btn_right | joystick_0[0] | joystick_1[0];
wire m_fire = btn_fire1 | joystick_0[4] | joystick_1[4];
wire m_bomb = btn_fire2 | joystick_0[5] | joystick_1[5];
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;
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_fire1 = 0;
reg btn_fire2 = 0;
reg btn_fire3 = 0;
reg btn_coin = 0;
wire key_pressed;
wire [7:0] key_code;
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
'h6B: btn_left <= key_pressed; // left
'h74: btn_right <= key_pressed; // right
'h76: btn_coin <= key_pressed; // ESC
'h05: btn_one_player <= key_pressed; // F1
'h06: btn_two_players <= key_pressed; // F2
'h14: btn_fire3 <= key_pressed; // ctrl
'h11: btn_fire2 <= key_pressed; // alt
'h29: btn_fire1 <= key_pressed; // Space
endcase
end
end
arcade_inputs inputs (
.clk ( clk_sys ),
.key_strobe ( key_strobe ),
.key_pressed ( key_pressed ),
.key_code ( key_code ),
.joystick_0 ( joystick_0 ),
.joystick_1 ( joystick_1 ),
.rotate ( status[2] ),
.orientation ( 2'b11 ),
.joyswap ( 1'b0 ),
.oneplayer ( 1'b1 ),
.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

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -223,10 +223,11 @@ set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
set_global_assignment -name VHDL_FILE rtl/rom/midssio_82s123.vhd
set_global_assignment -name VHDL_FILE rtl/cmos_ram.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 QIP_FILE ../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -492,7 +492,7 @@ port map(
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;
I_SEL_L => '1', -- in std_logic; -- NC
O_AUDIO => ay1_audio_muxed, -- out std_logic_vector(7 downto 0);
O_CHAN => ay1_audio_chan, -- out std_logic_vector(1 downto 0);
@@ -525,7 +525,7 @@ port map(
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;
I_SEL_L => '1', -- in std_logic; -- NC
O_AUDIO => ay2_audio_muxed, -- out std_logic_vector(7 downto 0);
O_CHAN => ay2_audio_chan, -- out std_logic_vector(1 downto 0);

View File

@@ -185,7 +185,6 @@ set_global_assignment -name USE_SIGNALTAP_FILE output_files/jo.stp
set_global_assignment -name SYSTEMVERILOG_FILE rtl/Journey_MiST.sv
set_global_assignment -name VHDL_FILE rtl/journey.vhd
set_global_assignment -name VHDL_FILE rtl/satans_hollow_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
@@ -194,5 +193,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -474,7 +474,7 @@ port map(
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;
I_SEL_L => '1', -- in std_logic; -- NC for AY compat
O_AUDIO => ay1_audio_muxed, -- out std_logic_vector(7 downto 0);
O_CHAN => ay1_audio_chan, -- out std_logic_vector(1 downto 0);
@@ -507,7 +507,7 @@ port map(
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;
I_SEL_L => '1', -- in std_logic; -- NC for AY compat
O_AUDIO => ay2_audio_muxed, -- out std_logic_vector(7 downto 0);
O_CHAN => ay2_audio_chan, -- out std_logic_vector(1 downto 0);

View File

@@ -216,7 +216,6 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name SYSTEMVERILOG_FILE rtl/MCR2_MiST.sv
set_global_assignment -name VHDL_FILE rtl/satans_hollow.vhd
set_global_assignment -name VHDL_FILE rtl/satans_hollow_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
@@ -226,5 +225,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -490,7 +490,7 @@ port map(
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;
I_SEL_L => '1', -- 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);
@@ -523,7 +523,7 @@ port map(
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;
I_SEL_L => '1', -- 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);

View File

@@ -220,7 +220,6 @@ set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name VHDL_FILE rtl/sounds_good.vhd
set_global_assignment -name VHDL_FILE rtl/turbo_cheap_squeak.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 VHDL_FILE rtl/midssio_82s123.vhd
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
set_global_assignment -name VHDL_FILE rtl/spy_hunter_control.vhd
@@ -229,5 +228,7 @@ set_global_assignment -name QIP_FILE ../../common/CPU/68000/FX68k/fx68k.qip
set_global_assignment -name VHDL_FILE ../../common/IO/pia6821.vhd
set_global_assignment -name VHDL_FILE ../../common/CPU/MC6809/cpu09l_128a.vhd
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -497,7 +497,7 @@ port map(
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;
I_SEL_L => '1', -- 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);
@@ -530,7 +530,7 @@ port map(
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;
I_SEL_L => '1', -- 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);

View File

@@ -227,7 +227,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/CraterRaider_MiST.sv
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
set_global_assignment -name VHDL_FILE rtl/crater_raider.vhd
set_global_assignment -name VHDL_FILE rtl/spy_hunter_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
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/midssio_82s123.vhd
@@ -236,5 +235,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -506,7 +506,7 @@ port map(
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;
I_SEL_L => '1', -- 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);
@@ -539,7 +539,7 @@ port map(
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;
I_SEL_L => '1', -- 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);

View File

@@ -227,7 +227,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/SpyHunter_MiST.sv
set_global_assignment -name VHDL_FILE rtl/spy_hunter.vhd
set_global_assignment -name VHDL_FILE rtl/spy_hunter_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/spy_hunter_control.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
@@ -239,5 +238,7 @@ set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name VHDL_FILE ../../../common/IO/pia6821.vhd
set_global_assignment -name QIP_FILE ../../../common/CPU/68000/FX68k/fx68k.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -507,7 +507,7 @@ port map(
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;
I_SEL_L => '1', -- 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);
@@ -540,7 +540,7 @@ port map(
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;
I_SEL_L => '1', -- 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);

View File

@@ -229,7 +229,6 @@ set_global_assignment -name VHDL_FILE rtl/turbo_tag_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/cheap_squeak_deluxe.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/rom/midssio_82s123.vhd
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/turbo_tag_control.vhd
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
@@ -239,5 +238,7 @@ set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
set_global_assignment -name VHDL_FILE ../../../common/IO/pia6821.vhd
set_global_assignment -name QIP_FILE ../../../common/CPU/68000/FX68k/fx68k.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/YM2149.vhd
set_global_assignment -name VHDL_FILE ../../../common/Sound/ym2149/vol_table_array.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,574 +0,0 @@
-- 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;

View File

@@ -502,7 +502,7 @@ port map(
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;
I_SEL_L => '1', -- 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);
@@ -535,7 +535,7 @@ port map(
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;
I_SEL_L => '1', -- 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);

View File

@@ -1,326 +0,0 @@
//
// Copyright (c) MikeJ - Jan 2005
// Copyright (c) 2016-2018 Sorgelig
//
// 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.
//
// BDIR BC MODE
// 0 0 inactive
// 0 1 read value
// 1 0 write value
// 1 1 set address
//
module YM2149
(
input CLK, // Global clock
input CE, // PSG Clock enable
input RESET, // Chip RESET (set all Registers to '0', active hi)
input BDIR, // Bus Direction (0 - read , 1 - write)
input BC, // Bus control
input [7:0] DI, // Data In
output [7:0] DO, // Data Out
output [7:0] CHANNEL_A, // PSG Output channel A
output [7:0] CHANNEL_B, // PSG Output channel B
output [7:0] CHANNEL_C, // PSG Output channel C
input SEL,
input MODE,
output [5:0] ACTIVE,
input [7:0] IOA_in,
output [7:0] IOA_out,
input [7:0] IOB_in,
output [7:0] IOB_out
);
assign ACTIVE = ~ymreg[7][5:0];
assign IOA_out = ymreg[7][6] ? ymreg[14] : 8'hff;
assign IOB_out = ymreg[7][7] ? ymreg[15] : 8'hff;
reg [7:0] addr;
reg [7:0] ymreg[16];
// Write to PSG
reg env_reset;
always @(posedge CLK) begin
if(RESET) begin
ymreg <= '{default:0};
ymreg[7] <= '1;
addr <= '0;
env_reset <= 0;
end else begin
env_reset <= 0;
if(BDIR) begin
if(BC) addr <= DI;
else if(!addr[7:4]) begin
ymreg[addr[3:0]] <= DI;
env_reset <= (addr == 13);
end
end
end
end
// Read from PSG
assign DO = dout;
reg [7:0] dout;
always_comb begin
dout = 8'hFF;
if(~BDIR & BC & !addr[7:4]) begin
case(addr[3:0])
0: dout = ymreg[0];
1: dout = ymreg[1][3:0];
2: dout = ymreg[2];
3: dout = ymreg[3][3:0];
4: dout = ymreg[4];
5: dout = ymreg[5][3:0];
6: dout = ymreg[6][4:0];
7: dout = ymreg[7];
8: dout = ymreg[8][4:0];
9: dout = ymreg[9][4:0];
10: dout = ymreg[10][4:0];
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = ymreg[13][3:0];
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase
end
end
reg ena_div;
reg ena_div_noise;
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
reg noise_div;
if(CE) begin
ena_div <= 0;
ena_div_noise <= 0;
if(!cnt_div) begin
cnt_div <= {SEL, 3'b111};
ena_div <= 1;
noise_div <= (~noise_div);
if (noise_div) ena_div_noise <= 1;
end else begin
cnt_div <= cnt_div - 1'b1;
end
end
end
reg [2:0] noise_gen_op;
// p_noise_gen
always @(posedge CLK) begin
reg [16:0] poly17;
reg [4:0] noise_gen_cnt;
if(CE) begin
if (ena_div_noise) begin
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
noise_gen_cnt <= 0;
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
noise_gen_op <= {3{poly17[0]}};
end
end
end
wire [11:0] tone_gen_freq[1:3];
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
reg [3:1] tone_gen_op;
//p_tone_gens
always @(posedge CLK) begin
integer i;
reg [11:0] tone_gen_cnt[1:3];
if(CE) begin
// looks like real chips count up - we need to get the Exact behaviour ..
for (i = 1; i <= 3; i = i + 1) begin
if(ena_div) begin
if (tone_gen_freq[i]) begin
if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
tone_gen_cnt[i] <= 0;
tone_gen_op[i] <= ~tone_gen_op[i];
end else begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end else begin
tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0;
end
end
end
end
end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
always @(posedge CLK) begin
reg [15:0] env_gen_cnt;
if(CE) begin
env_ena <= 0;
if(ena_div) begin
if (env_gen_cnt >= env_gen_comp) begin
env_gen_cnt <= 0;
env_ena <= 1;
end else begin
env_gen_cnt <= (env_gen_cnt + 1'd1);
end
end
end
end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg env_hold;
reg env_inc;
// 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 | RESET) begin
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end
else if(CE) begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
end
end
end
reg [5:0] A,B,C;
always @(posedge CLK) begin
A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
end
wire [7:0] volTable[64] = '{
//YM2149
8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
//AY8910
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
};
assign CHANNEL_A = volTable[A];
assign CHANNEL_B = volTable[B];
assign CHANNEL_C = volTable[C];
endmodule

View File

@@ -1,553 +0,0 @@
-- 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
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;

View File

@@ -51,31 +51,42 @@
-- 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.
-- NOTE, when MIXER_VOLTABLE = '0', 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 (MIXER_VOLTABLE = '1').
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity YM2149 is
generic (
MIXER_VOLTABLE : std_logic := '0'
);
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_A9_L : in std_logic := '0';
I_A8 : in std_logic := '1';
I_BDIR : in std_logic;
I_BC2 : in std_logic;
I_BC2 : in std_logic := '1';
I_BC1 : in std_logic;
I_SEL_L : in std_logic;
I_SEL_L : in std_logic := '1';
I_STEREO : in std_logic := '0';
-- separate channel output
O_AUDIO : out std_logic_vector(7 downto 0);
O_CHAN : out std_logic_vector(1 downto 0);
-- mixed output
O_AUDIO_L : out std_logic_vector(9 downto 0);
O_AUDIO_R : out std_logic_vector(9 downto 0);
-- port a
I_IOA : in std_logic_vector(7 downto 0);
O_IOA : out std_logic_vector(7 downto 0);
@@ -87,7 +98,7 @@ entity YM2149 is
ENA : in std_logic; -- clock enable for higher speed operation
RESET_L : in std_logic;
CLK : in std_logic -- note 6 Mhz
CLK : in std_logic
);
end;
@@ -130,6 +141,17 @@ architecture RTL of YM2149 is
signal chan_vol : std_logic_vector(4 downto 0);
signal dac_amp : std_logic_vector(7 downto 0);
signal vol_l : std_logic_vector(9 downto 0);
signal vol_r : std_logic_vector(9 downto 0);
signal vol_mixer_l : std_logic_vector(9 downto 0);
signal vol_mixer_r : std_logic_vector(9 downto 0);
signal vol_table_in_l : std_logic_vector(11 downto 0);
signal vol_table_in_r : std_logic_vector(11 downto 0);
signal vol_table_out_l : std_logic_vector(9 downto 0);
signal vol_table_out_r : std_logic_vector(9 downto 0);
begin
-- cpu i/f
p_busdecode : process(I_BDIR, I_BC2, I_BC1, addr, I_A9_L, I_A8)
@@ -183,10 +205,8 @@ begin
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;
if (busctrl_addr = '1') then
addr <= I_DA;
end if;
end if;
end process;
@@ -197,28 +217,11 @@ begin
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;
env_reset <= '0';
if (busctrl_we = '1') then
reg(to_integer(unsigned(addr(3 downto 0)))) <= I_DA;
if addr(3 downto 0) = x"D" then
env_reset <= '1';
end if;
end if;
end if;
@@ -246,12 +249,12 @@ begin
when x"E" => if (reg(7)(6) = '0') then -- input
O_DA <= ioa_inreg;
else
O_DA <= reg(14); -- read output reg
O_DA <= reg(14) and ioa_inreg; -- read output reg
end if;
when x"F" => if (Reg(7)(7) = '0') then
O_DA <= iob_inreg;
else
O_DA <= reg(15);
O_DA <= reg(15) and iob_inreg;
end if;
when others => null;
end case;
@@ -393,25 +396,25 @@ begin
-- 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
if rising_edge(CLK) then
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';
else
env_vol <= "00000";
env_inc <= '1'; -- +1
end if;
env_hold <= '0';
is_bot := (env_vol = "00000");
is_bot_p1 := (env_vol = "00001");
is_top_m1 := (env_vol = "11110");
is_top := (env_vol = "11111");
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 (ENA = '1' and env_ena = '1') then
if (env_hold = '0') then
if (env_inc = '1') then
env_vol <= (env_vol + "00001");
@@ -459,6 +462,8 @@ begin
end if;
end process;
-- output mixer
p_chan_mixer : process(cnt_div, reg, tone_gen_op)
begin
tone_ena_l <= '1'; tone_src <= '1';
@@ -552,9 +557,147 @@ begin
O_AUDIO <= dac_amp(7 downto 0);
O_CHAN <= cnt_div_t1(1 downto 0);
end if;
end if;
end process;
-- output mixer(s)
p_chan_mixer_linear : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
vol_l <= (others => '0');
vol_r <= (others => '0');
vol_mixer_l <= (others => '0');
vol_mixer_r <= (others => '0');
elsif rising_edge(CLK) then
if (ENA = '1') then
case cnt_div_t1(1 downto 0) is
when "10" => -- Channel C
vol_r <= "00" & dac_amp;
if I_STEREO = '0' then
vol_l <= "00" & dac_amp;
else
vol_l <= (others => '0');
end if;
when "01" => -- Channel B
vol_l <= vol_l + dac_amp;
vol_r <= vol_r + dac_amp;
when "00" => -- Channel A
if I_STEREO = '0' then
vol_mixer_l <= vol_l + dac_amp;
else
vol_mixer_l <= vol_l;
end if;
vol_mixer_r <= vol_r + dac_amp;
when others => null;
end case;
end if;
end if;
end process;
VOLTABLE: if MIXER_VOLTABLE = '1' generate
p_chan_mixer_table : process
variable chan_mixed : std_logic_vector(2 downto 0);
begin
wait until rising_edge(CLK);
if (ENA = '1') then
chan_mixed(0) := (reg(7)(0) or tone_gen_op(1)) and (reg(7)(3) or noise_gen_op);
chan_mixed(1) := (reg(7)(1) or tone_gen_op(2)) and (reg(7)(4) or noise_gen_op);
chan_mixed(2) := (reg(7)(2) or tone_gen_op(3)) and (reg(7)(5) or noise_gen_op);
vol_table_in_l <= x"000";
vol_table_in_r <= x"000";
if (chan_mixed(0) = '1') then
if(I_STEREO = '1') then
if (reg(8)(4) = '0') then
vol_table_in_l(3 downto 0) <= reg(8)(3 downto 0);
else
vol_table_in_l(3 downto 0) <= env_vol(4 downto 1);
end if;
else
if (reg(8)(4) = '0') then
vol_table_in_l(3 downto 0) <= reg(8)(3 downto 0);
vol_table_in_r(3 downto 0) <= reg(8)(3 downto 0);
else
vol_table_in_l(3 downto 0) <= env_vol(4 downto 1);
vol_table_in_r(3 downto 0) <= env_vol(4 downto 1);
end if;
end if;
end if;
if (chan_mixed(1) = '1') then
if (reg(9)(4) = '0') then
vol_table_in_l(7 downto 4) <= reg(9)(3 downto 0);
vol_table_in_r(7 downto 4) <= reg(9)(3 downto 0);
else
vol_table_in_l(7 downto 4) <= env_vol(4 downto 1);
vol_table_in_r(7 downto 4) <= env_vol(4 downto 1);
end if;
end if;
if (chan_mixed(2) = '1') then
if(I_STEREO = '1') then
if (reg(10)(4) = '0') then
vol_table_in_r(11 downto 8) <= reg(10)(3 downto 0);
else
vol_table_in_r(11 downto 8) <= env_vol(4 downto 1);
end if;
else
if (reg(10)(4) = '0') then
vol_table_in_l(11 downto 8) <= reg(10)(3 downto 0);
vol_table_in_r(11 downto 8) <= reg(10)(3 downto 0);
else
vol_table_in_l(11 downto 8) <= env_vol(4 downto 1);
vol_table_in_r(11 downto 8) <= env_vol(4 downto 1);
end if;
end if;
end if;
end if;
end process;
u_vol_table : work.vol_table
port map (
CLK => clk,
ADDR_A => vol_table_in_l,
DATA_A => vol_table_out_l,
ADDR_B => vol_table_in_r,
DATA_B => vol_table_out_r
);
end generate; -- VOLTABLE
NO_VOLTABLE: if MIXER_VOLTABLE = '0' generate
vol_table_out_l <= (others => '0');
vol_table_out_r <= (others => '0');
end generate;
-- mixed audio output
p_vol_out : process
variable chan_mixed : std_logic;
variable chan_amp : std_logic_vector(4 downto 0);
begin
wait until rising_edge(CLK);
if (RESET_L = '0') then
O_AUDIO_L <= (others => '0');
O_AUDIO_R <= (others => '0');
else
if (MIXER_VOLTABLE = '1') then
O_AUDIO_L <= vol_table_out_l;
O_AUDIO_R <= vol_table_out_r;
else
O_AUDIO_L <= vol_mixer_l;
O_AUDIO_R <= vol_mixer_r;
end if;
end if;
end process;
-- IO ports
p_io_ports : process(reg)
begin
O_IOA <= reg(14);
@@ -566,9 +709,7 @@ begin
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;
ioa_inreg <= I_IOA;
iob_inreg <= I_IOB;
end process;
end architecture RTL;

View File

@@ -0,0 +1,293 @@
-- Sixteen level by Three voice YM2149 volume_table[C][B][A]
-- Data measured by Paulo Simoes. Copyright 2012 Paulo Simoes.
-- original 16 bit data reduced to 10 bit
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity vol_table is
port (
CLK : in std_logic;
ADDR_A : in std_logic_vector(11 downto 0);
DATA_A : out std_logic_vector(9 downto 0);
ADDR_B : in std_logic_vector(11 downto 0);
DATA_B : out std_logic_vector(9 downto 0)
);
end;
architecture RTL of vol_table is
type ROM_ARRAY is array(0 to 4095) of std_logic_vector(9 downto 0);
constant voltable : ROM_ARRAY := (
"00"&x"00","00"&x"01","00"&x"03","00"&x"06","00"&x"09","00"&x"0d","00"&x"13","00"&x"1a","00"&x"27","00"&x"36","00"&x"50","00"&x"6e","00"&x"a1","00"&x"e4","01"&x"66","10"&x"1a",
"00"&x"01","00"&x"04","00"&x"06","00"&x"08","00"&x"0c","00"&x"0f","00"&x"16","00"&x"1d","00"&x"2a","00"&x"38","00"&x"52","00"&x"70","00"&x"a4","00"&x"e6","01"&x"67","10"&x"1a",
"00"&x"03","00"&x"06","00"&x"08","00"&x"0a","00"&x"0e","00"&x"11","00"&x"18","00"&x"1f","00"&x"2c","00"&x"3a","00"&x"54","00"&x"72","00"&x"a5","00"&x"e8","01"&x"68","10"&x"1a",
"00"&x"06","00"&x"08","00"&x"0a","00"&x"0c","00"&x"10","00"&x"14","00"&x"1a","00"&x"21","00"&x"2e","00"&x"3d","00"&x"56","00"&x"74","00"&x"a7","00"&x"e9","01"&x"69","10"&x"1b",
"00"&x"09","00"&x"0c","00"&x"0e","00"&x"10","00"&x"13","00"&x"17","00"&x"1e","00"&x"25","00"&x"31","00"&x"40","00"&x"5a","00"&x"77","00"&x"aa","00"&x"ec","01"&x"6b","10"&x"1b",
"00"&x"0d","00"&x"0f","00"&x"11","00"&x"14","00"&x"17","00"&x"1b","00"&x"21","00"&x"29","00"&x"35","00"&x"43","00"&x"5d","00"&x"7a","00"&x"ad","00"&x"ef","01"&x"6d","10"&x"1c",
"00"&x"13","00"&x"16","00"&x"18","00"&x"1a","00"&x"1e","00"&x"21","00"&x"28","00"&x"2f","00"&x"3b","00"&x"4a","00"&x"63","00"&x"80","00"&x"b3","00"&x"f4","01"&x"71","10"&x"1d",
"00"&x"1a","00"&x"1d","00"&x"1f","00"&x"21","00"&x"25","00"&x"29","00"&x"2f","00"&x"36","00"&x"42","00"&x"50","00"&x"6a","00"&x"85","00"&x"b9","00"&x"f9","01"&x"75","10"&x"1f",
"00"&x"27","00"&x"2a","00"&x"2c","00"&x"2e","00"&x"31","00"&x"35","00"&x"3b","00"&x"42","00"&x"4e","00"&x"5c","00"&x"75","00"&x"90","00"&x"c3","01"&x"03","01"&x"7d","10"&x"22",
"00"&x"36","00"&x"38","00"&x"3a","00"&x"3d","00"&x"40","00"&x"43","00"&x"4a","00"&x"50","00"&x"5c","00"&x"6a","00"&x"82","00"&x"9d","00"&x"d0","01"&x"0e","01"&x"87","10"&x"28",
"00"&x"50","00"&x"52","00"&x"54","00"&x"56","00"&x"5a","00"&x"5d","00"&x"63","00"&x"6a","00"&x"75","00"&x"82","00"&x"98","00"&x"b4","00"&x"e6","01"&x"22","01"&x"99","10"&x"34",
"00"&x"6e","00"&x"70","00"&x"72","00"&x"74","00"&x"77","00"&x"7a","00"&x"80","00"&x"85","00"&x"90","00"&x"9d","00"&x"b4","00"&x"cf","01"&x"01","01"&x"3b","01"&x"af","10"&x"44",
"00"&x"a1","00"&x"a4","00"&x"a5","00"&x"a7","00"&x"aa","00"&x"ad","00"&x"b3","00"&x"b9","00"&x"c3","00"&x"d0","00"&x"e6","01"&x"01","01"&x"2f","01"&x"6a","01"&x"dc","10"&x"69",
"00"&x"e4","00"&x"e6","00"&x"e8","00"&x"e9","00"&x"ec","00"&x"ef","00"&x"f4","00"&x"f9","01"&x"03","01"&x"0e","01"&x"22","01"&x"3b","01"&x"6a","01"&x"a3","10"&x"14","10"&x"9a",
"01"&x"66","01"&x"67","01"&x"68","01"&x"69","01"&x"6b","01"&x"6d","01"&x"71","01"&x"75","01"&x"7d","01"&x"87","01"&x"99","01"&x"af","01"&x"dc","10"&x"14","10"&x"79","10"&x"f3",
"10"&x"1a","10"&x"1a","10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"22","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"01","00"&x"04","00"&x"06","00"&x"08","00"&x"0c","00"&x"0f","00"&x"16","00"&x"1d","00"&x"2a","00"&x"38","00"&x"52","00"&x"70","00"&x"a4","00"&x"e6","01"&x"67","10"&x"1a",
"00"&x"04","00"&x"07","00"&x"09","00"&x"0b","00"&x"0e","00"&x"12","00"&x"19","00"&x"20","00"&x"2c","00"&x"3b","00"&x"55","00"&x"72","00"&x"a6","00"&x"e8","01"&x"68","10"&x"1b",
"00"&x"06","00"&x"09","00"&x"0b","00"&x"0d","00"&x"10","00"&x"14","00"&x"1b","00"&x"22","00"&x"2e","00"&x"3d","00"&x"57","00"&x"74","00"&x"a8","00"&x"ea","01"&x"6a","10"&x"1b",
"00"&x"08","00"&x"0b","00"&x"0d","00"&x"0f","00"&x"12","00"&x"16","00"&x"1d","00"&x"24","00"&x"30","00"&x"3f","00"&x"59","00"&x"76","00"&x"a9","00"&x"eb","01"&x"6b","10"&x"1b",
"00"&x"0c","00"&x"0e","00"&x"10","00"&x"12","00"&x"16","00"&x"1a","00"&x"20","00"&x"27","00"&x"34","00"&x"42","00"&x"5c","00"&x"79","00"&x"ac","00"&x"ee","01"&x"6c","10"&x"1b",
"00"&x"0f","00"&x"12","00"&x"14","00"&x"16","00"&x"1a","00"&x"1d","00"&x"24","00"&x"2b","00"&x"37","00"&x"46","00"&x"5f","00"&x"7c","00"&x"af","00"&x"f1","01"&x"6e","10"&x"1c",
"00"&x"16","00"&x"19","00"&x"1b","00"&x"1d","00"&x"20","00"&x"24","00"&x"2a","00"&x"31","00"&x"3e","00"&x"4c","00"&x"65","00"&x"81","00"&x"b5","00"&x"f5","01"&x"72","10"&x"1d",
"00"&x"1d","00"&x"20","00"&x"22","00"&x"24","00"&x"27","00"&x"2b","00"&x"31","00"&x"39","00"&x"45","00"&x"53","00"&x"6c","00"&x"87","00"&x"bb","00"&x"fb","01"&x"77","10"&x"1f",
"00"&x"2a","00"&x"2c","00"&x"2e","00"&x"30","00"&x"34","00"&x"37","00"&x"3e","00"&x"45","00"&x"51","00"&x"5f","00"&x"78","00"&x"92","00"&x"c5","01"&x"05","01"&x"7f","10"&x"22",
"00"&x"38","00"&x"3b","00"&x"3d","00"&x"3f","00"&x"42","00"&x"46","00"&x"4c","00"&x"53","00"&x"5f","00"&x"6d","00"&x"84","00"&x"9f","00"&x"d2","01"&x"0f","01"&x"88","10"&x"28",
"00"&x"52","00"&x"55","00"&x"57","00"&x"59","00"&x"5c","00"&x"5f","00"&x"65","00"&x"6c","00"&x"78","00"&x"84","00"&x"9a","00"&x"b6","00"&x"e8","01"&x"24","01"&x"9a","10"&x"34",
"00"&x"70","00"&x"72","00"&x"74","00"&x"76","00"&x"79","00"&x"7c","00"&x"81","00"&x"87","00"&x"92","00"&x"9f","00"&x"b6","00"&x"d1","01"&x"02","01"&x"3d","01"&x"b0","10"&x"44",
"00"&x"a4","00"&x"a6","00"&x"a8","00"&x"a9","00"&x"ac","00"&x"af","00"&x"b5","00"&x"bb","00"&x"c5","00"&x"d2","00"&x"e8","01"&x"02","01"&x"31","01"&x"6c","01"&x"dc","10"&x"69",
"00"&x"e6","00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ee","00"&x"f1","00"&x"f5","00"&x"fb","01"&x"05","01"&x"0f","01"&x"24","01"&x"3d","01"&x"6c","01"&x"a4","10"&x"14","10"&x"9a",
"01"&x"67","01"&x"68","01"&x"6a","01"&x"6b","01"&x"6c","01"&x"6e","01"&x"72","01"&x"77","01"&x"7f","01"&x"88","01"&x"9a","01"&x"b0","01"&x"dc","10"&x"14","10"&x"79","10"&x"f3",
"10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"22","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"03","00"&x"06","00"&x"08","00"&x"0a","00"&x"0e","00"&x"11","00"&x"18","00"&x"1f","00"&x"2c","00"&x"3a","00"&x"54","00"&x"72","00"&x"a5","00"&x"e8","01"&x"68","10"&x"1a",
"00"&x"06","00"&x"09","00"&x"0b","00"&x"0d","00"&x"10","00"&x"14","00"&x"1b","00"&x"22","00"&x"2e","00"&x"3d","00"&x"57","00"&x"74","00"&x"a8","00"&x"ea","01"&x"6a","10"&x"1b",
"00"&x"08","00"&x"0b","00"&x"0d","00"&x"0f","00"&x"12","00"&x"16","00"&x"1d","00"&x"24","00"&x"30","00"&x"3f","00"&x"59","00"&x"76","00"&x"a9","00"&x"eb","01"&x"6b","10"&x"1b",
"00"&x"0a","00"&x"0d","00"&x"0f","00"&x"11","00"&x"15","00"&x"18","00"&x"1f","00"&x"26","00"&x"33","00"&x"41","00"&x"5b","00"&x"78","00"&x"ab","00"&x"ed","01"&x"6c","10"&x"1b",
"00"&x"0e","00"&x"10","00"&x"12","00"&x"15","00"&x"18","00"&x"1c","00"&x"22","00"&x"2a","00"&x"36","00"&x"44","00"&x"5e","00"&x"7b","00"&x"ae","00"&x"ef","01"&x"6e","10"&x"1c",
"00"&x"11","00"&x"14","00"&x"16","00"&x"18","00"&x"1c","00"&x"20","00"&x"26","00"&x"2d","00"&x"3a","00"&x"48","00"&x"61","00"&x"7e","00"&x"b1","00"&x"f2","01"&x"70","10"&x"1c",
"00"&x"18","00"&x"1b","00"&x"1d","00"&x"1f","00"&x"22","00"&x"26","00"&x"2c","00"&x"33","00"&x"40","00"&x"4e","00"&x"67","00"&x"83","00"&x"b6","00"&x"f7","01"&x"73","10"&x"1d",
"00"&x"1f","00"&x"22","00"&x"24","00"&x"26","00"&x"2a","00"&x"2d","00"&x"33","00"&x"3b","00"&x"47","00"&x"55","00"&x"6e","00"&x"89","00"&x"bd","00"&x"fc","01"&x"78","10"&x"1f",
"00"&x"2c","00"&x"2e","00"&x"30","00"&x"33","00"&x"36","00"&x"3a","00"&x"40","00"&x"47","00"&x"53","00"&x"61","00"&x"79","00"&x"94","00"&x"c7","01"&x"06","01"&x"7f","10"&x"23",
"00"&x"3a","00"&x"3d","00"&x"3f","00"&x"41","00"&x"44","00"&x"48","00"&x"4e","00"&x"55","00"&x"61","00"&x"6f","00"&x"85","00"&x"a1","00"&x"d4","01"&x"10","01"&x"89","10"&x"28",
"00"&x"54","00"&x"57","00"&x"59","00"&x"5b","00"&x"5e","00"&x"61","00"&x"67","00"&x"6e","00"&x"79","00"&x"85","00"&x"9c","00"&x"b8","00"&x"ea","01"&x"25","01"&x"9b","10"&x"34",
"00"&x"72","00"&x"74","00"&x"76","00"&x"78","00"&x"7b","00"&x"7e","00"&x"83","00"&x"89","00"&x"94","00"&x"a1","00"&x"b8","00"&x"d3","01"&x"04","01"&x"3e","01"&x"b1","10"&x"44",
"00"&x"a5","00"&x"a8","00"&x"a9","00"&x"ab","00"&x"ae","00"&x"b1","00"&x"b6","00"&x"bd","00"&x"c7","00"&x"d4","00"&x"ea","01"&x"04","01"&x"32","01"&x"6c","01"&x"dd","10"&x"69",
"00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ed","00"&x"ef","00"&x"f2","00"&x"f7","00"&x"fc","01"&x"06","01"&x"10","01"&x"25","01"&x"3e","01"&x"6c","01"&x"a5","10"&x"15","10"&x"9a",
"01"&x"68","01"&x"6a","01"&x"6b","01"&x"6c","01"&x"6e","01"&x"70","01"&x"73","01"&x"78","01"&x"7f","01"&x"89","01"&x"9b","01"&x"b1","01"&x"dd","10"&x"15","10"&x"79","10"&x"f3",
"10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"23","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"06","00"&x"08","00"&x"0a","00"&x"0c","00"&x"10","00"&x"14","00"&x"1a","00"&x"21","00"&x"2e","00"&x"3d","00"&x"56","00"&x"74","00"&x"a7","00"&x"e9","01"&x"69","10"&x"1b",
"00"&x"08","00"&x"0b","00"&x"0d","00"&x"0f","00"&x"12","00"&x"16","00"&x"1d","00"&x"24","00"&x"30","00"&x"3f","00"&x"59","00"&x"76","00"&x"a9","00"&x"eb","01"&x"6b","10"&x"1b",
"00"&x"0a","00"&x"0d","00"&x"0f","00"&x"11","00"&x"15","00"&x"18","00"&x"1f","00"&x"26","00"&x"33","00"&x"41","00"&x"5b","00"&x"78","00"&x"ab","00"&x"ed","01"&x"6c","10"&x"1b",
"00"&x"0c","00"&x"0f","00"&x"11","00"&x"13","00"&x"17","00"&x"1b","00"&x"21","00"&x"28","00"&x"35","00"&x"43","00"&x"5d","00"&x"7a","00"&x"ad","00"&x"ee","01"&x"6d","10"&x"1c",
"00"&x"10","00"&x"12","00"&x"15","00"&x"17","00"&x"1a","00"&x"1e","00"&x"24","00"&x"2c","00"&x"38","00"&x"46","00"&x"60","00"&x"7d","00"&x"b0","00"&x"f1","01"&x"6f","10"&x"1c",
"00"&x"14","00"&x"16","00"&x"18","00"&x"1b","00"&x"1e","00"&x"22","00"&x"28","00"&x"2f","00"&x"3c","00"&x"4a","00"&x"63","00"&x"80","00"&x"b3","00"&x"f4","01"&x"71","10"&x"1c",
"00"&x"1a","00"&x"1d","00"&x"1f","00"&x"21","00"&x"24","00"&x"28","00"&x"2e","00"&x"35","00"&x"42","00"&x"50","00"&x"69","00"&x"84","00"&x"b8","00"&x"f8","01"&x"74","10"&x"1e",
"00"&x"21","00"&x"24","00"&x"26","00"&x"28","00"&x"2c","00"&x"2f","00"&x"35","00"&x"3d","00"&x"49","00"&x"57","00"&x"70","00"&x"8a","00"&x"be","00"&x"fe","01"&x"79","10"&x"1f",
"00"&x"2e","00"&x"30","00"&x"33","00"&x"35","00"&x"38","00"&x"3c","00"&x"42","00"&x"49","00"&x"55","00"&x"63","00"&x"7b","00"&x"95","00"&x"c9","01"&x"08","01"&x"80","10"&x"23",
"00"&x"3d","00"&x"3f","00"&x"41","00"&x"43","00"&x"46","00"&x"4a","00"&x"50","00"&x"57","00"&x"63","00"&x"71","00"&x"87","00"&x"a3","00"&x"d5","01"&x"12","01"&x"8a","10"&x"29",
"00"&x"56","00"&x"59","00"&x"5b","00"&x"5d","00"&x"60","00"&x"63","00"&x"69","00"&x"70","00"&x"7b","00"&x"87","00"&x"9e","00"&x"b9","00"&x"eb","01"&x"26","01"&x"9c","10"&x"34",
"00"&x"74","00"&x"76","00"&x"78","00"&x"7a","00"&x"7d","00"&x"80","00"&x"84","00"&x"8a","00"&x"95","00"&x"a3","00"&x"b9","00"&x"d4","01"&x"05","01"&x"3f","01"&x"b1","10"&x"44",
"00"&x"a7","00"&x"a9","00"&x"ab","00"&x"ad","00"&x"b0","00"&x"b3","00"&x"b8","00"&x"be","00"&x"c9","00"&x"d5","00"&x"eb","01"&x"05","01"&x"33","01"&x"6d","01"&x"dd","10"&x"69",
"00"&x"e9","00"&x"eb","00"&x"ed","00"&x"ee","00"&x"f1","00"&x"f4","00"&x"f8","00"&x"fe","01"&x"08","01"&x"12","01"&x"26","01"&x"3f","01"&x"6d","01"&x"a5","10"&x"15","10"&x"9a",
"01"&x"69","01"&x"6b","01"&x"6c","01"&x"6d","01"&x"6f","01"&x"71","01"&x"74","01"&x"79","01"&x"80","01"&x"8a","01"&x"9c","01"&x"b1","01"&x"dd","10"&x"15","10"&x"79","10"&x"f3",
"10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1e","10"&x"1f","10"&x"23","10"&x"29","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"09","00"&x"0c","00"&x"0e","00"&x"10","00"&x"13","00"&x"17","00"&x"1e","00"&x"25","00"&x"31","00"&x"40","00"&x"5a","00"&x"77","00"&x"aa","00"&x"ec","01"&x"6b","10"&x"1b",
"00"&x"0c","00"&x"0e","00"&x"10","00"&x"12","00"&x"16","00"&x"1a","00"&x"20","00"&x"27","00"&x"34","00"&x"42","00"&x"5c","00"&x"79","00"&x"ac","00"&x"ee","01"&x"6c","10"&x"1b",
"00"&x"0e","00"&x"10","00"&x"12","00"&x"15","00"&x"18","00"&x"1c","00"&x"22","00"&x"2a","00"&x"36","00"&x"44","00"&x"5e","00"&x"7b","00"&x"ae","00"&x"ef","01"&x"6e","10"&x"1c",
"00"&x"10","00"&x"12","00"&x"15","00"&x"17","00"&x"1a","00"&x"1e","00"&x"24","00"&x"2c","00"&x"38","00"&x"46","00"&x"60","00"&x"7d","00"&x"b0","00"&x"f1","01"&x"6f","10"&x"1c",
"00"&x"13","00"&x"16","00"&x"18","00"&x"1a","00"&x"1d","00"&x"21","00"&x"28","00"&x"2f","00"&x"3b","00"&x"4a","00"&x"63","00"&x"80","00"&x"b2","00"&x"f3","01"&x"70","10"&x"1c",
"00"&x"17","00"&x"1a","00"&x"1c","00"&x"1e","00"&x"21","00"&x"25","00"&x"2c","00"&x"32","00"&x"3f","00"&x"4d","00"&x"66","00"&x"82","00"&x"b6","00"&x"f6","01"&x"72","10"&x"1d",
"00"&x"1e","00"&x"20","00"&x"22","00"&x"24","00"&x"28","00"&x"2c","00"&x"32","00"&x"39","00"&x"45","00"&x"53","00"&x"6c","00"&x"87","00"&x"bb","00"&x"fb","01"&x"76","10"&x"1e",
"00"&x"25","00"&x"27","00"&x"2a","00"&x"2c","00"&x"2f","00"&x"32","00"&x"39","00"&x"40","00"&x"4c","00"&x"5a","00"&x"73","00"&x"8d","00"&x"c1","01"&x"00","01"&x"7a","10"&x"20",
"00"&x"31","00"&x"34","00"&x"36","00"&x"38","00"&x"3b","00"&x"3f","00"&x"45","00"&x"4c","00"&x"58","00"&x"66","00"&x"7e","00"&x"98","00"&x"cb","01"&x"0a","01"&x"82","10"&x"23",
"00"&x"40","00"&x"42","00"&x"44","00"&x"46","00"&x"4a","00"&x"4d","00"&x"53","00"&x"5a","00"&x"66","00"&x"74","00"&x"8a","00"&x"a5","00"&x"d8","01"&x"14","01"&x"8c","10"&x"29",
"00"&x"5a","00"&x"5c","00"&x"5e","00"&x"60","00"&x"63","00"&x"66","00"&x"6c","00"&x"73","00"&x"7e","00"&x"8a","00"&x"a1","00"&x"bc","00"&x"ed","01"&x"28","01"&x"9d","10"&x"34",
"00"&x"77","00"&x"79","00"&x"7b","00"&x"7d","00"&x"80","00"&x"82","00"&x"87","00"&x"8d","00"&x"98","00"&x"a5","00"&x"bc","00"&x"d7","01"&x"07","01"&x"41","01"&x"b2","10"&x"44",
"00"&x"aa","00"&x"ac","00"&x"ae","00"&x"b0","00"&x"b2","00"&x"b6","00"&x"bb","00"&x"c1","00"&x"cb","00"&x"d8","00"&x"ed","01"&x"07","01"&x"35","01"&x"6f","01"&x"de","10"&x"69",
"00"&x"ec","00"&x"ee","00"&x"ef","00"&x"f1","00"&x"f3","00"&x"f6","00"&x"fb","01"&x"00","01"&x"0a","01"&x"14","01"&x"28","01"&x"41","01"&x"6f","01"&x"a6","10"&x"15","10"&x"9a",
"01"&x"6b","01"&x"6c","01"&x"6e","01"&x"6f","01"&x"70","01"&x"72","01"&x"76","01"&x"7a","01"&x"82","01"&x"8c","01"&x"9d","01"&x"b2","01"&x"de","10"&x"15","10"&x"79","10"&x"f3",
"10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1e","10"&x"20","10"&x"23","10"&x"29","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"0d","00"&x"0f","00"&x"11","00"&x"14","00"&x"17","00"&x"1b","00"&x"21","00"&x"29","00"&x"35","00"&x"43","00"&x"5d","00"&x"7a","00"&x"ad","00"&x"ef","01"&x"6d","10"&x"1c",
"00"&x"0f","00"&x"12","00"&x"14","00"&x"16","00"&x"1a","00"&x"1d","00"&x"24","00"&x"2b","00"&x"37","00"&x"46","00"&x"5f","00"&x"7c","00"&x"af","00"&x"f1","01"&x"6e","10"&x"1c",
"00"&x"11","00"&x"14","00"&x"16","00"&x"18","00"&x"1c","00"&x"20","00"&x"26","00"&x"2d","00"&x"3a","00"&x"48","00"&x"61","00"&x"7e","00"&x"b1","00"&x"f2","01"&x"70","10"&x"1c",
"00"&x"14","00"&x"16","00"&x"18","00"&x"1b","00"&x"1e","00"&x"22","00"&x"28","00"&x"2f","00"&x"3c","00"&x"4a","00"&x"63","00"&x"80","00"&x"b3","00"&x"f4","01"&x"71","10"&x"1c",
"00"&x"17","00"&x"1a","00"&x"1c","00"&x"1e","00"&x"21","00"&x"25","00"&x"2c","00"&x"32","00"&x"3f","00"&x"4d","00"&x"66","00"&x"82","00"&x"b6","00"&x"f6","01"&x"72","10"&x"1d",
"00"&x"1b","00"&x"1d","00"&x"20","00"&x"22","00"&x"25","00"&x"29","00"&x"2f","00"&x"36","00"&x"42","00"&x"51","00"&x"6a","00"&x"85","00"&x"b9","00"&x"f9","01"&x"74","10"&x"1e",
"00"&x"21","00"&x"24","00"&x"26","00"&x"28","00"&x"2c","00"&x"2f","00"&x"35","00"&x"3c","00"&x"48","00"&x"57","00"&x"70","00"&x"8a","00"&x"be","00"&x"fe","01"&x"78","10"&x"1f",
"00"&x"29","00"&x"2b","00"&x"2d","00"&x"2f","00"&x"32","00"&x"36","00"&x"3c","00"&x"43","00"&x"4f","00"&x"5d","00"&x"76","00"&x"90","00"&x"c4","01"&x"03","01"&x"7c","10"&x"20",
"00"&x"35","00"&x"37","00"&x"3a","00"&x"3c","00"&x"3f","00"&x"42","00"&x"48","00"&x"4f","00"&x"5b","00"&x"69","00"&x"81","00"&x"9b","00"&x"ce","01"&x"0c","01"&x"84","10"&x"24",
"00"&x"43","00"&x"46","00"&x"48","00"&x"4a","00"&x"4d","00"&x"51","00"&x"57","00"&x"5d","00"&x"69","00"&x"77","00"&x"8d","00"&x"a8","00"&x"db","01"&x"16","01"&x"8e","10"&x"29",
"00"&x"5d","00"&x"5f","00"&x"61","00"&x"63","00"&x"66","00"&x"6a","00"&x"70","00"&x"76","00"&x"81","00"&x"8d","00"&x"a4","00"&x"bf","00"&x"f0","01"&x"2a","01"&x"9f","10"&x"35",
"00"&x"7a","00"&x"7c","00"&x"7e","00"&x"80","00"&x"82","00"&x"85","00"&x"8a","00"&x"90","00"&x"9b","00"&x"a8","00"&x"bf","00"&x"da","01"&x"09","01"&x"43","01"&x"b4","10"&x"44",
"00"&x"ad","00"&x"af","00"&x"b1","00"&x"b3","00"&x"b6","00"&x"b9","00"&x"be","00"&x"c4","00"&x"ce","00"&x"db","00"&x"f0","01"&x"09","01"&x"37","01"&x"71","01"&x"df","10"&x"69",
"00"&x"ef","00"&x"f1","00"&x"f2","00"&x"f4","00"&x"f6","00"&x"f9","00"&x"fe","01"&x"03","01"&x"0c","01"&x"16","01"&x"2a","01"&x"43","01"&x"71","01"&x"a8","10"&x"16","10"&x"9a",
"01"&x"6d","01"&x"6e","01"&x"70","01"&x"71","01"&x"72","01"&x"74","01"&x"78","01"&x"7c","01"&x"84","01"&x"8e","01"&x"9f","01"&x"b4","01"&x"df","10"&x"16","10"&x"79","10"&x"f3",
"10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1e","10"&x"1f","10"&x"20","10"&x"24","10"&x"29","10"&x"35","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"13","00"&x"16","00"&x"18","00"&x"1a","00"&x"1e","00"&x"21","00"&x"28","00"&x"2f","00"&x"3b","00"&x"4a","00"&x"63","00"&x"80","00"&x"b3","00"&x"f4","01"&x"71","10"&x"1d",
"00"&x"16","00"&x"19","00"&x"1b","00"&x"1d","00"&x"20","00"&x"24","00"&x"2a","00"&x"31","00"&x"3e","00"&x"4c","00"&x"65","00"&x"81","00"&x"b5","00"&x"f5","01"&x"72","10"&x"1d",
"00"&x"18","00"&x"1b","00"&x"1d","00"&x"1f","00"&x"22","00"&x"26","00"&x"2c","00"&x"33","00"&x"40","00"&x"4e","00"&x"67","00"&x"83","00"&x"b6","00"&x"f7","01"&x"73","10"&x"1d",
"00"&x"1a","00"&x"1d","00"&x"1f","00"&x"21","00"&x"24","00"&x"28","00"&x"2e","00"&x"35","00"&x"42","00"&x"50","00"&x"69","00"&x"84","00"&x"b8","00"&x"f8","01"&x"74","10"&x"1e",
"00"&x"1e","00"&x"20","00"&x"22","00"&x"24","00"&x"28","00"&x"2c","00"&x"32","00"&x"39","00"&x"45","00"&x"53","00"&x"6c","00"&x"87","00"&x"bb","00"&x"fb","01"&x"76","10"&x"1e",
"00"&x"21","00"&x"24","00"&x"26","00"&x"28","00"&x"2c","00"&x"2f","00"&x"35","00"&x"3c","00"&x"48","00"&x"57","00"&x"70","00"&x"8a","00"&x"be","00"&x"fe","01"&x"78","10"&x"1f",
"00"&x"28","00"&x"2a","00"&x"2c","00"&x"2e","00"&x"32","00"&x"35","00"&x"3c","00"&x"43","00"&x"4f","00"&x"5d","00"&x"75","00"&x"90","00"&x"c3","01"&x"02","01"&x"7c","10"&x"20",
"00"&x"2f","00"&x"31","00"&x"33","00"&x"35","00"&x"39","00"&x"3c","00"&x"43","00"&x"4a","00"&x"55","00"&x"63","00"&x"7c","00"&x"96","00"&x"c9","01"&x"08","01"&x"80","10"&x"21",
"00"&x"3b","00"&x"3e","00"&x"40","00"&x"42","00"&x"45","00"&x"48","00"&x"4f","00"&x"55","00"&x"61","00"&x"6f","00"&x"85","00"&x"a1","00"&x"d3","01"&x"10","01"&x"87","10"&x"25",
"00"&x"4a","00"&x"4c","00"&x"4e","00"&x"50","00"&x"53","00"&x"57","00"&x"5d","00"&x"63","00"&x"6f","00"&x"7d","00"&x"92","00"&x"ae","00"&x"e0","01"&x"1b","01"&x"91","10"&x"2a",
"00"&x"63","00"&x"65","00"&x"67","00"&x"69","00"&x"6c","00"&x"70","00"&x"75","00"&x"7c","00"&x"85","00"&x"92","00"&x"a9","00"&x"c4","00"&x"f5","01"&x"2f","01"&x"a1","10"&x"35",
"00"&x"80","00"&x"81","00"&x"83","00"&x"84","00"&x"87","00"&x"8a","00"&x"90","00"&x"96","00"&x"a1","00"&x"ae","00"&x"c4","00"&x"df","01"&x"0d","01"&x"47","01"&x"b6","10"&x"45",
"00"&x"b3","00"&x"b5","00"&x"b6","00"&x"b8","00"&x"bb","00"&x"be","00"&x"c3","00"&x"c9","00"&x"d3","00"&x"e0","00"&x"f5","01"&x"0d","01"&x"3b","01"&x"74","01"&x"e0","10"&x"69",
"00"&x"f4","00"&x"f5","00"&x"f7","00"&x"f8","00"&x"fb","00"&x"fe","01"&x"02","01"&x"08","01"&x"10","01"&x"1b","01"&x"2f","01"&x"47","01"&x"74","01"&x"aa","10"&x"17","10"&x"9a",
"01"&x"71","01"&x"72","01"&x"73","01"&x"74","01"&x"76","01"&x"78","01"&x"7c","01"&x"80","01"&x"87","01"&x"91","01"&x"a1","01"&x"b6","01"&x"e0","10"&x"17","10"&x"79","10"&x"f3",
"10"&x"1d","10"&x"1d","10"&x"1d","10"&x"1e","10"&x"1e","10"&x"1f","10"&x"20","10"&x"21","10"&x"25","10"&x"2a","10"&x"35","10"&x"45","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"1a","00"&x"1d","00"&x"1f","00"&x"21","00"&x"25","00"&x"29","00"&x"2f","00"&x"36","00"&x"42","00"&x"50","00"&x"6a","00"&x"85","00"&x"b9","00"&x"f9","01"&x"75","10"&x"1f",
"00"&x"1d","00"&x"20","00"&x"22","00"&x"24","00"&x"27","00"&x"2b","00"&x"31","00"&x"39","00"&x"45","00"&x"53","00"&x"6c","00"&x"87","00"&x"bb","00"&x"fb","01"&x"77","10"&x"1f",
"00"&x"1f","00"&x"22","00"&x"24","00"&x"26","00"&x"2a","00"&x"2d","00"&x"33","00"&x"3b","00"&x"47","00"&x"55","00"&x"6e","00"&x"89","00"&x"bd","00"&x"fc","01"&x"78","10"&x"1f",
"00"&x"21","00"&x"24","00"&x"26","00"&x"28","00"&x"2c","00"&x"2f","00"&x"35","00"&x"3d","00"&x"49","00"&x"57","00"&x"70","00"&x"8a","00"&x"be","00"&x"fe","01"&x"79","10"&x"1f",
"00"&x"25","00"&x"27","00"&x"2a","00"&x"2c","00"&x"2f","00"&x"32","00"&x"39","00"&x"40","00"&x"4c","00"&x"5a","00"&x"73","00"&x"8d","00"&x"c1","01"&x"00","01"&x"7a","10"&x"20",
"00"&x"29","00"&x"2b","00"&x"2d","00"&x"2f","00"&x"32","00"&x"36","00"&x"3c","00"&x"43","00"&x"4f","00"&x"5d","00"&x"76","00"&x"90","00"&x"c4","01"&x"03","01"&x"7c","10"&x"20",
"00"&x"2f","00"&x"31","00"&x"33","00"&x"35","00"&x"39","00"&x"3c","00"&x"43","00"&x"4a","00"&x"55","00"&x"63","00"&x"7c","00"&x"96","00"&x"c9","01"&x"08","01"&x"80","10"&x"21",
"00"&x"36","00"&x"39","00"&x"3b","00"&x"3d","00"&x"40","00"&x"43","00"&x"4a","00"&x"50","00"&x"5c","00"&x"6a","00"&x"82","00"&x"9c","00"&x"cf","01"&x"0c","01"&x"84","10"&x"23",
"00"&x"42","00"&x"45","00"&x"47","00"&x"49","00"&x"4c","00"&x"4f","00"&x"55","00"&x"5c","00"&x"68","00"&x"76","00"&x"8c","00"&x"a7","00"&x"d9","01"&x"15","01"&x"8b","10"&x"26",
"00"&x"50","00"&x"53","00"&x"55","00"&x"57","00"&x"5a","00"&x"5d","00"&x"63","00"&x"6a","00"&x"76","00"&x"82","00"&x"99","00"&x"b4","00"&x"e5","01"&x"20","01"&x"94","10"&x"2c",
"00"&x"6a","00"&x"6c","00"&x"6e","00"&x"70","00"&x"73","00"&x"76","00"&x"7c","00"&x"82","00"&x"8c","00"&x"99","00"&x"af","00"&x"ca","00"&x"fa","01"&x"33","01"&x"a4","10"&x"36",
"00"&x"85","00"&x"87","00"&x"89","00"&x"8a","00"&x"8d","00"&x"90","00"&x"96","00"&x"9c","00"&x"a7","00"&x"b4","00"&x"ca","00"&x"e4","01"&x"11","01"&x"4b","01"&x"b9","10"&x"46",
"00"&x"b9","00"&x"bb","00"&x"bd","00"&x"be","00"&x"c1","00"&x"c4","00"&x"c9","00"&x"cf","00"&x"d9","00"&x"e5","00"&x"fa","01"&x"11","01"&x"3f","01"&x"78","01"&x"e3","10"&x"6a",
"00"&x"f9","00"&x"fb","00"&x"fc","00"&x"fe","01"&x"00","01"&x"03","01"&x"08","01"&x"0c","01"&x"15","01"&x"20","01"&x"33","01"&x"4b","01"&x"78","01"&x"ad","10"&x"18","10"&x"9a",
"01"&x"75","01"&x"77","01"&x"78","01"&x"79","01"&x"7a","01"&x"7c","01"&x"80","01"&x"84","01"&x"8b","01"&x"94","01"&x"a4","01"&x"b9","01"&x"e3","10"&x"18","10"&x"79","10"&x"f3",
"10"&x"1f","10"&x"1f","10"&x"1f","10"&x"1f","10"&x"20","10"&x"20","10"&x"21","10"&x"23","10"&x"26","10"&x"2c","10"&x"36","10"&x"46","10"&x"6a","10"&x"9a","10"&x"f3","11"&x"61",
"00"&x"27","00"&x"2a","00"&x"2c","00"&x"2e","00"&x"31","00"&x"35","00"&x"3b","00"&x"42","00"&x"4e","00"&x"5c","00"&x"75","00"&x"90","00"&x"c3","01"&x"03","01"&x"7d","10"&x"22",
"00"&x"2a","00"&x"2c","00"&x"2e","00"&x"30","00"&x"34","00"&x"37","00"&x"3e","00"&x"45","00"&x"51","00"&x"5f","00"&x"78","00"&x"92","00"&x"c5","01"&x"05","01"&x"7f","10"&x"22",
"00"&x"2c","00"&x"2e","00"&x"30","00"&x"33","00"&x"36","00"&x"3a","00"&x"40","00"&x"47","00"&x"53","00"&x"61","00"&x"79","00"&x"94","00"&x"c7","01"&x"06","01"&x"7f","10"&x"23",
"00"&x"2e","00"&x"30","00"&x"33","00"&x"35","00"&x"38","00"&x"3c","00"&x"42","00"&x"49","00"&x"55","00"&x"63","00"&x"7b","00"&x"95","00"&x"c9","01"&x"08","01"&x"80","10"&x"23",
"00"&x"31","00"&x"34","00"&x"36","00"&x"38","00"&x"3b","00"&x"3f","00"&x"45","00"&x"4c","00"&x"58","00"&x"66","00"&x"7e","00"&x"98","00"&x"cb","01"&x"0a","01"&x"82","10"&x"23",
"00"&x"35","00"&x"37","00"&x"3a","00"&x"3c","00"&x"3f","00"&x"42","00"&x"48","00"&x"4f","00"&x"5b","00"&x"69","00"&x"81","00"&x"9b","00"&x"ce","01"&x"0c","01"&x"84","10"&x"24",
"00"&x"3b","00"&x"3e","00"&x"40","00"&x"42","00"&x"45","00"&x"48","00"&x"4f","00"&x"55","00"&x"61","00"&x"6f","00"&x"85","00"&x"a1","00"&x"d3","01"&x"10","01"&x"87","10"&x"25",
"00"&x"42","00"&x"45","00"&x"47","00"&x"49","00"&x"4c","00"&x"4f","00"&x"55","00"&x"5c","00"&x"68","00"&x"76","00"&x"8c","00"&x"a7","00"&x"d9","01"&x"15","01"&x"8b","10"&x"26",
"00"&x"4e","00"&x"51","00"&x"53","00"&x"55","00"&x"58","00"&x"5b","00"&x"61","00"&x"68","00"&x"74","00"&x"81","00"&x"97","00"&x"b2","00"&x"e3","01"&x"1e","01"&x"92","10"&x"2a",
"00"&x"5c","00"&x"5f","00"&x"61","00"&x"63","00"&x"66","00"&x"69","00"&x"6f","00"&x"76","00"&x"81","00"&x"8c","00"&x"a3","00"&x"be","00"&x"ef","01"&x"29","01"&x"9b","10"&x"2f",
"00"&x"75","00"&x"78","00"&x"79","00"&x"7b","00"&x"7e","00"&x"81","00"&x"85","00"&x"8c","00"&x"97","00"&x"a3","00"&x"ba","00"&x"d4","01"&x"03","01"&x"3c","01"&x"aa","10"&x"39",
"00"&x"90","00"&x"92","00"&x"94","00"&x"95","00"&x"98","00"&x"9b","00"&x"a1","00"&x"a7","00"&x"b2","00"&x"be","00"&x"d4","00"&x"ee","01"&x"1a","01"&x"53","01"&x"bf","10"&x"48",
"00"&x"c3","00"&x"c5","00"&x"c7","00"&x"c9","00"&x"cb","00"&x"ce","00"&x"d3","00"&x"d9","00"&x"e3","00"&x"ef","01"&x"03","01"&x"1a","01"&x"47","01"&x"7f","01"&x"e7","10"&x"6b",
"01"&x"03","01"&x"05","01"&x"06","01"&x"08","01"&x"0a","01"&x"0c","01"&x"10","01"&x"15","01"&x"1e","01"&x"29","01"&x"3c","01"&x"53","01"&x"7f","01"&x"b3","10"&x"1b","10"&x"9b",
"01"&x"7d","01"&x"7f","01"&x"7f","01"&x"80","01"&x"82","01"&x"84","01"&x"87","01"&x"8b","01"&x"92","01"&x"9b","01"&x"aa","01"&x"bf","01"&x"e7","10"&x"1b","10"&x"7a","10"&x"f3",
"10"&x"22","10"&x"22","10"&x"23","10"&x"23","10"&x"23","10"&x"24","10"&x"25","10"&x"26","10"&x"2a","10"&x"2f","10"&x"39","10"&x"48","10"&x"6b","10"&x"9b","10"&x"f3","11"&x"61",
"00"&x"36","00"&x"38","00"&x"3a","00"&x"3d","00"&x"40","00"&x"43","00"&x"4a","00"&x"50","00"&x"5c","00"&x"6a","00"&x"82","00"&x"9d","00"&x"d0","01"&x"0e","01"&x"87","10"&x"28",
"00"&x"38","00"&x"3b","00"&x"3d","00"&x"3f","00"&x"42","00"&x"46","00"&x"4c","00"&x"53","00"&x"5f","00"&x"6d","00"&x"84","00"&x"9f","00"&x"d2","01"&x"0f","01"&x"88","10"&x"28",
"00"&x"3a","00"&x"3d","00"&x"3f","00"&x"41","00"&x"44","00"&x"48","00"&x"4e","00"&x"55","00"&x"61","00"&x"6f","00"&x"85","00"&x"a1","00"&x"d4","01"&x"10","01"&x"89","10"&x"28",
"00"&x"3d","00"&x"3f","00"&x"41","00"&x"43","00"&x"46","00"&x"4a","00"&x"50","00"&x"57","00"&x"63","00"&x"71","00"&x"87","00"&x"a3","00"&x"d5","01"&x"12","01"&x"8a","10"&x"29",
"00"&x"40","00"&x"42","00"&x"44","00"&x"46","00"&x"4a","00"&x"4d","00"&x"53","00"&x"5a","00"&x"66","00"&x"74","00"&x"8a","00"&x"a5","00"&x"d8","01"&x"14","01"&x"8c","10"&x"29",
"00"&x"43","00"&x"46","00"&x"48","00"&x"4a","00"&x"4d","00"&x"51","00"&x"57","00"&x"5d","00"&x"69","00"&x"77","00"&x"8d","00"&x"a8","00"&x"db","01"&x"16","01"&x"8e","10"&x"29",
"00"&x"4a","00"&x"4c","00"&x"4e","00"&x"50","00"&x"53","00"&x"57","00"&x"5d","00"&x"63","00"&x"6f","00"&x"7d","00"&x"92","00"&x"ae","00"&x"e0","01"&x"1b","01"&x"91","10"&x"2a",
"00"&x"50","00"&x"53","00"&x"55","00"&x"57","00"&x"5a","00"&x"5d","00"&x"63","00"&x"6a","00"&x"76","00"&x"82","00"&x"99","00"&x"b4","00"&x"e5","01"&x"20","01"&x"94","10"&x"2c",
"00"&x"5c","00"&x"5f","00"&x"61","00"&x"63","00"&x"66","00"&x"69","00"&x"6f","00"&x"76","00"&x"81","00"&x"8c","00"&x"a3","00"&x"be","00"&x"ef","01"&x"29","01"&x"9b","10"&x"2f",
"00"&x"6a","00"&x"6d","00"&x"6f","00"&x"71","00"&x"74","00"&x"77","00"&x"7d","00"&x"82","00"&x"8c","00"&x"99","00"&x"b0","00"&x"cb","00"&x"fb","01"&x"33","01"&x"a2","10"&x"34",
"00"&x"82","00"&x"84","00"&x"85","00"&x"87","00"&x"8a","00"&x"8d","00"&x"92","00"&x"99","00"&x"a3","00"&x"b0","00"&x"c6","00"&x"e0","01"&x"0d","01"&x"46","01"&x"b2","10"&x"3d",
"00"&x"9d","00"&x"9f","00"&x"a1","00"&x"a3","00"&x"a5","00"&x"a8","00"&x"ae","00"&x"b4","00"&x"be","00"&x"cb","00"&x"e0","00"&x"f9","01"&x"25","01"&x"5d","01"&x"c6","10"&x"4c",
"00"&x"d0","00"&x"d2","00"&x"d4","00"&x"d5","00"&x"d8","00"&x"db","00"&x"e0","00"&x"e5","00"&x"ef","00"&x"fb","01"&x"0d","01"&x"25","01"&x"51","01"&x"87","01"&x"ed","10"&x"6e",
"01"&x"0e","01"&x"0f","01"&x"10","01"&x"12","01"&x"14","01"&x"16","01"&x"1b","01"&x"20","01"&x"29","01"&x"33","01"&x"46","01"&x"5d","01"&x"87","01"&x"ba","10"&x"20","10"&x"9c",
"01"&x"87","01"&x"88","01"&x"89","01"&x"8a","01"&x"8c","01"&x"8e","01"&x"91","01"&x"94","01"&x"9b","01"&x"a2","01"&x"b2","01"&x"c6","01"&x"ed","10"&x"20","10"&x"7c","10"&x"f3",
"10"&x"28","10"&x"28","10"&x"28","10"&x"29","10"&x"29","10"&x"29","10"&x"2a","10"&x"2c","10"&x"2f","10"&x"34","10"&x"3d","10"&x"4c","10"&x"6e","10"&x"9c","10"&x"f3","11"&x"61",
"00"&x"50","00"&x"52","00"&x"54","00"&x"56","00"&x"5a","00"&x"5d","00"&x"63","00"&x"6a","00"&x"75","00"&x"82","00"&x"98","00"&x"b4","00"&x"e6","01"&x"22","01"&x"99","10"&x"34",
"00"&x"52","00"&x"55","00"&x"57","00"&x"59","00"&x"5c","00"&x"5f","00"&x"65","00"&x"6c","00"&x"78","00"&x"84","00"&x"9a","00"&x"b6","00"&x"e8","01"&x"24","01"&x"9a","10"&x"34",
"00"&x"54","00"&x"57","00"&x"59","00"&x"5b","00"&x"5e","00"&x"61","00"&x"67","00"&x"6e","00"&x"79","00"&x"85","00"&x"9c","00"&x"b8","00"&x"ea","01"&x"25","01"&x"9b","10"&x"34",
"00"&x"56","00"&x"59","00"&x"5b","00"&x"5d","00"&x"60","00"&x"63","00"&x"69","00"&x"70","00"&x"7b","00"&x"87","00"&x"9e","00"&x"b9","00"&x"eb","01"&x"26","01"&x"9c","10"&x"34",
"00"&x"5a","00"&x"5c","00"&x"5e","00"&x"60","00"&x"63","00"&x"66","00"&x"6c","00"&x"73","00"&x"7e","00"&x"8a","00"&x"a1","00"&x"bc","00"&x"ed","01"&x"28","01"&x"9d","10"&x"34",
"00"&x"5d","00"&x"5f","00"&x"61","00"&x"63","00"&x"66","00"&x"6a","00"&x"70","00"&x"76","00"&x"81","00"&x"8d","00"&x"a4","00"&x"bf","00"&x"f0","01"&x"2a","01"&x"9f","10"&x"35",
"00"&x"63","00"&x"65","00"&x"67","00"&x"69","00"&x"6c","00"&x"70","00"&x"75","00"&x"7c","00"&x"85","00"&x"92","00"&x"a9","00"&x"c4","00"&x"f5","01"&x"2f","01"&x"a1","10"&x"35",
"00"&x"6a","00"&x"6c","00"&x"6e","00"&x"70","00"&x"73","00"&x"76","00"&x"7c","00"&x"82","00"&x"8c","00"&x"99","00"&x"af","00"&x"ca","00"&x"fa","01"&x"33","01"&x"a4","10"&x"36",
"00"&x"75","00"&x"78","00"&x"79","00"&x"7b","00"&x"7e","00"&x"81","00"&x"85","00"&x"8c","00"&x"97","00"&x"a3","00"&x"ba","00"&x"d4","01"&x"03","01"&x"3c","01"&x"aa","10"&x"39",
"00"&x"82","00"&x"84","00"&x"85","00"&x"87","00"&x"8a","00"&x"8d","00"&x"92","00"&x"99","00"&x"a3","00"&x"b0","00"&x"c6","00"&x"e0","01"&x"0d","01"&x"46","01"&x"b2","10"&x"3d",
"00"&x"98","00"&x"9a","00"&x"9c","00"&x"9e","00"&x"a1","00"&x"a4","00"&x"a9","00"&x"af","00"&x"ba","00"&x"c6","00"&x"dc","00"&x"f5","01"&x"21","01"&x"58","01"&x"c2","10"&x"47",
"00"&x"b4","00"&x"b6","00"&x"b8","00"&x"b9","00"&x"bc","00"&x"bf","00"&x"c4","00"&x"ca","00"&x"d4","00"&x"e0","00"&x"f5","01"&x"0c","01"&x"38","01"&x"6e","01"&x"d5","10"&x"55",
"00"&x"e6","00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ed","00"&x"f0","00"&x"f5","00"&x"fa","01"&x"03","01"&x"0d","01"&x"21","01"&x"38","01"&x"63","01"&x"97","01"&x"fa","10"&x"75",
"01"&x"22","01"&x"24","01"&x"25","01"&x"26","01"&x"28","01"&x"2a","01"&x"2f","01"&x"33","01"&x"3c","01"&x"46","01"&x"58","01"&x"6e","01"&x"97","01"&x"c8","10"&x"2a","10"&x"a0",
"01"&x"99","01"&x"9a","01"&x"9b","01"&x"9c","01"&x"9d","01"&x"9f","01"&x"a1","01"&x"a4","01"&x"aa","01"&x"b2","01"&x"c2","01"&x"d5","01"&x"fa","10"&x"2a","10"&x"82","10"&x"f5",
"10"&x"34","10"&x"34","10"&x"34","10"&x"34","10"&x"34","10"&x"35","10"&x"35","10"&x"36","10"&x"39","10"&x"3d","10"&x"47","10"&x"55","10"&x"75","10"&x"a0","10"&x"f5","11"&x"61",
"00"&x"6e","00"&x"70","00"&x"72","00"&x"74","00"&x"77","00"&x"7a","00"&x"80","00"&x"85","00"&x"90","00"&x"9d","00"&x"b4","00"&x"cf","01"&x"01","01"&x"3b","01"&x"af","10"&x"44",
"00"&x"70","00"&x"72","00"&x"74","00"&x"76","00"&x"79","00"&x"7c","00"&x"81","00"&x"87","00"&x"92","00"&x"9f","00"&x"b6","00"&x"d1","01"&x"02","01"&x"3d","01"&x"b0","10"&x"44",
"00"&x"72","00"&x"74","00"&x"76","00"&x"78","00"&x"7b","00"&x"7e","00"&x"83","00"&x"89","00"&x"94","00"&x"a1","00"&x"b8","00"&x"d3","01"&x"04","01"&x"3e","01"&x"b1","10"&x"44",
"00"&x"74","00"&x"76","00"&x"78","00"&x"7a","00"&x"7d","00"&x"80","00"&x"84","00"&x"8a","00"&x"95","00"&x"a3","00"&x"b9","00"&x"d4","01"&x"05","01"&x"3f","01"&x"b1","10"&x"44",
"00"&x"77","00"&x"79","00"&x"7b","00"&x"7d","00"&x"80","00"&x"82","00"&x"87","00"&x"8d","00"&x"98","00"&x"a5","00"&x"bc","00"&x"d7","01"&x"07","01"&x"41","01"&x"b2","10"&x"44",
"00"&x"7a","00"&x"7c","00"&x"7e","00"&x"80","00"&x"82","00"&x"85","00"&x"8a","00"&x"90","00"&x"9b","00"&x"a8","00"&x"bf","00"&x"da","01"&x"09","01"&x"43","01"&x"b4","10"&x"44",
"00"&x"80","00"&x"81","00"&x"83","00"&x"84","00"&x"87","00"&x"8a","00"&x"90","00"&x"96","00"&x"a1","00"&x"ae","00"&x"c4","00"&x"df","01"&x"0d","01"&x"47","01"&x"b6","10"&x"45",
"00"&x"85","00"&x"87","00"&x"89","00"&x"8a","00"&x"8d","00"&x"90","00"&x"96","00"&x"9c","00"&x"a7","00"&x"b4","00"&x"ca","00"&x"e4","01"&x"11","01"&x"4b","01"&x"b9","10"&x"46",
"00"&x"90","00"&x"92","00"&x"94","00"&x"95","00"&x"98","00"&x"9b","00"&x"a1","00"&x"a7","00"&x"b2","00"&x"be","00"&x"d4","00"&x"ee","01"&x"1a","01"&x"53","01"&x"bf","10"&x"48",
"00"&x"9d","00"&x"9f","00"&x"a1","00"&x"a3","00"&x"a5","00"&x"a8","00"&x"ae","00"&x"b4","00"&x"be","00"&x"cb","00"&x"e0","00"&x"f9","01"&x"25","01"&x"5d","01"&x"c6","10"&x"4c",
"00"&x"b4","00"&x"b6","00"&x"b8","00"&x"b9","00"&x"bc","00"&x"bf","00"&x"c4","00"&x"ca","00"&x"d4","00"&x"e0","00"&x"f5","01"&x"0c","01"&x"38","01"&x"6e","01"&x"d5","10"&x"55",
"00"&x"cf","00"&x"d1","00"&x"d3","00"&x"d4","00"&x"d7","00"&x"da","00"&x"df","00"&x"e4","00"&x"ee","00"&x"f9","01"&x"0c","01"&x"23","01"&x"4e","01"&x"84","01"&x"e7","10"&x"63",
"01"&x"01","01"&x"02","01"&x"04","01"&x"05","01"&x"07","01"&x"09","01"&x"0d","01"&x"11","01"&x"1a","01"&x"25","01"&x"38","01"&x"4e","01"&x"78","01"&x"a9","10"&x"0b","10"&x"80",
"01"&x"3b","01"&x"3d","01"&x"3e","01"&x"3f","01"&x"41","01"&x"43","01"&x"47","01"&x"4b","01"&x"53","01"&x"5d","01"&x"6e","01"&x"84","01"&x"a9","01"&x"da","10"&x"37","10"&x"a9",
"01"&x"af","01"&x"b0","01"&x"b1","01"&x"b1","01"&x"b2","01"&x"b4","01"&x"b6","01"&x"b9","01"&x"bf","01"&x"c6","01"&x"d5","01"&x"e7","10"&x"0b","10"&x"37","10"&x"8c","10"&x"f9",
"10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"45","10"&x"46","10"&x"48","10"&x"4c","10"&x"55","10"&x"63","10"&x"80","10"&x"a9","10"&x"f9","11"&x"61",
"00"&x"a1","00"&x"a4","00"&x"a5","00"&x"a7","00"&x"aa","00"&x"ad","00"&x"b3","00"&x"b9","00"&x"c3","00"&x"d0","00"&x"e6","01"&x"01","01"&x"2f","01"&x"6a","01"&x"dc","10"&x"69",
"00"&x"a4","00"&x"a6","00"&x"a8","00"&x"a9","00"&x"ac","00"&x"af","00"&x"b5","00"&x"bb","00"&x"c5","00"&x"d2","00"&x"e8","01"&x"02","01"&x"31","01"&x"6c","01"&x"dc","10"&x"69",
"00"&x"a5","00"&x"a8","00"&x"a9","00"&x"ab","00"&x"ae","00"&x"b1","00"&x"b6","00"&x"bd","00"&x"c7","00"&x"d4","00"&x"ea","01"&x"04","01"&x"32","01"&x"6c","01"&x"dd","10"&x"69",
"00"&x"a7","00"&x"a9","00"&x"ab","00"&x"ad","00"&x"b0","00"&x"b3","00"&x"b8","00"&x"be","00"&x"c9","00"&x"d5","00"&x"eb","01"&x"05","01"&x"33","01"&x"6d","01"&x"dd","10"&x"69",
"00"&x"aa","00"&x"ac","00"&x"ae","00"&x"b0","00"&x"b2","00"&x"b6","00"&x"bb","00"&x"c1","00"&x"cb","00"&x"d8","00"&x"ed","01"&x"07","01"&x"35","01"&x"6f","01"&x"de","10"&x"69",
"00"&x"ad","00"&x"af","00"&x"b1","00"&x"b3","00"&x"b6","00"&x"b9","00"&x"be","00"&x"c4","00"&x"ce","00"&x"db","00"&x"f0","01"&x"09","01"&x"37","01"&x"71","01"&x"df","10"&x"69",
"00"&x"b3","00"&x"b5","00"&x"b6","00"&x"b8","00"&x"bb","00"&x"be","00"&x"c3","00"&x"c9","00"&x"d3","00"&x"e0","00"&x"f5","01"&x"0d","01"&x"3b","01"&x"74","01"&x"e0","10"&x"69",
"00"&x"b9","00"&x"bb","00"&x"bd","00"&x"be","00"&x"c1","00"&x"c4","00"&x"c9","00"&x"cf","00"&x"d9","00"&x"e5","00"&x"fa","01"&x"11","01"&x"3f","01"&x"78","01"&x"e3","10"&x"6a",
"00"&x"c3","00"&x"c5","00"&x"c7","00"&x"c9","00"&x"cb","00"&x"ce","00"&x"d3","00"&x"d9","00"&x"e3","00"&x"ef","01"&x"03","01"&x"1a","01"&x"47","01"&x"7f","01"&x"e7","10"&x"6b",
"00"&x"d0","00"&x"d2","00"&x"d4","00"&x"d5","00"&x"d8","00"&x"db","00"&x"e0","00"&x"e5","00"&x"ef","00"&x"fb","01"&x"0d","01"&x"25","01"&x"51","01"&x"87","01"&x"ed","10"&x"6e",
"00"&x"e6","00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ed","00"&x"f0","00"&x"f5","00"&x"fa","01"&x"03","01"&x"0d","01"&x"21","01"&x"38","01"&x"63","01"&x"97","01"&x"fa","10"&x"75",
"01"&x"01","01"&x"02","01"&x"04","01"&x"05","01"&x"07","01"&x"09","01"&x"0d","01"&x"11","01"&x"1a","01"&x"25","01"&x"38","01"&x"4e","01"&x"78","01"&x"a9","10"&x"0b","10"&x"80",
"01"&x"2f","01"&x"31","01"&x"32","01"&x"33","01"&x"35","01"&x"37","01"&x"3b","01"&x"3f","01"&x"47","01"&x"51","01"&x"63","01"&x"78","01"&x"9e","01"&x"ce","10"&x"2c","10"&x"9b",
"01"&x"6a","01"&x"6c","01"&x"6c","01"&x"6d","01"&x"6f","01"&x"71","01"&x"74","01"&x"78","01"&x"7f","01"&x"87","01"&x"97","01"&x"a9","01"&x"ce","01"&x"fd","10"&x"54","10"&x"c0",
"01"&x"dc","01"&x"dc","01"&x"dd","01"&x"dd","01"&x"de","01"&x"df","01"&x"e0","01"&x"e3","01"&x"e7","01"&x"ed","01"&x"fa","10"&x"0b","10"&x"2c","10"&x"54","10"&x"a4","11"&x"09",
"10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"6a","10"&x"6b","10"&x"6e","10"&x"75","10"&x"80","10"&x"9b","10"&x"c0","11"&x"09","11"&x"67",
"00"&x"e4","00"&x"e6","00"&x"e8","00"&x"e9","00"&x"ec","00"&x"ef","00"&x"f4","00"&x"f9","01"&x"03","01"&x"0e","01"&x"22","01"&x"3b","01"&x"6a","01"&x"a3","10"&x"14","10"&x"9a",
"00"&x"e6","00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ee","00"&x"f1","00"&x"f5","00"&x"fb","01"&x"05","01"&x"0f","01"&x"24","01"&x"3d","01"&x"6c","01"&x"a4","10"&x"14","10"&x"9a",
"00"&x"e8","00"&x"ea","00"&x"eb","00"&x"ed","00"&x"ef","00"&x"f2","00"&x"f7","00"&x"fc","01"&x"06","01"&x"10","01"&x"25","01"&x"3e","01"&x"6c","01"&x"a5","10"&x"15","10"&x"9a",
"00"&x"e9","00"&x"eb","00"&x"ed","00"&x"ee","00"&x"f1","00"&x"f4","00"&x"f8","00"&x"fe","01"&x"08","01"&x"12","01"&x"26","01"&x"3f","01"&x"6d","01"&x"a5","10"&x"15","10"&x"9a",
"00"&x"ec","00"&x"ee","00"&x"ef","00"&x"f1","00"&x"f3","00"&x"f6","00"&x"fb","01"&x"00","01"&x"0a","01"&x"14","01"&x"28","01"&x"41","01"&x"6f","01"&x"a6","10"&x"15","10"&x"9a",
"00"&x"ef","00"&x"f1","00"&x"f2","00"&x"f4","00"&x"f6","00"&x"f9","00"&x"fe","01"&x"03","01"&x"0c","01"&x"16","01"&x"2a","01"&x"43","01"&x"71","01"&x"a8","10"&x"16","10"&x"9a",
"00"&x"f4","00"&x"f5","00"&x"f7","00"&x"f8","00"&x"fb","00"&x"fe","01"&x"02","01"&x"08","01"&x"10","01"&x"1b","01"&x"2f","01"&x"47","01"&x"74","01"&x"aa","10"&x"17","10"&x"9a",
"00"&x"f9","00"&x"fb","00"&x"fc","00"&x"fe","01"&x"00","01"&x"03","01"&x"08","01"&x"0c","01"&x"15","01"&x"20","01"&x"33","01"&x"4b","01"&x"78","01"&x"ad","10"&x"18","10"&x"9a",
"01"&x"03","01"&x"05","01"&x"06","01"&x"08","01"&x"0a","01"&x"0c","01"&x"10","01"&x"15","01"&x"1e","01"&x"29","01"&x"3c","01"&x"53","01"&x"7f","01"&x"b3","10"&x"1b","10"&x"9b",
"01"&x"0e","01"&x"0f","01"&x"10","01"&x"12","01"&x"14","01"&x"16","01"&x"1b","01"&x"20","01"&x"29","01"&x"33","01"&x"46","01"&x"5d","01"&x"87","01"&x"ba","10"&x"20","10"&x"9c",
"01"&x"22","01"&x"24","01"&x"25","01"&x"26","01"&x"28","01"&x"2a","01"&x"2f","01"&x"33","01"&x"3c","01"&x"46","01"&x"58","01"&x"6e","01"&x"97","01"&x"c8","10"&x"2a","10"&x"a0",
"01"&x"3b","01"&x"3d","01"&x"3e","01"&x"3f","01"&x"41","01"&x"43","01"&x"47","01"&x"4b","01"&x"53","01"&x"5d","01"&x"6e","01"&x"84","01"&x"a9","01"&x"da","10"&x"37","10"&x"a9",
"01"&x"6a","01"&x"6c","01"&x"6c","01"&x"6d","01"&x"6f","01"&x"71","01"&x"74","01"&x"78","01"&x"7f","01"&x"87","01"&x"97","01"&x"a9","01"&x"ce","01"&x"fd","10"&x"54","10"&x"c0",
"01"&x"a3","01"&x"a4","01"&x"a5","01"&x"a5","01"&x"a6","01"&x"a8","01"&x"aa","01"&x"ad","01"&x"b3","01"&x"ba","01"&x"c8","01"&x"da","01"&x"fd","10"&x"29","10"&x"7b","10"&x"e0",
"10"&x"14","10"&x"14","10"&x"15","10"&x"15","10"&x"15","10"&x"16","10"&x"17","10"&x"18","10"&x"1b","10"&x"20","10"&x"2a","10"&x"37","10"&x"54","10"&x"7b","10"&x"c6","11"&x"25",
"10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9b","10"&x"9c","10"&x"a0","10"&x"a9","10"&x"c0","10"&x"e0","11"&x"25","11"&x"7a",
"01"&x"66","01"&x"67","01"&x"68","01"&x"69","01"&x"6b","01"&x"6d","01"&x"71","01"&x"75","01"&x"7d","01"&x"87","01"&x"99","01"&x"af","01"&x"dc","10"&x"14","10"&x"79","10"&x"f3",
"01"&x"67","01"&x"68","01"&x"6a","01"&x"6b","01"&x"6c","01"&x"6e","01"&x"72","01"&x"77","01"&x"7f","01"&x"88","01"&x"9a","01"&x"b0","01"&x"dc","10"&x"14","10"&x"79","10"&x"f3",
"01"&x"68","01"&x"6a","01"&x"6b","01"&x"6c","01"&x"6e","01"&x"70","01"&x"73","01"&x"78","01"&x"7f","01"&x"89","01"&x"9b","01"&x"b1","01"&x"dd","10"&x"15","10"&x"79","10"&x"f3",
"01"&x"69","01"&x"6b","01"&x"6c","01"&x"6d","01"&x"6f","01"&x"71","01"&x"74","01"&x"79","01"&x"80","01"&x"8a","01"&x"9c","01"&x"b1","01"&x"dd","10"&x"15","10"&x"79","10"&x"f3",
"01"&x"6b","01"&x"6c","01"&x"6e","01"&x"6f","01"&x"70","01"&x"72","01"&x"76","01"&x"7a","01"&x"82","01"&x"8c","01"&x"9d","01"&x"b2","01"&x"de","10"&x"15","10"&x"79","10"&x"f3",
"01"&x"6d","01"&x"6e","01"&x"70","01"&x"71","01"&x"72","01"&x"74","01"&x"78","01"&x"7c","01"&x"84","01"&x"8e","01"&x"9f","01"&x"b4","01"&x"df","10"&x"16","10"&x"79","10"&x"f3",
"01"&x"71","01"&x"72","01"&x"73","01"&x"74","01"&x"76","01"&x"78","01"&x"7c","01"&x"80","01"&x"87","01"&x"91","01"&x"a1","01"&x"b6","01"&x"e0","10"&x"17","10"&x"79","10"&x"f3",
"01"&x"75","01"&x"77","01"&x"78","01"&x"79","01"&x"7a","01"&x"7c","01"&x"80","01"&x"84","01"&x"8b","01"&x"94","01"&x"a4","01"&x"b9","01"&x"e3","10"&x"18","10"&x"79","10"&x"f3",
"01"&x"7d","01"&x"7f","01"&x"7f","01"&x"80","01"&x"82","01"&x"84","01"&x"87","01"&x"8b","01"&x"92","01"&x"9b","01"&x"aa","01"&x"bf","01"&x"e7","10"&x"1b","10"&x"7a","10"&x"f3",
"01"&x"87","01"&x"88","01"&x"89","01"&x"8a","01"&x"8c","01"&x"8e","01"&x"91","01"&x"94","01"&x"9b","01"&x"a2","01"&x"b2","01"&x"c6","01"&x"ed","10"&x"20","10"&x"7c","10"&x"f3",
"01"&x"99","01"&x"9a","01"&x"9b","01"&x"9c","01"&x"9d","01"&x"9f","01"&x"a1","01"&x"a4","01"&x"aa","01"&x"b2","01"&x"c2","01"&x"d5","01"&x"fa","10"&x"2a","10"&x"82","10"&x"f5",
"01"&x"af","01"&x"b0","01"&x"b1","01"&x"b1","01"&x"b2","01"&x"b4","01"&x"b6","01"&x"b9","01"&x"bf","01"&x"c6","01"&x"d5","01"&x"e7","10"&x"0b","10"&x"37","10"&x"8c","10"&x"f9",
"01"&x"dc","01"&x"dc","01"&x"dd","01"&x"dd","01"&x"de","01"&x"df","01"&x"e0","01"&x"e3","01"&x"e7","01"&x"ed","01"&x"fa","10"&x"0b","10"&x"2c","10"&x"54","10"&x"a4","11"&x"09",
"10"&x"14","10"&x"14","10"&x"15","10"&x"15","10"&x"15","10"&x"16","10"&x"17","10"&x"18","10"&x"1b","10"&x"20","10"&x"2a","10"&x"37","10"&x"54","10"&x"7b","10"&x"c6","11"&x"25",
"10"&x"79","10"&x"79","10"&x"79","10"&x"79","10"&x"79","10"&x"79","10"&x"79","10"&x"79","10"&x"7a","10"&x"7c","10"&x"82","10"&x"8c","10"&x"a4","10"&x"c6","11"&x"0c","11"&x"62",
"10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f5","10"&x"f9","11"&x"09","11"&x"25","11"&x"62","11"&x"b1",
"10"&x"1a","10"&x"1a","10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"22","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"22","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1a","10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1f","10"&x"23","10"&x"28","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1b","10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1e","10"&x"1f","10"&x"23","10"&x"29","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1b","10"&x"1b","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1e","10"&x"20","10"&x"23","10"&x"29","10"&x"34","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1c","10"&x"1d","10"&x"1e","10"&x"1f","10"&x"20","10"&x"24","10"&x"29","10"&x"35","10"&x"44","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1d","10"&x"1d","10"&x"1d","10"&x"1e","10"&x"1e","10"&x"1f","10"&x"20","10"&x"21","10"&x"25","10"&x"2a","10"&x"35","10"&x"45","10"&x"69","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"1f","10"&x"1f","10"&x"1f","10"&x"1f","10"&x"20","10"&x"20","10"&x"21","10"&x"23","10"&x"26","10"&x"2c","10"&x"36","10"&x"46","10"&x"6a","10"&x"9a","10"&x"f3","11"&x"61",
"10"&x"22","10"&x"22","10"&x"23","10"&x"23","10"&x"23","10"&x"24","10"&x"25","10"&x"26","10"&x"2a","10"&x"2f","10"&x"39","10"&x"48","10"&x"6b","10"&x"9b","10"&x"f3","11"&x"61",
"10"&x"28","10"&x"28","10"&x"28","10"&x"29","10"&x"29","10"&x"29","10"&x"2a","10"&x"2c","10"&x"2f","10"&x"34","10"&x"3d","10"&x"4c","10"&x"6e","10"&x"9c","10"&x"f3","11"&x"61",
"10"&x"34","10"&x"34","10"&x"34","10"&x"34","10"&x"34","10"&x"35","10"&x"35","10"&x"36","10"&x"39","10"&x"3d","10"&x"47","10"&x"55","10"&x"75","10"&x"a0","10"&x"f5","11"&x"61",
"10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"44","10"&x"45","10"&x"46","10"&x"48","10"&x"4c","10"&x"55","10"&x"63","10"&x"80","10"&x"a9","10"&x"f9","11"&x"61",
"10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"69","10"&x"6a","10"&x"6b","10"&x"6e","10"&x"75","10"&x"80","10"&x"9b","10"&x"c0","11"&x"09","11"&x"67",
"10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9a","10"&x"9b","10"&x"9c","10"&x"a0","10"&x"a9","10"&x"c0","10"&x"e0","11"&x"25","11"&x"7a",
"10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f3","10"&x"f5","10"&x"f9","11"&x"09","11"&x"25","11"&x"62","11"&x"b1",
"11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"61","11"&x"67","11"&x"7a","11"&x"b1","11"&x"f9"
);
signal ROM : ROM_ARRAY := voltable;
begin
process(CLK)
begin
if rising_edge(CLK) then
DATA_A <= ROM(to_integer(unsigned(ADDR_A)));
DATA_B <= ROM(to_integer(unsigned(ADDR_B)));
end if;
end process;
end RTL;