| read_address_field.vhd
--------------------------------------------------------------------------
-- FILENAME : read_address_field.vhd
--
-- When ever the 'Address Mark' of an 'Address Field' is detected this
-- component will read the sector and head fields. The CRC field is also
-- read and checked agains't a pre-calculated CRC. If the CRC's match
-- then the sector and head values are considered to be valid.
--
-- This component signals to the reading and writing components where
-- abouts on the disk the read / write head is.
--
-- AUTHOR : Craig Dunn
-- DATE STARTED : 20 December 2003
-- TAB SETTING : 4
-- RESET : Async (active low)
-- CLOCK : 32MHz (not clock dependent)
-- 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_address_field is
Port ( MCLK : in std_logic;
EN : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
BYTE_COUNT : in std_logic_vector(9 downto 0);
CRC_OUT : in std_logic_vector(15 downto 0);
CRC_IN : out std_logic_vector(15 downto 0);
CRC_DATA : out std_logic_vector(7 downto 0);
SECTOR : out std_logic_vector(4 downto 0)
);
end read_address_field;
architecture read_address_field_arch of read_address_field is
type state_type is ( STORE_AF, CRC_TRACK, CRC_HEAD, CRC_SECTOR, CRC_BYTES, CHECK_CRC );
signal state : state_type;
signal track_reg : std_logic_vector(7 downto 0);
signal sector_reg : std_logic_vector(7 downto 0);
signal side_reg : std_logic_vector(7 downto 0);
signal crc_reg : std_logic_vector(15 downto 0);
begin
main : process(MCLK)
begin
if rising_edge(MCLK) then
-- This process should only be active when the read / write
-- head of the disk drive is in the address field of a sector.
-- If at any point we leave the address field then this process
-- must be reset or it will become unsynchronized with the data.
if EN = '0' then
track_reg <= (others => '0');
side_reg <= (others => '0');
sector_reg <= (others => '1');
SECTOR <= sector_reg(4 downto 0);
crc_reg <= (others => '0');
state <= STORE_AF;
else -- we are in the address field
case state is
-- Stay here storing the data from the address field. When
-- the 6th and final byte of the address field is read,
-- calculate the CRC.
--
-- Although I ignore the track field I still have to read it
-- to check the CRC is correct.
---------------------------------------------------------------
when STORE_AF =>
case byte_count is
when "0000000001" => track_reg <= DATA_IN;
when "0000000010" => side_reg <= DATA_IN;
when "0000000011" => sector_reg <= DATA_IN;
when "0000000101" => crc_reg(15 downto 8) <= DATA_IN;
when "0000000110" => crc_reg(7 downto 0) <= DATA_IN;
state <= CRC_TRACK;
when others => null;
end case;
-- Initialise the CRC with the address mark of the
-- address field and then load the track field (field 1 of 4).
---------------------------------------------------------------
when CRC_TRACK =>
crc_in <= x"B230";
crc_data <= track_reg;
state <= CRC_HEAD;
-- Load the head field (field 2 of 4).
---------------------------------------------------------------
when CRC_HEAD =>
crc_in <= crc_out;
crc_data <= side_reg;
state <= CRC_SECTOR;
-- Load the sector field (field 3 of 4).
---------------------------------------------------------------
when CRC_SECTOR =>
crc_in <= crc_out;
crc_data <= sector_reg;
state <= CRC_BYTES;
-- Load the number of bytes, which is always fixed at two
-- (field 4 of 4).
---------------------------------------------------------------
when CRC_BYTES =>
crc_in <= crc_out;
crc_data <= x"02";
state <= CHECK_CRC;
-- Check the CRC field from the address field matches
-- our calculated CRC. If it does assert af_valid to
-- confirm the data is correct and then stay here. When
-- the next address mark of the next address field is
-- detected this state machine will reset.
---------------------------------------------------------------
when CHECK_CRC =>
if crc_reg = crc_out then
SECTOR <= sector_reg(4 downto 0);
else
SECTOR <= (others => '1');
end if;
state <= CHECK_CRC;
when others =>
null;
end case;
end if;
end if;
end process main;
end read_address_field_arch;
|