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.