Verilog Barrel Shifter

I want to create a 64-bit barrel shifter in verilog (rotate right for now). I want to know if there is a way to do it without writing a 65 part case statement? Is there a way to write some simple code such as:

 Y = {S[i - 1:0], S[63:i]}; 

I tried the code above in Xilinx and get an error: i is not a constant.

Main Question: Is there a way to do this without a huge case statment?

0

2 Answers

I've simplified some of the rules for clarity, but here are the details.

In the statement

Y = {S[i - 1:0], S[63:i]}; 

you have a concatenation of two signals, each with a constant part select. A constant part select is of the form

identifier [ constant_expression : constant_expression ]

but your code uses a variable for the first expression. As you saw this isn't allowed, but you are correct in that there are ways to avoid typing a large case statement. What you can use instead is an indexed part select. These are of the form

identifier [ expression +: constant_expression ]

identifier [ expression -: constant_expression ]

These constructs enforce that the width of the resulting signal is constant, regardless of the variable on the left side.

wire [HIGH_BIT:LOW_BIT] signalAdd,signaSub; signalAdd[some_expression +: some_range]; signalSub[some_expression -: some_range]; //Resolves to signalAdd[some_expression + (some_range - 1) : some_expression]; signalSub[some_expression : some_expression - (some_range - 1)]; //The location of the high value depends on how the signal was declared: wire [15: 0] a_vect; wire [0 :15] b_vect; a_vect[0 +: 8] // a_vect[7 : 0] b_vect[0 +: 8] // b_vect[0 : 7] 

Rather than trying to build one signal out of two part selects, you can simply extend the input signal to 128 bits, and use a variable part select from that.

wire [63:0] data_in,data_out; wire [127:0] data_in_double; wire [5:0] select; //Concatenate the input signal assign data_in_double = {data_in,data_in}; //The same as signal[select + 63 : select] assign data_out = data_in_double[select+63-:64]; 

Another approach you could use is generate loops. This is a more general approach to replicating code based on a variable. It is much less efficient since it creates 4096 signals.

wire [63:0] data_in,data_out; wire [127:0] data_in_double; wire [5:0] select; wire [63:0] array [0:63]; genver i; //Concatenate the input signal assign data_in_double = {data_in,data_in}; for(i=0;i<64;i=i+1) begin : generate_loop //Allowed since i is constant when the loop is unrolled assign array[i] = data_in_double[63+i:i]; /* Unrolls to assign array[0] = data_in_double[63:0]; assign array[1] = data_in_double[64:1]; assign array[2] = data_in_double[65:2]; ... assign array[63] = data_in_double[127:64]; */ end //Select the shifted value assign data_out = array[select]; 
6

The best way I found to do this is finding a pattern. When you want to rotate left an 8 bit signal 1 position (8'b00001111 << 1) the result is = 8'b00011110) also when you want to rotate left 9 positions (8'b00001111 << 9) the result is the same = 8'b00011110, and also rotating 17 positions, this reduce your possibilities to next table:

PATTERN_TABLE

so if you look, the tree first bits of all numbers on table equivalent to rotate 1 position (1,9,17,25...249) are equal to 001 (1)

the tree first bits of all numbers on table equivalent to rotate 6 positions (6,14,22,30...254) are equal to 110 (6)

so you can apply a mask (8'b00000111) to determine the correct shifting number by making zero all other bits:

reg_out_temp <= reg_in_1 << (reg_in_2 & 8'h07);

reg_out_temp shall be the double of reg_in_1, in this case reg_out_temp shall be 16 bit and reg_in_1 8 bit, so you can get the carried bits to the other byte when you shift the data so you can combine them using an OR expression:

reg_out <= reg_out_temp[15:8] | reg_out_temp[7:0];

so by two clock cycles you have the result. For a 16 bit rotation, your mask shall be 8'b00011111 (8'h1F) because your shifts goes from 0 to 16, and your temporary register shall be of 32 bits.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like