OpenCores
URL https://opencores.org/ocsvn/fat_32_file_parser/fat_32_file_parser/trunk

Subversion Repositories fat_32_file_parser

[/] [fat_32_file_parser/] [trunk/] [SdCardReadWrite.vhd] - Rev 2

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:20:06 11/16/2014 
-- Design Name: 
-- Module Name:    SdCardReadWrite - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library UNISIM;
use UNISIM.VComponents.all;
 
entity SdCardReadWrite is
    Port ( CLK_IN : in  STD_LOGIC;
           RESET_IN : in  STD_LOGIC;
 
			  FAT_BEGIN_ADDR_IN 				: in  STD_LOGIC_VECTOR (31 downto 0);
			  SECTORS_PER_FAT_IN				: in  STD_LOGIC_VECTOR (31 downto 0);
           CLUSTER_BEGIN_ADDR_IN 		: in  STD_LOGIC_VECTOR (31 downto 0);
           SECTORS_PER_CLUSTER_IN 		: in  STD_LOGIC_VECTOR (7 downto 0);
           ROOT_DIR_FIRST_CLUSTER_IN 	: in  STD_LOGIC_VECTOR (31 downto 0);
 
			  SD_INIT_CMPLT_IN 	: in STD_LOGIC;
 
			  SD_BLOCK_RD_OUT 	: out STD_LOGIC;
           SD_BLOCK_ADDR_OUT 	: out STD_LOGIC_VECTOR (31 downto 0);
           SD_DATA_IN 			: in  STD_LOGIC_VECTOR (7 downto 0);
           SD_BUSY_IN 			: in  STD_LOGIC;
           SD_BYTE_RD_OUT 		: out STD_LOGIC;
           SD_BYTE_RD_ACK_IN 	: in  STD_LOGIC;
 
			  GET_NEXT_DIRENT_IN			: in STD_LOGIC;
			  NEXT_DIRENT_DONE_OUT		: out STD_LOGIC;
			  DIRENT_IS_FOLDER_OUT		: out STD_LOGIC;
			  RD_DIRENT_NAME_CHAR_IN	: in STD_LOGIC;
			  DIRENT_CHAR_OUT				: out STD_LOGIC_VECTOR(7 downto 0);
			  END_OF_DIRENT_NAME_OUT	: out STD_LOGIC;
			  NO_MORE_DIRENTS_OUT		: out STD_LOGIC;
 
			  DEBUG_IN 		: in STD_LOGIC_VECTOR(7 downto 0);
			  DEBUG_OUT 	: out STD_LOGIC_VECTOR(15 downto 0);
			  DEBUG_OUT2	: out STD_LOGIC_VECTOR(7 downto 0));
end SdCardReadWrite;
 
architecture Behavioral of SdCardReadWrite is
 
	COMPONENT TDP_RAM
		Generic (G_DATA_A_SIZE 	:natural :=32;
					G_ADDR_A_SIZE	:natural :=9;
					G_RELATION		:natural :=3;
					G_INIT_FILE		:string :="");--log2(SIZE_A/SIZE_B)
		Port ( CLK_A_IN 	: in  STD_LOGIC;
				 WE_A_IN 	: in  STD_LOGIC;
				 ADDR_A_IN 	: in  STD_LOGIC_VECTOR (G_ADDR_A_SIZE-1 downto 0);
				 DATA_A_IN	: in  STD_LOGIC_VECTOR (G_DATA_A_SIZE-1 downto 0);
				 DATA_A_OUT	: out STD_LOGIC_VECTOR (G_DATA_A_SIZE-1 downto 0);
				 CLK_B_IN 	: in  STD_LOGIC;
				 WE_B_IN 	: in  STD_LOGIC;
				 ADDR_B_IN 	: in  STD_LOGIC_VECTOR (G_ADDR_A_SIZE+G_RELATION-1 downto 0);
				 DATA_B_IN 	: in  STD_LOGIC_VECTOR (G_DATA_A_SIZE/(2**G_RELATION)-1 downto 0);
				 DATA_B_OUT : out STD_LOGIC_VECTOR (G_DATA_A_SIZE/(2**G_RELATION)-1 downto 0));
	END COMPONENT;
 
	COMPONENT lifo is
		Generic ( 	G_LOG2_DEPTH  	: natural := 6;
						G_DATA_SIZE		: natural := 8	); -- LOG2(lifo depth)
		 Port ( CLK_IN 			: in  STD_LOGIC;
				  RESET_IN 			: in  STD_LOGIC;
				  CACHE_ADDR_IN	: in  STD_LOGIC;
				  GOTO_CACHE_IN 	: in  STD_LOGIC;
				  WR_DATA_IN 		: in  STD_LOGIC_VECTOR ((G_DATA_SIZE - 1) downto 0);
				  WR_EN_IN 			: in  STD_LOGIC;
				  RD_DATA_OUT 		: out STD_LOGIC_VECTOR ((G_DATA_SIZE - 1) downto 0);
				  RD_EN_IN 			: in  STD_LOGIC;
				  EMPTY_OUT 		: out STD_LOGIC;
				  FULL_OUT			: out STD_LOGIC);
	END COMPONENT;
 
subtype slv is std_logic_vector;
 
constant C_unused_entry 			: std_logic_vector(7 downto 0) := X"E5";
constant C_end_of_directory		: std_logic_vector(7 downto 0) := X"00";
constant C_file_name_type 			: std_logic_vector(7 downto 0) := X"0F";
constant C_folder_type 				: std_logic_vector(7 downto 0) := X"10";
constant C_file_type 				: std_logic_vector(7 downto 0) := X"20";
constant C_attrib_offset 			: unsigned(4 downto 0) := "01011";
constant C_lsb_word_lsb_offset 	: unsigned(4 downto 0) := "11010";
constant C_lsb_word_msb_offset 	: unsigned(4 downto 0) := "11011";
constant C_msb_word_lsb_offset 	: unsigned(4 downto 0) := "10100";
constant C_msb_word_msb_offset 	: unsigned(4 downto 0) := "10101";
 
signal sd_init_cmplt, sd_block_rd, perform_block_rd, block_rd_cmplt : std_logic := '0';
signal sd_busy, rd_byte, rd_byte_ack, get_next_dirent : std_logic := '0';
signal sd_data, block_rd_data	: std_logic_vector(7 downto 0) := (others => '0');
 
