OpenCores
URL https://opencores.org/ocsvn/sdhc-sc-core/sdhc-sc-core/trunk

Subversion Repositories sdhc-sc-core

[/] [sdhc-sc-core/] [trunk/] [grpSd/] [unitSdCmd/] [src/] [SdCmd-Rtl-ea.vhdl] - Rev 185

Compare with Previous | Blame | View Log

-- SDHC-SC-Core
-- Secure Digital High Capacity Self Configuring Core
-- 
-- (C) Copyright 2010, Rainer Kastl
-- All rights reserved.
-- 
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--     * Redistributions of source code must retain the above copyright
--       notice, this list of conditions and the following disclaimer.
--     * Redistributions in binary form must reproduce the above copyright
--       notice, this list of conditions and the following disclaimer in the
--       documentation and/or other materials provided with the distribution.
--     * Neither the name of the <organization> nor the
--       names of its contributors may be used to endorse or promote products
--       derived from this software without specific prior written permission.
-- 
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  "AS IS" AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- 
-- File        : SdCmd-Rtl-ea.vhdl
-- Owner       : Rainer Kastl
-- Description : FSM for low level sending of SD commands and receiving responses
-- Links       : SD Spec 2.00
-- 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.Global.all;
use work.Sd.all;
use work.CRCs.all;
 
entity SdCmd is
	port (
		iClk         : in std_ulogic; -- Clk, rising edge
		iRstSync     : in std_ulogic; -- Reset, synchronous active high
 
		iStrobe      : in std_ulogic; -- Strobe to send data
 
		iFromController : in aSdCmdFromController;
		oToController   : out aSdCmdToController;
 
		-- SDCard
		iCmd : in aiSdCmd;
		oCmd : out aoSdCmd
	);
end entity SdCmd;
 
