---------------------------------------------------------------------------- -- IEEE1284 interface IP(intellectual property) core. Version 0.1 -- (C)Copyright 2002-2003 Nahitafu Nahitech -- http://www.nahitech.com/nahitafu/ ---------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity IEEE1284Main is Port ( CLK : in std_logic; RESET : in std_logic; DataAvail : in std_logic; -- Status of user data available DataReq : out std_logic; -- Host requires periph's data DataReceived : out std_logic; -- Data received from host DataWr : in std_logic; -- Strobe to write user data to host Busy : in std_logic; -- Peripheral busy Data_IN : in std_logic_vector(7 downto 0); Data_OUT : out std_logic_vector(7 downto 0); IEEE1284_DIN : in std_logic_vector(7 downto 0); IEEE1284_DOUT : out std_logic_vector(7 downto 0); IEEE1284_nError : out std_logic; IEEE1284_Select : out std_logic; IEEE1284_PaperEnd : out std_logic; IEEE1284_nAck : out std_logic; IEEE1284_Busy : out std_logic; IEEE1284_nStrobe : in std_logic; IEEE1284_nAutoLF : in std_logic; IEEE1284_nInit : in std_logic; IEEE1284_nSelectIn : in std_logic; Mode_Compatible : out std_logic; Mode_Byte : out std_logic; Mode_Nibble : out std_logic; Mode_EPP : out std_logic; Mode_ECP : out std_logic; Mode_AutoNego : out std_logic; ODBuf_En : out std_logic; Debug_OUT : out std_logic_vector(7 downto 0) ); end IEEE1284Main; architecture Behavioral of IEEE1284Main is type rom_type is array (0 to 127) of std_logic_vector (7 downto 0); constant PRODID : rom_type := ( x"00",x"45",x"4D",x"46",x"47",x"3A",x"4E",x"61",x"68",x"69",x"74",x"61",x"66",x"75",x"3B",x"4D", x"44",x"4C",x"3A",x"46",x"50",x"47",x"41",x"31",x"32",x"38",x"34",x"3B",x"43",x"4C",x"53",x"3A", x"54",x"61",x"70",x"65",x"44",x"72",x"69",x"76",x"65",x"3B",x"44",x"45",x"53",x"3A",x"4E",x"61", x"68",x"69",x"74",x"61",x"66",x"75",x"20",x"49",x"45",x"45",x"45",x"31",x"32",x"38",x"34",x"20", x"46",x"50",x"47",x"41",x"3B",x"FF",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00", x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00" ); signal prodid_address : std_logic_vector(6 downto 0); signal RequestProdID : std_logic; signal DataReceived_node : std_logic; signal DataReq_node : std_logic; -- IEEE1284 components require data to send to host. signal Data_ProdID : std_logic_vector(7 downto 0); signal DataAvail_ProdID : std_logic; -- for Auto negotiation signal MainState : integer range 0 to 63; signal IEEE1284_ExtByte : std_logic_vector(7 downto 0); signal Timer : integer range 0 to 1000; constant TimerCount : integer := 25; -- CLKFreq * 0.5 constant Ext_ReqEXTLINK : std_logic_vector(7 downto 0) := "10000000"; constant Ext_ReqEPPMode : std_logic_vector(7 downto 0) := "01000000"; constant Ext_ReqECPModeRLE : std_logic_vector(7 downto 0) := "00110000"; constant Ext_ReqECPMode : std_logic_vector(7 downto 0) := "00010000"; constant Ext_ReqDevIDNibble : std_logic_vector(7 downto 0) := "00000100"; constant Ext_ReqDevIDByte : std_logic_vector(7 downto 0) := "00000101"; constant Ext_ReqDevIDECP : std_logic_vector(7 downto 0) := "00010100"; constant Ext_ReqDevIDECPRLE : std_logic_vector(7 downto 0) := "00110100"; constant Ext_ReqByteMode : std_logic_vector(7 downto 0) := "00000001"; constant Ext_ReqNibbleMode : std_logic_vector(7 downto 0) := "00000000"; -- Nodes for mode determination signal Mode : Integer range 0 to 7; constant mdCompatible : Integer := 0; constant mdByte : Integer := 1; constant mdNibble : Integer := 2; constant mdEPP : Integer := 3; constant mdECP : Integer := 4; constant mdAutoNego : Integer := 7; begin Debug_OUT <= RequestProdID & "0" & conv_std_logic_vector(MainState,6); Mode_Compatible <= '1' when (Mode = mdCompatible) else '0'; Mode_Byte <= '1' when (Mode = mdByte) else '0'; Mode_Nibble <= '1' when (Mode = mdNibble) else '0'; Mode_EPP <= '1' when (Mode = mdEPP) else '0'; Mode_ECP <= '1' when (Mode = mdECP) else '0'; Mode_AutoNego <= '1' when (Mode = mdAutoNego) else '0'; DataReq <= DataReq_node when(RequestProdID = '0') else '0'; DataReceived <= DataReceived_node; process(CLK) begin if(CLK'event and CLK='1') then if(Reset = '1') then MainState <= 0; else case MainState is when 0 => --IDLE State RequestProdID <= '0'; DataReq_node <= '0'; ODBuf_En <= '0'; if((IEEE1284_nSelectIn = '1') and (IEEE1284_nAutoLF = '0')) then MainState <= 1; IEEE1284_nError <= '1'; --nDataAvail (S3) IEEE1284_nAck <= '0'; --PtrClk (S6) IEEE1284_Busy <= '1'; --PtrBusy (S7) IEEE1284_PaperEnd <= '1'; --AckDataReq (S5) IEEE1284_Select <= '1'; --XFlag (S4) Mode <= mdAutoNego; DataReceived_node <= '0'; elsif(IEEE1284_nStrobe = '0') then -- Compatibility mode data write MainState <= 8; Data_OUT <= IEEE1284_DIN; IEEE1284_nAck <= '0'; IEEE1284_Busy <= '1'; Timer <= TimerCount; Mode <= mdCompatible; DataReceived_node <= '1'; else IEEE1284_nError <= '1'; --nDataAvail (S3) IEEE1284_nAck <= '1'; IEEE1284_Busy <= Busy; IEEE1284_PaperEnd <= '1'; IEEE1284_Select <= '0'; Mode <= mdCompatible; DataReceived_node <= '0'; end if; when 1 => if(IEEE1284_nSelectIn = '0') then --1284Active(C3) MainState <= 0; --return to IDLE state elsif(IEEE1284_nStrobe = '0') then --HostClk(C0) IEEE1284_ExtByte <= IEEE1284_DIN; -- Latch ExtByte at this timing Timer <= TimerCount; -- Launch timer MainState <= 2; end if; when 2 => if(Timer /= 0) then -- wait for 500ns Timer <= Timer - 1; else MainState <= 3; end if; when 3 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif((IEEE1284_nStrobe = '1') and (IEEE1284_nAutoLF = '1')) then IEEE1284_nAck <= '0'; --PtrClk (S6) : IEEE1284_PaperEnd <= '0'; --AckDataReq (S5) : ack if(IEEE1284_ExtByte = Ext_ReqNibbleMode) then IEEE1284_nError <= '1'; --nDataAvail (S3) : no data to transfer IEEE1284_Select <= '0'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '0'; elsif(IEEE1284_ExtByte = Ext_ReqDevIDNibble) then IEEE1284_nError <= '0'; --nDataAvail (S3) : data available ! IEEE1284_Select <= '1'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '1'; elsif(IEEE1284_ExtByte = Ext_ReqByteMode) then IEEE1284_nError <= '1'; --nDataAvail (S3) : no data to transfer IEEE1284_Select <= '1'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '0'; elsif(IEEE1284_ExtByte = Ext_ReqDevIDByte) then IEEE1284_nError <= '0'; --nDataAvail (S3) : data available ! IEEE1284_Select <= '1'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '1'; elsif(IEEE1284_ExtByte = Ext_ReqECPMode) then IEEE1284_nError <= '1'; --nDataAvail (S3) : no data to transfer IEEE1284_Select <= '1'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '0'; elsif(IEEE1284_ExtByte = Ext_ReqDevIDECP) then IEEE1284_nError <= '0'; --nDataAvail (S3) : data available ! IEEE1284_Select <= '1'; --XFlag (S4) : supported ! IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '1'; else IEEE1284_nError <= '1'; --nDataAvail (S3) : no data to transfer IEEE1284_Select <= '0'; --XFlag (S4) : not supported IEEE1284_Busy <= Busy;--PtrBusy (S7) : periph. busy status RequestProdID <= '0'; end if; Timer <= TimerCount; -- launch timer MainState <= 4; end if; when 4 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '1'; --PtrClk (S6) : Bring PtrClk to High. MainState <= 5; end if; when 5 => if(IEEE1284_ExtByte = Ext_ReqNibbleMode) then MainState <= 16; elsif(IEEE1284_ExtByte = Ext_ReqDevIDNibble) then MainState <= 16; elsif(IEEE1284_ExtByte = Ext_ReqByteMode) then MainState <= 32; elsif(IEEE1284_ExtByte = Ext_ReqDevIDByte) then MainState <= 32; elsif(IEEE1284_ExtByte = Ext_ReqECPMode) then MainState <= 48; elsif(IEEE1284_ExtByte = Ext_ReqDevIDECP) then MainState <= 48; else MainState <= 0; end if; -- ******************** COMPATIBILITY MODE ************************** when 8 => DataReceived_node <= '0'; if(Timer /= 0) then Timer <= Timer - 1; else MainState <= 9; IEEE1284_nAck <= '1'; IEEE1284_Busy <= '0'; end if; when 9 => if(IEEE1284_nStrobe = '1') then Timer <= TimerCount; MainState <= 10; end if; when 10 => if(Timer /= 0) then Timer <= Timer - 1; else MainState <= 0; end if; -- ******************** NIBBLE MODE ************************** when 16 => Mode <= mdNibble; IEEE1284_nError <= not DataAvail_ProdID; --nDataAvail (S3) IEEE1284_Busy <= Busy; if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '0') then --HostBusy (C1) MainState <= 17; DataReq_node <= '1'; end if; when 17 => DataReq_node <= '0'; MainState <= 18; when 18 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif((DataAvail = '0') or (DataWr = '1')) then IEEE1284_nError <= Data_ProdID(0); --nDataAvail (S3) IEEE1284_Select <= Data_ProdID(1); --XFlag (S4) IEEE1284_PaperEnd <= Data_ProdID(2); --AckDataReq (S5) IEEE1284_Busy <= Data_ProdID(3); --PtrBusy (S7) Timer <= TimerCount; -- launch timer MainState <= 19; end if; when 19 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '0'; --PtrClk (S6) : Bring PtrClk to Low MainState <= 20; end if; when 20 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '1') then --HostBusy (C1) : Wait HostBust to High Timer <= TimerCount; MainState <= 21; end if; when 21 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '1'; --PtrClk (S6) : Bring PtrClk to High MainState <= 22; end if; when 22 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '0') then --HostBusy (C1) : Wait HostBust to Low IEEE1284_nError <= Data_ProdID(4); --nDataAvail (S3) IEEE1284_Select <= Data_ProdID(5); --XFlag (S4) IEEE1284_PaperEnd <= Data_ProdID(6); --AckDataReq (S5) IEEE1284_Busy <= Data_ProdID(7); --PtrBusy (S7) Timer <= TimerCount; -- launch timer MainState <= 23; end if; when 23 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '0'; --PtrClk (S6) : Bring PtrClk to Low MainState <= 24; end if; when 24 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '1') then --HostBusy (C1) : Wait HostBust to High IEEE1284_nError <= not DataAvail; --nDataAvail (S3) IEEE1284_Select <= RequestProdID; --XFlag (S4) IEEE1284_PaperEnd <= not DataAvail; --AckDataReq (S5) IEEE1284_Busy <= Busy; --PtrBusy (S7) Timer <= TimerCount; MainState <= 25; end if; when 25 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '1'; --PtrClk (S6) : Bring PtrClk to High MainState <= 16; end if; -- ******************** BYTE MODE ************************** when 32 => Mode <= mdByte; IEEE1284_nError <= not DataAvail_ProdID; --nDataAvail (S3) IEEE1284_PaperEnd <= not DataAvail_ProdID; --AckDataReq (S5) IEEE1284_Busy <= Busy; --PtrBusy (S7) if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '0') then --HostBusy (C1) MainState <= 33; DataReq_node <= '1'; ODBuf_En <= '1'; end if; when 33 => DataReq_node <= '0'; MainState <= 34; when 34 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif((DataAvail = '0') or (DataWr = '1')) then IEEE1284_DOUT <= Data_ProdID; -- Output Data !! Timer <= TimerCount; -- launch timer MainState <= 35; end if; when 35 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '0'; --PtrClk (S6) : Bring PtrClk to Low MainState <= 36; end if; when 36 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '1') then --HostBusy (C1) : Wait HostBusy to High MainState <= 37; IEEE1284_nError <= not DataAvail_ProdID; --nDataAvail (S3) IEEE1284_PaperEnd <= not DataAvail_ProdID; --AckDataReq (S5) IEEE1284_Busy <= Busy; --PtrBusy (S7) Timer <= TimerCount; end if; when 37 => if(Timer /= 0) then Timer <= Timer - 1; else IEEE1284_nAck <= '1'; --PtrClk (S6) : Bring PtrClk to High MainState <= 38; end if; when 38 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nStrobe = '0') then --HostClk (C0) : Wait HostClk to Low Timer <= TimerCount; MainState <= 39; end if; when 39 => if(Timer /= 0) then Timer <= Timer - 1; else MainState <= 40; end if; when 40 => if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nStrobe = '1') then --HostClk (C0) : Wait HostClk to High MainState <= 32; end if; -- ******************** ECP MODE ************************** when 48 => Mode <= mdECP; ODBuf_En <= '0'; IEEE1284_nError <= not DataAvail_ProdID; --nPeriphReq (S3) -- IEEE1284_Select <= '1'; --XFlag (S4) -- IEEE1284_PaperEnd <= '1'; --nAckReverse (S5) : Not ack IEEE1284_nAck <= '1'; --PeriphClk (S6) : Bring PtrClk to High normally IEEE1284_Busy <= Busy; --PtrBusy (S7) if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nInit = '0') then --ReverseReq (C2) : MainState <= 49; --goto reverse transfers end if; when 49 => IEEE1284_nError <= not DataAvail_ProdID; --nPeriphReq (S3) IEEE1284_PaperEnd <= '0'; --nAckReverse (S5) : Ack ! IEEE1284_Busy <= Busy; --PtrBusy (S7) if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif((IEEE1284_nAutoLF = '0') and (DataAvail_ProdID = '1')) then --HostAck (C1) : Wait HostAck to Low MainState <= 50; DataReq_node <= '1'; ODBuf_En <= '1'; end if; when 50 => DataReq_node <= '0'; MainState <= 51; when 51 => IEEE1284_nError <= not DataAvail_ProdID; --nPeriphReq (S3) IEEE1284_Busy <= '1'; --PtrBusy (S7) : Data OUT if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(DataWr = '1') then IEEE1284_DOUT <= Data_ProdID; -- Output Data !! MainState <= 52; end if; when 52 => IEEE1284_nError <= not DataAvail_ProdID; --nPeriphReq (S3) IEEE1284_nAck <= '0'; --PeriphClk (S6) : Bring PtrClk to Low if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '1') then --HostAck (C1) : Wait HostAck to High MainState <= 53; end if; when 53 => IEEE1284_nError <= not DataAvail_ProdID; --nPeriphReq (S3) IEEE1284_nAck <= '1'; --PeriphClk (S6) : Bring PtrClk to High if(IEEE1284_nSelectIn = '0') then MainState <= 0; elsif(IEEE1284_nAutoLF = '0') then --HostAck (C1) : Wait HostAck to Low MainState <= 49; end if; when others => MainState <= 0; end case; end if; end if; end process; -- Data_Out <= Data_ProdID; process(CLK) begin if(CLK'event and CLK='1') then -- For device ID if(DataReq_node = '1')then prodid_address <= prodid_address + 1; elsif(MainState = 0) then prodid_address <= (others=>'0'); end if; if(RequestProdID = '1') then if(DataReq_node = '1') then Data_ProdID <= PRODID(conv_integer(prodid_address)); end if; if(PRODID(conv_integer(prodid_address)) = x"FF") then DataAvail_ProdID <= '0'; else DataAvail_ProdID <= '1'; end if; else if(DataReq_node = '1') then Data_ProdID <= Data_IN; end if; DataAvail_ProdID <= DataAvail; end if; end if; end process; end Behavioral;