ossc/ip/altera_up_sd_card_avalon_in.../hdl/Altera_UP_SD_Card_Response_...

308 lines
11 KiB
VHDL

-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module looks at the data on the CMD line and waits to receive a response.
-- It begins examining the data lines when the i_begin signal is asserted. It then
-- waits for a first '0'. It then proceeds to store as many bits as are required by
-- the response packet. Each message bit passes through the CRC7 circuit so that
-- the CRC check sum can be verified at the end of transmission. The circuit then produces
-- the o_data and o_CRC_passed outputs to indicate the message received and if the CRC
-- check passed.
--
-- If for some reason the requested response does not arrive within 56 clock cycles
-- then the circuit will produce a '1' on the o_timeout output. In such a case the
-- o_data should be ignored.
--
-- In case of a response that is not 001, 010, 011 or 110, the circuit expects
-- no response.
--
-- A signal o_done is asserted when the circuit has completed response retrieval. In
-- a case when a response is not expected, just wait for the CD Card to process the
-- command. This is done by waiting 8 (=PROCESSING_DELAY) clock cycles.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Response_Receiver is
generic (
TIMEOUT : std_logic_vector(7 downto 0) := "00111000";
BUSY_WAIT : std_logic_vector(7 downto 0) := "00110000";
PROCESSING_DELAY : std_logic_vector(7 downto 0) := "00001000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_begin : in std_logic;
i_scan_pulse : in std_logic;
i_datain : in std_logic;
i_wait_cmd_busy : in std_logic;
i_response_type : in std_logic_vector(2 downto 0);
o_data : out std_logic_vector(127 downto 0);
o_CRC_passed : out std_logic;
o_timeout : out std_logic;
o_done : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Response_Receiver is
component Altera_UP_SD_CRC7_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(6 downto 0)
);
end component;
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type state_type is (s_WAIT_BEGIN, s_WAIT_END, s_WAIT_PROCESSING_DELAY, s_WAIT_BUSY, s_WAIT_BUSY_END, s_WAIT_BEGIN_DEASSERT);
-- Register to hold the current state
signal current_state : state_type;
signal next_state : state_type;
-- Local wires
-- REGISTERED
signal registered_data_input : std_logic_vector(127 downto 0);
signal response_incoming : std_logic;
signal counter, timeout_counter : std_logic_vector(7 downto 0);
signal crc_shift, keep_reading_bits, shift_crc_bits : std_logic;
-- UNREGISTERED
signal limit, limit_minus_1 : std_logic_vector(7 downto 0);
signal check_crc : std_logic;
signal CRC_bits : std_logic_vector(6 downto 0);
signal start_reading_bits, operation_complete, enable_crc_unit : std_logic;
begin
-- Control FSM. Begin operation when i_begin is raised, then wait for the operation to end and i_begin to be deasserted.
state_regs: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
current_state <= s_WAIT_BEGIN;
elsif (rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
state_transitions: process(current_state, i_begin, operation_complete, timeout_counter, i_wait_cmd_busy, i_scan_pulse, i_datain)
begin
case current_state is
when s_WAIT_BEGIN =>
if (i_begin = '1') then
next_state <= s_WAIT_END;
else
next_state <= s_WAIT_BEGIN;
end if;
when s_WAIT_END =>
if (operation_complete = '1') then
if (timeout_counter = TIMEOUT) then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_PROCESSING_DELAY;
end if;
else
next_state <= s_WAIT_END;
end if;
when s_WAIT_PROCESSING_DELAY =>
if (timeout_counter = PROCESSING_DELAY) then
if (i_wait_cmd_busy = '1') then
next_state <= s_WAIT_BUSY;
else
next_state <= s_WAIT_BEGIN_DEASSERT;
end if;
else
next_state <= s_WAIT_PROCESSING_DELAY;
end if;
when s_WAIT_BUSY =>
if ((i_scan_pulse = '1') and (i_datain = '0')) then
next_state <= s_WAIT_BUSY_END;
else
if (timeout_counter = BUSY_WAIT) then
-- If the card did not become busy, then it would not have raised the optional busy signal.
-- In such a case, proceeed further as the command has finished correctly.
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BUSY;
end if;
end if;
when s_WAIT_BUSY_END =>
if ((i_scan_pulse = '1') and (i_datain = '1')) then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BUSY_END;
end if;
when s_WAIT_BEGIN_DEASSERT =>
if (i_begin = '1') then
next_state <= s_WAIT_BEGIN_DEASSERT;
else
next_state <= s_WAIT_BEGIN;
end if;
when others =>
next_state <= s_WAIT_BEGIN;
end case;
end process;
-- Store the response as it appears on the i_datain line.
received_data_buffer: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
registered_data_input <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Only read new data and update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
registered_data_input(127 downto 1) <= registered_data_input(126 downto 0);
registered_data_input(0) <= i_datain;
end if;
end if;
end if;
end process;
-- Counter received bits
data_read_counter: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
counter <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Reset he counter every time you being reading the response.
if (current_state = s_WAIT_BEGIN) then
counter <= (OTHERS => '0');
end if;
-- Update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
counter <= counter + '1';
end if;
end if;
end if;
end process;
operation_complete <= '1' when (((counter = limit) and (not (limit = "00000000"))) or
(timeout_counter = TIMEOUT) or
((timeout_counter = PROCESSING_DELAY) and (limit = "00000000"))) else '0';
-- Count the number of scan pulses before the response is received. If the counter
-- exceeds TIMEOUT value, then an error must have occured when the SD card received a message.
timeout_counter_control: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
timeout_counter <= (OTHERS=>'0');
elsif (rising_edge(i_clock)) then
-- Reset the counter every time you begin reading the response.
if ((current_state = s_WAIT_BEGIN) or ((current_state = s_WAIT_END) and (operation_complete = '1') and (not (timeout_counter = TIMEOUT)))) then
timeout_counter <= (OTHERS => '0');
end if;
-- Update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if (((start_reading_bits = '0') and (keep_reading_bits = '0') and (current_state = s_WAIT_END) and (not (timeout_counter = TIMEOUT))) or
(current_state = s_WAIT_PROCESSING_DELAY) or (current_state = s_WAIT_BUSY)) then
timeout_counter <= timeout_counter + '1';
end if;
end if;
end if;
end process;
-- Enable data storing only after you see the first 0.
read_enable_logic: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
keep_reading_bits <= '0';
elsif (rising_edge(i_clock)) then
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or ((keep_reading_bits = '1') and (not (counter = limit_minus_1)))) then
keep_reading_bits <= '1';
else
keep_reading_bits <= '0';
end if;
end if;
end if;
end process;
start_reading_bits <= '1' when ((current_state = s_WAIT_END) and (i_datain = '0') and
(counter = "00000000") and (not (limit = "00000000"))) else '0';
-- CRC7 checker.
crc_checker: Altera_UP_SD_CRC7_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_enable => enable_crc_unit,
i_shift => shift_crc_bits,
i_datain => registered_data_input(7),
o_crcout => CRC_bits
);
enable_crc_unit <= '1' when ((i_scan_pulse = '1') and (current_state = s_WAIT_END)) else '0';
-- Clear CRC7 registers before processing the response bits
crc_control_register: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
shift_crc_bits <= '1';
elsif (rising_edge(i_clock)) then
-- Reset he counter every time you being reading the response.
if (current_state = s_WAIT_BEGIN) then
-- clear the CRC7 contents before you process the next message.
shift_crc_bits <= '1';
end if;
-- Only read new data and update the counter value when the scan pulse is high.
if (i_scan_pulse = '1') then
if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then
if (counter = "00000111") then
-- Once the 7-bits of the CRC checker have been cleared you can process the message and
-- compute its CRC bits to verify the validity of the transmission.
shift_crc_bits <= '0';
end if;
end if;
end if;
end if;
end process;
-- Indicate the number of bits to expect in the response packet.
limit <= "00110000" when ((i_response_type = "001") or
(i_response_type = "011") or
(i_response_type = "110")) else
"10001000" when (i_response_type = "010") else
"00000000"; -- No response
limit_minus_1 <=
"00101111" when ((i_response_type = "001") or
(i_response_type = "011") or
(i_response_type = "110")) else
"10000111" when (i_response_type = "010") else
"00000000"; -- No response
check_crc <= '1' when ((i_response_type = "001") or (i_response_type = "110")) else '0';
-- Generate Circuit outputs
o_data <= (registered_data_input(127 downto 1) & '1') when (i_response_type = "010") else
(CONV_STD_LOGIC_VECTOR(0, 96) & registered_data_input(39 downto 8));
o_CRC_passed <= '1' when ((check_crc = '0') or
((registered_data_input(0) = '1') and (CRC_bits = registered_data_input(7 downto 1)))) else '0';
o_timeout <= '1' when (timeout_counter = TIMEOUT) else '0';
o_done <= '1' when (current_state = s_WAIT_BEGIN_DEASSERT) else '0';
end rtl;