Electronic – Standard integer width function in VHDL

vhdl

I find my self using a function which returns the number of bits necessary to represent an integer value a lot in my designs.

I define this function in each of my modules:

function int_width(value: integer) return integer is
begin
    return integer(floor(log2(real(value))));
end function;

Example use:

entity vga_sync is
    generic(
        TOTAL_WIDTH: integer := 800;
        TOTAL_HEIGHT: integer := 525;
        -- [...]
    port(
    -- [...]
    );
end vga_sync;

architecture arch of vga_sync is
    signal horizontal_counter: unsigned(int_width(TOTAL_WIDTH) downto 0);
    signal vertical_counter: unsigned(int_width(TOTAL_HEIGHT) downto 0);
    -- [...]
end arch;

It seems to be a common issue to me. Is there a standard function in VHDL to do this ?
Should I always use a large enough (ie, always 32 bits) unsigned is these cases ?

Best Answer

First of all you should extract this function into a VHDL package and use this packages in your modules. So it's only declared once. Functions from a package can also be used in the entity definition.

VHDL does not have an integrated function to shorten your function.

Second, your calculation is not correct. The number of needed bits to encode N combinations is always greater or equal to log2(N). So you need to round up (ceil(...)) not down (floor(...)). Because bit-vectors are zero-indexed, the upper boundary is log2(N)-1.

An integer based log2 function which automatically performs a round-up can be defined as follows:

function log2ceil(arg : positive) return natural is
    variable tmp : positive     := 1;
    variable log : natural      := 0;
begin
    if arg = 1 then return 0; end if;
    while arg > tmp loop
        tmp := tmp * 2;
        log := log + 1;
    end loop;
    return log;
end function;

Source: PoC.utils package

Example:

signal vertical_counter: unsigned(log2ceil(TOTAL_HEIGHT) - 1 downto 0);
Related Topic