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

Discrete range in CASE

569 views
Skip to first unread message

hssig

unread,
Jan 4, 2010, 6:03:25 AM1/4/10
to
Hi,

I have the following VHDL case structure:

signal numa : unsigned(2 downto 0);

constant cA : unsigned(2 downto 0) := "000";
constant cB : unsigned(2 downto 0) := "001";
constant cC : unsigned(2 downto 0) := "100";

process(rstn, clk)
begin
if rstn='0' then
numa <= "000";

elsif rising_edge(clk) then
...

case to_integer(numa) is
when to_integer(cA) => ...
when to_integer(cB) to to_integer(cC) => ...
when others => ...
end case;

end if;

end process;


When trying to insert a (Lattice) Reveal core I get the following
error message:

"ERROR: case choice must be a locally static expression (VHDL-1438)"

How can I make use of the discrete range choice without violating the
static expression rule ?
Thank you for your opinion.


Cheers,
hssig

Jonathan Bromley

unread,
Jan 4, 2010, 6:15:44 AM1/4/10
to
On Mon, 4 Jan 2010 03:03:25 -0800 (PST), hssig wrote:

>signal numa : unsigned(2 downto 0);
>
>constant cA : unsigned(2 downto 0) := "000";
>constant cB : unsigned(2 downto 0) := "001";
>constant cC : unsigned(2 downto 0) := "100";
>
>process(rstn, clk)
>begin
> if rstn='0' then
> numa <= "000";
>
> elsif rising_edge(clk) then
> ...
>
> case to_integer(numa) is
> when to_integer(cA) => ...
> when to_integer(cB) to to_integer(cC) => ...
> when others => ...
> end case;
>
> end if;
>
>end process;

>"ERROR: case choice must be a locally static expression (VHDL-1438)"


>
>How can I make use of the discrete range choice without violating the
>static expression rule ?

"Locally static" in VHDL is a very aggressive restriction and
there's not much you can do about it. Function call in the
case choice is a no-no, sorry.

I suggest you re-cast your code so that the original constants
are integers:

