Andy said:
KJ,
Thanks for the comments, you raise some really good points...
I've had FPGA designs with dozens of centralized parameters; assuming
you want those managed from one place, there are two reasonable
possibilities, a global package of constants, or generic records.
I prefer to put the constants in the top level of the design itself.
If there are multiple designs that need to access the same constant
then it would go into a package. By 'top level of the design' I mean
that if for example, I have three FPGAs and one CPLD on a board then
each of those parts will have some 'top level' source file and that's
the place I would put all but the shared constants.
I realize I could pull those constants out and make them generics as
well and bring them up higher but then you can run into the problem of
you're simulating one way for building actual parts another. By
stopping the generics at the top level of a physical design and making
them constants at that level, there is no chance of that happening. In
simulating real board designs with multiple parts I find that one less
headache is a good thing but others might like to bring those constants
out to be tweaked by the simulation testbench model itself and then
manually manage that synthesis builds use the correct parameter values.
With generics, the parameters must be passed through every level, from
the top down to where they are needed. In a large, complex design,
managing what goes where is a lot tougher than managing a record
typedef, and passing everything everywhere. The record typedef becomes
the conduit, and you can pull as many wires through it as you want
(unlike a real conduit!), only having to worry about the endpoints, not
all the interfaces along the way.
I agree it is easier to manage things through the single generic record
type IF the entity is in flux and subject to change. I just haven't
hit the "threshold of pain" yet where this management hurts. Now maybe
the only reason for that is because of editor macros and the way I go
about instantiating an entity the first time. Plopping down an entity
to use it somewhere generally takes me mere moments regardless of how
many signals and generics there are.
Now if the entity itself is in flux and the signals or generics are
frequently changing then the record approach will pay for itself in
time....but so would nailing down the entity in the first place.
BTW, I've used records for signal interfaces too, but they get uglier
with in/out/inout modes. They're supposed to be working on that (mode
definitions for multi-mode record ports). Since generics are always
like "mode in", records work extremely well for generics.
I tried records for signal interfaces also and didn't like the way
Modelsim handled it in the 'Dataflow' window which I use while
debugging. I came to the conclusion that while it did sort of look
tidy to have all of the 'gazintas' in a single record, (and gazoutas
and bi-directs) in practice I didn't like to use it.
If naming collisions between record elements get to be a problem, you
could break up the record into subrecords for different sets of related
parameters, or even mimic the hierarchy of the design in the record
itself. The latter may or may not work so well when the same parameter
is used in different leaves of the hierarchy, since referencing it in
one leaf requires knowledge of the location of the other leaf where it
is set in the record.
Getting messy
You can also define functions along with the record type that override
a given element in the record, while passing the others intact, so you
do not have to manually break out the record elements and assign them
individually when you need to override an individual record element
before passing it on down. This would be helpful if an architecture
modifies a port width (muxing or demuxing it), or DCM's the clock
before handing it to a lower level entity.
Functions are great that way.
I don't really see any difference, WRT the history of a designer's
designs, between a global package opf constants and using generics to
centrally manage design parameters.
I don't either. I'll just point out that the "edit all of the design
parameters in a single file" can also be accomplished by simply putting
them as constants in whatever the 'top level' is.
We already agree that there are advantages to the record approach.
Where I was going with the "history of a designer's designs" was from
the standpoint of design reuse. In order to reuse the code without
modification you would need to not change the name of that record type.
This would lead one to choose a name for that record "KJ_Generics" and
always use that. That way any code that I write could safely get at
any record elements. Now you've done the same thing but I'm guessing
that yours might be called "Andys_Generics" or something...but
certainly not "KJ_Generics". Integrating our code will cause a bit of
headaches on those generics.
Using a record name that is somehow associated with the project
"ProjectX_Generics" doesn't solve the problem when you try to reuse
code on "Project Y".
If you don't reuse code much then this is not an issue....but since you
probably do I think it will.
You'd have to prune the package or
the record to keep the parameters pared to those needed in the current
design. Using a record simplifies the generic pruning (compared to
separate generics), since it need only be done in one place (or two, if
you break them out individually at the top level)
And that pruning will be a reason to make sure you don't do the design
specific sort of path name thing that I think you were alluding to
either. You wouldn't want any parameter to be down a path since it
will probably be down a different path when reused in a different
design.
It sounds like your argument is more specifically against centralized
parameter management, preferring to manage the parameters at the point
of use (at which point they cease being a parameter), or slightly above
it.
No I manage it at the top level of each physical design as I mentioned
earlier which is just as centralized, definitely not point of use.
Must've been confusing in my wording.
That's another approach that has both strengths and weaknesses. I
like having a single 'parameter set' that controls the whole design,
and multiple ways to control that (defaults, instance generic map,
configurations, and tool options), but it does have its costs in
maintenance, etc. Centralized management also is really nice when two
distant entities need the same parameter. Managing them locally to each
entity invites problems with keeping them in sync.
I agree but like I said I don't like to ever be caught in the situation
when there is a problem on a real board that needs debugging and I'm
simulating something that is different because of a difference in
parameter settings. Putting the constants at the top level of each
physical design (but putting constants that are shared between designs
into a package) is the best way I've found to avoid getting into that
situation.
Using a subtype of time for the clock period is a superior solution, so
long as your toolset, including simulation, formal analysis, synthesis,
etc. supports it universally.
And complain to the tool vendor when they don't, that's the best way to
improve the tool (although not guaranteed to work). Synplify responded
on my beef with 'time'. It doesn't get you past the immediate problem
if the tool chokes but like I said that's when you can band-aid it with
a type that the tool is happy with.
Some tools even support setting record
type generics on the command line, but unless they also support named
association (and not just a parenthesized list of values), that would
get really ugly, and it would probably be better to break them out into
individual generics at the top level if you intend to manage them
through the tool. If instead you only want to manage them through the
language (instance generic maps, configuration declarations, etc.) then
there is no need to break them out at the top level.
Another good reason for leaving them as constants where I do...less
tool specific issues.
I would say limit them [generic subtypes] to ranges that you've at least somewhat tested.
Thanks, that's a better way to define "practical".
Good discussion. The idea of a single generic as a record type is
certainly a 'neat and tidy' solution that has a lot of merit. Whether
people find it productive or not I think would depend on how fluid
those entity definitions are and the design reuse perspective....and
both of those will probably a function of the particular engineer and
the company they work for, etc.
KJ