VHDL - одновременное добавление большого 2D-массива. Какой синтаксис для этого - PullRequest
0 голосов
/ 05 июля 2018

Я достиг положения в своем проекте, в котором нам нужно значительно увеличить распараллеливание, но у нас есть много ресурсов, чтобы сэкономить в ПЛИС.

Для этого у меня есть тип, определенный как

type LargeByteArray is array(0 to 10000) of std_logic_vector(7 downto 0);

У меня есть два из них, которые я хочу «побайтно» усреднить за как можно меньшее количество операций, а также сдвинуть вправо для деления на два. Так, например, avg (0) должен быть 8-битным стандартным логическим вектором, который является a_in (0) + b_in (0) / 2. avg (1) должен быть a_in (1) + b_in (1) / 2 и так далее. Предположим, на данный момент нам все равно, что два 8-битных числа добавляют к 9-битным. И я хочу быть в состоянии сделать все 10000 операций параллельно.

Я думаю, что мне нужно использовать промежуточный шаг, чтобы иметь возможность сдвигать биты вот так, используя сигнал "inter".

entity Large_adder is
Port ( a_in : LargeByteArray;
       b_in : LargeByteArray;
       avg_out : LargeByteArray);

architecture arch of Large_adder is
    SIGNAL inter : LargeByteArray;
begin

Мой текущий код выглядит примерно так;

inter(0) <= std_logic_vector((unsigned(a_in(0)) + unsigned(b_in(0))));
inter(1) <= std_logic_vector((unsigned(a_in(1)) + unsigned(b_in(1))));

10000 строк позже ...

inter(10000) <= std_logic_vector((unsigned(a_in(10000)) + unsigned(b(10000))));

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

avg_out(0) <= '0' & inter(0)(7 downto 1);
avg_out(1) <= '0' & inter(1)(7 downto 1);

Вплоть до 10000.

Конечно, есть более эффективный способ указать это.

Я пытался

inter <= std_logic_vector((unsigned(a_in) + unsigned(b)));

но я получаю ошибку об обнаруженных '0' соответствующих определениях для оператора <=. </p>

Теперь очевидно, что число может быть уменьшено с 10000 в случае, если этот вопрос выглядит глупо в том, что я пытаюсь достичь, но в целом, как вы пишете операции такого рода элегантно, без строки для каждого элемента моего Типа?

Если бы мне пришлось угадывать, я бы сказал, что мы можем описать оператору "<=", что делать, когда встречаются с типами LargeByteArray. Но я не знаю, как это сделать или где определить это поведение. </p>

Спасибо

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Используйте обычный процесс:

process(a_in, b_in)
  variable tmp: unsigned(8 downto 0);
begin
  for i in a_in'range loop
    tmp := unsigned('0' & a_in(i)) +  unsigned('0' & b_in(i));
    avg_out(i) <= std_logic_vector(tmp(8 downto 1));
  end loop;
end process;

Это выглядит последовательно, но это не так, по причинам семантики VHDL, которые здесь слишком долго объяснять. Ваш синтезатор будет хотеть, чтобы вы хотели.

И, кстати, сумма двух 8-битных чисел без знака представляет собой 9-битное число без знака (причина, по которой переменная tmp объявлена ​​как unsigned(8 downto 0)). А деление на два просто состоит в смещении вправо (если младший значащий бит является самым правым, как это обычно бывает) на одну позицию. Итак, если вы хотите получить 8-битный результат, просто увеличьте свои операнды влево на один бит, добавьте их и отбросьте младший бит результата, как предложено в процессе выше. Если вместо этого вы добавите их без расширения, вы столкнетесь с проблемами переполнения и серьезными неточностями.

0 голосов
/ 05 июля 2018

У вас есть два варианта. Либо цикл для внутри процесса:

  process (a_in, b_in)
  begin
    for I in 0 to 10000 loop
      inter(I) <= std_logic_vector((unsigned(a_in(I)) + unsigned(b_in(I))));
    end loop;
  end process;

  process (inter)
  begin
    for I in 0 to 10000 loop
      c_out(I) <= '0' & inter(I)(7 downto 1);
    end loop;
  end process;

или генерирует цикл вне процесса:

G1: for I in 0 to 10000 generate
  inter(I) <= std_logic_vector((unsigned(a_in(I)) + unsigned(b_in(I))));
end generate;

G2: for I in 0 to 10000 generate
  c_out(I) <= '0' & inter(I)(7 downto 1);
end generate;

https://www.edaplayground.com/x/3hJV

Имитатор выполняет строки внутри цикла for (внутри процесса) последовательно , потому что симуляторы всегда выполняют строки внутри процесса последовательно (но одновременно будут другие процессы и параллельные назначения). Симулятор выполняет строки внутри цикла генерации одновременно, потому что цикл генерации - это языковая конструкция, которая используется для генерации нескольких параллельных объектов. Из-за топологии вашей схемы (все параллельно), оба метода будут вести себя одинаково при моделировании и синтезе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...