Conditional Generates

A

Andy

Hello All,

I've a question with regards to conditional generates. I'm using a 'for
generate' to interconnect an array of signals. I'm then using the index
of this generate to set the connectivity of the array.

The following is an example to demonstrate the problem (A complete
example module is described below). It seems that 'Method One' should
work, as x-1 is only used when x>0. However, Modelsim complains about
the indexing being out of range. If, however, I use method Two,
everything is OK.

VectorNextLogic : for x in 0 to 7 generate
begin

-- Method One (doesn't work)
dataVector(x) <= dIn(x) xor dataVector(7) when (x=0) else
dIn(x) xor dataVector(x-1);

-- Method Two (does work)
BitConnect0 : if (x=0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(7);
end generate;

BitConnect1 : if (x>0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(x-1);
end generate;

end generate;

I'm guessing that 'Method One' is not legal/valid VHDL, but would like
to know for sure. Also, is 'method Two' the only available approach to
this problem? It seems far more prone to error, and in the real module
in which I need to do this, it would require a great deal more code.

Any help/advice/comments much appreciated.
Many Thanks
Andy


References:
http://groups.google.co.uk/group/co...read/thread/e66302c5b11aa0c1/50ee70d2b0aa9287

For Module:

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

entity Test is
port ( clk : in std_logic;
nReset : in std_logic;
dIn : in std_logic_vector(7 downto 0);
dOut : out std_logic_vector(7 downto 0));
end Test;

architecture General of Test is

signal dataVectorNext : std_logic_vector(7 downto 0);
signal dataVector : std_logic_vector(7 downto 0);

begin

dOut <= dataVector;

process (clk)
begin

if (clk'event and clk='1') then

if (nReset='0') then
dataVector <= (others => '0');

else
dataVector <= dataVectorNext;

end if;
end if;
end process;

VectorNextLogic : for x in 0 to 7 generate
begin

-- Method One (doesn't work)
dataVector(x) <= dIn(x) xor dataVector(7) when (x=0) else
dIn(x) xor dataVector(x-1);

-- Method Two (does work)
BitGen0 : if (x=0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(7);
end generate;

BitGen1 : if (x>0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(x-1);
end generate;

end generate;

end General;
 
K

KJ

Doesn't directly address the question about the generate but

-- Method Three (might work)
dataVector(x) <= dIn(x) xor dataVector((x-1) mod 8);

KJ
 
A

Andy

KJ said:
Doesn't directly address the question about the generate but

-- Method Three (might work)
dataVector(x) <= dIn(x) xor dataVector((x-1) mod 8);

KJ
KJ,

Thanks for the pointer. That's a trick I've used before when working
with arrays that wrap around. Very handy when doing things like cellular
Automata. But in this case that doesn't happen.

What interests me more is that, x-1 when x=0 should never need to be
calculated, so an out of range 'should' never occur.

Cheers
Andy
 
J

Jonathan Bromley

It seems that 'Method One' should
work, as x-1 is only used when x>0. However, Modelsim complains about
the indexing being out of range. If, however, I use method Two,
everything is OK.

VectorNextLogic : for x in 0 to 7 generate
begin

-- Method One (doesn't work)
dataVector(x) <= dIn(x) xor dataVector(7) when (x=0) else
dIn(x) xor dataVector(x-1);

-- Method Two (does work)
BitConnect0 : if (x=0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(7);
end generate;

BitConnect1 : if (x>0) generate
begin
dataVectorNext(x) <= dIn(x) xor dataVector(x-1);
end generate;

end generate;

I believe ModelSim is right here. The conditional signal assignment
works not only with constants but also with any expression as the
conditional, so "datavector(x-1)" is part of the overall expression;
I know that (x=0) is a constant expression, but that's an
optimisation issue. Effectively, one pass of your generate
loop gets re-written as

dataVector(0) <= dIn(0) xor dataVector(7) when (TRUE) else
dIn(0) xor dataVector(-1);

and the error is manifest long before anyone gets to deciding
that the second branch is unused.

I agree that your "Method 2" is tiresome; VHDL's
lack of "else" on "if...generate" is pretty painful here.

I guess the example you've posted is a simplified version of what
you're really trying to do, so you need a reasonably robust fix.
How about the following...

G: for x in dataVector'range generate
datavector(x) <= dIn(x) xor dataVector( index_shuffle(x) );
endgenerate;

where "index_shuffle" is a function that takes the integer
value x and returns the modified index you want. Now all
the messy complexity can be pushed into the function.
What's more, you can avoid any compiler warnings
by declaring the function so that its return value is of
type "dataVector'range", so the body of the generate
statement cannot possibly have any out-of-range access.

hth
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
M

Mike Treseler

Andy said:
I've a question with regards to conditional generates.

Jonathan has provided excellent answers, as usual,
but I have another question for anyone interested.

What is a possible upside to generating processes
and wiring them up vs. using some array
type and declaring some variables to be
updated every clock in a single processs?

So far, I have:

1. A generate could drive a tri-state pin interface.
2. ?

The generate loop works and is very popular,
but it is also very tedious on the edges
and in the wiring.

-- Mike Treseler
 
J

Jonathan Bromley

What is a possible upside to generating processes
and wiring them up vs. using some array
type and declaring some variables to be
updated every clock in a single processs?

So far, I have:
1. A generate could drive a tri-state pin interface.

And, in general, it's rather easier to control what
drivers you're creating when using generate.
Sometimes that matters. Most times, though,
there's an easier way around it. I'm not as
completely convinced as Mike of the virtues of
big single-process designs - I was brought up on
Occam and CSP, so my instinct is to decompose
a design into blocks that communicate in a
well-structured way - but for anything
algorithmic, software-like processes are IMHO
something that's worth striving for.

My standard answer to that always used to be
"because generates allow you to describe variable-
sized structures, and allow you to declare the variable-
sized interconnects between the parts of those structures".
For Verilog, this would be completely true, I think. But
in VHDL we have the delights of dynamically-elaborated
subprograms - the variables in a function are manufactured
only when the function is called - and this does pretty
much everything you need for building funny-shaped
hardware: trees, jagged arrays and the like. Any
interconnect that gets unnecessarily declared will
in due course be optimised away by synthesis. So
my views on this are increasingly aligned with Mike's.

However, you may well be confronted with existing
design fragments that are structured as components
or processes, and you need to create groupings of
those things. In such a case, generate provides an
easy way out.
The generate loop works and is very popular,
but it is also very tedious on the edges
and in the wiring.

It's hard to disagree.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
M

Mike Treseler

Jonathan said:
I was brought up on
Occam and CSP, so my instinct is to decompose
a design into blocks that communicate in a
well-structured way -

You are ahead of your time.
At some high level, communication becomes
serial and very well-structured. It used
to be cross-country. Buses like
PCIe make it happen at a few centimeters.
I have no doubt this will become
a canned, on-chip "buffer" someday.
but for anything
algorithmic, software-like processes are IMHO
something that's worth striving for.

That's a software-like thread
describing *parallel* hardware.
The point is to get the outputs
I really want without mentioning
every wire and mux involved.

A vhdl process is a fantastic virtual
machine with registers arranged
and updated however I like.
Synthesis maintains this illusion
by unwinding procedures, arrays, and loops
without complaint. Simulation lets me
take a test drive before actual
construction has even begun.
However, you may well be confronted with existing
design fragments that are structured as components
or processes, and you need to create groupings of
those things. In such a case, generate provides an
easy way out.

That's a fine list item 2.
There is plenty of working code around
that I prefer to leave in the black box.

Thanks for the reply.

-- Mike Treseler
 
K

KJ

Mike Treseler said:
Andy wrote:
What is a possible upside to generating processes
and wiring them up vs. using some array
type and declaring some variables to be
updated every clock in a single processs?

So far, I have:

1. A generate could drive a tri-state pin interface.
2. ?
This is pretty much along the same lines as Jonathon's earlier reply, but
generated processes would seem to fit in better when the 'other' things in
the architecture don't fit into that single clocked process model (i.e. the
'other' things being components that need to be instantiated and
combinatorial equations). One example that I've used several times is
needing a bank of fifos for some purpose. Overall control of that bank
tends to be in a clocked process but the actual read and write controls into
the fifos tend to be combinatorial since they tend to involve combinatorial
gating with the full/empty status bits out of the instantiated fifos.

So you end up needing combinatorial equations to connect the process to the
instantiated component so why not put all of that inside of the same single
generate block instead of putting a single process with a for loop and the
'other' stuff inside the still needed anyway generate block?

Then again, even your #1 item about tri-states is just another example of
something that doesn't fit into the clocked process model.

If the code for the architecture of the entity's required function does fit
nicely into the single clocked process model though I agree with you that it
is generally better to use the for loops inside the single
process...although I might tend to break them up into several basically
identical processes with loops, but that's just me.

KJ
 
J

Jonathan Bromley

You are ahead of your time.
At some high level, communication becomes
serial and very well-structured. It used
to be cross-country. Buses like
PCIe make it happen at a few centimeters.
I have no doubt this will become
a canned, on-chip "buffer" someday.

Someday? How about Transputer Links, vintage 1975?
Now that's an idea that was ahead of its time (and, in
fairness, ahead of the technological capabilities that
would have made it genuinely useful). Bromley's
First Law of Technology Business asserts that any
technology product is certain to fail in the marketplace
if it meets the following three criteria:

1) It is technically competent and founded on valid theory.
2) It is ahead of its time by more than 2 years.
3) It is British in origin.

SERDES I/Os on modern FPGAs do a nice job, but it
would be good if they had a handshaking protocol
layered on top of them so that you could use them
easily for synchronisation. I'm sure lots of people
do exactly that for themselves, already.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

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,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top