Enhanced integers


Proposal Details

  • Who Updates: JonasBaggett
  • Date Proposed: 2016-07-30
  • Date Last Updated: 2016-08-02
  • Priority:
  • Complexity: Medium, I think.
  • Focus: Synthesis; also simulation to a lesser extent

Current Situation

Currently the best option to do integer arithmetics for synthetizable code is to work with the types signed/unsigned from numeric_std which forces the user to do low level programming all the time (like size calculation and resizing vectors). It is true that low-level programming is unavoidable when interfacing an external entity, but as soon as you go inside your design, the need to specify the physical representation of the signals decreases.

Secondly, the numeric_std signed/unsigned types are actually defined as arrays of std_logic, a nine value enumeration type, with arithmetic and binary operations added, which leads to weirdness and performance issues. It would be more natural both for the user and the compiler (by compiler I mean : simulator or synthetizer) to use real integers, hence both the user and the compiler become more efficient. Unfortunetely with current VHDL, integer types have too much limitations for synthetizable code.

Introduction

I have written some code here example_1.vhd that is valid with current VHDL but which would help to introduce the point I would like to make.

Since Top interfaces an external entity, it is absolutely necessarly to do low level programming and specify the length of its port signals. But for the signals inside the design (here : AE, BE, CE, DE), I don't see, in this simple case, a need for that much specifications.

So basically, here are the (slighty simplified) specifications that are to be met by the compiler :

  • A and B have 8 bits; C has 24
  • Convert A and B into a natural integer and assign them to AE, respectively BE
  • Assign AE + BE to DE (and no overflow allowed)
  • Assign DE * BE to CE (and no overflow allowed)
  • Convert CE into a std_logic_vector and assign it to C (and no overflow allowed).
As long as these specifications are met, we don't care about the bit size of AE, BE, CE and DE. We are actually giving to the compiler the constraints that are really necessarly for us and giving it the freedom of the physical implementation on what we don't specify because it doesn't really matter for us. More freedom means more ability for the compiler to produce optimized code. Of course there are cases when the compiler needs more informations and must complain if they are lacking. For example if a signal is an accumulator, we need to specify it's range or size because the compiler cannot guess how much the accumulator is supposed to grow; that's of course the user who has to find out what are his needs and specify the range or size accordingly.

Now the user can concentrate more on its design than on questions like « how much bits is needed after multiplying N1 bits by N2 bits and sustracting a number of N3 bits ? » which could be calculated by the compiler. Letting the compiler find the size when it's obvious allows a gain of developpement time and a reduction of bugs due to incorrect size calculations that leads either to overflows which still need to be catched, most of the time by analyzing the waves, or to bad optimized code if more bits are used than needed.

The goal of this proposal is to add new integer types, the binary integer types, which inheritate all the properties of standard integer types but have some more properties.

Requirement

  • The above rule about size calculations will apply to these new types, unless otherwise specified.
  • Some extensions need to be added to the type declaration mechanism of VHDL (see remarks on implementation details).

  • We need to specify integers whose maximal ranges isn't limited as suggested in ArbitraryIntegers.

  • With the integers types, a constraint error will raise in case of an overflow. But it is not yet possible to use modulo integers. So a first enhancement would be to allow to create modulo integer types (as already suggested with Modular Integer Types, but I will present a different way).

  • Binary operations should be allowed on the binary integer types, which should answer the IntegerOperators proposal. Not only using conversion functions to do binary operations is painful, but by nature, binary integers should have a binary representation accessible. Therefore I suggest to add a 'bits attribute on binary integers that returns a bit_vector representing its bits. This attribute will be read/write and will enable binary operations. The binary representation will be a standard 2's complement. The user may want a different binary representation than the default one. Then I think we should make this attribute overridable so that the user can create his own functions/procedures for the 'bits attribute. Therefore I suggest the use of attribute getters/setters that follow the same principle as Python properties. Extended User-Defined Attributes proposal seems to address this issue.

    With the suggested implementation for binary operations on the new integer types (see below), the following proposals are required (at least partially) :

Implementation details

