cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
mustishesap
Contributor
Contributor
1,285 Views
Registered: ‎08-22-2019

Range Expression Could not be Resolved to a Constant - Synthesis Error - VHDL

Hi,

I am trying to perform some Dynamic Assignments in VHDL. My code works in simulation but in synthesis Vivado returns with "range expression could not be resolved to a constant." error.

My code is not very short but here is the particular place where the error occurs:

 

type index_type is array (0 to 7) of INTEGER;
signal index_array : index_type := (0, 7, 15, 23, 31, 39, 47, 55);
signal byte_index : INTEGER := 6;

signal interval_reg : STD_LOGIC_VECTOR(63 downto 0);

signal datain: STD_LOGIC_VECTOR(63 downto 0);

process(clk)
begin
if rising_edge(clk) then

interval_reg(index_array(byte_index) downto 0) <= datain(63 downto 63 - index_array(byte_index));
end if;
end process;

 

byte_index is controlled in another process. I've searched it and found that allocations such as (6*8  + 5 -1 downto 0) is too complex. That's why I put every value that I need into arrays and called them with an index. Is it also too complex? Should I simplify it or is there another problem?

Thanks for your help.

0 Kudos
10 Replies
drjohnsmith
Teacher
Teacher
1,270 Views
Registered: ‎07-09-2009

Your making hardware ,
how can the hardware change size depending upon another process ?

All hardware size needs to be defined at synthesis time, so if byte_index is not a constant at synthesis , then you will fail.

So double check at synthesis that byte_index is a constant

One way is to put byte_index as a constant into a package , referenced by any process that needs the constant.

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
mustishesap
Contributor
Contributor
1,257 Views
Registered: ‎08-22-2019

Actually my size does not depend on anything. It is always 64 bits. But sometimes I want to transfer, for instance, 40 bit of a register and sometimes 50 bit of a register. And this range changes according to my logic. I think it must be legal.  I can imagine it in my head with some mux circuit. 

https://forums.xilinx.com/t5/Synthesis/range-expression-could-not-be-resolved-to-a-constant/m-p/1067616/highlight/false#M33904

 

This discussion says that this is a problem for Vivado. 

0 Kudos
mustishesap
Contributor
Contributor
1,223 Views
Registered: ‎08-22-2019

I have written two codes:

 

1

signal byte_index : INTEGER := 4;
signal datain : STD_LOGIC_VECTOR(63 downto 0);
signal dataout : STD_LOGIC_VECTOR(63 downto 0);

process(clk)
begin
if rising_edge(clk) then
dataout(31 downto 0) <= datain((byte_index *8)  - 1 downto 0);


end if;
end process;

 

2)

signal byte_index : INTEGER := 4;
signal datain : STD_LOGIC_VECTOR(63 downto 0);
signal dataout : STD_LOGIC_VECTOR(63 downto 0);

process(clk)
begin
if rising_edge(clk) then

case byte_index is
when 1 =>
dataout(7 downto 0) <= din(7 downto 0);
when 2 =>
dataout(15 downto 0) <= din(15 downto 0);
when 3 =>
dataout(23 downto 0) <= din(23 downto 0);
when 4 =>
dataout(31 downto 0) <= din(31 downto 0);

when others =>

dataout <= (others => '0');

end case;

end if;
end process;

 

First one returns with a synthesis error but the second one works properly. I does not make any sense to me, I think both are the same. But looks like I am going to arrange my code according to the second method. I am still open to different advices though.

0 Kudos
richardhead
Scholar
Scholar
1,209 Views
Registered: ‎08-01-2012

You dont mention what Vivado version you are using?

This kind of construct has been an issue not just in Vivado, it used to be an issue in Quartus too. They generally didnt like variable ranges for slices.

See this AR:

https://www.xilinx.com/support/answers/52302.html

 

Using the case expression is usually the workaround.

0 Kudos
mustishesap
Contributor
Contributor
1,200 Views
Registered: ‎08-22-2019

My version is 2017.3

 

0 Kudos
richardhead
Scholar
Scholar
1,193 Views
Registered: ‎08-01-2012

Have you tried in a newer version? latest is 2020.1. There were several VHDL 2008 improvements in 2017.4 and each year has got better.

0 Kudos
drjohnsmith
Teacher
Teacher
1,137 Views
Registered: ‎07-09-2009

