Search code examples
vhdlmodelsim

VHDL n-bit barrel shifter


I have a 32 bit barrel shifter using behavior architecture. Now I need to convert it to an n-bit shifter. The problem that I'm facing is that there is some kind of restriction to the for loop that I have to put a constant as sentinel value.

Following is my Code

library IEEE;
use IEEE.std_logic_1164.all;

Entity bshift is   -- barrel shifter
      port (left    : in  std_logic; -- '1' for left, '0' for right
            logical : in  std_logic; -- '1' for logical, '0' for arithmetic
            shift   : in  std_logic_vector(4 downto 0);  -- shift count
            input   : in  std_logic_vector (31 downto 0);
            output  : out std_logic_vector (31 downto 0) );
end entity bshift;


architecture behavior of bshift is
  function to_integer(sig : std_logic_vector) return integer is
    variable num : integer := 0;  -- descending sig as integer
  begin
    for i in sig'range loop
      if sig(i)='1' then
        num := num*2+1;
      else
        num := num*2;
      end if;
    end loop;  -- i
    return num;
  end function to_integer;

begin  -- behavior
  shft32: process(left, logical, input, shift)
            variable shft : integer;
            variable out_right_arithmetic : std_logic_vector(31 downto 0);
            variable out_right_logical    : std_logic_vector(31 downto 0);
            variable out_left_logical     : std_logic_vector(31 downto 0);
          begin
            shft := to_integer(shift);
            if logical = '0' then
              out_right_arithmetic := (31 downto 32-shft => input(31)) &
                                      input(31 downto shft);
              output <= out_right_arithmetic after 250 ps;
            else
              if left = '1' then
                out_left_logical := input(31-shft downto 0) &
                                    (shft-1 downto 0 => '0');
                output <= out_left_logical after 250 ps;
              else
                out_right_logical := (31 downto 32-shft => '0') &
                                     input(31 downto shft);
                output <= out_right_logical after 250 ps;
              end if;
            end if;
          end process shft32;
end architecture behavior;  -- of bshift

any help will be appreciated


Solution

  • Your code is not a barrel shifter implementation, because a barrel shift is a mux-tree. enter image description here

    If you have a 32 bit BarrelShifter module, you will need a 5 bit Shift input, wherein every bit position i enables a 2^i shift operation.

    So for example shift = 5d -> 00101b enables a mux in stage 1 to shift for 1 bit and a mux in stage 3 to shift 4 bits. All other mux stages are set to pass through (shift(i) = 0).

    I also would not advice to mix up basic shifting with shift modes (arithmetic, logic, rotate) and directions (left, right).

    • arithmetic and logic is only different in the shift-in value
    • shift right can be done by a conversion => shiftright = reverse(shiftleft(reverse(input), n)

    An open source implementation can be found here:
    https://github.com/VLSI-EDA/PoC/blob/master/src/arith/arith_shifter_barrel.vhdl