Pregunta

I have a FIFO who's size is determined according to a parameter in the package:

signal fifo : std_logic_vector(FIFO_SIZE*8 -1 downto 0);

I also have a 4 bit vector (numOfBytes) saying how many bytes are in the FIFO at any given time (up to 8).
I want the data out (a single byte) from the FIFO to be determined according the numOfBytes signal:
Do <= fifo(to_integer(unsigned(numOfBytes)*8 -1 downto to_integer(unsigned(numOfBytes)*8 -8) when numOfBytes /= x"0" else (others => '0');
when simulating, this works well, however when I try to synthesis it (using Synopsys DC) I get an elaboration error upon linking the design saying "Constant value required (ELAB-922)".

The ELAB code means "This error message occurs because an expression in the indicated line of your RTL description does not evaluate to a constant value, as required by the language."

How else can I make the output mux so it will undergo synthesis? if not for the parameter i'd change the Do line to a regular mux, but it can't work with the parameters. (I can't call fifo(63 downto 54) when fifo is 4 byte...)

p.s. I tried working with conv_integer in the beginning, but changed to to_integer(unsigned())due to answers found on the web.

¿Fue útil?

Solución

Signal indexes used to construct a range have to be compile-time constants for synthesis to accept them.

There are two ways to solve this problem:

1) Change your FIFO to use an array. This is the standard way of declaring any form of memory, such as a FIFO.

type fifo_type is array(0 to FIFO_SIZE-1) of std_logic_vector(8-1 downto 0);
signal fifo : fifo_type;
...
Do <= fifo(to_integer(unsigned(numOfBytes))-1) when(numOfBytes/=0) else (others=>'0');

2) Use a loop to convert the variable into a constant. This is a common way to code a generic mux.

Do <= (others=>'0');
for i in 0 to FIFO_SIZE-1 loop
    if(numOfBytes=i+1) then
        Do <= fifo((i+1)*8-1 downto i*8);
    end if;
end loop;

I would recommend the first approach for larger, memory-based FIFOs, and the second for smaller, register-based ones.

Otros consejos

If the FIFO created with a number of bytes, instead of combining it into the same std_logic_vector then Synopsys DC may be able to handle it. Code could look like:

library ieee;
use ieee.numeric_std.all;

architecture syn of mdl is

  ... Declaration of FIFO_SIZE natural constant

  type fifo_t is array(natural range <>) of std_logic_vector(7 downto 0);
  signal fifo : fifo_t(FIFO_SIZE - 1 downto 0);

begin

  ... Handling FIFO insert and remove

  Do <= fifo(to_integer(unsigned(numOfBytes))) when numOfBytes /= x"0" else (others => '0');

end architecture;

If you don't need a runtime-dynamic size to the FIFO, use a generic on your entity.

If you truly need a dynamic sized FIFO, you'll have to use a loop in a process as someone else said. But be very careful how you use such a FIFO, as if you change the size of it while someone is reading or writing, bad things may happen!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top