------------------------------------------------------------------------------- -- -- interfacefsm.vhd: FSM for controlling parallel bus interface -- Dan R. K. Ports -- 6.111 final project, 2003/12/01 -- ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity interfacefsm is port ( start : in std_logic; reset : in std_logic; busy : out std_logic; sendbufsel, recvbufsel : in std_logic_vector(2 downto 0); clk : in std_logic; fftsending : out std_logic; procsending : in std_logic; fftrdyack : out std_logic; procrdyack : in std_logic; ack2 : in std_logic; ramaddr : out std_logic_vector(13 downto 0); ramdatain : in std_logic_vector(7 downto 0); ramdataout : out std_logic_vector(7 downto 0); databus : inout std_logic_vector(7 downto 0); ramreq : out std_logic; ramdone : in std_logic; ramwe : out std_logic); end interfacefsm; architecture behavioral of interfacefsm is type StateType is (s_Idle, s_SendStart, s_SendAddrSelect, s_SendRAMWait, s_SendReady, s_SendAck, s_SendComplete, s_RecvWait, s_WriteAddrSelect, s_Write, s_RecvAck); signal curState, nextState : StateType := s_Idle; signal count : std_logic_vector(10 downto 0); signal buf : std_logic_vector(7 downto 0); begin -- behavioral -- purpose: determine next state -- type : combinational -- inputs : curState, count, procsending, procrdyack, ack2, reset -- outputs: nextState newState: process (curState, count, procsending, procrdyack, ack2, reset) begin -- process newState if reset = '1' then nextState <= s_Idle; else case curState is when s_Idle => if start = '1' then nextState <= s_SendStart; else nextState <= s_Idle; end if; when s_SendStart => nextState <= s_SendRAMWait; when s_SendRAMWait => if ramdone = '1' then nextState <= s_SendReady; else nextState <= s_SendRAMWait; end if; when s_SendReady => if procrdyack = '1' and ack2 = '1' then nextState <= s_SendAck; else nextState <= s_SendReady; end if; when s_SendAck => if procrdyack = '0' and ack2 = '0' then nextState <= s_SendAddrSelect; else nextState <= s_SendAck; end if; when s_SendAddrSelect => -- if count = "00000000000" then if count = 0 then nextState <= s_SendComplete; else nextState <= s_SendRAMWait; end if; when s_SendComplete => if procsending = '1' then nextState <= s_RecvWait; else nextState <= s_SendComplete; end if; when s_RecvWait => if procsending = '0' then nextState <= s_Idle; else if procrdyack = '1' then nextState <= s_WriteAddrSelect; else nextState <= s_RecvWait; end if; end if; when s_WriteAddrSelect => nextState <= s_Write; when s_Write => if ramdone = '1' then nextState <= s_RecvAck; else nextState <= s_Write; end if; when s_RecvAck => if procrdyack = '0' then if procsending = '0' then nextState <= s_Idle; else nextState <= s_RecvWait; end if; else nextState <= s_RecvAck; end if; when others => nextState <= s_Idle; end case; end if; end process newState; -- purpose: update current state on clock rising edge -- type : combinational -- inputs : clk, nextState -- outputs: curState state_clocked: process (clk) begin -- process state_clocked if rising_edge(clk) then curState <= nextState; if nextState = s_SendAddrSelect or nextState = s_WriteAddrSelect then count <= count + 1; elsif nextState = s_Idle then count <= (others => '0'); end if; if curState = s_SendRAMWait then buf <= ramdatain; elsif curState = s_RecvWait then buf <= databus; end if; end if; end process state_clocked; databus <= buf when curState = s_SendRAMWait or curState = s_SendReady or curState = s_SendAck else (others => 'Z'); ramaddr <= sendbufsel & count when curState = s_SendAddrSelect or curState = s_SendAck or curState = s_SendReady or curState = s_SendStart or curState = s_SendComplete else recvbufsel & count; ramwe <= '1' when curState = s_Write else '0'; ramdataout <= buf; -- purpose: generate output values -- type : combinational -- inputs : curState -- outputs: busy, fftsending, ctrenable, readenable, writeenable -- gen_outputs: process (curState) -- begin -- process gen_outputs busy <= '0' when curState = s_Idle else '1'; fftsending <= '1' when curState = s_SendStart or curState = s_SendAddrSelect or curState = s_SendReady or curState = s_SendAck or curState = s_SendRAMWait else '0'; -- readenable <= '1' when curState = s_SendStart -- or curState = s_SendAddrSelect -- or curState = s_SendReady -- or curState = s_SendAck -- or curState = s_SendRAMWait -- else '0'; with curState select fftrdyack <= '0' when s_SendStart, '0' when s_SendRAMWait, '0' when s_SendAck, '0' when s_SendAddrSelect, '1' when s_SendReady, '0' when s_WriteAddrSelect, '0' when s_Write, '0' when s_RecvWait, '1' when s_RecvAck, '0' when others; -- ctrenable <= '1' when curState = s_SendAddrSelect -- or curState = s_WriteAddrSelect -- else '0'; -- writeenable <= '1' when curState = s_Write else '0'; -- -- end process gen_outputs; ramreq <= '1' when curState = s_SendRAMWait or curState = s_Write else '0'; end behavioral;