diff --git a/Arcade_MiST/Midway MCR 2/Journey_MiST/Journey.qsf b/Arcade_MiST/Midway MCR 2/Journey_MiST/Journey.qsf index 5d156956..096cfc8c 100644 --- a/Arcade_MiST/Midway MCR 2/Journey_MiST/Journey.qsf +++ b/Arcade_MiST/Midway MCR 2/Journey_MiST/Journey.qsf @@ -181,7 +181,7 @@ set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top set_global_assignment -name ENABLE_SIGNALTAP OFF -set_global_assignment -name USE_SIGNALTAP_FILE output_files/jo.stp +set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.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 @@ -196,4 +196,7 @@ 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_global_assignment -name VHDL_FILE ../../../common/Sound/diskimage_by_byte.vhd +set_global_assignment -name SYSTEMVERILOG_FILE ../../../common/Sound/wave_sound.sv +set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/Midway MCR 2/Journey_MiST/meta/Journey.mra b/Arcade_MiST/Midway MCR 2/Journey_MiST/meta/Journey.mra index c508429d..b626040d 100644 --- a/Arcade_MiST/Midway MCR 2/Journey_MiST/meta/Journey.mra +++ b/Arcade_MiST/Midway MCR 2/Journey_MiST/meta/Journey.mra @@ -5,7 +5,7 @@ 1984 Bally Midway Action - MCR3 + Journey journey diff --git a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/Journey_MiST.sv b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/Journey_MiST.sv index e360448f..974305d4 100644 --- a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/Journey_MiST.sv +++ b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/Journey_MiST.sv @@ -16,13 +16,15 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. //============================================================================ +`default_nettype none + module Journey_MiST( output LED, output [5:0] VGA_R, output [5:0] VGA_G, output [5:0] VGA_B, - output VGA_HS, - output VGA_VS, + output reg VGA_HS, + output reg VGA_VS, output AUDIO_L, output AUDIO_R, input SPI_SCK, @@ -53,6 +55,7 @@ localparam CONF_STR = { "O5,Blend,Off,On;", "O6,Service,Off,On;", "R2048,Save NVRAM;", +// "S0U,WAVVHD,Cas Audio:;", "T0,Reset;", "V,v1.0.",`BUILD_DATE }; @@ -95,10 +98,21 @@ wire key_pressed; wire [7:0] key_code; wire key_strobe; +wire [31:0] sd_lba; +wire sd_rd; +wire sd_ack; +wire sd_ack_conf; +wire [7:0] sd_dout; +wire sd_dout_strobe; +wire img_mounted; +wire [63:0] img_size; + user_io #( - .STRLEN(($size(CONF_STR)>>3))) -user_io( + .STRLEN(($size(CONF_STR)>>3)), + .SD_IMAGES(1) +) user_io( .clk_sys (clk_sys ), + .clk_sd (clk_sys ), .conf_str (CONF_STR ), .SPI_CLK (SPI_SCK ), .SPI_SS_IO (CONF_DATA0 ), @@ -114,6 +128,23 @@ user_io( .key_code (key_code ), .joystick_0 (joystick_0 ), .joystick_1 (joystick_1 ), + + // SD CARD + .sd_lba (sd_lba ), + .sd_rd (sd_rd ), + .sd_wr (1'b0 ), + .sd_ack (sd_ack ), + .sd_ack_conf (sd_ack_conf ), + .sd_conf (1'b0 ), + .sd_sdhc (1'b1 ), + .sd_dout (sd_dout ), + .sd_dout_strobe (sd_dout_strobe), + .sd_din ( ), + .sd_din_strobe ( ), + .sd_buff_addr ( ), + .img_mounted (img_mounted ), + .img_size (img_size ), + .status (status ) ); @@ -223,6 +254,8 @@ wire hs, vs, cs; wire blankn; wire [2:0] g, r, b; +wire [7:0] output_4; + journey journey( .clock_40(clk_sys), .reset(reset), @@ -243,6 +276,8 @@ journey journey( .input_2 ( input_2 ), .input_3 ( input_3 ), .input_4 ( input_4 ), + + .output_4 ( output_4 ), .cpu_rom_addr ( rom_addr ), .cpu_rom_do ( rom_addr[0] ? rom_do[15:8] : rom_do[7:0] ), @@ -259,8 +294,10 @@ journey journey( wire vs_out; wire hs_out; -assign VGA_HS = (~no_csync & scandoublerD & ~ypbpr)? cs : hs_out; -assign VGA_VS = (~no_csync & scandoublerD & ~ypbpr)? 1'b1 : vs_out; +always @(posedge clk_sys) begin + VGA_HS <= (~no_csync & scandoublerD & ~ypbpr)? cs : hs_out; + VGA_VS <= (~no_csync & scandoublerD & ~ypbpr)? 1'b1 : vs_out; +end mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video( .clk_sys ( clk_sys ), @@ -286,21 +323,99 @@ mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video( .ypbpr ( ypbpr ) ); +// Wave sound + +wire wav_mounted; +wire [31:0] wav_addr; +wire wav_rd; +wire wav_rd_next; +wire [7:0] wav_d; +wire wav_ack; + +assign wav_addr[31:28] = 4'h0; +assign sd_lba[31:23] = 8'h00; + +// Bytewise interface to disk images +diskimage_by_byte waveinterface ( + .clk(clk_sys), + .reset_n(~reset), + + .sd_lba(sd_lba), + .sd_rd(sd_rd), + .sd_ack(sd_ack), + .sd_d(sd_dout), + .sd_d_strobe(sd_dout_strobe), + .sd_imgsize(img_size), + .sd_imgmounted(img_mounted), + + .client_mounted(wav_mounted), + .client_addr(wav_addr), + .client_rd(wav_rd), + .client_rd_next(wav_rd_next), + .client_q(wav_d), + .client_ack(wav_ack) +); + +// Wave player + +wire [15:0] wav_out_l; +wire [15:0] wav_out_r; + +wire playing; + +assign playing = wav_mounted && output_4[0]; + +wave_sound #(.SYSCLOCK(40000000)) waveplayer +( + .I_CLK(clk_sys), + .I_RST(reset | img_mounted), + + .I_BASE_ADDR(0), + .I_LOOP(1'b1), + .I_PAUSE(~playing), + + .O_ADDR(wav_addr), + .O_READ(wav_rd), + .O_READNEXT(wav_rd_next), + .I_DATA(wav_d), + .I_READY(wav_ack), + + .O_PCM_L(wav_out_l), + .O_PCM_R(wav_out_r) +); + + +reg [16:0] audio_l_sum; +reg [16:0] audio_r_sum; + +reg [16:0] dac_in_l; +reg [16:0] dac_in_r; + +always @(posedge clk_sys) begin + + audio_l_sum <= {wav_out_l[15],wav_out_l} + {audio_l,1'b0} - 16'h4000; + audio_r_sum <= {wav_out_r[15],wav_out_r} + {audio_r,1'b0} - 16'h4000; + + dac_in_l <= {~audio_l_sum[16],audio_l_sum[15:0]}; + dac_in_r <= {~audio_r_sum[16],audio_r_sum[15:0]}; +end + + dac #( - .C_bits(16)) + .C_bits(17)) dac_l( .clk_i(clk_sys), .res_n_i(1), - .dac_i(audio_l), + .dac_i(dac_in_l), .dac_o(AUDIO_L) ); dac #( - .C_bits(16)) + .C_bits(17)) dac_r( .clk_i(clk_sys), .res_n_i(1), - .dac_i(audio_r), + .dac_i(dac_in_r), .dac_o(AUDIO_R) ); diff --git a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/journey.vhd b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/journey.vhd index 5e251f69..45590d25 100644 --- a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/journey.vhd +++ b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/journey.vhd @@ -158,6 +158,8 @@ port( input_2 : in std_logic_vector( 7 downto 0); input_3 : in std_logic_vector( 7 downto 0); input_4 : in std_logic_vector( 7 downto 0); + + output_4 : out std_logic_vector( 7 downto 0); cpu_rom_addr : out std_logic_vector(15 downto 0); cpu_rom_do : in std_logic_vector(7 downto 0); @@ -851,6 +853,8 @@ port map( input_3 => input_3, input_4 => input_4, + output_4 => output_4, + separate_audio => separate_audio, audio_out_l => audio_out_l, audio_out_r => audio_out_r, diff --git a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/satans_hollow_sound_board.vhd b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/satans_hollow_sound_board.vhd index 030a6269..41560a17 100644 --- a/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/satans_hollow_sound_board.vhd +++ b/Arcade_MiST/Midway MCR 2/Journey_MiST/rtl/satans_hollow_sound_board.vhd @@ -68,6 +68,7 @@ port( input_2 : in std_logic_vector(7 downto 0); input_3 : in std_logic_vector(7 downto 0); input_4 : in std_logic_vector(7 downto 0); + output_4 : out std_logic_vector(7 downto 0); separate_audio : in std_logic; audio_out_l : out std_logic_vector(15 downto 0); @@ -446,8 +447,12 @@ begin iram_1_do <= (others => '0'); iram_2_do <= (others => '0'); iram_3_do <= (others => '0'); + output_4 <= (others => '0'); else if rising_edge(clock_snd) then + if ssio_iowe = '1' and main_cpu_addr(7 downto 2) = "000001" then -- 0x04 - 0x07 + output_4 <= ssio_di; + end if; if ssio_iowe = '1' and main_cpu_addr(7 downto 2) = "000111" then -- 0x1C - 0x1F case main_cpu_addr(1 downto 0) is when "00" => iram_0_do <= ssio_di; diff --git a/common/Sound/diskimage_by_byte.vhd b/common/Sound/diskimage_by_byte.vhd new file mode 100644 index 00000000..dae59452 --- /dev/null +++ b/common/Sound/diskimage_by_byte.vhd @@ -0,0 +1,168 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_misc.all; +use ieee.numeric_std.all; + + +entity diskimage_by_byte is +generic ( + lbahigh : integer := 31; + lbalow : integer := 9 +); +port ( + clk : in std_logic; + reset_n : in std_logic; + -- Disk image interface + sd_lba : out std_logic_vector(lbahigh-lbalow downto 0); + sd_rd : out std_logic; + sd_ack : in std_logic; + sd_d : in std_logic_vector(7 downto 0); + sd_d_strobe : in std_logic; + sd_imgsize : in std_logic_vector(lbahigh downto 0); + sd_imgmounted : in std_logic; + -- Word interface + client_mounted : out std_logic; + client_addr : in std_logic_vector(lbahigh downto 0); -- Offset from start of file, in bytes - but LSB should be zero + client_rd : in std_logic; + client_rd_next : in std_logic; + client_q : out std_logic_vector(7 downto 0); + client_ack : out std_logic +); +end entity; + +architecture rtl of diskimage_by_byte is + type bufdata_t is array(0 to 1024) of std_logic_vector(7 downto 0); + signal buf : bufdata_t; + type states_t is (IDLE,WAITACK,READING,READEND); + signal state : states_t; + signal fillbuf : std_logic; + signal drainbuf : std_logic; + signal client_mounted_i : std_logic :='0'; +begin + + sdinterface : block + signal imgsize : unsigned(lbahigh downto 0); + signal fillidx : unsigned(lbahigh downto 0); -- Byte index into file + signal fillbuf_d : std_logic; + begin + + client_mounted <= client_mounted_i; + + fillbuf <= fillidx(lbalow); + + process(clk) begin + if rising_edge(clk) then + if sd_imgmounted='1' then + imgsize <= unsigned(sd_imgsize); + if or_reduce(sd_imgsize) /= '0' then + client_mounted_i <= '1'; + else + client_mounted_i <= '0'; + end if; + end if; + end if; + end process; + + process(clk) begin + if rising_edge(clk) then + + case(state) is + + when IDLE => + -- If the read pointer has progressed into the last buffer, read the next sector into the newly-vacated buffer + if fillbuf /= drainbuf then + if fillidx(lbahigh downto lbalow) '0'); + sd_lba <= client_addr(lbahigh downto lbalow); + sd_rd <= '1'; + state <= WAITACK; + end if; + + when WAITACK => + if sd_ack='1' then + sd_rd<='0'; + state <= READING; + end if; + + when READING => + if sd_d_strobe='1' then + buf(to_integer(fillidx(lbalow downto 0))) <= sd_d; + fillidx <= fillidx+1; + end if; + if fillbuf /= fillbuf_d then + state <= READEND; + end if; + fillbuf_d<=fillbuf; + + when READEND => + if sd_ack='0' then + state <= IDLE; + end if; + + when others => + null; + + end case; + if reset_n='0' or sd_imgmounted='1' then + fillidx<=(others => '0'); + sd_rd<='0'; + state <= IDLE; + end if; + end if; + end process; + end block; + + clientinterface : block + signal drainidx : unsigned(lbahigh downto 0); + signal rd_d : std_logic; + signal client_ack_i : std_logic; + begin + + client_ack <= client_ack_i; + drainbuf <= drainidx(lbalow); + + process(clk) begin + + if rising_edge(clk) then + client_ack_i <='0'; + + if client_rd='1' and client_ack_i='0' then + drainidx <= unsigned(client_addr); + end if; + + if client_rd = '1' or client_rd_next='1' then -- Latch incoming read requests, and give SM time to respond + rd_d <= not client_ack_i; + end if; + + if client_ack_i='0' and rd_d='1' and (state=IDLE or fillbuf /= drainbuf) then + client_q <= buf(to_integer(drainidx(lbalow downto 0))); + drainidx <= drainidx+1; + rd_d <= '0'; + client_ack_i <= '1'; + end if; + + if sd_imgmounted='1' then + rd_d <= '0'; + drainidx<=(others => '0'); + end if; + + if reset_n='0' or client_mounted_i='0' then + rd_d<='0'; + client_ack_i<='0'; + end if; + + end if; + end process; + + end block; + +end architecture; + diff --git a/common/Sound/wave_sound.sv b/common/Sound/wave_sound.sv new file mode 100644 index 00000000..392195f3 --- /dev/null +++ b/common/Sound/wave_sound.sv @@ -0,0 +1,172 @@ +//============================================================================ +// Sound sample player. +// +// Author: gaz68 (https://github.com/gaz68) +// October 2019 +// Adapted by alanswx to parse the wave +// +// Adjustments for diskimage interface, and stereo support by +// Alastair M. Robinson +// +//============================================================================ + +module wave_sound #(parameter SYSCLOCK = 40000000) +( + input I_CLK, + input I_RST, + + input [27:0] I_BASE_ADDR, + input I_LOOP, + input I_PAUSE, + + output [27:0] O_ADDR, // output address to wave ROM + output O_READ, // read a byte + output O_READNEXT, // read a byte + input [7:0] I_DATA, // Data coming back from wave ROM + input I_READY, // data is ready + + output [15:0] O_PCM_L, + output [15:0] O_PCM_R +); + +reg [27:0] W_DMA_ADDR; +reg [27:0] END_ADDR; +reg W_DMA_EN; +reg inheader; +reg [15:0] num_channels; +reg [31:0] sample_rate; +reg [31:0] byte_rate; +reg [15:0] block_align; +reg [15:0] bits_per_sample; +reg [23:0] data_size; +reg [27:0] START_ADDR; + +reg [7:0] W_SAMPL_LSB; +reg [15:0] W_SAMPL_L; +reg [15:0] W_SAMPL_R; + +reg [31:0] sum; +wire[31:0] sum_next = sum + ( stereo ? {sample_rate,1'b0} : sample_rate); + +wire stereo = num_channels==16'h2 ? 1'b1 : 1'b0; +reg channel_toggle; + +reg ce_sample; +always @(posedge I_CLK) begin + ce_sample <= 0; + sum <= sum_next; + if(sum_next >= SYSCLOCK) begin + sum <= sum_next - SYSCLOCK; + ce_sample <= 1; + end +end + +reg read_done = 0; +always@(posedge I_CLK) begin + + if(I_RST)begin + W_DMA_ADDR <= I_BASE_ADDR; + W_DMA_EN <= 1'b1; + O_READ <= 1'b1; + O_READNEXT <= 1'b0; + inheader <= 1'b1; + read_done <= 1'b0; + end + else if (W_DMA_EN) begin + if (I_READY) begin + O_READ <= 0; + O_READNEXT <= 0; + end + + if (I_READY & ~read_done) begin + if (inheader) begin + O_READNEXT <= 1'b1; + case (W_DMA_ADDR[5:0]) + 00: ; // R + 01: ; // I + 02: ; // F + 03: ; // F + 22: num_channels[7:0] <= I_DATA; + 23: num_channels[15:8] <= I_DATA; + 24: sample_rate[7:0] <= I_DATA; + 25: sample_rate[15:8] <= I_DATA; + 26: sample_rate[23:16] <= I_DATA; + 27: sample_rate[31:24] <= I_DATA; + //28: byte_rate[7:0] <= I_DATA; + //29: byte_rate[15:8] <= I_DATA; + //30: byte_rate[23:16] <= I_DATA; + //31: byte_rate[31:24] <= I_DATA; + //32: block_align[7:0] <= I_DATA; + //33: block_align[15:8] <= I_DATA; + 34: bits_per_sample[7:0] <= I_DATA; + 35: bits_per_sample[15:8] <= I_DATA; + 40: data_size[7:0] <= I_DATA; + 41: data_size[15:8] <= I_DATA; + 42: data_size[23:16] <= I_DATA; + 43: begin +// data_size[31:24] <= I_DATA;// AMR - Applied too late + //$display("num_channels %x %d\n",num_channels,num_channels); + $display("sample_rate %x %d\n",sample_rate,sample_rate); + //$display("byte_rate %x %d\n",byte_rate,byte_rate); + //$display("block_align%x %d\n",block_align,block_align); + $display("bits_per_sample %x %d\n",bits_per_sample,bits_per_sample); + $display("data_size %x %d\n",data_size,data_size); + $display("data_size %x %d\n",data_size,data_size); + $display("data_size %x %d\n",data_size[15:0],data_size[15:0]); + END_ADDR <= W_DMA_ADDR + data_size + {I_DATA,24'd0}; // AMR - Merge in MSB + START_ADDR <= W_DMA_ADDR + 1'd1; + inheader <= 0; + O_READ <= 0; + O_READNEXT <= 0; + read_done <= 1; + channel_toggle<=1'b0; + end + endcase + end + else if (bits_per_sample != 16) begin + if(channel_toggle| !stereo) + W_SAMPL_L <= {I_DATA,I_DATA}; + if(!channel_toggle| !stereo) + W_SAMPL_R <= {I_DATA,I_DATA}; + read_done <= 1; + end + else if (!W_DMA_ADDR[0]) begin + W_SAMPL_LSB <= I_DATA; + O_READNEXT <= 1'b1; + end + else begin + if(channel_toggle| !stereo) + W_SAMPL_L <= {I_DATA,W_SAMPL_LSB}; + if(!channel_toggle| !stereo) + W_SAMPL_R <= {I_DATA,W_SAMPL_LSB}; + read_done <= 1; + end + + W_DMA_ADDR <= W_DMA_ADDR + 1'd1; + end + + if(read_done && ce_sample && !I_PAUSE) begin + read_done <= 0; + channel_toggle<=~channel_toggle; + W_DMA_EN <= ~(W_DMA_ADDR >= END_ADDR); + if (W_DMA_ADDR >= END_ADDR && I_LOOP) begin + W_DMA_EN <= 1'b1; + W_DMA_ADDR <= START_ADDR; + O_READ <= 1'b1; + end + else + O_READNEXT <= 1'b1; + end + end + + if(I_RST || I_PAUSE || !W_DMA_EN) begin + W_SAMPL_L <= 0; + W_SAMPL_R <= 0; + end +end + +assign O_ADDR = W_DMA_ADDR; +assign O_PCM_L = W_SAMPL_L; +assign O_PCM_R = W_SAMPL_R; + +endmodule