entity switch is
    port (data_in : in bit_vector (0 to 3);
          data_out : out bit_vector (0 to 3);
		data_inavail : in bit_vector (0 to 3);
		data_outavail : in bit_vector (0 to 3);

          CLK : in bit);
end switch;


entity inport is
    port (next_data : in bit;
          address0 : out bit;
          address1 : out bit;
          packet_ready : out bit;
          current_data_bit : out bit;
          data_in : in bit;
          data_avail : in bit;
          CLK : in bit);
end inport;


architecture behavior of inport is

begin

    process (CLK)
	  variable count : integer :=0;
        variable bits_remaining : integer;
        variable shift_register : bit_vector (0 to 5);

begin
	  if CLK = '1' then

            if next_data = '1' then
                shift_register (3) := shift_register (2);
                shift_register (2) := shift_register (1);
                shift_register (1) := shift_register (0);
                bits_remaining := bits_remaining - 1;
	
                if bits_remaining = 0 then
                    count := 0;
                    packet_ready <= '0';
                end if;
            end if;

            if data_avail = '1' and count < 6 then
                shift_register (5) := shift_register (4);
                shift_register (4) := shift_register (3);
                shift_register (3) := shift_register (2);
                shift_register (2) := shift_register (1);
                shift_register (1) := shift_register (0);
                shift_register (0) := data_in;
                count := count + 1;
                if count = 6 then
                    bits_remaining := 4;
			  packet_ready <= '1';
                end if;
            end if;

		address0 <= shift_register (4);
		address1 <= shift_register (5);
		current_data_bit <= shift_register (3);

        end if;


    end process;
end behavior;


architecture behavioral of switch is
    component inport
        port (next_data : in bit;
              address0 : out bit;
              address1 : out bit;
              packet_ready : out bit;
              current_data_bit : out bit;
              data_in : in bit;
			  data_avail : in bit;
			  CLK : in bit);
	end component;
	signal next_data : bit_vector (0 to 3);
	signal data_bit : bit_vector (0 to 3);
	signal address0 : bit_vector (0 to 3);
	signal address1 : bit_vector (0 to 3);
	signal p_ready : bit_vector (0 to 3);
begin
    b0 : inport port map (next_data (0), address0 (0), address1 (0), p_ready(0),
                          data_bit (0), data_in (0), data_inavail (0), CLK);
    b1 : inport port map (next_data (1), address0 (1), address1 (1), p_ready(1),
                          data_bit (1), data_in (1), data_inavail (1), CLK);
    b2 : inport port map (next_data (2), address0 (2), address1 (2), p_ready(2),
                          data_bit (2), data_in (2), data_inavail (2), CLK);
    b3 : inport port map (next_data (3), address0 (3), address1 (3), p_ready(3),
                          data_bit (3), data_in (3), data_inavail (3), CLK);
    process
        variable add :integer;
        variable i :integer := 0;
    begin
        wait until CLK'event and CLK = '1';

        add:=0;

                if p_ready(i) = '1' then
                    if address0(i) = '1' then add:=add+1; end if;
			  if address1(i) = '1' then add:=add+2; end if;
                    data_out(add) <= data_bit(i);
                    next_data (i) <= '1';
				
			wait until CLK'event and CLK = '1';
			wait for 0ns;			

			data_out(add) <= data_bit(i);
			wait until CLK'event and CLK = '1';
			data_out(add) <= data_bit(i);
			wait until CLK'event and CLK = '1';
			data_out(add) <= data_bit(i);

                end if;

               i := i+1;
               if i = 4 then i = 0; end if;

    end process;
end behavioral;
