mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-03-10 12:28:26 +00:00
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
293
common/Sound/ym2149/vol_table_array.vhd
Normal file
293
common/Sound/ym2149/vol_table_array.vhd
Normal 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;
|
||||
Reference in New Issue
Block a user