问题
My task is to write a 16 bit ALU in verilog. I found difficulties when I do the part that needs to rotate the operand and doing the 2's complement addition and subtraction. I know how to work that out by paper and pencil but i cant figure out ways to do it in Verilog. for example: A is denoted as a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 if i am going to rotate 4 bits, the answer would be a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 a15 a14 a13 a12
i tried concatenation but it turns out to be incorrect. need you all help...
回答1:
Why is concatenation incorrect? This should do what you ask.
assign A_out[15:0] = {A_in[11:0], A_in[15:12]};
回答2:
The following will work using one shifter:
assign A_out = {A_in,A_in} >> (16-shift[3:0]);
When shift
is 0 the left A_in
is selected. As shift
increase the left A_in
shifts to the left and the MSBs of the right A_in
fills in.
If synthesizing, then you may want to use muxes, as dynamic shift logic tends require more gates. A 16-bit barrel shifter will require 4 levels of 2-to-1 muxes.
wire [15:0] tmp [3:1];
assign tmp[3] = shift[3] ? { A_in[ 7:0], A_in[15: 8]} : A_in;
assign tmp[2] = shift[2] ? {tmp[3][11:0],tmp[3][15:12]} : tmp[3];
assign tmp[1] = shift[1] ? {tmp[2][13:0],tmp[2][15:14]} : tmp[2];
assign A_out = shift[0] ? {tmp[1][14:0],tmp[1][15 ]} : tmp[1];
回答3:
assign A_out = A_in << bits_to_rotate;
Where bits_to_rotate
can be a variable value (either a signal or a reg).
This will infer a generic shifter using multiplexers, or a barrel shifter, whatever suits better the target hardware. The synthetizer will take care about that.
Oh, well. If you want to rotate instead of shift, the thing is just a bit trickier:
assign A_out = (A_in << bits_to_rotate) | (A_in >> ~bits_to_rotate);
回答4:
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 reduces your possibilities to next table:
So if you look, the three first bits of all numbers on tale equivalent to rotate 1 position (1,9,17,25...249) are equal to 001 (1).
The three 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 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.
来源:https://stackoverflow.com/questions/21191943/rotate-left-verilog-case