Files
FireBee_SVN/FalconIO_SDCard_IDE_CF/WF_SDC_IF/sd-card-interface.vhd
aschi54 92c2ab95fc
2010-12-27 13:20:36 +00:00

228 lines
8.7 KiB
VHDL

----------------------------------------------------------------------
---- ----
---- ATARI IP Core peripheral Add-On ----
---- ----
---- This file is part of the FPGA-ATARI project. ----
---- http://www.experiment-s.de ----
---- ----
---- Description: ----
---- This hardware provides an interface to connect to a SD-Card. ----
---- ----
---- This interface is based on the project 'SatanDisk' of ----
---- Miroslav Nohaj 'Jookie'. The code is an interpretation of ----
---- the original code, written in VERILOG. It is provided for ----
---- the use in a system on programmable chips (SOPC). ----
---- ----
---- Timing: Use a clock frequency of 16MHz for this component. ----
---- Use the same clock frequency for the connected AVR ----
---- microcontroller. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2007 Wolfgang Foerster ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source is distributed in the hope that it will be ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
---- PURPOSE. See the GNU Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/lgpl.html ----
---- ----
----------------------------------------------------------------------
---- This hardware works with the original ATARI ----
---- hard dik driver. ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 1.0 2007/01/05 WF
-- Initial Release.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity WF_SD_CARD is
port (
-- System:
RESETn : in bit;
CLK : in bit; -- 16MHz, see above.
-- ACSI section:
ACSI_A1 : in bit;
ACSI_CSn : in bit;
ACSI_ACKn : in bit;
ACSI_INTn : out bit;
ACSI_DRQn : out bit;
ACSI_D : inout std_logic_vector(7 downto 0);
-- Microcontroller interface:
MC_D : inout std_logic_vector(7 downto 0);
MC_DO : in bit;
MC_PIO_DMAn : in bit;
MC_RWn : in bit;
MC_CLR_CMD : in bit;
MC_DONE : out bit;
MC_GOT_CMD : out bit
);
end WF_SD_CARD;
architecture BEHAVIOR of WF_SD_CARD is
signal DATA_REG : std_logic_vector(7 downto 0);
signal D0_REG : bit;
signal INT_REG : bit;
signal DRQ_REG : bit;
signal DONE_REG : bit;
signal GOT_CMD_REG : bit;
signal HOLD : bit;
signal PREV_CSn : bit;
signal PREV_ACKn : bit;
begin
MC_D <= DATA_REG when MC_RWn = '0' and DONE_REG = '1' else (others => 'Z');
ACSI_D <= DATA_REG when MC_RWn = '1' and (ACSI_CSn = '0' or ACSI_ACKn = '0' or HOLD = '1') else (others => 'Z');
ACSI_INTn <= INT_REG;
ACSI_DRQn <= DRQ_REG;
MC_DONE <= DONE_REG;
MC_GOT_CMD <= GOT_CMD_REG;
P_DATA: process(RESETn, CLK)
begin
if RESETn = '0' then
DATA_REG <= (others => '0');
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_RWn = '1' then
DATA_REG <= MC_D; -- Read from AVR to ACSI.
end if;
--
if PREV_CSn = '0' and ACSI_CSn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D; -- Write from ACSI to AVR.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and MC_RWn = '0' and DONE_REG = '0' then
DATA_REG <= ACSI_D; -- Write from ACSI to AVR.
end if;
end if;
end process P_DATA;
P_SYNC: process
begin
wait until CLK = '1' and CLK' event;
PREV_CSn <= ACSI_CSn;
PREV_ACKn <= ACSI_ACKn;
end process P_SYNC;
P_INT_DRQ: process(RESETn, CLK)
begin
if RESETn = '0' then
INT_REG <= '1'; -- No interrupt.
DRQ_REG <= '1'; -- No data request.
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' and MC_PIO_DMAn = '1' then -- Positive MC_DO edge.
INT_REG <= '0'; -- Release an interrupt.
DRQ_REG <= '1';
elsif D0_REG = '0' and MC_DO = '1' then
INT_REG <= '1';
DRQ_REG <= '0'; -- Release a data request.
end if;
--
if MC_CLR_CMD = '1' then -- Clear done.
INT_REG <= '1'; -- Restore INT_REG.
DRQ_REG <= '1'; -- Restore DRQ_REG.
end if;
--
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
if ACSI_CSn = '0' then
INT_REG <= '1';
end if;
--
if ACSI_ACKn = '0' then
DRQ_REG <= '1';
end if;
end if;
end if;
end process P_INT_DRQ;
P_HOLD: process(RESETn, CLK)
begin
if RESETn = '0' then
HOLD <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
HOLD <= '1';
elsif PREV_CSn = '1' and ACSI_CSn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_ACKn = '1' and ACSI_ACKn = '1' then -- If signal is high.
HOLD <= '0';
elsif PREV_CSn = '0' and ACSI_CSn = '1' then -- Rising edge.
HOLD <= '1';
elsif PREV_ACKn = '0' and ACSI_ACKn = '1' then -- Rising edge.
HOLD <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
HOLD <= '0';
end if;
end if;
end process P_HOLD;
P_DONE: process(RESETn, CLK)
begin
if RESETn = '0' then
DONE_REG <= '0';
elsif CLK = '1' and CLK' event then
if (PREV_CSn = '0' and ACSI_CSn = '0') or (PREV_ACKn = '0' and ACSI_ACKn = '0') then
DONE_REG <= '1';
elsif MC_CLR_CMD = '1' then -- Clear done.
DONE_REG <= '0';
elsif D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
DONE_REG <= '0';
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
DONE_REG <= '0';
end if;
end if;
end process P_DONE;
P_DO_REG: process(RESETn, CLK)
begin
if RESETn = '0' then
D0_REG <= '0';
elsif CLK = '1' and CLK' event then
if D0_REG = '0' and MC_DO = '1' then -- Positive MC_DO edge.
D0_REG <= MC_DO;
elsif D0_REG = '1' and MC_DO = '0' then -- Negative MC_DO edge.
D0_REG <= MC_DO;
end if;
end if;
end process P_DO_REG;
P_GOT_CMD: process(RESETn, CLK)
begin
if RESETn = '0' then
GOT_CMD_REG <= '0';
elsif CLK = '1' and CLK' event then
if PREV_CSn = '0' and ACSI_CSn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif PREV_ACKn = '0' and ACSI_ACKn = '0' and ACSI_CSn = '0' and ACSI_A1 = '0' then
GOT_CMD_REG <= '1'; -- If command was received.
elsif MC_CLR_CMD = '1' then -- Clear done.
GOT_CMD_REG <= '0';
end if;
end if;
end process P_GOT_CMD;
end architecture BEHAVIOR;