[vhdl] shift a std_logic_vector of n bit to right or left

I have a vector signal tmp : std_logic_vector(15 downto 0)

I have to shift it to left or right of n bit. how can I realize this operation. I thought to concatenation operation but I didn't know how use it.

This question is related to vhdl

The answer is


There are two ways that you can achieve this. Concatenation, and shift/rotate functions.

  • Concatenation is the "manual" way of doing things. You specify what part of the original signal that you want to "keep" and then concatenate on data to one end or the other. For example: tmp <= tmp(14 downto 0) & '0';

  • Shift functions (logical, arithmetic): These are generic functions that allow you to shift or rotate a vector in many ways. The functions are: sll (shift left logical), srl (shift right logical). A logical shift inserts zeros. Arithmetric shifts (sra/sla) insert the left most or right most bit, but work in the same way as logical shift. Note that for all of these operations you specify what you want to shift (tmp), and how many times you want to perform the shift (n bits)

  • Rotate functions: rol (rotate left), ror (rotate right). Rotating does just that, the MSB ends up in the LSB and everything shifts left (rol) or the other way around for ror.

Here is a handy reference I found (see the first page).


Personally, I think the concatenation is the better solution. The generic implementation would be

entity shifter is
    generic (
        REGSIZE  : integer := 8);
    port(
        clk      : in  str_logic;
        Data_in  : in  std_logic;
        Data_out : out std_logic(REGSIZE-1 downto 0);
end shifter ;

architecture bhv of shifter is
    signal shift_reg : std_logic_vector(REGSIZE-1 downto 0) := (others<='0');
begin
    process (clk) begin
        if rising_edge(clk) then
            shift_reg <= shift_reg(REGSIZE-2 downto 0) & Data_in;
        end if;
    end process;
end bhv;
Data_out <= shift_reg;

Both will implement as shift registers. If you find yourself in need of more shift registers than you are willing to spend resources on (EG dividing 1000 numbers by 4) you might consider using a BRAM to store the values and a single shift register to contain "indices" that result in the correct shift of all the numbers.


add_Pbl <= to_stdlogicvector(to_bitvector(dato_cu(25 downto 2)) sll 1);
add_Pbl is a std_logic_vector of 24 bit
dato_cu is a std_logic_vector of 32 bit

First, you need to convert the std_logic_vector with to_bitvector() function because sll statement works with logic 1 and 0 bits.


I would not suggest to use sll or srl with std_logic_vector.

During simulation sll gave me 'U' value for those bits, where I expected 0's.

Use shift_left(), shift_right() functions.

For example:

OP1 : in std_logic_vector(7 downto 0); signal accum: std_logic_vector(7 downto 0);

accum <= std_logic_vector(shift_left(unsigned(accum), to_integer(unsigned(OP1)))); accum <= std_logic_vector(shift_right(unsigned(accum), to_integer(unsigned(OP1))));


This is typically done manually by choosing the appropriate bits from the vector and then appending 0s.

For example, to shift a vector 8 bits

variable tmp : std_logic_vector(15 downto 0)
...
tmp := x"00" & tmp(15 downto 8);

Hopefully this simple answer is useful to someone