"Interesting" behavior with aggregates

T

Tim Hubberstey

Guest
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
 
Mike Treseler wrote:

Tim Hubberstey <bogus@bogusname.com> wrote in message news:<40DC6DB4.89ADEE25@bogusname.com>...


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
 
Egbert Molenkamp wrote:
"Tim Hubberstey" <bogus@bogusname.com> schreef in bericht
news:40DC6DB4.89ADEE25@bogusname.com...

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

Welcome to EDABoard.com

Sponsor

Back
Top