byte_index is a signal,
A signal can not be fixed at synthesis by the tools, its a signal, they have no idea that you are not going to change it,

Define it as a constant, and it should work.



<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
bitjockey
Adventurer
Adventurer
1,043 Views
Registered: ‎03-21-2011

Your problems are probably two-fold:

as @drjohnsmith points out, you used signal instead of constants for byte_index and index_array;  so synthesis doesn't know they can't change at some future point.  It might be smart enough to see nothing but the default assignment writes them.  Might.

Secondly, yeah, vhdl doesn't like you using dynamic ranges like this for rtl.  Simulation is fine but it's not real hardware.  What you are effectively doing is a byte lane select and a shift down.  There's also the weird case of writing (63 downto 63) to bit (0) only if index == 0?  Is that intended, or did you want to be selecting 1..8 bytes for xfer using a 0..7 byte_index?  As-is you can't do larger than a 56 bit transfer and upper byte of datain is inaccessible. Also, did you intend to try to move the high bytes and shift them down?

if rising_edge(clk) then
    for i in interval_reg'RANGE loop
        if(i/8 <= byte_index)
            interval_reg(i) <= datain(8*(8-byte_index)+i);
        end if;
    end loop;
...

Extra style points: consistent use of underscores, and UPPER for constants.

Update: based on situation number 2) I think you aren't doing bit shifts?  then it's just datain(i) none of the 8-byte_index reversal.  However, a question to ask is what's happening to the high-bits?  You will have stale data there.  You could have the else (of the i/8 <= index) be <= '0' to zero it out.  you could also make it <= '-' to optimize logic and 'infect' your sim with '-' if stale data is ever used, unless stale data is desired.

mustishesap
Contributor
Contributor
1,025 Views
Registered: ‎08-22-2019

Hi, thanks for the detailed answer bitjockey.

First of all, I haven't used constants because my signals change in a different processes. What I am sharing with you is the concept, the entire code is more complex and I can not share it since it is forbidden. I realise there are some weird cases but the code should work fine because my indexes never go in to that weird cases. However, they must be fixed to have a well written code. 

It looks like for loops are the most suitable solution for me. But it doesn't still make sense why I can't use dynamic assignments in a line while I can do it in a loop.

You are right, I am not doing bit shifts. I am doing two distinct assignments. One covers the least significant and the other covers tthe most significant bits. That's why there is no stale data. However, I couldn't understand the last two sentences. What do you mean by saying <= '-' operation?

 

 

0 Kudos
bitjockey
Adventurer
Adventurer
958 Views
Registered: ‎03-21-2011

Synthesis tools don't do well when a range (x downto y) can change at run time.  Too many non-realizable cases.  Where as the for-loop makes each bits behavior depend on its index, but no ranges are involved.

If you aren't bit shifting, and the active bits can be a math function of byte_index, doing the bitwise for-loop is probably the cleanest.  if the math function is a bunch of special cases and not just "> i/8", etc.,  then an 8-entry case statement may be clearer.  Longer code is sometimes more readable, more maintainable code than "clever" code.

The '-' is a "don't care" in std_logic.  In simulation it is one of the 7 std_logic types and usually shows up blue color. It has rules like '-' and '0' is '0'.   But if you use it in a way that it's value would potentially matter-- '-' and '1' is 'X'.   So let's say you previously loaded data out with 0xDEADBEEF on a prior cycle.  Now you come along and only write the low word w/ 0x9999.  Do you really want 0xDEAD9999 at the output?  What if follow on code accidentally uses the stale high bits.  If you set it to 0x----9999 if those high bits ever got used you'd all of a sudden see a whole bunch of 'X' in bright red in your simulation, triggering all of those defensive programming assertions you put in there for error checking (you did that, right?).  But what does '-' mean for synthesis?  To the synthesis it means "user doesn't care so minimize logic".  It will likely do the most efficient laziest thing it can and use the fewest LUTs.   (Sometimes you can also just fill the "stale" bits directly with 'X' as another style choice.  Modern synth will treat 'X' like '-' I believe? But you might give yourself a fright if you see red in the sim waveform.)

Now if you really are trying to "blend" previous din transactions, so that dataout is a mix of multiple write cycles worth of din then don't use the '-' because in that case you do care about each bit still, they just got loaded piecemeal.