ossc/ip/altera_up_sd_card_avalon_in.../hdl/Altera_UP_SD_Card_48_bit_Co...

570 lines
25 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 takes a command ID and data, and generates a 48-bit message for it.
-- It will first check if the command is a valid 48-bit command and produce the
-- following outputs:
-- 1. o_dataout -> a single bit output that produces the message to be sent to the
-- SD card one bit at a time. Every time the i_message_bit_out input
-- is high and the i_clock has a positive edge, a new bit is produced.
-- 2. o_message_done -> a signal that is asserted high when the entire message has been
-- produced through the o_dataout output.
-- 3. o_valid -> is a signal that is asserted high if the specified message is valid.
-- 4. o_response_type -> indicates the command response type.
-- 5. o_returning_ocr -> the response from the SD card will contain the OCR register
-- 6. o_returning_cid -> the response from the SD card will contain the CID register
-- 7. o_returning_rca -> the response from the SD card will contain the RCA register
-- 8. o_returning_csd -> the response from the SD card will contain the CSD register
-- 9. o_data_read -> asserted when the command being sent is a data read command.
-- 10. o_data_write -> asserted when the command being sent is a data write command.
-- 11. o_wait_cmd_busy -> is set high when the response to this command will be
-- followed by a busy signal.
--
-- 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_48_bit_Command_Generator is
generic (
-- Basic commands
COMMAND_0_GO_IDLE : STD_LOGIC_VECTOR(5 downto 0) := "000000";
COMMAND_2_ALL_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "000010";
COMMAND_3_SEND_RCA : STD_LOGIC_VECTOR(5 downto 0) := "000011";
COMMAND_4_SET_DSR : STD_LOGIC_VECTOR(5 downto 0) := "000100";
COMMAND_6_SWITCH_FUNCTION : STD_LOGIC_VECTOR(5 downto 0) := "000110";
COMMAND_7_SELECT_CARD : STD_LOGIC_VECTOR(5 downto 0) := "000111";
COMMAND_9_SEND_CSD : STD_LOGIC_VECTOR(5 downto 0) := "001001";
COMMAND_10_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "001010";
COMMAND_12_STOP_TRANSMISSION : STD_LOGIC_VECTOR(5 downto 0) := "001100";
COMMAND_13_SEND_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
COMMAND_15_GO_INACTIVE : STD_LOGIC_VECTOR(5 downto 0) := "001111";
-- Block oriented read/write/lock commands
COMMAND_16_SET_BLOCK_LENGTH : STD_LOGIC_VECTOR(5 downto 0) := "010000";
-- Block oriented read commands
COMMAND_17_READ_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "010001";
COMMAND_18_READ_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010010";
-- Block oriented write commands
COMMAND_24_WRITE_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "011000";
COMMAND_25_WRITE_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "011001";
COMMAND_27_PROGRAM_CSD : STD_LOGIC_VECTOR(5 downto 0) := "011011";
-- Block oriented write-protection commands
COMMAND_28_SET_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011100";
COMMAND_29_CLEAR_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011101";
COMMAND_30_SEND_PROTECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "011110";
-- Erase commands
COMMAND_32_ERASE_BLOCK_START : STD_LOGIC_VECTOR(5 downto 0) := "100000";
COMMAND_33_ERASE_BLOCK_END : STD_LOGIC_VECTOR(5 downto 0) := "100001";
COMMAND_38_ERASE_SELECTED_GROUPS: STD_LOGIC_VECTOR(5 downto 0) := "100110";
-- Block lock commands
COMMAND_42_LOCK_UNLOCK : STD_LOGIC_VECTOR(5 downto 0) := "101010";
-- Command Type Settings
COMMAND_55_APP_CMD : STD_LOGIC_VECTOR(5 downto 0) := "110111";
COMMAND_56_GEN_CMD : STD_LOGIC_VECTOR(5 downto 0) := "111000";
-- Application Specific commands - must be preceeded with command 55.
ACOMMAND_6_SET_BUS_WIDTH : STD_LOGIC_VECTOR(5 downto 0) := "000110";
ACOMMAND_13_SD_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101";
ACOMMAND_22_SEND_NUM_WR_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010100";
ACOMMAND_23_SET_BLK_ERASE_COUNT : STD_LOGIC_VECTOR(5 downto 0) := "010101";
ACOMMAND_41_SEND_OP_CONDITION : STD_LOGIC_VECTOR(5 downto 0) := "101001";
ACOMMAND_42_SET_CLR_CARD_DETECT : STD_LOGIC_VECTOR(5 downto 0) := "101010";
ACOMMAND_51_SEND_SCR : STD_LOGIC_VECTOR(5 downto 0) := "110011";
-- First custom_command
FIRST_NON_PREDEFINED_COMMAND : STD_LOGIC_VECTOR(3 downto 0) := "1010"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_message_bit_out : in std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_predefined_message : in std_logic_vector(3 downto 0);
i_generate : in std_logic;
i_DSR : in std_logic_vector(15 downto 0);
i_OCR : in std_logic_vector(31 downto 0);
i_RCA : in std_logic_vector(15 downto 0);
o_dataout : out std_logic;
o_message_done : out std_logic;
o_valid : out std_logic;
o_returning_ocr : out std_logic;
o_returning_cid : out std_logic;
o_returning_rca : out std_logic;
o_returning_csd : out std_logic;
o_returning_status : out std_logic;
o_data_read : out std_logic;
o_data_write : out std_logic;
o_wait_cmd_busy : out std_logic;
o_last_cmd_was_55 : out std_logic;
o_response_type : out std_logic_vector(2 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_Card_48_bit_Command_Generator 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;
-- Local wires
-- REGISTERED
signal counter : std_logic_vector(6 downto 0);
signal last_command_id : std_logic_vector(5 downto 0);
signal message_bits : std_logic_vector(39 downto 0);
signal last_command_sent_was_CMD55, valid : std_logic;
signal bit_to_send, sending_CRC, command_valid : std_logic;
signal returning_cid_reg, returning_rca_reg, returning_csd_reg, returning_dsr_reg, returning_ocr_reg, returning_status_reg : std_logic;
-- UNREGISTERED
signal temp_4_bits : std_logic_vector(3 downto 0);
signal message_done, CRC_generator_out, produce_next_bit : std_logic;
signal app_specific_valid, regular_command_valid : std_logic;
signal response_type, response_type_reg : std_logic_vector(2 downto 0);
signal cmd_argument : std_logic_vector(31 downto 0);
begin
-- This set of bits is necessary to allow the SD card to accept a VDD level for communication.
temp_4_bits <= "1111" when ((i_OCR(23) = '1') or (i_OCR(22) = '1') or (i_OCR(21) = '1') or (i_OCR(20) = '1')) else "0000";
-- Generate the bits to be sent to the SD card. These bits must pass through the CRC generator
-- to produce error checking code. The error checking code will follow the message. The message terminates with
-- a logic '1'. Total message length is 48 bits.
message_data_generator: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
message_bits <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Store type of a response.
response_type_reg <= response_type;
-- Generate a message. Please note that the predefined messages are used for initialization.
-- If executed in sequence, they will initialize the SD card to work correctly. Only once these
-- instructions are completed can the data transfer begin.
case (i_predefined_message) is
when "0000" =>
-- Generate a predefined message - CMD0.
message_bits <= ("01" & COMMAND_0_GO_IDLE & "00000000000000000000000000000000");
when "0001" =>
-- Generate a predefined message - CMD55.
message_bits <= ("01" & COMMAND_55_APP_CMD & "0000000000000000" & "0000000000000000");
when "0010" =>
-- Generate a predefined message - ACMD41.
message_bits <= ("01" & ACOMMAND_41_SEND_OP_CONDITION & "0000" & temp_4_bits & "000" & i_OCR(20) & "00000000000000000000");
when "0011" =>
-- Generate a predefined message - CMD2.
message_bits <= ("01" & COMMAND_2_ALL_SEND_CID & "00000000000000000000000000000000");
when "0100" =>
-- Generate a predefined message - CMD3.
message_bits <= ("01" & COMMAND_3_SEND_RCA & "00000000000000000000000000000000");
when "0101" =>
-- Generate a predefined message - CMD9.
message_bits <= ("01" & COMMAND_9_SEND_CSD & i_RCA & "0000000000000000");
when "0110" =>
-- Generate a predefined message - CMD4.
message_bits <= ("01" & COMMAND_4_SET_DSR & i_DSR & "0000000000000000");
when "0111" =>
-- Generate a predefined message - CMD16. Set block length to 512.
message_bits <= ("01" & COMMAND_16_SET_BLOCK_LENGTH & "0000000000000000" & "0000001000000000" );
when "1000" =>
-- Generate a predefined message - CMD7. Select the card so we can access it's data.
message_bits <= ("01" & COMMAND_7_SELECT_CARD & i_RCA & "0000001000000000" );
when "1001" =>
-- Generate a predefined message - CMD13. Send SD card status.
message_bits <= ("01" & COMMAND_13_SEND_STATUS & i_RCA & "0000000000000000");
when others =>
-- Generate a custom message
message_bits <= ("01" & i_command_ID & cmd_argument);
end case;
else
-- Shift bits out as needed
if (produce_next_bit = '1') then
-- Shift message bits.
message_bits(39 downto 1) <= message_bits(38 downto 0);
message_bits(0) <= '0';
end if;
end if;
end if;
end if;
end process;
-- Generate command argument based on the command_ID. For most commands, the argument is user specified.
-- For some commands, it is necessary to send a particular SD Card register contents. Hence, these contents are
-- sent instead of the user data.
argument_generator: process (i_command_ID, last_command_sent_was_CMD55, i_generate, i_RCA, i_DSR, i_OCR, i_argument)
begin
cmd_argument <= i_argument;
if (i_generate = '1') then
case (i_command_ID) is
when COMMAND_4_SET_DSR =>
cmd_argument <= i_DSR & i_argument(15 downto 0);
when COMMAND_7_SELECT_CARD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_9_SEND_CSD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_10_SEND_CID =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_13_SEND_STATUS =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_15_GO_INACTIVE =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when COMMAND_55_APP_CMD =>
cmd_argument <= i_RCA & i_argument(15 downto 0);
when ACOMMAND_41_SEND_OP_CONDITION =>
if (last_command_sent_was_CMD55 = '1') then
cmd_argument <= i_OCR;
end if;
when others =>
cmd_argument <= i_argument;
end case;
end if;
end process;
-- Validate the message ID before sending it out.
command_validator: process(i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
command_valid <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
if (("0" & i_predefined_message) >= ("0" & FIRST_NON_PREDEFINED_COMMAND)) then
-- Check the custom message
if (last_command_sent_was_CMD55 = '1') then
-- Check the application specific messages
command_valid <= app_specific_valid;
else
-- Check the default messages.
command_valid <= regular_command_valid;
end if;
else
-- A command is valid if the message is predefined.
command_valid <= '1';
end if;
end if;
end if;
end if;
end process;
-- Registers that indicate that the command sent will return contents of a control register.
-- The contents of the response should therefore be stored in the appropriate register.
responses_with_control_regs: process(i_clock, i_reset_n, last_command_sent_was_CMD55, last_command_id, message_done)
begin
if (i_reset_n = '0') then
returning_ocr_reg <= '0';
returning_cid_reg <= '0';
returning_rca_reg <= '0';
returning_csd_reg <= '0';
returning_status_reg <= '0';
elsif (rising_edge(i_clock)) then
if (i_generate = '1') then
returning_ocr_reg <= '0';
returning_cid_reg <= '0';
returning_rca_reg <= '0';
returning_csd_reg <= '0';
returning_status_reg <= '0';
elsif (message_done = '1') then
-- OCR
if ((last_command_sent_was_CMD55 = '1') and (last_command_id = ACOMMAND_41_SEND_OP_CONDITION)) then
returning_ocr_reg <= '1';
end if;
-- CID
if (last_command_id = COMMAND_2_ALL_SEND_CID) then
returning_cid_reg <= '1';
end if;
-- RCA
if (last_command_id = COMMAND_3_SEND_RCA) then
returning_rca_reg <= '1';
end if;
-- CSD
if (last_command_id = COMMAND_9_SEND_CSD) then
returning_csd_reg <= '1';
end if;
-- Status
if ((last_command_sent_was_CMD55 = '0') and (last_command_id = COMMAND_13_SEND_STATUS)) then
returning_status_reg <= '1';
end if;
end if;
end if;
end process;
-- Count the number of bits sent using a counter.
sent_bit_counter: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter)
begin
if (i_reset_n = '0') then
counter <= (OTHERS => '0');
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Reset the counter indicating the number of bits produced.
counter <= "0000000";
else
if (produce_next_bit = '1') then
-- Update the number of message bits sent.
counter <= counter + '1';
end if;
end if;
end if;
end if;
end process;
-- Select the source for the output data to be either the message data or the CRC bits.
source_selector: process(i_clock, i_reset_n, i_generate)
begin
if (i_reset_n = '0') then
sending_CRC <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
-- Set sending CRC flag to 0.
sending_CRC <= '0';
else
-- If this is the last bit being sent, then bits that follow are the CRC bits.
if (counter = "0101000") then
sending_CRC <= '1';
end if;
end if;
end if;
end if;
end process;
-- When the message is sent, store its ID. In a special case when CMD55 is sent, the next command can be an application
-- specific command. We need to check those command IDs to verify the validity of the message.
CMD55_recognizer: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter, message_done, last_command_id)
begin
if (i_reset_n = '0') then
last_command_sent_was_CMD55 <= '0';
else
if (rising_edge(i_clock)) then
if (i_generate = '0') then
-- Store the ID of the current command.
if (produce_next_bit = '1') then
if (counter = "0000000") then
last_command_id <= message_bits(37 downto 32);
end if;
end if;
-- When message has been sent then check if it was CMD55.
if (message_done = '1') then
if (last_command_id = COMMAND_55_APP_CMD) then
last_command_sent_was_CMD55 <= '1';
else
last_command_sent_was_CMD55 <= '0';
end if;
end if;
end if;
end if;
end if;
end process;
-- Instantiate a CRC7 generator. Message bits will pass through it to create the CRC code for the message.
CRC7_Gen: Altera_UP_SD_CRC7_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_enable => i_message_bit_out,
i_shift => sending_CRC,
i_datain => message_bits(39),
o_dataout => CRC_generator_out
);
-- Define the source of the data produced by this module, depending on the counter value and the sending_CRC register state.
data_bit_register: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter)
begin
if (i_reset_n = '0') then
bit_to_send <= '1';
else
if (rising_edge(i_clock)) then
if (i_generate = '1') then
bit_to_send <= '1';
elsif (produce_next_bit = '1') then
-- Send data to output.
if (sending_CRC = '0') then
-- Send message bits
bit_to_send <= message_bits(39);
else
-- Send CRC bits
if ((counter = "0101111") or (counter = "0110000")) then
-- At the end of CRC bits put a 1.
bit_to_send <= '1';
else
bit_to_send <= CRC_generator_out;
end if;
end if;
end if;
end if;
end if;
end process;
-- Define conditions to produce the next message bit on the module output port o_dataout.
produce_next_bit <= i_message_bit_out and (not message_done);
-- Message is done when the last bit appears at the output.
message_done <= '1' when (counter = "0110001") else '0';
-- Check the application specific messages
app_specific_valid <= '1' when (
--(i_command_ID = COMMAND_0_GO_IDLE) or
(i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_3_SEND_RCA) or
(i_command_ID = COMMAND_4_SET_DSR) or
--(i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or
--(i_command_ID = COMMAND_7_SELECT_CARD) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID) or
--(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
(i_command_ID = ACOMMAND_13_SD_STATUS) or
--(i_command_ID = COMMAND_15_GO_INACTIVE) or
--(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
(i_command_ID = COMMAND_17_READ_BLOCK) or
--(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
(i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or
(i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_27_PROGRAM_CSD) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = ACOMMAND_41_SEND_OP_CONDITION) or
(i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or
(i_command_ID = ACOMMAND_51_SEND_SCR) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD)
)
else '0';
-- Check the default messages.
regular_command_valid <= '1' when (
-------------------------------------------------------
-- Disabled to prevent malfunction of the core
-------------------------------------------------------
--(i_command_ID = COMMAND_0_GO_IDLE) or
--(i_command_ID = COMMAND_6_SWITCH_FUNCTION) or
--(i_command_ID = COMMAND_7_SELECT_CARD) or
--(i_command_ID = COMMAND_15_GO_INACTIVE) or
--(i_command_ID = COMMAND_27_PROGRAM_CSD) or
--(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
--(i_command_ID = COMMAND_42_LOCK_UNLOCK) or
-------------------------------------------------------
(i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_3_SEND_RCA) or
(i_command_ID = COMMAND_4_SET_DSR) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID) or
(i_command_ID = COMMAND_13_SEND_STATUS) or
-------------------------------------------------------
-- Disabled to simplify the circuit
-------------------------------------------------------
--(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
--(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
--(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
--(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
-------------------------------------------------------
(i_command_ID = COMMAND_17_READ_BLOCK) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD)
)
else '0';
response_type <= "001" when -- Wait for type 1 response when
(
(i_predefined_message = "0001") or
(i_predefined_message = "0111") or
(i_predefined_message = "1000") or
(i_predefined_message = "1001") or
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and
((i_command_ID = COMMAND_6_SWITCH_FUNCTION) or
(i_command_ID = COMMAND_7_SELECT_CARD) or
(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or
(i_command_ID = COMMAND_13_SEND_STATUS) or
(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or
(i_command_ID = COMMAND_17_READ_BLOCK) or
(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_24_WRITE_BLOCK) or
(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or
(i_command_ID = COMMAND_27_PROGRAM_CSD) or
(i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or
(i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or
(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or
(i_command_ID = COMMAND_32_ERASE_BLOCK_START) or
(i_command_ID = COMMAND_33_ERASE_BLOCK_END) or
(i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or
(i_command_ID = COMMAND_42_LOCK_UNLOCK) or
(i_command_ID = COMMAND_55_APP_CMD) or
(i_command_ID = COMMAND_56_GEN_CMD) or
((last_command_sent_was_CMD55 = '1') and
((i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or
(i_command_ID = ACOMMAND_13_SD_STATUS) or
(i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or
(i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or
(i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or
(i_command_ID = ACOMMAND_51_SEND_SCR)))))
) else
"010" when -- Wait for type 2 response when
(
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and
((i_command_ID = COMMAND_2_ALL_SEND_CID) or
(i_command_ID = COMMAND_9_SEND_CSD) or
(i_command_ID = COMMAND_10_SEND_CID))) or
(i_predefined_message = "0011") or
(i_predefined_message = "0101")
) else
"011" when -- Wait for type 3 response when
(
((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (last_command_sent_was_CMD55 = '1') and (i_command_ID = ACOMMAND_41_SEND_OP_CONDITION)) or
(i_predefined_message = "0010")
) else
"110" when -- Wait for type 6 response when
(((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (i_command_ID = COMMAND_3_SEND_RCA)) or
(i_predefined_message = "0100"))
else "000"; -- Otherwise there is no response pending.
-- Define circuit outputs
o_message_done <= message_done;
o_response_type <= response_type_reg;
o_valid <= command_valid;
o_dataout <= bit_to_send;
o_returning_ocr <= returning_ocr_reg;
o_returning_cid <= returning_cid_reg;
o_returning_rca <= returning_rca_reg;
o_returning_csd <= returning_csd_reg;
o_returning_status <= returning_status_reg;
o_data_read <= '1' when (last_command_id = COMMAND_17_READ_BLOCK) else '0';
o_data_write <= '1' when (last_command_id = COMMAND_24_WRITE_BLOCK) else '0';
o_last_cmd_was_55 <= last_command_sent_was_CMD55;
o_wait_cmd_busy <= '1' when (
(last_command_id = COMMAND_7_SELECT_CARD) or
(last_command_id = COMMAND_12_STOP_TRANSMISSION) or
(last_command_id = COMMAND_28_SET_WRITE_PROTECT) or
(last_command_id = COMMAND_29_CLEAR_WRITE_PROTECT) or
(last_command_id = COMMAND_38_ERASE_SELECTED_GROUPS))
else '0';
end rtl;