GENERATE with non contiguous index?

N

Niv

I now have a set of test bench processes which work nicely on my 35
output signals, verifying their correct assertion/negation/timing etc.

To do this I've concatenated the signals into a 35 bit SLV, and then
used GENERATE for the test process for each signal type; e.g. below
for one such.

-------------------------------------------------------------------------------------------------------------------------
two_state_assert_hi_drv_en: FOR i IN 19 TO 24 GENERATE
hi_two_state_assert_check_drv_en: PROCESS
.....
.....
WAIT UNTIL ((reset_n = '0') OR event_0_to_1(all_outputs(i)))
FOR timeout;
....
....
END PROCESS hi_two_state_assert_check_drv_en;
END GENERATE;
-------------------------------------------------------------------------------------------------------------------------
However, I may need to re-assign signals to a different group, so what
I'd like to do is use the generate statement like you do with a CASE
statement, as follows:

FOR i IN 19 OR 22 TO 24 GENERATE

but obviously this doesn't work.

Any ideas how I can generate for unique, non-contiguous, integers?
This will make it very easy to move signals around my 6 different
process types, otherwise I have to re-arrange the signal order and
then edit all the generate statement indices.

TIA, Niv.
 
N

Niv

I now have a set of test bench processes which work nicely on my 35
output signals, verifying their correct assertion/negation/timing etc.

To do this I've concatenated the signals into a 35 bit SLV, and then
used GENERATE for the test process for each signal type; e.g. below
for one such.

---------------------------------------------------------------------------­----------------------------------------------
two_state_assert_hi_drv_en: FOR i IN 19 TO 24 GENERATE
hi_two_state_assert_check_drv_en: PROCESS
....
....
WAIT UNTIL ((reset_n = '0') OR event_0_to_1(all_outputs(i)))
FOR timeout;
...
...
END PROCESS hi_two_state_assert_check_drv_en;
END GENERATE;
---------------------------------------------------------------------------­----------------------------------------------
However, I may need to re-assign signals to a different group, so what
I'd like to do is use the generate statement like you do with a CASE
statement, as follows:

FOR i IN 19 OR 22 TO 24 GENERATE

but obviously this doesn't work.

Any ideas how I can generate for unique, non-contiguous, integers?
This will make it very easy to move signals around my 6 different
process types, otherwise I have to re-arrange the signal order and
then edit all the generate statement indices.

TIA, Niv.

Think I can do it with nested GENERATE statements:

gen_all: FOR i IN 1 TO 35 GENERATE
 
N

Niv

I now have a set of test bench processes which work nicely on my 35
output signals, verifying their correct assertion/negation/timing etc.

To do this I've concatenated the signals into a 35 bit SLV, and then
used GENERATE for the test process for each signal type; e.g. below
for one such.

---------------------------------------------------------------------------­----------------------------------------------
two_state_assert_hi_drv_en: FOR i IN 19 TO 24 GENERATE
hi_two_state_assert_check_drv_en: PROCESS
....
....
WAIT UNTIL ((reset_n = '0') OR event_0_to_1(all_outputs(i)))
FOR timeout;
...
...
END PROCESS hi_two_state_assert_check_drv_en;
END GENERATE;
---------------------------------------------------------------------------­----------------------------------------------
However, I may need to re-assign signals to a different group, so what
I'd like to do is use the generate statement like you do with a CASE
statement, as follows:

FOR i IN 19 OR 22 TO 24 GENERATE

but obviously this doesn't work.

Any ideas how I can generate for unique, non-contiguous, integers?
This will make it very easy to move signals around my 6 different
process types, otherwise I have to re-arrange the signal order and
then edit all the generate statement indices.

TIA, Niv.

I think I can do this with nested GENERATE statements:

gen_all: FOR i IN 1 TO 35 GENERATE
p_lo: IF (i=1) OR i=2 OR i=3 GENERATE
PROCESS here..
end generate p_lo;
p_hi; IF (i=5) OR (I=6).... GENERATE
end generate p_hi;
end generate gen_all;

