1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-04-29 13:32:38 +00:00

Irem HW: use common PSG

This commit is contained in:
Gyorgy Szombathelyi
2020-08-01 17:43:55 +02:00
parent 4dd702f4ef
commit 6b1d389f37
13 changed files with 241 additions and 1640 deletions

View File

@@ -41,7 +41,7 @@
# ========================
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "12.1 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "09:07:52 FEBRUARY 01, 2013"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:src/build_id.tcl"
@@ -204,7 +204,6 @@ set_global_assignment -name VHDL_FILE src/video_controller_pkg.vhd
set_global_assignment -name VHDL_FILE src/video_controller.vhd
set_global_assignment -name VHDL_FILE src/moon_patrol_sound_board.vhd
set_global_assignment -name VHDL_FILE src/moon_patrol_sound_prog.vhd
set_global_assignment -name SYSTEMVERILOG_FILE src/YM2149.sv
set_global_assignment -name VHDL_FILE src/Z80.vhd
set_global_assignment -name VHDL_FILE src/tilemapctl.vhd
set_global_assignment -name VHDL_FILE src/sprom.vhd
@@ -229,4 +228,6 @@ set_global_assignment -name VHDL_FILE src/build_id.vhd
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/CPU/6800/cpu68.vhd
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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,4 +0,0 @@
{ "" "" "" "*" { } { } 0 10873 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 10296 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 19016 "" 0 0 "Quartus II" 0 -1 0 ""}

View File

