library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity SD_Detection is
port (clk: in std_logic; cs_cd_dat3,cmd_di,dat0_do,dat1,dat2:inout std_logic; salida: out std_logic_vector(6 downto 0));
end SD_Detection;
architecture Sequence of SD_Detection is
signal cmd_0 : std_logic_vector(47 downto 0) := X"400000000095"; -- "0x40,0x00,0x00,0x00,0x00,0x95"
--"Respuesta = 0x01 : Tarjeta en modo IDLE"
signal cmd_41: std_logic_vector(47 downto 0) := X"4100000000FF"; -- "0x41,0x00,0x00,0x00,0x00,0xXX"
--"Respuesta = 0x00 : Tarjeta está lista"
signal cmd_55: std_logic_vector(47 downto 0) := X"7700000000FF"; -- "0x77,0x00,0x00,0x00,0x00,0xXX"
--"Respuesta = 0x00 : Tarjeta Kingstone no necesario"
signal cmd_58: std_logic_vector(47 downto 0) := X"7A00000000FF"; -- "0x7A,0x00,0x00,0x00,0x00,0xXX"
--"Respuesta = 0x00 : Tarjeta preparada para 3,3V"
signal clk_sdi, locked, fin, reset, cmd_dii, cs_cd_dat3i, clk_sd_pos_edge, clk_sd_neg_edge : std_logic;
signal response : std_logic_vector(7 downto 0):=X"00";
signal salidai : std_logic_vector(6 downto 0);
signal flancos_entr : integer range 0 to 48;
signal flancos_resp : integer range 0 to 8;
signal patron : std_logic_vector(3 downto 0);
signal count: integer range 0 to 90;
signal init_sd, init_resp: boolean;
begin
-- CLKDLL: Delay Locked Loop Circuit for Virtex and Spartan-II (Low frequency)
CLK_SDCARD : CLKDLL
generic map (
CLKDV_DIVIDE => 4.0, -- Divide by: 1.5,2.0,2.5,3.0,4.0,5.0,8.0 or 16.0
DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE
FACTORY_JF => X"C080", -- FACTORY JF Values
STARTUP_WAIT => FALSE) -- Delay config DONE until DLL LOCK, TRUE/FALSE
port map (
--CLK0 => CLK0, -- 0 degree DLL CLK ouptput
--CLK180 => CLK180, -- 180 degree DLL CLK output
--CLK270 => CLK270, -- 270 degree DLL CLK output
--CLK2X => CLK2X, -- 2X DLL CLK output
--CLK90 => CLK90, -- 90 degree DLL CLK output
CLKDV => clk_sdi, -- Divided DLL CLK out (CLKDV_DIVIDE)
LOCKED => locked, -- DLL LOCK status output --CLKFB => clk_sd_back, -- DLL clock feedback
CLKIN => clk, -- Clock input (from IBUFG, BUFG or DLL)
RST => reset -- DLL asynchronous reset input
);
HUELLA: process
begin
wait until clk'event and clk='1';
patron <= clk_sdi & patron(3 downto 1); -- Para observar flancos de clk.
end process;
clk_sd_neg_edge <= '1' when patron(1 downto 0)= "01" else '0';
clk_sd_pos_edge <= '1' when patron(1 downto 0)= "10" else '0';
process_count: process -- contando flancos de reloj. Dejamos unos 80 flancos para inicializar la tarjeta. (Min 74)
begin
wait until clk_sdi'event and clk_sdi = '1';
if (reset = '1') then
count <= 0;
init_sd <= false;
else
count <= count + 1;
if count = 80 then
init_sd <= true;
end if;
end if;
end process;
INTRO_CMD_0:process -- Comando de inicialización de tarjeta. Según esté CS, se irá a SPI mode o SD mode.
begin
wait until clk_sdi'event and clk_sdi = '1' and init_sd = true;
if reset = '1' then
fin <= '1';
flancos_entr<= 0 ;
cs_cd_dat3i<= '0'; -- directos a spi mode (Por ahora solo este modo) cmd_dii <= 'H';
dat0_do<= 'H';
dat1<= 'H';
dat2<= 'H';
else
if flancos_entr < 48 and ((fin = '1') or (fin = 'U')) then -- la U está pq no tengo reset inmediato.
cmd_dii <= cmd_0(47);
cmd_0 <= cmd_0(46 downto 0) & '0';
flancos_entr <= flancos_entr + 1;
else
fin <= '0';
if flancos_entr = 48 then
cs_cd_dat3i <= '1';
flancos_entr <= 0;
end if;
end if;
end if;
end process;-- Tengo que hacer una tabla con todos los comendos que uso. Tb necesito comprobar que el comando
-- que he introducido es el correcto.
cmd_di<=cmd_dii;
cs_cd_dat3<=cs_cd_dat3i;
WAIT_RESPONSE: process
begin
wait until clk_sdi'event and clk_sdi = '1' and init_sd = true;
if reset = '1' then
flancos_resp <= 0;
init_resp <= false;
else
if cs_cd_dat3 = '0' and fin = '0' and flancos_resp < 8 then
init_resp <= TRUE;
response <= response (6 downto 0) & cmd_di;
flancos_resp <= flancos_resp + 1;
end if;
end if;
end process;
WHAT_RESPONSE: process
begin
wait until clk_sdi'event and clk_sdi = '1' and init_resp = true;
if reset = '1' then
-- los que sea
else
if response(7) = '0' then
if response = "00000001" then
salidai<="1111001"; --1 (Veremos un 1 en los displays)
-- estamos en idle state
elsif response = "00000010" then
salidai<="0100100"; --2 (Veremos un 2 en los displays)...
-- estamos en erase reset
elsif response = "00000100" then
salidai<="0110000"; --3
-- estamos en illegal command
elsif response = "00001000" then
salidai<="0011001"; --4
-- estamos en "COMMAND CRC ERROR"
elsif response = "00010000" then
salidai<="0010010"; --5
-- estamos en "ERASE SEQUENCE ERROR"
elsif response = "00100000" then
salidai<="0000010"; --6
-- estamos en "ADDRES ERROR"
else
salidai<="1111000"; --7
-- estamos en "PARAMETER ERROR"
end if;
else
salidai<="0000000"; --8
-- error en la respuesta, el bit 7 debe ser 0
end if;
end if;
end process;
salida<=salidai;
end Sequence;