--- Useful bits and pieces
subtype u3 is unsigned(2 downto 0);
subtype i3 is integer range 0 to (2**u3'length - 1);
function to_u3(n: i3) return u3 is begin
return to_unsigned(n, u3'length);
end;

--- Your constants as proper integers
constant nA : i3 := 0;
constant nB : i3 := 1;
constant nC : i3 := 4;

--- Your unsigned signals and constants,
--- derived from the original integers
signal numa: u3;
constant cA: u3 := to_u3(nA);
constant cB: u3 := to_u3(nB);
constant cC: u3 := to_u3(nC);

--- Now the case statement should be OK,
--- as well as being easier to read:
case to_integer(numa) is
when nA => ...
when nB to nC => ...


when others => ...
end case;

Hope this helps
--
Jonathan Bromley

Brian Drummond

unread,
Jan 4, 2010, 7:43:42 AM1/4/10
to
On Mon, 4 Jan 2010 03:03:25 -0800 (PST), hssig <hs...@gmx.net> wrote:

>Hi,
>
>I have the following VHDL case structure:
>
>signal numa : unsigned(2 downto 0);

>constant cA : unsigned(2 downto 0) := "000";
>constant cB : unsigned(2 downto 0) := "001";
>constant cC : unsigned(2 downto 0) := "100";
>

...

> case to_integer(numa) is
> when to_integer(cA) => ...
> when to_integer(cB) to to_integer(cC) => ...
> when others => ...
> end case;

>"ERROR: case choice must be a locally static expression (VHDL-1438)"


>
>How can I make use of the discrete range choice without violating the
>static expression rule ?

The number of type conversions here suggest you are fighting the type system
instead of using it... that's often a hint that the design can be improved.

Assuming you need to write the constant values in binary for clarity, one way is
to keep them in integer form, and write

subtype numaRange is
constant cA : natural range 0 to 7 := 2#000#;
subtype BtoC is natural range 2#
and
case to_integer(numa) is
when cA => ...
when BtoC => ...

Much less clutter. And it avoids functions in the case arm branches, which is
the likely cause of the error...

The meaning of "to_integer" is not locally defined; since it is a function
declared somewhere else, it may not even have been written yet!

Thinking hardware, a case statement typically generates a multiplexer.

So while a function call in the case variable is allowed (you can select a
different multiplexer input depending on external conditions), a function call
in a case arm would change the shape of the hardware implementation if the
function evaluated differently ... it's not surprising that isn't allowed.

The fact that it is a standard function from a standard library is known to you,
but not to me, or the compiler. From the code you posted (no use clauses) I
can't tell if you are using the "real" unsigned, (from numeric_std), or an
impostor (from the Synopsis libraries) or even your own implementation.

VHDL doesn't cheat and impose special case meanings on your code - even at the
level of assuming '1' = true and '0' = false. That decision is (IMO, correctly)
kept outside the language, in the libraries. So you could implement negative
logic systems simply by replacing std_logic_1164 and numeric_std with their
negative logit equivalents. (If ECL ever comes back into fashion, this could be
a big win for VHDL over that other language, but I'm not holding my breath!)

You do have to be explicit about what you mean - in your case, simply using
integer ranges will do. IMO the result is cleaner - and easier for the next guy
to read and understand..

- Brian

Andy

unread,
Jan 4, 2010, 10:20:57 AM1/4/10
to
On Jan 4, 6:43 am, Brian Drummond <brian_drumm...@btconnect.com>
wrote:

IINM, the reason for the locally static restriction on choice
expressions is because the case statement choices must be evaluated at
analysis time (before elaboration) to determine that they are complete
and mutually exclusive. Non-locally static function calls cannot be
evaluated at analysis time, and therefore the set of choices cannot be
evaluated for completeness and mutual exclusivity.

Andy

hssig

unread,
Jan 4, 2010, 10:58:54 AM1/4/10
to
Hi,

thank you for your answers.

@Brian:
I use "std_logic_arith" and "numeric_std".

The constant definition "constant cA : natural range 0 to 7 :=
2#000#;"
is clear to me. But how do you use the proposed subtypes

subtype numaRange is


subtype BtoC is natural range 2#

? What is their purpose ?


Cheers,
hssig

hssig

unread,
Jan 4, 2010, 10:59:51 AM1/4/10
to
Sorry, I mean:
"std_logic_1164" and "numeric_std"

Cheers,
hssig

Brian Drummond

unread,
Jan 4, 2010, 7:18:34 PM1/4/10
to

Sorry, the subtype got garbled in editing; I was doing something else but
decided to shorten the post.

Jonathan answered it better anyway, but to borrow from his post:
subtype u3 is unsigned(2 downto 0); -- was "numaRange" in my post


constant cB: u3 := to_u3(nB);
constant cC: u3 := to_u3(nC);

case to_integer(numa) is


when nA => ...
when nB to nC => ...

"nB to nC" here is a range; this is essentially a subtype.

So it ought to be possible to write:
subtype BtoC is natural range cB to cC;
case to_integer(numa) is
when nA => ...
when BtoC => ...
In this example it doesn't add clarity.

But if "numa" stands for "Non-Uniform Memory Architecture", then (with suitable
constant and subtype names) you can write
case (numa_address) is
when local => ...
when close => ...
when distant => ...
when others => -- garbled address
and make the intent clear.

And when you extend the design, hopefully you only need to change the subtype
and maybe constant declarations:
subtype u3 is unsigned(4 downto 0);
-- oops! hence in my opinion: name it after its purpose, not its size!
subtype numaRange is unsigned(4 downto 0);
and the work is done.

Or only 99% of it; there's usually one explicit "std_logic(2 downto 0)" on a top
level port that slipped through somehow...

- Brian

Mike Treseler

unread,
Jan 4, 2010, 10:46:05 PM1/4/10
to
hssig wrote:

> How can I make use of the discrete range choice without violating the
> static expression rule ?

I like to use cases of enumerated types, but ...

If I couldn't change your declarations, I would use
if, elsif, elsif, ..., else
You will get no such errors,
the conditions can be whatever you like,
and it won't cost any gates unless you really need them.

-- Mike Treseler

Jonathan Bromley

unread,
Jan 5, 2010, 4:12:50 AM1/5/10
to
On Tue, 05 Jan 2010 00:18:34 +0000, Brian Drummond wrote:

>And when you extend the design, hopefully you only need to change the subtype
>and maybe constant declarations:
> subtype u3 is unsigned(4 downto 0);
> -- oops! hence in my opinion: name it after its purpose, not its size!
> subtype numaRange is unsigned(4 downto 0);

Yes, of course Brian is completely right about this -
unless, as occasionally happens, the size is an essential
part of the nature of the thing. Apologies for the
illiterate programming. [*]

[*] If Brian can use Knuth as a stick to beat me with,
there's no reason why I shouldn't do so myself :-)
--
Jonathan Bromley

hssig

unread,
Jan 6, 2010, 9:19:55 AM1/6/10
to
Thank you.

Cheers,
hssig

JimLewis

unread,
Jan 6, 2010, 8:14:26 PM1/6/10
to
Hssig,
In VHDL-2008, array types and functions in std_logic_1164 and
numeric_std became locally static.

Does lattice have a language switch for VHDL-2008? If not submit the
issue as a bug since it is supported in the current revision of the
language - approved by IEEE in September 2008 and approved by
Accellera as a trial standard in July 2006, so vendors really don't
have an excuse for not having implemented it at this point.

Best,
Jim
SynthWorks

HT-Lab

unread,
Jan 8, 2010, 4:58:48 AM1/8/10
to

"JimLewis" <J...@SynthWorks.com> wrote in message
news:c45d64f3-3844-4e06...@j19g2000yqk.googlegroups.com...

Unfortunately the excuse they gave me is that not many users are asking for it!
I find this very frustrating since there are some very basic language
enhancements which can make your code a lot cleaner, examples are:

1) Reading output ports
2) Case statement with don't care support
3) Expressions in port maps
4) Process(all)
5) Generic on packages