So here is a suggested implementation of integers types that can meet the proposal goals while, AFAIK, still keeping backward compatibility.

I will start with the types definition here : types_definitions.vhd.

Currently (2016.08.02), proposal Extended User-Defined Attributes is incomplete and no implemention is suggested. Therefore I also suggest an implementation for user defined attribute getters/setters. Here is an example for a one's complement signed that require the overriding of the 'bits attribute : bits_attribute.vhd.

Remarks

Some extensions were needed to the type declaration mechanism of VHDL :

  1. It was necessary to borrow from ada the derived types feature in order to create types that are incompatible without an explicit cast. (see https://en.wikibooks.org/wiki/Ada_Programming/Type_System#Derived_types)
  2. Since new properties (or attributes) need to be set to integer types, a mechanism was created to allow that.

Code Examples

Then here is some VHDL code using these types : example_2.vhd

Remarks

  • Size and range properties are either set by the compiler, or by the user. When properties aren't set by the user, the compiler set them to the minimum possible. Here are some examples :
    signal A : Unsigned; -- Size and range set by the compiler to the minimum possible
    signal B : Unsigned with Size => 8 -- Range 0 to 255; set by the compiler
    signal C : Unsigned range 0 to 99  -- Size >= 7; set by the compiler. Size = 7 when possible. Impossible if there is such an assignment :
                                       -- C'Bits <= Bit_Vect_Sig, where Bit_Vect_Sig'Length > 7
    signal D : Unsigned range 0 to 99 with Size => 9 -- Ok
    signal E : Unsigned range 0 to 99 with Size => 6 -- Error : the given range exceeds the size
  • If we assign signals of different size, the same rules apply than with standard integers because they have a range, either defined by the user or by the compiler. Here are some examples :
    signal E1, E2 : Unsigned with Size => 8; -- range 0 to 255, calculated by the compiler
    signal F1, F2 : Unsigned with Size => 4; -- range 0 to 15, calculated by the compiler
    signal G : Mod_Unsigned with Size => 4;  -- range 0 to 15, calculated by the compiler
    (...)
    F1 <= E1; -- A constraint error will be raised if the value of E1 exceeds F1 range
    G  <= Mod_Unsigned (E1); -- OK, even if the value of E1 exceeds G range because a modulo operation will be made
    E2 <= F2; -- Always OK because E2'Size > F2'Size

Open questions

  • With numeric_std signed/unsigned signals, it is easy for the user to see if he forgets to initialize a signal because it's value is set to unitialized. Is there a way to mitigate the lack of this feature in binary integer signals ?

Related Issues

Arguments FOR

Compared to the signed/unsigned types in numeric_std, I see the following advantages :

  • More high-level programming when possible, then the user can be more focused to his design.
  • Less error prone because the compiler does now a lot of size calculations that have to be done previously by the user.
  • Leads to a lot more readable code
  • It is now possible to define if a binary integer is modulo or not, then it is easier to catch unwanted overflows.
  • Easier for the compiler to do optimizations
  • Should address a good part of the issues reported by ArbitraryIntegers, LongIntegers, Modular Integer Types, IntegerOperators and ImplicitConversionNumeric.
It is also easy to extend to fixed and floating numbers.

Arguments AGAINST

General Comments

Thanks to PatrickLehmann for the inspiring discussions we had smile

Supporters

-- JonasBaggett - 2016-08-01

Add your signature here to indicate your support for the proposal

I Attachment Action Size Date Who Comment
Unknown file formatvhd bits_attribute.vhd manage 2.6 K 2016-08-03 - 10:51 JonasBaggett  
Unknown file formatvhd example_1.vhd manage 1.0 K 2016-07-30 - 19:59 JonasBaggett Example 1
Unknown file formatvhd example_2.vhd manage 2.5 K 2016-08-02 - 11:46 JonasBaggett  
Unknown file formatvhd types_definitions.vhd manage 1.5 K 2016-08-03 - 10:46 JonasBaggett  
Edit | Attach | Print version | History: r7 < r6 < r5 < r4 < r3 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r1 - 2020-02-17 - 15:34:52 - TWikiGuest
 
Copyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback