2
\$\begingroup\$

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 ?

\$\endgroup\$
  • 2
    \$\begingroup\$ What problem are you trying to cure with this function? If you're trying to describe hardware in the abstract you could use ranged integers for your counters. Synthesis does a wonderful job of converting to the right number of bits. If you're trying to describe hardware you're making it look hard. There's also a function in the body of package numeric_std named UNSIGNED_NUM_BITS that makes a nice simple model. \$\endgroup\$ – user8352 Aug 8 '15 at 9:47
  • \$\begingroup\$ @user1155120, if you post this as an answer, I will mark it as accepted. \$\endgroup\$ – Xion345 Aug 8 '15 at 15:20
4
\$\begingroup\$

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);
\$\endgroup\$
  • \$\begingroup\$ I should have mentionned that I always use the result of this function as an upper bound. And for x > 2.0, ceil(log2(x)) - 1 == floor(log2(x)) \$\endgroup\$ – Xion345 Aug 8 '15 at 15:16
  • \$\begingroup\$ @Xion345 This is only true if x is not a power of 2. But your problem remains: the width (bits) of an integer is ceil(log2(N)). It works in your case of zero-indexed vectors, but the function's result does not fit to it's name. \$\endgroup\$ – Paebbels Aug 8 '15 at 15:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.