Taken from the Verilog-2001 Language Reference Manual (LRM) standard example since $clog2() doesn't exist prior to Verilog-2005 (and thus, SystemVerilog).
This returns the necessary number of bits to index N items with a binary integer. For example:
Bring in the function at the start of the body of your module like so:
`include "clog2_function.vh"
Pass the function a value which, at elaboration time, is either a constant or an expression which evaluates to a constant. Then use that value as an integer for a localparam, genvar, etc...
You don't need this function often, but it's very handy when a module receives some item count as a parameter, and you need to create an internal register to hold an index to those items (e.g.: a binary counter).
We use a temp value for calculations since Vivado raises warnings if we internally assign a value to a function input port.
Since this is an included file, it must be idempotent. (defined only once globally)
`ifndef CLOG2_FUNCTION
`define CLOG2_FUNCTION
function integer clog2;
input integer value;
integer temp;
begin
temp = value - 1;
for (clog2 = 0; temp > 0; clog2 = clog2 + 1) begin
temp = temp >> 1;
end
end
endfunction
`endif