WB_SDHC - Wishbone SDHC Controller
Contents
- Features at-a-glance
- Availability
- Pin Description
- Operational Overview
- Card Detection and Removal
- Transmitting Commands
- Receiving Responses
- Transmitting Data
- Receiving Data
- DMA Interface
- Register Interface
- Software Platform Support
- Associated Design Interface Component
- Resource Usage
- Example Reference Design
- See Also
Parent article: FPGA Peripheral Components - Wishbone
The Wishbone SDHC Controller component (WB_SDHC) provides an interface that enables a host processor to efficiently communicate with a Secure Digital (SD) or Secure Digital High-Capacity (SDHC) storage device – resident outside of the physical FPGA device to which the design is targeted. Communication is over a 4-bit parallel data bus, with control implemented using a single-bit command bus.
The WB_SDHC can be used with any of the 32-bit processors available in Altium Designer.
Features at-a-glance
- Transmit commands through a simple register-based interface
- Receive command responses through a FIFO-based interface
- Transmit data block-wise through a 32-bit DMA interface
- Receive data multiple-block-wise through the same DMA interface
- Maximum clock speed on SD is one quarter the system frequency
- Maximum raw transfer speed of 6.25MByte/s (based on a system clock of 50MHz)
- Maximum Read/Write speeds through file system (tested using a TSK3000A at 50MHz):
- Read: 5.7MByte/s (depends on SD/SDHC card used)
- Write: 4.5MByte/s (depends on SD/SDHC card used)
- CRC on both command and data interfaces
- Wishbone-compliant
Availability
From an OpenBus System document, the SDHC Controller component can be found in the Peripherals region of the OpenBus Palette panel.
From a schematic document, the WB_SDHC component can be found in the FPGA Peripherals (Wishbone) integrated library (FPGA Peripherals (Wishbone).IntLib
), located in the \Library\Fpga
folder of the installation.
Pin Description
The following pin description is for the WB_SDHC component when used on the schematic. In an OpenBus System, although the same signals are present, the abstract nature of the system hides the pin-level Wishbone interfaces. The external interface signals will be made available as sheet entries, associated with the parent sheet symbol used to reference the underlying OpenBus System.
Work In Progress
Operational Overview
The following sections outline the basic procedure in order to initiate communications with the target SD/SDHC Card.
Card Detection and Removal
Two bits in the Status register are available to check if a card is inserted and/or has been changed:
- Bit 0 reflects the state of the input pin SD_DETECT. It is '1' if there is a card inserted.
- Bit 2 is set if the card is removed. It stays '1' until you write a '1' into the bit from software. Thus, if this bit is set, you must re-initialize the SD Card before further use.
Transmitting Commands
A commands always consists of 48 bits. It contains a start bit ('0'), a direction bit (host to card: '1'), 6 command bits, 32 argument bits, a 7-bit CRC and a stop bit ('1').
In order to transmit a command:
- Write the command to the CMD_TXCMD register
- Write the argument to the CMD_TXARG register
- Set the CMD_TXENABLE bit in the Control register
- Wait until the CMD_TXENABLE bit disappears from the Status register
- Wait until the CMD_TXBUSY bit disappears from the Status register
Receiving Responses
A response consists of 48 or 136 bits and can include a CRC. It always starts with a start bit ('0') a direction bit ('0' as well) and ends with a stop bit ('1').
In order to reliably receive a response, you should indicate you want to receive an answer at the same time you set up the transmission, as follows:
- Write the command to the CMD_TXCMD register
- Write the argument to the CMD_TXARG register
- Write the expected number of response bytes (excluding CRC) in the CMD_RXSIZE register
- Set the CMD_TXENABLE and CMD_RXENABLE bits in the Control register
- Wait until the CMD_TXENABLE bit disappears from the Status register
- Wait until the CMD_TXBUSY bit disappears from the Status register
- Setup a timeout for the receiver
- While timeout did not elapse, check FIFO and copy response into memory. Stop if you've got all bytes you want
- Check for timeout, busy, rxempty and CRC.
Even though a message can contain up to 136 bits, the FIFO is large enough to store 16 bytes. The 17th byte in a long message always contains the CRC of the payload and is stripped by the WB_SDHC.
Transmitting Data
Data transmission can be done in single-block mode only. However, the SD Card protocol implements a multi-block write command that can be used to transmit individual blocks in succession. It is not needed to send data using the single_block_write
command.
In order to transmit data, send the write_single_block
command (SDMEM command 24) and wait for response as usual. Then:
- Set block size to physical block size of SD Card (in bytes)
- Set DMA address to where data is stored in memory
- Set the DAT_TXENABLE bit in the Control register
- Wait for DAT_TXENABLE to disappear from the Status register
- Wait for DAT_TXBUSY to disappear from the Status register
- Check for overrun and CRC errors
If you want to send multiple blocks, send a write_multiple_block
command (SDMEM command 25), wait for response, than execute steps 1 and 2 only once and loop steps 3 – 6 until done. Then send a transmission_stop
command (SDMEM command 12).
Transmitting data may be followed by the card being busy. Check for DAT_READY before starting a new read- or write-cycle.
Receiving Data
If you are ready to receive data, you should:
- Write the buffer address (must be in external memory!) into the DAT_MEMADR register
- Write the SD card's physical block size in the DAT_BLKSIZE register
- Write the number of bytes you want to receive in the DAT_RXSIZE register
- Arm the data receiver by setting DAT_RXENABLE in the Control register
- Transmit and wait for the response to the data read command (SDMEM: cmd17 or cmd18)
- Setup the data timeout
- Wait while timeout did not elapse and DAT_RXBUSY in the Status register is not set
- If DAT_RXBUSY is set, wait for it to disappear (timeout error otherwise)
- If reading multiple blocks, sent a stop message
- Check data CRC and DMA timeout status bits
DMA Interface
The DMA interface consists of a 32-bit wishbone-compliant master bus. It currently has 20 address bits (19..0), from which the lower 2 bits are fixed to '0'. Reads and writes thus always are word-wide (MEM_SEL_O[3..0] are fixed to '1') and they are 32-bit aligned. The core assumes memory access is big endian hosted, thus the first nibble in a card to host transmission is written on MEM_DAT_O[31..28], the second on MEM_DAT_O[27..24] and so on. In line with this, the host should write big endian style when preparing data for transmission to the card (MEM_DAT_I[31..28] should contain the first nibble to be transmitted).
The WB_SDHC core needs access to the memory every 8 SD_CLK cycles. The maximum frequency of SD_CLK is CLK_I / 4. Since most SD cards accept faster clock speeds than this, the WB_SDHC DMA unit typically will require access to memory every 32 system clock cycles during data transfer. You must make sure in your design that this requirement is met or you will at one time run into DMA errors!
Register Interface
Main article: WB_SDHC - Accessible Internal Registers
Address | Name | Function |
---|---|---|
0000 (00h) | CDIV | 10-bit clock divider |
0001 (01h) | CTRL | Control register |
0010 (02h) | STAT | Status register |
0011 (03h) | CMD_TXCMD | Command transmitter command code |
0100 (04h) | CMD_TXARG | Command transmitter argument |
0101 (05h) | CMD_RXSIZE | Command Receiver size |
0110 (06h) | CMD_RXFIFO | Command Receiver FIFO |
0111 (07h) | DAT_BLKSIZE | Data block size (in bytes) |
1000 (08h) | DAT_RXSIZE | Data transfer size |
1001 (09h) | DAT_MEMADR | DMA address for data Read/Write |
1111 (0Fh) | VERSION_INFO | Version and configuration |
Software Platform Support
The WB_SDHC is fully supported by the Software Platform. All registers of the peripheral are described in per_sdhc.h
, a device driver is available in drv_sdhc.c
and drv_sdhc.h
. See online documentation for a full description of its interface. The driver connects to the posix Block Device I/O system if required, thus directly providing support for the posix filesystem.
Associated Design Interface Component
The following table summarizes the available design interface component that can be placed from the relevant port-plugin library for access to, and communications with, an SD/SDHC memory card inserted into:
- The SD Card reader accessible by the User FPGA on a 3000-series NanoBoard (port-plugin library:
FPGA NB3000 Port-Plugin.IntLib
).
- The SD Card reader resident on a Mass Storage peripheral board (PB02) attached to a NanoBoard NB2 (port-plugin library:
FPGA PB02 Port-Plugin.IntLib
).
Component Symbol
|
Component Name
|
Description
|
---|---|---|
SDHC | Place this component to interface to the Secure Digital (SD) card reader and write/read an SD or SDHC memory card inserted within. |
Resource Usage
As a rough guide (subject to change!) – on a Xilinx Spartan3, the core currently takes approx. 761 LUTs, 8 dual port 16x1D RAMs and 456 register bits.
Example Reference Design
An example design, demonstrating the use of the SDHC Controller peripheral, is included as part of your Altium Designer installation:
sdhc_memory_card.PrjFpg
– located in the\Examples\Soft Designs\Storage\SDHC Memory Card
folder.