Search code examples
verilogiverilog

Verilog error : A reference to a wire or reg is not allowed in a constant expression


I'm new to Verilog and I would really appreciate it if someone could help me out with this error:

output  reg [0:image_width][image_height:0]    result
....
integer i, j, imageX, imageY, x, y, kernelX, kernelY;
....

@(negedge ACLK)
for(x = 0; x < image_width; x++) begin 
    for(y = 0; y < image_height; y++)
    begin
    //multiply every value of the filter with corresponding image pixel
        for(kernelX = 0; kernelX < kernel_width; kernelX++) begin            
            for(kernelY = 0; kernelY < kernel_height; kernelY++)
                begin           
                    imageX = (x - kernel_width / 2 + kernelX + image_width) % image_width;
                    imageY = (y - kernel_height / 2 + kernelY + image_height) % image_height;

                    // ignore input samples which are out of bound
                    if( imageY >= 0 && imageY < image_height && imageX >= 0 && imageX < image_width )
                        //ERROR HERE!!!
                        result[x][y] += image[imageX][imageY] * kernel[kernelX][kernelY];   
                    end
                end
        end
    end
end

The error I get is:

error: A reference to a wire or reg ('x') is not allowed in a constant expression.
error: Array index expressions must be constant here.
error: A reference to a wire or reg ('imageX') is not allowed in a constant expression.
error: Array index expressions must be constant here.
error: A reference to a wire or reg ('kernelX') is not allowed in a constant expression.
error: Array index expressions must be constant here.

Could somebody tell me what I'm doing wrong? Thank you!


Solution

  • This line is the problem:

    result[x][y] += image[imageX][imageY] * kernel[kernelX][kernelY];
    

    Indexing into arrays is only allowed for constant expressions. You are not allowed to use variables in vector indexes. Remember that you're working with an HDL: you're dictating physical connections in hardware. Having a variable in the index implies the ability to dynamically rewire the circuit. This SO question has some rough workarounds that may work for you. However, you should really try to refactor your algorithm to avoid the need to use the variable indexing in the first place.

    By the way, you should be using non-blocking assignments instead of the blocking assignments you currently have. Your code is in a clocked block, so blocking combinational logic should be avoided:

    imageX <= (x - kernel_width / 2 + kernelX + image_width) % image_width;
    imageY <= (y - kernel_height / 2 + kernelY + image_height) % image_height;
    
    // ignore input samples which are out of bound
    if( imageY >= 0 && imageY < image_height && imageX >= 0 && imageX < image_width )
        result[x][y] <= result[x][y] + image[imageX][imageY] * kernel[kernelX][kernelY];