vhdl

Can I access a constant inside a instantiated entity from outside?


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)


Solution

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