1 |
2 |
craighaywo |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company:
|
3 |
|
|
-- Engineer: CW
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 12:30:20 11/16/2014
|
6 |
|
|
-- Design Name:
|
7 |
|
|
-- Module Name: SdCardInit - Behavioral
|
8 |
|
|
-- Project Name:
|
9 |
|
|
-- Target Devices:
|
10 |
|
|
-- Tool versions:
|
11 |
|
|
-- Description:
|
12 |
|
|
--
|
13 |
|
|
-- Dependencies:
|
14 |
|
|
--
|
15 |
|
|
-- Revision:
|
16 |
|
|
-- Revision 0.01 - File Created
|
17 |
|
|
-- Additional Comments:
|
18 |
|
|
--
|
19 |
|
|
----------------------------------------------------------------------------------
|
20 |
|
|
library IEEE;
|
21 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
22 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
23 |
|
|
|
24 |
|
|
library UNISIM;
|
25 |
|
|
use UNISIM.VComponents.all;
|
26 |
|
|
|
27 |
|
|
entity SdCardInit is
|
28 |
|
|
Port ( CLK_IN : in STD_LOGIC;
|
29 |
|
|
RESET_IN : in STD_LOGIC;
|
30 |
|
|
|
31 |
|
|
SD_PRESENT_BAR_IN : in STD_LOGIC;
|
32 |
|
|
SD_INIT_OUT : out STD_LOGIC;
|
33 |
|
|
SD_BLOCK_RD_OUT : out STD_LOGIC;
|
34 |
|
|
SD_BLOCK_ADDR_OUT : out STD_LOGIC_VECTOR (31 downto 0);
|
35 |
|
|
SD_DATA_IN : in STD_LOGIC_VECTOR (7 downto 0);
|
36 |
|
|
SD_BUSY_IN : in STD_LOGIC;
|
37 |
|
|
SD_BYTE_RD_OUT : out STD_LOGIC;
|
38 |
|
|
SD_BYTE_RD_ACK_IN : in STD_LOGIC;
|
39 |
|
|
SD_ERROR_IN : in STD_LOGIC_VECTOR (15 downto 0);
|
40 |
|
|
SD_INIT_CMPLT_OUT : out STD_LOGIC;
|
41 |
|
|
|
42 |
|
|
FAT_BEGIN_ADDR_OUT : out STD_LOGIC_VECTOR (31 downto 0);
|
43 |
|
|
SECTORS_PER_FAT_OUT : out STD_LOGIC_VECTOR (31 downto 0);
|
44 |
|
|
CLUSTER_BEGIN_ADDR_OUT : out STD_LOGIC_VECTOR (31 downto 0);
|
45 |
|
|
SECTORS_PER_CLUSTER_OUT : out STD_LOGIC_VECTOR (7 downto 0);
|
46 |
|
|
ROOT_DIR_FIRST_CLUSTER_OUT : out STD_LOGIC_VECTOR (31 downto 0));
|
47 |
|
|
end SdCardInit;
|
48 |
|
|
|
49 |
|
|
architecture Behavioral of SdCardInit is
|
50 |
|
|
|
51 |
|
|
COMPONENT TDP_RAM
|
52 |
|
|
Generic (G_DATA_A_SIZE :natural :=32;
|
53 |
|
|
G_ADDR_A_SIZE :natural :=9;
|
54 |
|
|
G_RELATION :natural :=3;
|
55 |
|
|
G_INIT_FILE :string :="");--log2(SIZE_A/SIZE_B)
|
56 |
|
|
Port ( CLK_A_IN : in STD_LOGIC;
|
57 |
|
|
WE_A_IN : in STD_LOGIC;
|
58 |
|
|
ADDR_A_IN : in STD_LOGIC_VECTOR (G_ADDR_A_SIZE-1 downto 0);
|
59 |
|
|
DATA_A_IN : in STD_LOGIC_VECTOR (G_DATA_A_SIZE-1 downto 0);
|
60 |
|
|
DATA_A_OUT : out STD_LOGIC_VECTOR (G_DATA_A_SIZE-1 downto 0);
|
61 |
|
|
CLK_B_IN : in STD_LOGIC;
|
62 |
|
|
WE_B_IN : in STD_LOGIC;
|
63 |
|
|
ADDR_B_IN : in STD_LOGIC_VECTOR (G_ADDR_A_SIZE+G_RELATION-1 downto 0);
|
64 |
|
|
DATA_B_IN : in STD_LOGIC_VECTOR (G_DATA_A_SIZE/(2**G_RELATION)-1 downto 0);
|
65 |
|
|
DATA_B_OUT : out STD_LOGIC_VECTOR (G_DATA_A_SIZE/(2**G_RELATION)-1 downto 0));
|
66 |
|
|
END COMPONENT;
|
67 |
|
|
|
68 |
|
|
subtype slv is std_logic_vector;
|
69 |
|
|
|
70 |
|
|
------------------------ INIT FSM -----------------------------------
|
71 |
|
|
|
72 |
|
|
constant C_500_ms_startup_delay : unsigned(25 downto 0) := "10"&X"FAF080"; -- zero indexed
|
73 |
|
|
constant C_sd_init_attempts : unsigned(3 downto 0) := X"2"; -- zero indexed
|
74 |
|
|
constant C_mbr_veracity : std_logic_vector(15 downto 0) := X"AA55";
|
75 |
|
|
constant C_bytes_per_sector : std_logic_vector(15 downto 0) := X"0200";
|
76 |
|
|
constant C_volume_signature : std_logic_vector(15 downto 0) := X"AA55";
|
77 |
|
|
|
78 |
|
|
signal startup_delay_counter : unsigned(25 downto 0) := C_500_ms_startup_delay;
|
79 |
|
|
signal startup_delay_cmplt : std_logic := '0';
|
80 |
|
|
signal sd_busy, sd_present, sd_init, sd_rd_block, rd_byte, rd_byte_ack : std_logic := '0';
|
81 |
|
|
signal sd_init_attempts_counter : unsigned(3 downto 0) := X"0";
|
82 |
|
|
signal sd_error : std_logic_vector(15 downto 0) := (others => '0');
|
83 |
|
|
signal sd_data, block_rd_data : std_logic_vector(7 downto 0) := (others => '0');
|
84 |
|
|
signal sd_block_addr : std_logic_vector(31 downto 0) := (others => '0');
|
85 |
|
|
signal init_cmplt : std_logic;
|
86 |
|
|
|
87 |
|
|
signal mbr_veracity : std_logic_vector(15 downto 0) := (others => '0');
|
88 |
|
|
signal lba_block_addr : std_logic_vector(31 downto 0) := (others => '0');
|
89 |
|
|
signal num_reserved_sectors, vol_signature : std_logic_vector(15 downto 0);
|
90 |
|
|
signal bytes_per_sector : std_logic_vector(15 downto 0);
|
91 |
|
|
signal sectors_per_fat : std_logic_vector(30 downto 0);
|
92 |
|
|
|
93 |
|
|
signal sectors_per_cluster : unsigned(7 downto 0);
|
94 |
|
|
signal fat_begin_lba, cluster_begin_lba : unsigned(31 downto 0);
|
95 |
|
|
signal root_dir_cluster : unsigned(31 downto 0);
|
96 |
|
|
|
97 |
|
|
type MAIN_ROUTINE is ( REPORT_ERROR,
|
98 |
|
|
WAIT_FOR_SD_UNPLUGGED,
|
99 |
|
|
IDLE,
|
100 |
|
|
SD_INIT0,
|
101 |
|
|
SD_INIT1,
|
102 |
|
|
SD_INIT2,
|
103 |
|
|
SD_INIT3,
|
104 |
|
|
CHECK_FILE_SYS_VERACITY0,
|
105 |
|
|
CHECK_FILE_SYS_VERACITY1,
|
106 |
|
|
CHECK_FILE_SYS_VERACITY2,
|
107 |
|
|
CHECK_FILE_SYS_VERACITY3,
|
108 |
|
|
CHECK_FILE_SYS_VERACITY4,
|
109 |
|
|
CHECK_FILE_SYS_VERACITY5,
|
110 |
|
|
CHECK_FILE_SYS_VERACITY6,
|
111 |
|
|
GET_LBA_START_ADDR0,
|
112 |
|
|
GET_LBA_START_ADDR1,
|
113 |
|
|
GET_LBA_START_ADDR2,
|
114 |
|
|
GET_LBA_START_ADDR3,
|
115 |
|
|
GET_LBA_START_ADDR4,
|
116 |
|
|
GET_LBA_START_ADDR5,
|
117 |
|
|
GET_LBA_START_ADDR6,
|
118 |
|
|
GET_VOLUME_ID_DATA0,
|
119 |
|
|
GET_VOLUME_ID_DATA1,
|
120 |
|
|
GET_VOLUME_ID_DATA2,
|
121 |
|
|
GET_VOLUME_ID_DATA3,
|
122 |
|
|
GET_VOLUME_ID_DATA4,
|
123 |
|
|
GET_VOLUME_ID_DATA5,
|
124 |
|
|
GET_VOLUME_ID_DATA6,
|
125 |
|
|
GET_VOLUME_ID_DATA7,
|
126 |
|
|
GET_VOLUME_ID_DATA8,
|
127 |
|
|
GET_VOLUME_ID_DATA9,
|
128 |
|
|
GET_VOLUME_ID_DATA10,
|
129 |
|
|
GET_VOLUME_ID_DATA11,
|
130 |
|
|
GET_VOLUME_ID_DATA12,
|
131 |
|
|
GET_VOLUME_ID_DATA13,
|
132 |
|
|
GET_VOLUME_ID_DATA14,
|
133 |
|
|
GET_VOLUME_ID_DATA15,
|
134 |
|
|
GET_VOLUME_ID_DATA16,
|
135 |
|
|
GET_VOLUME_ID_DATA17,
|
136 |
|
|
GET_VOLUME_ID_DATA18,
|
137 |
|
|
GET_VOLUME_ID_DATA19,
|
138 |
|
|
GET_VOLUME_ID_DATA20,
|
139 |
|
|
GET_VOLUME_ID_DATA21,
|
140 |
|
|
GET_VOLUME_ID_DATA22,
|
141 |
|
|
GET_VOLUME_ID_DATA23,
|
142 |
|
|
SD_INIT_CMPLT);
|
143 |
|
|
|
144 |
|
|
signal ir_state, ir_next_state : MAIN_ROUTINE := IDLE;
|
145 |
|
|
|
146 |
|
|
------------------------ BLOCK RD -----------------------------------
|
147 |
|
|
|
148 |
|
|
signal perform_block_rd, block_rd_we : std_logic := '0';
|
149 |
|
|
signal block_wr_addr, block_rd_addr : unsigned(8 downto 0);
|
150 |
|
|
|
151 |
|
|
type BLOCK_RD_ROUTINE is ( IDLE,
|
152 |
|
|
READ_BYTE0,
|
153 |
|
|
READ_BYTE1,
|
154 |
|
|
READ_BYTE2,
|
155 |
|
|
READ_BYTE3 );
|
156 |
|
|
signal br_state, br_next_state : BLOCK_RD_ROUTINE;
|
157 |
|
|
|
158 |
|
|
begin
|
159 |
|
|
|
160 |
|
|
SD_INIT_OUT <= sd_init;
|
161 |
|
|
SD_BLOCK_RD_OUT <= sd_rd_block;
|
162 |
|
|
SD_BLOCK_ADDR_OUT <= sd_block_addr;
|
163 |
|
|
sd_data <= SD_DATA_IN;
|
164 |
|
|
sd_busy <= SD_BUSY_IN;
|
165 |
|
|
SD_BYTE_RD_OUT <= rd_byte;
|
166 |
|
|
rd_byte_ack <= SD_BYTE_RD_ACK_IN;
|
167 |
|
|
sd_error <= SD_ERROR_IN;
|
168 |
|
|
SD_INIT_CMPLT_OUT <= init_cmplt;
|
169 |
|
|
|
170 |
|
|
SECTORS_PER_FAT_OUT <= '0'§ors_per_fat;
|
171 |
|
|
FAT_BEGIN_ADDR_OUT <= slv(fat_begin_lba);
|
172 |
|
|
CLUSTER_BEGIN_ADDR_OUT <= slv(cluster_begin_lba);
|
173 |
|
|
SECTORS_PER_CLUSTER_OUT <= slv(sectors_per_cluster);
|
174 |
|
|
ROOT_DIR_FIRST_CLUSTER_OUT <= slv(root_dir_cluster);
|
175 |
|
|
|
176 |
|
|
STARTUP_DELAY: process(CLK_IN)
|
177 |
|
|
begin
|
178 |
|
|
if rising_edge(CLK_IN) then
|
179 |
|
|
if ir_state = IDLE then
|
180 |
|
|
if sd_present = '1' and startup_delay_counter /= "00"&X"000000" then
|
181 |
|
|
startup_delay_counter <= startup_delay_counter - 1;
|
182 |
|
|
else
|
183 |
|
|
startup_delay_counter <= C_500_ms_startup_delay;
|
184 |
|
|
end if;
|
185 |
|
|
else
|
186 |
|
|
startup_delay_counter <= C_500_ms_startup_delay;
|
187 |
|
|
end if;
|
188 |
|
|
if startup_delay_counter = X"000000" then
|
189 |
|
|
startup_delay_cmplt <= '1';
|
190 |
|
|
else
|
191 |
|
|
startup_delay_cmplt <= '0';
|
192 |
|
|
end if;
|
193 |
|
|
end if;
|
194 |
|
|
end process;
|
195 |
|
|
|
196 |
|
|
SD_CARD_PRESENT: process(CLK_IN)
|
197 |
|
|
begin
|
198 |
|
|
if rising_edge(CLK_IN) then
|
199 |
|
|
sd_present <= not SD_PRESENT_BAR_IN;
|
200 |
|
|
end if;
|
201 |
|
|
end process;
|
202 |
|
|
|
203 |
|
|
SD_INIT_FLAGS: process(CLK_IN)
|
204 |
|
|
begin
|
205 |
|
|
if rising_edge(CLK_IN) then
|
206 |
|
|
if ir_state = SD_INIT0 then
|
207 |
|
|
sd_init <= '1';
|
208 |
|
|
else
|
209 |
|
|
sd_init <= '0';
|
210 |
|
|
end if;
|
211 |
|
|
if ir_state = SD_INIT2 then
|
212 |
|
|
sd_init_attempts_counter <= sd_init_attempts_counter + 1;
|
213 |
|
|
end if;
|
214 |
|
|
end if;
|
215 |
|
|
end process;
|
216 |
|
|
|
217 |
|
|
SD_RD_BLOCK_FLAGS: process(CLK_IN)
|
218 |
|
|
begin
|
219 |
|
|
if rising_edge(CLK_IN) then
|
220 |
|
|
if ir_state = CHECK_FILE_SYS_VERACITY0 then
|
221 |
|
|
sd_rd_block <= '1';
|
222 |
|
|
elsif ir_state = GET_LBA_START_ADDR6 then
|
223 |
|
|
sd_rd_block <= '1';
|
224 |
|
|
else
|
225 |
|
|
sd_rd_block <= '0';
|
226 |
|
|
end if;
|
227 |
|
|
if ir_state = CHECK_FILE_SYS_VERACITY0 then
|
228 |
|
|
sd_block_addr <= X"00000000";
|
229 |
|
|
elsif ir_state = GET_LBA_START_ADDR6 then
|
230 |
|
|
sd_block_addr <= lba_block_addr;
|
231 |
|
|
else
|
232 |
|
|
sd_block_addr <= X"00000000";
|
233 |
|
|
end if;
|
234 |
|
|
if ir_state = CHECK_FILE_SYS_VERACITY2 then
|
235 |
|
|
block_rd_addr <= "1"&X"FE";
|
236 |
|
|
elsif ir_state = CHECK_FILE_SYS_VERACITY3 then
|
237 |
|
|
block_rd_addr <= "1"&X"FF";
|
238 |
|
|
elsif ir_state = GET_LBA_START_ADDR0 then
|
239 |
|
|
block_rd_addr <= "1"&X"C6";
|
240 |
|
|
elsif ir_state = GET_LBA_START_ADDR1 then
|
241 |
|
|
block_rd_addr <= "1"&X"C7";
|
242 |
|
|
elsif ir_state = GET_LBA_START_ADDR2 then
|
243 |
|
|
block_rd_addr <= "1"&X"C8";
|
244 |
|
|
elsif ir_state = GET_LBA_START_ADDR3 then
|
245 |
|
|
block_rd_addr <= "1"&X"C9";
|
246 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA2 then
|
247 |
|
|
block_rd_addr <= "0"&X"0D";
|
248 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA3 then
|
249 |
|
|
block_rd_addr <= "0"&X"0E";
|
250 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA4 then
|
251 |
|
|
block_rd_addr <= "0"&X"0F";
|
252 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA5 then
|
253 |
|
|
block_rd_addr <= "0"&X"24";
|
254 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA6 then
|
255 |
|
|
block_rd_addr <= "0"&X"25";
|
256 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA7 then
|
257 |
|
|
block_rd_addr <= "0"&X"26";
|
258 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA8 then
|
259 |
|
|
block_rd_addr <= "0"&X"27";
|
260 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA9 then
|
261 |
|
|
block_rd_addr <= "0"&X"2C";
|
262 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA10 then
|
263 |
|
|
block_rd_addr <= "0"&X"2D";
|
264 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA11 then
|
265 |
|
|
block_rd_addr <= "0"&X"2E";
|
266 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA12 then
|
267 |
|
|
block_rd_addr <= "0"&X"2F";
|
268 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA13 then
|
269 |
|
|
block_rd_addr <= "1"&X"FE";
|
270 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA14 then
|
271 |
|
|
block_rd_addr <= "1"&X"FF";
|
272 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA15 then
|
273 |
|
|
block_rd_addr <= "0"&X"0B";
|
274 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA16 then
|
275 |
|
|
block_rd_addr <= "0"&X"0C";
|
276 |
|
|
else
|
277 |
|
|
block_rd_addr <= (others => '0');
|
278 |
|
|
end if;
|
279 |
|
|
if ir_state = CHECK_FILE_SYS_VERACITY4 then
|
280 |
|
|
mbr_veracity(7 downto 0) <= block_rd_data;
|
281 |
|
|
elsif ir_state = CHECK_FILE_SYS_VERACITY5 then
|
282 |
|
|
mbr_veracity(15 downto 8) <= block_rd_data;
|
283 |
|
|
end if;
|
284 |
|
|
end if;
|
285 |
|
|
end process;
|
286 |
|
|
|
287 |
|
|
LBA_SETUP: process(CLK_IN)
|
288 |
|
|
begin
|
289 |
|
|
if rising_edge(CLK_IN) then
|
290 |
|
|
if ir_state = GET_LBA_START_ADDR2 then
|
291 |
|
|
lba_block_addr(7 downto 0) <= block_rd_data;
|
292 |
|
|
elsif ir_state = GET_LBA_START_ADDR3 then
|
293 |
|
|
lba_block_addr(15 downto 8) <= block_rd_data;
|
294 |
|
|
elsif ir_state = GET_LBA_START_ADDR4 then
|
295 |
|
|
lba_block_addr(23 downto 16) <= block_rd_data;
|
296 |
|
|
elsif ir_state = GET_LBA_START_ADDR5 then
|
297 |
|
|
lba_block_addr(31 downto 24) <= block_rd_data;
|
298 |
|
|
end if;
|
299 |
|
|
end if;
|
300 |
|
|
end process;
|
301 |
|
|
|
302 |
|
|
VOLUME_DATA: process(CLK_IN)
|
303 |
|
|
begin
|
304 |
|
|
if rising_edge(CLK_IN) then
|
305 |
|
|
if ir_state = GET_VOLUME_ID_DATA4 then
|
306 |
|
|
sectors_per_cluster <= unsigned(block_rd_data);
|
307 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA5 then
|
308 |
|
|
num_reserved_sectors(7 downto 0) <= block_rd_data;
|
309 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA6 then
|
310 |
|
|
num_reserved_sectors(15 downto 8) <= block_rd_data;
|
311 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA7 then
|
312 |
|
|
sectors_per_fat(7 downto 0) <= block_rd_data;
|
313 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA8 then
|
314 |
|
|
sectors_per_fat(15 downto 8) <= block_rd_data;
|
315 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA9 then
|
316 |
|
|
sectors_per_fat(23 downto 16) <= block_rd_data;
|
317 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA10 then
|
318 |
|
|
sectors_per_fat(30 downto 24) <= block_rd_data(6 downto 0);
|
319 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA11 then
|
320 |
|
|
root_dir_cluster(7 downto 0) <= unsigned(block_rd_data);
|
321 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA12 then
|
322 |
|
|
root_dir_cluster(15 downto 8) <= unsigned(block_rd_data);
|
323 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA13 then
|
324 |
|
|
root_dir_cluster(23 downto 16) <= unsigned(block_rd_data);
|
325 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA14 then
|
326 |
|
|
root_dir_cluster(31 downto 24) <= unsigned(block_rd_data);
|
327 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA15 then
|
328 |
|
|
vol_signature(7 downto 0) <= block_rd_data;
|
329 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA16 then
|
330 |
|
|
vol_signature(15 downto 8) <= block_rd_data;
|
331 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA17 then
|
332 |
|
|
bytes_per_sector(7 downto 0) <= block_rd_data;
|
333 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA18 then
|
334 |
|
|
bytes_per_sector(15 downto 8) <= block_rd_data;
|
335 |
|
|
end if;
|
336 |
|
|
if ir_state = GET_VOLUME_ID_DATA20 then
|
337 |
|
|
fat_begin_lba <= unsigned(lba_block_addr) + RESIZE(unsigned(num_reserved_sectors), 32);
|
338 |
|
|
end if;
|
339 |
|
|
if ir_state = GET_VOLUME_ID_DATA21 then
|
340 |
|
|
cluster_begin_lba <= fat_begin_lba;
|
341 |
|
|
elsif ir_state = GET_VOLUME_ID_DATA22 then
|
342 |
|
|
cluster_begin_lba <= cluster_begin_lba + unsigned(sectors_per_fat&"0");
|
343 |
|
|
end if;
|
344 |
|
|
end if;
|
345 |
|
|
end process;
|
346 |
|
|
|
347 |
|
|
CMPLT_FLAG: process(CLK_IN)
|
348 |
|
|
begin
|
349 |
|
|
if rising_edge(CLK_IN) then
|
350 |
|
|
if ir_state = SD_INIT_CMPLT then
|
351 |
|
|
init_cmplt <= '1';
|
352 |
|
|
else
|
353 |
|
|
init_cmplt <= '0';
|
354 |
|
|
end if;
|
355 |
|
|
end if;
|
356 |
|
|
end process;
|
357 |
|
|
|
358 |
|
|
INIT_ROUTINE_SYNC: process(CLK_IN)
|
359 |
|
|
begin
|
360 |
|
|
if rising_edge(CLK_IN) then
|
361 |
|
|
if RESET_IN = '0' then
|
362 |
|
|
ir_state <= ir_next_state;
|
363 |
|
|
else
|
364 |
|
|
ir_state <= IDLE;
|
365 |
|
|
end if;
|
366 |
|
|
end if;
|
367 |
|
|
end process;
|
368 |
|
|
|
369 |
|
|
INIT_ROUTINE_DECODE: process ( ir_state,
|
370 |
|
|
sd_error,
|
371 |
|
|
sd_present,
|
372 |
|
|
startup_delay_cmplt,
|
373 |
|
|
sd_busy,
|
374 |
|
|
sd_init_attempts_counter,
|
375 |
|
|
mbr_veracity,
|
376 |
|
|
bytes_per_sector,
|
377 |
|
|
vol_signature )
|
378 |
|
|
begin
|
379 |
|
|
ir_next_state <= ir_state; -- default is to stay in current state
|
380 |
|
|
case (ir_state) is
|
381 |
|
|
when REPORT_ERROR =>
|
382 |
|
|
ir_next_state <= WAIT_FOR_SD_UNPLUGGED;
|
383 |
|
|
when WAIT_FOR_SD_UNPLUGGED =>
|
384 |
|
|
if sd_present = '0' then
|
385 |
|
|
ir_next_state <= IDLE;
|
386 |
|
|
end if;
|
387 |
|
|
when IDLE =>
|
388 |
|
|
if startup_delay_cmplt = '1' then
|
389 |
|
|
ir_next_state <= SD_INIT0;
|
390 |
|
|
end if;
|
391 |
|
|
when SD_INIT0 =>
|
392 |
|
|
if sd_busy = '1' then
|
393 |
|
|
ir_next_state <= SD_INIT1;
|
394 |
|
|
end if;
|
395 |
|
|
when SD_INIT1 =>
|
396 |
|
|
if sd_busy = '0' then
|
397 |
|
|
if sd_error = X"0000" then
|
398 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY0;
|
399 |
|
|
else
|
400 |
|
|
ir_next_state <= SD_INIT2;
|
401 |
|
|
end if;
|
402 |
|
|
end if;
|
403 |
|
|
when SD_INIT2 =>
|
404 |
|
|
if sd_init_attempts_counter = C_sd_init_attempts then
|
405 |
|
|
ir_next_state <= SD_INIT3;
|
406 |
|
|
else
|
407 |
|
|
ir_next_state <= SD_INIT0;
|
408 |
|
|
end if;
|
409 |
|
|
when SD_INIT3 =>
|
410 |
|
|
ir_next_state <= REPORT_ERROR;
|
411 |
|
|
when CHECK_FILE_SYS_VERACITY0 =>
|
412 |
|
|
if sd_busy = '1' then
|
413 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY1;
|
414 |
|
|
end if;
|
415 |
|
|
when CHECK_FILE_SYS_VERACITY1 =>
|
416 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY2;
|
417 |
|
|
when CHECK_FILE_SYS_VERACITY2 =>
|
418 |
|
|
if sd_busy = '0' then
|
419 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY3;
|
420 |
|
|
end if;
|
421 |
|
|
when CHECK_FILE_SYS_VERACITY3 =>
|
422 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY4;
|
423 |
|
|
when CHECK_FILE_SYS_VERACITY4 =>
|
424 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY5;
|
425 |
|
|
when CHECK_FILE_SYS_VERACITY5 =>
|
426 |
|
|
ir_next_state <= CHECK_FILE_SYS_VERACITY6;
|
427 |
|
|
when CHECK_FILE_SYS_VERACITY6 =>
|
428 |
|
|
if mbr_veracity = C_mbr_veracity then
|
429 |
|
|
ir_next_state <= GET_LBA_START_ADDR0;
|
430 |
|
|
else
|
431 |
|
|
ir_next_state <= REPORT_ERROR;
|
432 |
|
|
end if;
|
433 |
|
|
when GET_LBA_START_ADDR0 =>
|
434 |
|
|
ir_next_state <= GET_LBA_START_ADDR1;
|
435 |
|
|
when GET_LBA_START_ADDR1 =>
|
436 |
|
|
ir_next_state <= GET_LBA_START_ADDR2;
|
437 |
|
|
when GET_LBA_START_ADDR2 =>
|
438 |
|
|
ir_next_state <= GET_LBA_START_ADDR3;
|
439 |
|
|
when GET_LBA_START_ADDR3 =>
|
440 |
|
|
ir_next_state <= GET_LBA_START_ADDR4;
|
441 |
|
|
when GET_LBA_START_ADDR4 =>
|
442 |
|
|
ir_next_state <= GET_LBA_START_ADDR5;
|
443 |
|
|
when GET_LBA_START_ADDR5 =>
|
444 |
|
|
ir_next_state <= GET_LBA_START_ADDR6;
|
445 |
|
|
when GET_LBA_START_ADDR6 =>
|
446 |
|
|
if sd_busy = '1' then
|
447 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA0;
|
448 |
|
|
end if;
|
449 |
|
|
when GET_VOLUME_ID_DATA0 =>
|
450 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA1;
|
451 |
|
|
when GET_VOLUME_ID_DATA1 =>
|
452 |
|
|
if sd_busy = '0' then
|
453 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA2;
|
454 |
|
|
end if;
|
455 |
|
|
when GET_VOLUME_ID_DATA2 =>
|
456 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA3;
|
457 |
|
|
when GET_VOLUME_ID_DATA3 =>
|
458 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA4;
|
459 |
|
|
when GET_VOLUME_ID_DATA4 =>
|
460 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA5;
|
461 |
|
|
when GET_VOLUME_ID_DATA5 =>
|
462 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA6;
|
463 |
|
|
when GET_VOLUME_ID_DATA6 =>
|
464 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA7;
|
465 |
|
|
when GET_VOLUME_ID_DATA7 =>
|
466 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA8;
|
467 |
|
|
when GET_VOLUME_ID_DATA8 =>
|
468 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA9;
|
469 |
|
|
when GET_VOLUME_ID_DATA9 =>
|
470 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA10;
|
471 |
|
|
when GET_VOLUME_ID_DATA10 =>
|
472 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA11;
|
473 |
|
|
when GET_VOLUME_ID_DATA11 =>
|
474 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA12;
|
475 |
|
|
when GET_VOLUME_ID_DATA12 =>
|
476 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA13;
|
477 |
|
|
when GET_VOLUME_ID_DATA13 =>
|
478 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA14;
|
479 |
|
|
when GET_VOLUME_ID_DATA14 =>
|
480 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA15;
|
481 |
|
|
when GET_VOLUME_ID_DATA15 =>
|
482 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA16;
|
483 |
|
|
when GET_VOLUME_ID_DATA16 =>
|
484 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA17;
|
485 |
|
|
when GET_VOLUME_ID_DATA17 =>
|
486 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA18;
|
487 |
|
|
when GET_VOLUME_ID_DATA18 =>
|
488 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA19;
|
489 |
|
|
when GET_VOLUME_ID_DATA19 =>
|
490 |
|
|
if bytes_per_sector /= C_bytes_per_sector or vol_signature /= C_volume_signature then
|
491 |
|
|
ir_next_state <= REPORT_ERROR;
|
492 |
|
|
else
|
493 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA20;
|
494 |
|
|
end if;
|
495 |
|
|
when GET_VOLUME_ID_DATA20 =>
|
496 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA21;
|
497 |
|
|
when GET_VOLUME_ID_DATA21 =>
|
498 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA22;
|
499 |
|
|
when GET_VOLUME_ID_DATA22 =>
|
500 |
|
|
ir_next_state <= GET_VOLUME_ID_DATA23;
|
501 |
|
|
when GET_VOLUME_ID_DATA23 =>
|
502 |
|
|
ir_next_state <= SD_INIT_CMPLT;
|
503 |
|
|
when SD_INIT_CMPLT =>
|
504 |
|
|
ir_next_state <= SD_INIT_CMPLT;
|
505 |
|
|
end case;
|
506 |
|
|
end process;
|
507 |
|
|
|
508 |
|
|
BLOCK_READ_SYNC: process(CLK_IN)
|
509 |
|
|
begin
|
510 |
|
|
if rising_edge(CLK_IN) then
|
511 |
|
|
br_state <= br_next_state;
|
512 |
|
|
end if;
|
513 |
|
|
end process;
|
514 |
|
|
|
515 |
|
|
BLOCK_READ_TRIG: process(CLK_IN)
|
516 |
|
|
begin
|
517 |
|
|
if rising_edge(CLK_IN) then
|
518 |
|
|
if ir_state = CHECK_FILE_SYS_VERACITY0 and sd_busy = '1' then
|
519 |
|
|
perform_block_rd <= '1';
|
520 |
|
|
elsif ir_state = GET_LBA_START_ADDR6 and sd_busy = '1' then
|
521 |
|
|
perform_block_rd <= '1';
|
522 |
|
|
else
|
523 |
|
|
perform_block_rd <= '0';
|
524 |
|
|
end if;
|
525 |
|
|
end if;
|
526 |
|
|
end process;
|
527 |
|
|
|
528 |
|
|
BLOCK_READ_FLAGS: process(CLK_IN)
|
529 |
|
|
begin
|
530 |
|
|
if rising_edge(CLK_IN) then
|
531 |
|
|
if br_state = READ_BYTE0 and rd_byte_ack = '1' then
|
532 |
|
|
block_rd_we <= '1';
|
533 |
|
|
else
|
534 |
|
|
block_rd_we <= '0';
|
535 |
|
|
end if;
|
536 |
|
|
if br_state = READ_BYTE1 then
|
537 |
|
|
rd_byte <= '1';
|
538 |
|
|
elsif br_state = READ_BYTE2 and rd_byte_ack = '0' then
|
539 |
|
|
rd_byte <= '0';
|
540 |
|
|
end if;
|
541 |
|
|
if br_state = IDLE then
|
542 |
|
|
block_wr_addr <= (others => '0');
|
543 |
|
|
elsif br_state = READ_BYTE1 then
|
544 |
|
|
block_wr_addr <= block_wr_addr + 1;
|
545 |
|
|
end if;
|
546 |
|
|
end if;
|
547 |
|
|
end process;
|
548 |
|
|
|
549 |
|
|
BLOCK_READ_DECODE: process (br_state, perform_block_rd, rd_byte_ack, block_wr_addr)
|
550 |
|
|
begin
|
551 |
|
|
br_next_state <= br_state; -- default is to stay in current state
|
552 |
|
|
case (br_state) is
|
553 |
|
|
when IDLE =>
|
554 |
|
|
if perform_block_rd = '1' then
|
555 |
|
|
br_next_state <= READ_BYTE0;
|
556 |
|
|
end if;
|
557 |
|
|
when READ_BYTE0 =>
|
558 |
|
|
if rd_byte_ack = '1' then
|
559 |
|
|
br_next_state <= READ_BYTE1;
|
560 |
|
|
end if;
|
561 |
|
|
when READ_BYTE1 =>
|
562 |
|
|
br_next_state <= READ_BYTE2;
|
563 |
|
|
when READ_BYTE2 =>
|
564 |
|
|
if rd_byte_ack = '0' then
|
565 |
|
|
br_next_state <= READ_BYTE3;
|
566 |
|
|
end if;
|
567 |
|
|
when READ_BYTE3 =>
|
568 |
|
|
if block_wr_addr = "000000000" then
|
569 |
|
|
br_next_state <= IDLE;
|
570 |
|
|
else
|
571 |
|
|
br_next_state <= READ_BYTE0;
|
572 |
|
|
end if;
|
573 |
|
|
end case;
|
574 |
|
|
end process;
|
575 |
|
|
|
576 |
|
|
TDP_RAM_Inst : TDP_RAM
|
577 |
|
|
Generic Map ( G_DATA_A_SIZE => sd_data'length,
|
578 |
|
|
G_ADDR_A_SIZE => block_wr_addr'length,
|
579 |
|
|
G_RELATION => 0,
|
580 |
|
|
G_INIT_FILE => "") --log2(SIZE_A/SIZE_B)
|
581 |
|
|
Port Map ( CLK_A_IN => CLK_IN,
|
582 |
|
|
WE_A_IN => block_rd_we,
|
583 |
|
|
ADDR_A_IN => slv(block_wr_addr),
|
584 |
|
|
DATA_A_IN => sd_data,
|
585 |
|
|
DATA_A_OUT => open,
|
586 |
|
|
CLK_B_IN => CLK_IN,
|
587 |
|
|
WE_B_IN => '0',
|
588 |
|
|
ADDR_B_IN => slv(block_rd_addr),
|
589 |
|
|
DATA_B_IN => X"00",
|
590 |
|
|
DATA_B_OUT => block_rd_data);
|
591 |
|
|
|
592 |
|
|
end Behavioral;
|
593 |
|
|
|