**这是本文档旧的修订版!**

SD cards are easily interfaceable with FPGAs. They come in different sizes (standard, mini and micro) but electrically they all work the same way. Let's focus on micro-SD cards since they are conveniently small and popular nowadays.

Micro-SD cards have 8 pins. First the power connection goes on pins 4 and 6.

Then, you need between three and six connections to FPGA pins depending on the mode of operation you decide to use.

SPI mode

In SPI mode, the DI/DO lines are unidirectional. That means:

  • No pull-up necessary on DI/DO
  • Commands (and sectors data when you do a sector write) are sent to the DI pin
  • Response (and sectors data when you do a sector read) are received from the DO pin

The SPI mode is often used in microcontroller systems. With an FPGA, we migh be better served with the…

SD modes

In SD modes, the CMD/DATx lines are bidirectional. That means:

  • Pull-ups are required on CMD/DATx (FPGAs can usually provide them internally)
  • Commands/response are sent/received on the CMD pin
  • Sectors data (for sector read and writes) are sent/received from the DATx pins

So for example, we need these connections in SD one-bit mode:

协议

SD cards work with a command/response scheme. For example, command “17” allows reading one sector (512 bytes) of the card memory. All communication is synchronous to a clock provided by the host (FPGA in our case). The clock should run below 400KHz at startup and can go faster after some card initialization.

All commands and most responses are 48bits long (6 bytes). Sector data come in multiples of 512 bytes. For example, here's a simple code that allows sending commands to the SD card.

// we use the Xylo-E FX2 FIFO2 as data source for "commanding" an SD card
// the SD card is used in one-bit SD mode
 
// first we are going to drive the SD card at a much slower speed than the FPGA itself
// let's create a "shift" signal that is asserted once every 64 clock periods
reg [5:0] cnt=0;  always @(posedge clk) cnt <= cnt+1;
reg shift=0;  always @(posedge clk) shift <= &cnt;
 
// now we serialize every byte we get from the FIFO2
reg [2:0] cntbit=0;
reg shifting=0;
reg [7:0] data=0;
always @(posedge clk) if(shift) shifting <= shifting ? ~(&cntbit & ~FIFO2_data_available) : FIFO2_data_available;
always @(posedge clk) if(shift & shifting) cntbit <= cntbit+1;
always @(posedge clk) if(shift) data <= (FIFO2_data_available & (~shifting | &cntbit)) ? FIFO_DATAIN : {data[6:0],1'b0};
assign FIFO_RD = shift & (~shifting | &cntbit);
 
// and send the serial data to the SD card
assign SD_CLK = cnt[5];
assign SD_CMD = shifting ? data[7] : 1'bZ;

Some commands have no reply, while some other will issue a response on the SD_DAT line. For example, to initialize the card, we start with a CMD0 followed by CMD8:

  • CMD0 “GOIDLESTATE”
  • CMD8 “SENDIFCOND”, response expected

Here's a session recorded using Xylo-E's demo software:

❌SD.exe USB driver opened CMD0 400000000095 CMD8 48000001AA87… OK CMD55 770000000065… OK CMD41 694018000019… OK CMD55 770000000065… OK CMD41 694018000019… OK SDHC/SDXC (high capacity) card CMD2 42000000004D… OK ASTC 3.4 CMD3 430000000021… OK RCA=0100 CMD7 4700010000DD… OK CMD13 4D0001000053… OK CMD17 510000000055… OK FAT32 detected Reading 1 sector(s) starting at 8192 CMD17 5100002000B1… OK Directory /

After some initialization, the card accepts CMD17 “READSINGLEBLOCK” so that files can be read from the card.

相关资源

Seabright技术公司的SD卡的协议 Wikipedia上关于SD卡的介绍. SD联盟的最新简化SD规范