VHDL: Finding out/reporting bit width/length of integer (vs. std_logic_vector)?
Asked Answered
D

4

6

Say I need a signal to represent numbers from 0 to 5; obviously this needs 3 bits of std_logic to be represented (i.e if MAXVAL=5, then bitwidth= {wcalc "floor(logtwo($MAXVAL))+1"}).

I'm aware I could do:

SIGNAL myLogicVector : STD_LOGIC_VECTOR(2 downto 0) := 5; 

with which I'd explicitly specify an array of three std_logic 'bits', and set initial value; then I could use REPORT to print out the length (in this case, 3):

report("Bit width of myLogicVector is "& integer'image(myLogicVector'length));

So far, so good. But, let's say I use an integer (number) type instead:

SIGNAL myInteger : NATURAL range 0 to 5 := 5;

I'm guessing that here the 'compiler' ('synthesizer') would automatically infer that it needs 3 bits of storage length, as this integer is ranged with values between 0 and 5. If that is the case, my question is: is it possible to somehow print out this bit width/length/size in a REPORT?

The trick is, of course, that something like this:

report("Bit width of myInteger is "& integer'image(myInteger'length));

... will fail (say, with "HDLParsers:3389 - Prefix of attribute 'length must be an array object"), since as far as I gather, all these attributes like 'length and 'range are applicable only to arrays (Understanding VHDL Attributes), whereas an integer (natural) is not an array - it is a number :) (VHDL vector integer conversion question)

Again, I'm aware I could possibly utilize a log2 (Computing the width of an unsigned variable from maximum value?) - but what I'd like is just to see quickly (during synthesis) how many 'bits' the 'synthesizer' allocated for an eventual synthesized design, and thus approx how much would be used in terms of final FPGA resources (especially if I'd use 'generics' to somehow calculate a particular max value for an integer).

Well, thanks in advance for any responses, Cheers!

EDIT: a bit of context: I'm using ISE Webpack 9.2; I'm trying to use 'generic' variables/constants as parameters, and then use equations to calculate max values for counters. This calculation, I guess occurs at 'compile' time (which would be 'Synthesize' in ISE - not 'Implement Design'), and so it is here where I want the report messages to occur (and I in fact got them so, for std_logic_vector proper, in the synthesis log - however, the same report messages for me occur at start of behavioral simulation too, which is fine).

And the goal of these report messages is to make sure both that my equations are OK, and that the synthesizer will not try to infer a 32-bit counter - even if I want to count just from 0 to 5 :)

Dignitary answered 4/3, 2011 at 14:49 Comment(4)
Hi Sdaau. Just to clarify, do you want this information at compile time, or post synthesis? If post synthesis, which synthesis tool are you using?Cookie
Hi @George, thanks for your comment! I have added a bit of clarification to the OP; I guess what I want is messages at 'compile' time (except, the way I see it, for ISE at least: compile time = synthesis?!)Dignitary
No, you cannot assign value integer 5 to a vector. You can try to assign bit string literal "101".Bonne
Hi @Phillipe, thanks for the comment! I guess one could always use a conversion like 'std_logic_vector(to_unsigned(5, x'length)' - but then, you need to specify the bit width by hand; I was otherwise looking for a way for the synthesizer to tell me automatically the needed bit width :) Cheers!Dignitary
P
2

I'm guessing that here the 'compiler' ('synthesizer') would automatically infer that it needs 3 bits of storage length, as this integer is ranged with values between 0 and 5

According to the spec it should, but it is not required. From IEEE 1076.6-2004:

1.3 Terminology

The word shall indicates mandatory requirements strictly to be followed in order to conform to the standard and from which no deviation is permitted (shall equals is required to). The word should is used to indicate that a certain course of action is preferred but not necessarily required;

8.3.1.2 Integer Types

It is recommended that a synthesis tool should convert a signal or variable that has an integer subtype indication to a corresponding vector of bits. If the range contains no negative values, the item should have an unsigned binary representation. If the range contains one or more negative values, the item should have a twos-complement implementation. The vector should have the smallest width consistent with these representations.

The synthesis tool shall support integer types and positive, negative, and unconstrained (universal) integers whose bounds lie within the range –2 147 483 648 to +2 147 483 647 inclusive (the range that successfully maps 32 bit twos-complement numbers)

Example: “INTEGER range 9 to 10” should be synthesized using an equivalent vector length of 4 bits, just as if it had been defined with a subtype indication of “INTEGER range 0 to 15”.

I can say definitively at least one synthesis tool does not use range in this manner as I had to debug the formal verification miscompares.

For Xilinx FPGAs, the XST synthesis report will tell which storage elements have unused bits, but not simple wires.

