diff --git a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl deleted file mode 100644 index c772941..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl +++ /dev/null @@ -1,159 +0,0 @@ -# (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. - - -# TCL File Generated by Component Editor 8.0 -# Mon Dec 22 17:22:07 EST 2008 -# DO NOT MODIFY - -set aup_version 15.1 - - - -# +----------------------------------- -# | -# | Altera_UP_SD_Card_Avalon_Interface "Altera_UP_SD_Card_Avalon_Interface" v1.0 -# | null 2008.12.22.17:22:07 -# | A module that allows communication with an SD Card -# | -# | ./hdl/Altera_UP_SD_Card_Avalon_Interface.vhd syn -# | ./hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd syn -# | ./hdl/Altera_UP_SD_Card_Buffer.vhd syn -# | ./hdl/Altera_UP_SD_Card_Clock.vhd syn -# | ./hdl/Altera_UP_SD_Card_Control_FSM.vhd syn -# | ./hdl/Altera_UP_SD_Card_Interface.vhd syn -# | ./hdl/Altera_UP_SD_Card_Memory_Block.qip syn -# | ./hdl/Altera_UP_SD_Card_Response_Receiver.vhd syn -# | ./hdl/Altera_UP_SD_CRC16_Generator.vhd syn -# | ./hdl/Altera_UP_SD_CRC7_Generator.vhd syn -# | ./hdl/Altera_UP_SD_Signal_Trigger.vhd syn -# | -# +----------------------------------- - - -# +----------------------------------- -# | module Altera_UP_SD_Card_Avalon_Interface -# | -set_module_property DESCRIPTION "A module that allows communication with an SD Card" -set_module_property NAME Altera_UP_SD_Card_Avalon_Interface_mod -set_module_property VERSION $aup_version -set_module_property GROUP "Memory" -set_module_property DISPLAY_NAME "SD Card Interface" -set_module_property DATASHEET_URL "[pwd]/doc/SD_Card_Interface_for_SoPC_Builder.pdf" -set_module_property LIBRARIES {ieee.std_logic_1164.all ieee.std_logic_arith.all ieee.std_logic_unsigned.all std.standard.all} -set_module_property TOP_LEVEL_HDL_FILE "hdl/Altera_UP_SD_Card_Avalon_Interface.vhd" -set_module_property TOP_LEVEL_HDL_MODULE Altera_UP_SD_Card_Avalon_Interface -set_module_property INSTANTIATE_IN_SYSTEM_MODULE true -set_module_property EDITABLE false -#set_module_property ANALYZE_HDL false -set_module_property SIMULATION_MODEL_IN_VERILOG false -set_module_property SIMULATION_MODEL_IN_VHDL false -set_module_property SIMULATION_MODEL_HAS_TULIPS false -set_module_property SIMULATION_MODEL_IS_OBFUSCATED false -# | -# +----------------------------------- - -# +----------------------------------- -# | files -# | -add_file hdl/Altera_UP_SD_Card_Avalon_Interface.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Buffer.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Clock.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Control_FSM.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Interface.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Response_Receiver.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_CRC16_Generator.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_CRC7_Generator.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Signal_Trigger.vhd {SYNTHESIS} -add_file hdl/Altera_UP_SD_Card_Memory_Block.vhd {SYNTHESIS} -# | -# +----------------------------------- - -# +----------------------------------- -# | parameters -# | -# | -# +----------------------------------- - -# +----------------------------------- -# | connection point avalon_sdcard_slave -# | -add_interface avalon_sdcard_slave avalon end -set_interface_property avalon_sdcard_slave holdTime 0 -set_interface_property avalon_sdcard_slave linewrapBursts false -set_interface_property avalon_sdcard_slave minimumUninterruptedRunLength 1 -set_interface_property avalon_sdcard_slave bridgesToMaster "" -set_interface_property avalon_sdcard_slave isMemoryDevice false -set_interface_property avalon_sdcard_slave burstOnBurstBoundariesOnly false -set_interface_property avalon_sdcard_slave addressSpan 1024 -set_interface_property avalon_sdcard_slave timingUnits Cycles -set_interface_property avalon_sdcard_slave setupTime 0 -set_interface_property avalon_sdcard_slave writeWaitTime 0 -set_interface_property avalon_sdcard_slave isNonVolatileStorage false -set_interface_property avalon_sdcard_slave addressAlignment DYNAMIC -set_interface_property avalon_sdcard_slave maximumPendingReadTransactions 0 -set_interface_property avalon_sdcard_slave readWaitTime 1 -set_interface_property avalon_sdcard_slave readLatency 0 -set_interface_property avalon_sdcard_slave printableDevice false - -set_interface_property avalon_sdcard_slave associatedClock clk -set_interface_property avalon_sdcard_slave associatedReset reset - -add_interface_port avalon_sdcard_slave i_avalon_chip_select chipselect Input 1 -add_interface_port avalon_sdcard_slave i_avalon_address address Input 8 -add_interface_port avalon_sdcard_slave i_avalon_read read Input 1 -add_interface_port avalon_sdcard_slave i_avalon_write write Input 1 -add_interface_port avalon_sdcard_slave i_avalon_byteenable byteenable Input 4 -add_interface_port avalon_sdcard_slave i_avalon_writedata writedata Input 32 -add_interface_port avalon_sdcard_slave o_avalon_readdata readdata Output 32 -add_interface_port avalon_sdcard_slave o_avalon_waitrequest waitrequest Output 1 -# | -# +----------------------------------- - -# +----------------------------------- -# | connection point clk -# | -add_interface clk clock end -set_interface_property clk enabled true - -add_interface_port clk i_clock clk Input 1 -# | -# +----------------------------------- - -# +----------------------------------- -# | connection point reset -# | -add_interface reset reset end -set_interface_property reset associatedClock clk -set_interface_property reset enabled true -set_interface_property reset synchronousEdges DEASSERT - -add_interface_port reset i_reset_n reset_n Input 1 -# | -# +----------------------------------- - -# +----------------------------------- -# | connection point conduit_end -# | -add_interface conduit_end conduit end - -add_interface_port conduit_end b_SD_cmd export Bidir 1 -add_interface_port conduit_end b_SD_dat export Bidir 1 -add_interface_port conduit_end b_SD_dat3 export Bidir 1 -add_interface_port conduit_end o_SD_clock export Output 1 -# | -# +----------------------------------- - -## Add documentation links for user guide and/or release notes -add_documentation_link "User Guide" file:///ip/altera/university_program/memory/altera_up_sd_card_avalon_interface/doc/SD_Card_Interface_for_SoPC_Builder.pdf -add_documentation_link "Release Notes" https://documentation.altera.com/#/link/hco1421698042087/hco1421698013408 diff --git a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl deleted file mode 100644 index 9cc0821..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl +++ /dev/null @@ -1,56 +0,0 @@ -# (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. - - -# TCL File Generated by Altera University Program -# DO NOT MODIFY - -set aup_version 15.1 - -# Create a new driver - this name must be different than the -# hardware component name -create_driver Altera_UP_SD_Card_Avalon_Interface_mod_driver - -# Associate it with some hardware -set_sw_property hw_class_name Altera_UP_SD_Card_Avalon_Interface_mod - -# The version of this driver -set_sw_property version $aup_version - -# This driver is proclaimed to be compatible with 'component' -# as old as version "1.0". The component hardware version is set in the -# _hw.tcl file - If the hardware component version number is not equal -# or greater than the min_compatable_hw_version number, the driver -# source files will not be copied over to the BSP driver directory -set_sw_property min_compatible_hw_version 15.1 - -# Initialize the driver in alt_sys_init() -set_sw_property auto_initialize true - -# Location in generated BSP that sources will be copied into -set_sw_property bsp_subdirectory drivers - -# -# Source file listings... -# - -# C/C++ source files -add_sw_property c_source HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c - -# Include files -add_sw_property include_source HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h - -# This driver supports HAL type -add_sw_property supported_bsp_type HAL - -# End of file - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h b/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h deleted file mode 100644 index 4e1dbef..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ -#define __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#define SD_RAW_IFACE - -/* - * Device structure definition. Each instance of the driver uses one - * of these structures to hold its associated state. - */ -typedef struct alt_up_sd_card_dev { - /// @brief character mode device structure - /// @sa Developing Device Drivers for the HAL in Nios II Software Developer's Handbook - alt_dev dev; - /// @brief the base address of the device - unsigned int base; - -} alt_up_sd_card_dev; - -#ifndef bool - typedef enum e_bool { false = 0, true = 1 } bool; -#endif - -////////////////////////////////////////////////////////////////////////// -// HAL system functions - -alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char *name); -/* Open an SD Card Interface if it is connected to the system. */ - - -bool alt_up_sd_card_is_Present(void); -/* Check if there is an SD Card insterted into the SD Card socket. - */ - -#ifndef SD_RAW_IFACE -bool alt_up_sd_card_is_FAT16(void); -/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 - * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. - */ - - -short int alt_up_sd_card_fopen(char *name, bool create); -/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 - * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. - * - * Inputs: - * name - a file name including a directory, relative to the root directory - * create - a flag set to true to create a file if it does not already exist - * Output: - * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. - */ - - -short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name); -/* This function sets up a search algorithm to go through a given directory looking for files. - * If the search directory is valid, then the function searches for the first file it finds. - * Inputs: - * directory_to_search_through - name of the directory to search through - * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). - * Outputs: - * 0 - success - * 1 - invalid directory - * 2 - No card or incorrect card format. - * - * To specify a directory give the name in a format consistent with the following regular expression: - * [{[valid_chars]+}/]*. - * - * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. - * Then, append a '.' to the directory name. Examples: - * "." - look through the root directory - * "first/." - look through a directory named "first" that is located in the root directory. - * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. - * Invalid examples include: - * "/.", "/////." - this is not the root directory. - * "/first/." - the first character may not be a '/'. - */ - - - -short int alt_up_sd_card_find_next(char *file_name); -/* This function searches for the next file in a given directory, as specified by the find_first function. - * Inputs: - * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). - * Outputs: - * -1 - end of directory. - * 0 - success - * 2 - No card or incorrect card format. - * 4 - find_first has not been called successfully. - */ - -void alt_up_sd_card_set_attributes(short int file_handle, short int attributes); -/* Set file attributes as needed. - */ - -short int alt_up_sd_card_get_attributes(short int file_handle); -/* Return file attributes, or -1 if the file_handle is invalid. - */ - - -short int alt_up_sd_card_read(short int file_handle); -/* Read a single character from the given file. Return -1 if at the end of a file. Any other negative number - * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ - - -bool alt_up_sd_card_write(short int file_handle, char byte_of_data); -/* Write a single character to a given file. Return true if successful, and false otherwise. */ - - -bool alt_up_sd_card_fclose(short int file_handle); -// This function closes an opened file and saves data to SD Card if necessary. - -#else -bool Write_Sector_Data(int sector_index, int partition_offset); -bool Save_Modified_Sector(); -bool Read_Sector_Data(int sector_index, int partition_offset); -#endif //SD_RAW_IFACE - -////////////////////////////////////////////////////////////////////////// -// file-like operation functions - -////////////////////////////////////////////////////////////////////////// -// direct operation functions - - -/* - * Macros used by alt_sys_init - */ -#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INSTANCE(name, device) \ - static alt_up_sd_card_dev device = \ - { \ - { \ - ALT_LLIST_ENTRY, \ - name##_NAME, \ - NULL , /* open */ \ - NULL , /* close */ \ - NULL, /* read */ \ - NULL, /* write */ \ - NULL , /* lseek */ \ - NULL , /* fstat */ \ - NULL , /* ioctl */ \ - }, \ - name##_BASE, \ - } - -#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INIT(name, device) \ -{ \ - alt_dev_reg(&device.dev); \ -} - - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ */ - - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c b/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c deleted file mode 100644 index b98e077..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c +++ /dev/null @@ -1,1908 +0,0 @@ -/****************************************************************************** -* * -* License Agreement * -* * -* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * -* All rights reserved. * -* * -* Permission is hereby granted, free of charge, to any person obtaining a * -* copy of this software and associated documentation files (the "Software"), * -* to deal in the Software without restriction, including without limitation * -* the rights to use, copy, modify, merge, publish, distribute, sublicense, * -* and/or sell copies of the Software, and to permit persons to whom the * -* Software is furnished to do so, subject to the following conditions: * -* * -* The above copyright notice and this permission notice shall be included in * -* all copies or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * -* DEALINGS IN THE SOFTWARE. * -* * -* This agreement shall be governed in all respects by the laws of the State * -* of California and by the laws of the United States of America. * -* * -******************************************************************************/ - -#include -#include -#include -#include -#include -#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" - -/////////////////////////////////////////////////////////////////////////// -// Local Define Statements -/////////////////////////////////////////////////////////////////////////// - -#define CHAR_TO_UPPER(ch) ((char) (((ch >= 'a') && (ch <= 'z')) ? ((ch-'a')+'A'): ch)) - -// Data Buffer Address -#define SD_CARD_BUFFER(base, x) (base + x) -// 128-bit Card Identification Number -#define SD_CARD_CID(base, x) (base + 0x0200 + x) -// 128-bit Card Specific Data Register -#define SD_CARD_CSD(base, x) (base + 0x0210 + x) -// 32-bit Operating Conditions Register -#define SD_CARD_OCR(base) (base + 0x0220) -// 32-bit Card Status Register -#define SD_CARD_STATUS(base) (base + 0x0224) -// 16-bit Relative Card Address Register -#define SD_CARD_RCA(base) (base + 0x0228) -// 32-bit Card Argument Register -#define SD_CARD_ARGUMENT(base) (base + 0x022C) -// 16-bit Card Command Register -#define SD_CARD_COMMAND(base) (base + 0x0230) -// 16-bit Card Auxiliary Status Register -#define SD_CARD_AUX_STATUS(base) (base + 0x0234) -// 32-bit R1 Response Register -#define SD_CARD_R1_RESPONSE(base) (base + 0x0238) - -#define CMD_READ_BLOCK 17 -#define CMD_WRITE_BLOCK 24 - -// FAT 12/16 related stuff -//#define BOOT_SECTOR_DATA_SIZE 0x005A -#define MAX_FILES_OPENED 2 - -/******************************************************************************/ -/****** LOCAL DATA STRUCTURES ***********************************************/ -/******************************************************************************/ - - -typedef struct s_FAT_12_16_boot_sector { - unsigned char jump_instruction[3]; - char OEM_name[8]; - unsigned short int sector_size_in_bytes; - unsigned char sectors_per_cluster; - unsigned short int reserved_sectors; - unsigned char number_of_FATs; - unsigned short int max_number_of_dir_entires; - unsigned short int number_of_sectors_in_partition; - unsigned char media_descriptor; - unsigned short int number_of_sectors_per_table; - unsigned short int number_of_sectors_per_track; - unsigned short int number_of_heads; - unsigned int number_of_hidden_sectors; - unsigned int total_sector_count_if_above_32MB; - unsigned char drive_number; - unsigned char current_head; - unsigned char boot_signature; - unsigned char volume_id[4]; - char volume_label[11]; - unsigned char file_system_type[8]; - unsigned char bits_for_cluster_index; - unsigned int first_fat_sector_offset; - unsigned int second_fat_sector_offset; - unsigned int root_directory_sector_offset; - unsigned int data_sector_offset; -} t_FAT_12_16_boot_sector; - - -typedef struct s_file_record { - unsigned char name[8]; - unsigned char extension[3]; - unsigned char attributes; - unsigned short int create_time; - unsigned short int create_date; - unsigned short int last_access_date; - unsigned short int last_modified_time; - unsigned short int last_modified_date; - unsigned short int start_cluster_index; - unsigned int file_size_in_bytes; - /* The following fields are only used when a file has been created or opened. */ - unsigned int current_cluster_index; - unsigned int current_sector_in_cluster; - unsigned int current_byte_position; - // Absolute location of the file record on the SD Card. - unsigned int file_record_cluster; - unsigned int file_record_sector_in_cluster; - short int file_record_offset; - // Is this record in use and has the file been modified. - unsigned int home_directory_cluster; - bool modified; - bool in_use; -} t_file_record; - - -typedef struct s_find_data { - unsigned int directory_root_cluster; // 0 means root directory. - unsigned int current_cluster_index; - unsigned int current_sector_in_cluster; - short int file_index_in_sector; - bool valid; -} t_find_data; - - -/////////////////////////////////////////////////////////////////////////// -// Local Variables -/////////////////////////////////////////////////////////////////////////// - - -bool initialized = false; -bool is_sd_card_formated_as_FAT16 = false; -volatile short int *aux_status_register = NULL; -volatile int *status_register = NULL; -volatile short int *CSD_register_w0 = NULL; -volatile short int *command_register = NULL; -volatile int *command_argument_register = NULL; -volatile char *buffer_memory = NULL; -int fat_partition_offset_in_512_byte_sectors = 0; -int fat_partition_size_in_512_byte_sectors = 0; - -#ifndef SD_RAW_IFACE -t_FAT_12_16_boot_sector boot_sector_data; -#endif - -alt_up_sd_card_dev *device_pointer = NULL; - -#ifndef SD_RAW_IFACE -// Pointers to currently opened files. -t_file_record active_files[MAX_FILES_OPENED]; -#endif -bool current_sector_modified = false; -unsigned int current_sector_index = 0; - -#ifndef SD_RAW_IFACE -t_find_data search_data; -#endif - - -/////////////////////////////////////////////////////////////////////////// -// Local Functions -/////////////////////////////////////////////////////////////////////////// - -#ifndef SD_RAW_IFACE -static bool Write_Sector_Data(int sector_index, int partition_offset) -#else -bool Write_Sector_Data(int sector_index, int partition_offset) -#endif -// This function writes a sector at the specified address on the SD Card. -{ - bool result = false; - - if (alt_up_sd_card_is_Present()) - { - short int reg_state = 0xff; - - /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, - * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ - IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); - IOWR_16DIRECT(command_register, 0, CMD_WRITE_BLOCK); - do { - reg_state = (short int) IORD_16DIRECT(aux_status_register,0); - } while ((reg_state & 0x04)!=0); - // Make sure the request did not time out. - if ((reg_state & 0x10) == 0) - { - result = true; - current_sector_modified = false; - current_sector_index = sector_index+partition_offset; - } - } - return result; -} - -#ifndef SD_RAW_IFACE -static bool Save_Modified_Sector() -#else -bool Save_Modified_Sector() -#endif -// If the sector has been modified, then save it to the SD Card. -{ - bool result = true; - if (current_sector_modified) - { - result = Write_Sector_Data(current_sector_index, 0); - } - return result; -} - -#ifndef SD_RAW_IFACE -static bool Read_Sector_Data(int sector_index, int partition_offset) -#else -bool Read_Sector_Data(int sector_index, int partition_offset) -#endif -// This function reads a sector at the specified address on the SD Card. -{ - bool result = false; - - if (alt_up_sd_card_is_Present()) - { - short int reg_state = 0xff; - - /* Write data to the SD card if the current buffer is out of date. */ - if (current_sector_modified) - { - if (Write_Sector_Data(current_sector_index, 0) == false) - { - return false; - } - } - /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, - * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ - IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); - IOWR_16DIRECT(command_register, 0, CMD_READ_BLOCK); - do { - reg_state = (short int) IORD_16DIRECT(aux_status_register,0); - } while ((reg_state & 0x04)!=0); - // Make sure the request did not time out. - if ((reg_state & 0x10) == 0) - { - result = true; - current_sector_modified = false; - current_sector_index = sector_index+partition_offset; - } - } - return result; -} - -#ifndef SD_RAW_IFACE -static bool get_cluster_flag(unsigned int cluster_index, unsigned short int *flag) -// Read a cluster flag. -{ - unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; - - sector_index = sector_index + boot_sector_data.first_fat_sector_offset; - - if (sector_index != current_sector_index) - { - if (Read_Sector_Data(sector_index, 0) == false) - { - return false; - } - } - *flag = (unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256)); - return true; -} - - -static bool mark_cluster(unsigned int cluster_index, short int flag, bool first_fat) -// Place a marker on the specified cluster in a given FAT. -{ - unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; - - if (first_fat) - { - sector_index = sector_index + boot_sector_data.first_fat_sector_offset; - } - else - { - sector_index = sector_index + boot_sector_data.second_fat_sector_offset; - } - - if (sector_index != current_sector_index) - { - if (Read_Sector_Data(sector_index, 0) == false) - { - return false; - } - } - IOWR_16DIRECT(device_pointer->base, 2*(cluster_index % 256), flag); - current_sector_modified = true; - return true; -} - - -static bool Check_for_Master_Boot_Record(void) -// This function reads the first 512 bytes on the SD Card. This data should -// contain the Master Boot Record. If it does, then print -// relevant information and return true. Otherwise, return false. -{ - bool result = false; - int index; - int end, offset, partition_size; - - /* Load the first 512 bytes of data from SD card. */ - if (Read_Sector_Data(0, 0)) - { - end = (short int) IORD_16DIRECT(device_pointer->base,0x1fe); - - // Check if the end of the sector contains an end string 0xaa55. - if ((end & 0x0000ffff) == 0x0000aa55) - { - // Check four partition entries and see if any are valid - for (index = 0; index < 4; index++) - { - int partition_data_offset = (index * 16) + 0x01be; - char type; - - // Read Partition type - type = (unsigned char) IORD_8DIRECT(device_pointer->base,partition_data_offset + 0x04); - - // Check if this is an FAT parition - if ((type == 1) || (type == 4) || (type == 6) || (type == 14)) - { - // Get partition offset and size. - offset = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0A)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x08)); - partition_size = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0E)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0C)); - - // Check if the partition is valid - if (partition_size > 0) - { - result = true; - fat_partition_size_in_512_byte_sectors = partition_size; - fat_partition_offset_in_512_byte_sectors = offset; - break; - } - } - } - } - } - - return result; -} - - -static bool Read_File_Record_At_Offset(int offset, t_file_record *record, unsigned int cluster_index, unsigned int sector_in_cluster) -// This function reads a file record -{ - bool result = false; - if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - int counter; - - for (counter = 0; counter < 8; counter++) - { - record->name[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter); - } - for (counter = 0; counter < 3; counter++) - { - record->extension[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter+8); - } - record->attributes = (char) IORD_8DIRECT(device_pointer->base, offset+11); - /* Ignore reserved bytes at locations 12 and 13. */ - record->create_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+14); - record->create_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+16); - record->last_access_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+18); - /* Ignore reserved bytes at locations 20 and 21. */ - record->last_modified_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+22); - record->last_modified_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+24); - record->start_cluster_index = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+26); - record->file_size_in_bytes = (unsigned int) IORD_32DIRECT(device_pointer->base, offset+28); - record->file_record_cluster = cluster_index; - record->file_record_sector_in_cluster = sector_in_cluster; - record->file_record_offset = offset; - result = true; - } - return result; -} - - -static bool Write_File_Record_At_Offset(int offset, t_file_record *record) -// This function writes a file record at a given offset. The offset is given in bytes. -{ - bool result = false; - if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - int counter; - - for (counter = 0; counter < 8; counter=counter+2) - { - short int two_chars = (short int) record->name[counter+1]; - two_chars = two_chars << 8; - two_chars = two_chars | record->name[counter]; - IOWR_16DIRECT(device_pointer->base, offset+counter, two_chars); - } - for (counter = 0; counter < 3; counter++) - { - IOWR_8DIRECT(device_pointer->base, offset+counter+8, record->extension[counter]); - } - IOWR_8DIRECT(device_pointer->base, offset+11, record->attributes); - /* Ignore reserved bytes at locations 12 and 13. */ - IOWR_16DIRECT(device_pointer->base, offset+14, record->create_time); - IOWR_16DIRECT(device_pointer->base, offset+16, record->create_date); - IOWR_16DIRECT(device_pointer->base, offset+18, record->last_access_date); - /* Ignore reserved bytes at locations 20 and 21. */ - IOWR_16DIRECT(device_pointer->base, offset+22, record->last_modified_time); - IOWR_16DIRECT(device_pointer->base, offset+24, record->last_modified_date); - IOWR_16DIRECT(device_pointer->base, offset+26, record->start_cluster_index); - IOWR_32DIRECT(device_pointer->base, offset+28, record->file_size_in_bytes); - current_sector_modified = true; - result = true; - } - return result; -} - - -static bool Check_for_DOS_FAT(int FAT_partition_start_sector) -// This function reads the boot sector for the FAT file system on the SD Card. -// The offset_address should point to the sector on the card where the boot sector is located. -// The sector number is specified either in the master Boot Record, or is 0 by default for a purely FAT -// based file system. If the specified sector contains a FAT boot sector, then this function prints the -// relevant information and returns 1. Otherwise, it returns 0. -{ - bool result = false; - int counter = 0; - short int end; - - result = Read_Sector_Data(0, FAT_partition_start_sector); - end = (short int) IORD_16DIRECT(device_pointer->base, 0x1fe); - if (((end & 0x0000ffff) == 0x0000aa55) && (result)) - { - int num_clusters = 0; - - boot_sector_data.jump_instruction[0] = (char) IORD_8DIRECT(device_pointer->base, 0); - boot_sector_data.jump_instruction[1] = (char) IORD_8DIRECT(device_pointer->base, 1); - boot_sector_data.jump_instruction[2] = (char) IORD_8DIRECT(device_pointer->base, 2); - for (counter = 0; counter < 8; counter++) - { - boot_sector_data.OEM_name[counter] = (char) IORD_8DIRECT(device_pointer->base, 3+counter); - } - boot_sector_data.sector_size_in_bytes = (((unsigned char) IORD_8DIRECT(device_pointer->base, 12)) << 8 ) | ((char) IORD_8DIRECT(device_pointer->base, 11)); - boot_sector_data.sectors_per_cluster = ((unsigned char) IORD_8DIRECT(device_pointer->base, 13)); - boot_sector_data.reserved_sectors = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 14)); - boot_sector_data.number_of_FATs = ((unsigned char) IORD_8DIRECT(device_pointer->base, 16)); - boot_sector_data.max_number_of_dir_entires = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 18)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 17)); - boot_sector_data.number_of_sectors_in_partition = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 20)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 19)); - boot_sector_data.media_descriptor = ((unsigned char) IORD_8DIRECT(device_pointer->base, 21)); - boot_sector_data.number_of_sectors_per_table = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 22)); - boot_sector_data.number_of_sectors_per_track = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 24)); - boot_sector_data.number_of_heads = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 26)); - boot_sector_data.number_of_hidden_sectors = ((unsigned int) IORD_32DIRECT(device_pointer->base, 28)); - boot_sector_data.total_sector_count_if_above_32MB = ((unsigned int) IORD_32DIRECT(device_pointer->base, 32)); - boot_sector_data.drive_number = ((unsigned char) IORD_8DIRECT(device_pointer->base, 36)); - boot_sector_data.current_head = ((unsigned char) IORD_8DIRECT(device_pointer->base, 37)); - boot_sector_data.boot_signature = ((unsigned char) IORD_8DIRECT(device_pointer->base, 38)); - boot_sector_data.first_fat_sector_offset = boot_sector_data.reserved_sectors; - boot_sector_data.second_fat_sector_offset = boot_sector_data.first_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; - boot_sector_data.root_directory_sector_offset = boot_sector_data.second_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; - boot_sector_data.data_sector_offset = boot_sector_data.root_directory_sector_offset + (32*boot_sector_data.max_number_of_dir_entires / boot_sector_data.sector_size_in_bytes); - - if (boot_sector_data.number_of_sectors_in_partition > 0) - { - num_clusters = (boot_sector_data.number_of_sectors_in_partition / boot_sector_data.sectors_per_cluster); - } - else - { - num_clusters = (boot_sector_data.total_sector_count_if_above_32MB / boot_sector_data.sectors_per_cluster); - } - if (num_clusters < 4087) - { - boot_sector_data.bits_for_cluster_index = 12; - } - else if (num_clusters <= 65517) - { - boot_sector_data.bits_for_cluster_index = 16; - } - else - { - boot_sector_data.bits_for_cluster_index = 32; - } - - for (counter = 0; counter < 4; counter++) - { - boot_sector_data.volume_id[counter] = ((char) IORD_8DIRECT(device_pointer->base, 39+counter)); - } - for (counter = 0; counter < 11; counter++) - { - boot_sector_data.volume_label[counter] = ((char) IORD_8DIRECT(device_pointer->base, 43+counter)); - } - for (counter = 0; counter < 8; counter++) - { - boot_sector_data.file_system_type[counter] = ((char) IORD_8DIRECT(device_pointer->base, 54+counter)); - } - // Clear file records - for (counter = 0; counter < MAX_FILES_OPENED; counter++) - { - active_files[counter].in_use = false; - } - result = true; - } - else - { - result = false; - } - return result; -} - - -static bool Look_for_FAT16(void) -// Read the SD card to determine if it contains a FAT16 partition. -{ - bool result = false; - - if (alt_up_sd_card_is_Present()) - { - short int csd_file_format = *CSD_register_w0; - - fat_partition_offset_in_512_byte_sectors = 0; - fat_partition_size_in_512_byte_sectors = 0; - - if (((csd_file_format & 0x8000) == 0) && ((csd_file_format & 0x0c00) != 0x0c00)) - { - if ((csd_file_format & 0x0c00) == 0x0400) - { - /* SD Card contains files stored in a DOS FAT (floppy like) file format, without a partition table */ - result = Check_for_DOS_FAT(0); - } - if ((csd_file_format & 0x0c00) == 0x0000) - { - /* SD Card contains files stored in a Hard disk-like file format that contains a partition table */ - if (Check_for_Master_Boot_Record()) - { - result = Check_for_DOS_FAT(fat_partition_offset_in_512_byte_sectors); - } - } - if (result == true) - { - // Accept only FAT16, not FAT12. - if (boot_sector_data.bits_for_cluster_index != 16) - { - result = false; - } - else - { - fat_partition_size_in_512_byte_sectors = boot_sector_data.number_of_sectors_in_partition; - } - } - } - } - return result; -} - - -static void filename_to_upper_case(char *file_name) -// Change file name to upper case. -{ - int index; - int length = strlen(file_name); - - for (index = 0; index < length; index++) - { - if ((file_name[index] >= 'a') && (file_name[index] <= 'z')) - { - file_name[index] = (file_name[index] - 'a') + 'A'; - } - } -} - - -static bool check_file_name_for_FAT16_compliance(char *file_name) -// Check if the file complies with FAT16 naming convention. -{ - int length = strlen(file_name); - int index; - int last_dir_break_position = -1; - int last_period = -1; - bool result = true; - - for(index = 0; index < length; index++) - { - if ((file_name[index] == ' ') || - ((last_dir_break_position == (index - 1)) && ((file_name[index] == '\\') || (file_name[index] == '/'))) || - ((index - last_period == 9) && (file_name[index] != '.')) || - ((last_dir_break_position != last_period) && (index - last_period > 3) && - (file_name[index] != '\\') && (file_name[index] != '/')) - ) - { - result = false; - break; - } - if ((file_name[index] == '\\') || (file_name[index] == '/')) - { - last_period = index; - last_dir_break_position = index; - } - if (file_name[index] == '.') - { - last_period = index; - } - } - if ((file_name[length-1] == '\\') || (file_name[length-1] == '/')) - { - result = false; - } - return result; -} - - -static int get_dir_divider_location(char *name) -// Find a directory divider location. -{ - int index = 0; - int length = strlen(name); - - for(index = 0; index < length; index++) - { - if ((name[index] == '\\') || (name[index] == '/')) - { - break; - } - } - - if (index == length) - { - index = -1; - } - - return index; -} - - -static bool match_file_record_to_name_ext(t_file_record *file_record, char *name, char *extension) -/* See if the given name and extension match the file record. Return true if this is so, false otherwise. */ -{ - bool match = true; - int index; - - for (index = 0; index < 8; index++) - { - if (CHAR_TO_UPPER(file_record->name[index]) != CHAR_TO_UPPER(name[index])) - { - match = false; - break; - } - } - for (index = 0; index < 3; index++) - { - if (CHAR_TO_UPPER(file_record->extension[index]) != CHAR_TO_UPPER(extension[index])) - { - match = false; - break; - } - } - return match; -} - - -static bool get_home_directory_cluster_for_file(char *file_name, int *home_directory_cluster, t_file_record *file_record) -// Scan the directories in given in the file name and find the root directory for the file. -{ - bool result = false; - int home_dir_cluster = 0; - int location, index; - int start_location = 0; - - /* Get Next Directory. */ - location = get_dir_divider_location( file_name ); - while (location > 0) - { - char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; - char extension[3] = { ' ', ' ', ' ' }; - int ext_index = -1; - int new_cluster = home_dir_cluster; - - // Get the name of the directory in name/extension format. - for (index = 0; index < location; index++) - { - if (file_name[index+start_location] == '.') - { - ext_index = index; - } - else if (ext_index < 0) - { - name[index] = file_name[index+start_location]; - } - else - { - extension[index-ext_index] = file_name[index+start_location]; - } - } - - if (home_dir_cluster == 0) - { - /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ - int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); - int sector_index; - - for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) - { - if (Read_Sector_Data(sector_index+boot_sector_data.root_directory_sector_offset, fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - - // Read file record. - Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); - if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) - { - bool match = match_file_record_to_name_ext(file_record, name, extension); - if (match) - { - new_cluster = file_record->start_cluster_index; - file_record->file_record_cluster = 1; // Home directory is a subdirectory in the root directory. - break; - } - } - } - } - else - { - break; - } - if (new_cluster != home_dir_cluster) - { - break; - } - } - if (new_cluster != home_dir_cluster) - { - // A valid directory is found, so go to it. - home_dir_cluster = new_cluster; - start_location = start_location+location+1; - } - else - { - // Directory path is invalid. - return false; - } - } else { - // This is a subdirectory that can have any number of elements. So scan through it as though it was a file - // and see if you can find the directory of interest. - int cluster = home_dir_cluster; - - do { - int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; - int sector_index; - - for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) - { - if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - // Read file record. - Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); - if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) - { - bool match = match_file_record_to_name_ext(file_record, name, extension); - if (match) - { - new_cluster = file_record->start_cluster_index; - break; - } - } - } - } - else - { - break; - } - if (new_cluster != home_dir_cluster) - { - break; - } - } - // If this is the end of the cluster and the directory has not been found, then see if there is another cluster - // that holds data for the current directory. - if (new_cluster == home_dir_cluster) - { - unsigned short int next_cluster; - - if (get_cluster_flag(new_cluster, &next_cluster)) - { - // The directory needs to be expanded to store more files. - if ((next_cluster & 0x0000fff8) == 0x0000fff8) - { - return false; - } - new_cluster = (next_cluster & 0x0000fff8); - } - else - { - // Directory path is invalid. - return false; - } - } - } while ((cluster < 0x0000fff8) && (new_cluster == home_dir_cluster)); - if (new_cluster != home_dir_cluster) - { - // A valid directory is found, so go to it. - home_dir_cluster = new_cluster; - start_location = start_location+location+1; - } - else - { - // Directory path is invalid. - return false; - } - } - location = get_dir_divider_location(&(file_name[start_location])); - if (location < 0) - { - // Directory has been located. - result = true; - } - } - - *home_directory_cluster = home_dir_cluster; - if (home_dir_cluster == 0) - { - file_record->file_record_cluster = 0; // Home directory is the root directory. - result = true; - } - return result; -} - - -static bool find_file_in_directory(int directory_start_cluster, char *file_name, t_file_record *file_record) -// Given a cluster and a file name, check if the file already exists. Return the file record if the file is found. -{ - int location = get_dir_divider_location( file_name ); - int last_dir_separator = 0; - char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; - char extension[3] = { ' ', ' ', ' ' }; - int ext_index = -1; - int cluster = directory_start_cluster; - int index; - int length = strlen(file_name); - bool result = false; - - // Skip through all directory separators. - while (location > 0) - { - last_dir_separator = last_dir_separator+location+1; - location = get_dir_divider_location( &(file_name[last_dir_separator]) ); - } - - // Get the name of the file in name/extension format. - for (index = last_dir_separator; index < length; index++) - { - if (file_name[index] == '.') - { - ext_index = index; - } - else if (ext_index < 0) - { - name[index-last_dir_separator] = file_name[index]; - } - else - { - extension[index-ext_index-1] = file_name[index]; - } - } - - // Look for the file. - if (directory_start_cluster == 0) - { - /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ - int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); - int sector_index; - - for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) - { - if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, - fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - // Read file record. - Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); - if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) - { - bool match = match_file_record_to_name_ext(file_record, name, extension); - - if (match) - { - result = true; - break; - } - } - } - } - else - { - break; - } - if (result) - { - break; - } - } - } - else - { - do { - int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; - int sector_index; - - for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) - { - if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - // Read file record. - Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); - if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) - { - bool match = match_file_record_to_name_ext(file_record, name, extension); - - if (match) - { - result = true; - break; - } - } - } - } - else - { - break; - } - if (result) - { - break; - } - } - // If this is the end of the cluster and the file has not been found, then see if there is another cluster - // that holds data for the current directory. - if (result == false) - { - unsigned short int new_cluster; - - if (get_cluster_flag(cluster, &new_cluster)) - { - // The directory needs to be expanded to store more files. - if ((new_cluster & 0x0000fff8) == 0x0000fff8) - { - return false; - } - cluster = (new_cluster & 0x0000fff8); - } - else - { - // Directory path is invalid. - return false; - } - } - } while ((cluster < 0x0000fff8) && (result == false)); - } - - return result; -} - - -static bool find_first_empty_cluster(unsigned int *cluster_number) -// Find the first empty cluster. It will be marked by a 0 entry in the File Allocation Table. -{ - unsigned int sector = boot_sector_data.first_fat_sector_offset; - unsigned int cluster_index = 2; - short int cluster = -1; - bool result = false; - unsigned max_cluster_index = 0; - unsigned int non_data_sectors = boot_sector_data.data_sector_offset; - unsigned int less_than_32 = boot_sector_data.number_of_sectors_in_partition; - unsigned int greater_than_32 = boot_sector_data.total_sector_count_if_above_32MB; - - if (less_than_32 > greater_than_32) - { - max_cluster_index = ((less_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; - } - else - { - max_cluster_index = ((greater_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; - } - // Find an empty cluster for the file. - while (sector != boot_sector_data.second_fat_sector_offset) - { - if (Read_Sector_Data( sector, fat_partition_offset_in_512_byte_sectors)) - { - do { - cluster = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256))); - if (cluster == 0) - { - // Free cluster found. - break; - } - else - { - cluster_index++; - } - } while ((cluster_index % 256) != 0); - } - if (cluster == 0) - { - break; - } - sector++; - } - if ((cluster == 0) && (cluster <= max_cluster_index)) - { - *cluster_number = cluster_index; - result = true; - } - return result; -} - - -static int find_first_empty_record_in_a_subdirectory(int start_cluster_index) -// Search for a free spot in a subdirectory. Return an encoded location for the file record. -{ - int result = -1; - int cluster = start_cluster_index; - do { - int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; - int sector_index; - - for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) - { - if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - unsigned short int leading_char; - - // Read file record. - leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); - if ((leading_char == 0x00e5) || (leading_char == 0)) - { - result = (cluster) | ((sector_index*16 + file_counter) << 16); - return result; - } - } - } - else - { - break; - } - } - // If this is the end of the cluster and the file has not been found, then see if there is another cluster - // that holds data for the current directory. - if (result < 0) - { - unsigned short int new_cluster; - if (get_cluster_flag(cluster, &new_cluster)) - { - // The directory needs to be expanded to store more files. - if ((new_cluster & 0x0000fff8) == 0x0000fff8) - { - unsigned int new_dir_cluster; - if (find_first_empty_cluster(&new_dir_cluster)) - { - // Add the new cluster to the linked list of the given directory. - if (mark_cluster(cluster, ((short int) (new_dir_cluster)), true) && - mark_cluster(new_dir_cluster, ((short int) (0xffff)), true) && - mark_cluster(cluster, ((short int) (new_dir_cluster)), false) && - mark_cluster(new_dir_cluster, ((short int) (0xffff)), false)) - { - Save_Modified_Sector(); - // The new file will begin at the first entry of the directory. - result = new_dir_cluster; - } - } - cluster = (new_cluster & 0x0000fff8); - } - } - else - { - // Error encountered. - result = -1; - } - } - } while ((cluster < 0x0000fff8) && (result == -1)); - return result; -} - - -static int find_first_empty_record_in_root_directory() -// Find a first unused record location to use. Return -1 if none is found. -{ - int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); - int sector_index; - int result = -1; - - for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) - { - if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, - fat_partition_offset_in_512_byte_sectors)) - { - int file_counter; - - for (file_counter = 0; file_counter < 16; file_counter++) - { - unsigned short int leading_char; - - // Read first character of the file record. - leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); - if ((leading_char == 0x00e5) || (leading_char == 0)) - { - result = (sector_index*16 + file_counter) << 16; - return result; - } - } - } - else - { - break; - } - } - return result; -} - -static void convert_filename_to_name_extension(char *filename, char *name, char *extension) -// This function converts the file name into a name . extension format. -{ - int counter; - int local = 0; - - for(counter = 0; counter < 8; counter++) - { - if (filename[local] != '.') - { - name[counter] = filename[local]; - if (filename[local] != 0) local++; - } - else - { - name[counter] = ' '; - } - } - if (filename[local] == '.') local++; - for(counter = 0; counter < 3; counter++) - { - if (filename[local] != 0) - { - extension[counter] = filename[local]; - local++; - } - else - { - extension[counter] = ' '; - } - } - -} - -static bool create_file(char *name, t_file_record *file_record, t_file_record *home_dir) -// Create a file in a given directory. Expand the directory if needed. -{ - unsigned int cluster_number; - bool result = false; - - if (find_first_empty_cluster(&cluster_number)) - { - int record_index; - - if (home_dir->file_record_cluster == 0) - { - // Put a file in the root directory. - record_index = find_first_empty_record_in_root_directory(); - } - else - { - // Put a file in a subdirectory. - record_index = find_first_empty_record_in_a_subdirectory(home_dir->start_cluster_index); - } - if (record_index >= 0) - { - unsigned int file_record_sector; - int location = get_dir_divider_location( name ); - int last_dir_separator = 0; - - // Skip through all directory separators. - while (location > 0) - { - last_dir_separator = last_dir_separator+location+1; - location = get_dir_divider_location( &(name[last_dir_separator]) ); - } - - convert_filename_to_name_extension(&(name[last_dir_separator]), (char *)file_record->name, (char *)file_record->extension); - - file_record->attributes = 0; - file_record->create_time = 0; - file_record->create_date = 0; - file_record->last_access_date = 0; - file_record->last_modified_time = 0; - file_record->last_modified_date = 0; - file_record->start_cluster_index = cluster_number; - file_record->file_size_in_bytes = 0; - file_record->current_cluster_index = cluster_number; - file_record->current_sector_in_cluster = 0; - file_record->current_byte_position = 0; - file_record->file_record_cluster = record_index & 0x0000ffff; - file_record->file_record_sector_in_cluster = ((record_index >> 16) & 0x0000ffff) / 16; - file_record->file_record_offset = (((record_index >> 16) & 0x0000ffff) % 16)*32; - file_record->home_directory_cluster = home_dir->start_cluster_index; - file_record->in_use = true; - file_record->modified = true; - // Now write the record at the specified location. - file_record_sector = (file_record->file_record_cluster == 0) ? - (boot_sector_data.root_directory_sector_offset + file_record->file_record_sector_in_cluster): - (boot_sector_data.data_sector_offset + (file_record->file_record_cluster-2)*boot_sector_data.sectors_per_cluster + - file_record->file_record_sector_in_cluster); - - if (Read_Sector_Data(file_record_sector, fat_partition_offset_in_512_byte_sectors)) - { - if (Write_File_Record_At_Offset(file_record->file_record_offset, file_record)) - { - Save_Modified_Sector(); - // Mark the first cluster of the file as the last cluster at first. - mark_cluster(cluster_number, ((short int) (0xffff)), true); - if (mark_cluster(cluster_number, ((short int) (0xffff)), false)) - { - result = true; - } - } - } - } - - } - return result; -} - - -static void copy_file_record_name_to_string(t_file_record *file_record, char *file_name) -/* Copy a file name from the file record to a given string */ -{ - int index; - int flength = 0; - - /* Copy file name.*/ - for (index = 0; index < 8; index++) - { - if (file_record->name[index] != ' ') - { - file_name[flength] = file_record->name[index]; - flength = flength + 1; - } - } - if (file_record->extension[0] != ' ') - { - file_name[flength] = '.'; - flength = flength + 1; - for (index = 0; index < 3; index++) - { - if (file_record->extension[index] != ' ') - { - file_name[flength] = file_record->extension[index]; - flength = flength + 1; - } - } - } - file_name[flength] = 0; -} -#endif //SD_RAW_IFACE - -/////////////////////////////////////////////////////////////////////////// -// Direct functions -/////////////////////////////////////////////////////////////////////////// - - -alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char* name) -{ - // find the device from the device list - // (see altera_hal/HAL/inc/priv/alt_file.h - // and altera_hal/HAL/src/alt_find_dev.c - // for details) - alt_up_sd_card_dev *dev = (alt_up_sd_card_dev *) alt_find_dev(name, &alt_dev_list); - - if (dev != NULL) - { - aux_status_register = ((short int *) SD_CARD_AUX_STATUS(dev->base)); - status_register = ((int *) SD_CARD_STATUS(dev->base)); - CSD_register_w0 = ((short int *) SD_CARD_CSD(dev->base, 0)); - command_register = ((short int *) SD_CARD_COMMAND(dev->base)); - command_argument_register = ((int *) SD_CARD_ARGUMENT(dev->base)); - buffer_memory = (char *) SD_CARD_BUFFER(dev->base, 0); - device_pointer = dev; - initialized = false; -#ifndef SD_RAW_IFACE - is_sd_card_formated_as_FAT16 = false; - search_data.valid = false; -#endif - } - return dev; -} - - -bool alt_up_sd_card_is_Present(void) -// Check if there is an SD Card insterted into the SD Card socket. -{ - bool result = false; - - if ((device_pointer != NULL) && ((IORD_16DIRECT(aux_status_register,0) & 0x02) != 0)) - { - result = true; - } - else if (initialized == true) - { - int index; - - initialized = false; -#ifndef SD_RAW_IFACE - search_data.valid = false; - is_sd_card_formated_as_FAT16 = false; - - for(index = 0; index < MAX_FILES_OPENED; index++) - { - active_files[index].in_use = false; - active_files[index].modified = false; - } -#endif - } - return result; -} - -#ifndef SD_RAW_IFACE -bool alt_up_sd_card_is_FAT16(void) -/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 - * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. - * If the card contains a FAT16 volume, the local data structures will be initialized to allow reading and writing - * to the SD card as though it was a hard drive. - */ -{ - bool result = false; - - if (alt_up_sd_card_is_Present()) - { - // Check if an SD Card is in the SD Card slot. - if (initialized == false) - { - // Now determine if the card is formatted as FAT 16. - is_sd_card_formated_as_FAT16 = Look_for_FAT16(); - initialized = is_sd_card_formated_as_FAT16; - search_data.valid = false; - } - result = is_sd_card_formated_as_FAT16; - } - else - { - // If not then you may as well not open the device. - initialized = false; - is_sd_card_formated_as_FAT16 = false; - } - - return result; -} - - -short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name) -/* This function sets up a search algorithm to go through a given directory looking for files. - * If the search directory is valid, then the function searches for the first file it finds. - * Inputs: - * directory_to_search_through - name of the directory to search through - * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). - * Outputs: - * 0 - success - * 1 - invalid directory - * 2 - No card or incorrect card format. - * - * To specify a directory give the name in a format consistent with the following regular expression: - * [{[valid_chars]+}/]*. - * - * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. - * Then, append a '.' to the directory name. Examples: - * "." - look through the root directory - * "first/." - look through a directory named "first" that is located in the root directory. - * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. - * Invalid examples include: - * "/.", "/////." - this is not the root directory. - * "/first/." - the first character may not be a '/'. - */ -{ - short int result = 2; - if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - int home_directory_cluster; - t_file_record file_record; - - if (get_home_directory_cluster_for_file(directory_to_search_through, &home_directory_cluster, &file_record)) - { - search_data.directory_root_cluster = home_directory_cluster; - search_data.current_cluster_index = home_directory_cluster; - search_data.current_sector_in_cluster = 0; - search_data.file_index_in_sector = -1; - search_data.valid = true; - result = alt_up_sd_card_find_next(file_name); - } - else - { - result = 1; - } - } - return result; -} - - -short int alt_up_sd_card_find_next(char *file_name) -/* This function searches for the next file in a given directory, as specified by the find_first function. - * Inputs: - * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). - * Outputs: - * -1 - end of directory. - * 0 - success - * 2 - No card or incorrect card format. - * 3 - find_first has not been called successfully. - */ -{ - short int result = 2; - if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - if (search_data.valid) - { - t_file_record file_record; - int cluster = search_data.current_cluster_index; - - if (cluster == 0) - { - // Searching through the root directory - int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); - int sector_index = search_data.current_sector_in_cluster; - int file_counter = search_data.file_index_in_sector+1; - - for (; sector_index < max_root_dir_sectors; sector_index++) - { - if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, - fat_partition_offset_in_512_byte_sectors)) - { - for (; file_counter < 16; file_counter++) - { - if (Read_File_Record_At_Offset(file_counter*32, &file_record, 0, sector_index)) - { - if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) - { - /* Update search structure. */ - search_data.file_index_in_sector = file_counter; - search_data.current_sector_in_cluster = sector_index; - - /* Copy file name.*/ - copy_file_record_name_to_string(&file_record, file_name); - return 0; - } - } - } - file_counter = 0; - } - else - { - break; - } - } - result = -1; - } - else - { - int file_counter = search_data.file_index_in_sector+1; - do - { - int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; - int sector_index = search_data.current_sector_in_cluster; - - for (; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) - { - if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) - { - for (; file_counter < 16; file_counter++) - { - if (Read_File_Record_At_Offset(file_counter*32, &file_record, cluster, sector_index)) - { - if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) - { - /* Update search structure. */ - search_data.current_cluster_index = cluster; - search_data.file_index_in_sector = file_counter; - search_data.current_sector_in_cluster = sector_index; - - /* Copy file name.*/ - copy_file_record_name_to_string(&file_record, file_name); - return 0; - } - } - } - file_counter = 0; - } - else - { - break; - } - } - // If this is the end of the cluster and the file has not been found, then see if there is another cluster - // that holds data for the current directory. - if (sector_index >= boot_sector_data.sectors_per_cluster) - { - unsigned short int new_cluster; - - if (get_cluster_flag(cluster, &new_cluster)) - { - if ((new_cluster & 0x0000fff8) == 0x0000fff8) - { - result = -1; - search_data.valid = false; - } - cluster = ((new_cluster) & 0x0000fff8); - } - else - { - // Error encountered. - result = -1; - } - } - } while (cluster < 0x0000fff8); - } - } - else - { - // Call Find_First first. - result = 3; - } - } - return result; -} - - -short int alt_up_sd_card_fopen(char *name, bool create) -/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 - * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. - * - * Inputs: - * name - a file name including a directory, relative to the root directory - * create - a flag set to true to create a file if it does not already exist - * Output: - * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. - * Return -2 if the specified file has already been opened previously. - */ -{ - short int file_record_index = -1; - - if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - unsigned int home_directory_cluster = 0; - t_file_record home_dir; - - /* First check the file name format. It should not be longer than 12 characters, including a period and the extension. - * Rules: - * - no spaces - * - at most 12 chatacters per name, with a period in 9th position. - * - a / or a \ every at most 12 characters. - */ - filename_to_upper_case(name); - if (check_file_name_for_FAT16_compliance(name)) - { - int index; - - /* Get home directory cluster location for the specified file. 0 means root directory. */ - if (!get_home_directory_cluster_for_file(name, (int *) &home_directory_cluster, &home_dir)) - { - return file_record_index; - } - - /* Find a free file slot to store file specs in. */ - for (index = 0; index < MAX_FILES_OPENED; index++) - { - if (active_files[index].in_use == false) - { - file_record_index = index; - break; - } - } - if (file_record_index >= 0) - { - /* If file record is found, then look for the specified file. If the create flag is set to true - * and the file is not found, then it should be created in the current directory. - */ - - if (find_file_in_directory(home_directory_cluster, name, &(active_files[file_record_index]))) - { - if (create) - { - /* Do not allow overwriting existing files for now. */ - return -1; - } - active_files[file_record_index].current_cluster_index = active_files[file_record_index].start_cluster_index; - active_files[file_record_index].current_sector_in_cluster = 0; - active_files[file_record_index].current_byte_position = 0; - active_files[file_record_index].in_use = true; - active_files[file_record_index].modified = false; - - /* Check if the file has already been opened. */ - for (index = 0; index < MAX_FILES_OPENED; index++) - { - if ((file_record_index != index) && (active_files[index].in_use == true)) - { - if ((active_files[file_record_index].file_record_cluster == active_files[index].file_record_cluster) && - (active_files[file_record_index].file_record_sector_in_cluster == active_files[index].file_record_sector_in_cluster) && - (active_files[file_record_index].file_record_offset == active_files[index].file_record_offset)) - { - // file already in use. - file_record_index = -2; - break; - } - } - } - - } - else if (create) - { - /* Create file if needed. */ - if (create_file(name, &(active_files[file_record_index]), &home_dir)) - { - active_files[file_record_index].in_use = true; - active_files[file_record_index].modified = true; - } - else - { - /* If file creation fails then return an invalid file handle. */ - file_record_index = -1; - } - } - else - { - /* Otherwise the file could not be opened.*/ - file_record_index = -1; - } - } - } - } - - return file_record_index; -} - - -void alt_up_sd_card_set_attributes(short int file_handle, short int attributes) -/* Return file attributes, or -1 if the file_handle is invalid. - */ -{ - if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) - { - if (active_files[file_handle].in_use) - { - active_files[file_handle].attributes = ((char)(attributes & 0x00ff)); - } - } -} - - -short int alt_up_sd_card_get_attributes(short int file_handle) -/* Return file attributes, or -1 if the file_handle is invalid. - */ -{ - short int result = -1; - if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) - { - if (active_files[file_handle].in_use) - { - result = ((active_files[file_handle].attributes) & 0x00ff); - } - } - return result; -} - -short int alt_up_sd_card_read(short int file_handle) -/* Read a single character from a given file. Return -1 if at the end of a file. Any other negative number - * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ -{ - short int ch = -1; - - if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) - { - if (active_files[file_handle].in_use) - { - if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) - { - int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + - active_files[file_handle].current_sector_in_cluster; - - if ((active_files[file_handle].current_byte_position > 0) && ((active_files[file_handle].current_byte_position % 512) == 0)) - { - // Read in a new sector of data. - if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) - { - // Go to the next cluster. - unsigned short int next_cluster; - if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) - { - if ((next_cluster & 0x0000fff8) == 0x0000fff8) - { - /* End of file */ - return -1; - } - else - { - active_files[file_handle].current_cluster_index = next_cluster; - active_files[file_handle].current_sector_in_cluster = 0; - data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + - active_files[file_handle].current_sector_in_cluster; - } - } - else - { - return -2; - } - } - else - { - active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; - data_sector = data_sector + 1; - } - } - // Reading te first byte of the file. - if (current_sector_index != (data_sector + fat_partition_offset_in_512_byte_sectors)) - { - if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) - { - return -2; - } - } - - ch = (unsigned char) IORD_8DIRECT(buffer_memory, (active_files[file_handle].current_byte_position % 512)); - active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; - } - } - } - - return ch; -} - - -bool alt_up_sd_card_write(short int file_handle, char byte_of_data) -/* Write a single character to a given file. Return true if successful, and false otherwise. */ -{ - bool result = false; - - if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) - { - if (active_files[file_handle].in_use) - { - int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + - active_files[file_handle].current_sector_in_cluster; - short int buffer_offset = active_files[file_handle].current_byte_position % boot_sector_data.sector_size_in_bytes; - - if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) - { - if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) - { - // Read in a new sector of data. - if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) - { - // Go to the next cluster. - unsigned short int next_cluster; - if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) - { - if (next_cluster < 0x0000fff8) - { - active_files[file_handle].current_cluster_index = next_cluster; - active_files[file_handle].current_sector_in_cluster = 0; - data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + - active_files[file_handle].current_sector_in_cluster; - } - } - else - { - return false; - } - } - else - { - active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; - data_sector = data_sector + 1; - } - } - } - else - { - /* You are adding data to the end of the file, so increment its size and look for an additional data cluster if needed. */ - if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) - { - if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) - { - /* Find a new cluster if possible. */ - unsigned int cluster_number; - - if (find_first_empty_cluster(&cluster_number)) - { - // mark clusters in both File Allocation Tables. - mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), true); - mark_cluster(cluster_number, 0xffff, true); - mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), false); - mark_cluster(cluster_number, 0xffff, false); - // Change cluster index and sector index to compute a new data sector. - active_files[file_handle].current_cluster_index = cluster_number; - active_files[file_handle].current_sector_in_cluster = 0; - } - else - { - return false; - } - } - else - { - /* Read the next sector in the cluster and modify it. We only need to change the data_sector value. The actual read happens a few lines below. */ - active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_byte_position / boot_sector_data.sector_size_in_bytes; - } - data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + - active_files[file_handle].current_sector_in_cluster; - } - } - // Reading a data sector into the buffer. Note that changes to the most recently modified sector will be saved before - // a new sector is read from the SD Card. - if (current_sector_index != data_sector + fat_partition_offset_in_512_byte_sectors) - { - if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) - { - return false; - } - } - // Write a byte of data to the buffer. - IOWR_8DIRECT(buffer_memory, buffer_offset, byte_of_data); - active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; - - // Modify the file record only when necessary. - if (active_files[file_handle].current_byte_position >= active_files[file_handle].file_size_in_bytes) - { - active_files[file_handle].file_size_in_bytes = active_files[file_handle].file_size_in_bytes + 1; - active_files[file_handle].modified = true; - } - // Invaldiate the buffer to ensure that the buffer contents are written to the SD card whe nthe file is closed. - current_sector_modified = true; - result = true; - } - } - - return result; -} - - -bool alt_up_sd_card_fclose(short int file_handle) -// This function closes an opened file and saves data to SD Card if necessary. -{ - bool result = false; - if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) - { - if (active_files[file_handle].in_use) - { - if (active_files[file_handle].modified) - { - unsigned int record_sector = active_files[file_handle].file_record_sector_in_cluster; - if (active_files[file_handle].file_record_cluster == 0) - { - record_sector = record_sector + boot_sector_data.root_directory_sector_offset; - } - else - { - record_sector = record_sector + boot_sector_data.data_sector_offset + - (active_files[file_handle].file_record_cluster - 2)*boot_sector_data.sectors_per_cluster; - } - if (Read_Sector_Data(record_sector, fat_partition_offset_in_512_byte_sectors)) - { - if (Write_File_Record_At_Offset(active_files[file_handle].file_record_offset, &(active_files[file_handle]))) - { - // Make sure that the Data has been saved to the SD Card. - result = Save_Modified_Sector(); - } - } - } - active_files[file_handle].in_use = false; - result = true; - } - } - - return result; -} - -#endif //SD_RAW_IFACE diff --git a/ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf b/ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf deleted file mode 100644 index 1aa463d..0000000 Binary files a/ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf and /dev/null differ diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC16_Generator.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC16_Generator.vhd deleted file mode 100644 index 55322e9..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC16_Generator.vhd +++ /dev/null @@ -1,79 +0,0 @@ --- (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 generates the necessary 16-CRC for Command and Response --- Implementation: serial input/parallel output --- When input stream ends, the crcout output is the CRC checksum for them --- --- NOTES/REVISIONS: ----------------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity Altera_UP_SD_CRC16_Generator is - - port - ( - i_clock : in std_logic; - i_enable : in std_logic; - i_reset_n : in std_logic; - i_sync_reset : 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 entity; - -architecture rtl of Altera_UP_SD_CRC16_Generator is - - -- Local wires - -- REGISTERED - signal shift_register : std_logic_vector(15 downto 0); -begin - - process (i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - shift_register <= (OTHERS => '0'); - else - if (rising_edge(i_clock)) then - if (i_sync_reset = '1') then - shift_register <= (OTHERS => '0'); - elsif (i_enable = '1') then - if (i_shift = '0') then - shift_register(0) <= i_datain XOR shift_register(15); - shift_register(4 downto 1) <= shift_register(3 downto 0); - shift_register(5) <= shift_register(4) XOR i_datain XOR shift_register(15); - shift_register(11 downto 6) <= shift_register(10 downto 5); - shift_register(12) <= shift_register(11) XOR i_datain XOR shift_register(15); - shift_register(15 downto 13) <= shift_register(14 downto 12); - else -- shift CRC out (no more calculation now) - shift_register(15 downto 1) <= shift_register(14 downto 0); - shift_register(0) <= '0'; - end if; - end if; - end if; - end if; - end process; - - o_dataout <= shift_register(15); - o_crcout <= shift_register; -end rtl; - - - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd deleted file mode 100644 index 3ae9430..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd +++ /dev/null @@ -1,76 +0,0 @@ --- (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 generates the necessary 7-CRC for Command and Response --- Implementation: serial input/parallel output --- --- When input stream ends, the crcout output is the CRC checksum for the input stream. --- --- NOTES/REVISIONS: ---------------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity Altera_UP_SD_CRC7_Generator is - - 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 entity; - -architecture rtl of Altera_UP_SD_CRC7_Generator is - - -- Local wires - -- REGISTERED - signal shift_register : std_logic_vector(6 downto 0); -begin - - process (i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - shift_register <= (OTHERS => '0'); - else - if (rising_edge(i_clock)) then - if (i_enable = '1') then - if (i_shift = '0') then - shift_register(0) <= i_datain XOR shift_register(6); - shift_register(1) <= shift_register(0); - shift_register(2) <= shift_register(1); - shift_register(3) <= shift_register(2) XOR i_datain XOR shift_register(6); - shift_register(4) <= shift_register(3); - shift_register(5) <= shift_register(4); - shift_register(6) <= shift_register(5); - else -- shift CRC out (no more calculation now) - shift_register(0) <= '0'; - shift_register(6 downto 1) <= shift_register(5 downto 0); - end if; - end if; - end if; - end if; - end process; - - o_dataout <= shift_register(6); - o_crcout <= shift_register; -end rtl; - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd deleted file mode 100644 index f9bb3b0..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd +++ /dev/null @@ -1,570 +0,0 @@ --- (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; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd deleted file mode 100644 index 9900419..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd +++ /dev/null @@ -1,518 +0,0 @@ --- (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 is an FSM that allows access to the SD Card IP core via the Avalon Interconnect. --- --- This module takes a range of addresses on the Avalon Interconnect. Specifically: --- - 0x00000000 to 0x000001ff --- word addressable buffer space. The data to be written to the SD card as well --- as data read from the SD card can be accessed here. --- --- - 0x00000200 to 0x0000020f --- 128-bit containing the Card Identification Number. The meaning of each bit is described in the --- SD Card Physical Layer Specification Document. --- --- - 0x00000210 to 0x0000021f --- 128-bit register containing Card Specific Data. The meaning of each bit is described in the --- SD Card Physical Layer Specification Document. --- --- - 0x00000220 to 0x00000223 --- 32-bit register containing Operating Conditions Register. The meaning of each bit is described --- in the SD Card Physical Layer Specification Document. --- --- - 0x00000224 to 0x00000227 --- 32-bit register containing the Status Register. The meaning of each bit is described --- in the SD Card Physical Layer Specification Document. However, if the card is not connected or the --- status register could not be read from the SD card, this register will contain invalid data. In such --- a case, wait for a card to be connected by checking the Auxiliary Status Register (UP Core Specific), and --- a command 13 (SEND_STATUS) to update the contents of this register when possible. If a card is connected then --- the Auxiliary Status Register can be polled until such a time that Status Register is valid, as the SD Card --- interface circuit updates the status register approximately every 0.1 of a second, and after every command --- is executed. --- --- - 0x00000228 to 0x000000229 --- 16-bit register containing the Relative Card Address. This address uniquely identifies a card --- connected to the SD Card slot. --- --- - 0x0000022C to 0x00000022F --- 32-bit register used to set the argument for a command to be sent to the SD Card. --- --- - 0x00000230 to 0x000000231 --- 16-bit register used to send a command to an SD card. Once written, the interface will issue the --- specified command. The meaning of each bit in this register is as follows: --- - 0-5 - command index. This is a command index as per SD Card Physical Layer specification document. --- - 6 - use most recent RCA. If this bit is set, the command argument will be replaced with the contents of --- the Relative Card Address register, followed by 16 0s. For commands that require RCA to be sent as --- an argument, this bit should be set and users will not need to specify RCA themselves. --- - 7-15 - currently unused bits. They will be ignored. --- NOTE: If a specified command is determined to be invalid, or the card is not connected to the SD Card socket, --- then the SD Card interface circuit will not issue the command. --- --- - 0x00000234 to 0x00000235 --- 16-bit register with Auxiliary Status Register. This is the Altera UP SD Card Interface status. The meaning of --- the bits is as follows: --- - 0 - last command valid - Set to '1' if the most recently user issued command was valid. --- - 1 - card connected - Set to '1' if at present an SD card --- - 2 - execution in progress - Set to '1' if the command recently issued is currently being executed. If true, --- then the current state of SD Card registers should be ignored. --- - 3 - status register valid - Set to '1' if the status register is valid. --- - 4 - command timed out - Set to '1' if the last command timed out. --- - 5 - crc failed - Set to '1' if the last command failed a CRC check. --- - 6-15 - unused. --- --- - 0x00000238 to 0x0000023B --- 32-bit register containing the 32-bit R1 response message. Use it to test validity of the response. This register --- will not store the response to SEND_STATUS command. Insteand, read the SD_status register at location 0x00000224. --- --- Date: December 8, 2008 --- NOTES/REVISIONS: --- December 17, 2008 - added R1 response register to the core. It is now available at 0x00000238. ----------------------------------------------------------------------------------------------------------------- - -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_Avalon_Interface is - generic ( - ADDRESS_BUFFER : std_logic_vector(7 downto 0) := "00000000"; - ADDRESS_CID : std_logic_vector(7 downto 0) := "10000000"; - ADDRESS_CSD : std_logic_vector(7 downto 0) := "10000100"; - ADDRESS_OCR : std_logic_vector(7 downto 0) := "10001000"; - ADDRESS_SR : std_logic_vector(7 downto 0) := "10001001"; - ADDRESS_RCA : std_logic_vector(7 downto 0) := "10001010"; - ADDRESS_ARGUMENT : std_logic_vector(7 downto 0) := "10001011"; - ADDRESS_COMMAND : std_logic_vector(7 downto 0) := "10001100"; - ADDRESS_ASR : std_logic_vector(7 downto 0) := "10001101"; - ADDRESS_R1 : std_logic_vector(7 downto 0) := "10001110" - ); - port - ( - -- Clock and Reset signals - i_clock : in STD_LOGIC; - i_reset_n : in STD_LOGIC; -- Asynchronous reset - - -- Avalon Interconnect Signals - i_avalon_address : in STD_LOGIC_VECTOR(7 downto 0); - i_avalon_chip_select : in STD_LOGIC; - i_avalon_read : in STD_LOGIC; - i_avalon_write : in STD_LOGIC; - i_avalon_byteenable : in STD_LOGIC_VECTOR(3 downto 0); - i_avalon_writedata : in STD_LOGIC_VECTOR(31 downto 0); - o_avalon_readdata : out STD_LOGIC_VECTOR(31 downto 0); - o_avalon_waitrequest : out STD_LOGIC; - - -- SD Card interface ports - b_SD_cmd : inout STD_LOGIC; - b_SD_dat : inout STD_LOGIC; - b_SD_dat3 : inout STD_LOGIC; - o_SD_clock : out STD_LOGIC - ); - -end entity; - -architecture rtl of Altera_UP_SD_Card_Avalon_Interface is - - component 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 component; - - -- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state - -- of the switches. - type buffer_state_type is ( s_RESET, s_WAIT_REQUEST, s_READ_FIRST_WORD, s_READ_SECOND_WORD, s_RECEIVE_FIRST_WORD, - s_RECEIVE_SECOND_WORD, s_WR_READ_FIRST_WORD, s_WR_READ_FIRST_WORD_DELAY, s_WRITE_FIRST_BYTE, s_WRITE_FIRST_WORD, - s_WR_READ_SECOND_WORD, s_WR_READ_SECOND_WORD_DELAY, s_WRITE_SECOND_BYTE, s_WRITE_SECOND_WORD, s_WAIT_RELEASE); - type command_state_type is (s_RESET_CMD, s_WAIT_COMMAND, s_WAIT_RESPONSE, s_UPDATE_AUX_SR); - - -- Register to hold the current state - signal current_state : buffer_state_type; - signal next_state : buffer_state_type; - signal current_cmd_state : command_state_type; - signal next_cmd_state : command_state_type; - - ------------------- - -- Local signals - ------------------- - -- REGISTERED - signal auxiliary_status_reg : std_logic_vector(5 downto 0); - signal buffer_data_out_reg : std_logic_vector(31 downto 0); - signal buffer_data_in_reg : std_logic_vector(31 downto 0); - signal buffer_data_out : std_logic_vector(15 downto 0); - signal command_ID_reg : std_logic_vector( 5 downto 0); - signal argument_reg : std_logic_vector(31 downto 0); - signal avalon_address : std_logic_vector(7 downto 0); - signal avalon_byteenable : std_logic_vector(3 downto 0); - -- UNREGISTERED - signal buffer_address : std_logic_vector(7 downto 0); - signal buffer_data_in : std_logic_vector(15 downto 0); - signal SD_REG_card_identification_number : std_logic_vector(127 downto 0); - signal SD_REG_relative_card_address : std_logic_vector(15 downto 0); - signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0); - signal SD_REG_card_specific_data : std_logic_vector(127 downto 0); - signal SD_REG_status_register : std_logic_vector(31 downto 0); - signal SD_REG_response_R1 : std_logic_vector(31 downto 0); - signal command_ready, send_command_ready, - command_valid, command_completed, card_connected : std_logic; - signal status_reg_valid, argument_write : std_logic; - signal read_buffer_request, write_buffer_request, buffer_enable, buffer_write : std_logic; - signal command_timed_out, command_crc_failed : std_logic; - -begin - -- Define state transitions for buffer interface. - state_transitions_buffer: process (current_state, read_buffer_request, write_buffer_request, i_avalon_byteenable, avalon_byteenable) - begin - case current_state is - when s_RESET => - -- Reset local registers. - next_state <= s_WAIT_REQUEST; - - when s_WAIT_REQUEST => - -- Wait for a user command. - if (read_buffer_request = '1') then - next_state <= s_READ_FIRST_WORD; - elsif (write_buffer_request = '1') then - if ((i_avalon_byteenable(1) = '1') and (i_avalon_byteenable(0) = '1')) then - next_state <= s_WRITE_FIRST_WORD; - elsif ((i_avalon_byteenable(3) = '1') and (i_avalon_byteenable(2) = '1')) then - next_state <= s_WRITE_SECOND_WORD; - elsif ((i_avalon_byteenable(1) = '1') or (i_avalon_byteenable(0) = '1')) then - next_state <= s_WR_READ_FIRST_WORD; - elsif ((i_avalon_byteenable(3) = '1') or (i_avalon_byteenable(2) = '1')) then - next_state <= s_WR_READ_SECOND_WORD; - else - next_state <= s_WAIT_REQUEST; - end if; - else - next_state <= s_WAIT_REQUEST; - end if; - - when s_READ_FIRST_WORD => - -- Read first 16-bit word from the buffer - next_state <= s_READ_SECOND_WORD; - - when s_READ_SECOND_WORD => - -- Read second 16-bit word from the buffer - next_state <= s_RECEIVE_FIRST_WORD; - - when s_RECEIVE_FIRST_WORD => - -- Store first word read - next_state <= s_RECEIVE_SECOND_WORD; - - when s_RECEIVE_SECOND_WORD => - -- Store second word read - next_state <= s_WAIT_RELEASE; - - -- The following states control writing to the buffer. To write a single byte it is necessary to read a - -- word and then write it back, changing only on of its bytes. - when s_WR_READ_FIRST_WORD => - -- Read first 16-bit word from the buffer - next_state <= s_WR_READ_FIRST_WORD_DELAY; - - when s_WR_READ_FIRST_WORD_DELAY => - -- Wait a cycle - next_state <= s_WRITE_FIRST_BYTE; - - when s_WRITE_FIRST_BYTE => - -- Write one of the bytes in the given word into the memory. - if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then - next_state <= s_WRITE_SECOND_WORD; - elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then - next_state <= s_WR_READ_SECOND_WORD; - else - next_state <= s_WAIT_RELEASE; - end if; - - when s_WR_READ_SECOND_WORD => - -- Read second 16-bit word from the buffer - next_state <= s_WR_READ_SECOND_WORD_DELAY; - - when s_WR_READ_SECOND_WORD_DELAY => - -- Wait a cycle - next_state <= s_WRITE_SECOND_BYTE; - - when s_WRITE_SECOND_BYTE => - -- Write one of the bytes in the given word into the memory. - next_state <= s_WAIT_RELEASE; - - -- Full word writing can be done without reading the word in the first place. - when s_WRITE_FIRST_WORD => - -- Write the first word into memory - if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then - next_state <= s_WRITE_SECOND_WORD; - elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then - next_state <= s_WR_READ_SECOND_WORD; - else - next_state <= s_WAIT_RELEASE; - end if; - - when s_WRITE_SECOND_WORD => - -- Write the second word into memory - next_state <= s_WAIT_RELEASE; - - when s_WAIT_RELEASE => - -- if ((read_buffer_request = '1') or (write_buffer_request = '1')) then - -- next_state <= s_WAIT_RELEASE; - -- else - next_state <= s_WAIT_REQUEST; - -- end if; - - when others => - -- Make sure to start in the reset state if the circuit powers up in an odd state. - next_state <= s_RESET; - end case; - end process; - - -- State Registers - buffer_state_regs: process(i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - current_state <= s_RESET; - elsif(rising_edge(i_clock)) then - current_state <= next_state; - end if; - end process; - - helper_regs: process(i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - avalon_address <= (OTHERS => '0'); - buffer_data_out_reg <= (OTHERS => '0'); - buffer_data_in_reg <= (OTHERS => '0'); - avalon_byteenable <= (OTHERS => '0'); - elsif(rising_edge(i_clock)) then - if (current_state = s_WAIT_REQUEST) then - avalon_address <= i_avalon_address; - buffer_data_in_reg <= i_avalon_writedata; - avalon_byteenable <= i_avalon_byteenable; - end if; - if (current_state = s_RECEIVE_FIRST_WORD) then - buffer_data_out_reg(15 downto 0) <= buffer_data_out; - end if; - if (current_state = s_RECEIVE_SECOND_WORD) then - buffer_data_out_reg(31 downto 16) <= buffer_data_out; - end if; - end if; - end process; - - -- FSM outputs - o_avalon_waitrequest <= (read_buffer_request or write_buffer_request) when (not (current_state = s_WAIT_RELEASE)) else '0'; - buffer_address(7 downto 1) <= avalon_address(6 downto 0); - buffer_address(0) <= '1' when ( (current_state = s_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_WORD) or - (current_state = s_WR_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else - '0'; - buffer_enable <= '1' when ( (current_state = s_READ_FIRST_WORD) or (current_state = s_WR_READ_FIRST_WORD) or - (current_state = s_READ_SECOND_WORD) or (current_state = s_WR_READ_SECOND_WORD) or - (current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or - (current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else - '0'; - buffer_write <= '1' when ( (current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or - (current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else - '0'; - buffer_data_in <= (buffer_data_out(15 downto 8) & buffer_data_in_reg(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "01")) else - (buffer_data_in_reg(15 downto 8) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "10")) else - (buffer_data_out(15 downto 8) & buffer_data_in_reg(23 downto 16)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "01")) else - (buffer_data_in_reg(31 downto 24) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "10")) else - buffer_data_in_reg(15 downto 0) when (current_state = s_WRITE_FIRST_WORD) else - buffer_data_in_reg(31 downto 16); - -- Glue Logic - read_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_read); - write_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_write); - - -- Define state transitions for command interface. - state_transitions_cmd: process (current_cmd_state, command_completed, command_valid, command_ready) - begin - case current_cmd_state is - when s_RESET_CMD => - -- Reset local registers. - next_cmd_state <= s_WAIT_COMMAND; - - when s_WAIT_COMMAND => - -- Wait for a user command. - if (command_ready = '1') then - next_cmd_state <= s_WAIT_RESPONSE; - else - next_cmd_state <= s_WAIT_COMMAND; - end if; - - when s_WAIT_RESPONSE => - -- Generate a predefined command to the SD card. This is the identification process for the SD card. - if ((command_completed = '1') or (command_valid = '0')) then - next_cmd_state <= s_UPDATE_AUX_SR; - else - next_cmd_state <= s_WAIT_RESPONSE; - end if; - - when s_UPDATE_AUX_SR => - -- Update the Auxiliary status register. - if (command_ready = '1') then - next_cmd_state <= s_UPDATE_AUX_SR; - else - next_cmd_state <= s_WAIT_COMMAND; - end if; - - when others => - -- Make sure to start in the reset state if the circuit powers up in an odd state. - next_cmd_state <= s_RESET_CMD; - end case; - end process; - - -- State registers - cmd_state_regs: process(i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - current_cmd_state <= s_RESET_CMD; - elsif(rising_edge(i_clock)) then - current_cmd_state <= next_cmd_state; - end if; - end process; - - -- FSM outputs - send_command_ready <= '1' when ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) else '0'; - - -- Glue logic - command_ready <= '1' when ( (i_avalon_chip_select = '1') and (i_avalon_write = '1') and - (i_avalon_address = ADDRESS_COMMAND)) else '0'; - argument_write <= '1' when ((i_avalon_chip_select = '1') and (i_avalon_write = '1') and - (i_avalon_address = ADDRESS_ARGUMENT)) else '0'; - -- Local Registers - local_regs: process(i_clock, i_reset_n, current_cmd_state, card_connected, command_valid, i_avalon_writedata, command_completed, command_ready) - begin - if (i_reset_n = '0') then - auxiliary_status_reg <= "000000"; - command_ID_reg <= (OTHERS => '0'); - elsif(rising_edge(i_clock)) then - -- AUX Status Register - if ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) then - auxiliary_status_reg(2) <= not command_completed; - auxiliary_status_reg(4) <= command_timed_out; - auxiliary_status_reg(5) <= command_crc_failed; - end if; - auxiliary_status_reg(0) <= command_valid; - auxiliary_status_reg(1) <= card_connected; - auxiliary_status_reg(3) <= status_reg_valid; - -- Command - if (command_ready = '1') then - command_ID_reg <= i_avalon_writedata(5 downto 0); - end if; - end if; - end process; - - argument_regs_processing: process(i_clock, i_reset_n, current_cmd_state, i_avalon_writedata, command_ready) - begin - if (i_reset_n = '0') then - argument_reg <= (OTHERS => '0'); - elsif(rising_edge(i_clock)) then - -- Argument register - if ((command_ready = '1') and ( i_avalon_writedata(6) = '1')) then - argument_reg <= SD_REG_relative_card_address & "0000000000000000"; - elsif (argument_write = '1') then - argument_reg <= i_avalon_writedata; - end if; - end if; - end process; - - o_avalon_readdata <= buffer_data_out_reg when (not (current_state = s_WAIT_REQUEST)) else - SD_REG_card_identification_number(31 downto 0) when (i_avalon_address = ADDRESS_CID) else - SD_REG_card_identification_number(63 downto 32) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "01") else - SD_REG_card_identification_number(95 downto 64) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "10") else - SD_REG_card_identification_number(127 downto 96) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "11") else - SD_REG_card_specific_data(31 downto 0) when (i_avalon_address = ADDRESS_CSD) else - SD_REG_card_specific_data(63 downto 32) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "01") else - SD_REG_card_specific_data(95 downto 64) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "10") else - SD_REG_card_specific_data(127 downto 96) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "11") else - SD_REG_operating_conditions_register when (i_avalon_address = ADDRESS_OCR) else - SD_REG_status_register when (i_avalon_address = ADDRESS_SR) else - ("0000000000000000" & SD_REG_relative_card_address)when (i_avalon_address = ADDRESS_RCA) else - argument_reg when (i_avalon_address = ADDRESS_ARGUMENT) else - ("00000000000000000000000000" & command_ID_reg) when (i_avalon_address = ADDRESS_COMMAND) else - SD_REG_response_R1 when (i_avalon_address = ADDRESS_R1) else - ("00000000000000000000000000" & auxiliary_status_reg); - - -- Instantiated Components - SD_Card_Port: Altera_UP_SD_Card_Interface - port map - ( - i_clock => i_clock, - i_reset_n => i_reset_n, - - -- Command interface - b_SD_cmd => b_SD_cmd, - b_SD_dat => b_SD_dat, - b_SD_dat3 => b_SD_dat3, - i_command_ID => command_ID_reg, - i_argument => argument_reg, - i_user_command_ready => send_command_ready, - - o_SD_clock => o_SD_clock, - o_card_connected => card_connected, - o_command_completed => command_completed, - o_command_valid => command_valid, - o_command_timed_out => command_timed_out, - o_command_crc_failed => command_crc_failed, - - -- Buffer access - i_buffer_enable => buffer_enable, - i_buffer_address => buffer_address, - i_buffer_write => buffer_write, - i_buffer_data_in => buffer_data_in, - o_buffer_data_out => buffer_data_out, - - -- Show SD Card registers as outputs - 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 => status_reg_valid - ); - -end rtl; - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd deleted file mode 100644 index 3cdb04f..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd +++ /dev/null @@ -1,382 +0,0 @@ --- (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 a dual port memory block. It has a 16-bit port and a 1-bit port. --- The 1-bit port is used to either send or receive data, while the 16-bit port is used --- by Avalon interconnet to store and retrieve data. --- --- 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_Buffer is - 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 entity; - -architecture rtl of Altera_UP_SD_Card_Buffer is - - component Altera_UP_SD_CRC16_Generator - port - ( - i_clock : in std_logic; - i_enable : in std_logic; - i_reset_n : in std_logic; - i_sync_reset : 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_Card_Memory_Block - PORT - ( - address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); - address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); - clock_a : IN STD_LOGIC ; - clock_b : IN STD_LOGIC ; - data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); - data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0); - enable_a : IN STD_LOGIC := '1'; - enable_b : IN STD_LOGIC := '1'; - wren_a : IN STD_LOGIC := '1'; - wren_b : IN STD_LOGIC := '1'; - q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); - q_b : OUT STD_LOGIC_VECTOR (0 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_RESET, s_WAIT_REQUEST, s_SEND_START_BIT, s_SEND_DATA, s_SEND_CRC, s_SEND_STOP, s_WAIT_BUSY, s_WAIT_BUSY_END, - s_WAIT_DATA_START, s_RECEIVING_LEADING_BITS, s_RECEIVING_DATA, s_RECEIVING_STOP_BIT, s_WAIT_DEASSERT); - - -- Register to hold the current state - signal current_state : state_type; - signal next_state : state_type; - -- Local wires - -- REGISTERED - signal crc_counter : std_logic_vector(3 downto 0); - signal local_mode : std_logic; - signal dataout_1bit : std_logic; - signal bit_counter : std_logic_vector(2 downto 0); - signal byte_counter : std_logic_vector(8 downto 0); - signal shift_register : std_logic_vector(16 downto 0); - signal timeout_register : std_logic_vector(15 downto 0); - signal data_in_reg : std_logic; - -- UNREGISTERED - signal crc_out : std_logic_vector(15 downto 0); - signal single_bit_conversion, single_bit_out : std_logic_vector( 0 downto 0); - signal packet_mem_addr_b : std_logic_vector(11 downto 0); - signal local_reset, to_crc_generator, from_crc_generator, from_mem_1_bit, shift_crc, - recv_data, crc_generator_enable : std_logic; -begin - -- State transitions - state_transitions: process( current_state, i_begin, i_sd_clock_pulse_trigger, i_transmit, byte_counter, - bit_counter, crc_counter, i_1bit_data_in, timeout_register, data_in_reg) - begin - case (current_state) is - when s_RESET => - -- Reset local registers and begin waiting for user input. - next_state <= s_WAIT_REQUEST; - - when s_WAIT_REQUEST => - -- Wait for i_begin to be high - if ((i_begin = '1') and (i_sd_clock_pulse_trigger = '1')) then - if (i_transmit = '1') then - next_state <= s_SEND_START_BIT; - else - next_state <= s_WAIT_DATA_START; - end if; - else - next_state <= s_WAIT_REQUEST; - end if; - - when s_SEND_START_BIT => - -- Send a 0 first, followed by 4096 bits of data, 16 CRC bits, and stop bit. - if (i_sd_clock_pulse_trigger = '1') then - next_state <= s_SEND_DATA; - else - next_state <= s_SEND_START_BIT; - end if; - - when s_SEND_DATA => - -- Send 4096 data bits - if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then - next_state <= s_SEND_CRC; - else - next_state <= s_SEND_DATA; - end if; - - when s_SEND_CRC => - -- Send 16 CRC bits - if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then - next_state <= s_SEND_STOP; - else - next_state <= s_SEND_CRC; - end if; - - when s_SEND_STOP => - -- Send stop bit. - if (i_sd_clock_pulse_trigger = '1') then - next_state <= s_WAIT_BUSY; - else - next_state <= s_SEND_STOP; - end if; - - when s_WAIT_BUSY => - -- After a write, wait for the busy signal. Do not return a done signal until you receive a busy signal. - -- If you do not and a long time expires, then the data must have been rejected (due to CRC error maybe). - -- In such a case return failure. - if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0') and (timeout_register = "0000000000010000")) then - next_state <= s_WAIT_BUSY_END; - else - if (timeout_register = BUSY_WAIT) then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_BUSY; - end if; - end if; - - when s_WAIT_BUSY_END => - if (i_sd_clock_pulse_trigger = '1') then - if (data_in_reg = '1') then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_BUSY_END; - end if; - else - next_state <= s_WAIT_BUSY_END; - end if; - - when s_WAIT_DATA_START => - -- Wait for the start bit - if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0')) then - next_state <= s_RECEIVING_LEADING_BITS; - else - if (timeout_register = TIMEOUT) then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_DATA_START; - end if; - end if; - - when s_RECEIVING_LEADING_BITS => - -- shift the start bit in as well as the next 16 bits. Once they are all in you can start putting data into memory. - if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then - next_state <= s_RECEIVING_DATA; - else - next_state <= s_RECEIVING_LEADING_BITS; - end if; - - when s_RECEIVING_DATA => - -- Wait until all bits arrive. - if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then - next_state <= s_RECEIVING_STOP_BIT; - else - next_state <= s_RECEIVING_DATA; - end if; - - when s_RECEIVING_STOP_BIT => - -- Wait until all bits arrive. - if (i_sd_clock_pulse_trigger = '1')then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_RECEIVING_STOP_BIT; - end if; - - when s_WAIT_DEASSERT => - if (i_begin = '1') then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_REQUEST; - end if; - - when others => - next_state <= s_RESET; - end case; - end process; - - -- State registers - state_regs: process(i_clock, i_reset_n, local_reset) - begin - if (i_reset_n = '0') then - current_state <= s_RESET; - elsif (rising_edge(i_clock)) then - current_state <= next_state; - end if; - end process; - - -- FSM outputs - to_crc_generator <= shift_register(16) when (current_state = s_RECEIVING_DATA) else - from_mem_1_bit when (current_state = s_SEND_DATA) else - '0'; - shift_crc <= '1' when (current_state = s_SEND_CRC) else '0'; - local_reset <= '1' when ((current_state = s_RESET) or (current_state = s_WAIT_REQUEST)) else '0'; - recv_data <= '1' when (current_state = s_RECEIVING_DATA) else '0'; - single_bit_conversion(0) <= shift_register(15); - crc_generator_enable <= '0' when (current_state = s_WAIT_DEASSERT) else i_sd_clock_pulse_trigger; - o_operation_complete <= '1' when (current_state = s_WAIT_DEASSERT) else '0'; - o_dat_direction <= '1' when ( (current_state = s_SEND_START_BIT) or - (current_state = s_SEND_DATA) or - (current_state = s_SEND_CRC) or - (current_state = s_SEND_STOP)) - else '0'; - o_1bit_data_out <= dataout_1bit; - o_crc_passed <= '1' when ((crc_out = shift_register(16 downto 1)) and (shift_register(0) = '1')) else '0'; - o_timed_out <= '1' when (timeout_register = TIMEOUT) else '0'; - - -- Local components - local_regs: process(i_clock, i_reset_n, local_reset) - begin - if (i_reset_n = '0') then - bit_counter <= (OTHERS => '1'); - byte_counter <= (OTHERS => '0'); - dataout_1bit <= '1'; - crc_counter <= (OTHERS => '0'); - shift_register <= (OTHERS => '0'); - elsif (rising_edge(i_clock)) then - -- counters and serial output - if (local_reset = '1') then - bit_counter <= (OTHERS => '1'); - byte_counter <= (OTHERS => '0'); - dataout_1bit <= '1'; - data_in_reg <= '1'; - crc_counter <= (OTHERS => '0'); - shift_register <= (OTHERS => '0'); - elsif (i_sd_clock_pulse_trigger = '1') then - if ((not (current_state = s_RECEIVING_LEADING_BITS)) and (not (current_state = s_SEND_CRC))) then - crc_counter <= (OTHERS => '0'); - else - if (not (crc_counter = "1111")) then - crc_counter <= crc_counter + '1'; - end if; - end if; - if ((current_state = s_RECEIVING_DATA) or (current_state = s_SEND_DATA)) then - if (not ((bit_counter = "000") and (byte_counter = "111111111"))) then - if (bit_counter = "000") then - byte_counter <= byte_counter + '1'; - bit_counter <= "111"; - else - bit_counter <= bit_counter - '1'; - end if; - end if; - end if; - -- Output data bit. - if (current_state = s_SEND_START_BIT) then - dataout_1bit <= '0'; - elsif (current_state = s_SEND_DATA) then - dataout_1bit <= from_mem_1_bit; - elsif (current_state = s_SEND_CRC) then - dataout_1bit <= from_crc_generator; - else - dataout_1bit <= '1'; -- Stop bit. - end if; - - -- Shift register to store the CRC bits once the message is received. - if ((current_state = s_RECEIVING_DATA) or - (current_state = s_RECEIVING_LEADING_BITS) or - (current_state = s_RECEIVING_STOP_BIT)) then - shift_register(16 downto 1) <= shift_register(15 downto 0); - shift_register(0) <= data_in_reg; - end if; - data_in_reg <= i_1bit_data_in; - end if; - end if; - end process; - - -- Register holding the timeout value for data transmission. - timeout_reg: process(i_clock, i_reset_n, current_state, i_sd_clock_pulse_trigger) - begin - if (i_reset_n = '0') then - timeout_register <= (OTHERS => '0'); - elsif (rising_edge(i_clock)) then - if ((current_state = s_SEND_STOP) or - (current_state = s_WAIT_REQUEST)) then - timeout_register <= (OTHERS => '0'); - elsif (i_sd_clock_pulse_trigger = '1') then - -- Increment the timeout counter - if (((current_state = s_WAIT_DATA_START) or - (current_state = s_WAIT_BUSY)) and (not (timeout_register = TIMEOUT))) then - timeout_register <= timeout_register + '1'; - end if; - end if; - end if; - end process; - - -- Instantiated components. - crc16_checker: Altera_UP_SD_CRC16_Generator - port map - ( - i_clock => i_clock, - i_reset_n => i_reset_n, - i_sync_reset => local_reset, - i_enable => crc_generator_enable, - i_shift => shift_crc, - i_datain => to_crc_generator, - o_dataout => from_crc_generator, - o_crcout => crc_out - ); - - packet_memory: Altera_UP_SD_Card_Memory_Block - PORT MAP - ( - address_a => i_address_16bit_port, - address_b => packet_mem_addr_b, - clock_a => i_clock, - clock_b => i_clock, - data_a => i_16bit_data_in, - data_b => single_bit_conversion, - enable_a => i_enable_16bit_port, - enable_b => '1', - wren_a => i_write_16bit, - wren_b => recv_data, - q_a => o_16bit_data_out, - q_b => single_bit_out - ); - from_mem_1_bit <= single_bit_out(0); - packet_mem_addr_b <= (byte_counter & bit_counter); - -end rtl; diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd deleted file mode 100644 index 094d9dd..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd +++ /dev/null @@ -1,80 +0,0 @@ --- (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 a clock generator for the SD card interface. It takes a 50 MHz --- clock as input and produces a clock signal that depends on the mode in which the --- SD card interface is in. For a card identification mode a clock with a frequency of --- 390.625 kHz is generated. For the data transfer mode, a clock with a frequency of --- 12.5MHz is generated. --- --- In addition, the generator produces a clock_mode value that identifies the frequency --- of the o_SD_clock that is currently being generated. --- --- 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_Clock is - - 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 entity; - -architecture rtl of Altera_UP_SD_Card_Clock is - - -- Local wires - -- REGISTERED - signal counter : std_logic_vector(6 downto 0); - signal local_mode : std_logic; - -- UNREGISTERED -begin - process(i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - counter <= (OTHERS => '0'); - local_mode <= '0'; - else - if (rising_edge(i_clock)) then - if (i_enable = '1') then - counter <= counter + '1'; - end if; - -- Change the clock pulse only when at the positive edge of the clock - if (counter = "1000000") then - local_mode <= i_mode; - end if; - end if; - end if; - end process; - - o_clock_mode <= local_mode; - o_SD_clock <= counter(6) when (local_mode = '0') else counter(1); - o_trigger_receive <= '1' when ((local_mode = '0') and (counter = "0111111")) else - ((not counter(1)) and (counter(0))) when (local_mode = '1') else '0'; - o_trigger_send <= '1' when ((local_mode = '0') and (counter = "0011111")) else - ((counter(1)) and (counter(0))) when (local_mode = '1') else '0'; - -end rtl; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd deleted file mode 100644 index c020fbd..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd +++ /dev/null @@ -1,347 +0,0 @@ --- (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 is an FSM that controls the SD Card interface circuitry. --- --- On reset, the FSM will initiate a predefined set of commands in an attempt to connect to the SD Card. --- When successful, it will allow commands to be issued to the SD Card, otherwise it will return a signal that --- no card is present in the SD Card slot. --- --- 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_Control_FSM is - 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 entity; - -architecture rtl of Altera_UP_SD_Card_Control_FSM is - - -- 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_RESET, s_WAIT_74_CYCLES, s_GENERATE_PREDEFINED_COMMAND, s_WAIT_PREDEFINED_COMMAND_TRANSMITTED, s_WAIT_PREDEFINED_COMMAND_RESPONSE, - s_GO_TO_NEXT_COMMAND, s_TOGGLE_CLOCK_FREQUENCY, s_AWAIT_USER_COMMAND, s_REACTIVATE_CLOCK, - s_GENERATE_COMMAND, s_SEND_COMMAND, s_WAIT_RESPONSE, s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE, s_WAIT_DEASSERT, - s_PERIODIC_STATUS_CHECK); - - -- Register to hold the current state - signal current_state : state_type; - signal next_state : state_type; - - ------------------- - -- Local signals - ------------------- - -- REGISTERED - signal SD_clock_mode, waiting_for_vdd_setup : std_logic; - signal id_sequence_step_index : std_logic_vector(3 downto 0); - signal delay_counter : std_logic_vector(6 downto 0); - signal periodic_status_check : std_logic_vector(23 downto 0); - -- UNREGISTERED - -begin - -- Define state transitions. - state_transitions: process (current_state, i_command_sent, i_response_received, id_sequence_step_index, - i_response_timed_out, i_response_crc_passed, delay_counter, waiting_for_vdd_setup, - i_user_command_ready, i_clocking_pulse_enable, i_current_clock_mode, - i_user_message_valid, i_last_cmd_was_55, periodic_status_check) - begin - case current_state is - when s_RESET => - -- Reset local registers and begin identification process. - next_state <= s_WAIT_74_CYCLES; - - when s_WAIT_74_CYCLES => - -- Wait 74 cycles before the card can be sent commands to. - if (delay_counter = "1001010") then - next_state <= s_GENERATE_PREDEFINED_COMMAND; - else - next_state <= s_WAIT_74_CYCLES; - end if; - - when s_GENERATE_PREDEFINED_COMMAND => - -- Generate a predefined command to the SD card. This is the identification process for the SD card. - next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED; - - when s_WAIT_PREDEFINED_COMMAND_TRANSMITTED => - -- Send a predefined command to the SD card. This is the identification process for the SD card. - if (i_command_sent = '1') then - next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE; - else - next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED; - end if; - - when s_WAIT_PREDEFINED_COMMAND_RESPONSE => - -- Wait for a response from SD card. - if (i_response_received = '1') then - if (i_response_timed_out = '1') then - if (waiting_for_vdd_setup = '1') then - next_state <= s_GO_TO_NEXT_COMMAND; - else - next_state <= s_RESET; - end if; - else - if (i_response_crc_passed = '0') then - next_state <= s_GENERATE_PREDEFINED_COMMAND; - else - next_state <= s_GO_TO_NEXT_COMMAND; - end if; - end if; - else - next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE; - end if; - - when s_GO_TO_NEXT_COMMAND => - -- Process the next command in the ID sequence. - if (id_sequence_step_index = PREDEFINED_COMMAND_GET_STATUS) then - next_state <= s_TOGGLE_CLOCK_FREQUENCY; - else - next_state <= s_GENERATE_PREDEFINED_COMMAND; - end if; - - when s_TOGGLE_CLOCK_FREQUENCY => - -- Now that the card has been initialized, increase the SD card clock frequency to 25MHz. - -- Wait for the clock generator to switch operating mode before proceeding further. - if (i_current_clock_mode = '1') then - next_state <= s_AWAIT_USER_COMMAND; - else - next_state <= s_TOGGLE_CLOCK_FREQUENCY; - end if; - - when s_AWAIT_USER_COMMAND => - -- Wait for the user to send a command to the SD card - if (i_user_command_ready = '1') then - next_state <= s_REACTIVATE_CLOCK; - else - -- Every 5 million cycles, or 0.1 of a second. - if (periodic_status_check = "010011000100101101000000") then - next_state <= s_PERIODIC_STATUS_CHECK; - else - next_state <= s_AWAIT_USER_COMMAND; - end if; - end if; - - when s_PERIODIC_STATUS_CHECK => - -- Update status every now and then. - next_state <= s_GENERATE_PREDEFINED_COMMAND; - - when s_REACTIVATE_CLOCK => - -- Activate the clock signal and wait 8 clock cycles. - if (delay_counter = "0001000") then - next_state <= s_GENERATE_COMMAND; - else - next_state <= s_REACTIVATE_CLOCK; - end if; - - when s_GENERATE_COMMAND => - -- Generate user command. If valid, proceed further. Otherwise, indicate that the command is invalid. - if (i_user_message_valid = '0') then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_SEND_COMMAND; - end if; - - when s_SEND_COMMAND => - -- Wait for the command to be sent. - if (i_command_sent = '1') then - next_state <= s_WAIT_RESPONSE; - else - next_state <= s_SEND_COMMAND; - end if; - - when s_WAIT_RESPONSE => - -- Wait for the SD card to respond. - if (i_response_received = '1') then - if (i_response_timed_out = '1') then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE; - end if; - else - next_state <= s_WAIT_RESPONSE; - end if; - - when s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE => - -- Wait for a positive clock edge before you disable the clock. - if (i_clocking_pulse_enable = '1') then - next_state <= s_WAIT_DEASSERT; - else - next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE; - end if; - - when s_WAIT_DEASSERT => - -- wait for the user to release command generation request. - if (i_user_command_ready = '1') then - next_state <= s_WAIT_DEASSERT; - else - if (i_last_cmd_was_55 = '1') then - next_state <= s_AWAIT_USER_COMMAND; - else - -- Send a get status command to obtain the result of sending the last command. - next_state <= s_GENERATE_PREDEFINED_COMMAND; - end if; - end if; - - when others => - -- Make sure to start in the reset state if the circuit powers up in an odd state. - next_state <= s_RESET; - end case; - end process; - - -- State registers. - state_registers: process (i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - current_state <= s_RESET; - elsif (rising_edge(i_clock)) then - current_state <= next_state; - end if; - end process; - - -- Local FFs: - local_ffs:process ( i_clock, i_reset_n, i_powerup_busy_n, current_state, - id_sequence_step_index, i_response_received, i_response_timed_out, - i_allow_partial_rw) - begin - if (i_reset_n = '0') then - SD_clock_mode <= '0'; - id_sequence_step_index <= (OTHERS => '0'); - periodic_status_check <= (OTHERS => '0'); - waiting_for_vdd_setup <= '0'; - elsif (rising_edge(i_clock)) then - -- Set SD clock mode to 0 initially, thereby using a clock with frequency between 100 kHz and 400 kHz as - -- per SD card specifications. When the card is initialized change the clock to run at 25 MHz. - if (current_state = s_WAIT_DEASSERT) then - periodic_status_check <= (OTHERS => '0'); - elsif (current_state = s_AWAIT_USER_COMMAND) then - periodic_status_check <= periodic_status_check + '1'; - end if; - - if (current_state = s_RESET) then - SD_clock_mode <= '0'; - elsif (current_state = s_TOGGLE_CLOCK_FREQUENCY) then - SD_clock_mode <= '1'; - end if; - -- Update the ID sequence step as needed. - if (current_state = s_RESET) then - id_sequence_step_index <= (OTHERS => '0'); - elsif (current_state = s_GO_TO_NEXT_COMMAND) then - if ((i_powerup_busy_n = '0') and (id_sequence_step_index = "0010")) then - id_sequence_step_index <= "0001"; - else - if (id_sequence_step_index = "0110") then - if (i_allow_partial_rw = '0') then - -- If partial read-write not allowed, then skip SET_BLK_LEN command - it will fail. - id_sequence_step_index <= "1000"; - else - id_sequence_step_index <= "0111"; - end if; - else - id_sequence_step_index <= id_sequence_step_index + '1'; - end if; - end if; - elsif (current_state = s_WAIT_DEASSERT) then - if (i_last_cmd_was_55 = '0') then - -- After each command execute a get status command. - id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS; - end if; - elsif (current_state = s_PERIODIC_STATUS_CHECK) then - id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS; - end if; - - -- Do not reset the card when SD card is having its VDD set up. Wait for it to respond, this may take some time. - if (id_sequence_step_index = "0010") then - waiting_for_vdd_setup <= '1'; - elsif ((id_sequence_step_index = "0011") or (current_state = s_RESET)) then - waiting_for_vdd_setup <= '0'; - end if; - - end if; - end process; - - -- Counter that counts to 74 to delay any commands. - initial_delay_counter: process(i_clock, i_reset_n, i_clocking_pulse_enable ) - begin - if (i_reset_n = '0') then - delay_counter <= (OTHERS => '0'); - elsif (rising_edge(i_clock)) then - if ((current_state = s_RESET) or (current_state = s_AWAIT_USER_COMMAND))then - delay_counter <= (OTHERS => '0'); - elsif (((current_state = s_WAIT_74_CYCLES) or (current_state = s_REACTIVATE_CLOCK)) and - (i_clocking_pulse_enable = '1')) then - delay_counter <= delay_counter + '1'; - end if; - end if; - end process; - - -- FSM outputs. - o_SD_clock_mode <= SD_clock_mode; - o_generate_command <= '1' when ((current_state = s_GENERATE_PREDEFINED_COMMAND) or - (current_state = s_GENERATE_COMMAND)) - else '0'; - o_receive_response <= '1' when ((current_state = s_WAIT_PREDEFINED_COMMAND_RESPONSE) or - (current_state = s_WAIT_RESPONSE)) - else '0'; - o_drive_CMD_line <= '1' when ( (current_state = s_WAIT_PREDEFINED_COMMAND_TRANSMITTED) or - (current_state = s_SEND_COMMAND)) else '0'; - o_predefined_command_ID <= id_sequence_step_index; - o_card_connected <= '1' when (id_sequence_step_index(3) = '1') and ( - (id_sequence_step_index(2) = '1') or - (id_sequence_step_index(1) = '1') or - (id_sequence_step_index(0) = '1')) - else '0'; - o_resetting <= '1' when (current_state = s_RESET) else '0'; - o_command_completed <= '1' when (current_state = s_WAIT_DEASSERT) else '0'; - o_enable_clock_generator <= '0' when (current_state = s_AWAIT_USER_COMMAND) else '1'; - o_clear_response_register <= '1' when (current_state = s_REACTIVATE_CLOCK) else '0'; - -end rtl; - diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd deleted file mode 100644 index ba2f743..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd +++ /dev/null @@ -1,518 +0,0 @@ --- (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; diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd deleted file mode 100644 index 5b1d0cc..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd +++ /dev/null @@ -1,296 +0,0 @@ --- (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. - - --- megafunction wizard: %RAM: 2-PORT% --- GENERATION: STANDARD --- VERSION: WM1.0 --- MODULE: altsyncram - --- ============================================================ --- File Name: Altera_UP_SD_Card_Memory_Block.vhd --- Megafunction Name(s): --- altsyncram --- --- Simulation Library Files(s): --- altera_mf --- ============================================================ --- ************************************************************ --- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! --- --- 8.0 Build 215 05/29/2008 SJ Full Version --- ************************************************************ - - ---Copyright (C) 1991-2013 Altera Corporation ---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 from 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. - - -LIBRARY ieee; -USE ieee.std_logic_1164.all; - -LIBRARY altera_mf; -USE altera_mf.all; - -ENTITY Altera_UP_SD_Card_Memory_Block IS - PORT - ( - address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); - address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); - clock_a : IN STD_LOGIC ; - clock_b : IN STD_LOGIC ; - data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); - data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0); - enable_a : IN STD_LOGIC := '1'; - enable_b : IN STD_LOGIC := '1'; - wren_a : IN STD_LOGIC := '1'; - wren_b : IN STD_LOGIC := '1'; - q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); - q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0) - ); -END Altera_UP_SD_Card_Memory_Block; - - -ARCHITECTURE SYN OF altera_up_sd_card_memory_block IS - - SIGNAL sub_wire0 : STD_LOGIC_VECTOR (15 DOWNTO 0); - SIGNAL sub_wire1 : STD_LOGIC_VECTOR (0 DOWNTO 0); - - - - COMPONENT altsyncram - GENERIC ( - address_reg_b : STRING; - clock_enable_input_a : STRING; - clock_enable_input_b : STRING; - clock_enable_output_a : STRING; - clock_enable_output_b : STRING; - indata_reg_b : STRING; - init_file : STRING; - init_file_layout : STRING; - intended_device_family : STRING; - lpm_type : STRING; - numwords_a : NATURAL; - numwords_b : NATURAL; - operation_mode : STRING; - outdata_aclr_a : STRING; - outdata_aclr_b : STRING; - outdata_reg_a : STRING; - outdata_reg_b : STRING; - power_up_uninitialized : STRING; - widthad_a : NATURAL; - widthad_b : NATURAL; - width_a : NATURAL; - width_b : NATURAL; - width_byteena_a : NATURAL; - width_byteena_b : NATURAL; - wrcontrol_wraddress_reg_b : STRING - ); - PORT ( - clocken0 : IN STD_LOGIC ; - clocken1 : IN STD_LOGIC ; - wren_a : IN STD_LOGIC ; - clock0 : IN STD_LOGIC ; - wren_b : IN STD_LOGIC ; - clock1 : IN STD_LOGIC ; - address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); - address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); - q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); - q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); - data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); - data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0) - ); - END COMPONENT; - -BEGIN - q_a <= sub_wire0(15 DOWNTO 0); - q_b <= sub_wire1(0 DOWNTO 0); - - altsyncram_component : altsyncram - GENERIC MAP ( - address_reg_b => "CLOCK1", - clock_enable_input_a => "NORMAL", - clock_enable_input_b => "NORMAL", - clock_enable_output_a => "BYPASS", - clock_enable_output_b => "BYPASS", - indata_reg_b => "CLOCK1", - init_file => "initial_data.mif", - init_file_layout => "PORT_A", - intended_device_family => "Cyclone II", - lpm_type => "altsyncram", - numwords_a => 256, - numwords_b => 4096, - operation_mode => "BIDIR_DUAL_PORT", - outdata_aclr_a => "NONE", - outdata_aclr_b => "NONE", - outdata_reg_a => "UNREGISTERED", - outdata_reg_b => "UNREGISTERED", - power_up_uninitialized => "FALSE", - widthad_a => 8, - widthad_b => 12, - width_a => 16, - width_b => 1, - width_byteena_a => 1, - width_byteena_b => 1, - wrcontrol_wraddress_reg_b => "CLOCK1" - ) - PORT MAP ( - clocken0 => enable_a, - clocken1 => enable_b, - wren_a => wren_a, - clock0 => clock_a, - wren_b => wren_b, - clock1 => clock_b, - address_a => address_a, - address_b => address_b, - data_a => data_a, - data_b => data_b, - q_a => sub_wire0, - q_b => sub_wire1 - ); - - - -END SYN; - --- ============================================================ --- CNX file retrieval info --- ============================================================ --- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" --- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" --- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" --- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" --- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" --- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" --- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" --- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" --- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" --- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "1" --- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" --- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" --- Retrieval info: PRIVATE: CLRdata NUMERIC "0" --- Retrieval info: PRIVATE: CLRq NUMERIC "0" --- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" --- Retrieval info: PRIVATE: CLRrren NUMERIC "0" --- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" --- Retrieval info: PRIVATE: CLRwren NUMERIC "0" --- Retrieval info: PRIVATE: Clock NUMERIC "5" --- Retrieval info: PRIVATE: Clock_A NUMERIC "0" --- Retrieval info: PRIVATE: Clock_B NUMERIC "0" --- Retrieval info: PRIVATE: ECC NUMERIC "0" --- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" --- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" --- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" --- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" --- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" --- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" --- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" --- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" --- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" --- Retrieval info: PRIVATE: MEMSIZE NUMERIC "4096" --- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "1" --- Retrieval info: PRIVATE: MIFfilename STRING "initial_data.mif" --- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" --- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" --- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" --- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" --- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" --- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" --- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" --- Retrieval info: PRIVATE: REGdata NUMERIC "1" --- Retrieval info: PRIVATE: REGq NUMERIC "0" --- Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" --- Retrieval info: PRIVATE: REGrren NUMERIC "0" --- Retrieval info: PRIVATE: REGwraddress NUMERIC "1" --- Retrieval info: PRIVATE: REGwren NUMERIC "1" --- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" --- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" --- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" --- Retrieval info: PRIVATE: VarWidth NUMERIC "1" --- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "16" --- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "1" --- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "16" --- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "1" --- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" --- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" --- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" --- Retrieval info: PRIVATE: enable NUMERIC "1" --- Retrieval info: PRIVATE: rden NUMERIC "0" --- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" --- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL" --- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "NORMAL" --- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" --- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" --- Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" --- Retrieval info: CONSTANT: INIT_FILE STRING "initial_data.mif" --- Retrieval info: CONSTANT: INIT_FILE_LAYOUT STRING "PORT_A" --- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" --- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" --- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" --- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "4096" --- Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" --- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" --- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" --- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" --- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" --- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" --- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" --- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "12" --- Retrieval info: CONSTANT: WIDTH_A NUMERIC "16" --- Retrieval info: CONSTANT: WIDTH_B NUMERIC "1" --- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" --- Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" --- Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" --- Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL address_a[7..0] --- Retrieval info: USED_PORT: address_b 0 0 12 0 INPUT NODEFVAL address_b[11..0] --- Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT NODEFVAL clock_a --- Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL clock_b --- Retrieval info: USED_PORT: data_a 0 0 16 0 INPUT NODEFVAL data_a[15..0] --- Retrieval info: USED_PORT: data_b 0 0 1 0 INPUT NODEFVAL data_b[0..0] --- Retrieval info: USED_PORT: enable_a 0 0 0 0 INPUT VCC enable_a --- Retrieval info: USED_PORT: enable_b 0 0 0 0 INPUT VCC enable_b --- Retrieval info: USED_PORT: q_a 0 0 16 0 OUTPUT NODEFVAL q_a[15..0] --- Retrieval info: USED_PORT: q_b 0 0 1 0 OUTPUT NODEFVAL q_b[0..0] --- Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT VCC wren_a --- Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT VCC wren_b --- Retrieval info: CONNECT: @data_a 0 0 16 0 data_a 0 0 16 0 --- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 --- Retrieval info: CONNECT: q_a 0 0 16 0 @q_a 0 0 16 0 --- Retrieval info: CONNECT: q_b 0 0 1 0 @q_b 0 0 1 0 --- Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0 --- Retrieval info: CONNECT: @data_b 0 0 1 0 data_b 0 0 1 0 --- Retrieval info: CONNECT: @address_b 0 0 12 0 address_b 0 0 12 0 --- Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 --- Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 --- Retrieval info: CONNECT: @clocken0 0 0 0 0 enable_a 0 0 0 0 --- Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 --- Retrieval info: CONNECT: @clocken1 0 0 0 0 enable_b 0 0 0 0 --- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.vhd TRUE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.inc FALSE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.cmp TRUE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.bsf TRUE FALSE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_inst.vhd FALSE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_waveforms.html TRUE --- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_wave*.jpg FALSE --- Retrieval info: LIB_FILE: altera_mf diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd deleted file mode 100644 index 7b195b6..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd +++ /dev/null @@ -1,308 +0,0 @@ --- (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; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd deleted file mode 100644 index 7529de8..0000000 --- a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd +++ /dev/null @@ -1,57 +0,0 @@ --- (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 generates a trigger pulse every time it sees a transition --- from 0 to 1 on signal i_signal. --- --- NOTES/REVISIONS: ---------------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity Altera_UP_SD_Signal_Trigger is - - port - ( - i_clock : in std_logic; - i_reset_n : in std_logic; - i_signal : in std_logic; - o_trigger : out std_logic - ); - -end entity; - -architecture rtl of Altera_UP_SD_Signal_Trigger is - - -- Local wires - -- REGISTERED - signal local_reg : std_logic; -begin - - process (i_clock, i_reset_n) - begin - if (i_reset_n = '0') then - local_reg <= '0'; - else - if (rising_edge(i_clock)) then - local_reg <= i_signal; - end if; - end if; - end process; - - o_trigger <= '1' when ((local_reg = '0') and (i_signal = '1')) - else '0'; -end rtl; \ No newline at end of file