1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-01 22:32:06 +00:00
Files
Gehstock.Mist_FPGA/common/Sound/diskimage_by_byte.vhd
2024-03-06 12:57:21 +00:00

169 lines
4.1 KiB
VHDL

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;