signal fat_begin_addr, sectors_per_fat : unsigned(31 downto 0);
signal sd_block_addr : unsigned(31 downto 0);
signal cluster_begin_addr : unsigned(31 downto 0);
signal find_dirent_addr, find_dirent_addr_rd, find_dirent_addr_cache : unsigned(8 downto 0) := (others => '0');
signal find_dirent_addr_rd_slv : std_logic_vector(8 downto 0);
 
signal dirent_found, dirent_is_folder : std_logic := '0';
signal dirent_lifo_we, dirent_lifo_rst, dirent_lifo_cache_addr 		: std_logic := '0';
signal dirent_lifo_goto_cache, dirent_lifo_full, dirent_lifo_empty 	: std_logic := '0';
 
signal folder_addr, folder_addr_tmp, folder_addr_final : unsigned(31 downto 0) := X"00000000";
signal sectors_per_cluster, spc_counter : std_logic_vector(7 downto 0) := X"00";
 
signal bp_lifo_rst, bp_lifo_we, bp_lifo_rd, bp_lifo_empty : std_logic := '0';
signal bp_lifo_block_data : std_logic_vector(31 downto 0) := (others => '0');
 
signal find_addr_lifo_rst, find_addr_lifo_we, find_addr_lifo_rd, find_addr_lifo_empty : std_logic := '0';
 
signal end_of_dirents : std_logic := '0';
signal sectors_per_cluster_zero_indexed, find_dirent_block_num, find_dirent_block_num_rd : unsigned(7 downto 0) := X"00";
signal current_cluster, current_cluster_buf, current_cluster_rd : unsigned(31 downto 0) := X"00000000";
signal current_cluster_fat_block_addr, current_cluster_tmp, next_cluster_lba : unsigned(31 downto 0) := X"00000000";
signal current_cluster_lifo_rst, current_cluster_lifo_we, current_cluster_lifo_rd : std_logic := '0';
signal current_cluster_lifo_empty : std_logic := '0';
signal current_cluster_rd_slv : std_logic_vector(31 downto 0);
 
signal find_dirent_block_lifo_rst, find_dirent_block_lifo_we, find_dirent_block_lifo_rd : std_logic := '0';
signal find_dirent_block_lifo_empty : std_logic := '0';
signal find_dirent_block_num_rd_slv : std_logic_vector(7 downto 0);
 
signal file_counter :unsigned(15 downto 0) := (others => '0');
signal debug : std_logic := '0';
 
type MAIN_ROUTINE is (	REPORT_ERROR,
								WAIT_FOR_INIT_CMPLT,
								IDLE_W_BLOCK_RD,
								IDLE_NO_BLOCK_RD,
 
								FIND_NEXT_DIRENT0,
								FIND_NEXT_DIRENT1,
								FIND_NEXT_DIRENT2,
								FIND_NEXT_DIRENT3,
								FIND_NEXT_DIRENT4,
								FIND_NEXT_DIRENT5,
								FIND_NEXT_DIRENT6,
 
								PARSE_NAME_DIRENT0,
								PARSE_NAME_DIRENT1,
								PARSE_NAME_DIRENT2,
								PARSE_NAME_DIRENT3,
								PARSE_NAME_DIRENT4,
								PARSE_NAME_DIRENT5,
								PARSE_NAME_DIRENT6,
								PARSE_NAME_DIRENT7,
								PARSE_NAME_DIRENT8,
								PARSE_NAME_DIRENT9,
								PARSE_NAME_DIRENT10,
								PARSE_NAME_DIRENT11,
								PARSE_NAME_DIRENT12,
								PARSE_NAME_DIRENT13,
								PARSE_NAME_DIRENT14,
								PARSE_NAME_DIRENT15,
								PARSE_NAME_DIRENT16,
								PARSE_NAME_DIRENT17,
 
								HANDLE_FILE_DIRENT0,
 
								HANDLE_END_OF_DIR0,
								HANDLE_END_OF_DIR1,
								HANDLE_END_OF_DIR2,
								HANDLE_END_OF_DIR3,
 
								HANDLE_FOLDER_DIRENT0,
								HANDLE_FOLDER_DIRENT1,
								HANDLE_FOLDER_DIRENT2,
								HANDLE_FOLDER_DIRENT3,
								HANDLE_FOLDER_DIRENT4,
								HANDLE_FOLDER_DIRENT5,
								HANDLE_FOLDER_DIRENT6,
								HANDLE_FOLDER_DIRENT7,
								HANDLE_FOLDER_DIRENT8,
								HANDLE_FOLDER_DIRENT9,
 
								HANDLE_INTERNAL_ADDR_INC0,
								HANDLE_INTERNAL_ADDR_INC1,
								HANDLE_INTERNAL_ADDR_INC2,
								HANDLE_INTERNAL_ADDR_INC3,
								HANDLE_INTERNAL_ADDR_INC4,
								HANDLE_INTERNAL_ADDR_INC5,
								HANDLE_INTERNAL_ADDR_INC6,
								HANDLE_INTERNAL_ADDR_INC7,
 
								FIND_NEXT_CLUSTER0,
								FIND_NEXT_CLUSTER1,
								FIND_NEXT_CLUSTER2,
								FIND_NEXT_CLUSTER3,
								FIND_NEXT_CLUSTER4,
								FIND_NEXT_CLUSTER5,
								FIND_NEXT_CLUSTER6,
								FIND_NEXT_CLUSTER7,
								FIND_NEXT_CLUSTER8,
								FIND_NEXT_CLUSTER9,
 
								HANDLE_END_OF_DIRENTS0,
								HANDLE_END_OF_DIRENTS1);
 
signal rw_state, rw_next_state, rw_state_cached : MAIN_ROUTINE := WAIT_FOR_INIT_CMPLT;
 
signal block_rd_we : std_logic := '0';
signal block_wr_addr, block_rd_addr : unsigned(8 downto 0) := (others => '0');
 
type BLOCK_RD_ROUTINE is (	IDLE,
									WAIT_UNTIL_NOT_BUSY,
									WAIT_UNTIL_BLOCK_READ_ACKD,
									READ_BYTE0,
									READ_BYTE1,
									READ_BYTE2,
									READ_BYTE3,
									READ_BYTE4
									);
signal br_state, br_next_state : BLOCK_RD_ROUTINE;
 
signal state_debug_sig : unsigned(5 downto 0);
signal state_debug_sig2 : unsigned(1 downto 0);
 
