*

rw_byte.vhd


--------------------------------------------------------------------------

-- FILENAME : rw_byte.vhd
--
-- Reads or writes a single byte from a sector on the disk. If reading a
-- byte then the sector is first read and then the byte from that sector
-- is output. If writing the sector is first read then the byte is
-- changed, and then the sector is put back on the disk.
--
-- This component is mainly used when reading and writing to the FAT.
--
-- AUTHOR : Craig Dunn
-- DATE STARTED : 2 April 2004
-- TAB SETTING : 4
-- RESET : Sync
-- CLOCK : 32MHz
-- 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 rw_byte is
port ( MCLK : in std_logic;
SIDE_IN : in std_logic;
RD_BYTE : in std_logic;
WR_BYTE : in std_logic;
FDD_BSY : in std_logic;
FDD_RDY : in std_logic;
CRC_ERROR : in std_logic;
SEEK_ERROR : in std_logic;
WP_ERROR : in std_logic;
SECTOR_IN : in std_logic_vector(4 downto 0);
TRACK_IN : in std_logic_vector(7 downto 0);
RAM_DO : in std_logic_vector(7 downto 0);
DATA_IN : in std_logic_vector(7 downto 0);
ADDR_IN : in std_logic_vector(8 downto 0);
SIDE_OUT : out std_logic;
BSY : out std_logic;
ERROR : out std_logic;
RAM_CLK : out std_logic;
RAM_WE : out std_logic;
RD_SECT : out std_logic;
WR_SECT : out std_logic;
SECTOR_OUT : out std_logic_vector(4 downto 0);
RAM_DI : out std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0);
TRACK_OUT : out std_logic_vector(7 downto 0);
ADDR_OUT : out std_logic_vector(8 downto 0)
);
end rw_byte;

architecture rw_byte_arch of rw_byte is

type mode_type is ( READING, WRITING );
type state_type is ( IDLE, READ_SECTOR, WAIT_FOR_READ, CLOCK_RAM,
WRITE_SECTOR, WAIT_FOR_WRITE );

signal mode : mode_type;
signal state : state_type;

begin

ADDR_OUT <= ADDR_IN;
SECTOR_OUT <= SECTOR_IN;
TRACK_OUT <= TRACK_IN;
SIDE_OUT <= SIDE_IN;
RAM_DI <= DATA_IN;
DATA_OUT <= RAM_DO;

main : process(MCLK)
begin
if rising_edge(MCLK) then
if FDD_RDY = '0' then
RAM_CLK <= '0';
RD_SECT <= '0';
WR_SECT <= '0';
BSY <= '0';
ERROR <= '0';
state <= IDLE;
else
case state is

-- Wait here until the external read or write signals
-- go high.
---------------------------------------------------------------
when IDLE =>
RAM_CLK <= '0';

if RD_BYTE = '1' and FDD_BSY = '0' then
RAM_WE <= '0';
mode <= READING;
BSY <= '1';
state <= READ_SECTOR;
elsif WR_BYTE = '1' and FDD_BSY = '0' then
RAM_WE <= '1';
mode <= WRITING;
BSY <= '1';
state <= READ_SECTOR;
else
BSY <= '0';
state <= IDLE;
end if;


-- Instruct the FDD controller to read a sector.
---------------------------------------------------------------
when READ_SECTOR =>
RD_SECT <= '1';
if FDD_BSY = '1' then
state <= WAIT_FOR_READ;
else
state <= READ_SECTOR;
end if;


-- Wait for the FDD controller to finish reading the sector.
---------------------------------------------------------------
when WAIT_FOR_READ =>
RD_SECT <= '0';
if FDD_BSY = '0' then
if SEEK_ERROR = '1' or CRC_ERROR = '1' then
ERROR <= '1';
state <= IDLE;
else
ERROR <= '0';
state <= CLOCK_RAM;
end if;
else
state <= WAIT_FOR_READ;
end if;


-- Assert the RAM clock. If reading this will read a byte
-- from RAM or if writing then this will write a byte to RAM.
---------------------------------------------------------------
when CLOCK_RAM =>
RAM_CLK <= '1';
if mode = READING then
state <= IDLE;
else -- mode = writing
if FDD_BSY = '0' then
state <= WRITE_SECTOR;
else
state <= CLOCK_RAM;
end if;
end if;


-- Instruct the FDD controller to write a sector.
---------------------------------------------------------------
when WRITE_SECTOR =>
RAM_CLK <= '0';
WR_SECT <= '1';
if FDD_BSY = '1' then
state <= WAIT_FOR_WRITE;
else
state <= WRITE_SECTOR;
end if;


-- Wait for the FDD controller to finish writing the sector.
---------------------------------------------------------------
when WAIT_FOR_WRITE =>
WR_SECT <= '0';
if FDD_BSY = '0' then
if SEEK_ERROR = '1' or WP_ERROR = '1' then
ERROR <= '1';
else
ERROR <= '0';
end if;

state <= IDLE;
else
state <= WAIT_FOR_WRITE;
end if;


when others =>
null;

end case;
end if;
end if;
end process main;

end rw_byte_arch;


BackHome