IF someone has a better/neater solution, I'd be interested.

Regards, Niv.
 
B

Brian Drummond

I think I can do this with nested GENERATE statements:

gen_all: FOR i IN 1 TO 35 GENERATE
p_lo: IF (i=1) OR i=2 OR i=3 GENERATE
PROCESS here..
end generate p_lo;
p_hi; IF (i=5) OR (I=6).... GENERATE
end generate p_hi;
end generate gen_all;

IF someone has a better/neater solution, I'd be interested.

Perhaps easier to reconfigure...

CONSTANT config: array (1 to 35) of boolean := (
1=> true,
2=> true,
3 => true,
5 => true,
6 => true,
-- don't run this test today 19 => true,
others => false );

gen_all: FOR i IN 1 TO 35 GENERATE
p: IF config(i) GENERATE
PROCESS here..
end generate p_lo;
end generate gen_all;

- Brian
 
B

Brian Drummond

I think I can do this with nested GENERATE statements:

gen_all: FOR i IN 1 TO 35 GENERATE
p_lo: IF (i=1) OR i=2 OR i=3 GENERATE
PROCESS here..
end generate p_lo;
p_hi; IF (i=5) OR (I=6).... GENERATE
end generate p_hi;
end generate gen_all;

IF someone has a better/neater solution, I'd be interested.

Perhaps easier to reconfigure...

CONSTANT config: array (1 to 35) of boolean := (
1=> true,
2=> true,
3 => true,
5 => true,
6 => true,
-- don't run this test today 19 => true,
others => false );

gen_all: FOR i IN 1 TO 35 GENERATE
p: IF config(i) GENERATE
PROCESS here..
end generate p_lo;
end generate gen_all;

Or if the constant is more conveniently a std_logic_vector,

CONSTANT config: STD_LOGIC_VECTOR (1 to 35)
:= ("11101 10000 00000 00000 00000 00000 00000");
....
p: IF config(i) = '1' GENERATE
....

It's clearer to me, if you separate the specialisation (or
customisation) out from the generate statement into something more
easily readable. Also, this ought to work for a constant in a package,
which can be generated automatically from other tools...

printf("package Customise is\nbegin\n CONSTANT config:
STD_LOGIC_VECTOR (1 to 35) := (X\"%x\" & \"000\");\nend package;",
my_magic_number); //or something less ugly

please excuse duplicate post!

- Brian
 
N

Niv

Perhaps easier to reconfigure...

CONSTANT config: array (1 to 35) of boolean := (
1=> true,
2=> true,
3 => true,
5 => true,
6 => true,
-- don't run this test today 19 => true,
others => false );

gen_all: FOR i IN 1 TO 35 GENERATE
p: IF config(i) GENERATE
PROCESS here..
end generate p_lo;
end generate gen_all;

Or if the constant is more conveniently a std_logic_vector,

CONSTANT config: STD_LOGIC_VECTOR (1 to 35)
:= ("11101 10000 00000 00000 00000 00000 00000");
...
p: IF config(i) = '1' GENERATE
...

It's clearer to me, if you separate the specialisation (or
customisation) out from the generate statement into something more
easily readable. Also, this ought to work for a constant in a package,
which can be generated automatically from other tools...

printf("package Customise is\nbegin\n CONSTANT config:
STD_LOGIC_VECTOR (1 to 35) := (X\"%x\" & \"000\");\nend package;",
my_magic_number); //or something less ugly

please excuse duplicate post!

- Brian- Hide quoted text -

- Show quoted text -

I don't think that quite works for what I'm doing:
I have to run a test on each of 35 signals, always, each of which are
one of 6 different types, so I have 6 processes, one per signal type.
However, as the definition of each signal type is still in a state of
flux, I need to be able to easily move a signal from one test process
to another. That's why i think the nested generate with "IF"s works
OK; I just move an i=7 (for example) from one generate to another.

I think your constant approach would need 6 constants, all 35 bits
long, one per process, with the bits set to '1' in the appropriate
places. This may be beter than the IF approach, but not sure it's
really any neater.

Thanks anyway, Niv.
 
A

Andy

I don't think that quite works for what I'm doing:
I have to run a test on each of 35 signals, always, each of which are
one of 6 different types, so I have 6 processes, one per signal type.
However, as the definition of each signal type is still in a state of
flux, I need to be able to easily move a signal from one test process
to another. That's why i think the nested generate with "IF"s works
OK; I just move an i=7 (for example) from one generate to another.

I think your constant approach would need 6 constants, all 35 bits
long, one per process, with the bits set to '1' in the appropriate
places. This may be beter than the IF approach, but not sure it's
really any neater.

Thanks anyway, Niv.

Try an enumerated type constant array, with 35 elements. The
enumerated type would have 6 values, one for each type of signal.

You could then use 6 parallel if-generates inside a for-generate. This
one area where a case-generate statement would be cool.

You may want to explore other ways to accomplish this. Things like
procedure overloading based on the vhdl type of the argument come to
mind: if you had a procedure that took the signal as an argument, then
you could have 6 different copies of that procedure, all named the
same. The compiler would automatically call the correct one based on
the vhdl type of the argument you gave it.

Then you just have to figure out a way to step through a list of
signals that are of different types (assuming they are different vhdl
types). I've always wished you could use a for-generate (or for-loop)
statement to step through the elements in a record, with the loop
index taking on the name of the element for each iteration.

type data_type is record...

for i in data'range generate
test(data.i); -- won't work :(
end loop;

Also, this is a little nit, but when iterating through an array with a
for-loop or for-generate, use the 'range or 'reverse_range attributes!
They were tailor-made for this: self documenting, and easier to
maintain (just add/subtract an element to/from the array, and the loop
automatically adapts to accommodate it).

Andy
 
M

Martin Thompson

Niv said:
I now have a set of test bench processes which work nicely on my 35
output signals, verifying their correct assertion/negation/timing etc.

To do this I've concatenated the signals into a 35 bit SLV, and then
used GENERATE for the test process for each signal type; e.g. below
for one such.

-------------------------------------------------------------------------------------------------------------------------
two_state_assert_hi_drv_en: FOR i IN 19 TO 24 GENERATE
hi_two_state_assert_check_drv_en: PROCESS
....
....
WAIT UNTIL ((reset_n = '0') OR event_0_to_1(all_outputs(i)))
FOR timeout;
...
...
END PROCESS hi_two_state_assert_check_drv_en;
END GENERATE;
-------------------------------------------------------------------------------------------------------------------------
However, I may need to re-assign signals to a different group, so what
I'd like to do is use the generate statement like you do with a CASE
statement, as follows:

FOR i IN 19 OR 22 TO 24 GENERATE

but obviously this doesn't work.

Any ideas how I can generate for unique, non-contiguous, integers?
This will make it very easy to move signals around my 6 different
process types, otherwise I have to re-arrange the signal order and
then edit all the generate statement indices.

TIA, Niv.


Can you do:

type t_int_array is array (natural range <>) of integer;
constant ints : t_int_array := (19,22,44);

for i in ints'range generate
do_something (ints(i));
end generate;

Cheers,
Martin
 
B

Brian Drummond

I don't think that quite works for what I'm doing:
I have to run a test on each of 35 signals, always, each of which are
one of 6 different types, so I have 6 processes, one per signal type.
However, as the definition of each signal type is still in a state of
flux, I need to be able to easily move a signal from one test process
to another. That's why i think the nested generate with "IF"s works
OK; I just move an i=7 (for example) from one generate to another.

The above implies that any signal is applied to just one process,
(during a particular simulation)

Then an array of integer (range 0 to 6) could control the assignment of
signals to processes.

Inside the for...generate statement, six if..generate..statements
connect each signal to one of six processes (or nothing) according to
the value of the integer.

As Andy says, an enumeration type could be neater and work equally well,
though the integers may be easier to customise.

- Brian
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top