When the XuLA2 was released, I still didn't have an easy-to-use controller module to interface the FPGA with the SD Flash card. But now I do and you can get it here.
Here's a block diagram that shows the various control signals and datapaths for the SD card controller module.
After looking at the diagram, maybe you're thinking that "easy-to-use" isn't the best adjective to apply to this module. But it's really pretty simple:
- Set-up:
First of all, you have to give the controller a clock signal on the
clk_i
input with a higher frequency than the serial clock sent to the SD card through thesclk_o
output. You can set generic parameters for the controller to tell it the master clock frequency (100 MHz), the SCLK frequency for initialization (400 KHz), the SCLK frequency for normal operation (25 MHz), the size of data sectors in the Flash memory (512 bytes), and the type of card (either SD or SDHC). I typically use a 100 MHz clock if I'm running an SD card with a 25 Mbps serial data stream.- Initialize it:
Pulsing the
reset_i
input high and then bringing it low again will make the controller initialize the SD card so it will work in SPI mode. Basically, it sends the card the commandsCMD0
,CMD8
, and thenACMD41
(which isCMD55
followed byCMD41
). Thebusy_o
output will be high during the initialization and will go low once it is done.After the initialization command sequence, the SD card will send back an
R1
response byte. If only theIDLE
bit of theR1
response is set, then the controller will repeatedly re-try theACMD41
command whilebusy_o
remains high.If any other bit of the
R1
response is set, then an error occurred. The controller will stall, lowerbusy_o
, and output theR1
response code on theerror_o
bus. You'll have to pulsereset_i
to unfreeze the controller.If the
R1
response is all zeroes (i.e., no errors occurred during the initialization), then the controller will lowerbusy_o
and wait for a read or write operation from the host. The controller will only accept new operations whenbusy_o
is low.- Write data:
To write a data block to the SD card, the address of a block is placed on the
addr_i
input bus and thewr_i
input is raised. The address and write strobe can be removed oncebusy_o
goes high to indicate the write operation is underway. The data to be written to the SD card is passed as follows:- The controller requests a byte of data by raising the
hndShk_o
output. - The host applies the next byte to the
data_i
input bus and raises thehndShk_i
input. - The controller accepts the byte and lowers the
hndShk_o
output. - The host lowers the
hndShk_i
input.
This sequence of steps is repeated until all
BLOCK_SIZE_G
bytes of the data block are passed from the host to the controller. Once all the data is passed, the sector on the SD card will be written and thebusy_o
output will be lowered.- The controller requests a byte of data by raising the
- Read data:
To read a block of data from the SD card, the address of a block is placed on the
addr_i
input bus and therd_i
input is raised. The address and read strobe can be removed oncebusy_o
goes high to indicate the read operation is underway. The data read from the SD card is passed to the host as follows:- The controller raises the
hndShk_o
output when the next data byte is available. - The host reads the byte from the
data_o
output bus and raises thehndShk_i
input. - The controller lowers the
hndShk_o
output. - The host lowers the
hndShk_i
input.
This sequence of steps is repeated until all
BLOCK_SIZE_G
bytes of the data block are passed from the controller to the host. Once all the data is read, thebusy_o
output will be lowered.- The controller raises the
- Handle errors:
If an error is detected during either a read or write operation, then the controller will stall, lower
busy_o
, and output an error code on theerror_o
bus. You'll have to pulsereset_i
to unfreeze the controller. That may seem a bit excessive, but it does guarantee that you can't ignore any errors that occur.
The SD card controller was successfully tested with a 2GB Sandisk SD card, a 4GB Sandisk SDHC card, and a 4GB Kingston SDHC card. The controller module was also ported to the original XuLA and tested using the setup shown below.