architecture Rtl of SdCmd is
 
	type aSdCmdState is (idle, sending, receiving);
	type aRegion is (startbit, transbit, cmdid, arg, cid, crc, endbit, waitstate);
 
	subtype aCounter is unsigned(integer(log2(real(128))) - 1 downto 0);
 
	type aRegSet is record
		State         : aSdCmdState;
		Region        : aRegion;
		Counter       : aCounter;
		ReceivedToken : aSdCmdToken;
		Cid           : aSdRegCID;
	end record aRegSet;
 
	constant cDefaultRegSet : aRegSet := (
	State         => idle,
	Region        => startbit,
	Counter       => to_unsigned(0, aCounter'length),
	ReceivedToken => cDefaultSdCmdToken,
	Cid           => cDefaultSdRegCID);
 
	type aOutputRegSet is record
		Controller : aSdCmdToController;
		Cmd        : aoSdCmd;
	end record aOutputRegSet;
 
	constant cDefaultOutputRegSet : aOutputRegSet := (
	Controller => cDefaultSdCmdToController,
	Cmd => (Cmd       => '0',
	En         => '0'));
 
	type aCrcOut is record
		Clear  : std_ulogic;
		DataIn : std_ulogic;
		Data   : std_ulogic;
	end record aCrcOut;
 
	constant cDefaultCrcOut : aCrcOut := (
	Clear  => cInactivated,
	DataIn => cInactivated,
	Data   => cInactivated);
 
	signal SerialCrc, CrcCorrect : std_ulogic;
	signal CrcOut : aCrcOut;
 
	signal R, NextR : aRegSet;
	signal O, NextO : aOutputRegSet;
 
begin
 
	oToController <= O.Controller;
	oCmd <= O.Cmd;
 
	-- State register
	CmdStateReg : process (iClk)
	begin
		if iClk'event and iClk = cActivated then
			if iRstSync = cActivated then
				R <= cDefaultRegSet;
				O <= cDefaultOutputRegSet;
			else
 
				if (iStrobe = cActivated) then
					R <= NextR;
					O <= NextO;
				end if;
			end if;
		end if;
	end process CmdStateReg;
 
	-- Comb. process
	NextStateAndOutput : process (iFromController, iCmd.Cmd, SerialCrc, CrcCorrect, iStrobe, R)
 
		procedure NextStateWhenAllSent (constant nextlength : in natural; constant toRegion : in aRegion) is
		begin
			if (R.Counter > 0) then
				NextR.Counter <= R.Counter - 1;
			else
				NextR.Counter <= to_unsigned(nextlength, NextR.Counter'length);
				NextR.Region <= toRegion;
			end if;
		end procedure NextStateWhenAllSent;
 
		procedure ShiftIntoCrc(constant data : in std_ulogic) is
		begin
			CrcOut.DataIn <= cActivated;
			CrcOut.Data   <= data;
		end procedure;
 
		procedure SendBitsAndCalcCrc (signal container : in std_ulogic_vector; constant toRegion : in aRegion; constant nextlength : in natural) is
		begin
			NextO.Cmd.En  <= cActivated;
			NextO.Cmd.Cmd <= container(to_integer(R.Counter));
 
			ShiftIntoCrc(container(to_integer(R.Counter)));
			NextStateWhenAllSent(nextlength, toRegion);
		end procedure SendBitsAndCalcCrc;
 
		procedure RecvBitsAndCalcCrc (signal container : out std_ulogic_vector;	constant toRegion : in aRegion; constant nextlength : in natural) is
		begin
			container(to_integer(R.Counter)) <= iCmd.Cmd;		
			ShiftIntoCrc(iCmd.Cmd);
			NextStateWhenAllSent(nextlength, toRegion);
		end procedure RecvBitsAndCalcCrc;
 
	begin
		-- defaults
		NextR                    <= R;
		NextO                    <= cDefaultOutputRegSet;
		NextO.Controller.Content <= R.ReceivedToken.content;
		NextO.Controller.Cid     <= R.Cid;
		CrcOut                   <= cDefaultCrcOut;
 
		case R.State is
			when idle => 
					-- Start receiving or start transmitting
				if (iCmd.Cmd = cSdStartBit) then
					-- Start receiving
					ShiftIntoCrc(iCmd.Cmd);
 
					NextR.ReceivedToken.startbit <= iCmd.Cmd;
					NextR.State                  <= receiving;
					NextR.Region                 <= transbit;
 
				elsif (iFromController.Valid = cActivated) then
					-- Start sending
					NextR.State  <= sending;
					NextR.Region <= startbit;
 
				end if;
 
			when sending => 
				NextO.Cmd.En <= cActivated;
 
				case R.Region is
					when startbit =>
						NextO.Cmd.Cmd  <= cSdStartBit;
						NextR.Region <= transbit;
						ShiftIntoCrc(cSdStartBit);
 
					when transbit => 
						NextO.Cmd.Cmd   <= cSdTransBitHost;
						NextR.Counter <= to_unsigned(iFromController.Content.id'high, aCounter'length);
						NextR.Region <= cmdid;
						ShiftIntoCrc(cSdTransBitHost);
 
					when cmdid => 
						SendBitsAndCalcCrc(iFromController.Content.id, arg,	iFromController.Content.arg'high);
 
					when arg => 
						SendBitsAndCalcCrc(iFromController.Content.arg, crc, crc7'high-1);
 
					when crc => 
						NextO.Cmd.Cmd <= SerialCrc;
 
						if (R.Counter > 0) then
							NextR.Counter <= R.Counter - 1;
 
						else
							NextR.Region         <= endbit;
							NextO.Controller.Ack <= cActivated;
						end if;
 
					when endbit => 
						NextO.Cmd.Cmd <= cSdEndBit;
						NextR.Region  <= waitstate;
 
					when waitstate => 
						NextO.Cmd.En <= cInactivated;
						NextR.State  <= idle;
						NextR.Region <= startbit;
 
					when others => 
						report "SdCmd: Region not handled" severity error;
 
				end case;
 
			when receiving => 
				NextO.Controller.Receiving   <= cActivated;
 
				case R.Region is
					when transbit => 
						NextR.ReceivedToken.transbit <= iCmd.Cmd;
						NextR.Counter <= to_unsigned(NextR.ReceivedToken.Content.id'high, NextR.Counter'length);
						NextR.Region <= cmdid;
						ShiftIntoCrc(iCmd.Cmd);
 
					when cmdid => 
						if (iFromController.ExpectCID = cInactivated) then
							RecvBitsAndCalcCrc(NextR.ReceivedToken.Content.id, arg, NextR.ReceivedToken.Content.arg'high);
 
						elsif (iFromController.ExpectCID = cActivated) then
							RecvBitsAndCalcCrc(NextR.ReceivedToken.Content.id, cid, cCIDLength-8);
							CrcOut.Clear <= cActivated;
 
						end if;
 
					when arg => 
						RecvBitsAndCalcCrc(NextR.ReceivedToken.Content.arg, crc, crc7'high-1);
 
					when cid => 
						NextR.Cid <= UpdateCID(R.Cid, iCmd.Cmd, to_integer(R.Counter)+8);
						ShiftIntoCrc(iCmd.Cmd);
						NextStateWhenAllSent(crc7'high-1, crc);
 
					when crc => 
						NextR.ReceivedToken.crc7(to_integer(R.Counter)) <= iCmd.Cmd;
						ShiftIntoCrc(iCmd.Cmd);
 
						if (R.Counter > 0) then
							NextR.Counter <= R.Counter - 1;
						else
							NextR.Region <= endbit;
						end if;
 
					when endbit => 
						NextR.ReceivedToken.endbit <= iCmd.Cmd;
 
							-- check 
						if (iFromController.CheckCrc = cActivated) then
							if (CrcCorrect = cActivated and R.ReceivedToken.transbit = cSdTransBitSlave) then
								NextO.Controller.Valid <= cActivated;
 
							else
								NextO.Controller.Err <= cActivated;
 
							end if;
						else 
							NextO.Controller.Valid <= cActivated;
						end if;
 
						NextR.State <= idle;
						NextR.Region <= startbit;
 
					when others => 
						report "SdCmd : Region not handled" severity error;
 
				end case;
 
			when others => 
				report "SdCmd: State not handled" severity error;
 
		end case;
 
	end process NextStateAndOutput;
 
	CRC7_inst: entity work.Crc
	generic map(
		gPolynom => crc7)
	port map(
		iClk         => iClk,
		iRstSync     => iRstSync,
		iClear		 => CrcOut.Clear,
		iStrobe      => iStrobe,
		iDataIn      => CrcOut.DataIn,
		iData        => CrcOut.Data,
		oIsCorrect   => CrcCorrect,
		oSerial      => SerialCrc);
 
end architecture Rtl;	
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.