-------------------------------------------------
|
-------------------------------------------------
|
-- file: SdCmd-ea.vhdl
|
-- file: SdCmd-ea.vhdl
|
-- author: Rainer Kastl
|
-- author: Rainer Kastl
|
--
|
--
|
-- Low level sending commands and receiving responses
|
-- Low level sending commands and receiving responses
|
-- SD Spec 2.00
|
-- SD Spec 2.00
|
-------------------------------------------------
|
-------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
use ieee.math_real.all;
|
use ieee.math_real.all;
|
use work.Global.all;
|
use work.Global.all;
|
use work.Sd.all;
|
use work.Sd.all;
|
use work.CRCs.all;
|
use work.CRCs.all;
|
|
|
entity SdCmd is
|
entity SdCmd is
|
port (
|
port (
|
iClk : in std_ulogic; -- Clk, rising edge
|
iClk : in std_ulogic; -- Clk, rising edge
|
inResetAsync : in std_ulogic; -- Reset, asynchronous active low
|
inResetAsync : in std_ulogic; -- Reset, asynchronous active low
|
|
|
iCmdContent: in aSdCmdContent; -- Content to send to card
|
iCmdContent: in aSdCmdContent; -- Content to send to card
|
ioCmd : inout std_ulogic -- Cmd line to and from card
|
ioCmd : inout std_logic -- Cmd line to and from card
|
);
|
);
|
end entity SdCmd;
|
end entity SdCmd;
|
|
|
architecture Rtl of SdCmd is
|
architecture Rtl of SdCmd is
|
|
|
type aSdCmdState is (idle, startbit, transbit, cmdid, arg, crc, endbit);
|
type aSdCmdState is (idle, startbit, transbit, cmdid, arg, crc, endbit);
|
signal State, NextState : aSdCmdState;
|
signal State, NextState : aSdCmdState;
|
signal CrcClear, CrcDataIn : std_ulogic;
|
signal CrcClear, CrcDataIn : std_ulogic;
|
signal CrcData, SerialCrc : std_ulogic;
|
signal CrcData, SerialCrc : std_ulogic;
|
signal Counter, NextCounter : unsigned(integer(log2(real(32))) - 1 downto 0);
|
signal Counter, NextCounter : unsigned(integer(log2(real(32))) - 1 downto 0);
|
|
|
begin
|
begin
|
|
|
-- State register
|
-- State register
|
CmdStateReg : process (iClk, inResetAsync)
|
CmdStateReg : process (iClk, inResetAsync)
|
begin
|
begin
|
if inResetAsync = cInactivated then
|
if inResetAsync = cInactivated then
|
State <= endbit;
|
State <= idle;
|
Counter <= to_unsigned(0, Counter'length);
|
Counter <= to_unsigned(0, Counter'length);
|
elsif iClk'event and iClk = cActivated then
|
elsif iClk'event and iClk = cActivated then
|
State <= NextState;
|
State <= NextState;
|
|
Counter <= NextCounter;
|
end if;
|
end if;
|
end process CmdStateReg;
|
end process CmdStateReg;
|
|
|
-- Comb. process
|
-- Comb. process
|
NextStateAndOutput : process (iCmdContent, State)
|
NextStateAndOutput : process (iCmdContent, State, Counter)
|
|
|
procedure NextStateWhenAllSent (constant length : in natural; constant toState : in aSdCmdState) is
|
procedure NextStateWhenAllSent (constant length : in natural; constant toState : in aSdCmdState) is
|
begin
|
begin
|
if (NextCounter < length-1) then
|
if (NextCounter < length-1) then
|
NextCounter <= NextCounter + 1;
|
NextCounter <= NextCounter + 1;
|
else
|
else
|
NextCounter <= to_unsigned(0, NextCounter'length);
|
NextCounter <= to_unsigned(0, NextCounter'length);
|
NextState <= toState;
|
NextState <= toState;
|
end if;
|
end if;
|
end procedure NextStateWhenAllSent;
|
end procedure NextStateWhenAllSent;
|
|
|
|
|
|
|
procedure SendBitsAndCalcCrc (signal container : in std_ulogic_vector; constant toState : in aSdCmdState) is
|
procedure SendBitsAndCalcCrc (signal container : in std_ulogic_vector; constant toState : in aSdCmdState) is
|
begin
|
begin
|
ioCmd <= container(to_integer(NextCounter));
|
ioCmd <= container(to_integer(NextCounter));
|
CrcData <= container(to_integer(NextCounter));
|
CrcData <= container(to_integer(NextCounter));
|
CrcDataIn <= cActivated;
|
CrcDataIn <= cActivated;
|
NextStateWhenAllSent(container'length, toState);
|
NextStateWhenAllSent(container'length, toState);
|
end procedure SendBitsAndCalcCrc;
|
end procedure SendBitsAndCalcCrc;
|
|
|
|
|
begin
|
begin
|
NextState <= State;
|
NextState <= State;
|
NextCounter <= Counter;
|
NextCounter <= Counter;
|
ioCmd <= 'Z';
|
ioCmd <= 'Z';
|
CrcClear <= cInactivated;
|
CrcClear <= cInactivated;
|
CrcDataIn <= cInactivated;
|
CrcDataIn <= cInactivated;
|
CrcData <= cInactivated;
|
CrcData <= cInactivated;
|
|
|
case State is
|
case State is
|
when idle =>
|
when idle =>
|
-- todo: implement Sync. with host
|
-- todo: implement Sync. with host
|
NextState <= startbit;
|
NextState <= startbit;
|
|
CrcDataIn <= cActivated;
|
|
CrcData <= cSdStartBit;
|
|
|
when startbit =>
|
when startbit =>
|
ioCmd <= cSdStartBit;
|
ioCmd <= cSdStartBit;
|
NextState <= transbit;
|
NextState <= transbit;
|
|
CrcDataIn <= cActivated;
|
|
CrcData <= cSdTransBitHost;
|
|
|
when transbit =>
|
when transbit =>
|
ioCmd <= cSdTransBitHost;
|
ioCmd <= cSdTransBitHost;
|
NextState <= cmdid;
|
NextState <= cmdid;
|
|
CrcDataIn <= cActivated;
|
|
CrcData <= iCmdContent.id(to_integer(NextCounter));
|
|
|
when cmdid =>
|
when cmdid =>
|
SendBitsAndCalcCrc(iCmdContent.id, arg);
|
-- SendBitsAndCalcCrc(iCmdContent.id, arg);
|
|
ioCmd <= iCmdContent.id(to_integer(NextCounter));
|
|
if (NextCounter < iCmdContent.id'length-2) then
|
|
CrcData <= iCmdContent.id(to_integer(NextCounter)+1);
|
|
else
|
|
CrcData <= iCmdContent.arg(0);
|
|
end if;
|
|
CrcDataIn <= cActivated;
|
|
NextStateWhenAllSent(iCmdContent.id'length, arg);
|
|
|
|
|
when arg =>
|
when arg =>
|
SendBitsAndCalcCrc(iCmdContent.arg, crc);
|
-- SendBitsAndCalcCrc(iCmdContent.arg, crc);
|
|
ioCmd <= iCmdContent.arg(to_integer(NextCounter));
|
|
if (NextCounter < iCmdContent.arg'length-2) then
|
|
CrcData <= iCmdContent.arg(to_integer(NextCounter)+1);
|
|
CrcDataIn <= cActivated;
|
|
else
|
|
CrcDataIn <= cInactivated;
|
|
end if;
|
|
NextStateWhenAllSent(iCmdContent.arg'length, crc);
|
|
|
when crc =>
|
when crc =>
|
ioCmd <= SerialCrc;
|
ioCmd <= SerialCrc;
|
NextStateWhenAllSent(crc7'length, endbit);
|
NextStateWhenAllSent(crc7'length-1, endbit);
|
|
|
when endbit =>
|
when endbit =>
|
ioCmd <= cSdEndBit;
|
ioCmd <= cSdEndBit;
|
NextState <= idle; -- todo: receive response
|
NextState <= idle; -- todo: receive response
|
|
|
when others =>
|
when others =>
|
report "SdCmd: State not handled" severity error;
|
report "SdCmd: State not handled" severity error;
|
end case;
|
end case;
|
end process NextStateAndOutput;
|
end process NextStateAndOutput;
|
|
|
CRC7_inst: entity work.Crc
|
CRC7_inst: entity work.Crc
|
generic map(gPolynom => crc7)
|
generic map(gPolynom => crc7)
|
port map(iClk => iClk,
|
port map(iClk => iClk,
|
inResetAsync => inResetAsync,
|
inResetAsync => inResetAsync,
|
iClear => CrcClear,
|
iClear => CrcClear,
|
iDataIn => CrcDataIn,
|
iDataIn => CrcDataIn,
|
iData => CrcData,
|
iData => CrcData,
|
oSerial => SerialCrc);
|
oSerial => SerialCrc);
|
|
|
end architecture Rtl;
|
end architecture Rtl;
|
|
|