shift a std_logic_vector of n bit to right or left
Asked Answered
W

6

24

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.

Warnerwarning answered 26/1, 2012 at 12:27 Comment(0)
C
32

Use the ieee.numeric_std library, and the appropriate vector type for the numbers you are working on (unsigned or signed).

Then the operators are `sla`/`sra` for arithmetic shifts (ie fill with sign bit on right shifts and lsb on left shifts) and `sll`/`srl` for logical shifts (ie fill with '0's).

You pass a parameter to the operator to define the number of bits to shift:

A <= B srl 2; -- logical shift right 2 bits
--- Update: --- I have no idea what I was writing above (thanks to Val for pointing that out!)

Of course the correct way to shift signed and unsigned types is with the shift_left and shift_right functions defined in ieee.numeric_std.

The shift and rotate operators sll, ror etc are for vectors of boolean, bit or std_ulogic, and can have interestingly unexpected behaviour in that the arithmetic shifts duplicate the end-bit even when shifting left.

And much more history can be found here:

http://jdebp.eu./FGA/bit-shifts-in-vhdl.html

However, the answer to the original question is still

sig <= tmp sll number_of_bits;
Cowbind answered 27/1, 2012 at 15:32 Comment(9)
I found in ieee.std_logic_arith library the function shr and shl to make shift operationsWarnerwarning
@Warnerwarning Don't use that library. It's not actually standard IEEE and deprecated.Carpentaria
I have had some tools not allow these functions for vectors larger than 32 bits, and had to do manual shift and concatenate (covered in other answers).Carpentaria
@Mazzy: for more on the why nots of std_logic_arith, see here: parallelpoints.com/node/3Cowbind
Look at the numeric_std, eda.org/rassp/vhdl/models/standards/numeric_std.vhd, and tell where is the sra function is located.Fellah
Arithmetic operators for std_logic_vector seem to be non-standard and probably only supported by some IDEs. I'd stick to casting to unsigned or signed, depending on whether you need logical or arithmetic shift, and using the functionsCooley
sll doesn't appear to work on std_logic_vector instances: "somevector sll 1" results in an error on vivado.Quartzite
This is only applicable for VHDL2008. Could you suggest something for VHDL?Hildahildagard
@marpangal: to me, VHDL is VHDL 2008, and has been for nearly a decade. Apologies if you are stuck with old tools, but I am very "out of date" with what to do with them.Cowbind
F
19

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).

Font answered 26/1, 2012 at 12:54 Comment(4)
I tried to use shift functions but I receive an error: Overloaded Operator srl does not match its parameter profileWarnerwarning
I'm using ieee.numeric_std,ieee.numberic_bit,ieee.std_logic_unsignedWarnerwarning
I tried to use ieee.numeric_std,ieee.numeric_bit,ieee.std_logic_unsigned and ieee.std_logic_signed but in my architecture I realize sum operation and I receive the error cannot resolve overloading because it is ambiguosWarnerwarning
Edit your question and post in the code snippet that doesn't work.Font
D
9

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))));
Declivitous answered 31/5, 2015 at 11:31 Comment(0)
A
7

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.

Atmospheric answered 26/1, 2012 at 18:37 Comment(3)
I'm intrigued... why do you say concatentation is better than using the standard defined functions?Cowbind
It may be my naivite, but when I used to program in VHDL, I had quite a lot of trouble with those particular built in functions. It was likely a confusion of using the built ins on the wrong type (although I could not test this now to verify). My guess is these builtins don't work well on standard logic vectors.Atmospheric
It might be you ran foul of this: en.wikipedia.org/wiki/Arithmetic_shift#cite_note-1 ?Cowbind
P
6

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

Percolator answered 31/8, 2017 at 9:52 Comment(0)
D
0
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.

Dissatisfaction answered 26/11, 2015 at 21:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.