You've come to this page because you've asked about shift operators in VHDL.

Arithmetic and logical shifts and rotates are done with functions in VHDL,
not operators. The functions are part of the
`ieee.numeric_std`

and `ieee.numeric_bit`

packages,
and are named `shift_left()`

, `shift_right()`

,
`rotate_left()`

, and `rotate_right()`

. The
difference between arithmetic and logical shifts is encoded in the type of
the first argument to the function. The function is overloaded according
to this type, with different overloads performing different operations.
So, for example: If you want to do an arithmetic right shift of a
`std_logic_vector`

(from `numeric_std`

), convert
your signal to a `signed`

and pass it to
`shift_right()`

. But if you want to do a logical right shift,
convert your signal to an `unsigned`

and pass it to
`shift_right()`

.

These are the way to do shifts and rotates in VHDL. Don't try to use operators.

The problem with the operators —
`sll`

,
`sla`

,
`srl`

,
`sra`

,
`rol`

, and
`rar`

,
— is that they were an afterthought, weren't specified correctly, and
have been removed from IEEE 1076.

What happened is that the standards Working Group originally specified
only functions for shifts and rotates. They created the four functions in
both the `ieee.numeric_std`

and `ieee.numeric_bit`

packages. Then during the standards approval balloting process, someone
suggested that the infix operators be defined to operate the same as the
relevant function, and this suggestion was acted upon. So the standard
gained overloads for the four operators
`sll`

,
`srl`

,
`rol`

, and
`rar`

,
in the two packages that were supposed to be equivalent to the four
functions
`shift_left()`

,
`shift_right()`

,
`rotate_left()`

, and
`rotate_right()`

in those packages.

The problem was that the operators weren't defined correctly. First:
There were outright editorial errors in the standards document itself.
The descriptions of the operators for `ieee.numeric_bit`

erroneously described the operators as predefined in VHDL. Second: The
definitions of the operators didn't match the definitions of the original
functions. In particular, the operators were given defined semantics for
the case where the second operand was negative. (The type of the second
arguments to the functions is `NATURAL`

, which cannot be
negative.) Third: The consequences of extending the semantics, and of
choosing this particular mapping from operators to functions, weren't
thought through.

VHDL is an unusual language, in that it contains the notion of an
arithmetic *left* shift. In most languages, there is no such
thing, arithmetic and logical left shifts being considered to be
identical. In VHDL, however, arithmetic left shift is the mirror image of
arithmetic right shift: bits are shifted to the left and value of the
original rightmost bit is shifted in at the right (i.e. that bit retains
its value). In this regard, VHDL is completely orthogonal, having both
arithmetic and logical shifts and rotates in both directions, with the
left shifts and rotates being mirror images of the right shifts and
rotates.

The `shift_left()`

function, overloaded for
`signed`

, performs arithmetic left shifts. There is no problem
with this. The problem lies with the subsequent additions of overloads
for the `sll`

and `srl`

operators, how they work
with negative shift counts, and how they work with signed shiftends.

Whilst the original functions didn't accept negative shifts, the newly
added overloaded operators did. The semantics of this were defined in
what people thought to be the "obvious" way: a shift/rotate by a negative
amount `-N`

was defined to be the same type of shift/rotate in
the opposite direction, by `+N`

. Unfortunately, the
consequences of this weren't thought through.

Worse, the *logical* shift infix operators actually perform
*arithmetic* shifts. `sll`

and `srl`

map
onto `shift_left()`

and `shift_right()`

, and no
overloads for the `sla`

and `sra`

operators are
provided. But the *functions* switch between arithmetic and
logical shifting according to the types of the first operand. This means
that so do the `sll`

and `srl`

operators, even
though lexically the "l" in the names of the operators stands for
"logical".

One consequence that wasn't thought through is that using these operators
results in hardware that is bigger than what hardware designers actually
want. A non-constant arithmetic shifter, inferred by a synthesis tool
from an `sll`

or `srl`

operator, has, in order to be
*correct*, to incorporate hardware that checks the sign of the
shift count, and switches directions accordingly, negating the count as
appropriate. Clearly, this is excessive hardware when one simply wants to
synthesize a simple unidirectional barrel shifter. But designing in VHDL
using the shift and rotate operators doesn't allow a hardware designer to
choose *not* to incorporate such hardware. To be functionally
correct, what is synthesized for such operators has to include the extra
logic for bidirectionality.

Another consequence is that this definition of the operators results in
the somewhat ludicrous situation that the location of the sign bit in
one's data words is dependent from whether one is arithmetic shifting by a
positive or a negative amount. An arithmetic left shift by a negative
amount, `A sll -B`

, is defined as being an arithmetic right
shift by a positive amount, `A srl B`

. For an arithmetic left
shift by a positive amount the sign bit is the leftmost bit. But for an
arithmetic right shift by a positive amount the sign bit is the rightmost
bit; hence an arithmetic shift left by a negative amount the sign bit is
also the rightmost bit. Thus changing the sign of the shift count
*also* changes which bit of the shiftend is treated as the sign
bit. Clearly, this is hardly ever useful.

A third consequence is that this is simply not what hardware designers
expect. A hardware designer who naïvely thinks that "srl" and "sra"
stand for "shift right logical" and "shift right arithmetic" will be
surprised to find that (a) the "srl" operator does arithmetic shifts under
some circumstances, and (b) the "sra" operator isn't even defined *at
all* for `ieee.numeric_std`

types.

Eventually, these problems were recognized, and the overloads for the shift
operators were removed from the `ieee.numeric_std`

and
`ieee.numeric_bit`

packages. So even if your VHDL synthesis or
simulaton tool supports these operators, don't use them. Use the functions.
They were the original idea. They don't have all of these problems and
unexpected pitfalls and consequences. They just work.

© Copyright 2008 Jonathan de Boyne Pollard. "Moral" rights asserted.

Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.