"Interesting" behavior with aggregates

Discussion in 'VHDL' started by Tim Hubberstey, Jun 25, 2004.

  1. Hi all,

    I was trying to create a mask for a vector in a semi-portable way when I
    encountered an interesting behavior of aggregates. The problem is that
    for 'outa', the aggregate ends up bring (7 downto 0) while for 'outb',
    it ends up bring (0 to 7) with the result that the mask value is
    incorrect. I solved this by doing it a different way so there is no
    urgency.

    ------------------
    -- in a separate package:
    constant MaskBit : natural := 3;
    ------------------
    signal Vector2Mask : std_logic_vector(7 downto 0) := (others => '1');
    signal outa, outb : std_logic_vector(7 downto 0);

    begin

    -- outa = F7, aggregate is a "downto"
    outa <= ( 7 downto MaskBit+1 => '1',
    MaskBit => '0',
    MaskBit-1 downto 0 => '1' );

    -- outb = EF, aggregate is a "to"
    outb <= Vector2Mask and
    ( 7 downto MaskBit+1 => '1',
    MaskBit => '0',
    MaskBit-1 downto 0 => '1' );
    ------------------

    I looked at the LRM and I think that the issue is that there is no
    reference for the aggregate in case 'outb' so it uses a 'default'
    behavior. I didn't find the LRM to be very clear though, so I have a few
    questions:

    1. What exactly is happening here?

    2. Is there a way to constrain the direction and/or size of an aggregate
    so that I can force the direction to be the same ("downto" in this
    example) in all cases? I know I can create a variable and assign it with
    the aggregate but this seems unnecessarily complex.

    Any insight is appreciated.

    Thanks,
    Tim

    PS: I know this won't work if MaskBit is 0 or 7. What I *really* wanted
    to do was:

    outb <= Vector2Mask and (MaskBit => '0', others => '1');

    but this produces an "'Others' is in unconstrained array aggregate"
    error.
    --
    Tim Hubberstey, P.Eng. . . . . . Hardware/Software Consulting Engineer
    Marmot Engineering . . . . . . . VHDL, ASICs, FPGAs, embedded systems
    Vancouver, BC, Canada . . . . . . . . . . . http://www.marmot-eng.com
     
    Tim Hubberstey, Jun 25, 2004
    #1
    1. Advertising

  2. "Tim Hubberstey" <> schreef in bericht
    news:...
    > Hi all,
    >
    > I was trying to create a mask for a vector in a semi-portable way when I
    > encountered an interesting behavior of aggregates. The problem is that
    > for 'outa', the aggregate ends up bring (7 downto 0) while for 'outb',
    > it ends up bring (0 to 7) with the result that the mask value is
    > incorrect. I solved this by doing it a different way so there is no
    > urgency.
    >
    > ------------------
    > -- in a separate package:
    > constant MaskBit : natural := 3;
    > ------------------
    > signal Vector2Mask : std_logic_vector(7 downto 0) := (others => '1');
    > signal outa, outb : std_logic_vector(7 downto 0);
    >
    > begin
    >
    > -- outa = F7, aggregate is a "downto"
    > outa <= ( 7 downto MaskBit+1 => '1',
    > MaskBit => '0',
    > MaskBit-1 downto 0 => '1' );
    >
    > -- outb = EF, aggregate is a "to"
    > outb <= Vector2Mask and
    > ( 7 downto MaskBit+1 => '1',
    > MaskBit => '0',
    > MaskBit-1 downto 0 => '1' );
    > ------------------
    >
    > I looked at the LRM and I think that the issue is that there is no
    > reference for the aggregate in case 'outb' so it uses a 'default'
    > behavior. I didn't find the LRM to be very clear though, so I have a few
    > questions:
    >
    > 1. What exactly is happening here?


    Type std_logic_vector is an unconstrained array (NATURAL range ..)
    Type natural is a subtype of integer, and
    type integer is a range from low TO high.
    The latter is the reason why, if there is no range given, the default range
    is TO
    (from the lowest, that is 0 in the subtype).

    >
    > 2. Is there a way to constrain the direction and/or size of an aggregate
    > so that I can force the direction to be the same ("downto" in this
    > example) in all cases? I know I can create a variable and assign it with
    > the aggregate but this seems unnecessarily complex.
    >


    I added 2 solution.
    Solution 1 uses concatenation (in comment).
    Solution 2 uses a tricky function 'feel downto'

    I think that is what you want?

    library ieee;
    use ieee.std_logic_1164.all;
    entity top is
    port (outa, outb : out std_logic_vector(7 downto 0));
    end top;

    architecture test of top is


    ------------------
    -- in a separate package:
    constant MaskBit : natural := 3;
    ------------------
    signal Vector2Mask : std_logic_vector(7 downto 0) := (others => '1');
    -- signal outa, outb : std_logic_vector(7 downto 0);

    function feels_downto( i : std_logic_vector) return std_logic_vector is
    variable res : std_logic_vector(i'reverse_range);
    begin
    if i'ascending then
    for j in i'range loop
    res(j):=i(j);
    end loop;
    return res;
    else
    return i;
    end if;
    end feels_downto;
    begin

    -- outa = F7, aggregate is a "downto"
    outa <= ( 7 downto MaskBit+1 => '1',
    MaskBit => '0',
    MaskBit-1 downto 0 => '1' );

    --Solution 1
    -- outb <= Vector2Mask and
    -- ( (7 downto MaskBit+1 => '1')&
    -- (MaskBit => '0')&
    -- (MaskBit-1 downto 0 => '1' ));

    --Solution 2
    outb <= Vector2Mask and
    feels_downto (( 7 downto MaskBit+1 => '1',
    MaskBit => '0',
    MaskBit-1 downto 0 => '1' ));

    end test;

    Egbert Molenkamp
     
    Egbert Molenkamp, Jun 25, 2004
    #2
    1. Advertising

  3. Tim Hubberstey <> wrote in message news:<>...

    > PS: I know this won't work if MaskBit is 0 or 7. What I *really* wanted
    > to do was:
    >
    > outb <= Vector2Mask and (MaskBit => '0', others => '1');
    >
    > but this produces an "'Others' is in unconstrained array aggregate"
    > error.


    OK. Solution 3:

    -- ...
    subtype vec is std_logic_vector(7 downto 0);
    signal Vector2Mask : vec := (others => '1');
    -- ...
    begin
    outd <= Vector2Mask and vec'(MaskBit => '0', others => '1');

    -- Mike Treseler
     
    Mike Treseler, Jun 28, 2004
    #3
  4. Mike Treseler wrote:

    > Tim Hubberstey <> wrote in message news:<>...
    >
    >
    >>PS: I know this won't work if MaskBit is 0 or 7. What I *really* wanted
    >>to do was:
    >>
    >> outb <= Vector2Mask and (MaskBit => '0', others => '1');
    >>
    >>but this produces an "'Others' is in unconstrained array aggregate"
    >>error.

    >
    >
    > OK. Solution 3:
    >
    > -- ...
    > subtype vec is std_logic_vector(7 downto 0);
    > signal Vector2Mask : vec := (others => '1');
    > -- ...
    > begin
    > outd <= Vector2Mask and vec'(MaskBit => '0', others => '1');


    Thanks, Mike. That will certainly work but it isn't really an
    improvement over:

    variable mask : std_logic_vector(7 downto 0)
    := (MaskBit => '0', others => '1');
    ....
    outd <= Vector2Mask and mask;

    I was hoping there was some way that didn't require a long-winded set of
    declarations. An obvious (but unfortunately incorrect) solution would be
    something like:

    outd <= Vector2Mask and std_logic_vector(7 downto 0)'(MaskBit => '0',
    others => '1');
    --
    Tim Hubberstey, P.Eng. . . . . . Hardware/Software Consulting Engineer
    Marmot Engineering . . . . . . . VHDL, ASICs, FPGAs, embedded systems
    Vancouver, BC, Canada . . . . . . . . . . . http://www.marmot-eng.com
     
    Tim Hubberstey, Jun 29, 2004
    #4
  5. Egbert Molenkamp wrote:
    > "Tim Hubberstey" <> schreef in bericht
    > news:...
    >
    >>Hi all,
    >>
    >>I was trying to create a mask for a vector in a semi-portable way when I
    >>encountered an interesting behavior of aggregates. The problem is that
    >>for 'outa', the aggregate ends up bring (7 downto 0) while for 'outb',
    >>it ends up bring (0 to 7) with the result that the mask value is
    >>incorrect. I solved this by doing it a different way so there is no
    >>urgency.
    >>
    >>------------------
    >>-- in a separate package:
    >> constant MaskBit : natural := 3;
    >>------------------
    >> signal Vector2Mask : std_logic_vector(7 downto 0) := (others => '1');
    >> signal outa, outb : std_logic_vector(7 downto 0);
    >>
    >>begin
    >>
    >> -- outa = F7, aggregate is a "downto"
    >> outa <= ( 7 downto MaskBit+1 => '1',
    >> MaskBit => '0',
    >> MaskBit-1 downto 0 => '1' );
    >>
    >> -- outb = EF, aggregate is a "to"
    >> outb <= Vector2Mask and
    >> ( 7 downto MaskBit+1 => '1',
    >> MaskBit => '0',
    >> MaskBit-1 downto 0 => '1' );
    >>------------------
    >>
    >>I looked at the LRM and I think that the issue is that there is no
    >>reference for the aggregate in case 'outb' so it uses a 'default'
    >>behavior. I didn't find the LRM to be very clear though, so I have a few
    >>questions:
    >>
    >>1. What exactly is happening here?

    >
    >
    > Type std_logic_vector is an unconstrained array (NATURAL range ..)
    > Type natural is a subtype of integer, and
    > type integer is a range from low TO high.
    > The latter is the reason why, if there is no range given, the default range
    > is TO
    > (from the lowest, that is 0 in the subtype).


    Thanks for the explanation, Egbert. It all makes sense now.

    >>2. Is there a way to constrain the direction and/or size of an aggregate
    >>so that I can force the direction to be the same ("downto" in this
    >>example) in all cases? I know I can create a variable and assign it with
    >>the aggregate but this seems unnecessarily complex.

    [ useful function snipped ]

    The bottom line seems to be that it is at least as much (error-prone)
    work to constrain an aggregate as it is to use a temporary variable so I
    think I'll stick to the variable solution.
    --
    Tim Hubberstey, P.Eng. . . . . . Hardware/Software Consulting Engineer
    Marmot Engineering . . . . . . . VHDL, ASICs, FPGAs, embedded systems
    Vancouver, BC, Canada . . . . . . . . . . . http://www.marmot-eng.com
     
    Tim Hubberstey, Jun 29, 2004
    #5
  6. Tim Hubberstey <> wrote in message news:<yGaEc.43759$E84.40192@edtnps89>...

    > > OK. Solution 3:
    > >
    > > -- ...
    > > subtype vec is std_logic_vector(7 downto 0);
    > > signal Vector2Mask : vec := (others => '1');
    > > -- ...
    > > begin
    > > outd <= Vector2Mask and vec'(MaskBit => '0', others => '1');

    >
    > Thanks, Mike. That will certainly work but it isn't really an
    > improvement over:
    >
    > variable mask : std_logic_vector(7 downto 0)
    > := (MaskBit => '0', others => '1');
    > ...
    > outd <= Vector2Mask and mask;


    I agree.
    Hard to guess what someone will like.
    Any reason mask can't be a constant?

    > I was hoping there was some way that didn't require a long-winded set of
    > declarations.


    The declaration
    subtype vec is std_logic_vector(7 downto 0);
    seems short-winded to me.
    And it could be used more than once
    in the process or architecture.

    -- Mike Treseler
     
    Mike Treseler, Jun 29, 2004
    #6
  7. Mike Treseler wrote:

    > Any reason mask can't be a constant?


    Not really. It was all the result of iterative code writing. I started
    out with

    outd <= Vector2Mask and (MaskBit => '0', others => '1');

    but then that gave errors so I modified it until it stopped complaining.
    I then discovered the "interesting" feature of the unexpected range
    direction and got distracted by trying to figure out what the !@#$$%^
    was going on.
    --
    Tim Hubberstey, P.Eng. . . . . . Hardware/Software Consulting Engineer
    Marmot Engineering . . . . . . . VHDL, ASICs, FPGAs, embedded systems
    Vancouver, BC, Canada . . . . . . . . . . . http://www.marmot-eng.com
     
    Tim Hubberstey, Jun 30, 2004
    #7
    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. Kot

    Question - aggregates..

    Kot, Sep 12, 2003, in forum: VHDL
    Replies:
    4
    Views:
    656
  2. Anand P Paralkar

    Using Aggregates in Case Expressions

    Anand P Paralkar, Oct 27, 2003, in forum: VHDL
    Replies:
    6
    Views:
    637
    Anand P Paralkar
    Oct 28, 2003
  3. Gary Thorpe

    Using aggregates for assignments

    Gary Thorpe, Jun 14, 2004, in forum: VHDL
    Replies:
    4
    Views:
    743
  4. Replies:
    2
    Views:
    7,617
  5. John Smith
    Replies:
    2
    Views:
    331
    Flash Gordon
    Apr 19, 2006
Loading...

Share This Page