-- indi16 vhdl -- ATA Disk Interface (PIO Mode) -- (C)2007 K Ring Technologies Semiconductor -- designed for 64/66MHz operation -- PIO Mode 4 ATA Interface -- Writes do not delay so long as 8 cycles are left between writes -- Reads do not delay also * cycles, but have a FIFO buffer -- so reading gives the last access, and shedules the next read ready for -- reading when the next read cycle happens. -- This requires blank reading sometimes, so reading the status register seems -- appropriate. Reads and writes are qued separate. LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY ata IS PORT ( -- Slave WISHBONE Classic interface (STB_I decoded) HLT_I : IN STD_LOGIC; RST_I : IN STD_LOGIC; CLK_I : IN STD_LOGIC; ADR_I : IN STD_LOGIC_VECTOR(15 DOWNTO 0); DAT_I : IN STD_LOGIC_VECTOR(15 DOWNTO 0); DAT_O : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); WE_I : IN STD_LOGIC; SEL_I : IN STD_LOGIC; STB_I : IN STD_LOGIC; ACK_O : OUT STD_LOGIC; CYC_I : IN STD_LOGIC; -- ATA Interface RESETN : OUT STD_LOGIC; DD : INOUT STD_LOGIC_VECTOR(15 DOWNTO 0); DMARQ : IN STD_LOGIC; --DMA Request DIOWN : OUT STD_LOGIC; DIORN : OUT STD_LOGIC; IORDY : IN STD_LOGIC; CSEL : OUT STD_LOGIC; -- Cable Select DMACKN : OUT STD_LOGIC; -- DMA ACK INTRQ : IN STD_LOGIC; -- Interrupt Request DA : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); CSN : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); DASPN : IN STD_LOGIC -- device active/slave present ); END ata; ARCHITECTURE a OF ata IS CONSTANT HiZ : STD_LOGIC_VECTOR(15 DOWNTO 0) := "ZZZZZZZZZZZZZZZZ"; SIGNAL Read, Write : STD_LOGIC_VECTOR(15 DOWNTO 0); -- CS1, CS0, DA2, DA1, DA0 SIGNAL Addr : STD_LOGIC_VECTOR(4 DOWNTO 0); SIGNAL Busy, Dir : STD_LOGIC; SIGNAL Seq : STD_LOGIC_VECTOR(2 DOWNTO 0); BEGIN DMACKN <= '1'; -- no dma ACK_O <= NOT Busy AND STB_I; DAT_O <= Read; -- process read and write via wishbone PROCESS(CLK_I, HLT_I, RST_I) BEGIN IF RST_I = '1' THEN Seq <= "000"; Busy <= '0'; RESETN <= '0'; DD <= HiZ; DIOWN <= '1'; DIORN <= '0'; ELSIF rising_edge(CLK_I) THEN RESETN <= '1'; IF Busy = '1' THEN -- must perform ATA CASE Seq IS WHEN "000" => -- set up address DA <= Addr(2 DOWNTO 0); CSN <= Addr(4 DOWNTO 3); Seq <= "001"; WHEN "001" => -- yes keep that address up Seq <= "010"; WHEN "010" => -- assert direction IF Dir = '1' THEN DIOWN <= '0'; ELSE DIORN <= '0'; END IF; Seq <= "011"; WHEN "011" => -- assert data out IF Dir = '1' THEN DD <= Write; END IF; Seq <= "100"; WHEN "100" => -- wait Seq <= "101"; WHEN "101" => -- check IORDY IF IORDY = '1' THEN Seq <= "110"; ELSE Seq <= "101"; END IF; WHEN "110" => -- latch in IF Dir = '0' THEN Read <= DD; END IF; Seq <= "110"; WHEN "111" => -- deasert direction DD <= HiZ; DIORN <= '1'; DIOWN <= '1'; Busy <= '0'; Seq <= "000"; END CASE; ELSE IF STB_I = '1' AND HLT_I = '0' THEN Busy <= '1'; Addr <= ADR_I(4 DOWNTO 0); Write <= DAT_I; Dir <= WE_I; END IF; END IF; END IF; END PROCESS; END a;