hierarchical signal names inside generate statements

P

Peter Riocreux

Guest
What follows seems to be true in Modelsim v5.8b and 5.8c, but I cannot
speak for other tools or other Modelsim versions.

With the code at the end of this post, if the instantiation of X is
replaced by that of (the commented-out) Y or Z then the andtree module
works as expected, but with X as the instantiation, the inputs to the
gates thus generated are not driven so we get an x output when all
input bits are 1.

In the LRM, there are no examples that I could find of using a
hierarchical name on a port of an instantiation inside a generate, so
I can't tell if everything is as everyone else would expect, or if one
or both of the working variants should not, or if the one not working
should, or if I have made some kind of error.

Can anyone enlighten me as to whether this is expected behaviour, my
error or the tool's error.


Peter


----8<--------8<--------8<--------8<--------8<--------8<----
`timescale 1ns/10ps

module my_and2(o, i0, i1);
output o;
input i0, i1;
and I0 (o, i0, i1);
endmodule

module andtree (o, a);
parameter SIZE = 8;
output o;
input [SIZE-1:0] a;

genvar i, j;
generate
for (j=(SIZE/2); j>=0; j=j-1) begin:LEVEL
for(i=0; i<(2**j); i=i+1) begin:GATE
if (j<(SIZE/2))
begin
assign p1 = LEVEL[j+1].GATE[i*2].t1;
assign p2 = LEVEL[j+1].GATE[i*2+1].t1;
my_and2 X (t1, LEVEL[j+1].GATE[i*2].t1, LEVEL[j+1].GATE[i*2+1].t1);
//my_and2 Y (t1, p1, p2);
//and Z (t1, LEVEL[j+1].GATE[i*2].t1, LEVEL[j+1].GATE[i*2+1].t1);
end
else
begin
buf B( t1, a);
end
end
end
endgenerate
assign o = LEVEL[0].GATE[0].t1;

endmodule

module test;
reg [3:0] a;
wire o;

andtree #(4) I0 (o, a);

initial $monitor($time,, "a=", a, " o=", o);

initial begin
a = 0;
#10 a = 1;
#10 a = 4'hf;
#10 $finish;
end
endmodule
----8<--------8<--------8<--------8<--------8<--------8<----
 
Hi Peter,

I'm not sure that can solve your problem, but you seems having forget
some thing about 'generate'

The 'generate' give you the capability to regroup some part of code with
similar syntax.

But the code must remain valid when you made 'manual' deployment of loops.

In your case, you instantiate (size/2 * 2^size/2 = 4 * 16 =) 64 times
the component my_and2 X.

I am not sure that you haven't instantiation problem after ;-)
I think that you must add something to differentiate all implementations.

If I made a intrepretation mistake, I will be happy to learn.

JaI

Peter Riocreux wrote:

snip


----8<--------8<--------8<--------8<--------8<--------8<----
`timescale 1ns/10ps

module my_and2(o, i0, i1);
output o;
input i0, i1;
and I0 (o, i0, i1);
endmodule

module andtree (o, a);
parameter SIZE = 8;
output o;
input [SIZE-1:0] a;

genvar i, j;
generate
for (j=(SIZE/2); j>=0; j=j-1) begin:LEVEL
for(i=0; i<(2**j); i=i+1) begin:GATE
if (j<(SIZE/2))
begin
assign p1 = LEVEL[j+1].GATE[i*2].t1;
assign p2 = LEVEL[j+1].GATE[i*2+1].t1;
my_and2 X (t1, LEVEL[j+1].GATE[i*2].t1, LEVEL[j+1].GATE[i*2+1].t1);
//my_and2 Y (t1, p1, p2);
//and Z (t1, LEVEL[j+1].GATE[i*2].t1, LEVEL[j+1].GATE[i*2+1].t1);
end
else
begin
buf B( t1, a);
end
end
end
endgenerate
assign o = LEVEL[0].GATE[0].t1;

endmodule

module test;
reg [3:0] a;
wire o;

andtree #(4) I0 (o, a);

initial $monitor($time,, "a=", a, " o=", o);

initial begin
a = 0;
#10 a = 1;
#10 a = 4'hf;
#10 $finish;
end
endmodule
----8<--------8<--------8<--------8<--------8<--------8<----

 
Peter Riocreux <par+usenet@silistix.com> wrote in message news:<85briujzd9.fsf@fathom.silistix.com>...
With the code at the end of this post, if the instantiation of X is
replaced by that of (the commented-out) Y or Z then the andtree module
works as expected, but with X as the instantiation, the inputs to the
gates thus generated are not driven so we get an x output when all
input bits are 1.
I don't see any reason why instantiating gates should work but
instantiating modules wouldn't. They should work the same way.
This should be independent of generates. So this sounds like a
bug in your tool.