begin
 
	sd_init_cmplt <= SD_INIT_CMPLT_IN;
	SD_BLOCK_RD_OUT <= sd_block_rd;
	SD_BLOCK_ADDR_OUT <= slv(sd_block_addr);
	sd_data <= SD_DATA_IN;
	sd_busy <= SD_BUSY_IN;
	SD_BYTE_RD_OUT <= rd_byte;
	rd_byte_ack <= SD_BYTE_RD_ACK_IN;
 
	fat_begin_addr <= unsigned(FAT_BEGIN_ADDR_IN);
	sectors_per_fat <= unsigned(SECTORS_PER_FAT_IN);
	cluster_begin_addr <= unsigned(CLUSTER_BEGIN_ADDR_IN);
	get_next_dirent <= GET_NEXT_DIRENT_IN;
	sectors_per_cluster <= SECTORS_PER_CLUSTER_IN;
	sectors_per_cluster_zero_indexed <= unsigned(SECTORS_PER_CLUSTER_IN) - 1;
 
	NEXT_DIRENT_DONE_OUT <= dirent_found;
	DIRENT_IS_FOLDER_OUT <= dirent_is_folder;
	END_OF_DIRENT_NAME_OUT <= dirent_lifo_empty;
	NO_MORE_DIRENTS_OUT <= end_of_dirents;
 
--	debug_state: process(CLK_IN)
--	begin
-- 		if rising_edge(CLK_IN) then
--			case (br_state) is
--				when IDLE =>
--					state_debug_sig <= to_unsigned(0, 6);
--				when WAIT_UNTIL_NOT_BUSY =>
--					state_debug_sig <= to_unsigned(1, 6);
--				when WAIT_UNTIL_BLOCK_READ_ACKD =>
--					state_debug_sig <= to_unsigned(2, 6);
--				when READ_BYTE0 =>
--					state_debug_sig <= to_unsigned(3, 6);
--				when READ_BYTE1 =>
--					state_debug_sig <= to_unsigned(4, 6);
--				when READ_BYTE2 =>
--					state_debug_sig <= to_unsigned(5, 6);
--				when READ_BYTE3 =>
--					state_debug_sig <= to_unsigned(6, 6);
--				when READ_BYTE4 =>
--					state_debug_sig <= to_unsigned(7, 6);
--			end case;
--		end if;
--	end process;
 
	debug_state: process(CLK_IN)
	begin
 		if rising_edge(CLK_IN) then
 			case( rw_state ) is
 
				when REPORT_ERROR =>
					state_debug_sig <= to_unsigned(0, 6);
				when WAIT_FOR_INIT_CMPLT =>
					state_debug_sig <= to_unsigned(1, 6);
				when IDLE_W_BLOCK_RD =>
					state_debug_sig <= to_unsigned(2, 6);
				when IDLE_NO_BLOCK_RD =>
					state_debug_sig <= to_unsigned(3, 6);	
				when FIND_NEXT_DIRENT0 =>
					state_debug_sig <= to_unsigned(4, 6);
				when FIND_NEXT_DIRENT1 =>
					state_debug_sig <= to_unsigned(5, 6);
				when FIND_NEXT_DIRENT2 =>
					state_debug_sig <= to_unsigned(6, 6);
				when FIND_NEXT_DIRENT3 =>
					state_debug_sig <= to_unsigned(7, 6);
				when FIND_NEXT_DIRENT4 =>
					state_debug_sig <= to_unsigned(8, 6);
				when FIND_NEXT_DIRENT5 =>
					state_debug_sig <= to_unsigned(9, 6);
				when FIND_NEXT_DIRENT6 =>
					state_debug_sig <= to_unsigned(10, 6);	
				when PARSE_NAME_DIRENT0 =>
					state_debug_sig <= to_unsigned(11, 6);
				when PARSE_NAME_DIRENT1 =>
					state_debug_sig <= to_unsigned(12, 6);
				when PARSE_NAME_DIRENT2 =>
					state_debug_sig <= to_unsigned(13, 6);
				when PARSE_NAME_DIRENT3 =>
					state_debug_sig <= to_unsigned(14, 6);
				when PARSE_NAME_DIRENT4 =>
					state_debug_sig <= to_unsigned(15, 6);
				when PARSE_NAME_DIRENT5 =>
					state_debug_sig <= to_unsigned(16, 6);
				when PARSE_NAME_DIRENT6 =>
					state_debug_sig <= to_unsigned(17, 6);
				when PARSE_NAME_DIRENT7 =>
					state_debug_sig <= to_unsigned(18, 6);
				when PARSE_NAME_DIRENT8 =>
					state_debug_sig <= to_unsigned(19, 6);
				when PARSE_NAME_DIRENT9 =>
					state_debug_sig <= to_unsigned(20, 6);
				when PARSE_NAME_DIRENT10 =>
					state_debug_sig <= to_unsigned(21, 6);
				when PARSE_NAME_DIRENT11 =>
					state_debug_sig <= to_unsigned(22, 6);
				when PARSE_NAME_DIRENT12 =>
					state_debug_sig <= to_unsigned(23, 6);
				when PARSE_NAME_DIRENT13 =>
					state_debug_sig <= to_unsigned(24, 6);
				when PARSE_NAME_DIRENT14 =>
					state_debug_sig <= to_unsigned(25, 6);
				when PARSE_NAME_DIRENT15 =>
					state_debug_sig <= to_unsigned(26, 6);
				when PARSE_NAME_DIRENT16 =>
					state_debug_sig <= to_unsigned(27, 6);
				when PARSE_NAME_DIRENT17 =>
					state_debug_sig <= to_unsigned(28, 6);	
				when HANDLE_FILE_DIRENT0 =>
					state_debug_sig <= to_unsigned(29, 6);	
				when HANDLE_END_OF_DIR0 =>
					state_debug_sig <= to_unsigned(30, 6);
				when HANDLE_END_OF_DIR1 =>
					state_debug_sig <= to_unsigned(31, 6);
				when HANDLE_END_OF_DIR2 =>
					state_debug_sig <= to_unsigned(32, 6);
				when HANDLE_END_OF_DIR3 =>
					state_debug_sig <= to_unsigned(33, 6);
				when HANDLE_FOLDER_DIRENT0 =>
					state_debug_sig <= to_unsigned(34, 6);
				when HANDLE_FOLDER_DIRENT1 =>
					state_debug_sig <= to_unsigned(35, 6);
				when HANDLE_FOLDER_DIRENT2 =>
					state_debug_sig <= to_unsigned(36, 6);
				when HANDLE_FOLDER_DIRENT3 =>
					state_debug_sig <= to_unsigned(37, 6);
				when HANDLE_FOLDER_DIRENT4 =>
					state_debug_sig <= to_unsigned(38, 6);
				when HANDLE_FOLDER_DIRENT5 =>
					state_debug_sig <= to_unsigned(39, 6);
				when HANDLE_FOLDER_DIRENT6 =>
					state_debug_sig <= to_unsigned(40, 6);
				when HANDLE_FOLDER_DIRENT7 =>
					state_debug_sig <= to_unsigned(41, 6);
				when HANDLE_FOLDER_DIRENT8 =>
					state_debug_sig <= to_unsigned(42, 6);
				when HANDLE_FOLDER_DIRENT9 =>
					state_debug_sig <= to_unsigned(43, 6);
				when HANDLE_INTERNAL_ADDR_INC0 =>
					state_debug_sig <= to_unsigned(44, 6);
				when HANDLE_INTERNAL_ADDR_INC1 =>
					state_debug_sig <= to_unsigned(45, 6);
				when HANDLE_INTERNAL_ADDR_INC2 =>
					state_debug_sig <= to_unsigned(46, 6);
				when HANDLE_INTERNAL_ADDR_INC3 =>
					state_debug_sig <= to_unsigned(47, 6);
				when HANDLE_INTERNAL_ADDR_INC4 =>
					state_debug_sig <= to_unsigned(48, 6);
				when HANDLE_INTERNAL_ADDR_INC5 =>
					state_debug_sig <= to_unsigned(49, 6);
				when HANDLE_INTERNAL_ADDR_INC6 =>
					state_debug_sig <= to_unsigned(50, 6);
				when HANDLE_INTERNAL_ADDR_INC7 =>
					state_debug_sig <= to_unsigned(51, 6);
				when FIND_NEXT_CLUSTER0 =>
					state_debug_sig <= to_unsigned(52, 6);
				when FIND_NEXT_CLUSTER1 =>
					state_debug_sig <= to_unsigned(53, 6);
				when FIND_NEXT_CLUSTER2 =>
					state_debug_sig <= to_unsigned(54, 6);
				when FIND_NEXT_CLUSTER3 =>
					state_debug_sig <= to_unsigned(55, 6);
				when FIND_NEXT_CLUSTER4 =>
					state_debug_sig <= to_unsigned(56, 6);
				when FIND_NEXT_CLUSTER5 =>
					state_debug_sig <= to_unsigned(57, 6);
				when FIND_NEXT_CLUSTER6 =>
					state_debug_sig <= to_unsigned(58, 6);
				when FIND_NEXT_CLUSTER7 =>
					state_debug_sig <= to_unsigned(59, 6);
				when FIND_NEXT_CLUSTER8 =>
					state_debug_sig <= to_unsigned(60, 6);
				when FIND_NEXT_CLUSTER9 =>
					state_debug_sig <= to_unsigned(61, 6);				
				when HANDLE_END_OF_DIRENTS0 =>
					state_debug_sig <= to_unsigned(62, 6);
				when HANDLE_END_OF_DIRENTS1 =>
					state_debug_sig <= to_unsigned(63, 6);
 			end case;
 		end if;
 	end process;
 
	debug_state2: process(CLK_IN)
	begin
 		if rising_edge(CLK_IN) then
 			case( rw_state_cached ) is
 
				when FIND_NEXT_DIRENT2 =>
					state_debug_sig2 <= to_unsigned(0, 2);
				when PARSE_NAME_DIRENT15 =>
					state_debug_sig2 <= to_unsigned(1, 2);
				when IDLE_NO_BLOCK_RD =>
					state_debug_sig2 <= to_unsigned(2, 2);
				when others =>
					state_debug_sig2 <= to_unsigned(3, 2);
			end case;
		end if;
	end process;
 
