ieee.numeric_std?

Discussion in 'VHDL' started by Weng Tianxiang, Feb 11, 2006.

  1. Hi,
    There are many discussions on the liberaries used in VHDL.

    The following are the key points I summirized from many useful
    discussions and I would like to adopt in my coding:

    -- 02/11/2006
    -- 1. Use "use ieee.numeric_std.all", instead of two statements:
    -- use ieee.std_logic_unsigned.all;
    -- use ieee.std_logic_arith.all;
    --
    -- 2. All std_logic_vector() are converted to unsigned()
    -- 3. When signed() is to be used, use type conversion function
    to_integer()

    The final remaining question is:
    Is unsigend(...) acceptable in interface of entity?

    Thank you.

    Weng
     
    Weng Tianxiang, Feb 11, 2006
    #1
    1. Advertising

  2. On 11 Feb 2006 07:35:25 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi,
    >There are many discussions on the liberaries used in VHDL.
    >
    >The following are the key points I summirized from many useful
    >discussions and I would like to adopt in my coding:
    >
    >-- 02/11/2006
    >-- 1. Use "use ieee.numeric_std.all", instead of two statements:
    >-- use ieee.std_logic_unsigned.all;
    >-- use ieee.std_logic_arith.all;
    >--
    >-- 2. All std_logic_vector() are converted to unsigned()
    >-- 3. When signed() is to be used, use type conversion function
    >to_integer()
    >
    >The final remaining question is:
    >Is unsigend(...) acceptable in interface of entity?


    You might get a few differing opinions on this one...

    My take is that you should use whatever data types make sense for
    internal interfaces (e.g. use unsigned if it makes sense), but you
    should not use anything other than std_logic or std_logic_vector for
    top level ports (i.e. the pins of your chip).

    Things gets a little complicated if you are into module reuse, and a
    particular module can be compiled either as the whole chip or as a
    module instantiated inside another module.
    This leads to the use of a "top sheet" which maps your internal data
    types to std_logic or std_logic_vector and is also a convenient place
    to instantiate your clock buffers, etc.

    Regards,
    Allan
     
    Allan Herriman, Feb 11, 2006
    #2
    1. Advertising

  3. Allan Herriman wrote:

    > My take is that you should use whatever data types make sense for
    > internal interfaces (e.g. use unsigned if it makes sense), but you
    > should not use anything other than std_logic or std_logic_vector for
    > top level ports (i.e. the pins of your chip).


    I mostly agree. For an internal entity,
    I will match my variable types, whatever they are.
    For the device pin entity I use std_logic_vector
    for all vectors, std_logic for inout bits
    and std_ulogic for all other bits.
    Std_ulogic is 100% compatible with std_logic bits
    in port maps and for any other use.
    Integer and enumeration types generally cause
    pin assignment confusion on the top entity.

    > Things gets a little complicated if you are into module reuse, and a
    > particular module can be compiled either as the whole chip or as a
    > module instantiated inside another module.


    If I am making a module for another
    designer who already owns the pin entity,
    I will match his local bus types, whatever they are.

    > This leads to the use of a "top sheet" which maps your internal data
    > types to std_logic or std_logic_vector and is also a convenient place
    > to instantiate your clock buffers, etc.


    Yes, a top wrapper sheet will work in any case.
    Synthesis usually handles clock buffers
    OK, but things like PLLs or purchased netlists
    work well as unbound instances in the
    top wrapper.

    -- Mike Treseler
     
    Mike Treseler, Feb 11, 2006
    #3
  4. On Sat, 11 Feb 2006 11:21:25 -0800, Mike Treseler
    <> wrote:

    >Allan Herriman wrote:
    >
    >> My take is that you should use whatever data types make sense for
    >> internal interfaces (e.g. use unsigned if it makes sense), but you
    >> should not use anything other than std_logic or std_logic_vector for
    >> top level ports (i.e. the pins of your chip).

    >
    >I mostly agree. For an internal entity,
    >I will match my variable types, whatever they are.
    >For the device pin entity I use std_logic_vector
    >for all vectors, std_logic for inout bits
    >and std_ulogic for all other bits.
    >Std_ulogic is 100% compatible with std_logic bits
    >in port maps and for any other use.


    For the newbies: the perceived advantage of using std_ulogic instead
    of std_logic is that the simulator will flag drivers shorted
    together (i.e. multiple drivers on a non-resolved signal) as an error
    at compile time.

    Using std_logic (a resolved type) means that possibly buggy source
    code will compiler ok, and you don't find the error until you simulate
    your testbench.
    If it gets past your testbench, it will cause the synthesiser to flag
    an error, because the synthesiser will only allow multiple drivers on
    a signal if the code driving the signal matches a particular template
    (which you are rather unlikely to do by accident unless you like using
    internal tristate buses).

    I have never had a bug caused by accidentally shorted nets in VHDL
    (using std_logic) or Verilog, so for me this is not really an
    important issue.

    Mike: do you have any stats on measured time savings (or losses)
    caused by the use of std_ulogic vs std_logic on real world projects?


    >Integer and enumeration types generally cause
    >pin assignment confusion on the top entity.


    In theory, one could independently synthesise each module using a
    synthesiser from a different vendor, which could result in different
    encodings for certain datatypes on internal ports.
    At the EDIF level, one just has "bits".

    Unsigned has a well defined representation, so it should be safe, but
    we could argue that enumeration types, records, etc. aren't safe even
    for internal ports, unless one also has control over the build scripts
    (which is not always the case in a group project, or one being
    maintained well after the original design has been completed).

    That said, I have often used records for internal ports.

    Regards,
    Allan
     
    Allan Herriman, Feb 11, 2006
    #4
  5. Hi Allan,
    I will accept your method through my new projects.

    One thing you doesn't mention in your posts is why in the top level, we
    must insist to use std_logic and std_logic_vector and why unsigined or
    signed cannot be used in the top level.

    Thank you.

    Weng
     
    Weng Tianxiang, Feb 11, 2006
    #5
  6. Allan Herriman wrote:

    > I have never had a bug caused by accidentally shorted nets in VHDL
    > (using std_logic) or Verilog, so for me this is not really an
    > important issue.


    No it isn't.
    For me, it's more a non-conformist style signature
    than an important design rule. Note that I don't
    use std_ulogic_vector because it does not map cleanly.

    > Mike: do you have any stats on measured time savings (or losses)
    > caused by the use of std_ulogic vs std_logic on real world projects?


    The only time I have "lost" to this problem was to
    write myself an example to show that vcom could
    in fact find shorted std_ulogic drivers.
    I haven't seen it happen since.

    I think that only the uninitiated wire process outputs together,
    and not for very long. One of the advantages of a
    single process internal entity is that there is no
    second process to pick a fight with, so this problem cannot occur.

    >> Integer and enumeration types generally cause
    >> pin assignment confusion on the top entity.


    > In theory, one could independently synthesise each module using a
    > synthesiser from a different vendor, which could result in different
    > encodings for certain datatypes on internal ports.
    > At the EDIF level, one just has "bits".


    Yes. I was assuming a full synthesis and one encoding setting.
    It has been my experience that the first guy on the project
    gets the top level and does all of the top synthesis during
    development.

    > Unsigned has a well defined representation, so it should be safe,


    I think it is.

    > but
    > we could argue that enumeration types, records, etc. aren't safe even
    > for internal ports, unless one also has control over the build scripts
    > (which is not always the case in a group project, or one being
    > maintained well after the original design has been completed).


    I haven't tried it, but I can't imagine such a mismatch
    occurring without at least a warning from synthesis.
    In any case, these types are what makes well-written
    vhdl code easier to read than some other HDLs.

    > That said, I have often used records for internal ports.


    I think that is commendable.
    Thanks for the posting.

    -- Mike Treseler
     
    Mike Treseler, Feb 11, 2006
    #6
  7. On 11 Feb 2006 13:13:58 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi Allan,
    >I will accept your method through my new projects.
    >
    >One thing you doesn't mention in your posts is why in the top level, we
    >must insist to use std_logic and std_logic_vector and why unsigined or
    >signed cannot be used in the top level.



    You may wish to perform a gate level simulation at some stage. The
    gate level representation comes from HDL that the back end tools spit
    out.
    Recall that EDIF (or its equivalent) doesn't keep the type information
    - all ports are just "bits", consequently the gate level HDL just has
    std_logic type for its ports. The tools are usually clever enough to
    group like-named ports into std_logic_vectors where appropriate.

    Now imagine plugging this into your testbench. It's not going to work
    unless your testbench expects all ports to be std_logic or
    std_logic_vector.


    There were some other reasons, but I can't think of them right now.

    Regards,
    Allan
     
    Allan Herriman, Feb 12, 2006
    #7
  8. On Sat, 11 Feb 2006 13:49:48 -0800, Mike Treseler
    <> wrote:

    >Allan Herriman wrote:
    >
    >> I have never had a bug caused by accidentally shorted nets in VHDL
    >> (using std_logic) or Verilog, so for me this is not really an
    >> important issue.

    >
    >No it isn't.
    >For me, it's more a non-conformist style signature
    >than an important design rule.


    You rebel!

    :)

    Allan
     
    Allan Herriman, Feb 12, 2006
    #8
  9. On 11 Feb 2006 13:13:58 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi Allan,
    >I will accept your method through my new projects.
    >
    >One thing you doesn't mention in your posts is why in the top level, we
    >must insist to use std_logic and std_logic_vector and why unsigined or
    >signed cannot be used in the top level.
    >
    >Thank you.


    From the tools point of view, it can - synthesis and simulation of
    "signed" and "unsigned" both work perfectly with some tools (Leonardo
    Specrtum for synthesis, ModelSim for simulation). However I can't say
    whether all tools - Xilinx ISE for example - also work perfectly.

    The problem comes later, if you wish to simulate a gate-level version of
    the component, (after synthesis, place&route, with the actual timings
    back-annotated into the design). At this level, the tools give you an
    architecture with all ports using std_logic_vector signals, whether you
    like it or not.

    This is no longer compatible with the behavioural model, UNLESS you used
    std_logic_vector for the top level ports, so it cannot be dropped into
    the same testbench to verify that it gives the same simulation results.

    You could use a wrapper to convert port types, but it is less complex to
    restrict the port types at the top level.

    - Brian
     
    Brian Drummond, Feb 12, 2006
    #9
  10. On 11 Feb 2006 07:35:25 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi,
    >There are many discussions on the liberaries used in VHDL.
    >
    >The following are the key points I summirized from many useful
    >discussions and I would like to adopt in my coding:
    >
    >-- 02/11/2006
    >-- 1. Use "use ieee.numeric_std.all", instead of two statements:
    >-- use ieee.std_logic_unsigned.all;
    >-- use ieee.std_logic_arith.all;
    >--
    >-- 2. All std_logic_vector() are converted to unsigned()
    >-- 3. When signed() is to be used, use type conversion function
    >to_integer()


    I would suggest a modification of rules 2 and 3 ...
    firstly you suggest converting _all_ std_logic_vector to unsigned...
    This makes sense for unsigned datapaths, but not for e.g. control signal
    buses, and certainly not for signed datapaths!

    I use all 3 types; "unsigned" typically forms the bulk in my case, for
    unsigned datapaths, "signed" works equally well where the data is
    signed, and "std_logic_vector" where the signal is genuinely neither;
    e.g. for control signals (which could also be implemented as records)
    but also for floating point data (for designs predates the new floation
    point work).

    This helps clarify the intent of the design.

    - Brian
     
    Brian Drummond, Feb 12, 2006
    #10
  11. Hi,
    I am not an expert in synthesis, but absolutely I am confused with all
    discussions.

    A very simple thing that exists over all CPU software systems become so
    complex in the hardware system, unbelievable!

    If doing the following ways, I don't think there would be any problems
    with any type of signals whether they are on the top level or not.

    1. All signal must use std_logic or std_logic_vector system;
    2. If unsigned or signed are needed, just add type cast: unsigned() or
    signed().

    Is there any problem?

    In C, you can freely use type cast to transfer what type you want for
    the specified data: byte, word, double word, ...and over there there is
    no any problem.

    Weng
     
    Weng Tianxiang, Feb 12, 2006
    #11
  12. Weng Tianxiang wrote:


    > 1. All signal must use std_logic or std_logic_vector system;
    > 2. If unsigned or signed are needed, just add type cast: unsigned() or
    > signed().
    >
    > Is there any problem?


    If you have many conversions, you code may look not so nice. ;-)

    A quick and dirty rule is: Use whatever type you want, but use
    std_(U)logic(_vector) for your entities (or at least your top entity).

    My way of coding is:
    * std_ulogic(_vector) for normal signals (including I/O)
    * std_logic(_vector) for tri-state signals (including I/O)
    * unsigned / signed if I need arithmetics
    * integer for special purposes
    * float, time ... for testbenches

    Ralf
     
    Ralf Hildebrandt, Feb 12, 2006
    #12
  13. Hi Brian,
    The first post is my initial idea. Through many discussions of this
    post, I found a new set of rules are much better than the first set and
    I abandom the first set of rules.

    New set of rules:
    1. All signals are std_logic or std_logic_vector;
    2. Use "use ieee.numeric_std.all", instead of two statements:
    use ieee.std_logic_unsigned.all;
    use ieee.std_logic_arith.all;
    3. If signed operations are used not very often, add to_integer() to
    change their types to meet operational requirements.
    4. If signed operations are heavily used, specify new signals with same
    but signed data.

    Here is an example:
    signal A : std_logic_vector(3 downto 0);
    signal B : std_logic_vector(3 downto 0);

    if A, B are not very often used, for the following equations, we can
    do:
    if(to_integer(A) > to_integer(B)) then

    It is a signed comparison.

    If A, B are used heavily, do the following:
    1. Add two signal names
    signal Asigned : signed(3 downto 0);
    signal Bsigned : signed(3 downto 0);

    2. Add assignment equations to make them equal to original data without
    adding to_integer() later.
    Asigned <= to_integer(A);
    Bsigned <= to_integer(B);

    then where A and B are used as signed data, use Asigned and Bsigned.

    By doing that way, one never has to pay attention to whether or not the
    module is at the top level.

    My practice told me that the simplest form of anythings works best.

    Any comments?

    Weng
     
    Weng Tianxiang, Feb 12, 2006
    #13
  14. On 12 Feb 2006 07:35:56 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi Brian,
    >The first post is my initial idea. Through many discussions of this
    >post, I found a new set of rules are much better than the first set and
    >I abandom the first set of rules.
    >
    >New set of rules:
    >1. All signals are std_logic or std_logic_vector;
    >2. Use "use ieee.numeric_std.all", instead of two statements:
    > use ieee.std_logic_unsigned.all;
    > use ieee.std_logic_arith.all;
    >3. If signed operations are used not very often, add to_integer() to
    >change their types to meet operational requirements.
    >4. If signed operations are heavily used, specify new signals with same
    >but signed data.
    >
    >Here is an example:
    > signal A : std_logic_vector(3 downto 0);
    > signal B : std_logic_vector(3 downto 0);
    >
    >if A, B are not very often used, for the following equations, we can
    >do:
    > if(to_integer(A) > to_integer(B)) then
    >
    >It is a signed comparison.
    >
    >If A, B are used heavily, do the following:
    >1. Add two signal names
    > signal Asigned : signed(3 downto 0);
    > signal Bsigned : signed(3 downto 0);
    >
    >2. Add assignment equations to make them equal to original data without
    >adding to_integer() later.
    > Asigned <= to_integer(A);
    > Bsigned <= to_integer(B);
    >
    >then where A and B are used as signed data, use Asigned and Bsigned.
    >
    >By doing that way, one never has to pay attention to whether or not the
    >module is at the top level.


    The vast majority of your modules *won't* be at the top level.
    I recommend using either signed or unsigned types if you need to
    perform arithmetic.

    Regards,
    Allan
     
    Allan Herriman, Feb 12, 2006
    #14
  15. Weng Tianxiang a écrit:
    > 3. If signed operations are used not very often, add to_integer() to
    > change their types to meet operational requirements.
    > Here is an example:
    > signal A : std_logic_vector(3 downto 0);
    > signal B : std_logic_vector(3 downto 0);
    > if A, B are not very often used, for the following equations, we can
    > do:
    > if(to_integer(A) > to_integer(B)) then


    No you can't. to_integer only accepts a signed or unsigned parameter,
    not std_logic_vector.
    I think you want to use a type cast (signed, if I understand your
    point) instead.

    Nicolas
     
    Nicolas Matringe, Feb 13, 2006
    #15
  16. On 12 Feb 2006 07:35:56 -0800, "Weng Tianxiang" <>
    wrote:

    >Hi Brian,
    >The first post is my initial idea. Through many discussions of this
    >post, I found a new set of rules are much better than the first set and
    >I abandom the first set of rules.
    >
    >New set of rules:
    >1. All signals are std_logic or std_logic_vector;

    Allowing signed or unsigned where appropriate is better;
    (it is not appropriate for top level ports as discussed elsewhere)

    >2. Use "use ieee.numeric_std.all", instead of two statements:


    Definitely.

    > use ieee.std_logic_unsigned.all;
    > use ieee.std_logic_arith.all;
    >3. If signed operations are used not very often, add to_integer() to
    >change their types to meet operational requirements.


    Not quite. "to_integer" on std_logic_vector would be ambiguous because
    nothing tells it whether the std_logic_vector is signed or not; so it is
    not permitted with the standard libraries.

    "unsigned()" or "signed()" specifically gives you the right
    interpretation of the data; if you really need a signed integer, then
    "to(integer(signed())" will do it.

    >4. If signed operations are heavily used, specify new signals with same
    >but signed data.
    >
    >Here is an example:
    > signal A : std_logic_vector(3 downto 0);
    > signal B : std_logic_vector(3 downto 0);
    >
    >if A, B are not very often used, for the following equations, we can
    >do:
    > if(to_integer(A) > to_integer(B)) then
    >
    >It is a signed comparison.


    No, it won't work, because to_integer is ambiguous as above.

    >If A, B are used heavily, do the following:
    >1. Add two signal names
    > signal Asigned : signed(3 downto 0);
    > signal Bsigned : signed(3 downto 0);
    >
    >2. Add assignment equations to make them equal to original data without
    >adding to_integer() later.
    > Asigned <= to_integer(A);
    > Bsigned <= to_integer(B);
    >
    >then where A and B are used as signed data, use Asigned and Bsigned.


    AAAH! I think I see the problem ... you are coming to VHDL from C, and
    so it seems to you that "signed" and "unsigned" are varieties of integer
    as they are in C.

    Not so.

    Think of them as subclasses of std_logic_vector, which inherit most of
    the properties of std_logic_vector AND add _some_ properties inherited
    from signed (or unsigned) integers. So you don't need the
    std_logic_vector versions of these signals; signed or unsigned gives you
    those properties too.

    For example,

    signal A,B : signed(37 downto 0);
    A is very like a std_logic_vector 38 bits long, so it doesn't have
    restrictions on word length like an integer would (in C or VHDL), and
    you can still extract bits or ranges from it, perform logical operations
    on it, etc. But if you assign it to a std_logic_vector (or an unsigned)
    you have to cast it to the correct type.

    if A(37) = '1' then -- A is negative
    A(36 downto 0) <= (others => '0'); -- you can manipulate bits
    end if;

    But it also "inherits" arithmetic operations such as addition,
    subtraction and multiplication. (Division is more difficult!)
    Arithmetic is permitted between integer and signed, and between natural
    and unsigned. The same applies to comparison operations.

    signal S : signed(37 downto 0);
    Signal U : unsigned(37 downto 0);
    signal S_safe : signed(38 downto 0);
    signal SLV : std_logic_vector(37 downto 0);

    S <= A + B + 27; -- mix signed and integer
    U <= unsigned(A + B); -- cast to unsigned
    S_safe <= A(37) & A + B(37) & B; -- sign extend to prevent overflow
    -- alternatively S_safe <= RESIZE(A,39) + RESIZE(B,39);
    SLV <= std_logic_vector(S);

    Inheritance is not strictly correct but it's a useful way of looking at
    it.

    For the full definition of operations permitted on std_logic_vector and
    numeric_std, you can look at the ieee.std_logic_vector and
    ieee.numeric_std packages.

    >By doing that way, one never has to pay attention to whether or not the
    >module is at the top level.


    An alternative view: there is only one top level.
    It is trivial to write a wrapper to perform the appropriate conversion
    of port types ONCE at the top level and pass the signals on to an
    identical module with the correct port types for internal use.

    >My practice told me that the simplest form of anythings works best.


    Indeed ... and this is an area of VHDL worth understanding. You are
    still trying to fight the type system, instead of letting it do the work
    for you.

    The simplest form makes the expressions simple and clear, instead of
    peppered with type casts and conversions.

    Using signed or unsigned, you don't need two versions of the data - you
    get both sets of properties in the same type.

    - Brian
     
    Brian Drummond, Feb 13, 2006
    #16
  17. Weng Tianxiang wrote:

    > 3. If signed operations are used not very often, add to_integer() to
    > change their types to meet operational requirements.


    Don't use integers at all except for constant values. For signed
    arithmetic use the type "signed", that's what it is for. All arithmetic
    operations are overloaded for "signed" in numeric_std.

    Example:

    Z <= A + B; -- A, B, Z are signed
    Z <= std_logic_vector(signed(A) + signed(B)); -- A, B, Z are
    std_logic_vector

    The reason why not to use integer is that it is defined as a 32 bit
    signed vector. If you happen to have operands that are wider than 32
    bits, the use of integer fails. If your operands are shorter than 32,
    there is the potential risk that the synthesis results are not optimal
    because 32-bit operations are implemented instead of shorter ones.

    Reto
     
    Reto Zimmermann, Feb 14, 2006
    #17
  18. Reto Zimmermann <> writes:

    > Weng Tianxiang wrote:
    >
    >> 3. If signed operations are used not very often, add to_integer() to
    >> change their types to meet operational requirements.

    >
    > Don't use integers at all except for constant values. For signed
    > arithmetic use the type "signed", that's what it is for. All arithmetic
    > operations are overloaded for "signed" in numeric_std.


    Reto is too modest to mention his paper on related issues, so I'll
    do it for him:

    http://www.synopsis.com/products/designware/dwtb/articles/coding_guidelines/coding_guidelines.html

    Cheers,
    Colin
     
    Colin Marquardt, Feb 14, 2006
    #18
  19. Hi,
    Reto paper is excellent.

    Another question is unanswered:

    Why unsigned/signed cannot be used in top layer? and why the signals in
    the top layer must be std_logic and std_logic_vector?

    Thank you.

    Weng
     
    Weng Tianxiang, Feb 15, 2006
    #19
  20. Weng Tianxiang

    Eric Smith Guest

    Reto Zimmermann wrote:
    > The reason why not to use integer is that it is defined as a 32 bit
    > signed vector.


    No, it isn't. It is defined as an integer with a range of at least
    -2147483647 to +2147483647. The implementation could be anything with
    suitable semantics. It could be stored as ten BCD digits and a sign bit.
    It could be pseudo-ternary. It could be a list of prime numbers whose
    sum is the value in question. The standard does NOT define how an
    integer is stored or implemented.

    Nor can you assume that a VHDL integer type can store ONLY 32-bit values.
    It may be larger.

    Nor can you assume that a VHDL integer type can store ALL 32-bit twos
    complement integer values. It might not be able to store
    -2147483648, which is a valid 32-bit twos complement value.

    See section 3.1.2 of IEEE 1076-2000. (I don't have a copy of 1076-2002,
    but I don't expect that the definition of the integer type is likely
    to have changed significantly.)
     
    Eric Smith, Feb 15, 2006
    #20
    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. lezah
    Replies:
    2
    Views:
    7,786
    Mike Treseler
    Feb 6, 2004
  2. Chuck Roth
    Replies:
    3
    Views:
    1,087
    Jim Lewis
    Sep 14, 2005
  3. JustJohn
    Replies:
    6
    Views:
    659
    JustJohn
    Mar 29, 2006
  4. Gabriel Schuster

    Division with ieee.numeric_std

    Gabriel Schuster, Sep 21, 2006, in forum: VHDL
    Replies:
    5
    Views:
    4,674
    Nicolas Matringe
    Sep 22, 2006
  5. Chris
    Replies:
    10
    Views:
    1,552
    Chris
    Jun 29, 2007
Loading...

Share This Page