ossc/ip/altera_up_sd_card_avalon_in.../hdl/Altera_UP_SD_Card_Interface...

519 lines
20 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 is an interface to the Secure Data Card. This module is intended to be
-- used with the DE2 board.
--
-- This version of the interface supports only a 1-bit serial data transfer. This
-- allows the interface to support a MultiMedia card as well.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Altera_UP_SD_Card_Interface is
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- Command interface
b_SD_cmd : inout std_logic;
b_SD_dat : inout std_logic;
b_SD_dat3 : inout std_logic;
i_command_ID : in std_logic_vector(5 downto 0);
i_argument : in std_logic_vector(31 downto 0);
i_user_command_ready : in std_logic;
o_SD_clock : out std_logic;
o_card_connected : out std_logic;
o_command_completed : out std_logic;
o_command_valid : out std_logic;
o_command_timed_out : out std_logic;
o_command_crc_failed : out std_logic;
-- Buffer access
i_buffer_enable : in std_logic;
i_buffer_address : in std_logic_vector(7 downto 0);
i_buffer_write : in std_logic;
i_buffer_data_in : in std_logic_vector(15 downto 0);
o_buffer_data_out : out std_logic_vector(15 downto 0);
-- Show SD Card registers as outputs
o_SD_REG_card_identification_number : out std_logic_vector(127 downto 0);
o_SD_REG_relative_card_address : out std_logic_vector(15 downto 0);
o_SD_REG_operating_conditions_register : out std_logic_vector(31 downto 0);
o_SD_REG_card_specific_data : out std_logic_vector(127 downto 0);
o_SD_REG_status_register : out std_logic_vector(31 downto 0);
o_SD_REG_response_R1 : out std_logic_vector(31 downto 0);
o_SD_REG_status_register_valid : out std_logic
);
end entity;
architecture rtl of Altera_UP_SD_Card_Interface is
component Altera_UP_SD_Card_Clock
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_enable : in std_logic;
i_mode : in std_logic; -- 0 for card identification mode, 1 for data transfer mode.
o_SD_clock : out std_logic;
o_clock_mode : out std_logic;
o_trigger_receive : out std_logic;
o_trigger_send : out std_logic
);
end component;
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;
component Altera_UP_SD_CRC16_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(15 downto 0)
);
end component;
component Altera_UP_SD_Signal_Trigger
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
i_signal : in std_logic;
o_trigger : out std_logic
);
end component;
component Altera_UP_SD_Card_48_bit_Command_Generator
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 component;
component Altera_UP_SD_Card_Response_Receiver
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 component;
component Altera_UP_SD_Card_Control_FSM
generic (
PREDEFINED_COMMAND_GET_STATUS : STD_LOGIC_VECTOR(3 downto 0) := "1001"
);
port
(
-- Clock and Reset signals
i_clock : in STD_LOGIC;
i_reset_n : in STD_LOGIC;
-- FSM Inputs
i_user_command_ready : in std_logic;
i_response_received : in STD_LOGIC;
i_response_timed_out : in STD_LOGIC;
i_response_crc_passed : in STD_LOGIC;
i_command_sent : in STD_LOGIC;
i_powerup_busy_n : in STD_LOGIC;
i_clocking_pulse_enable : in std_logic;
i_current_clock_mode : in std_logic;
i_user_message_valid : in std_logic;
i_last_cmd_was_55 : in std_logic;
i_allow_partial_rw : in std_logic;
-- FSM Outputs
o_generate_command : out STD_LOGIC;
o_predefined_command_ID : out STD_LOGIC_VECTOR(3 downto 0);
o_receive_response : out STD_LOGIC;
o_drive_CMD_line : out STD_LOGIC;
o_SD_clock_mode : out STD_LOGIC; -- 0 means slow clock for card identification, 1 means fast clock for transfer mode.
o_resetting : out std_logic;
o_card_connected : out STD_LOGIC;
o_command_completed : out std_logic;
o_clear_response_register : out std_logic;
o_enable_clock_generator : out std_logic
);
end component;
component Altera_UP_SD_Card_Buffer
generic (
TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111";
BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- 1 bit port to transmit and receive data on the data line.
i_begin : in std_logic;
i_sd_clock_pulse_trigger : in std_logic;
i_transmit : in std_logic;
i_1bit_data_in : in std_logic;
o_1bit_data_out : out std_logic;
o_operation_complete : out std_logic;
o_crc_passed : out std_logic;
o_timed_out : out std_logic;
o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it.
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port : in std_logic;
i_address_16bit_port : in std_logic_vector(7 downto 0);
i_write_16bit : in std_logic;
i_16bit_data_in : in std_logic_vector(15 downto 0);
o_16bit_data_out : out std_logic_vector(15 downto 0)
);
end component;
-- Local wires
-- REGISTERED
signal sd_mode : std_logic;
-- SD Card Registers:
signal SD_REG_card_identification_number : std_logic_vector(127 downto 0);
signal SD_REG_response_R1 : std_logic_vector(31 downto 0);
signal SD_REG_relative_card_address : std_logic_vector(15 downto 0);
signal SD_REG_driver_stage_register : std_logic_vector(15 downto 0);
signal SD_REG_card_specific_data : std_logic_vector(127 downto 0);
signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0);
signal SD_REG_status_register : std_logic_vector(31 downto 0);
signal SD_REG_status_register_valid : std_logic;
-- UNREGISTERED
signal data_from_buffer : std_logic_vector(15 downto 0);
signal clock_generator_mode, enable_generator, SD_clock, create_message : std_logic;
signal send_next_bit, receive_next_bit : std_logic;
signal timed_out, response_done, passed_crc, begin_reading_response, resetting : std_logic;
signal returning_cid, returning_rca, returning_csd, returning_ocr : std_logic;
signal response_type : std_logic_vector(2 downto 0);
signal message_valid, messange_sent, data_to_CMD_line, CMD_tristate_buffer_enable, message_sent : std_logic;
signal predef_message_ID : std_logic_vector(3 downto 0);
signal receive_data_out : std_logic_vector(127 downto 0);
signal data_line_done, data_line_crc, data_line_timeout, data_line_direction, data_line_out : std_logic;
signal data_read, data_write, wait_cmd_busy, clear_response_register : std_logic;
signal response_done_combined : std_logic;
signal timeout_combined : std_logic;
signal crc_combined, allow_partial_rw : std_logic;
signal begin_data_line_operations, last_cmd_was_55, message_sent_trigger, returning_status : std_logic;
signal data_line_sd_clock_pulse_trigger : std_logic;
begin
-- Glue logic
SD_REG_driver_stage_register <= (OTHERS => '0');
response_done_combined <= (response_done and (not data_read) and (not data_write)) or
(response_done and (data_read or data_write) and data_line_done);
timeout_combined <= (timed_out and (not data_read) and (not data_write)) or
(timed_out and (data_read or data_write) and data_line_timeout);
crc_combined <= (passed_crc and (not data_read) and (not data_write)) or
(passed_crc and (data_read or data_write) and data_line_crc);
begin_data_line_operations <= (data_read and message_sent) or (data_write and response_done);
-- Partial read and write are only allowed when both bit 79 (partial read allowed) is high and
-- bit 21 (partial write allowed) is high.
allow_partial_rw <= SD_REG_card_specific_data(79) and SD_REG_card_specific_data(21);
-- SD Card control registers
control_regs: process (i_clock, i_reset_n)
begin
if (i_reset_n = '0') then
SD_REG_operating_conditions_register <= (OTHERS => '0');
SD_REG_card_identification_number <= (OTHERS => '0');
SD_REG_relative_card_address <= (OTHERS => '0');
SD_REG_card_specific_data <= (OTHERS => '0');
SD_REG_status_register <= (OTHERS => '0');
SD_REG_response_R1 <= (OTHERS => '1');
SD_REG_status_register_valid <= '0';
elsif (rising_edge(i_clock)) then
if ((response_type = "001") and (response_done = '1') and (returning_status = '0') and (clear_response_register = '0')) then
SD_REG_response_R1 <= receive_data_out(31 downto 0);
elsif (clear_response_register = '1') then
SD_REG_response_R1 <= (OTHERS => '1');
end if;
if (resetting = '1') then
SD_REG_operating_conditions_register <= (OTHERS => '0');
elsif ((returning_ocr = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_operating_conditions_register <= receive_data_out(31 downto 0);
end if;
if ((returning_cid = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_card_identification_number <= receive_data_out;
end if;
if ((returning_rca = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_relative_card_address <= receive_data_out(31 downto 16);
end if;
if ((returning_csd = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_card_specific_data <= receive_data_out;
end if;
if (message_sent_trigger = '1') then
SD_REG_status_register_valid <= '0';
elsif ((returning_status = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then
SD_REG_status_register <= receive_data_out(31 downto 0);
SD_REG_status_register_valid <= '1';
end if;
end if;
end process;
-- Instantiated components
command_generator: Altera_UP_SD_Card_48_bit_Command_Generator PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_message_bit_out => send_next_bit,
i_command_ID => i_command_ID,
i_argument => i_argument,
i_predefined_message => predef_message_ID,
i_generate => create_message,
i_DSR => SD_REG_driver_stage_register,
i_OCR => SD_REG_operating_conditions_register,
i_RCA => SD_REG_relative_card_address,
o_dataout => data_to_CMD_line,
o_message_done => message_sent,
o_valid => message_valid,
o_returning_ocr => returning_ocr,
o_returning_cid => returning_cid,
o_returning_rca => returning_rca,
o_returning_csd => returning_csd,
o_returning_status => returning_status,
o_data_read => data_read,
o_data_write => data_write,
o_wait_cmd_busy => wait_cmd_busy,
o_last_cmd_was_55 => last_cmd_was_55,
o_response_type => response_type
);
response_receiver: Altera_UP_SD_Card_Response_Receiver PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_begin => begin_reading_response,
i_scan_pulse => receive_next_bit,
i_datain => b_SD_cmd,
i_response_type => response_type,
i_wait_cmd_busy => wait_cmd_busy,
o_data => receive_data_out,
o_CRC_passed => passed_crc,
o_timeout => timed_out,
o_done => response_done
);
control_FSM: Altera_UP_SD_Card_Control_FSM PORT MAP
(
-- Clock and Reset signals
i_clock => i_clock,
i_reset_n => i_reset_n,
-- FSM Inputs
i_user_command_ready => i_user_command_ready,
i_clocking_pulse_enable => receive_next_bit,
i_response_received => response_done_combined,
i_response_timed_out => timeout_combined,
i_response_crc_passed => crc_combined,
i_command_sent => message_sent,
i_powerup_busy_n => SD_REG_operating_conditions_register(31),
i_current_clock_mode => clock_generator_mode,
i_user_message_valid => message_valid,
i_last_cmd_was_55 => last_cmd_was_55,
i_allow_partial_rw => allow_partial_rw,
-- FSM Outputs
o_generate_command => create_message,
o_predefined_command_ID => predef_message_ID,
o_receive_response => begin_reading_response,
o_drive_CMD_line => CMD_tristate_buffer_enable,
o_SD_clock_mode => sd_mode, -- 0 means slow clock for card identification, 1 means fast clock for transfer mode.
o_card_connected => o_card_connected,
o_command_completed => o_command_completed,
o_resetting => resetting,
o_clear_response_register => clear_response_register,
o_enable_clock_generator => enable_generator
);
clock_generator: Altera_UP_SD_Card_Clock PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_mode => sd_mode,
i_enable => enable_generator,
o_SD_clock => SD_clock,
o_clock_mode => clock_generator_mode,
o_trigger_receive => receive_next_bit,
o_trigger_send => send_next_bit
);
SD_clock_pulse_trigger: Altera_UP_SD_Signal_Trigger PORT MAP
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_signal => message_sent,
o_trigger => message_sent_trigger
);
data_line: Altera_UP_SD_Card_Buffer
port map
(
i_clock => i_clock,
i_reset_n => i_reset_n,
-- 1 bit port to transmit and receive data on the data line.
i_begin => begin_data_line_operations,
i_sd_clock_pulse_trigger => data_line_sd_clock_pulse_trigger,
i_transmit => data_write,
i_1bit_data_in => b_SD_dat,
o_1bit_data_out => data_line_out,
o_operation_complete => data_line_done,
o_crc_passed => data_line_crc,
o_timed_out => data_line_timeout,
o_dat_direction => data_line_direction,
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port => i_buffer_enable,
i_address_16bit_port => i_buffer_address,
i_write_16bit => i_buffer_write,
i_16bit_data_in => i_buffer_data_in,
o_16bit_data_out => data_from_buffer
);
data_line_sd_clock_pulse_trigger <= (data_write and send_next_bit) or ((not data_write) and receive_next_bit);
-- Buffer output registers.
buff_regs: process(i_clock, i_reset_n, data_from_buffer)
begin
if (i_reset_n = '0') then
o_buffer_data_out <= (OTHERS=> '0');
elsif (rising_edge(i_clock)) then
o_buffer_data_out <= data_from_buffer;
end if;
end process;
-- Circuit outputs.
o_command_valid <= message_valid;
o_command_timed_out <= timeout_combined;
o_command_crc_failed <= not crc_combined;
o_SD_clock <= SD_clock;
b_SD_cmd <= data_to_CMD_line when (CMD_tristate_buffer_enable = '1') else 'Z';
b_SD_dat <= data_line_out when (data_line_direction = '1') else 'Z';
b_SD_dat3 <= 'Z'; -- Set SD card to SD mode.
-- SD card registers
o_SD_REG_card_identification_number <= SD_REG_card_identification_number;
o_SD_REG_relative_card_address <= SD_REG_relative_card_address;
o_SD_REG_operating_conditions_register <= SD_REG_operating_conditions_register;
o_SD_REG_card_specific_data <= SD_REG_card_specific_data;
o_SD_REG_status_register <= SD_REG_status_register;
o_SD_REG_response_R1 <= SD_REG_response_R1;
o_SD_REG_status_register_valid <= SD_REG_status_register_valid;
end rtl;