diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf index a317f5a3..70e61ae1 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf @@ -204,6 +204,7 @@ 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/cpu68.vhd set_global_assignment -name VHDL_FILE src/tilemapctl.vhd set_global_assignment -name VHDL_FILE src/t80/Z80.vhd @@ -214,7 +215,6 @@ set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd set_global_assignment -name VHDL_FILE src/t80/T80.vhd set_global_assignment -name VHDL_FILE src/dac.vhd -set_global_assignment -name VHDL_FILE src/YM2149_linmix_sep.vhd set_global_assignment -name VHDL_FILE src/sprom.vhd set_global_assignment -name VHDL_FILE src/spram.vhd set_global_assignment -name VHDL_FILE src/platform.vhd diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149.sv b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149.sv new file mode 100644 index 00000000..eae73bb3 --- /dev/null +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149.sv @@ -0,0 +1,329 @@ +// +// 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 diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149_linmix_sep.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149_linmix_sep.vhd deleted file mode 100644 index 6ed2498a..00000000 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/YM2149_linmix_sep.vhd +++ /dev/null @@ -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; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/moon_patrol_sound_board.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/moon_patrol_sound_board.vhd index 11f5b5d7..8d238ee5 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/moon_patrol_sound_board.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/moon_patrol_sound_board.vhd @@ -37,9 +37,37 @@ 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_n : std_logic; signal clock_div : std_logic_vector(3 downto 0); + signal cpu_clock_en : std_logic; signal cpu_clock : std_logic; signal cpu_addr : std_logic_vector(15 downto 0); @@ -59,12 +87,18 @@ architecture struct of moon_patrol_sound_board is signal rom_cs : std_logic; signal rom_do : std_logic_vector( 7 downto 0); + signal ay1_chan_a : std_logic_vector(7 downto 0); + signal ay1_chan_b : std_logic_vector(7 downto 0); + signal ay1_chan_c : std_logic_vector(7 downto 0); signal ay1_do : std_logic_vector(7 downto 0); - signal ay1_audio : std_logic_vector(7 downto 0); + signal ay1_audio : std_logic_vector(9 downto 0); signal ay1_port_b_do : std_logic_vector(7 downto 0); - + + signal ay2_chan_a : std_logic_vector(7 downto 0); + signal ay2_chan_b : std_logic_vector(7 downto 0); + signal ay2_chan_c : std_logic_vector(7 downto 0); signal ay2_do : std_logic_vector(7 downto 0); - signal ay2_audio : std_logic_vector(7 downto 0); + signal ay2_audio : std_logic_vector(9 downto 0); signal ports_cs : std_logic; signal ports_we : std_logic; @@ -140,6 +174,7 @@ end process; -- cpu_clock is 3.58/4 cpu_clock <= clock_div(1); +cpu_clock_en <= '1' when clock_div(1 downto 0) = "00" else '0'; -- cs wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF @@ -170,8 +205,8 @@ begin if reset='1' then cpu_irq <= '0'; select_sound_7r := '0'; - else - if rising_edge(clock_div(0)) then + elsif rising_edge(clock_3p58) then + if clock_div(0) = '1' then --rising_edge(clock_div(0)) then if select_sound_7r = '0' and select_sound(7) = '1' then cpu_irq <= '1'; end if; @@ -194,8 +229,8 @@ begin port1_data <= (others=>'0'); -- port1 data set to 0 port2_ddr <= ("11100000"); -- port2 bit 7 to 5 should always remain output to simulate mode data port2_data <= ("01000000"); -- port2 data bit 7 to 5 set to 2 (for mode 2 at start up) - else - if rising_edge(clock_div(0)) then + elsif rising_edge(clock_3p58) then + if clock_div(0) = '1' then --rising_edge(clock_div(0)) then if ports_cs = '1' and ports_we = '1' then if cpu_addr(3 downto 0) = X"0" then port1_ddr <= cpu_do; end if; if cpu_addr(3 downto 0) = X"1" then port2_ddr <= cpu_do and "11100000"; end if; @@ -222,8 +257,8 @@ process (reset, clock_div(0)) begin if reset='1' then adpcm_0_di <= (others=>'0'); - else - if rising_edge(clock_div(0)) then + elsif rising_edge(clock_3p58) then + if clock_div(0) = '1' then --rising_edge(clock_div(0)) then if adpcm_cs = '1' and adpcm_we = '1' then if cpu_addr(1) = '0' then adpcm_0_di <= cpu_do(3 downto 0); end if; end if; @@ -301,7 +336,7 @@ begin end process; -- audio mux -audio <= ("00000"&ay1_audio) + ("00000"&ay2_audio) + ('0'&std_logic_vector(to_unsigned((adpcm_signal)+2048,12))); +audio <= ("000"&ay1_audio) + ("000"&ay2_audio) + ('0'&std_logic_vector(to_unsigned((adpcm_signal)+2048,12))); audio_out <= audio(12 downto 1); -- microprocessor 6800/01/03 @@ -325,7 +360,7 @@ port map( -- cpu program rom cpu_prog_rom : entity work.moon_patrol_sound_prog port map( - clk => clock_div(0), -- 3p58/2 + clk => clock_3p58, -- 3p58/2 addr => cpu_addr(11 downto 0), data => rom_do ); @@ -333,7 +368,7 @@ port map( cpu_ram : entity work.spram generic map( widthad_a => 7) port map( - clock => clock_div(0), -- 3p58/2 + clock => clock_3p58, -- 3p58/2 address => cpu_addr(6 downto 0), data => cpu_do, wren => wram_we, @@ -351,69 +386,62 @@ port map( -- q => wram_do --); --- 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; + ay83910_inst1: YM2149 + port map ( + CLK => clock_3p58, + CE => cpu_clock_en, + RESET => not reset_n, + 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, - O_AUDIO => ay1_audio, -- out std_logic_vector(7 downto 0); --- O_CHAN => ay1_audio_chan, -- out std_logic_vector(1 downto 0); - - -- 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; + SEL => '0', + MODE => '1', - ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation - RESET_L => reset_n, -- in std_logic; - CLK => cpu_clock -- in std_logic -- note 6 Mhz -); + ACTIVE => 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; + IOA_in => select_sound, + IOA_out => open, - O_AUDIO => ay2_audio, -- out std_logic_vector(7 downto 0); --- O_CHAN => ay2_audio_chan, -- out std_logic_vector(1 downto 0); - - -- port a - I_IOA => (others => '0'), -- in std_logic_vector(7 downto 0); - 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; + IOB_in => (others => '0'), + IOB_out => ay1_port_b_do + ); - ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation - RESET_L => reset_n, -- in std_logic; - CLK => cpu_clock -- in std_logic -- note 6 Mhz -); + ay1_audio <= "0000000000" + ay1_chan_a + ay1_chan_b + ay1_chan_c; + ay83910_inst2: YM2149 + port map ( + CLK => clock_3p58, + CE => cpu_clock_en, + RESET => not reset_n, + 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; end struct; \ No newline at end of file