Search code examples
verilogbit-shift

Verilog "not a constant" error on bit-rotation


I have this block of code. I am trying to rotate WNext by the lower 4 bits of data_fromRAM.

input clk, rst;

input wire [15:0] data_fromRAM;
output reg [15:0] data_toRAM;
output reg wrEn;

// 12 can be made smaller so that it fits in the FPGA
output reg [12:0] addr_toRAM;
output reg [12:0] PC; // This has been added as an output for TB purposes
output reg [15:0] W; // This has been added as an output for TB purposes

reg [12:0] PCNext;
reg [ 2:0] opcode, opcodeNext,state, stateNext;
reg [12:0] operand, operandNext;
reg [15:0] num, numNext, WNext;

always @*begin
    WNext = W;
    PCNext = PC;
    stateNext    = state;
    opcodeNext   = opcode;
    operandNext = operand;
    numNext     = num;
    addr_toRAM   = 0;
    wrEn         = 0;
    data_toRAM   = 0;
//here I have if(rst)
else 
    case(state)
//other cases
        2: begin
            PCNext = PC + 1;
            WNext = W;
            opcodeNext   = opcode;
            operandNext = operand;
            addr_toRAM   = 0;
            numNext     = data_fromRAM;
            wrEn         = 0;
            data_toRAM   = 0;
            stateNext    = 0;
            case (opcodeNext)
                ... //I excluded other cases
                3'b010: begin //SRRL
                    if(data_fromRAM < 16) WNext = W >> data_fromRAM;
                    else if (data_fromRAM > 16 & data_fromRAM < 31) WNext = W << data_fromRAM[3:0];
                    else if (data_fromRAM > 32 & data_fromRAM > 47) WNext = {W[data_fromRAM[3:0] - 1:0], W[15:data_fromRAM[3:0]]};
                    else WNext = {W[15 - data_fromRAM[3:0]:0], W[15:16 - data_fromRAM[3:0]]};
                end

But I am getting the error:

data_fromRAM is not a constant.

How can I fix this error? Is there a way to copy data_fromRAM into a constant variable and then do the operations? Or should I take a different approach?

Note: output reg [15:0] datatoRAM;

edit : If data_fromRAM = 40, then with this line: WNext = {W[data_fromRAM[3:0] - 1:0], W[15:data_fromRAM[3:0]]}; I am trying to rotate WNext right with the four least significant bits of data_fromRAM. 40 is equal to 101000 in binary and the four lowest bits give us 1000 which is 8 in decimal. So I will rotate WNext right by 8 bits and what I mean by rotate is basically shifting but new bits are the ones we were going to lose if we only did the shifting (eg. rotate 1000110 by 3 = 1101000)

If data_fromRAM is greater than 47, again I want to rotate WNext but this time left rather than right (again it's rotating by lowest four bits of data_fromRAM). So again, as in shifting, I want to move all the values to the left but the bits that are coming from right are the ones that were lost from left when shifting.


Solution

  • As the error message shows, you need to have a constant value for the bit select expression. The expression within the outer brackets must be a constant at elaboration/compile time:

    W[15 - data_fromRAM[3:0]:0]
    

    You can not copy the variable data_fromRAM into a constant.

    I believe you need a different approach, but it is difficult to know what you are trying to do from the little that you have shown.

    Also, this is a bug:

    else if (data_fromRAM > 32 & data_fromRAM > 47)
    

    I think you meant to use < 47:

    else if (data_fromRAM > 32 & data_fromRAM < 47)
    

    I think you want to change:

    WNext = {W[data_fromRAM[3:0] - 1:0], W[15:data_fromRAM[3:0]]};
    

    to:

    WNext = (W >> data_fromRAM[3:0]) | (W << (16-data_fromRAM[3:0]));
    

    And change:

    WNext = {W[15 - data_fromRAM[3:0]:0], W[15:16 - data_fromRAM[3:0]]};
    

    to:

    WNext = (W << data_fromRAM[3:0]) | (W >> (16-data_fromRAM[3:0]));
    

    I leveraged the idea from this answer.