Arithmetic and logical shifts and rotates are done with functions in VHDL, not operators.

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.