@@ -1,329 +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 A8,
input A9_L,
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];
wire cs = !A9_L & A8;
// 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(cs & 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(cs & ~BDIR & BC & !addr[7:4]) begin
case(addr[3:0])
0: dout = ymreg[0];
1: dout = ymreg[1][3:0];
2: dout = ymreg[2];
3: dout = ymreg[3][3:0];
4: dout = ymreg[4];
5: dout = ymreg[5][3:0];
6: dout = ymreg[6][4:0];
7: dout = ymreg[7];
8: dout = ymreg[8][4:0];
9: dout = ymreg[9][4:0];
10: dout = ymreg[10][4:0];
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = ymreg[13][3:0];
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase
end
end
reg ena_div;
reg ena_div_noise;
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
reg noise_div;
if(CE) begin
ena_div <= 0;
ena_div_noise <= 0;
if(!cnt_div) begin
cnt_div <= {SEL, 3'b111};
ena_div <= 1;
noise_div <= (~noise_div);
if (noise_div) ena_div_noise <= 1;
end else begin
cnt_div <= cnt_div - 1'b1;
end
end
end
reg [2:0] noise_gen_op;
// p_noise_gen
always @(posedge CLK) begin
reg [16:0] poly17;
reg [4:0] noise_gen_cnt;
if(CE) begin
if (ena_div_noise) begin
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
noise_gen_cnt <= 0;
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
noise_gen_op <= {3{poly17[0]}};
end
end
end
wire [11:0] tone_gen_freq[1:3];
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
reg [3:1] tone_gen_op;
//p_tone_gens
always @(posedge CLK) begin
integer i;
reg [11:0] tone_gen_cnt[1:3];
if(CE) begin
// looks like real chips count up - we need to get the Exact behaviour ..
for (i = 1; i <= 3; i = i + 1) begin
if(ena_div) begin
if (tone_gen_freq[i]) begin
if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
tone_gen_cnt[i] <= 0;
tone_gen_op[i] <= ~tone_gen_op[i];
end else begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end else begin
tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0;
end
end
end
end
end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
always @(posedge CLK) begin
reg [15:0] env_gen_cnt;
if(CE) begin
env_ena <= 0;
if(ena_div) begin
if (env_gen_cnt >= env_gen_comp) begin
env_gen_cnt <= 0;
env_ena <= 1;
end else begin
env_gen_cnt <= (env_gen_cnt + 1'd1);
end
end
end
end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg env_hold;
reg env_inc;
// envelope shapes
// C AtAlH
// 0 0 x x \___
//
// 0 1 x x /___
//
// 1 0 0 0 \\\\
//
// 1 0 0 1 \___
//
// 1 0 1 0 \/\/
// ___
// 1 0 1 1 \
//
// 1 1 0 0 ////
// ___
// 1 1 0 1 /
//
// 1 1 1 0 /\/\
//
// 1 1 1 1 /___
if(env_reset | RESET) begin
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end
else if(CE) begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
end
end
end
reg [5:0] A,B,C;
always @(posedge CLK) begin
A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
end
wire [7:0] volTable[64] = '{
//YM2149
8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
//AY8910
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
};
assign CHANNEL_A = volTable[A];
assign CHANNEL_B = volTable[B];
assign CHANNEL_C = volTable[C];
endmodule

View File

@@ -37,35 +37,9 @@ port(
end moon_patrol_sound_board;
architecture struct of moon_patrol_sound_board is
component YM2149
port (
CLK : in std_logic;
CE : in std_logic;
RESET : in std_logic;
A8 : in std_logic := '1';
A9_L : in std_logic := '0';
BDIR : in std_logic; -- Bus Direction (0 - read , 1 - write)
BC : in std_logic; -- Bus control
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
CHANNEL_A : out std_logic_vector(7 downto 0);
CHANNEL_B : out std_logic_vector(7 downto 0);
CHANNEL_C : out std_logic_vector(7 downto 0);
SEL : in std_logic;
MODE : in std_logic;
ACTIVE : out std_logic_vector(5 downto 0);
IOA_in : in std_logic_vector(7 downto 0);
IOA_out : out std_logic_vector(7 downto 0);
IOB_in : in std_logic_vector(7 downto 0);
IOB_out : out std_logic_vector(7 downto 0)
);
end component;
signal reset : std_logic := '1';
signal reset_n : std_logic;
signal reset_cnt : integer range 0 to 1000000 := 1000000;
signal cpu_addr : std_logic_vector(15 downto 0);
@@ -155,6 +129,7 @@ architecture struct of moon_patrol_sound_board is
begin
dbg_cpu_addr <= cpu_addr;
reset_n <= not reset;
-- cs
wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF
@@ -363,62 +338,66 @@ port map(
q => wram_do
);
ay83910_inst1: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(4),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay1_do,
CHANNEL_A => ay1_chan_a,
CHANNEL_B => ay1_chan_b,
CHANNEL_C => ay1_chan_c,
-- AY-3-8910 #1
ay_3_8910_1 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay1_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(4), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
O_AUDIO_L => ay1_audio, -- out std_logic_vector(9 downto 0);
SEL => '0',
MODE => '1',
-- port a
I_IOA => select_sound, -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => ay1_port_b_do, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
ACTIVE => open,
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
IOA_in => select_sound_r,
IOA_out => open,
-- AY-3-8910 #2
ay_3_8910_2 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay2_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(3), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
IOB_in => (others => '0'),
IOB_out => ay1_port_b_do
);
O_AUDIO_L => ay2_audio, -- out std_logic_vector(9 downto 0);
ay1_audio <= "0000000000" + ay1_chan_a + ay1_chan_b + ay1_chan_c;
ay83910_inst2: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(3),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay2_do,
CHANNEL_A => ay2_chan_a,
CHANNEL_B => ay2_chan_b,
CHANNEL_C => ay2_chan_c,
SEL => '0',
MODE => '1',
ACTIVE => open,
IOA_in => (others => '0'),
IOA_out => open,
IOB_in => (others => '0'),
IOB_out => open
);
ay2_audio <= "0000000000" + ay2_chan_a + ay2_chan_b + ay2_chan_c;
-- port a
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => open, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
end struct;

View File

