Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constant conversion (natural to std_logic_vector)

1,254 views
Skip to first unread message

a1_noc...@hotmail.com

unread,
Apr 10, 2006, 8:15:23 AM4/10/06
to
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

a1_noc...@hotmail.com

unread,
Apr 10, 2006, 8:28:26 AM4/10/06
to
I cannot use VHDL 93's HEX literal ( X'"AA" ) because my bus is not a
multiple of 4-bits wide.

Mike Treseler

unread,
Apr 10, 2006, 10:16:39 AM4/10/06
to
a1_noc...@hotmail.com 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

a1_noc...@hotmail.com

unread,
Apr 10, 2006, 11:37:57 AM4/10/06
to
> 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

Charles, NG

unread,
Apr 10, 2006, 12:10:19 PM4/10/06
to
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

a1_noc...@hotmail.com

unread,
Apr 10, 2006, 12:22:42 PM4/10/06
to
I am using subtypes in my code (not in my example) it doesnt help.

a1_noc...@hotmail.com

unread,
Apr 10, 2006, 12:34:36 PM4/10/06
to
>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

Mike Treseler

unread,
Apr 10, 2006, 12:42:09 PM4/10/06
to
a1_noc...@hotmail.com wrote:
>>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.

It probably should, but it doesn't and this is a FAQ.

-- Mike Treseler

Marcus Harnisch

unread,
Apr 11, 2006, 7:42:34 AM4/11/06
to
Alex,

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

a1_noc...@hotmail.com

unread,
Apr 11, 2006, 11:58:36 AM4/11/06
to
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

Andy

unread,
Apr 13, 2006, 6:29:41 PM4/13/06
to
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

0 new messages