Hello,
It seems to me it can be a good idea to add to VHDL a new attribute 'repr in order to be able to access the representation of a signal (bits) that is normally not accessible on most types (integer, records, enumerates, ...).
In the beginning of VHDL, if you want to do arithmetics on integers, you had to use the integer type. But there was a need of specifying a size, a range direction, easy access to the bits which was not possible with the integer type. Then came the Std_Logic_Arith which was a good solution on its time. Further, the IEEE made the numeric_std/numeric_bit packages that define the signed and unsigned type as an array of std_logic/bits. They were good packages but there is 2 or 3 things that bothers me :
* Doing arithmetics on arrays seems weird to me. The VHDL compilers consider the signed/unsigned types as arrays with some functions defined on it. They don't see them as numbers which leads to some strange situations like it is possible to add an integer to an (un)signed but not to affect an integer on it.
* We have already the integer type to do arithmetics on integer. After adding the signed/unsigned types, we have now to choose which type make more sense for each situation. Often they are redundant. Wouldn't be better to add some mecanisms on the integer type to allow to do what was missing on this type and have only one type (with the natural and positive subtypes) for arithmetics ?
With a new attribute 'repr and the "for ... use" clause taken from Ada, I think we can add what was missing to the integer type, as shows the following code :
So we have previously an utilisation of a 8 bits unsigned integer and how it is possible to access its bits as it is possible with the numeric_std unsigned type and how it is possible to do arithmetics as it is possible with the regular integer type.
There is a few more things missing :
* There is a limit (32 bits) on the Natural type. Then why not to add the Ada Base_Integer type to VHDL ? This type is an integer without range constraints. It is in Ada not allowed to use this type if we dont't add a range to it.
* Overflow is not possible but will raise an error, which is on some cases interesting, but often we want modulo integers. So I would propose to add a keyword (for example mod or modulo) to specify modulo integers.
So the declaration of My_Integer could be :
subtype My_Integer is Modulo Base_Natural; -- Same as Base_Integer but for Natural numbers only
And now I think that everything we can do on the numeric_std signed/unsigned types, we can also do on the integer types.
Now we can use this 'repr attribute for more applications. For example :
So here we were able to read some data from a memory as std_logic_vector and then to affect it to
the record without needing to affect each field.
A second possible use :
Here we were able to avoid to create a function to convert the FSM to a SLV signal in order to display the current state of the FSM to an logic analyzer. There are already synthesis attributes to define the encoding of an FSM but they are not standard and they are not used during simulation. It could also be possible to determine automatically the size needed for My_FSM with some of existing attributes of My_FSM.
Also we can use the same tricks for the real type and we can have the same possibilities as the new float type of the float_pkg :
subtype My_Real is Base_Real; -- Same as Base_Integer but for Real types
for My_Real'Exponent use Std_uLogic_Vector (7 downto 0);
for My_Real'Mantissa use Std_uLogic_Vector (21 downto 0);
Here we can access to the exponent and mantissa either by the 'exponent and 'mantissa attributes, either as a whole by the 'repr attribute
For the fixed type of the fixed_pkg, there is no equivalent standard type.
We could define a Base_Fixed type which is like the Base_Integer but for the fixed types and use it as follow :
subtype My_SFixed is Modulo Base_Fixed;
for My_SFixed'Decimal use Std_uLogic_Vector (7 downto 0); -- I don't know if decimal is the right word
for My_SFixed'Fraction use Std_uLogic_Vector (3 downto 0); -- I don't know if fraction is the right word
This is equivalent as :
subtype My_IEEE_SFixed is u_SFixed (7 downto -4);
But it will be less cumbersome to do arithmetics on My_SFixed than on My_IEEE_SFixed.
Here we can access to the decimal part and the fraction part either by the 'decimal and 'fraction attributes, either as a whole by the 'repr attribute. Here it could be interesting (I don't know) if the result of the 'repr attribute would be Std_uLogic_Vector(7 downto -4) instead of Std_uLogic_Vector(11 downto 0), but negative indexes are not allowed on Std_uLogic_Vector. So we can either create a new type like SLV but does allow negative indexes, either change the definition of the SLV to allow negative indexes. I think the latter is retro-compatible, and anyway why retrict SLV indexes to natural numbers ?
So, do you think there is something wrong with that proposition or it can be a good idea for the future VHDL standards ?
Jonas
It seems to me it can be a good idea to add to VHDL a new attribute 'repr in order to be able to access the representation of a signal (bits) that is normally not accessible on most types (integer, records, enumerates, ...).
In the beginning of VHDL, if you want to do arithmetics on integers, you had to use the integer type. But there was a need of specifying a size, a range direction, easy access to the bits which was not possible with the integer type. Then came the Std_Logic_Arith which was a good solution on its time. Further, the IEEE made the numeric_std/numeric_bit packages that define the signed and unsigned type as an array of std_logic/bits. They were good packages but there is 2 or 3 things that bothers me :
* Doing arithmetics on arrays seems weird to me. The VHDL compilers consider the signed/unsigned types as arrays with some functions defined on it. They don't see them as numbers which leads to some strange situations like it is possible to add an integer to an (un)signed but not to affect an integer on it.
* We have already the integer type to do arithmetics on integer. After adding the signed/unsigned types, we have now to choose which type make more sense for each situation. Often they are redundant. Wouldn't be better to add some mecanisms on the integer type to allow to do what was missing on this type and have only one type (with the natural and positive subtypes) for arithmetics ?
With a new attribute 'repr and the "for ... use" clause taken from Ada, I think we can add what was missing to the integer type, as shows the following code :
Code:
subtype My_Integer is Natural; -- Replace natural by integer in order to have a signed integer
for My_Integer use Std_uLogic_Vector (7 downto 0); -- Bit_Vector could also work
signal A_s : My_Integer;
signal C_s, B_s : Std_uLogic_Vector (A_s'Repr'Range);
begin
A : process (Reset_i, Clk_i) is
begin
if Reset_i = '1' then
A_s <= 0;
elsif Rising_Edge(Clk_i) then
if Start_i = '1' then
A_s'Repr <= B_s;
else
A_s <= A_s + 1;
end if;
end if;
end process A;
C_s <= A_s'Repr;
There is a few more things missing :
* There is a limit (32 bits) on the Natural type. Then why not to add the Ada Base_Integer type to VHDL ? This type is an integer without range constraints. It is in Ada not allowed to use this type if we dont't add a range to it.
* Overflow is not possible but will raise an error, which is on some cases interesting, but often we want modulo integers. So I would propose to add a keyword (for example mod or modulo) to specify modulo integers.
So the declaration of My_Integer could be :
subtype My_Integer is Modulo Base_Natural; -- Same as Base_Integer but for Natural numbers only
And now I think that everything we can do on the numeric_std signed/unsigned types, we can also do on the integer types.
Now we can use this 'repr attribute for more applications. For example :
Code:
type My_Record is
record
Field_1 : Std_Logic;
Field_2 : Std_Logic_Vector (14 downto 0);
Field_3 : Std_Logic_Vector (15 downto 0);
end record;
for My_Record use Std_Logic_Vector (31 downto 0);
-- Here it could be nice to have a 'size (or maybe 'repr_size) attribute to tell that
-- My_Record takes 32 bits, or to be able write : for My_Record use
-- Std_Logic_Vector (<> downto 0) to specify a range downto 0 (the size is known).
signal A_s : My_Record;
signal Mem_Data_s : Std_Logic_Vector (My_Record'Repr'Range);
begin
(...) -- Loading some data from a memory to Mem_Data_s
A_s'Repr <= Mem_Data_s;
the record without needing to affect each field.
A second possible use :
Code:
type My_FSM is (State_1, State_2, State_3);
for My_FSM use Std_uLogic_Vector (1 downto 0) as Gray; -- 2 bits, Gray encoding
signal State_s, Next_State_s : My_FSM;
begin
Logical_Analyzer_Data_o <= State_s'Repr;
Also we can use the same tricks for the real type and we can have the same possibilities as the new float type of the float_pkg :
subtype My_Real is Base_Real; -- Same as Base_Integer but for Real types
for My_Real'Exponent use Std_uLogic_Vector (7 downto 0);
for My_Real'Mantissa use Std_uLogic_Vector (21 downto 0);
Here we can access to the exponent and mantissa either by the 'exponent and 'mantissa attributes, either as a whole by the 'repr attribute
For the fixed type of the fixed_pkg, there is no equivalent standard type.
We could define a Base_Fixed type which is like the Base_Integer but for the fixed types and use it as follow :
subtype My_SFixed is Modulo Base_Fixed;
for My_SFixed'Decimal use Std_uLogic_Vector (7 downto 0); -- I don't know if decimal is the right word
for My_SFixed'Fraction use Std_uLogic_Vector (3 downto 0); -- I don't know if fraction is the right word
This is equivalent as :
subtype My_IEEE_SFixed is u_SFixed (7 downto -4);
But it will be less cumbersome to do arithmetics on My_SFixed than on My_IEEE_SFixed.
Here we can access to the decimal part and the fraction part either by the 'decimal and 'fraction attributes, either as a whole by the 'repr attribute. Here it could be interesting (I don't know) if the result of the 'repr attribute would be Std_uLogic_Vector(7 downto -4) instead of Std_uLogic_Vector(11 downto 0), but negative indexes are not allowed on Std_uLogic_Vector. So we can either create a new type like SLV but does allow negative indexes, either change the definition of the SLV to allow negative indexes. I think the latter is retro-compatible, and anyway why retrict SLV indexes to natural numbers ?
So, do you think there is something wrong with that proposition or it can be a good idea for the future VHDL standards ?
Jonas
Last edited: