0
0
VerilogHow-ToBeginner · 4 min read

Verilog Code for Barrel Shifter: Syntax and Example

A barrel shifter in Verilog shifts input bits by a variable amount in one clock cycle using multiplexers. You can implement it using a combination of shift operations and conditional logic inside an always block or with continuous assignments using bit slicing and concatenation.
📐

Syntax

A barrel shifter module typically has inputs for the data to shift, the shift amount, and the direction, and an output for the shifted result.

The main parts are:

  • input [N-1:0] data_in: The data to be shifted.
  • input [M-1:0] shift_amt: The number of positions to shift.
  • input dir: Direction of shift (0 for left, 1 for right).
  • output reg [N-1:0] data_out: The shifted output.

The shifting is done inside an always @(*) block using a case or if statements to select the shift amount.

verilog
module barrel_shifter(
    input wire [7:0] data_in,
    input wire [2:0] shift_amt,
    input wire dir, // 0 = left shift, 1 = right shift
    output reg [7:0] data_out
);

always @(*) begin
    if (dir == 0) // left shift
        data_out = data_in << shift_amt;
    else // right shift
        data_out = data_in >> shift_amt;
end

endmodule
💻

Example

This example shows a barrel shifter that shifts an 8-bit input left or right by 0 to 7 bits. It uses an always block and shift operators.

When run in simulation, it outputs the shifted values for different shift amounts and directions.

verilog
module testbench();
    reg [7:0] data_in;
    reg [2:0] shift_amt;
    reg dir;
    wire [7:0] data_out;

    barrel_shifter uut(
        .data_in(data_in),
        .shift_amt(shift_amt),
        .dir(dir),
        .data_out(data_out)
    );

    initial begin
        data_in = 8'b10110011;

        // Test left shifts
        dir = 0;
        for (shift_amt = 0; shift_amt < 8; shift_amt = shift_amt + 1) begin
            #5;
            $display("Left shift by %0d: %b", shift_amt, data_out);
        end

        // Test right shifts
        dir = 1;
        for (shift_amt = 0; shift_amt < 8; shift_amt = shift_amt + 1) begin
            #5;
            $display("Right shift by %0d: %b", shift_amt, data_out);
        end

        $finish;
    end
endmodule
Output
Left shift by 0: 10110011 Left shift by 1: 01100110 Left shift by 2: 11001100 Left shift by 3: 10011000 Left shift by 4: 00110000 Left shift by 5: 01100000 Left shift by 6: 11000000 Left shift by 7: 10000000 Right shift by 0: 10110011 Right shift by 1: 01011001 Right shift by 2: 00101100 Right shift by 3: 00010110 Right shift by 4: 00001011 Right shift by 5: 00000101 Right shift by 6: 00000010 Right shift by 7: 00000001
⚠️

Common Pitfalls

Common mistakes when writing barrel shifters include:

  • Using arithmetic shift operators instead of logical shifts, which can fill with sign bits instead of zeros.
  • Not handling shift amounts larger than the data width, causing unexpected results.
  • Confusing left and right shift directions.
  • Not using always @(*) for combinational logic, which can cause simulation mismatches.
verilog
/* Wrong: arithmetic right shift fills with sign bit */
assign data_out = data_in >>> shift_amt; // Avoid for unsigned data

/* Right: use logical shift operators */
always @(*) begin
    if (dir == 0)
        data_out = data_in << shift_amt;
    else
        data_out = data_in >> shift_amt;
end
📊

Quick Reference

Tips for barrel shifter design:

  • Use logical shift operators << and >> for unsigned data.
  • Use always @(*) for combinational logic blocks.
  • Limit shift amount to the data width to avoid unexpected zeros.
  • Test both shift directions thoroughly.

Key Takeaways

A barrel shifter shifts data by a variable amount in one cycle using logical shifts.
Use always @(*) blocks for combinational barrel shifters in Verilog.
Avoid arithmetic shifts for unsigned data to prevent sign extension errors.
Test all shift amounts and directions to ensure correct behavior.
Limit shift amounts to the data width to avoid unexpected results.