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?
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:
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.
I've simplified some of the rules for clarity, but here are the details.
In the statement
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.
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.
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.