SDController.v should work with any FPGA, but it's been specifically tested and used with the ICE40 and the Yosys/icestorm toolchain.
Photon uses a 102 MHz clock and the SDR104 access mode with SDController.v, resulting in a read/write throughput of 48 MB/sec.
In theory SDController.v can support a faster clock, but the signal integrity of the ICE40 IO pads degrades significantly beyond 102 MHz when wired to an SD card.
input wire config_trigger, input wire config_action, input wire config_clkSpeed, input wire[3:0] config_clkDelay, input wire config_pinMode,
config_trigger
is toggled. There are only two options: Reset
and Init
. The Reset
action resets SDController.v to its default state (clock speed = slow, clock delay = none, pin mode = open drain).
The Init
action configures SDController.v to use the values from config_*
inputs, described below.
The slow clock is needed for SD card initialization; once initialized, the fast clock is enabled for maximum throughput.
This permits dynamic delay adjustment to account for FPGA signal delays.
For SD card initialization, open-drain IOs are used because SD cards expect 3.3V signalling at 400 kHz.
After SD card initialization, push-pull IOs are used for 1.8V signalling with the fast clock.
CMD18 / READ_MULTIPLE_BLOCK
and CMD25 / WRITE_MULTIPLE_BLOCK
: input wire cmd_trigger, input wire[47:0] cmd_data, input wire[1:0] cmd_respType, input wire[1:0] cmd_datInType, output wire cmd_done,
cmd_*
inputs must be settled when cmd_trigger
toggles There are three options: don't trigger DatIn, trigger DatIn for a 512x1 response (eg CMD6 response), or trigger DatIn for a 4096xN response (eg mass data read response)
output wire resp_done, output wire[135:0] resp_data, output wire resp_crcErr,
resp_*
signals are valid input wire datOut_trigger, output wire datOut_done, output wire datOut_crcErr, output wire datOutRead_clk, input wire datOutRead_ready, output wire datOutRead_trigger, input wire[15:0] datOutRead_data, input wire datOutRead_done,
datOutRead_data
should be updated with the next 16-bit word datOutRead_ready=0
output wire datIn_done, output wire datIn_crcErr, output wire datInWrite_rst, output wire datInWrite_clk, input wire datInWrite_ready, output wire datInWrite_trigger, output wire[15:0] datInWrite_data,
datInWrite_data
contains the next 16-bit word output wire status_dat0Idle
DAT[0]
SD card signal This is used by clients to poll the SD card for completion of various operations, such as CMD11 / VOLTAGE_SWITCH
and CMD12 / STOP_TRANSMISSION
.
This voltage-switching behavior is a pain to accomplish with FPGAs, but is possible with some discrete logic. Photon uses the following circuit to allow for low-speed (400 kHz) open-drain 3.3V signalling, in addition to high-speed (102 MHz) push-pull 1.8V signalling:
SD_PULLUP_1V8_EN_
float to 1
(by way of the pull-up resistor), which sets the source voltage for the six 20k pull-up resistors to 3.3V, allowing for 3.3V open-drain signalling. (Photon actually uses 2.8V as the high voltage, but that's within the acceptable range for SD card 3.3V signalling.) After SD card initialization, Photon drives SD_PULLUP_1V8_EN_
to 0
, which sets the source voltage for the six 20k pull-ups to 1.8V. In this mode, Photon operates the SD_*
signals in 1.8V push-pull mode.