Out of Range - simulation vs. synthesis

A

ALuPin

Hi all,

I have the following piece of VHDL code which
is not accepted in simulation but in synthesis:

constant cCLUSTER : integer := 4;
type cluster_type is array(cCLUSTER-1 downto 0) of std_logic_vector(1
downto 0);
signal ls_addr_cluster : cluster_type;

process(Clk)
begin
if rising_edge(Clk) then

if TxValid='1' then

case Addr is
when "00" => if cCLUSTER >= 1 then
ls_addr_cluster(0) <= Addr;
end if;
when "01" => if cCLUSTER >=2 then
ls_addr_cluster(1) <= Addr;
end if;
when "10" => if cCLUSTER >=3 then
ls_addr_cluster(2) <= Addr;
end if;
when "11" => if cCLUSTER >=4 then
ls_addr_cluster(3) <= Addr;
end if;
end case;

end if;
end if;
end process;


When using cCLUSTER=3 the simulation is aborted with the error
message: "Index value 3 is out of range 2 downto 0".
The if-condition seems not to keep Modelsim from checking
the assignment "ls_addr_cluster(3) <= Addr;" although
cCLUSTER is a constant definition. Synthesis does not complain ...
How can I solve that problem ?

Thank you for your opinion.

Rgds
Andre
 
A

Andy

Hi all,

I have the following piece of VHDL code which
is not accepted in simulation but in synthesis:

constant cCLUSTER : integer := 4;
type cluster_type is array(cCLUSTER-1 downto 0) of std_logic_vector(1
downto 0);
signal ls_addr_cluster : cluster_type;

process(Clk)
begin
if rising_edge(Clk) then

if TxValid='1' then

case Addr is
when "00" => if cCLUSTER >= 1 then
ls_addr_cluster(0) <= Addr;
end if;
when "01" => if cCLUSTER >=2 then
ls_addr_cluster(1) <= Addr;
end if;
when "10" => if cCLUSTER >=3 then
ls_addr_cluster(2) <= Addr;
end if;
when "11" => if cCLUSTER >=4 then
ls_addr_cluster(3) <= Addr;
end if;
end case;

end if;
end if;
end process;

When using cCLUSTER=3 the simulation is aborted with the error
message: "Index value 3 is out of range 2 downto 0".
The if-condition seems not to keep Modelsim from checking
the assignment "ls_addr_cluster(3) <= Addr;" although
cCLUSTER is a constant definition. Synthesis does not complain ...
How can I solve that problem ?

Thank you for your opinion.

Rgds
Andre

It looks like your trying to store Addr in ls_addr_cluster, but
limiting the size of ls_addr_cluster to below what might appear in
Addr? This is a common issue in address decoding.

Instead of a case statement, use a for-loop indexed on the range of
the array:

for i in ls_addr_cluster'range loop
if i = unsigned(Addr) then
ls_addr_cluster(i) <= Addr;
exit; -- optional, speeds up sim
end if;
end loop;

Whenever the size of an array is variable, it is almost never a good
idea to use a case statement to access elements of it.

Loop statements are unrolled for synthesis, so this becomes a sequence
of if statements (the exit statements turns it into one big if-elsif-
elsif... statement)

The exit statement in this example will have no effect on synthesis
(the if conditions are mutually exclusive anyway), but it terminates
the loop in simulation once a match is found.

Andy
 
A

ALuPin

Hi Andy,

some additional question. How can I describe it as a loop when
using the following addressing:

Addr: IN std_logic_vector(3 DOWNTO 0);
....
constant cCLUSTER : integer := 4;
type cluster_type is array(cCLUSTER-1 downto 0) of std_logic_vector(1
downto 0);
signal ls_addr_cluster : cluster_type;


process(Clk)
begin
if rising_edge(Clk) then


if TxValid='1' then


case Addr(3 DOWNTO 2) is
when "00" => if cCLUSTER >= 1 then
ls_addr_cluster(0) <= Addr(1
DOWNTO 0);
end if;
when "01" => if cCLUSTER >=2 then
ls_addr_cluster(1) <=
Addr(1 DOWNTO 0);
end if;
when "10" => if cCLUSTER >=3 then
ls_addr_cluster(2) <= Addr(1
DOWNTO 0);
end if;
when "11" => if cCLUSTER >=4 then
ls_addr_cluster(3) <= Addr(1
DOWNTO 0);
end if;
end case;


end if;
end if;
end process;


Rgds
Andre
 
P

Pieter Hulshoff

USE ieee.numeric_std.ALL;

IF cCLUSTER-1 >= to_integer( unsigned( Addr(3 DOWNTO 2) ) ) THEN
ls_addr_cluster(to_integer( unsigned( Addr(3 DOWNTO 2) ) )) <= Addr(1 DOWNTO 0);
END IF;

Kind regards,

Pieter Hulshoff
 
D

Dave Pollum

Hi Andy,

some additional question. How can I describe it as a loop when
using the following addressing:

Addr: IN std_logic_vector(3 DOWNTO 0);
...
constant cCLUSTER : integer := 4;
type cluster_type is array(cCLUSTER-1 downto 0) of std_logic_vector(1
downto 0);
signal ls_addr_cluster : cluster_type;

process(Clk)
begin
if rising_edge(Clk) then

if TxValid='1' then

case Addr(3 DOWNTO 2) is
when "00" => if cCLUSTER >= 1 then
ls_addr_cluster(0) <= Addr(1
DOWNTO 0);
end if;
when "01" => if cCLUSTER >=2 then
ls_addr_cluster(1) <=
Addr(1 DOWNTO 0);
end if;
when "10" => if cCLUSTER >=3 then
ls_addr_cluster(2) <= Addr(1
DOWNTO 0);
end if;
when "11" => if cCLUSTER >=4 then
ls_addr_cluster(3) <= Addr(1
DOWNTO 0);
end if;
end case;

end if;
end if;
end process;

Rgds
Andre

You declared "cCLUSTER" to be a constant with a value of 4. Then in
your case statements you have
when "01" => if cCLUSTER >= 2 then...

But AFAIK that's the same as when "01" => if 4 >= 2 then...

So I'm confused. What are you trying to do???
-Dave Pollum
 
A

ALuPin

Hi Pieter,
thank you for your proposal.

@ Dave
Generic Multiplexer of two-dimensional arrays

Rgds
Andre
 
A

Andy

Hi Andy,

some additional question. How can I describe it as a loop when
using the following addressing:

Addr: IN std_logic_vector(3 DOWNTO 0);
...
constant cCLUSTER : integer := 4;
type cluster_type is array(cCLUSTER-1 downto 0) of std_logic_vector(1
downto 0);
signal ls_addr_cluster : cluster_type;

process(Clk)
begin
if rising_edge(Clk) then

if TxValid='1' then

case Addr(3 DOWNTO 2) is
when "00" => if cCLUSTER >= 1 then
ls_addr_cluster(0) <= Addr(1
DOWNTO 0);
end if;
when "01" => if cCLUSTER >=2 then
ls_addr_cluster(1) <=
Addr(1 DOWNTO 0);
end if;
when "10" => if cCLUSTER >=3 then
ls_addr_cluster(2) <= Addr(1
DOWNTO 0);
end if;
when "11" => if cCLUSTER >=4 then
ls_addr_cluster(3) <= Addr(1
DOWNTO 0);
end if;
end case;

end if;
end if;
end process;

Rgds
Andre

If you are asking what difference it makes if the addressed space is
indicated by Addr(4 downto 0), it doesn't. Have the loop iterate on
the elements of the array, and check to see if the value of the array
(loop) index equals the value of Addr (independent of length of Addr).
If it does, assign the element of the array, indexed with the loop
index, not Addr.

If you are asking how to control the width of Addr based on cCLUSTER,
then you need to pass cCluster in as a generic on the entity, and
specify the Addr port range in terms of that generic.

If, on the other hand, you are wanting to declare cCluster based on
the width of the Addr port, then you can use the Addr'length attribute
and exponentiation to determine the value of cCluster.

Andy
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top