@@ -151,7 +151,7 @@ set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name TOP_LEVEL_ENTITY TraverseUSA_MiST
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
@@ -188,11 +188,12 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/TraverseUSA_MiST.sv
set_global_assignment -name VHDL_FILE rtl/traverse_usa.vhd
set_global_assignment -name VHDL_FILE rtl/moon_patrol_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/YM2149.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/dpram.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 VHDL_FILE ../../../common/CPU/6800/cpu68.vhd
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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,329 +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 A8,
input A9_L,
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];
wire cs = !A9_L & A8;
// 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(cs & 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(cs & ~BDIR & BC & !addr[7:4]) begin
case(addr[3:0])
0: dout = ymreg[0];
1: dout = ymreg[1][3:0];
2: dout = ymreg[2];
3: dout = ymreg[3][3:0];
4: dout = ymreg[4];
5: dout = ymreg[5][3:0];
6: dout = ymreg[6][4:0];
7: dout = ymreg[7];
8: dout = ymreg[8][4:0];
9: dout = ymreg[9][4:0];
10: dout = ymreg[10][4:0];
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = ymreg[13][3:0];
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase
end
end
reg ena_div;
reg ena_div_noise;
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
reg noise_div;
if(CE) begin
ena_div <= 0;
ena_div_noise <= 0;
if(!cnt_div) begin
cnt_div <= {SEL, 3'b111};
ena_div <= 1;
noise_div <= (~noise_div);
if (noise_div) ena_div_noise <= 1;
end else begin
cnt_div <= cnt_div - 1'b1;
end
end
end
reg [2:0] noise_gen_op;
// p_noise_gen
always @(posedge CLK) begin
reg [16:0] poly17;
reg [4:0] noise_gen_cnt;
if(CE) begin
if (ena_div_noise) begin
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
noise_gen_cnt <= 0;
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
noise_gen_op <= {3{poly17[0]}};
end
end
end
wire [11:0] tone_gen_freq[1:3];
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
reg [3:1] tone_gen_op;
//p_tone_gens
always @(posedge CLK) begin
integer i;
reg [11:0] tone_gen_cnt[1:3];
if(CE) begin
// looks like real chips count up - we need to get the Exact behaviour ..
for (i = 1; i <= 3; i = i + 1) begin
if(ena_div) begin
if (tone_gen_freq[i]) begin
if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
tone_gen_cnt[i] <= 0;
tone_gen_op[i] <= ~tone_gen_op[i];
end else begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end else begin
tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0;
end
end
end
end
end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
always @(posedge CLK) begin
reg [15:0] env_gen_cnt;
if(CE) begin
env_ena <= 0;
if(ena_div) begin
if (env_gen_cnt >= env_gen_comp) begin
env_gen_cnt <= 0;
env_ena <= 1;
end else begin
env_gen_cnt <= (env_gen_cnt + 1'd1);
end
end
end
end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg env_hold;
reg env_inc;
// envelope shapes
// C AtAlH
// 0 0 x x \___
//
// 0 1 x x /___
//
// 1 0 0 0 \\\\
//
// 1 0 0 1 \___
//
// 1 0 1 0 \/\/
// ___
// 1 0 1 1 \
//
// 1 1 0 0 ////
// ___
// 1 1 0 1 /
//
// 1 1 1 0 /\/\
//
// 1 1 1 1 /___
if(env_reset | RESET) begin
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end
else if(CE) begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
end
end
end
reg [5:0] A,B,C;
always @(posedge CLK) begin
A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
end
wire [7:0] volTable[64] = '{
//YM2149
8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
//AY8910
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
};
assign CHANNEL_A = volTable[A];
assign CHANNEL_B = volTable[B];
assign CHANNEL_C = volTable[C];
endmodule

View File

@@ -40,35 +40,9 @@ port(
end moon_patrol_sound_board;
architecture struct of moon_patrol_sound_board is
component YM2149
port (
CLK : in std_logic;
CE : in std_logic;
RESET : in std_logic;
A8 : in std_logic := '1';
A9_L : in std_logic := '0';
BDIR : in std_logic; -- Bus Direction (0 - read , 1 - write)
BC : in std_logic; -- Bus control
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
CHANNEL_A : out std_logic_vector(7 downto 0);
CHANNEL_B : out std_logic_vector(7 downto 0);
CHANNEL_C : out std_logic_vector(7 downto 0);
SEL : in std_logic;
MODE : in std_logic;
ACTIVE : out std_logic_vector(5 downto 0);
IOA_in : in std_logic_vector(7 downto 0);
IOA_out : out std_logic_vector(7 downto 0);
IOB_in : in std_logic_vector(7 downto 0);
IOB_out : out std_logic_vector(7 downto 0)
);
end component;
signal reset : std_logic := '1';
signal reset_n : std_logic;
signal reset_cnt : integer range 0 to 1000000 := 1000000;
signal cpu_addr : std_logic_vector(15 downto 0);
@@ -158,6 +132,7 @@ architecture struct of moon_patrol_sound_board is
begin
dbg_cpu_addr <= cpu_addr;
reset_n <= not reset;
-- cs
wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF
@@ -367,62 +342,66 @@ port map(
q => wram_do
);
ay83910_inst1: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(4),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay1_do,
CHANNEL_A => ay1_chan_a,
CHANNEL_B => ay1_chan_b,
CHANNEL_C => ay1_chan_c,
-- AY-3-8910 #1
ay_3_8910_1 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay1_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(4), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
SEL => '0',
MODE => '1',
O_AUDIO_L => ay1_audio, -- out std_logic_vector(9 downto 0);
ACTIVE => open,
-- port a
I_IOA => select_sound, -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => ay1_port_b_do, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
IOA_in => select_sound_r,
IOA_out => open,
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
IOB_in => (others => '0'),
IOB_out => ay1_port_b_do
);
-- AY-3-8910 #2
ay_3_8910_2 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay2_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(3), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
ay1_audio <= "0000000000" + ay1_chan_a + ay1_chan_b + ay1_chan_c;
O_AUDIO_L => ay2_audio, -- out std_logic_vector(9 downto 0);
ay83910_inst2: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(3),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay2_do,
CHANNEL_A => ay2_chan_a,
CHANNEL_B => ay2_chan_b,
CHANNEL_C => ay2_chan_c,
-- port a
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => open, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
SEL => '0',
MODE => '1',
ACTIVE => open,
IOA_in => (others => '0'),
IOA_out => open,
IOB_in => (others => '0'),
IOB_out => open
);
ay2_audio <= "0000000000" + ay2_chan_a + ay2_chan_b + ay2_chan_c;
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
end struct;

