Operator | Name | Fills with | Typical use |
|---|---|---|---|
| Shift left | 0 in the low bits | Multiply by 2ᵏ (unsigned or signed) |
| Logical shift right | 0 in the high bits | Unsigned divide by 2ᵏ, field extraction |
| Arithmetic shift right | Sign bit, if the operand is signed | Signed divide by 2ᵏ, rounding toward −∞ (not toward 0 like /) |
Read each row against the top one: every bit moves one cell, and the orange cell is the one the operator had to invent.
`<<` always fills with 0 at the right, so -5 becomes -10.
`>>` fills with 0 even on a signed value, so -5 turns into the positive number 125.
`>>>` copies the sign bit when the operand is signed, so -5 becomes -3 (rounded toward negative infinity, as the warning below explains).
Shifting by a constant costs no logic; it is only wiring. Shifting by a variable amount builds a barrel shifter, a multiplexer network whose depth grows with the shift width.
Rotation has no operator. It is a concatenation.
Write a * 8 or a << 3: both synthesize to the same wiring. Prefer the one that reads as your intent.
Multiplication by a small constant (for example x * 5) becomes shift-and-add ((x << 2) + x); the tool does this for you.
Division and modulo by a non-power-of-two are expensive and slow. Restructure the algorithm or use a multi-cycle divider rather than writing a / 7 in a single-cycle path.
A variable shift amount adds a mux stage per bit of the shift count; keep the count narrow.
x by 10 without a *.(x << 3) + (x << 1): eight times plus two times. The result needs up to 12 bits (255·10 = 2550), so declare it wide enough.
The testbench below checks rotation, rounding of shifts versus division, and scaling by a shift.
module tb_shift;
logic [7:0] r = 8'b1001_0110;
logic signed [7:0] s = -8'sd5;
int errors = 0;
initial begin
// rotate left / right by 1
if ({r[6:0], r[7]} !== 8'b0010_1101) errors++;
if ({r[0], r[7:1]} !== 8'b0100_1011) errors++;
// divide a negative number by 2: shift rounds toward -infinity, division toward zero
if ((s >>> 1) !== -8'sd3) errors++; // -5 >>> 1 = -3
if ((s << 1) !== -8'sd10) errors++; // -5 << 1 = -10 (1111_0110)
if ((s >> 1) !== 8'sd125) errors++; // >> fills with 0 even when s is signed: 0111_1101
if ((s / 8'sd2) !== -8'sd2) errors++; // -5 / 2 = -2
$display("-5 >>> 1 = %0d, -5 / 2 = %0d", s >>> 1, s / 8'sd2);
// multiplying by a constant power of two is a left shift
if ((8'd5 << 2) !== 8'd20) errors++;
if (errors != 0) $fatal(1, "FAIL: shift errors=%0d", errors);
$display("PASS: shifts and rounding as described");
$finish;
end
endmodule