Another Rusty Topic -- Locally Static

Discussion in 'VHDL' started by M. Norton, Mar 16, 2010.

  1. M. Norton

    M. Norton Guest

    Hello again. I'm running into something I think ought to work, and as
    far as I can tell from Ashenden, it ought to work, but it all is based
    around values being locally static.

    I have a record type to aggregate information about my memory map.
    Something like:

    type MEMORY_STRUCT is record
    source_device_id : std_logic;
    source_channel : unsigned(3 downto 0);
    mem_bank : std_logic;
    mem_base_addr : unsigned(15 downto 0);
    end record;

    Then using this I defined constants:

    constant C_MYCHANNEL : MEMORY_STRUCT := ('1', X"2", '0', X"8000");

    This is declared IN THE ARCHITECTURE BODY, which appears to be an
    important point. The only discussion of doing this sort of thing I
    found in Ashenden was handling deferred constants that were declared
    but not defined in a package. As far as I can tell for this
    architecture, the constant ought to be static and known at the time of
    analysis.

    Then later I'm getting errors are a case choice:

    case current_channel is
    when C_MYCHANNEL.source_channel =>

    And the compiler declares C_MYCHANNEL.source_channel to not be locally
    static. However it's constant, declared local to the architecture
    body, fully defined in the architecture body... what am I missing
    here? Is it the fact that I'm referencing a record subvalue? Still,
    the value of that is constant as far as I can tell and additionally
    declared and defined locally, so I'm not entirely certain what isn't
    locally static.

    Fortunately it's not a major issue, there are only 15 choices and I
    can just go in and declare string constants, but I'd prefer to
    abstract that out if possible. It just seems to make more sense that
    way.

    Anyhow, if anyone knows why the constant isn't static, I'm all ears.
    Thanks!

    Best regards,
    Mark Norton
    M. Norton, Mar 16, 2010
    #1
    1. Advertising

  2. M. Norton

    Andy Guest

    Just a guess, but is the record type, as well as the constant,
    declared in the same architecture as contains the case statement?
    Maybe it is having a problem withe the ".source_channel" part?

    Andy
    Andy, Mar 16, 2010
    #2
    1. Advertising

  3. M. Norton

    M. Norton Guest

    On Mar 16, 3:11 pm, Andy <> wrote:
    > Just a guess, but is the record type, as well as the constant,
    > declared in the same architecture as contains the case statement?
    > Maybe it is having a problem withe the ".source_channel" part?


    Well I figure it must be the record type. If I had declared something
    like:

    constant C_MYCHANNEL_SRC_CHAN : unsigned(3 downto 0) := X"2";

    I'm absolutely sure that I could use that value as the expression
    value in the /when/ portion of a sequential case statement. It's a
    little disappointing though as it seemed quite nice to bundle this
    information together in a single location. Creating another ancillary
    group of constants just to support the one value in the record that I
    want to select against seems inelegant. I was stymied because I
    thought I couldn't make the value any more local or static than what I
    did (obviously not static enough). In the interests of getting it
    done, I've simply gone back and used string constants for my /when/
    expressions, but I grumbled while I did it ;-).
    M. Norton, Mar 16, 2010
    #3
  4. M. Norton

    M. Norton Guest

    On Mar 16, 3:11 pm, Andy <> wrote:
    > Just a guess, but is the record type, as well as the constant,
    > declared in the same architecture as contains the case statement?
    > Maybe it is having a problem withe the ".source_channel" part?


    I realized I misread what you were asking. The answer is yes. The
    type/record statement is in the architecture definition along with the
    constants. I should have been more explicit with my psuedo-code
    earlier. Something like this more fully illustrates the scopes
    involved.

    architecture rtl of foobar_driver is

    type MEMORY_STRUCT is record
    source_device_id : std_logic;
    source_channel : unsigned(3 downto 0);
    mem_bank : std_logic;
    mem_base_addr : unsigned(15 downto 0);
    end record;

    constant MY_CONSTANT : MEMORY_STRUCT := ('1', X"2", '0',
    X"8000");

    begin

    SOME_PROCESS : process (clk, rst)
    begin
    ...
    case my_signal is
    when MY_CONSTANT.source_channel => -- !!!!! Flagged as
    not locally static.
    ...
    end process;

    end architecture rtl;

    So, it's not even that. It must be a fundamental condition of "non-
    static" for record objects for any identifier whether signal,
    variable, or constant.

    Mark
    M. Norton, Mar 16, 2010
    #4
  5. On Tue, 16 Mar 2010 12:08:10 -0700 (PDT), "M. Norton" wrote:

    >Hello again. I'm running into something I think ought to work, and as
    >far as I can tell from Ashenden, it ought to work, but it all is based
    >around values being locally static.


    So, we all knew that VHDL has an obsessive-compulsive streak,
    and here it is on public display, as obvious as a train-spotter
    with a nervous tic.

    >I have a record type to aggregate information about my memory map.
    >Something like:
    >
    >type MEMORY_STRUCT is record
    > source_device_id : std_logic;
    > source_channel : unsigned(3 downto 0);
    > mem_bank : std_logic;
    > mem_base_addr : unsigned(15 downto 0);
    >end record;
    >
    >Then using this I defined constants:
    >
    >constant C_MYCHANNEL : MEMORY_STRUCT := ('1', X"2", '0', X"8000");


    And then you found that the constant couldn't be used as a case
    statement choice, because it isn't locally static. Grrrr.

    >This is declared IN THE ARCHITECTURE BODY, which appears to be an
    >important point.


    It isn't especially important. The important thing is that
    a record aggregate expression is not on the rather short list
    of things that count as locally static expressions (section
    7.4.1 in the 2002 LRM; I don't have the 2008 LRM to hand).
    So, in its turn the record constant is not locally static,
    and therefore neither is an element selected from it.

    So your simulator is obsessively telling the truth as per LRM.

    No, I didn't know that either until I looked it up. And
    I agree with you that it is way, way irritating.

    I *think* that VHDL-2008 has considerably relaxed the rules
    about static-ness of things appearing in a case statement.
    Check with Jim Lewis's excellent "Just the new bits" book.
    However, the easy (but slightly ugly) workaround is to
    re-cast your case statement as an if...elsif... instead.

    For a maximally synthesis-friendly version you could
    consider building an array of such constants, and
    scanning a for-loop over that array, comparing the input
    value with each in turn. I have used this approach
    successfully in the past to build address decoders and
    suchlike that are driven from a table of constants.

    > The only discussion of doing this sort of thing I
    > found in Ashenden [...]


    I know this sounds a bit schoolmaster-ish, but I've
    generally found that there is no substitute for having
    the LRM to hand when it comes to gnarly stuff like this.
    The VHDL LRM is not exactly something you'd read over
    the morning toast and marmalade, but it is rather precisely
    written and generally rewards the diligent by serving up
    the right answers to troublesome questions. Whether those
    answers are the ones you wanted to hear is quite another
    matter.

    >Fortunately it's not a major issue, there are only 15
    > choices and I can just go in and declare string constants,


    No, don't do that. Structured constants are one of the
    really good things about VHDL. Find another way to use
    them that doesn't offend the compiler's more delicate
    sensibilities.

    cheers
    --
    Jonathan Bromley
    Jonathan Bromley, Mar 16, 2010
    #5
  6. Jonathan Bromley <> writes:

    > On Tue, 16 Mar 2010 12:08:10 -0700 (PDT), "M. Norton" wrote:
    >
    > >Hello again. I'm running into something I think ought to work, and as
    > >far as I can tell from Ashenden, it ought to work, but it all is based
    > >around values being locally static.

    >
    > So, we all knew that VHDL has an obsessive-compulsive streak,
    > and here it is on public display, as obvious as a train-spotter
    > with a nervous tic.
    >
    > It isn't especially important. The important thing is that
    > a record aggregate expression is not on the rather short list
    > of things that count as locally static expressions (section
    > 7.4.1 in the 2002 LRM; I don't have the 2008 LRM to hand).
    > So, in its turn the record constant is not locally static,
    > and therefore neither is an element selected from it.
    >


    I scanned the LRM and came to the same conclusion as Jonathan. I
    wasn't entirely convinced that my interpretation was right, because I
    couldn't create an example to convince myself that there was a benefit
    in restricting the "locally static" concept that severely.

    The LRM can be concise in places, but it can also be irritatingly
    obscure and force you to search in a dozens of places to infer
    non-existence, rather than just tell you something right out.


    > For a maximally synthesis-friendly version you could
    > consider building an array of such constants, and
    > scanning a for-loop over that array, comparing the input
    > value with each in turn. I have used this approach
    > successfully in the past to build address decoders and
    > suchlike that are driven from a table of constants.
    >


    As a tangent, in a past project, I found one synthesizer that accepted
    the original record constant construct. I didn't realize it was a gray
    area until I ported the code to another synthesizer, where it
    bombed. At which point I found myself very annoyed with both vendors
    *and* the LRM.

    - Kenn
    Kenn Heinrich, Mar 17, 2010
    #6
  7. M. Norton

    M. Norton Guest

    On Mar 16, 5:23 pm, Jonathan Bromley <>
    wrote:
    > So your simulator is obsessively telling the truth as per LRM.
    >
    > No, I didn't know that either until I looked it up.  And
    > I agree with you that it is way, way irritating.


    Well frustrating because there seems to be perfect semantically
    appropriate way to describe the behavior desired and it's stifled by
    the language. I don't run into that too often, there's usually a good
    and design aesthetically pleasing way to do most things in VHDL in my
    experience.

    > I *think* that VHDL-2008 has considerably relaxed the rules
    > about static-ness of things appearing in a case statement.
    > Check with Jim Lewis's excellent "Just the new bits" book.
    > However, the easy (but slightly ugly) workaround is to
    > re-cast your case statement as an if...elsif... instead.
    >
    > For a maximally synthesis-friendly version you could
    > consider building an array of such constants, and
    > scanning a for-loop over that array, comparing the input
    > value with each in turn.  I have used this approach
    > successfully in the past to build address decoders and
    > suchlike that are driven from a table of constants.


    I have to admit, I try to be a progressively modern digital VHDL
    designer who doesn't get worried over using variables and all that,
    but for-loops in RTL code still (possibly irrationally) make me a
    little phobic. The guy I was working with yesterday had a shift
    register construct he'd gotten out of a textbook that used a for-loop
    and I was a little shocked THAT wasn't the part of the code that was
    having trouble. Apparently the synthesizer was just peachy with it.

    I have used the array method for testbenches before and agree that it
    can be very handy. I've just never attempted it for RTL. I may punt
    and go with your if-elsif structure for the moment until I have time
    to experiment with the for loop construct. I will have to create an
    ARINC-429 interface soon too, and the table of addresses and labels
    that need to be supported for ARINC also lend themselves to this
    constant record array method and that might be a good way to
    experiment and fold it into getting things done at the same time.

    > > The only discussion of doing this sort of thing I
    > > found in Ashenden [...]

    >
    > I know this sounds a bit schoolmaster-ish, but I've
    > generally found that there is no substitute for having
    > the LRM to hand when it comes to gnarly stuff like this.
    > The VHDL LRM is not exactly something you'd read over
    > the morning toast and marmalade, but it is rather precisely
    > written and generally rewards the diligent by serving up
    > the right answers to troublesome questions.  Whether those
    > answers are the ones you wanted to hear is quite another
    > matter.


    I believe you are quite likely right with this. Ashenden is so
    comprehensive that it's easy to forget it's not DEFINITIVE in the same
    way the language reference manual is.

    Thanks for the commentary, I really appreciate it.

    Best regards,
    Mark Norton
    M. Norton, Mar 17, 2010
    #7
  8. M. Norton

    Andy Guest

    On Mar 17, 8:41 am, "M. Norton" <> wrote:
    > I have to admit, I try to be a progressively modern digital VHDL
    > designer who doesn't get worried over using variables and all that,
    > but for-loops in RTL code still (possibly irrationally) make me a
    > little phobic. The guy I was working with yesterday had a shift
    > register construct he'd gotten out of a textbook that used a for-loop
    > and I was a little shocked THAT wasn't the part of the code that was
    > having trouble. Apparently the synthesizer was just peachy with it.


    It helps to think about RTL for-loops the way the synthesis tool does:
    it just unrolls them. This is why most synthesizable for-loops must
    have "static" bounds (from an RTL POV, not necessarily an LRM POV).

    Also keep in mind that, once the loop is unrolled, then the index
    value is just another static value for each iteration of the loop. So
    it can be used where, for instance you need a static power of two, or
    you need to bound an inner loop using the current outer index value.

    The reverse is also helpful. If a case statement contains (or can be
    written to contain) sequentially indexed when => statements and
    assignments/expressions, it can often be re-written into a series of
    if-then statements. Then that series can be rolled up into a loop.

    Rolling up an if-then-else series into a loop usually involves the use
    of an exit statement.

    For example:

    if input(0) = '1' then
    ...
    elsif input(1) = '1' then
    ...
    elsif input(2) = '1' then
    ...
    end if;

    Can be re-written as:

    for i in input'reverse_range loop
    if input(i) = '1' then
    ...
    exit; -- exit the loop
    end if;
    end loop;

    Happy Looping,

    Andy
    Andy, Mar 17, 2010
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sam
    Replies:
    1
    Views:
    307
    Keith Thompson
    Sep 24, 2008
  2. M. Norton

    Rusty with Configurations

    M. Norton, Mar 16, 2010, in forum: VHDL
    Replies:
    9
    Views:
    679
    Martin Thompson
    Mar 23, 2010
  3. David Hearn

    Rusty on the ASP. Array Question

    David Hearn, Aug 16, 2006, in forum: ASP General
    Replies:
    2
    Views:
    249
    David Hearn
    Aug 16, 2006
  4. Tricky

    Re: Really Rusty in VHDL...

    Tricky, Mar 30, 2012, in forum: VHDL
    Replies:
    1
    Views:
    736
    MBodnar
    Mar 30, 2012
  5. KJ
    Replies:
    1
    Views:
    724
Loading...

Share This Page