WB_SDHC - Wishbone SDHC Controller

Frozen Content

Parent article: FPGA Peripheral Components - Wishbone

WB_SDHC - Wishbone SDHC Controller.

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


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:

  1. Write the command to the CMD_TXCMD register
  2. Write the argument to the CMD_TXARG register
  3. Set the CMD_TXENABLE bit in the Control register
  4. Wait until the CMD_TXENABLE bit disappears from the Status register
  5. 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:

  1. Write the command to the CMD_TXCMD register
  2. Write the argument to the CMD_TXARG register
  3. Write the expected number of response bytes (excluding CRC) in the CMD_RXSIZE register
  4. Set the CMD_TXENABLE and CMD_RXENABLE bits in the Control register
  5. Wait until the CMD_TXENABLE bit disappears from the Status register
  6. Wait until the CMD_TXBUSY bit disappears from the Status register
  7. Setup a timeout for the receiver
  8. While timeout did not elapse, check FIFO and copy response into memory. Stop if you've got all bytes you want
  9. 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:

  1. Set block size to physical block size of SD Card (in bytes)
  2. Set DMA address to where data is stored in memory
  3. Set the DAT_TXENABLE bit in the Control register
  4. Wait for DAT_TXENABLE to disappear from the Status register
  5. Wait for DAT_TXBUSY to disappear from the Status register
  6. 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:

  1. Write the buffer address (must be in external memory!) into the DAT_MEMADR register
  2. Write the SD card's physical block size in the DAT_BLKSIZE register
  3. Write the number of bytes you want to receive in the DAT_RXSIZE register
  4. Arm the data receiver by setting DAT_RXENABLE in the Control register
  5. Transmit and wait for the response to the data read command (SDMEM: cmd17 or cmd18)
  6. Setup the data timeout
  7. Wait while timeout did not elapse and DAT_RXBUSY in the Status register is not set
  8. If DAT_RXBUSY is set, wait for it to disappear (timeout error otherwise)
  9. If reading multiple blocks, sent a stop message
  10. 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




0000 (00h)


10-bit clock divider

0001 (01h)


Control register

0010 (02h)


Status register

0011 (03h)


Command transmitter command code

0100 (04h)


Command transmitter argument

0101 (05h)


Command Receiver size

0110 (06h)


Command Receiver FIFO

0111 (07h)


Data block size (in bytes)

1000 (08h)


Data transfer size

1001 (09h)


DMA address for data Read/Write

1111 (0Fh)


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.

Hardware wrapper and driver for the WB_SDHC, as part of a defined Software Platform.

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






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.

See Also

You are reporting an issue with the following selected text and/or image within the active document: