Discrete range in CASE

H

hssig

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
 
J

Jonathan Bromley

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
 
A

Andy

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

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
 
H

hssig

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
 
M

Mike Treseler

hssig said:
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
 
J

Jonathan Bromley

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 :)
 
J

JimLewis

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
 
H

HT-Lab

JimLewis said:
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.

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
 
H

hssig

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
 
M

Mike Treseler

hssig said:
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
 
H

hssig

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
 
M

Mike Treseler

hssig said:
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
 
J

jr

hssig a écrit :
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.

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.
 
H

hssig

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
 
H

HT-Lab

hssig said:
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 ?

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
 
H

hssig

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top