
use work.TSL_Package.all;
        entity SER_IN_PAR_OUT is
                port (I: in  bit; CLOCK: in  bit; NINTI: buffer bit; OUTPUT: out WORD);
        end SER_IN_PAR_OUT;
 
        architecture SER_IN_PAR_OUT_RTL of SER_IN_PAR_OUT is
                type I_STATE is (RESET_STATE, I_LOW_1, I_LOW_2, I_LOW_3, RUNNING);
                        -- enum type for FSM
                signal STATE, NEXT_STATE : I_STATE;
                signal IREG : bit_vector (WORD_LENGTH downto 0);
                signal DIV_CLOCK, RESET, RUNNING_STATE : bit;
 
 
 
DIVIDE_CLOCK : process  -- clock dividing process - divide by four
        variable STATE : integer range 0 to 3;
        begin
                wait until CLOCK'event and CLOCK = '1';
                        if (STATE < 3) then
                                        STATE := STATE + 1;
                                        DIV_CLOCK <= '0';
                        else
                                        STATE := 0;
                                        DIV_CLOCK <= RUNNING_STATE;
                        end if;
        end process;
 
        SHIFT_IN : process(DIV_CLOCK) -- shift register process with asynch clear to 0...01
        begin
                if (RESET = '1') then
                        IREG(WORD_LENGTH downto 1) <= "00000000"; IREG(0) <= '1';
                elsif (DIV_CLOCK'event and DIV_CLOCK = '1') then
                        IREG <= IREG(WORD_LENGTH-1 downto 0) & I;
                end if;
        end process;

        OUTPUT <= IREG(WORD_LENGTH-1 downto 0); -- output get low word_length bits
 
        SAVE_STATE : process begin -- state machine state register declaration
                wait until CLOCK'event and CLOCK = '1';
                STATE <= NEXT_STATE;
        end process;
 
        FIND_START : process(I,STATE,IREG)  -- find low I bit (low for half period = 2 more ticks
        begin            
                case STATE is
                                when RESET_STATE =>
                                                if (I = '0') then NEXT_STATE <= I_LOW_1;                                              
                                                else              NEXT_STATE <= RESET_STATE;
                                                end if;
                                        NINTI <= '1';
                                when I_LOW_1 =>
                                                if (I = '0') then NEXT_STATE <= I_LOW_2;
                                                else              NEXT_STATE <= RESET_STATE;
                                                end if;
                                        NINTI <= '1';
                                when I_LOW_2 =>
                                        if (I = '0') then NEXT_STATE <= I_LOW_3;
                                                else              NEXT_STATE <= RESET_STATE;
                                                end if;
                                                NINTI <= '1';
                                when I_LOW_3 =>
                                                if (I = '0') then NEXT_STATE <= RUNNING;
                                                else              NEXT_STATE <= RESET_STATE;
                                                end if;
                                                NINTI <= '1';
 				when RUNNING =>
                                                if (IREG(WORD_LENGTH) = '0') then
                                                        NEXT_STATE <= RUNNING;
                                                        NINTI <= '1';
                                                else
                                                        NEXT_STATE <= RESET_STATE;
                                                        NINTI <= '0';
                                                end if;
                end case;
 
                if (STATE = RUNNING) then
                                RESET <= '0';
                                RUNNING_STATE <= '1';
                else
                                RESET <= '1';
                                RUNNING_STATE <= '0';
                end if;
         end process;
 
end SER_IN_PAR_OUT_RTL;
 
 