So have a look at the new language features and then send an email to your
vendor, it shouldn't take long!

Hans
www.ht-lab.com


>
> Best,
> Jim
> SynthWorks


hssig

unread,
Jan 16, 2010, 4:36:20 AM1/16/10
to
Hi Jim,

when compiling such case description including the "to_integer"
function in the when-tree(s)
"when to_integer(cA) => ..."

Modelsim PE 6.5d (Compile Options 2008) also shows the warning: "Case
choice must be a locally static expression."

So if Mentor did implement the VHDL-2008 feature correctly there would
be no warning ?

Cheers,
hssig

Mike Treseler

unread,
Jan 16, 2010, 2:31:34 PM1/16/10
to
hssig wrote:

> So if Mentor did implement the VHDL-2008 feature correctly there would
> be no warning ?

I don't know, and it doesn't really matter in this moment.
If we put the function in the case clause, like this:

case to_integer(unsigned(in_vec)) is

everything just works.

-- Mike

____________________________________________________
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity case_of_function is
port (
in_vec : in std_logic_vector(7 downto 0) := x"06");
end case_of_function;

architecture sim of case_of_function is
begin
case_test : process is
constant vec_len_c : natural := in_vec'length;
begin
case to_integer(unsigned(in_vec)) is
when 5|6 => report "it's a 5 or 6";
when 7 => report "it's a 7";
when others => report "it's not 5-7";
end case;
wait;
end process case_test;
end sim;
-- _______________________________
-- Sample run:
-- vsim -c case_of_function

-- VSIM 1> run
-- ** Note: it's a 5 or 6
-- Time: 0 ns Iteration: 0 Instance: /case_of_function

hssig

unread,
Jan 17, 2010, 2:57:21 PM1/17/10
to
>I don't know, and it doesn't really matter in this moment.

Yes, it does matter because I am trying to find out whether it is
allowed to put the function "to_integer"
in the when trees of a case statement.


Cheers,
hssig

Mike Treseler

unread,
Jan 17, 2010, 3:21:12 PM1/17/10
to
hssig wrote:

> Yes, it does matter because I am trying to find out whether it is
> allowed to put the function "to_integer"
> in the when trees of a case statement.

All I can tell you is that both Modelsim and Quartus disapprove.
This makes the reason irrelevant to me.
Besides, cases of integers or enums are easier for me to read.

So reread this thread.
Others have spent time given you rational reasons for the restriction.
Good luck.

-- Mike Treseler

jr

unread,
Jan 17, 2010, 3:25:12 PM1/17/10
to
hssig a �crit :

Nope. You can't have a non static computed value in a choice. The
compiler would have no means to determine if the case statement covers
each choice once and only once (think that the body of the function
might be not compiled yet).

You can use if/elsif instead.

--
jr
Particulier non cumulable

hssig

unread,
Jan 18, 2010, 2:30:05 AM1/18/10
to
>Others have spent time given you rational reasons for the restriction.

Yes, I agree. But at this point we are trying to find out if these
restrictions are still applicable for VHDL-2008 and whether M, X, A, L
or whatever vendors are implementing functions in case statements
the way the new standard is telling them.

>All I can tell you is that both Modelsim and Quartus disapprove.
>This makes the reason irrelevant to me.

But that does not prove that they are implementing it correctly (or at
all), doesn't it ?

Cheers,
hssig


HT-Lab

unread,
Jan 18, 2010, 3:28:22 AM1/18/10
to

"hssig" <hs...@gmx.net> wrote in message
news:693daa5c-06aa-43e0...@c29g2000yqd.googlegroups.com...

Modelsim's VHDL2008 support is very limited, just look under
help->technotes->vhdl2008 to see what is currently supported (in 6.6),

Hans
www.ht-lab.com

>
> Cheers,
> hssig
>


hssig

unread,
Jan 18, 2010, 7:51:13 AM1/18/10
to
Hi Jim,
to get to the point: Before asking Lattice and Mentor I want to be
sure whether the following code should be warning-free or not
when compiling with VHDL-2008 option:


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity function_in_case is
port( Clk : in std_logic;
Ad : in std_logic_vector(7 downto 0);
Sig : out std_logic_vector(1 downto 0)
);
end function_in_case;

architecture beh of function_in_case is

constant A : unsigned(7 downto 0) := x"00";
constant B : unsigned(7 downto 0) := x"01";
constant C : unsigned(7 downto 0) := x"EE";

signal addr : unsigned(7 downto 0);

begin

addr <= unsigned(Ad);

process(Clk)
begin
if rising_edge(Clk) then
case to_integer(addr) is
when to_integer(A) =>
Sig <= "00";
when to_integer(B) to to_integer(C) =>
Sig <= "01";
when others =>
Sig <= "11";

end case;
end if;
end process;

end beh;

Cheers,
hssig

0 new messages