| read_fat.vhd
--------------------------------------------------------------------------
-- FILENAME : read_fat.vhd
--
-- Read's a single entry from the first FAT.
--
-- AUTHOR : Craig Dunn
-- DATE STARTED : 16 April 2004
-- TAB SETTING : 4
-- RESET : Async (active low)
-- KNOWN BUGS : None
-- VERSION : 1.0
--
-- All of the design and code in this module is my own work. No design or
-- code has been borrowed or copied from any source.
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity read_fat is
port ( EN : in std_logic;
MCLK : in std_logic;
BSY : out std_logic;
ENTRY : in std_logic_vector(11 downto 0);
RD : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
FAT_OUT : out std_logic_vector(11 downto 0);
RAM_ADDR : out std_logic_vector(8 downto 0);
SECTOR : out std_logic_vector(4 downto 0);
SIDE : out std_logic;
TRACK : out std_logic_vector(7 downto 0);
RD_BYTE : out std_logic;
RW_BSY : in std_logic
);
end read_fat;
architecture read_fat_arch of read_fat is
type state_type is ( IDLE, CALC_LOCATION, READ_BYTE, WAIT_FOR_READ );
type byte_type is ( HIGH_BYTE, LOW_BYTE );
signal state : state_type;
signal current_byte : byte_type;
signal hi_byte : std_logic_vector(7 downto 0);
signal lo_byte : std_logic_vector(7 downto 0);
signal lo_sector : std_logic_vector(4 downto 0);
signal hi_sector : std_logic_vector(4 downto 0);
signal lo_address : std_logic_vector(8 downto 0);
signal hi_address : std_logic_vector(8 downto 0);
signal fat_offset : std_logic_vector(12 downto 0);
constant FAT1_OFFSET : std_logic_vector(4 downto 0) := "00010";
begin
SIDE <= '1';
TRACK <= (others => '0');
SECTOR <= (hi_sector + FAT1_OFFSET) when current_byte = HIGH_BYTE else
(lo_sector + FAT1_OFFSET);
RAM_ADDR <= hi_address when current_byte = HIGH_BYTE else lo_address;
FAT_OUT <= lo_byte(3 downto 0) & hi_byte when ENTRY(0) = '0' else
lo_byte & hi_byte(7 downto 4);
main : process(MCLK)
begin
if rising_edge(MCLK) then
if EN = '0' then
state <= IDLE;
else
case state is
-- Wait here for the external RD signal to go high.
---------------------------------------------------------------
when IDLE =>
RD_BYTE <= '0';
current_byte <= HIGH_BYTE;
if RD = '1' then
fat_offset <= ('0' & ENTRY) + ("00" & ENTRY(11 downto 1));
state <= CALC_LOCATION;
BSY <= '1';
else
state <= IDLE;
BSY <= '0';
end if;
-- Calculate the location of the entry.
---------------------------------------------------------------
when CALC_LOCATION =>
hi_address <= fat_offset(8 downto 0);
hi_sector <= '0' & fat_offset(12 downto 9);
if ENTRY(8 downto 0) = "101010101" then
lo_address <= (others => '0');
lo_sector <= ('0' & fat_offset(12 downto 9)) + '1';
else
lo_address <= fat_offset(8 downto 0) + '1';
lo_sector <= '0' & fat_offset(12 downto 9);
end if;
state <= READ_BYTE;
-- Read the byte of the FAT entry
---------------------------------------------------------------
when READ_BYTE =>
RD_BYTE <= '1';
if RW_BSY = '1' then
state <= WAIT_FOR_READ;
end if;
-- Wait for the read to finish and then read the next one if
-- there is another.
---------------------------------------------------------------
when WAIT_FOR_READ =>
RD_BYTE <= '0';
if RW_BSY = '0' then
if current_byte = HIGH_BYTE then
hi_byte <= DATA_IN;
current_byte <= LOW_BYTE;
state <= READ_BYTE;
else
lo_byte <= DATA_IN;
state <= IDLE;
end if;
end if;
when others =>
null;
end case;
end if;
end if;
end process main;
end read_fat_arch;
|