Constant conversion (natural to std_logic_vector)

Discussion in 'VHDL' started by a1_nocrap_exh@hotmail.com, Apr 10, 2006.

  1. Guest

    I am in a situation where I have to increase an address bus width in
    bit of re-usable code.

    In a package there is a list of constants which are used in the address
    decode

    constant abus_width : natural := 5;
    constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) :=
    "00001";
    constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) :=
    "00010";
    etc.

    I've now increased abus_width by 2 and now all the constant literals
    need updating because they are the wrong width.

    I thought I would try to work out a way of specifying the constants so
    that they would grow with abus_width so that if we ever had to do this
    again it would automatically work e.g.

    library ieee;
    use ieee.std_logic_arith.all;

    constant abus_width : natural := 7;
    constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#01#,abus_width);
    constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#02#,abus_width);

    However I now get the following warning "Case choice must be a locally
    static expression." in the Case statements which use these constants.

    But it IS locally static isnt it? It's a constant, it's in a package,
    that package is referenced...

    Anyone ever done anything like this before or got a better technique?

    Regards

    Alex Holland
    , Apr 10, 2006
    #1
    1. Advertising

  2. Guest

    I cannot use VHDL 93's HEX literal ( X'"AA" ) because my bus is not a
    multiple of 4-bits wide.
    , Apr 10, 2006
    #2
    1. Advertising

  3. wrote:

    > However I now get the following warning "Case choice must be a locally
    > static expression." in the Case statements which use these constants.
    > But it IS locally static isnt it? It's a constant, it's in a package,
    > that package is referenced...


    Sorry, that's the way it is.
    Use an if/elsif/elsif
    http://groups.google.com/groups/search?q=vhdl case static short answer

    -- Mike Treseler
    Mike Treseler, Apr 10, 2006
    #3
  4. Guest

    > Sorry, that's the way it is.
    > Use an if/elsif/elsif
    > http://groups.google.com/groups/search?q=vhdl case static short answer


    Thanks for the link. But in this situation I am not doing anything
    fancy. These ARE constants. It should work.

    > A case expression is limited to operands that are scalar


    But they are scalar, that is my point.

    If I store my constants as naturals, and convert my std_logic_vector
    signal to integer EVERYTHING works e.g.

    constant REGISTER_A : natural := 1;
    constant REGISTER_B : natural :=2;

    case conv_integer(unsigned(addr)) is

    when REGISTER_A =>

    when REGISTER_B =>

    when OTHERS =>

    end case;

    So I dont understand why I cannot store my constants as
    std_logic_vectors that are pre-converted from naturals?

    constant abus_width := 5;

    constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#01#, abus_width);

    constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#02#, abus_width);

    case addr is

    when REGISTER_A =>

    when REGISTER_B =>

    when OTHERS =>

    end case;

    I would switch to storing them as naturals, but the code containing the
    case statement has already been to silicon, dont really want to change
    anything in that file if I can help it.

    I think I *will* find the syntax to make this warning go away.

    Anyone?

    Alex Holland
    , Apr 10, 2006
    #4
  5. Charles, NG Guest

    You may find it easier if you use subtypes: e.g.

    use ieee.numeric_std.all;
    .. . . . .
    subtype abus_type_t is std_logic_vector(7 downto 0);
    .. . . . .
    constant abus_sig_s : abus_type_t :=
    std_logic_vector(to_unsigned(2, abus_type_t'length));

    Then you only have to change the subtype dimensions in a single place if
    your bus gets resized

    Regards,
    Charles
    Charles, NG, Apr 10, 2006
    #5
  6. Guest

    I am using subtypes in my code (not in my example) it doesnt help.
    , Apr 10, 2006
    #6
  7. Guest

    >use ieee.numeric_std.all;
    > . . . . .
    > subtype abus_type_t is std_logic_vector(7 downto 0);
    > . . . . .
    > constant abus_sig_s : abus_type_t :=
    > std_logic_vector(to_unsigned(2, abus_type_t'length));
    >
    > Then you only have to change the subtype dimensions in a single place if
    > your bus gets resized


    Not that it matters but you dont have to use subtypes to only need to
    change dimensions in a single place, look at my example I posted
    earlier (or below), you change one constant "abus_width" and voila.

    constant abus_width : natural := 7;

    constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#01#,abus_width);

    constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) :=
    conv_std_logic_vector(16#01#,abus_width);

    I've used std_logic_arith rather than numeric_std... I wonder if that
    helps? I doubt it.

    Charles, can you use a constant defined your way in a CASE statement?

    Alex Holland
    , Apr 10, 2006
    #7
  8. Mike Treseler, Apr 10, 2006
    #8
  9. Alex,

    writes:
    > I thought I would try to work out a way of specifying the constants so
    > that they would grow with abus_width so that if we ever had to do this
    > again it would automatically work e.g.
    >
    > library ieee;
    > use ieee.std_logic_arith.all;
    >
    > constant abus_width : natural := 7;
    > constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) :=
    > conv_std_logic_vector(16#01#,abus_width);
    > constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) :=
    > conv_std_logic_vector(16#02#,abus_width);


    You can either extend your registers widths to a multiple of 4 and use
    the VHDL'93 syntax. In the case-statement you would have to extend the
    case-expression to the same width and be done. Chances are that
    Synthesis will strip the unused bits anyway.

    Or, as someone else already noted, you could use if-elsif*-else
    chains. Synthesis tools are also pretty good at generating the
    expected logic in cases like this.

    Alternatively you could assign the registers like this

    constant REGISTER_A : std_logic_vector(abus_width-1 downto 0)
    := (0 => '1', others => '0');
    constant REGISTER_B : std_logic_vector(abus_width-1 downto 0)
    := (1 => '1', others => '0');

    (Actually I am not absolutely sure that this last assignment works as
    expected. You'd have to try that yourself.)

    > But it IS locally static isnt it? It's a constant, it's in a package,
    > that package is referenced...


    Not quite. Locally static expressions must be fixed at compile
    time. Functions, such as `conv_std_logic_vector', defined in package
    bodies are not. You could compile a different package body for
    std_logic_arith with completely different function definitions and be
    screwed.

    Best regards,
    Marcus
    Marcus Harnisch, Apr 11, 2006
    #9
  10. Guest

    Hi Marcus,

    Thanks for the reply, good suggestion for your alternative

    > > But it IS locally static isnt it? It's a constant, it's in a package,
    > > that package is referenced...

    >
    > Not quite. Locally static expressions must be fixed at compile
    > time. Functions, such as `conv_std_logic_vector', defined in package
    > bodies are not. You could compile a different package body for
    > std_logic_arith with completely different function definitions and be
    > screwed.


    Ah, yes now I understand. It ISNT the case statement which needs to
    resolve at compile time it's the WHEN operator. That is why I can
    define my constants as naturals and convert my case argument to an
    integer and it compiles fine e.g.

    constant REGISTER_A : natural := 1;
    constant REGISTER_B : natural := 2;

    case conv_integer(unsigned(addr)) is

    when REGISTER_A =>

    when REGISTER_B =>

    when OTHERS =>

    end case;

    Makes sense now, dont like it, but it makes sense.

    Alex
    , Apr 11, 2006
    #10
  11. Andy Guest

    The best approach I have found for address decoding registers on
    adjacent addresses is to define the registers as an array of SLV (or
    integer or unsigned or whatever), then convert the address to integer,
    and index the array with that. No case or if/elsif statements
    required. Pad the array to hold an integral power of two registers, and
    use mod on the index to ensure legal indices (synthesis will optimize
    out the unused registers). As an added bonus, if the synthesis tool
    can determine that your design only accesses one or two registers in
    any clock period, it can infer single or dual port ram for them.

    Whenever I see a long case or if/elsif tree with numeric targets, I
    think "can I use an array and/or loop here?"

    Hope this helps,

    Andy
    Andy, Apr 13, 2006
    #11
    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. Simone Winkler

    conversion: natural -> time

    Simone Winkler, Apr 1, 2004, in forum: VHDL
    Replies:
    1
    Views:
    1,817
    Jim Lewis
    Apr 1, 2004
  2. badwolf500
    Replies:
    0
    Views:
    1,018
    badwolf500
    Aug 14, 2006
  3. Sebastien Bourdeauducq

    Adding a NATURAL and a STD_LOGIC_VECTOR

    Sebastien Bourdeauducq, Jun 8, 2007, in forum: VHDL
    Replies:
    3
    Views:
    1,987
    Sebastien Bourdeauducq
    Jun 8, 2007
  4. Thomas Rouam
    Replies:
    6
    Views:
    1,116
  5. aleksa
    Replies:
    9
    Views:
    8,669
    Mike Treseler
    Jan 22, 2009
Loading...

Share This Page