Problems switching to ieee.numeric_std.all

Discussion in 'VHDL' started by aleksa, Mar 1, 2012.

  1. aleksa

    aleksa Guest

    My VHD files now begin with

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    and I have some questions...



    Example1:

    I'm copying CURRENT to ADDR, but limiting to 999:

    -- 2^10 = 1024
    signal CURRENT, ADDR : unsigned(9 downto 0);

    if CURRENT < 1000 then
    ADDR <= CURRENT;
    else
    ADDR <= to_unsigned(999, ADDR'length);
    end if;

    At first I had "ADDR <= 999" but had to change it.
    Is "to_unsigned" the correct way?

    Next, if I have to use "to_unsigned", is it safe to use
    "if CURRENT < 1000" or should I use
    "if CURRENT < to_unsigned(1000, CURRENT'length)" ?



    Example2:

    I have a data bus defined like this:
    signal DOUT : std_logic_vector(17 downto 0);

    and DOUT is aliased into 3 unsigned indexes:

    alias INDEX1 : unsigned(3 downto 0) is DOUT ( 3 downto 0);
    alias INDEX2 : unsigned(8 downto 0) is DOUT (12 downto 4);
    alias INDEX3 : unsigned(4 downto 0) is DOUT (17 downto 13);

    I get the error that the types are incompatible.

    Should I not use alias here, but create another signal?
    signal INDEX1 : unsigned(3 downto 0);

    INDEX1 <= DOUT(3 downto 0);
    INDEX1 <= to_unsigned(DOUT(3 downto 0));
    none of the above works.. how do I write it?



    Example3:

    signal DOUT : std_logic;
    signal COUNTER : unsigned(15 downto 0);
    signal INDEX : unsigned( 3 downto 0);

    DOUT <= COUNTER(to_integer(INDEX));

    Is that the correct way of extracting one bit?



    I'll probably ask more questions after I grasp these :)
     
    aleksa, Mar 1, 2012
    #1
    1. Advertising

  2. On Thu, 01 Mar 2012 17:27:40 +0100, aleksa wrote:

    > My VHD files now begin with
    >
    > library ieee;
    > use ieee.std_logic_1164.all;
    > use ieee.numeric_std.all;

    good...

    Find the source for the numeric_std package.
    In the Xilinx installation on this machine it's at
    /opt/Xilinx/12.4/ISE_DS/ISE/vhdl/src/ieee/numeric_std.vhd

    And look at the declarations in the package (you can ignore the package
    body below it) - or find the same information in documentation if you
    prefer.

    > Example1:
    > ADDR <= to_unsigned(999, ADDR'length);
    > Is "to_unsigned" the
    > correct way?


    Essentially yes.

    > is it safe to use "if CURRENT < 1000" ?


    You will find the package contains a declaration:
    function "<" (L: UNSIGNED; R: INTEGER) return BOOLEAN;
    Which tells you ... Yes.

    It is a little odd that you can freely mix integers and [un]signed in
    expressions, thanks to the overloaded operators, but you can't assign one
    to the other, because assignment is not an operator.

    (Some languages do pretend that assignment is an operator - but that
    leads to problems far worse than any of VHDL's quirks!)

    But back to
    ADDR <= to_unsigned(999, ADDR'length);
    If you find yourself doing this a lot, and the code is becoming
    unbearably ugly, how about this:

    subtype Address is unsigned(9 downto 0);
    constant Last_Address : Address := to_unsigned(999, Address'length);
    -- and other related declarations, safe in a package somewhere

    signal CURRENT, ADDR : Address;

    if CURRENT < Last_Address then
    ADDR <= CURRENT;
    else
    ADDR <= Last_Address;
    end if;

    Can you see how this expresses the intent more clearly, as well as
    behaving better if you decide to change the address range?
    (e.g. if you grep for all the 999s and forget to change the 1000...)

    > Example2:


    > signal DOUT : std_logic_vector(17 downto 0);
    > alias INDEX1 : unsigned(3 downto 0) is DOUT ( 3 downto 0);
    > I get the error that the types are incompatible.


    They are. So...
    First, if you were to create another signal,

    > signal INDEX1 : unsigned(3 downto 0);
    > how do I write it?

    INDEX1 <= unsigned(DOUT( 3 downto 0));

    You need the type conversion here. (It is a conversion between related
    types of the same size, and it costs nothing in HW of course! but tells
    the compiler the change in types is intentional)

    Now I have not used alias with different types in the alias expression.
    You obviously need a type conversion, but I don't see why it shouldn't
    work... So try

    alias INDEX1 : unsigned(3 downto 0) is unsigned(DOUT( 3 downto 0));
    and report back the result. If it works, use it.

    > signal DOUT : std_logic;
    > signal COUNTER : unsigned(15 downto 0); signal INDEX : unsigned( 3
    > downto 0);
    >
    > DOUT <= COUNTER(to_integer(INDEX));
    >
    > Is that the correct way of extracting one bit?


    Yes. But again, if you find yourself always converting INDEX to integer,
    don't be scared to make it an integer (actually, a natural range 0 to 15)
    in the first place.

    If you are writing a lot of conversions, that is a pointer that you
    haven't thought the design through fully yet.

    Once you learn to use the type system instead of fighting it, code will
    flow with little ugliness - and a very few conversions, usually at
    boundaries between "things". You should be able to point to each
    remaining conversion, and argue that there is a good and necessary reason
    for it. (For example, the external memory model you need, expects
    std_logic_vectors on its ports, so you have to convert your unsigned
    address to slv on the output port)

    - Brian
     
    Brian Drummond, Mar 2, 2012
    #2
    1. Advertising

  3. aleksa

    scrts Guest


    > Example1:
    >
    > I'm copying CURRENT to ADDR, but limiting to 999:
    >
    > -- 2^10 = 1024
    > signal CURRENT, ADDR : unsigned(9 downto 0);
    >
    > if CURRENT < 1000 then
    > ADDR <= CURRENT;
    > else
    > ADDR <= to_unsigned(999, ADDR'length);
    > end if;


    ADDR is already unsigned, what's the point to do to_unsigned here? Afaik
    to_unsigned() is mainly used to type-convert integer or signed numbers to
    unsigned. slv->unsigned use unsigned().
     
    scrts, Mar 2, 2012
    #3
  4. aleksa

    aleksa Guest

    "scrts" <> wrote in message news:jiq1gc$1kd$...
    >
    >> Example1:
    >>
    >> I'm copying CURRENT to ADDR, but limiting to 999:
    >>
    >> -- 2^10 = 1024
    >> signal CURRENT, ADDR : unsigned(9 downto 0);
    >>
    >> if CURRENT < 1000 then
    >> ADDR <= CURRENT;
    >> else
    >> ADDR <= to_unsigned(999, ADDR'length);
    >> end if;

    >


    > ADDR is already unsigned, what's the point to do to_unsigned here?


    You mean like this?
    ADDR <= unsigned(999);
    "The expression can not be converted to type unsigned."


    > to_unsigned() is mainly used to type-convert integer to unsigned


    Isn't 999 an integer?
     
    aleksa, Mar 2, 2012
    #4
  5. aleksa

    aleksa Guest

    "Brian Drummond" <> wrote in message news:jip501$qo2$...

    > subtype Address is unsigned(9 downto 0);
    > constant Last_Address : Address := to_unsigned(999, Address'length);
    > -- and other related declarations, safe in a package somewhere
    >
    > signal CURRENT, ADDR : Address;
    >
    > if CURRENT < Last_Address then
    > ADDR <= CURRENT;
    > else
    > ADDR <= Last_Address;
    > end if;
    >


    Good to know, thank you.



    > Now I have not used alias with different types in the alias expression.
    > You obviously need a type conversion, but I don't see why it shouldn't
    > work... So try
    >
    > alias INDEX1 : unsigned(3 downto 0) is unsigned(DOUT( 3 downto 0));
    > and report back the result. If it works, use it.


    It doesn't work in ISE 13.3.
    "type conversion unsigned can not be an alias name"
     
    aleksa, Mar 2, 2012
    #5
  6. aleksa

    scrts Guest

    > You mean like this?
    > ADDR <= unsigned(999);
    > "The expression can not be converted to type unsigned."


    ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";
     
    scrts, Mar 2, 2012
    #6
  7. aleksa

    aleksa Guest

    "scrts" <> wrote in message news:jiq641$nhb$...
    >> You mean like this?
    >> ADDR <= unsigned(999);
    >> "The expression can not be converted to type unsigned."

    >
    > ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";


    From my first post:
    "At first I had "ADDR <= 999" but had to change it."
     
    aleksa, Mar 2, 2012
    #7
  8. scrts <> wrote:
    >> ADDR <= unsigned(999);
    >> "The expression can not be converted to type unsigned."

    >
    > ADDR <= 999; but not sure. To be exact, You may use ADDR <= X"3E7";


    - you can't assign an integer to unsigned without conversion.
    - ADDR <= X"3E7" will work only if ADDR has 12 elements unless you are
    using VHDL-2008's enhanced bit string literals.

    Enrik
     
    Enrik Berkhan, Mar 2, 2012
    #8
  9. aleksa

    aleksa Guest

    One more question:

    ADDR : unsigned(9 downto 0);
    OFFSET : unsigned(4 downto 0);

    this is what I want:
    ADDR <= OFFSET + 1000;

    this is how I've written it:
    ADDR <= OFFSET + to_unsigned(1000, ADDR'length);

    correct?
     
    aleksa, Mar 2, 2012
    #9
  10. aleksa

    aleksa Guest

    "Alan Fitch" <> wrote in message news:...
    > On 02/03/12 13:53, aleksa wrote:
    >> One more question:
    >>
    >> ADDR : unsigned(9 downto 0);
    >> OFFSET : unsigned(4 downto 0);
    >>
    >> this is what I want:
    >> ADDR <= OFFSET + 1000;
    >>
    >> this is how I've written it:
    >> ADDR <= OFFSET + to_unsigned(1000, ADDR'length);
    >>
    >> correct?
    >>
    >>

    >
    > That's not necessary. "+" is overloaded for unsigned + unsigned, natural
    > + unsigned, unsigned + natural - all returning unsigned. So you can write
    >
    > ADDR <= OFFSET + 1000;


    Width mismatch. <ADDR> has a width of 10 bits but assigned expression is 5-bit wide.

    In the VHDL math tricks:
    Y <= A + B; -- Maximum (A'Length, B'Length)
    Y <= A + 10; -- A'Length

    Since ISE complains if I just "+ 1000",
    I wanted to convert "1000" to "B" in the first example.

    It works, but I don't know if that is the correct approach.




    BTW, I know that 2^5 is 32 and that 1000+32
    may overflow 10 bits... but I don't care.
     
    aleksa, Mar 4, 2012
    #10
  11. aleksa

    aleksa Guest

    "Alan Fitch" <> wrote in message news:...
    > On 04/03/12 12:41, aleksa wrote:
    >> "Alan Fitch" <> wrote in message news:...
    >>> On 02/03/12 13:53, aleksa wrote:
    >>>> One more question:
    >>>>
    >>>> ADDR : unsigned(9 downto 0);
    >>>> OFFSET : unsigned(4 downto 0);
    >>>>
    >>>> this is what I want:
    >>>> ADDR <= OFFSET + 1000;
    >>>>
    >>>> this is how I've written it:
    >>>> ADDR <= OFFSET + to_unsigned(1000, ADDR'length);
    >>>>
    >>>> correct?
    >>>>
    >>>>
    >>>
    >>> That's not necessary. "+" is overloaded for unsigned + unsigned, natural
    >>> + unsigned, unsigned + natural - all returning unsigned. So you can write
    >>>
    >>> ADDR <= OFFSET + 1000;

    >>
    >> Width mismatch. <ADDR> has a width of 10 bits but assigned expression is 5-bit wide.
    >>
    >> In the VHDL math tricks:
    >> Y <= A + B; -- Maximum (A'Length, B'Length)
    >> Y <= A + 10; -- A'Length
    >>
    >> Since ISE complains if I just "+ 1000",
    >> I wanted to convert "1000" to "B" in the first example.
    >>
    >> It works, but I don't know if that is the correct approach.
    >>
    >>
    >>
    >>
    >> BTW, I know that 2^5 is 32 and that 1000+32
    >> may overflow 10 bits... but I don't care.
    >>
    >>

    >
    > Oops, sorry. Yes of course the widths need to match. I blame a week of
    > SystemC coding (and jet lag).
    >
    > However the + sign itself will resize its arguments to match. So you
    > just have to resize one argument. Hence either
    >
    > ADDR <= resize(OFFSET, ADDR'LENGTH) + 1000;


    Great, I didn't know about "resize", thanks!



    >
    > or (as you originally wrote)
    >
    > ADDR <= OFFSET + to_unsigned(1000, ADDR'LENGTH);
    >
    > As you say, ISE might be fussier than the language rules require.
    >
    > kind regards
    > Alan
    >
    >
    > --
    > Alan Fitch
     
    aleksa, Mar 4, 2012
    #11
  12. aleksa

    aleksa Guest

    aleksa, Mar 4, 2012
    #12
    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,793
    Mike Treseler
    Feb 6, 2004
  2. Chuck Roth
    Replies:
    3
    Views:
    1,091
    Jim Lewis
    Sep 14, 2005
  3. Weng Tianxiang

    ieee.numeric_std?

    Weng Tianxiang, Feb 11, 2006, in forum: VHDL
    Replies:
    24
    Views:
    8,122
    janeruth
    Jul 23, 2009
  4. JustJohn
    Replies:
    6
    Views:
    664
    JustJohn
    Mar 29, 2006
  5. Gabriel Schuster

    Division with ieee.numeric_std

    Gabriel Schuster, Sep 21, 2006, in forum: VHDL
    Replies:
    5
    Views:
    4,679
    Nicolas Matringe
    Sep 22, 2006
Loading...

Share This Page