mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-05-03 23:09:16 +00:00
Added Wave playing of tape loop to Journey core.
This commit is contained in:
168
common/Sound/diskimage_by_byte.vhd
Normal file
168
common/Sound/diskimage_by_byte.vhd
Normal file
@@ -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)<imgsize(lbahigh downto lbalow) then
|
||||
sd_lba <= std_logic_vector(fillidx(lbahigh downto lbalow));
|
||||
sd_rd <= '1';
|
||||
state <= WAITACK;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if client_rd='1' and client_mounted_i='1' then
|
||||
fillidx(lbahigh downto lbalow) <= unsigned(client_addr(lbahigh downto lbalow));
|
||||
fillidx(lbalow-1 downto 0) <= (others => '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;
|
||||
|
||||
172
common/Sound/wave_sound.sv
Normal file
172
common/Sound/wave_sound.sv
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user