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模式

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

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:

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:

相关资源