mirror of https://github.com/marqs85/ossc.git
308 lines
11 KiB
VHDL
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; |