What about a new attribute to access the physical representation of a signal ?

Discussion in 'VHDL' started by Mister_J, Jun 29, 2012.

  1. Mister_J

    Mister_J

    Joined:
    Jun 28, 2012
    Messages:
    8
    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 :

    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;
    
    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 :

    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;
    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 :

    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;
    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
     
    Last edited: Jun 29, 2012
    Mister_J, Jun 29, 2012
    #1
    1. Advertising

  2. Mister_J

    Mister_J

    Joined:
    Jun 28, 2012
    Messages:
    8
    Actually, declaring a integer with a representation clause would be 3 times longer as declaring (un)signed signals :

    subtype My_Integer_8 is Base_Integer;
    for My_Integer_8 use Std_uLogic_Vector (7 downto 0);
    signal A_s : My_Integer_8;

    subtype My_Integer_16 is Base_Integer;
    for My_Integer_16 use Std_uLogic_Vector (15 downto 0);
    signal B_s : My_Integer_16;

    subtype My_Integer_24 is Base_Integer;
    for My_Integer_24 use Std_uLogic_Vector (23 downto 0);
    signal C_s : My_Integer_24;


    Allowing the following synthax could be one way to avoid this :

    -- My_Integer is an unconstrained type, just as signed
    subtype My_Integer is Base_Integer;
    for My_Integer use Std_uLogic_Vector;

    signal A_s : My_Integer Repr_Range (7 downto 0);
    signal B_s : My_Integer Repr_Range (15 downto 0);
    signal C_s : My_Integer Repr_Range (23 downto 0);


    Jonas
     
    Mister_J, Jun 29, 2012
    #2
    1. Advertising

  3. Mister_J

    Mister_J

    Joined:
    Jun 28, 2012
    Messages:
    8
    I forgot one thing : how the resizing should work when doing arithmetics on integers with representation clause :

    Here is an example :
    Code:
      subtype My_Natural is Base_Natural;
      signal A_s, B_s : My_Natural Repr_Range (7 downto 0);
      signal C_s : My_Natural Repr_Range (8 downto 0);
    
    begin
    
      C_s <= Resize(A_s, C_s'Repr'Length) + Resize(B_s, C_s'Repr'Length);
    Where Resize returns an integer that has a representation clause with the asked size.

    If we would like the resizing to be made automatically, we can use a new keyword (Auto_Resize) :

    Code:
      subtype My_Natural is Auto_Resize Base_Natural;
      signal A_s, B_s : My_Natural Repr_Range (7 downto 0);
      signal C_s : My_Natural Repr_Range (8 downto 0);
    
    begin
    
      C_s <= A_s + B_s; -- A_s + B_s will be autoresized to 8, so is C_s size

    Jonas
     
    Last edited: Jun 29, 2012
    Mister_J, Jun 29, 2012
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Pronath
    Replies:
    1
    Views:
    1,175
    Diez B. Roggisch
    Jan 3, 2005
  2. Jack Orenstein

    threading.Thread vs. signal.signal

    Jack Orenstein, Sep 18, 2005, in forum: Python
    Replies:
    0
    Views:
    470
    Jack Orenstein
    Sep 18, 2005
  3. Weng Tianxiang
    Replies:
    2
    Views:
    661
    Jonathan Bromley
    Jan 30, 2007
  4. Nicolas Moreau
    Replies:
    9
    Views:
    3,188
  5. dibacco73
    Replies:
    1
    Views:
    658
    joris
    Feb 12, 2009
Loading...

Share This Page