View File

@@ -43,7 +43,7 @@ set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:22:13 JUNE 04, 2019"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name SMART_RECOMPILE ON
# Pin & Location Assignments
@@ -227,10 +227,11 @@ set_global_assignment -name VHDL_FILE rtl/TropicalAngel.vhd
set_global_assignment -name VHDL_FILE rtl/moon_patrol_sound_board.vhd
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/YM2149.sv
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/mist/mist.qip
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../../common/CPU/6800/cpu68.vhd
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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -1,329 +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 A8,
input A9_L,
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];
wire cs = !A9_L & A8;
// 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(cs & 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(cs & ~BDIR & BC & !addr[7:4]) begin
case(addr[3:0])
0: dout = ymreg[0];
1: dout = ymreg[1][3:0];
2: dout = ymreg[2];
3: dout = ymreg[3][3:0];
4: dout = ymreg[4];
5: dout = ymreg[5][3:0];
6: dout = ymreg[6][4:0];
7: dout = ymreg[7];
8: dout = ymreg[8][4:0];
9: dout = ymreg[9][4:0];
10: dout = ymreg[10][4:0];
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = ymreg[13][3:0];
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase
end
end
reg ena_div;
reg ena_div_noise;
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
reg noise_div;
if(CE) begin
ena_div <= 0;
ena_div_noise <= 0;
if(!cnt_div) begin
cnt_div <= {SEL, 3'b111};
ena_div <= 1;
noise_div <= (~noise_div);
if (noise_div) ena_div_noise <= 1;
end else begin
cnt_div <= cnt_div - 1'b1;
end
end
end
reg [2:0] noise_gen_op;
// p_noise_gen
always @(posedge CLK) begin
reg [16:0] poly17;
reg [4:0] noise_gen_cnt;
if(CE) begin
if (ena_div_noise) begin
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
noise_gen_cnt <= 0;
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
noise_gen_op <= {3{poly17[0]}};
end
end
end
wire [11:0] tone_gen_freq[1:3];
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
reg [3:1] tone_gen_op;
//p_tone_gens
always @(posedge CLK) begin
integer i;
reg [11:0] tone_gen_cnt[1:3];
if(CE) begin
// looks like real chips count up - we need to get the Exact behaviour ..
for (i = 1; i <= 3; i = i + 1) begin
if(ena_div) begin
if (tone_gen_freq[i]) begin
if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
tone_gen_cnt[i] <= 0;
tone_gen_op[i] <= ~tone_gen_op[i];
end else begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end else begin
tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0;
end
end
end
end
end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
always @(posedge CLK) begin
reg [15:0] env_gen_cnt;
if(CE) begin
env_ena <= 0;
if(ena_div) begin
if (env_gen_cnt >= env_gen_comp) begin
env_gen_cnt <= 0;
env_ena <= 1;
end else begin
env_gen_cnt <= (env_gen_cnt + 1'd1);
end
end
end
end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg env_hold;
reg env_inc;
// envelope shapes
// C AtAlH
// 0 0 x x \___
//
// 0 1 x x /___
//
// 1 0 0 0 \\\\
//
// 1 0 0 1 \___
//
// 1 0 1 0 \/\/
// ___
// 1 0 1 1 \
//
// 1 1 0 0 ////
// ___
// 1 1 0 1 /
//
// 1 1 1 0 /\/\
//
// 1 1 1 1 /___
if(env_reset | RESET) begin
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end
else if(CE) begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
end
end
end
reg [5:0] A,B,C;
always @(posedge CLK) begin
A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
end
wire [7:0] volTable[64] = '{
//YM2149
8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
//AY8910
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
};
assign CHANNEL_A = volTable[A];
assign CHANNEL_B = volTable[B];
assign CHANNEL_C = volTable[C];
endmodule

View File

@@ -38,35 +38,9 @@ port(
end moon_patrol_sound_board;
architecture struct of moon_patrol_sound_board is
component YM2149
port (
CLK : in std_logic;
CE : in std_logic;
RESET : in std_logic;
A8 : in std_logic := '1';
A9_L : in std_logic := '0';
BDIR : in std_logic; -- Bus Direction (0 - read , 1 - write)
BC : in std_logic; -- Bus control
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
CHANNEL_A : out std_logic_vector(7 downto 0);
CHANNEL_B : out std_logic_vector(7 downto 0);
CHANNEL_C : out std_logic_vector(7 downto 0);
SEL : in std_logic;
MODE : in std_logic;
ACTIVE : out std_logic_vector(5 downto 0);
IOA_in : in std_logic_vector(7 downto 0);
IOA_out : out std_logic_vector(7 downto 0);
IOB_in : in std_logic_vector(7 downto 0);
IOB_out : out std_logic_vector(7 downto 0)
);
end component;
signal reset : std_logic := '1';
signal reset_n : std_logic;
signal reset_cnt : integer range 0 to 1000000 := 1000000;
signal cpu_addr : std_logic_vector(15 downto 0);
@@ -156,6 +130,7 @@ architecture struct of moon_patrol_sound_board is
begin
dbg_cpu_addr <= cpu_addr;
reset_n <= not reset;
-- cs
wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF
@@ -358,62 +333,66 @@ port map(
q => wram_do
);
ay83910_inst1: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(4),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay1_do,
CHANNEL_A => ay1_chan_a,
CHANNEL_B => ay1_chan_b,
CHANNEL_C => ay1_chan_c,
-- AY-3-8910 #1
ay_3_8910_1 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay1_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(4), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
SEL => '0',
MODE => '1',
O_AUDIO_L => ay1_audio, -- out std_logic_vector(9 downto 0);
ACTIVE => open,
-- port a
I_IOA => select_sound, -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => ay1_port_b_do, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
IOA_in => select_sound_r,
IOA_out => open,
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
IOB_in => (others => '0'),
IOB_out => ay1_port_b_do
);
-- AY-3-8910 #2
ay_3_8910_2 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay2_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(3), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
ay1_audio <= "0000000000" + ay1_chan_a + ay1_chan_b + ay1_chan_c;
O_AUDIO_L => ay2_audio, -- out std_logic_vector(9 downto 0);
ay83910_inst2: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(3),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay2_do,
CHANNEL_A => ay2_chan_a,
CHANNEL_B => ay2_chan_b,
CHANNEL_C => ay2_chan_c,
-- port a
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => open, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
SEL => '0',
MODE => '1',
ACTIVE => open,
IOA_in => (others => '0'),
IOA_out => open,
IOB_in => (others => '0'),
IOB_out => open
);
ay2_audio <= "0000000000" + ay2_chan_a + ay2_chan_b + ay2_chan_c;
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
end struct;

