--------------------------------------------------
-- BARREL.VHD Version 1.0                       --
-- Xilinx HDL Synthesis Design Guide            --
-- Based on XAPP 26 (see http://www.xilinx.com) --
-- 16-bit Barrel Shifter (shift right)          --
-- May 1997                                     --
--------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity barrel is
port (	S:   in STD_LOGIC_VECTOR(3 downto 0);
	A_P: in STD_LOGIC_VECTOR(15 downto 0);
	B_P: out STD_LOGIC_VECTOR(15 downto 0));
end barrel;

architecture RTL of barrel is

signal SEL1,SEL2: STD_LOGIC_VECTOR(1 downto 0);
signal C:         STD_LOGIC_VECTOR(15 downto 0);

begin
    FIRST_LVL: process (A_P, SEL1)
    begin
        case SEL1 is
            when "00" => -- Shift by 0 
               C 	       <= A_P;

            when "01" => -- Shift by 1
               C(15)   	       <= A_P(0);
               C(14 downto 0)  <= A_P(15 downto 1);

            when "10" => -- Shift by 2
               C(15 downto 14) <= A_P(1 downto 0);
               C(13 downto 0)  <= A_P(15 downto 2);

            when "11" => -- Shift by 3
               C(15 downto 13) <= A_P(2 downto 0);
               C(12 downto 0)  <= A_P(15 downto 3);

            when others =>
	       C 	       <= A_P;
        end case;
    end process; --End FIRST_LVL

SECND_LVL: process (C, SEL2)
    begin
        case SEL2 is 
           when "00" => --Shift by 0
               B_P 	         <=  C;
     
           when "01" => --Shift by 4
               B_P(15 downto 12) <= C(3 downto 0);
               B_P(11 downto 0)  <= C(15 downto 4);

           when "10" => --Shift by 8 
               B_P(7 downto 0)   <= C(15 downto 8);
	       B_P(15 downto 8)  <= C(7 downto 0);

           when "11" => --Shift by 12 
	       B_P(3 downto 0)   <= C(15 downto 12);
	       B_P(15 downto 4)  <= C(11 downto 0);

           when others =>
               B_P               <= C;
        end case;
    end process; -- End SECOND_LVL

    SEL1 <= S(1 downto 0);
    SEL2 <= S(3 downto 2);

end RTL;
