-------------------------------------------------------------------------------
-- Title      :  Barrel Shifter (Pure combinational)
-- Project    :  Barrel Shifter 
-------------------------------------------------------------------------------
-- File        : BarrelShifter.VHD
-- Author      : Jamil Khatib  (khatib@ieee.org)
-- Organization: OpenIPCore Project
-- Created     : 2000/08/2
-- Last update : 2000/08/2
-- Platform    : 
-- Simulators  : Modelsim 5.3XE/Windows98
-- Synthesizers: Leonardo/WindowsNT
-- Target      : 
-- Dependency  : ieee.std_logic_1164
--               utility.tools "private package"
-------------------------------------------------------------------------------
-- Description: Barrel Shifter Core (Combinational Shifter)
-------------------------------------------------------------------------------
-- Copyright (c) 2000 Jamil Khatib
-- 
-- This VHDL design file is an open design; you can redistribute it and/or
-- modify it and/or implement it after contacting the author
-- You can check the draft license at
-- http://www.opencores.org/OIPC/license.shtml

-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   1
-- Version         :   0.1
-- Date            :   1st Aug 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   Created
--
-------------------------------------------------------------------------------

-- Revisions  :
-- Revision Number :   2
-- Version         :   0.2
-- Date            :   3rd Nov 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   ShiftSize constant made generic
--
-------------------------------------------------------------------------------

library ieee;

use ieee.std_logic_1164.all;


library utility;

use utility.tools_pkg.all;



entity BarrelShifter is


  generic (
    REGSIZE   : integer := 16;          -- Register Size
    DIRECTION : integer := 0);          -- Shift Direction
                                        -- 0 Right 1 Left

  port (
    inReg  : in  std_logic_vector(REGSIZE -1 downto 0);  -- Input register
    ShSize : in  std_logic_vector(log2(REGSIZE) -1 downto 0);  -- Shift Size
    outReg : out std_logic_vector(REGSIZE -1 downto 0));  -- Shifted result

end BarrelShifter;

-------------------------------------------------------------------------------
architecture behave of BarrelShifter is

  constant SHIFTSIZE : integer := log2(REGSIZE);  -- Shift size
begin  -- behave
-------------------------------------------------------------------------------
  SHIFT_RIGHT        : if DIRECTION = 0 generate

    -- purpose: Perform the shifting
    -- type   : combinational
    -- inputs : inReg, ShSize
    -- outputs: outReg
    Shift             : process (inReg, Shsize)
      variable VarReg : std_logic_vector(REGSIZE -1 downto 0);
                                        -- Local storage for shifter
    begin  -- process Shift

      VarReg := inReg;

      for i in 0 to SHIFTSIZE -2 loop


        if ShSize(i) = '1' then

          VarReg(REGSIZE -1 downto 0) := (REGSIZE-1 downto REGSIZE-(2**i) => '0') & VarReg(REGSIZE -1 downto (2**i));

        end if;

      end loop;  -- i

      if ShSize(SHIFTSIZE-1) = '1' then
        VarReg := (others => '0');
      end if;

      outReg <= VarReg;

    end process Shift;

  end generate SHIFT_RIGHT;

-------------------------------------------------------------------------------
  SHIFT_LEFT : if DIRECTION = 1 generate


    -- purpose: Perform the shifting
    -- type   : combinational
    -- inputs : inReg, ShSize
    -- outputs: outReg
    Shift             : process (inReg, Shsize)
      variable VarReg : std_logic_vector(REGSIZE -1 downto 0);
                                        -- Local storage for shifter
    begin  -- process Shift

      VarReg := inReg;

      for i in 0 to SHIFTSIZE -2 loop


        if ShSize(i) = '1' then

          VarReg(REGSIZE -1 downto 0) := VarReg( (REGSIZE-(2**i)-1) downto 0) & ((2**i)-1 downto 0 => '0');

        end if;

      end loop;  -- i

      if ShSize(SHIFTSIZE-1) = '1' then
        VarReg := (others => '0');
      end if;

      outReg <= VarReg;

    end process Shift;


  end generate SHIFT_LEFT;
-------------------------------------------------------------------------------
end behave;