Files
MultiComp_MiSTer/Components/SDCARD/sd_controller.vhd
2024-12-08 09:58:13 -05:00

571 lines
17 KiB
VHDL

-- VHDL SD card interface
-- Reads and writes a single block of data as a data stream
-- Adapted from design by Steven J. Merrifield, June 2008
-- Read states are derived from the Apple II emulator by Stephen Edwards
-- This version of the code contains modifications copyright by Grant Searle 2013
-- You are free to use this file in your own projects but must never charge for it nor use it without
-- acknowledgement.
-- Please ask permission from Grant Searle before republishing elsewhere.
-- If you use this file or any part of it, please add an acknowledgement to myself and
-- a link back to my main web site http://searle.hostei.com/grant/
-- and to the "multicomp" page at http://searle.hostei.com/grant/Multicomp/index.html
--
-- Please check on the above web pages to see if there are any updates before using this file.
-- If for some reason the page is no longer available, please search for "Grant Searle"
-- on the internet to see if I have moved to another web hosting service.
--
-- Grant Searle
-- eMail address available on my main web page link above.
-- Minor changes by foofoobedoo@gmail.com
-- Additional functionality to provide SDHC support and 25 MHz SPI-clock by Rienk Koolstra.
--
-- This design uses the SPI interface and supports "standard capacity" (SDSC) and
-- "high capacity" (SDHC) cards.
-- Address Register
-- 0 SDDATA read/write data
-- 1 SDSTATUS read
-- 1 SDCONTROL write
-- 2 SDLBA0 write-only
-- 3 SDLBA1 write-only
-- 4 SDLBA2 write-only (only bits 6:0 are valid)
--
-- For both SDSC and SDHC (high capacity) cards, the block size is 512bytes (9-bit value) and the
-- SDLBA registers select the block number. SDLBA2 is most significant, SDLBA0 is least significant.
--
-- For SDSC, the read/write address parameter is a 512-byte aligned byte address. ie, it has 9 low
-- address bits explicitly set to 0. 23 of the 24 programmable address bits select the 512-byte block.
-- This gives an address capacity of 2^23 * 512 = 4GB .. BUT maximum SDSC capacity is 2GByte.
--
-- The SDLBA registers are used like this:
--
-- 31 30 29 28.27 26 25 24.23 22 21 20.19 18 17 16.15 14 13 12.11 10 09 08.07 06 05 04.03 02 01 00
--+------- SDLBA2 -----+------- SDLBA1 --------+------- SDLBA0 --------+ 0 0 0 0 0 0 0 0 0
--
-- For SDHC cards, the read/write address parameter is the ordinal number of 512-byte block ie, the
-- 9 low address bits are implicity 0. The 24 programmable address bits select the 512-byte block.
-- This gives an address capacity of 2^24 * 512 = 8GByte. SDHC can be upto 32GByte but this design
-- can only access the low 8GByte (could add SDLBA3 to get the extra address lines if required).
--
-- The SDLBA registers are used like this:
--
-- 31 30 29 28.27 26 25 24.23 22 21 20.19 18 17 16.15 14 13 12.11 10 09 08.07 06 05 04.03 02 01 00
-- 0 0 0 0 0 0 0 0+---------- SDLBA2 -----+------- SDLBA1 --------+------- SDLBA0 --------+
--
-- The end result of all this is that the addressing looks the same for SDSC and SDHC cards.
--
-- SDSTATUS (RO)
-- b7 Write Data Byte can be accepted
-- b6 Read Data Byte available
-- b5 Block Busy
-- b4 Init Busy
-- b3 Unused. Read 0
-- b2 Unused. Read 0
-- b1 Unused. Read 0
-- b0 Unused. Read 0
--
-- SDCONTROL (WO)
-- b7:0 0x00 Read block
-- 0x01 Write block
--
--
-- To read a 512-byte block from the SDCARD:
-- Wait until SDSTATUS=0x80 (ensures previous cmd has completed)
-- Write SDLBA0, SDLBA1 SDLBA2 to select block index to read from
-- Write 0 to SDCONTROL to issue read command
-- Loop 512 times:
-- Wait until SDSTATUS=0xE0 (read byte ready, block busy)
-- Read byte from SDDATA
--
-- To write a 512-byte block to the SDCARD:
-- Wait until SDSTATUS=0x80 (ensures previous cmd has completed)
-- Write SDLBA0, SDLBA1 SDLBA2 to select block index to write to
-- Write 1 to SDCONTROL to issue write command
-- Loop 512 times:
-- Wait until SDSTATUS=0xA0 (block busy)
-- Write byte to SDDATA
--
-- At HW level each data transfer is 515 bytes: a start byte, 512 data bytes,
-- 2 CRC bytes. CRC need not be valid in SPI mode, *except* for CMD0.
--
-- SDCARD specification can be downloaded from
-- https://www.sdcard.org/downloads/pls/
-- All you need is the "Part 1 Physical Layer Simplified Specification"
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity sd_controller is
generic (
constant CLKEDGE_DIVIDER : integer := 100 -- 50MHz / 100 gives edges at 500kHz ie output
-- or sdSCLK of 250kHz to be used during init phase
);
port (
sdCS : out std_logic;
sdMOSI : out std_logic;
sdMISO : in std_logic;
sdSCLK : out std_logic;
n_reset : in std_logic;
n_rd : in std_logic;
n_wr : in std_logic;
dataIn : in std_logic_vector(7 downto 0);
dataOut : out std_logic_vector(7 downto 0);
regAddr : in std_logic_vector(2 downto 0);
clk : in std_logic;
driveLED : out std_logic := '1'
);
end sd_controller;
architecture rtl of sd_controller is
type states is (
rst,
init,
cmd0,
cmd8,
cmd55,
acmd41,
poll_cmd,
cmd58,
cardsel,
idle, -- wait for read or write pulse
read_block_cmd,
read_block_wait,
read_block_data,
send_cmd,
send_regreq,
receive_ocr_wait,
receive_byte_wait,
receive_byte,
write_block_cmd,
write_block_init, -- initialise write command
write_block_data, -- loop through all data bytes
write_block_byte, -- send one byte
write_block_wait -- wait until not busy
);
-- one start byte, plus 512 bytes of data, plus two ff end bytes (crc)
constant write_data_size : integer := 515;
signal state, return_state : states;
signal sclk_sig : std_logic := '0';
signal cmd_out : std_logic_vector(55 downto 0);
-- at different times holds 8-bit data, 8-bit R1 response or 40-bit R7 response
signal recv_data : std_logic_vector(39 downto 0);
signal clkCount : std_logic_vector(5 downto 0);
signal clkEn : std_logic;
signal HighSpeed : std_logic := '0'; -- flag to switch to 25 MHz operation and back
signal status : std_logic_vector(7 downto 0) := x"00";
signal block_read : std_logic := '0';
signal block_write : std_logic := '0';
signal block_start_ack : std_logic := '0';
signal cmd_mode : std_logic := '1';
signal response_mode : std_logic := '1';
signal data_sig : std_logic_vector(7 downto 0) := x"00";
signal din_latched : std_logic_vector(7 downto 0) := x"00";
signal dout : std_logic_vector(7 downto 0) := x"00";
signal sdhc : std_logic := '0';
signal sd_read_flag : std_logic := '0';
signal host_read_flag : std_logic := '0';
signal sd_write_flag : std_logic := '0';
signal host_write_flag : std_logic := '0';
signal init_busy : std_logic := '1';
signal block_busy : std_logic := '0';
signal address: std_logic_vector(31 downto 0) :=x"00000000";
signal led_on_count : integer range 0 to 200;
begin
clock_enable: process(clk)
begin
if rising_edge(clk) then
if clkCount < (CLKEDGE_DIVIDER - 1) then
clkCount <= clkCount + 1;
else
clkCount <= (others=>'0');
end if;
end if;
end process;
clkEn <= '1' when ( clkCount = 0 ) or ( HighSpeed = '1' ) else '0';
wr_adrs_reg: process(n_wr)
begin
-- sdsc address 0..8 (first 9 bits) always zero because each sector is 512 bytes
if rising_edge(n_wr) then
if sdhc = '0' then -- SDSC card
if regAddr = "010" then
address(16 downto 9) <= dataIn;
elsif regAddr = "011" then
address(24 downto 17) <= dataIn;
elsif regAddr = "100" then
address(31 downto 25) <= dataIn(6 downto 0);
end if;
else -- SDHC card
-- SDHC address is the 512 bytes block address. starts at bit 0
if regAddr = "010" then
address(7 downto 0) <= dataIn; -- 128 k
elsif regAddr = "011" then
address(15 downto 8) <= dataIn; -- 32 M
elsif regAddr = "100" then
address(23 downto 16) <= dataIn; -- addresses upto 8 G
end if;
end if;
end if;
end process;
-- output data is MUXed externally based on CS so only need to
-- drive 0 by default if dataOut is being ORed externally
dataOut <= dout when regAddr = "000" else
status when regAddr = "001" else
x"00";
wr_dat_reg: process(n_wr)
begin
if rising_edge(n_wr) then
if (regAddr = "000") and (sd_write_flag = host_write_flag) then
din_latched <= dataIn;
host_write_flag <= not host_write_flag;
end if;
end if;
end process;
rd_dat_reg: process(n_rd)
begin
if rising_edge(n_rd) then
if (regAddr = "000") and (sd_read_flag /= host_read_flag) then
host_read_flag <= not host_read_flag;
end if;
end if;
end process;
wr_cmd_reg: process(n_wr, block_start_ack,init_busy)
begin
if init_busy='1' or block_start_ack='1' then
block_read <= '0';
block_write <= '0';
elsif rising_edge(n_wr) then
if regAddr = "001" and dataIn = "00000000" then
block_read <= '1';
end if;
if regAddr = "001" and dataIn = "00000001" then
block_write <= '1';
end if;
end if;
end process;
fsm: process(clk, clkEn, n_reset)
variable byte_counter : integer range 0 to write_data_size;
variable bit_counter : integer range 0 to 160;
begin
if (n_reset='0') then
state <= rst;
sclk_sig <= '0';
sdCS <= '1';
HighSpeed <= '0';
elsif rising_edge(clk) and clkEn = '1' then
case state is
when rst =>
-- HighSpeed <= '0';
sd_read_flag <= host_read_flag;
sd_write_flag <= host_write_flag;
sclk_sig <= '0';
cmd_out <= (others => '1');
byte_counter := 0;
cmd_mode <= '1'; -- 0=data, 1=command
response_mode <= '1'; -- 0=data, 1=command
bit_counter := 160;
sdCS <= '1';
state <= init;
init_busy <= '1';
block_start_ack <= '0';
when init => -- cs=1, send 80 clocks, cs=0
if (bit_counter = 0) then
sdCS <= '0';
state <= cmd0;
else
bit_counter := bit_counter - 1;
sclk_sig <= not sclk_sig;
end if;
when cmd0 =>
cmd_out <= x"ff400000000095"; -- GO_IDLE_STATE here, Select SPI
bit_counter := 55;
return_state <= cmd8;
state <= send_cmd;
when cmd8 =>
cmd_out <= x"ff48000001aa87"; -- SEND_IF_COND
bit_counter := 55;
return_state <= cmd55;
state <= send_regreq;
-- cmd55 is the "prefix" command for ACMDs
when cmd55 =>
cmd_out <= x"ff770000000001"; -- APP_CMD
bit_counter := 55;
return_state <= acmd41;
state <= send_cmd;
when acmd41 =>
cmd_out <= x"ff694000000077"; -- SD_SEND_OP_COND
bit_counter := 55;
return_state <= poll_cmd;
state <= send_cmd;
when poll_cmd =>
if (recv_data(0) = '0') then
state <= cmd58;
else
-- still busy; go round and do it again
state <= cmd55;
end if;
when cmd58 =>
cmd_out <= x"ff7a00000000fd"; -- READ_OCR
bit_counter := 55;
return_state <= cardsel;
state <= send_regreq;
when cardsel =>
if (recv_data(31) = '0' ) then -- power up not completed
state <= cmd58;
else
sdhc <= recv_data(30); -- CCS bit
state <= idle;
end if;
when idle =>
HighSpeed <= '1';
sd_read_flag <= host_read_flag;
sd_write_flag <= host_write_flag;
sclk_sig <= '0';
cmd_out <= (others => '1');
data_sig <= (others => '1');
byte_counter := 0;
cmd_mode <= '1'; -- 0=data, 1=command
response_mode <= '1'; -- 0=data, 1=command
block_busy <= '0';
init_busy <= '0';
dout <= (others => '0');
if (block_read = '1') then
state <= read_block_cmd;
block_start_ack <= '1';
elsif (block_write='1') then
state <= write_block_cmd;
block_start_ack <= '1';
else
state <= idle;
end if;
when read_block_cmd =>
block_busy <= '1';
block_start_ack <= '0';
cmd_out <= x"ff" & x"51" & address & x"ff"; -- CMD17 read single block
bit_counter := 55;
return_state <= read_block_wait;
state <= send_cmd;
-- wait until data token read (= 11111110)
when read_block_wait =>
if (sclk_sig='0' and sdMISO='0') then
state <= receive_byte;
byte_counter := 513; -- data plus crc
bit_counter := 8; -- ???????????????????????????????
return_state <= read_block_data;
end if;
sclk_sig <= not sclk_sig;
when read_block_data =>
if (byte_counter = 1) then -- crc byte 1 - ignore
byte_counter := byte_counter - 1;
return_state <= read_block_data;
bit_counter := 7;
state <= receive_byte;
elsif (byte_counter = 0) then -- crc byte 2 - ignore
bit_counter := 7;
return_state <= idle;
state <= receive_byte;
elsif (sd_read_flag /= host_read_flag) then
state <= read_block_data; -- stay here until previous byte read
else
byte_counter := byte_counter - 1;
return_state <= read_block_data;
bit_counter := 7;
state <= receive_byte;
end if;
when send_cmd =>
if (sclk_sig = '1') then -- sending command
if (bit_counter = 0) then -- command sent
state <= receive_byte_wait;
else
bit_counter := bit_counter - 1;
cmd_out <= cmd_out(54 downto 0) & '1';
end if;
end if;
sclk_sig <= not sclk_sig;
when send_regreq =>
if (sclk_sig = '1') then -- sending command
if (bit_counter = 0) then -- command sent
state <= receive_ocr_wait;
else
bit_counter := bit_counter - 1;
cmd_out <= cmd_out(54 downto 0) & '1';
end if;
end if;
sclk_sig <= not sclk_sig;
when receive_ocr_wait =>
if (sclk_sig = '0') then
if (sdMISO = '0') then -- wait for zero bit
recv_data <= (others => '0');
bit_counter := 38; -- already read bit 39
state <= receive_byte;
end if;
end if;
sclk_sig <= not sclk_sig;
when receive_byte_wait =>
if (sclk_sig = '0') then
if (sdMISO = '0') then -- wait for start bit
recv_data <= (others => '0');
if (response_mode='0') then -- data mode
bit_counter := 3; -- already read bits 7..4
else -- command mode
bit_counter := 6; -- already read bit 7 (start bit)
end if;
state <= receive_byte;
end if;
end if;
sclk_sig <= not sclk_sig;
-- read 8-bit data or 8-bit R1 response or 40-bit R7 response
when receive_byte =>
if (sclk_sig = '0') then
recv_data <= recv_data(38 downto 0) & sdMISO; -- read next bit
if (bit_counter = 0) then
state <= return_state;
-- if real data received then flag it (byte counter = 0 for both crc bytes)
if return_state= read_block_data and byte_counter > 0 then
sd_read_flag <= not sd_read_flag;
dout <= recv_data(7 downto 0);
end if;
else
bit_counter := bit_counter - 1;
end if;
end if;
sclk_sig <= not sclk_sig;
when write_block_cmd =>
block_busy <= '1';
block_start_ack <= '0';
cmd_mode <= '1';
cmd_out <= x"ff" & x"58" & address & x"ff"; -- CMD24 write single block
bit_counter := 55;
return_state <= write_block_init;
state <= send_cmd;
when write_block_init =>
cmd_mode <= '0';
byte_counter := write_data_size;
state <= write_block_data;
when write_block_data =>
if byte_counter = 0 then
state <= receive_byte_wait;
return_state <= write_block_wait;
response_mode <= '0';
else
if ((byte_counter = 2) or (byte_counter = 1)) then
data_sig <= x"ff"; -- two crc bytes
bit_counter := 7;
state <= write_block_byte;
byte_counter := byte_counter - 1;
elsif byte_counter = write_data_size then
data_sig <= x"fe"; -- start byte, single block
bit_counter := 7;
state <= write_block_byte;
byte_counter := byte_counter - 1;
elsif host_write_flag /= sd_write_flag then -- only send if flag set
data_sig <= din_latched;
bit_counter := 7;
state <= write_block_byte;
byte_counter := byte_counter - 1;
sd_write_flag <= not sd_write_flag;
end if;
end if;
when write_block_byte =>
if (sclk_sig = '1') then
if bit_counter=0 then
state <= write_block_data;
else
data_sig <= data_sig(6 downto 0) & '1';
bit_counter := bit_counter - 1;
end if;
end if;
sclk_sig <= not sclk_sig;
when write_block_wait =>
cmd_mode <= '1';
response_mode <= '1';
if sclk_sig='0' then
if sdMISO='1' then
state <= idle;
end if;
end if;
sclk_sig <= not sclk_sig;
when others =>
state <= idle;
end case;
end if;
end process;
sdSCLK <= sclk_sig;
sdMOSI <= cmd_out(55) when cmd_mode='1' else data_sig(7);
status(7) <= '1' when host_write_flag=sd_write_flag else '0'; -- tx byte empty when equal
status(6) <= '0' when host_read_flag=sd_read_flag else '1'; -- rx byte ready when not equal
status(5) <= block_busy;
status(4) <= init_busy;
-- Make sure the drive LED is on for a visible amount of time
ctl_led: process (clk, block_busy,init_busy)
begin
if block_busy='1' or init_busy = '1' then
led_on_count <= 200; -- ensure on for at least 200ms (assuming 1MHz clk)
driveLED <= '0';
elsif (rising_edge(clk)) then
if led_on_count>0 then
led_on_count <= led_on_count-1;
driveLED <= '0';
else
driveLED <= '1';
end if;
end if;
end process;
end rtl;