But there is another issue with your design, involving the language
definition. If you don't care about the details, and just want to
avoid the problem, you should declare t1 as a net explicitly inside
scope GATE instead of relying on implicit declaration. It is possible
this might work around your tool problem also.

In the LRM, there are no examples that I could find of using a
hierarchical name on a port of an instantiation inside a generate, so
I can't tell if everything is as everyone else would expect, or if one
or both of the working variants should not, or if the one not working
should, or if I have made some kind of error.
There are some serious issues with the way generates are described in
the LRM. The description is not entirely clear. The way most people
would probably interpret the LRM is not practical to implement in tools.
As a result, different implementers may have interpreted it different
ways, leading to incompatibilities between tools.

The IEEE 1364 Verilog Standards Group has significantly revised the
generate section for the next version of the standard, to resolve the
implementation problems and clarify how they should work. The intent
was that this would be the recommended interpretation even before the
next standard, to get compatibility between tools.

As you appear to understand already, LEVEL and GATE in your design are
scopes (actually more like arrays of scopes). The LRM requires these
scope names on for-generates. The revision makes the names optional,
but the body of the for-generate is still a scope. The name can be left
off unless you need it for a hierarchical reference to the scope (as
you do in this case).

However, the revision also clarifies that conditional generates
(generate-if and generate-case) also create scopes. The LRM allowed
named blocks inside conditional generates, but did not require them.
With the revised version, this works the same way as the for-generates.
You can leave the name off unless you need it for a hierarchical
reference. But even without the name, you still have a nested scope.

In your testcase, you have not explicitly declared t1, but use it
in an instance port list. That means you get an implicit declaration
of a scalar net (of the default nettype). This declaration will
appear in the same scope as the instance that caused it to be created.
That scope is inside the "if (j<(SIZE/2))". Since you didn't name
the if-generate scope, you can't use its name in a hierarchical
reference. So you can't reference t1 from outside the if-generate
that it is inside.

There are two possible solutions to this. The easy one is to put in
an explicit declaration of t1 inside GATE. Then it will appear in
that scope and your hierarchical references should be fine. The messy
solution would be to give the conditional-generate blocks explicit
names.

I think the easy solution is also more likely to work with tools that
have not followed this interpretation.
 
sharp@cadence.com (Steven Sharp) writes:

Peter Riocreux <par+usenet@silistix.com> wrote in message news:<85briujzd9.fsf@fathom.silistix.com>...
With the code at the end of this post, if the instantiation of X is
replaced by that of (the commented-out) Y or Z then the andtree module
works as expected, but with X as the instantiation, the inputs to the
gates thus generated are not driven so we get an x output when all
input bits are 1.

I don't see any reason why instantiating gates should work but
instantiating modules wouldn't. They should work the same way.
This should be independent of generates. So this sounds like a
bug in your tool.
The vendor has confirmed that it is a bug, and has been fixed in an
upcoming version subject to the conditional blocks being named.

....... declare t1 as a net explicitly inside scope GATE instead of
relying on implicit declaration. It is possible this might work
around your tool problem also.
In this case it didn't - they had previously been explicitly declared,
but I took out everything I could that didn't alter the behaviour I
was trying to ilustrate before posting.

In the LRM, ........ I can't tell if everything is as everyone
else would expect, or if one or both of the working variants should
not, or if the one not working should, or if I have made some kind
of error.

There are some serious issues with the way generates are described in
the LRM. The description is not entirely clear.
Understatement of the year! :)

The way most people would probably interpret the LRM is not
practical to implement in tools.
It is not obvious to me what interpretation is not practical - care to
elaborate? If I know what is never going to be supported I can make
sure I don't try to code that way.

As you appear to understand already, LEVEL and GATE in your design are
scopes (actually more like arrays of scopes). The LRM requires these
scope names on for-generates. The revision makes the names optional,
but the body of the for-generate is still a scope. The name can be left
off unless you need it for a hierarchical reference to the scope (as
you do in this case).

However, the revision also clarifies that conditional generates
(generate-if and generate-case) also create scopes. The LRM allowed
named blocks inside conditional generates, but did not require them.
With the revised version, this works the same way as the for-generates.
You can leave the name off unless you need it for a hierarchical
reference. But even without the name, you still have a nested scope.
This is *much* saner, I am pleased. Another problem we have been
fighting (not with this example) is that we have either implicit or
explicit declaration of a net with the same name in multiple parts of
a nested if-else, and the heirarchy viewer after compilation shows
multiple instances of the same named net in the same scope. Leaving
aside the fact that it should not have created the nets in multiple,
exclusive cases of the if-else, we couldn't tell which had come from
where as they were in the same scope.

