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
> 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
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
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
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
It probably should, but it doesn't and this is a FAQ.
-- Mike Treseler
a1_noc...@hotmail.com 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
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
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