Source

Index

# Bit Shifter

This module is a building block for application-specific shifts and rotates. It synthesizes to LUT logic and can be quite large if not specialized to a particular situation.

## A Warning About Shift Right and Signed Division

While a left shift by N is always equivalent to a multiplication by 2N for both signed and unsigned binary integers, an arithmetic shift right by N is only a truncating division by 2N for positive binary integers. For negative integers, the result is so-called modulus division, and the quotient ends up off by one in magnitude, and must be corrected by adding +1, but only if an odd number results as part of the intermediate division steps. That is, if a non-zero bit was shifted out to the right.

## Usage

We can treat the `shift_amount` and the `shift_direction` together as a signed magnitude number: the amount is an absolute value, and the direction is the sign of the value. Here, a `shift_direction` of `1`, meaning a negative number, shifts to the right. Choosing this convention for the sign matches the behaviour of a shift when we think about it as a multiplication or division by a power of 2:

• Multipliying by 8 is equivalent to 23N, which is a shift-left by 3 steps.
• Dividing N by 4 is equivalent to 2-2N, which is a shift-right by 2 steps.

Adding together these multiples and fractions generated by the shifts enables the creation of small, cheap scaling by constant ratios:

• 3N = N + 21N
• 10N = 8N + 2N = 23N + 21N
• 5N/4 = N + N/4 = N + 2-2N
• etc...

When the shift values are constant, the shifter reduces to simple rewiring, which in turn reduces the above examples to an adder or two each.

The shifts are internally unsigned and `word_in` and `word_out` are extended to the left and right so new bits can be shifted in and current bits shifted out without loss, regardless of shift amount or direction, which enables the creation of more complex shifts or rotates:

• Wire the most-significant bit (MSB) of `word_in` to all `word_in_left` inputs and zero to all `word_in_right` inputs to create a signed arithmetic shift.
• Wire the `word_in` MSB to `word_in_right` MSB (or vice-versa) to create a rotate function.
• Feed `word_out_left` and `word_out` to a double-word adder and set the shift to +1 (left by 1) as part of the construction of a conditional-add multiplier, which multiplies two N-bit words in N cycles, giving a 2N-bit result.
````default_nettype none

module Bit_Shifter
#(
parameter   WORD_WIDTH  = 0
)
(
input   wire    [WORD_WIDTH-1:0]    word_in_left,
input   wire    [WORD_WIDTH-1:0]    word_in,
input   wire    [WORD_WIDTH-1:0]    word_in_right,

input   wire    [WORD_WIDTH-1:0]    shift_amount,
input   wire                        shift_direction, // 0/1 -> left/right

output  reg     [WORD_WIDTH-1:0]    word_out_left,
output  reg     [WORD_WIDTH-1:0]    word_out,
output  reg     [WORD_WIDTH-1:0]    word_out_right
);
```

Let's document the shift direction convention again here, and define our initial values for the outputs and the intermediate result.

```    localparam  LEFT_SHIFT  = 1'b0;
localparam  RIGHT_SHIFT = 1'b1;

localparam  TOTAL_WIDTH = WORD_WIDTH * 3;
localparam  TOTAL_ZERO  = {TOTAL_WIDTH{1'b0}};
localparam  WORD_ZERO   = {WORD_WIDTH{1'b0}};

initial begin
word_out_left    = WORD_ZERO;
word_out         = WORD_ZERO;
word_out_right   = WORD_ZERO;
end

reg [TOTAL_WIDTH-1:0] word_in_total = TOTAL_ZERO;
```

Rather than do arithmetic and calculate slices of vectors to figure out where the shifted bits end up, let's concatenate the input words into one triple-wide word, shift it as an unsigned number, then deconcatenate the result into each output word. All we have to do is keep the same convention on bit significance: here LSB is on the right.

```    always @(*) begin
word_in_total = {word_in_left, word_in, word_in_right};
{word_out_left, word_out, word_out_right} = (shift_direction == LEFT_SHIFT) ? word_in_total << shift_amount : word_in_total >> shift_amount;
end

endmodule
```

fpgacpu.ca