In your testcase, you have not explicitly declared t1, but use it
in an instance port list. That means you get an implicit declaration
of a scalar net (of the default nettype). This declaration will
appear in the same scope as the instance that caused it to be created.
That scope is inside the "if (j<(SIZE/2))". Since you didn't name
the if-generate scope, you can't use its name in a hierarchical
reference. So you can't reference t1 from outside the if-generate
that it is inside.
Is that still the case if the implicit declaration is by a dotted-path
use, such as LEVEL.GATE{j].t1? That cannot be in the current scope
as there is no downward scope, or does the upward scope searching
mechanism still apply?

Regards,

Peter
 
Peter Riocreux <par+usenet@silistix.com> wrote in message news:<857jt4bc6l.fsf@fathom.silistix.com>...
sharp@cadence.com (Steven Sharp) writes:
I don't see any reason why instantiating gates should work but
instantiating modules wouldn't. They should work the same way.
This should be independent of generates. So this sounds like a
bug in your tool.

The vendor has confirmed that it is a bug, and has been fixed in an
upcoming version subject to the conditional blocks being named.
I thought that the naming the conditional blocks was required by the language?

--a
 
Peter Riocreux <par+usenet@silistix.com> wrote in message news:<857jt4bc6l.fsf@fathom.silistix.com>...
The way most people would probably interpret the LRM is not
practical to implement in tools.

It is not obvious to me what interpretation is not practical - care to
elaborate? If I know what is never going to be supported I can make
sure I don't try to code that way.
The conceptual model for the LRM text seems to have been that it would
work like a text preprocessor. For an conditional generate, it would
behave as if the selected declarations had been directly in the module,
with everything else deleted (similar to an ifdef). For a for-generate,
it would be as if the loop had been unrolled and the genvar references
textually substituted with a numeric literal in each iteration.

However, it is not possible to implement generates with a text
preprocessor. They can depend on parameter values, which cannot be
determined until after the source text has been parsed and the
design is being elaborated. By this point, the design is not text
any more. It has been converted into internal data structures, such
as parse trees and symbol tables. The parser has already made a lot
of decisions that it is impractical to change or defer to this point
in the process.

The revised description makes it clear that declarations inside a
conditional generate appear inside a nested scope created for it,
rather than directly at the module level. This resolves most of
the implementation problems. For-generates already required named
scopes, because I was able to convince the standards group to fix
them before standardization (though only because it resolved a
different problem; and not everyone understood that the named blocks
were really scopes). This interpretation should make sense to anyone
familiar with VHDL generates, since they create scopes also.

Some tool implementations may have tried to match the preprocessor
style behavior, with various kludges or restrictions to try to get
around the problems. Trying to write code that will work in all of
these implementations could be difficult. Obviously you would need
to avoid making hierarchical references to objects declared inside
conditional generates, especially ones without named blocks in them.

This is *much* saner, I am pleased. Another problem we have been
fighting (not with this example) is that we have either implicit or
explicit declaration of a net with the same name in multiple parts of
a nested if-else, and the heirarchy viewer after compilation shows
multiple instances of the same named net in the same scope. Leaving
aside the fact that it should not have created the nets in multiple,
exclusive cases of the if-else, we couldn't tell which had come from
where as they were in the same scope.
This sounds like another symptom of a kludged attempt to make the
declarations appear in the surrounding scope, instead of a nested
scope.

In your testcase, you have not explicitly declared t1, but use it
in an instance port list. That means you get an implicit declaration
of a scalar net (of the default nettype). This declaration will
appear in the same scope as the instance that caused it to be created.

Is that still the case if the implicit declaration is by a dotted-path
use, such as LEVEL.GATE{j].t1? That cannot be in the current scope
as there is no downward scope, or does the upward scope searching
mechanism still apply?

"Dotted-path" or hierarchical references do not create implicit
declarations. Only references to simple identifiers do, and these
will end up in the scope where the instantiation appeared. You are
getting implicit declarations because of the simple t1 references
in the first port expression in your instances. After those implicit
declarations are created, a hierarchical name can be resolved to them
by the upward scope searching mechanism.

If it weren't for the if-generate inside GATE in your example, this
would work fine. The resolution would search upward and find the
appropriate LEVEL scope, and inside that the appropriate GATE[j]
scope, and inside that the t1 that got implicitly declared because
a simple t1 was used there without any declaration.

But with the if-generate, there is another scope between GATE[j]
and t1, and it is unnamed. The compiler should give it the created
name of genblk1, but not allow that name to be used in a hierarchical
name such as LEVEL.GATE[j].genblk1.t1. This would have made it
too easy for users to shoot themselves in the foot by relying on a
created name, only to have it change when they modified the design.
You could give the if-generate a real name yourself, but it would
be easier to just explicitly declare t1 outside the if-generate,
inside GATE[j].
 

Welcome to EDABoard.com

Sponsor

Back
Top