View File

@@ -263,13 +263,14 @@ set_global_assignment -name VHDL_FILE rtl/sprom.vhd
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/YM2149.sv
set_global_assignment -name VHDL_FILE rtl/Sound_Board.vhd
set_global_assignment -name QIP_FILE ../../common/Sound/jt5205/jt5205.qip
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../common/CPU/T80/Z80.vhd
set_global_assignment -name VHDL_FILE ../../common/CPU/6800/cpu68.vhd
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 SIGNALTAP_FILE output_files/sp.stp
set_global_assignment -name SIGNALTAP_FILE output_files/tilemap.stp
set_global_assignment -name SIGNALTAP_FILE output_files/sprite.stp

View File

@@ -43,33 +43,6 @@ port(
end Sound_Board;
architecture struct of Sound_Board is
component YM2149
port (
CLK : in std_logic;
CE : in std_logic;
RESET : in std_logic;
A8 : in std_logic := '1';
A9_L : in std_logic := '0';
BDIR : in std_logic; -- Bus Direction (0 - read , 1 - write)
BC : in std_logic; -- Bus control
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
CHANNEL_A : out std_logic_vector(7 downto 0);
CHANNEL_B : out std_logic_vector(7 downto 0);
CHANNEL_C : out std_logic_vector(7 downto 0);
SEL : in std_logic;
MODE : in std_logic;
ACTIVE : out std_logic_vector(5 downto 0);
IOA_in : in std_logic_vector(7 downto 0);
IOA_out : out std_logic_vector(7 downto 0);
IOB_in : in std_logic_vector(7 downto 0);
IOB_out : out std_logic_vector(7 downto 0)
);
end component;
component jt5205
port (
@@ -85,6 +58,7 @@ architecture struct of Sound_Board is
end component;
signal reset : std_logic := '1';
signal reset_n : std_logic;
signal reset_cnt : integer range 0 to 1000000 := 1000000;
signal cpu_addr : std_logic_vector(15 downto 0);
@@ -149,6 +123,7 @@ architecture struct of Sound_Board is
begin
dbg_cpu_addr <= cpu_addr;
reset_n <= not reset;
-- cs
wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF
@@ -329,62 +304,66 @@ port map(
q => wram_do
);
ay83910_inst1: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(4),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay1_do,
CHANNEL_A => ay1_chan_a,
CHANNEL_B => ay1_chan_b,
CHANNEL_C => ay1_chan_c,
-- AY-3-8910 #1
ay_3_8910_1 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay1_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(4), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
SEL => '0',
MODE => '1',
O_AUDIO_L => ay1_audio, -- out std_logic_vector(9 downto 0);
ACTIVE => open,
-- port a
I_IOA => select_sound, -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => ay1_port_b_do, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
-- AY-3-8910 #2
ay_3_8910_2 : entity work.YM2149
port map(
-- data bus
I_DA => port1_data,-- in std_logic_vector(7 downto 0);
O_DA => ay2_do, -- out std_logic_vector(7 downto 0);
O_DA_OE_L => open, -- out std_logic;
-- control
I_A9_L => port2_data(3), -- in std_logic;
I_A8 => '1', -- in std_logic;
I_BDIR => port2_data(0), -- in std_logic;
I_BC2 => '1', -- in std_logic;
I_BC1 => port2_data(2), -- in std_logic;
I_SEL_L => '1', -- in std_logic;
O_AUDIO_L => ay2_audio, -- out std_logic_vector(9 downto 0);
-- port a
I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOA => open, -- out std_logic_vector(7 downto 0);
O_IOA_OE_L => open, -- out std_logic;
-- port b
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
O_IOB => open, -- out std_logic_vector(7 downto 0);
O_IOB_OE_L => open, -- out std_logic;
IOA_in => select_sound_r,
IOA_out => open,
IOB_in => (others => '0'),
IOB_out => ay1_port_b_do
);
ay1_audio <= "0000000000" + ay1_chan_a + ay1_chan_b + ay1_chan_c;
ay83910_inst2: YM2149
port map (
CLK => clock_E,
CE => '1',
RESET => reset,
A8 => '1',
A9_L => port2_data(3),
BDIR => port2_data(0),
BC => port2_data(2),
DI => port1_data,
DO => ay2_do,
CHANNEL_A => ay2_chan_a,
CHANNEL_B => ay2_chan_b,
CHANNEL_C => ay2_chan_c,
SEL => '0',
MODE => '1',
ACTIVE => open,
IOA_in => (others => '0'),
IOA_out => open,
IOB_in => (others => '0'),
IOB_out => open
);
ay2_audio <= "0000000000" + ay2_chan_a + ay2_chan_b + ay2_chan_c;
ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation
RESET_L => reset_n, -- in std_logic;
CLK => clock_E -- in std_logic
);
end struct;

View File

@@ -1,328 +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 A8,
input A9_L,
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];
wire cs = !A9_L & A8;
// Write to PSG
reg env_reset;
always @(posedge CLK) begin
if(RESET) begin
ymreg <= '{default:0};
addr <= '0;
env_reset <= 0;
end else begin
env_reset <= 0;
if(cs & 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(cs & ~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 : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] | IOA_in : 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