синтез динамического мультиплексора по байтам std_logic_vector

У меня есть FIFO, размер которого определяется в соответствии с параметром в пакете:

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

У меня также есть 4-битный вектор (numOfBytes), указывающий, сколько байтов находится в FIFO в любой момент времени (до 8).
Я хочу, чтобы данные (один байт) из FIFO определялись в соответствии с numOfBytes. signal:
Do <= fifo(to_integer(unsigned(numOfBytes)*8 -1 downto to_integer(unsigned(numOfBytes)*8 -8) when numOfBytes /= x"0" else (others => '0');
при моделировании это работает хорошо, однако, когда я пытаюсь его синтезировать (используя Synopsys DC), я получаю ошибку уточнения при связывании проекта, говоря: «Требуется постоянное значение (ELAB-922)».

Код ELAB означает: «Это сообщение об ошибке возникает из-за того, что выражение в указанной строке вашего описания RTL не оценивается как постоянное значение, как того требует язык».

Как еще я могу сделать выходной мультиплексор, чтобы он подвергался синтезу? если бы не параметр, я бы поменял линию Do на обычный мультиплексор, но он не может работать с параметрами. (Я не могу вызвать fifo (от 63 до 54), когда fifo 4 байта...)

p.s. Сначала я пытался работать с conv_integer, но изменил его на to_integer(unsigned()) из-за ответов, найденных в Интернете.


person user2141046    schedule 02.10.2013    source источник


Ответы (3)


Индексы сигналов, используемые для построения диапазона, должны быть константами времени компиляции, чтобы синтез мог их принять.

Есть два способа решить эту проблему:

1) Измените свой FIFO, чтобы использовать массив. Это стандартный способ объявления любой формы памяти, например 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) Используйте цикл для преобразования переменной в константу. Это распространенный способ кодирования универсального мультиплексора.

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;

Я бы рекомендовал первый подход для больших FIFO на основе памяти, а второй — для меньших, основанных на регистрах.

person zennehoy    schedule 02.10.2013
comment
кстати, такая проблема распространенная? Вижу, что получил почти сразу два ответа и практически одинаковых. - person user2141046; 02.10.2013
comment
Zennehoy, второй ответ решил это очень хорошо. и это почти не потребовало от меня изменения моего дизайна! теперь у меня есть список соединений :) Я не понимаю, как получилось, что вам не понадобился to_integer(unsigned(numOfBytes)), почему VHDL принимает такое преобразование? - person user2141046; 02.10.2013
comment
@user2141046 user2141046 В этом прелесть использования unsigned, а не std_logic_vector, когда это возможно. Поскольку известно, что unsigned представляет число, VHDL позволяет напрямую сравнивать его с integer. - person zennehoy; 02.10.2013
comment
@user2141046 user2141046 Кодирование FIFO или другой формы памяти очень распространено в VHDL. То, что вы получили два ответа почти сразу, вероятно, скорее связано с удачей. - person zennehoy; 02.10.2013
comment
@user2141046 user2141046 Тогда вы можете использовать IEEE.std_logic_unsigned, который указывает VHDL рассматривать все std_logic_vector как unsigned. Однако это не одобряется, поскольку оно нестандартно и подвержено ошибкам. Гораздо лучше использовать unsigned напрямую. - person zennehoy; 02.10.2013
comment
вы узнаете что-то новое каждый день... спасибо. Я использовал (to_integer(unsigned(numOfBytes)) на всякий случай (не хочу, чтобы меня осуждали :)) - person user2141046; 02.10.2013
comment
Привет ... этот пост довольно старый ... почему ваше второе решение преобразует переменную в константу? - person user8469759; 09.10.2015
comment
@Lukkio Извините за задержку, меня не было в городе. Правда, формулировка немного надуманная. Что происходит во втором решении, так это то, что вы создаете оборудование для всех возможных диапазонов параллельно (один диапазон на итерацию), а затем добавляете мультиплексор для выбора интересующего вас диапазона на основе значения numOfBytes. В операторе if i = numOfBytes-1, поэтому i эффективно numOfBytes преобразуется в константу. - person zennehoy; 26.10.2015

Если FIFO создается с несколькими байтами, а не объединяется в один и тот же std_logic_vector, Synopsys DC может справиться с этим. Код может выглядеть так:

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;
person Morten Zilmer    schedule 02.10.2013
comment
не пробовал ваше решение из-за решения Zennhoy - я закрыл исходный код и хотел минимизировать изменения в моем коде. объявление массива и соответствующая работа были бы серьезным изменением, которое я просто не хотел делать на текущем этапе проектирования. - person user2141046; 02.10.2013

Если вам не нужен динамический размер во время выполнения для FIFO, используйте generic для своей сущности.

Если вам действительно нужен FIFO с динамическим размером, вам придется использовать цикл в процессе, как сказал кто-то другой. Но будьте очень осторожны с тем, как вы используете такой FIFO, так как если вы измените его размер, пока кто-то читает или пишет, могут произойти плохие вещи!

person Martin Thompson    schedule 04.10.2013