-------- FSM OUTPUT --------
 
	BLOCK_RD: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_state = WAIT_FOR_INIT_CMPLT then
				sd_block_addr <= cluster_begin_addr;
			elsif rw_state = HANDLE_FOLDER_DIRENT9 then
				sd_block_addr <= folder_addr_final;
			elsif rw_state = HANDLE_END_OF_DIR0 then
				sd_block_addr <= unsigned(bp_lifo_block_data);
			elsif rw_state = HANDLE_END_OF_DIRENTS0 then
				sd_block_addr <= cluster_begin_addr;
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC1 then
				sd_block_addr <= sd_block_addr + 1;
			elsif rw_state = FIND_NEXT_CLUSTER1 then
				sd_block_addr <= current_cluster_fat_block_addr;
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC6 then
				sd_block_addr <= next_cluster_lba;
			end if;
			if rw_state = FIND_NEXT_DIRENT0 then
				perform_block_rd <= '1';
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC1 then
				perform_block_rd <= '1';
			elsif rw_state = FIND_NEXT_CLUSTER1 then
				perform_block_rd <= '1';
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC6 then
				perform_block_rd <= '1';
			else
				perform_block_rd <= '0';
			end if;
			if rw_state = FIND_NEXT_DIRENT2 then
				block_rd_addr <= find_dirent_addr;
			elsif rw_state = FIND_NEXT_DIRENT3 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_attrib_offset;
			elsif rw_state = PARSE_NAME_DIRENT1 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(30, 5);
			elsif rw_state = PARSE_NAME_DIRENT2 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(28,5);
			elsif rw_state = PARSE_NAME_DIRENT3 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(24,5);
			elsif rw_state = PARSE_NAME_DIRENT4 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(22,5);
			elsif rw_state = PARSE_NAME_DIRENT5 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(20,5);
			elsif rw_state = PARSE_NAME_DIRENT6 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(18,5);
			elsif rw_state = PARSE_NAME_DIRENT7 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(16,5);
			elsif rw_state = PARSE_NAME_DIRENT8 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(14,5);
			elsif rw_state = PARSE_NAME_DIRENT9 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(9, 5);
			elsif rw_state = PARSE_NAME_DIRENT10 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(7, 5);
			elsif rw_state = PARSE_NAME_DIRENT11 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(5, 5);
			elsif rw_state = PARSE_NAME_DIRENT12 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(3, 5);
			elsif rw_state = PARSE_NAME_DIRENT13 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & to_unsigned(1, 5);
			elsif rw_state = PARSE_NAME_DIRENT15 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_attrib_offset;
			elsif rw_state = HANDLE_FOLDER_DIRENT0 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_lsb_word_lsb_offset;
			elsif rw_state = HANDLE_FOLDER_DIRENT1 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_lsb_word_msb_offset;
			elsif rw_state = HANDLE_FOLDER_DIRENT2 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_msb_word_lsb_offset;
			elsif rw_state = HANDLE_FOLDER_DIRENT3 then
				block_rd_addr <= find_dirent_addr(8 downto 5) & C_msb_word_msb_offset;
			elsif rw_state = FIND_NEXT_CLUSTER3 then
				block_rd_addr <= current_cluster_buf(6 downto 0) & "00";
			elsif rw_state = FIND_NEXT_CLUSTER4 then
				block_rd_addr <= current_cluster_buf(6 downto 0) & "01";
			elsif rw_state = FIND_NEXT_CLUSTER5 then
				block_rd_addr <= current_cluster_buf(6 downto 0) & "10";
			elsif rw_state = FIND_NEXT_CLUSTER6 then
				block_rd_addr <= current_cluster_buf(6 downto 0) & "11";
			end if;
			if rw_state = FIND_NEXT_CLUSTER2 then
				current_cluster_buf <= current_cluster;
			end if;
			if rw_state = FIND_NEXT_DIRENT6 then
				rw_state_cached <= FIND_NEXT_DIRENT2;
			elsif rw_state = PARSE_NAME_DIRENT14 then
				rw_state_cached <= PARSE_NAME_DIRENT15;
			elsif rw_state = HANDLE_FILE_DIRENT0 then
				rw_state_cached <= IDLE_NO_BLOCK_RD;
			end if;
			if rw_state = HANDLE_FILE_DIRENT0 then
				file_counter <= file_counter + 1;
			elsif rw_state = HANDLE_END_OF_DIRENTS1 and DEBUG_IN(0) = '1' then
				file_counter <= (others => '0');
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT9 then
				find_dirent_addr <= (others => '0');
			elsif rw_state = HANDLE_END_OF_DIR0 then
				find_dirent_addr <= find_dirent_addr_rd;
			elsif rw_state = HANDLE_END_OF_DIRENTS0 then
				find_dirent_addr <= (others => '0');
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC0 then
				find_dirent_addr <= find_dirent_addr + "000100000";
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT0 then
				find_dirent_addr_cache <= find_dirent_addr + "000100000";
			end if;
			if rw_state = HANDLE_INTERNAL_ADDR_INC1 then
				if find_dirent_block_num = sectors_per_cluster_zero_indexed then
					find_dirent_block_num <= (others => '0');
				else
					find_dirent_block_num <= find_dirent_block_num + 1;
				end if;
			elsif rw_state = HANDLE_FOLDER_DIRENT9 then
				find_dirent_block_num <= (others => '0');
			elsif rw_state = HANDLE_END_OF_DIR0 then
				find_dirent_block_num <= find_dirent_block_num_rd;
			end if;
		end if;
	end process;
 
	DIRENT_LIFO: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_next_state = PARSE_NAME_DIRENT0 then
				dirent_lifo_rst <= '1';
			else
				dirent_lifo_rst <= '0';
			end if;
			if rw_state = PARSE_NAME_DIRENT2 then
				dirent_lifo_we <= '1';
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC0 then
				dirent_lifo_we <= '0';
			end if;
		end if;
	end process;
 
	dirent_name_lifo : lifo
		Generic Map ( 	G_LOG2_DEPTH 	=> 7,
							G_DATA_SIZE		=> block_rd_data'length	)
		 Port Map ( CLK_IN 			=> CLK_IN,
						RESET_IN 		=> dirent_lifo_rst,
						CACHE_ADDR_IN	=> dirent_lifo_cache_addr,
						GOTO_CACHE_IN 	=> dirent_lifo_goto_cache,
						WR_DATA_IN 		=> block_rd_data,
						WR_EN_IN 		=> dirent_lifo_we,
						RD_DATA_OUT 	=> DIRENT_CHAR_OUT,
						RD_EN_IN 		=> RD_DIRENT_NAME_CHAR_IN,
						EMPTY_OUT 		=> dirent_lifo_empty,
						FULL_OUT			=> dirent_lifo_full);
 
	HANDLE_FOLDER_DIRENT: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_next_state = HANDLE_FOLDER_DIRENT0 or rw_next_state = HANDLE_FILE_DIRENT0 then
				dirent_found <= '1';
			else
				dirent_found <= '0';
			end if;
			if rw_next_state = HANDLE_FOLDER_DIRENT0 then
				dirent_is_folder <= '1';
			else
				dirent_is_folder <= '0';
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT2 then
				folder_addr(7 downto 0) <= unsigned(block_rd_data);
			elsif rw_state = HANDLE_FOLDER_DIRENT3 then
				folder_addr(15 downto 8) <= unsigned(block_rd_data);
			elsif rw_state = HANDLE_FOLDER_DIRENT4 then
				folder_addr(23 downto 16) <= unsigned(block_rd_data);
			elsif rw_state = HANDLE_FOLDER_DIRENT5 then
				folder_addr(31 downto 24) <= unsigned(block_rd_data);
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT6 then
				folder_addr_tmp <= (folder_addr - 2);
			elsif rw_state = HANDLE_FOLDER_DIRENT7 then
				folder_addr_tmp(31 downto 1) <= folder_addr_tmp(30 downto 0);
				folder_addr_tmp(0) <= '0';
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT8 then
				folder_addr_final <= folder_addr_tmp + cluster_begin_addr;
			end if;
			if rw_state = HANDLE_FOLDER_DIRENT7 or rw_state = HANDLE_INTERNAL_ADDR_INC4 then
				spc_counter(7 downto 1) <= spc_counter(6 downto 0);
				spc_counter(0) <= '0';
			else
				spc_counter <= X"02";
			end if;
 
 
 
		end if;
	end process;
 
	HANDLE_BP_CACHING: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_state = HANDLE_FOLDER_DIRENT0 then
				bp_lifo_we <= '1';
			else
				bp_lifo_we <= '0';
			end if;
			if rw_next_state = HANDLE_END_OF_DIR0 then
				bp_lifo_rd <= '1';
			else
				bp_lifo_rd <= '0';
			end if;
		end if;
	end process;
 
	sd_block_pointer_lifo : lifo
		Generic Map ( 	G_LOG2_DEPTH 	=> 5,
							G_DATA_SIZE		=> sd_block_addr'length	)
		 Port Map ( CLK_IN 			=> CLK_IN,
						RESET_IN 		=> bp_lifo_rst,
						CACHE_ADDR_IN	=> '0',
						GOTO_CACHE_IN 	=> '0',
						WR_DATA_IN 		=> slv(sd_block_addr),
						WR_EN_IN 		=> bp_lifo_we,
						RD_DATA_OUT 	=> bp_lifo_block_data,
						RD_EN_IN 		=> bp_lifo_rd,
						EMPTY_OUT 		=> bp_lifo_empty,
						FULL_OUT			=> open);
 
	find_addr_lifo_we <= bp_lifo_we;
	find_addr_lifo_rd <= bp_lifo_rd;
	find_dirent_addr_rd <= unsigned(find_dirent_addr_rd_slv);
 
	find_dirent_addr_lifo : lifo
		Generic Map ( 	G_LOG2_DEPTH 	=> 5,
							G_DATA_SIZE		=> find_dirent_addr'length	)
		 Port Map ( CLK_IN 			=> CLK_IN,
						RESET_IN 		=> find_addr_lifo_rst,
						CACHE_ADDR_IN	=> '0',
						GOTO_CACHE_IN 	=> '0',
						WR_DATA_IN 		=> slv(find_dirent_addr_cache),
						WR_EN_IN 		=> find_addr_lifo_we,
						RD_DATA_OUT 	=> find_dirent_addr_rd_slv,
						RD_EN_IN 		=> find_addr_lifo_rd,
						EMPTY_OUT 		=> find_addr_lifo_empty,
						FULL_OUT			=> open);
 
	HANDLE_END_FLAG: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_state = HANDLE_END_OF_DIRENTS0 then
				end_of_dirents <= '1';
			elsif rw_state = FIND_NEXT_DIRENT0 then
				end_of_dirents <= '0';
			end if;
		end if;
	end process;
 
	GOTO_NEXT_CLUSTER: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_state = FIND_NEXT_CLUSTER0 then
				current_cluster_fat_block_addr <= fat_begin_addr + RESIZE(current_cluster(31 downto 7), 32);
			end if;
			if rw_state = FIND_NEXT_CLUSTER5 then
				current_cluster(7 downto 0) <= unsigned(block_rd_data);
			elsif rw_state = FIND_NEXT_CLUSTER6 then
				current_cluster(15 downto 8) <= unsigned(block_rd_data);
			elsif rw_state = FIND_NEXT_CLUSTER7 then
				current_cluster(23 downto 16) <= unsigned(block_rd_data);
			elsif rw_state = FIND_NEXT_CLUSTER8 then
				current_cluster(31 downto 24) <= unsigned(block_rd_data); -- TODO Check if equal to 0FFFFFFF (end of cluster) ?
			elsif rw_state = HANDLE_FOLDER_DIRENT6 then
				current_cluster <= folder_addr;
			elsif rw_state = WAIT_FOR_INIT_CMPLT or rw_state = HANDLE_END_OF_DIRENTS0 then
				current_cluster <= X"00000002"; -- TODO Set to ROOT_DIR_FIRST_CLUSTER_IN ?
			elsif rw_state = HANDLE_END_OF_DIR0 then
				current_cluster <= current_cluster_rd;
			end if;
			if rw_state = HANDLE_INTERNAL_ADDR_INC3 then
				current_cluster_tmp <= (current_cluster - 2);
			elsif rw_state = HANDLE_INTERNAL_ADDR_INC4 then
				current_cluster_tmp(31 downto 1) <= current_cluster_tmp(30 downto 0);
				current_cluster_tmp(0) <= '0';
			end if;
			if rw_state = HANDLE_INTERNAL_ADDR_INC5 then
				next_cluster_lba <= current_cluster_tmp + cluster_begin_addr;
			end if;
      end if;
   end process;
 
	current_cluster_lifo_we <= bp_lifo_we;
	current_cluster_lifo_rd <= bp_lifo_rd;
	current_cluster_rd <= unsigned(current_cluster_rd_slv);
 
	current_cluster_lifo : lifo
		Generic Map ( 	G_LOG2_DEPTH 	=> 5,
							G_DATA_SIZE		=> current_cluster'length	)
		 Port Map ( CLK_IN 			=> CLK_IN,
						RESET_IN 		=> current_cluster_lifo_rst,
						CACHE_ADDR_IN	=> '0',
						GOTO_CACHE_IN 	=> '0',
						WR_DATA_IN 		=> slv(current_cluster),
						WR_EN_IN 		=> current_cluster_lifo_we,
						RD_DATA_OUT 	=> current_cluster_rd_slv,
						RD_EN_IN 		=> current_cluster_lifo_rd,
						EMPTY_OUT 		=> current_cluster_lifo_empty,
						FULL_OUT			=> open);
 
	find_dirent_block_lifo_we <= bp_lifo_we;
	find_dirent_block_lifo_rd <= bp_lifo_rd;
	find_dirent_block_num_rd <= unsigned(find_dirent_block_num_rd_slv);
 
	find_dirent_block_num_lifo : lifo
		Generic Map ( 	G_LOG2_DEPTH 	=> 5,
							G_DATA_SIZE		=> find_dirent_block_num'length	)
		 Port Map ( CLK_IN 			=> CLK_IN,
						RESET_IN 		=> find_dirent_block_lifo_rst,
						CACHE_ADDR_IN	=> '0',
						GOTO_CACHE_IN 	=> '0',
						WR_DATA_IN 		=> slv(find_dirent_block_num),
						WR_EN_IN 		=> find_dirent_block_lifo_we,
						RD_DATA_OUT 	=> find_dirent_block_num_rd_slv,
						RD_EN_IN 		=> find_dirent_block_lifo_rd,
						EMPTY_OUT 		=> find_dirent_block_lifo_empty,
						FULL_OUT			=> open);
 
	LIFO_RST_PROC : process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if rw_state = HANDLE_END_OF_DIRENTS0 then
				find_dirent_block_lifo_rst <= '1';
				current_cluster_lifo_rst <= '1';
				find_addr_lifo_rst <= '1';
				bp_lifo_rst <= '1';
			else
				find_dirent_block_lifo_rst <= '0';
				current_cluster_lifo_rst <= '0';
				find_addr_lifo_rst <= '0';
				bp_lifo_rst <= '0';
			end if;
		end if;
	end process;
 
----------- MAIN FSM ------------
 
   MAIN_ROUTINE_SYNC: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if RESET_IN = '0' then
				rw_state <= rw_next_state;
			else
				rw_state <= IDLE_W_BLOCK_RD;
			end if;
      end if;
   end process;
 
	MAIN_ROUTINE_DECODE: process (	sd_init_cmplt,
												block_rd_cmplt,
												block_rd_cmplt
											)
   begin
      rw_next_state <= rw_state;  -- default is to stay in current state
      case (rw_state) is
			when REPORT_ERROR =>
				rw_next_state <= WAIT_FOR_INIT_CMPLT;
			when WAIT_FOR_INIT_CMPLT =>
				if sd_init_cmplt = '1' then
               rw_next_state <= IDLE_W_BLOCK_RD;
            end if;
 
			when IDLE_W_BLOCK_RD =>
				if get_next_dirent = '1' then
					rw_next_state <= FIND_NEXT_DIRENT0;
				end if;
			when IDLE_NO_BLOCK_RD =>
				if get_next_dirent = '1' then
					rw_next_state <= FIND_NEXT_DIRENT2;
				end if;
 
			when FIND_NEXT_DIRENT0 =>
				rw_next_state <= FIND_NEXT_DIRENT1;
			when FIND_NEXT_DIRENT1 =>
				if block_rd_cmplt = '1' then
					rw_next_state <= FIND_NEXT_DIRENT2;
				end if;
			when FIND_NEXT_DIRENT2 =>
				rw_next_state <= FIND_NEXT_DIRENT3;
			when FIND_NEXT_DIRENT3 =>
				rw_next_state <= FIND_NEXT_DIRENT4;
			when FIND_NEXT_DIRENT4 =>
				if block_rd_data = C_unused_entry then
					rw_next_state <= FIND_NEXT_DIRENT6;
				elsif block_rd_data = C_end_of_directory then
					rw_next_state <= HANDLE_END_OF_DIR0;
				else
					rw_next_state <= FIND_NEXT_DIRENT5;
				end if;
			when FIND_NEXT_DIRENT5 =>
				if block_rd_data /= C_file_name_type then
					rw_next_state <= FIND_NEXT_DIRENT6;
				else
					rw_next_state <= PARSE_NAME_DIRENT0;
				end if;
			when FIND_NEXT_DIRENT6 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC0;
 
			when PARSE_NAME_DIRENT0 =>
				rw_next_state <= PARSE_NAME_DIRENT1;
			when PARSE_NAME_DIRENT1 =>
				rw_next_state <= PARSE_NAME_DIRENT2;
			when PARSE_NAME_DIRENT2 =>
				rw_next_state <= PARSE_NAME_DIRENT3;
			when PARSE_NAME_DIRENT3 =>
				rw_next_state <= PARSE_NAME_DIRENT4;
			when PARSE_NAME_DIRENT4 =>
				rw_next_state <= PARSE_NAME_DIRENT5;
			when PARSE_NAME_DIRENT5 =>
				rw_next_state <= PARSE_NAME_DIRENT6;
			when PARSE_NAME_DIRENT6 =>
				rw_next_state <= PARSE_NAME_DIRENT7;
			when PARSE_NAME_DIRENT7 =>
				rw_next_state <= PARSE_NAME_DIRENT8;
			when PARSE_NAME_DIRENT8 =>
				rw_next_state <= PARSE_NAME_DIRENT9;
			when PARSE_NAME_DIRENT9 =>
				rw_next_state <= PARSE_NAME_DIRENT10;
			when PARSE_NAME_DIRENT10 =>
				rw_next_state <= PARSE_NAME_DIRENT11;
			when PARSE_NAME_DIRENT11 =>
				rw_next_state <= PARSE_NAME_DIRENT12;
			when PARSE_NAME_DIRENT12 =>
				rw_next_state <= PARSE_NAME_DIRENT13;
			when PARSE_NAME_DIRENT13 =>
				rw_next_state <= PARSE_NAME_DIRENT14;
			when PARSE_NAME_DIRENT14 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC0;
			when PARSE_NAME_DIRENT15 =>
				rw_next_state <= PARSE_NAME_DIRENT16;
			when PARSE_NAME_DIRENT16 =>
				rw_next_state <= PARSE_NAME_DIRENT17;
			when PARSE_NAME_DIRENT17 =>		
				if block_rd_data = C_file_name_type then
					rw_next_state <= PARSE_NAME_DIRENT1;
				elsif block_rd_data(7 downto 4) = C_folder_type(7 downto 4) then
					rw_next_state <= HANDLE_FOLDER_DIRENT0;
				elsif block_rd_data(7 downto 4) = C_file_type(7 downto 4) then
					rw_next_state <= HANDLE_FILE_DIRENT0; -- TODO create 'else' case to prevent lockups
				end if;
 
			when HANDLE_FILE_DIRENT0 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC0;
 
			when HANDLE_END_OF_DIR0 =>
				if bp_lifo_empty = '0' then
					rw_next_state <= HANDLE_END_OF_DIR1;
				else
					rw_next_state <= HANDLE_END_OF_DIRENTS0;
				end if;
			when HANDLE_END_OF_DIR1 =>
				rw_next_state <= HANDLE_END_OF_DIR2;
			when HANDLE_END_OF_DIR2 =>
				rw_next_state <= HANDLE_END_OF_DIR3;
			when HANDLE_END_OF_DIR3 =>
					rw_next_state <= IDLE_W_BLOCK_RD;
 
			when HANDLE_FOLDER_DIRENT0 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT1;
			when HANDLE_FOLDER_DIRENT1 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT2;
			when HANDLE_FOLDER_DIRENT2 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT3;
			when HANDLE_FOLDER_DIRENT3 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT4;
			when HANDLE_FOLDER_DIRENT4 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT5;
			when HANDLE_FOLDER_DIRENT5 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT6;
			when HANDLE_FOLDER_DIRENT6 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT7;
			when HANDLE_FOLDER_DIRENT7 =>
				if spc_counter = sectors_per_cluster then
					rw_next_state <= HANDLE_FOLDER_DIRENT8;
				end if;
			when HANDLE_FOLDER_DIRENT8 =>
				rw_next_state <= HANDLE_FOLDER_DIRENT9;
			when HANDLE_FOLDER_DIRENT9 =>
				rw_next_state <= IDLE_W_BLOCK_RD;
 
			when HANDLE_END_OF_DIRENTS0 =>
				rw_next_state <= HANDLE_END_OF_DIRENTS1;
			when HANDLE_END_OF_DIRENTS1 =>
				if DEBUG_IN(0) = '1' then
					rw_next_state <= IDLE_W_BLOCK_RD;
				end if;
 
			when HANDLE_INTERNAL_ADDR_INC0 =>
				if find_dirent_addr(8 downto 5) = "1111" then
					rw_next_state <= HANDLE_INTERNAL_ADDR_INC1;
				else
					rw_next_state <= rw_state_cached;
				end if;
			when HANDLE_INTERNAL_ADDR_INC1 =>
				if find_dirent_block_num = sectors_per_cluster_zero_indexed then
					rw_next_state <= FIND_NEXT_CLUSTER0;
				else
					rw_next_state <= HANDLE_INTERNAL_ADDR_INC2;
				end if;
			when HANDLE_INTERNAL_ADDR_INC2 =>
				if block_rd_cmplt = '1' then
					rw_next_state <= rw_state_cached;
				end if;
			when HANDLE_INTERNAL_ADDR_INC3 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC4;
			when HANDLE_INTERNAL_ADDR_INC4 =>
				if spc_counter = sectors_per_cluster then
					rw_next_state <= HANDLE_INTERNAL_ADDR_INC5;
				end if;
			when HANDLE_INTERNAL_ADDR_INC5 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC6;
			when HANDLE_INTERNAL_ADDR_INC6 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC7;
			when HANDLE_INTERNAL_ADDR_INC7 =>
				if block_rd_cmplt = '1' then
					rw_next_state <= rw_state_cached;
				end if;
 
			when FIND_NEXT_CLUSTER0 =>
				rw_next_state <= FIND_NEXT_CLUSTER1;
			when FIND_NEXT_CLUSTER1 =>
				rw_next_state <= FIND_NEXT_CLUSTER2;
			when FIND_NEXT_CLUSTER2 =>
				if block_rd_cmplt = '1' then
					rw_next_state <= FIND_NEXT_CLUSTER3;
				end if;
			when FIND_NEXT_CLUSTER3 =>
				rw_next_state <= FIND_NEXT_CLUSTER4;
			when FIND_NEXT_CLUSTER4 =>
				rw_next_state <= FIND_NEXT_CLUSTER5;
			when FIND_NEXT_CLUSTER5 =>
				rw_next_state <= FIND_NEXT_CLUSTER6;
			when FIND_NEXT_CLUSTER6 =>
				rw_next_state <= FIND_NEXT_CLUSTER7;
			when FIND_NEXT_CLUSTER7 =>
				rw_next_state <= FIND_NEXT_CLUSTER8;
			when FIND_NEXT_CLUSTER8 =>
				rw_next_state <= FIND_NEXT_CLUSTER9;
			when FIND_NEXT_CLUSTER9 =>
				rw_next_state <= HANDLE_INTERNAL_ADDR_INC3;
 
		end case;
	end process;
 
----------- BLOCK READ FSM ------------
 
   BLOCK_READ_SYNC: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			br_state <= br_next_state;  
      end if;
   end process;
 
	BLOCK_READ_FLAGS: process(CLK_IN)
   begin
		if rising_edge(CLK_IN) then
			if br_state = READ_BYTE0 and rd_byte_ack = '1' then
				block_rd_we <= '1';
			else
				block_rd_we <= '0';
			end if;
			if br_state = READ_BYTE1 then
				rd_byte <= '1';
			elsif br_state = READ_BYTE2 and rd_byte_ack = '0' then
				rd_byte <= '0';
			end if;
			if br_state = IDLE then
				block_wr_addr <= (others => '0');
			elsif br_state = READ_BYTE1 then
				block_wr_addr <= block_wr_addr + 1;
			end if;
			if br_state = READ_BYTE4 then
				block_rd_cmplt <= '1';
			else
				block_rd_cmplt <= '0';
			end if;
			if br_state = WAIT_UNTIL_BLOCK_READ_ACKD then
				sd_block_rd <= '1';
			else
				sd_block_rd <= '0';
			end if;
      end if;
   end process;
 
	BLOCK_READ_DECODE: process (br_state, perform_block_rd, rd_byte_ack, block_wr_addr)
   begin
      br_next_state <= br_state;  -- default is to stay in current state
      case (br_state) is
			when IDLE =>
				if perform_block_rd = '1' then
					br_next_state <= WAIT_UNTIL_NOT_BUSY;
				end if;
			when WAIT_UNTIL_NOT_BUSY =>
				if sd_busy = '0' then
					br_next_state <= WAIT_UNTIL_BLOCK_READ_ACKD;
				end if;
			when WAIT_UNTIL_BLOCK_READ_ACKD =>
				if sd_busy = '1' then
					br_next_state <= READ_BYTE0;
				end if;
			when READ_BYTE0 =>
				if rd_byte_ack = '1' then
					br_next_state <= READ_BYTE1;
				end if;
			when READ_BYTE1 =>
				br_next_state <= READ_BYTE2;
			when READ_BYTE2 =>
				if rd_byte_ack = '0' then
					br_next_state <= READ_BYTE3;
				end if;
			when READ_BYTE3 =>
				if block_wr_addr = "000000000" then
					br_next_state <= READ_BYTE4;
				else
					br_next_state <= READ_BYTE0;
				end if;
			when READ_BYTE4 =>
				br_next_state <= IDLE;
		end case;
	end process;
 
	Block_Ram_Inst : TDP_RAM
		Generic Map (	G_DATA_A_SIZE 	=> sd_data'length,
							G_ADDR_A_SIZE	=> block_wr_addr'length,
							G_RELATION		=> 0,
							G_INIT_FILE		=> "") --log2(SIZE_A/SIZE_B)
		Port Map ( 	CLK_A_IN 	=> CLK_IN, 
						WE_A_IN 		=> block_rd_we,
						ADDR_A_IN 	=> slv(block_wr_addr),
						DATA_A_IN	=> sd_data,
						DATA_A_OUT	=> open,
						CLK_B_IN 	=> CLK_IN,
						WE_B_IN 		=> '0',
						ADDR_B_IN 	=> slv(block_rd_addr),
						DATA_B_IN 	=> X"00",
						DATA_B_OUT 	=> block_rd_data);
 
	--DEBUG_OUT2(0) <= '1' when rw_state = PARSE_NAME_DIRENT17 else '0';
 
	DEBUG_OUT2(5 downto 0) <= slv(state_debug_sig);
	DEBUG_OUT2(7) <= sd_busy;
 
 
	DEBUG_OUT <= slv(file_counter(15 downto 0));
 
end Behavioral;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.