问题
I have a VHDL entity with a generic parameter list. The architecture to this entity calculates several constants, which are needed to create the intended functionality.
Is it possible to access one of these constants from outside?
Example 1:
Let's say there is a FIFO that decides based on DEPTH and OUTREG what the best implementation is (register based, SRL based or BlockRAM based). Depending on this the minimum delay through the FIFO can vary from 1 to 2 cycles.
Example 2:
Consider the same FIFO to be cross clock compatible. Now the min delay depends also on the choosen sync circuits and the frequency difference.
Example 3:
A division entity needs N cycles to calculate a div b. N depends on BITS, RADIX, OUTREG, IS_SIGNED, ...
Further let's say each entity has a MIN_DELAY constant of type NATURAL which is of interest for other instances.
E.g. the instantiating entity needs to know how long it must at least wait for a result.
I can think of 2 solutions, but I think neither is a nice one.
Solution 1:
I could store the algorithmn for the computation in a package so it's globally accessable. But this is against the encapsulation principle :). The outside world only needs to know the delay value not the algorithmn.
Solution 2:
I could use a valid bit. That's always a good solution in dynamic, adaptive or pipelined systems, but this bit can not be used at synthesis time for further choices or optimizations.
Possible solution 3:
VHDL has the ability to define new attributes, but can they be accessed?
Example entity: alu_div:
constant MIN_DELAY : NATURAL := BITS / log2(RADIX) + 2;
attribute DELAY : NATURAL;
attribute DELAY of alu_div : entity is MIN_DELAY;
Example top:
mydiv : entity work.alu_div
generic map (....)
port map (....);
blk : block
constant my : NATURAL := mydiv'delay;
begin
....
end block;
NEW: Possible solution 4:
I found this SE question, where Jim Lewis noted that hierarchical references should also work with constants.alias MY_DELAY is <<constant mydiv.DELAY : NATURAL >>;
Get internal signals of vhdl design in ncvhdl (alternative to modelsim's signal spy)
回答1:
This is a modification of Morten's first entity declaration, in which for the 'module' instantiating alu_div
I expect there's a component declaration which provides the declaration for the name alu_div
.
There is no attribute decorating that declaration so the instantiation found at label alu_div_0
has no attribute DELAY
.
If you were to use direct entity instantiation it might work:
entity alu_div is
constant MIN_DELAY : NATURAL := 42;
attribute DELAY : NATURAL;
attribute DELAY of alu_div : entity is MIN_DELAY;
end entity;
architecture foo of alu_div is
begin
end architecture;
entity test is
end entity;
architecture foo of test is
begin
alu_div_0:
entity work.alu_div ;
MONITOR:
process
begin
wait for 1 ns;
report "alu_div'DELAY = " & natural'image(work.alu_div'DELAY);
wait;
end process;
end architecture;
Which gives:
ghdl -a alu_div.vhdl
ghdl -e test
ghdl -r test
alu_div.vhdl:25:9:@1ns:(report note): alu_div'DELAY = 42
>
The idea is that if you use a direct entity instantiation with a selected name (an expanded name) you're using the declaration in the library noted by the prefix (in this case WORK).
The following demonstrates accessing the value of alu_div'DELAY
can be done at elaboration:
entity alu_div is
generic (pickone: natural := 1);
constant MIN_DELAY : NATURAL := 42;
constant TARG_DELAY: natural := MIN_DELAY + pickone;
attribute DELAY : NATURAL;
attribute DELAY of alu_div: entity is MIN_DELAY;
-- attribute DELAY of alu_div : entity is TARG_DELAY;
end entity;
architecture foo of alu_div is
begin
end architecture;
entity test is
end entity;
architecture fie of test is
constant fumble: natural := work.alu_div'DELAY;
component alu_div is
generic (pickone: natural := 1);
end component;
begin
alu_div_0:
alu_div
generic map(1);
MONITOR:
process
begin
report "constant fumble = " & natural'image(fumble);
report "alu_div'DELAY = " & natural'image(work.alu_div'DELAY);
wait;
end process;
end architecture;
And that works:
ghdl -a alu_div.vhdl
david_koontz@Macbook: ghdl -e test
david_koontz@Macbook: ghdl -r test
alu_div.vhdl:60:9:@0ms:(report note): constant fumble = 42
alu_div.vhdl:61:9:@0ms:(report note): alu_div'DELAY = 42
Also following Jonathan's comment that the question was attempting to loop information through the instantiated component supplied by generics I tried switching the entity attribute to depend on a generic (commenting out the one with MIN_DELAY
, uncommenting the one with TARG_DELAY
) and that results in a different error than Morten supplied:
ghdl -a alu_div.vhdl
alu_div.vhdl:36:13: attribute expression for entity must be locally static
ghdl: compilation error
And that error is singularly helpful and easy to find in the 2008 LRM and is quite specific:
7.2 Attribute specification (paragraph 8):
The expression specifies the value of this attribute for each of the named entities inheriting the attribute as a result of this attribute specification. The type of the expression in the attribute specification shall be the same as (or implicitly convertible to) the type mark in the corresponding attribute declaration. If the entity name list denotes an entity declaration, architecture body, configuration declaration, or an uninstantiated package that is declared as a design unit, then the expression is required to be locally static (see 9.4.1)....
This requirement was introduced in the '93 LRM (5.1 Attribute specification). And researching that we find there was a proposal for out-mode generics in the -1992 standardization effort (approved in -1993).
Also in the '87 Issue Report 40 (IR00040.txt) following the first ISAC rationale report of a discussion of the problem as relates to setting the attribute from within an architecture:
- Such a capability would greatly (and negatively) affect at least some implementations. A straightforward approach to the implementation of specifications is to decorate the named entity with the information contained in the specification. However, when the entity appears in one design unit and the applicable specification appears in another, many problems result. One cannot analyze the specification without modifying the library unit containing the entity, which can lead to potential circular chains of dependence. Moreover, multiple architectures corresponding to a given entity interface cannot each supply a different value to the attribute of some interface-resident entity. Finally, there is no LRM requirement that, if one architecture attributes some interface-resident entity, then all must, which seems desirable.
You could note the undesired circular dependencies are also possible with an attribute dependent on a generic. Or similarly with out-mode generics the issue moves from circular dependencies in analysis order (locally static expressions in attribute declarations) to elaboration order (evaluating globally static expressions) which is likely quite a bit harder. out-mode generics show sporadic mention in available records, the last time on the vhdl-200x-mp (Modeling and Productivity) email reflector.
It's not likely the status of either of these will change without someone defining how to deal with late binding (linking loader time) order dependencies.
In the mean time as Brian says the accepted method is to use a package commonly shared, which uses locally static constant declarations (and are declaration order dependent). You could also manage the issue with configuration.
回答2:
Good question. I have sometimes felt the need for "OUT mode generics" too, whose actual value is computed within the architecture, again to allow the higher levels in a hierarchy to know (and adjust to) the pipeline depth of a processing unit.
It might be worth writing a proposal to allow something of the sort in VHDL-201x and submit it to the standards group but meanwhile we have to live with what we have.
My normal solution is to use a package associated with the unit, holding both the initial constant (instead of a generic) and the dependent quantities. This limits the "encapsulation breakage" to those compilation units that use
the package, making them at least readily identifiable.
Within the package the constants are deferred where possible, or parameterless (impure) functions, which amount to the same thing.
A possible approach I haven't explored is that an entity declaration, after the PORT list
, also allows zero or more entity_delarative_item
s. If these may include function declarations, then we could potentially return such information that way.
EDIT : David points out an LRM rule (8.3) that prevents this approach with current VHDL versions : a limited relaxation of that rule might be an alternative to "OUT mode generics".
An entity declaration may also include begin
and some passive constructs - such as asserts that a set of generics and port widths are consistent. That way you would have to input all the required values, but at least the build would fail reporting errors if e.g. width
and depth
were inconsistent.
回答3:
Agree that it is sometimes very useful with information about implementation details from the entity, even though it breaks the encapsulation principle, but for white box verification it can be a great help.
Tried to use entity attribute based on entity like:
entity alu_div is
generic(
BITS : positive;
RADIX : positive);
port(
...);
constant MIN_DELAY : NATURAL := BITS / log2(RADIX) + 2;
attribute DELAY : NATURAL;
attribute DELAY of alu_div : entity is MIN_DELAY;
end entity;
But the module where the alu_div
is instantiated is not able to access it
using e.g. alu_div_0'DELAY
, since ModelSim gives error:
No attribute specification with designator "DELAY" decorates label "alu_div_0".
One method that is useful for white box verification, where the verification depends on the implementation, is to make an output port with information from the implementation, like:
entity alu_div is
...
port(
...
DELAY_O : out natural);
...
end entity;
architecture syn of alu_div is
begin
DELAY_O <= MIN_DELAY;
...
It won't be a true constant, since for simulation it will need a delta cycle before getting the value, but it may be a sufficient solution in many cases.
回答4:
Another approach I have used is to live with the restriction that all "generic" information flows into a module by specifying as another generic, the result I want from the derived parameter.
For example,
entity alu_div is
generic(
BITS : positive;
RADIX : positive;
DELAY : positive);
port(
...);
Within the architecture, an ACTUAL_DELAY
constant is derived from the other generics (plus port bus-widths, etc) and compared with the given DELAY
generic.
If the requested DELAY
and ACTUAL_DELAY
are identical, all is well.
If the requested DELAY
exceeds ACTUAL_DELAY
, the architecture can insert pipeline stages to meet the request. The overall design will function as intended, though it may consume more registers than strictly necessary.
Otherwise the requested delay cannot be met, and the architecture asserts with severity FAILURE.
来源:https://stackoverflow.com/questions/30564426/can-i-access-a-constant-inside-a-instantiated-entity-from-outside