Pentaprism answered 4/3, 2011 at 16:26 Comment(5)
Hi @Adam12, thanks and +1 for your answer! Just a little clarification - does that mean that for an 'integer' type, it is in principle impossible to get the used bitwidth during the synthesis step, as it is specified to be 32 bit for 'integer' - and possible only after the (in lack of better term) implementation (i.e. after place & route steps?)? Thanks again for the answer - cheers!Dignitary
Hi sdaau. You don't need to run PAR to get the register count. This is done with XST which is the very first step. Look in the .syn file.Pentaprism
This is not correct. The range constraint is part of the subtype indication. There is no reason why a synthesis tool would not take it into account upfront, before logic optimization.Capstone
INTEGER is nearly 32 bits, but not quite. The language spec calls for +/- (2^32)-1 to be supported, but not -2^32.Chacon
I don't know of other synthesizers, but Quartus II does NOT ignore the range. You can easily verify that it generates a more efficient design with less logic resources if you restrict the range of your signal/variable by subtyping Integer.Upturn
C
6

In principle, the representation of a VHDL integer is undefined.

In practice, you can normally assume that a synthesis tool will use a 2's complement representation, taking into account the range constraint. Therefore, the relation between the range constraint and the implemented bit width is straightforward, even though reporting the bit width from within VHDL is not.

Capstone answered 5/3, 2011 at 12:17 Comment(0)
P
2

I'm guessing that here the 'compiler' ('synthesizer') would automatically infer that it needs 3 bits of storage length, as this integer is ranged with values between 0 and 5

According to the spec it should, but it is not required. From IEEE 1076.6-2004:

1.3 Terminology

The word shall indicates mandatory requirements strictly to be followed in order to conform to the standard and from which no deviation is permitted (shall equals is required to). The word should is used to indicate that a certain course of action is preferred but not necessarily required;

8.3.1.2 Integer Types

It is recommended that a synthesis tool should convert a signal or variable that has an integer subtype indication to a corresponding vector of bits. If the range contains no negative values, the item should have an unsigned binary representation. If the range contains one or more negative values, the item should have a twos-complement implementation. The vector should have the smallest width consistent with these representations.

The synthesis tool shall support integer types and positive, negative, and unconstrained (universal) integers whose bounds lie within the range –2 147 483 648 to +2 147 483 647 inclusive (the range that successfully maps 32 bit twos-complement numbers)

Example: “INTEGER range 9 to 10” should be synthesized using an equivalent vector length of 4 bits, just as if it had been defined with a subtype indication of “INTEGER range 0 to 15”.

I can say definitively at least one synthesis tool does not use range in this manner as I had to debug the formal verification miscompares.

For Xilinx FPGAs, the XST synthesis report will tell which storage elements have unused bits, but not simple wires.

Pentaprism answered 4/3, 2011 at 16:26 Comment(5)
Hi @Adam12, thanks and +1 for your answer! Just a little clarification - does that mean that for an 'integer' type, it is in principle impossible to get the used bitwidth during the synthesis step, as it is specified to be 32 bit for 'integer' - and possible only after the (in lack of better term) implementation (i.e. after place & route steps?)? Thanks again for the answer - cheers!Dignitary
Hi sdaau. You don't need to run PAR to get the register count. This is done with XST which is the very first step. Look in the .syn file.Pentaprism
This is not correct. The range constraint is part of the subtype indication. There is no reason why a synthesis tool would not take it into account upfront, before logic optimization.Capstone
INTEGER is nearly 32 bits, but not quite. The language spec calls for +/- (2^32)-1 to be supported, but not -2^32.Chacon
I don't know of other synthesizers, but Quartus II does NOT ignore the range. You can easily verify that it generates a more efficient design with less logic resources if you restrict the range of your signal/variable by subtyping Integer.Upturn
C
-1

is it possible to somehow print out this bit width/length/size in a REPORT?

Basic maths:

Bit width = ceil(log2(my_integer + 1))

But VHDL requires a bit more effort...

Inline code:

use ieee.math_real.all;
...
report "Bit width of myInteger is " & integer'image(integer(ceil(log2(real(myInteger) + real(1)))));

As a function:

use ieee.math_real.all;
...
-- Returns the bit width of i as a positive integer.
function BitWidth(constant i: in positive) return positive is
begin
    return positive(ceil(log2(real(i) + real(1))));  -- Add one to prevent errors when i = 2**n
end function;

-- Overload for returning the string representation of the bit width of i.
function BitWidth(constant i: in positive) return string is
    variable bit_width: positive := BitWidth(i);
begin
    return positive'image(bit_width);
end function;

signal myInteger: positive := 8;
...
report "Bit width of myInteger is " & BitWidth(myInteger);

You can put these functions in a package of helper functions.

Chouest answered 15/12, 2020 at 14:20 Comment(0)
L
-2

This can be solved as follows:

First, declare a new (sub)type representing the range that should be used for myInteger. (Then declare myInteger as a signal of this type, not directly of the integer range).

Then, declare a dummy array type using the declared range as index range, and then use the 'length of that:

subtype myInteger_range is natural range 0 to 5;
signal myInteger : myInteger_range;
type myInteger_dummy_array is array (myInteger_range) of boolean; -- or whatever
report integer'image(myInteger_dummy_array'length); --> "6"
Legislative answered 16/9, 2016 at 21:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.