7

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)

Community
  • 1
  • 1
Paebbels
  • 15,573
  • 13
  • 70
  • 139

4 Answers4

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_items. 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.

  • "OUT mode generics" is a good name to describe this feature :). Writing a proposal might be a solution, but first I would like to wait for other answers. – Paebbels Jun 01 '15 at 12:29
  • What what form of item would you connect to an 'out' generic? Would a deferred constant be suitable? Also, would this create a problem due to the possibility of creating circular references? – scary_jeff Jun 01 '15 at 12:36
  • out mode generics isn't consistent with -2008, 6.5.6.2 Generic clauses "Generics provide a channel for information to be communicated to a block, a package, or a subprogram from its environment." Nothing about 'from a block'. It's a new category - elaboration order dependency checks and sounds like you'd require something be locally static to break loops and it may be tough to get the semantic description right. (The attributes in the other answers depend on analysis order). Might take a while for synthesis vendors to cotton to the idea. –  Jun 01 '15 at 13:33
  • It would probably be a deferred constant or something very like it, whose value may be set in the architecture - for example the length of the array of pipe stages. @David Koontz - if this WAS consistent with -2008, the question probably wouldn't have been asked. –  Jun 01 '15 at 13:48
  • An expanded name with a prefix that's an entity can only be accessed in the 'construct' itself or it's architectures (-2008 8.3 Selected names, para 9). Your possible approach calling functions declared as an entity declarative item shouldn't work. –  Jun 01 '15 at 14:14
  • @DavidKoontz this is just an idea for something to be added; nobody is suggesting that an output generic would be possible with any current tool. – scary_jeff Jun 01 '15 at 14:38
  • @scary_jeff Yes, the circular reference problem came to my mind, too. Hypothetically spoken: A deferred constant could be a nice way to grab a constant from another module. – Paebbels Jun 01 '15 at 15:09
  • What about hierarchical references? I found this SE question, where @JimLewis noted that these references should also work with constants: `A <= <>;` [Get internal signals of vhdl design in ncvhdl (alternative to modelsim's signal spy)](http://stackoverflow.com/a/24536327/3719459) – Paebbels Jun 08 '15 at 19:08
  • Haven't tried it, but it might work with adequate VHDL-2008 support. My concern is that since its intent is to smash open encapsulation to allow white box testing, it's unlikely to ever have synthesis support. If your purpose is simulation only, then it may work. –  Jun 08 '15 at 20:31
2

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:

  1. 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.

  • It works as is on modelsim. The problem with that is the `delay` attribute is constant, while OP wants it to depends on generics. I think that's what Morten tried, since the error he reported is about the *label* `alu_div_0', and not the entity `work.alu_div`. – Jonathan Drolet Jun 01 '15 at 16:15
  • @JonathanDrolet, Ya, and I made the point in another comment that the expressions in an attribute specification were locally static. (Duh Oh!). Morten's reported error still misses the mark. –  Jun 01 '15 at 23:24
  • What about hierarchical references? I found this SE question, where @JimLewis noted that these references should also work with constants: `A <= <>;` [Get internal signals of vhdl design in ncvhdl (alternative to modelsim's signal spy)](http://stackoverflow.com/a/24536327/3719459) – Paebbels Jun 08 '15 at 19:17
  • External names won't synthesize and are only suitable for verification. Communication between blocks is via signals. Entity/architecture pairs have block statement equivalents on elaboration, providing visibility restrictions, localizing name space. Shared variables are used to communicate between processes. Note that post elaboration a design network is flat and name space is represented by unique declaration which has locality in a design hierarchy. An implementation references declared objects by ID. Path/instance names are for people. –  Jun 08 '15 at 19:57
1

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.

Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
1

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.