2016-06-02 2 views
0

Я пытаюсь сделать 8 бит множителя массива в VHDL, я использую стандартную архитектуру множителя массива, чтобы сделать это, у меня есть файл BDF, получающий A (множитель) и B (множитель), и в этом файле BDF есть блок с именем «сумматор», который делает суммы из продуктов A и B. У меня возникают проблемы с суммарным выходом, что показывает гораздо меньшее число из правильного стоимость. enter image description here8 бит Множитель массивов VHDL (выход неправильный)

Изображение, приведенное выше, является моим основным BDF.

enter image description here

Изображение выше показывает де соединения от and_arrays на сумматор.

код Adder:

LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL; 
USE IEEE.std_logic_unsigned.ALL; 
use IEEE.std_logic_arith.ALL; 
use IEEE.numeric_std.ALL; 

ENTITY adder IS 
    PORT (i_IN0 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN1 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN2 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN3 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN4 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN5 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN6 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_IN7 : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     o_Q  : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); 
     o_COUT : OUT STD_LOGIC);-- data output 
END adder; 

architecture arch1 of adder is 
begin 
    process(i_IN0, i_IN1, i_IN2, i_IN3, i_IN4, i_IN5, i_IN6, i_IN7) 
     variable soma:std_logic_vector(14 downto 0); 
     variable aux0:std_logic_vector(14 downto 0); 
     variable aux1:std_logic_vector(14 downto 0); 
     variable aux2:std_logic_vector(14 downto 0); 
     variable aux3:std_logic_vector(14 downto 0); 
     variable aux4:std_logic_vector(14 downto 0); 
     variable aux5:std_logic_vector(14 downto 0); 
     variable aux6:std_logic_vector(14 downto 0); 
     variable aux7:std_logic_vector(14 downto 0); 
     variable c:std_logic; -- carry in 
     BEGIN 
     aux0(7 downto 0) := i_IN0; aux0(14 downto 8) := "0000000"; -- here i'm trying to shift the 8 nbit input value 
     aux1(0) := '0'; aux1(8 downto 1) := i_IN1; aux1(14 downto 9) := "000000"; -- to a 15 bit value to the sums 
     aux2(1 downto 0) := "00";aux2(9 downto 2) := i_IN2; aux2(14 downto 10) := "00000"; -- looking to the array multiplier 
     aux3(2 downto 0) := "000";aux3(10 downto 3) := i_IN3; aux3(14 downto 11) := "0000"; -- architecture, it seem to be 
     aux4(3 downto 0) := "0000";aux4(11 downto 4) := i_IN4; aux4(14 downto 12) := "000"; -- correct 
     aux5(4 downto 0) := "00000";aux5(12 downto 5) := i_IN5; aux5(14 downto 13) := "00"; 
     aux6(5 downto 0) := "000000"; aux6(13 downto 6) := i_IN6; aux6(14) := '0'; 
     aux7(6 downto 0) := "0000000"; aux7(14 downto 7) := i_IN7; 
    -- below the loop that make the sums bit-in-bit, i've addapted this code from a 8 bit adder 
     c := '0'; 
      for i in 0 to 14 loop 
       soma(i) := aux0(1) xor aux1(i) xor aux2(i) xor aux3(i) xor aux4(i) xor aux5(i) xor aux6(i) xor aux7(i) xor c; 
       c := (aux0(i) and aux1(i) and aux2(i) and aux3(i) and aux4(i) and aux5(i) and aux6(i) and aux7(i)) or ((aux0(i) xor aux1(i) xor aux2(i) xor aux3(i) xor aux4(i) xor aux5(i) xor aux6(i) xor aux7(i)) and c); 
      end loop; 
      o_COUT <= c; 
      o_Q(15) <= c; -- carry out atribuition to the last bit of the vector 
      o_Q(14 downto 0) <= soma; 
    end process; 
end arch1; 

И ARRAY КОД:

LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL; 
USE IEEE.std_logic_unsigned.ALL; 
use IEEE.std_logic_arith.ALL; 

ENTITY and_array IS 
    PORT (i_MULTIPLICANDO : IN STD_LOGIC_VECTOR(7 downto 0);-- data input 
     i_MULTIPLICADOR : IN STD_LOGIC;-- data input 
     o_Q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));-- data output 
END and_array; 

ARCHITECTURE arch_1 OF and_array IS 
    BEGIN 
     GEN_REG: 
     FOR i IN 0 TO 7 GENERATE 
      o_Q(i) <= i_MULTIPLICADOR and i_MULTIPLICANDO(i); 
     END GENERATE GEN_REG; 
END arch_1; 

Я сделал моделирования для этих двух блоков, то и блоки массива работают отлично, но появляется ошибка при моделировании сумматора , ниже Imagem от моделирования:

enter image description here

i'am имитирующие следующие входы:

 Multiplicand = 1 1 1 1 0 1 0 1 (245 dec) 
     Multiplier = 1 0 1 0 1 1 1 1 (175 dec) 

Правильное значение для данного продукта 42785, в моем моделирование появляется 24899

Я использую следующую логику сумм в сумматоре:

    1 1 1 1 0 1 0 1 
        1 0 1 0 1 1 1 1 
        ----------------- 
     x x x x x x x 1 1 1 1 0 1 0 1  p1 
     x x x x x x 1 1 1 1 0 1 0 1 x  p2 
     x x x x x 1 1 1 1 0 1 0 1 x x  p3 
     x x x x 1 1 1 1 0 1 0 1 x x x  p4 
     x x x 0 0 0 0 0 0 0 0 x x x x  p5 
     x x 1 1 1 1 0 1 0 1 x x x x x  p6 
     x 0 0 0 0 0 0 0 0 x x x x x x  p7 
     1 0 1 0 1 1 1 1 x x x x x x x  p8 
_________________________________________ 

В блоке сумматора я заменил все «X» на 0 на сумму (как сдвиг). В цикле блока сумматора суммы p1-p8 выполняются бит-в-бит. Вероятно, ошибка в этом цикле или в переносе, но я пытался сделать это из многих форм и всегда ошибаюсь.

У кого-нибудь есть идея, как это исправить?

Ниже это главная цепь абстракция изображение:

enter image description here

+0

Привлекательный вопрос, но [Некоторые вопросы по-прежнему не соответствуют теме, даже если они вписываются в одну из категорий, перечисленных выше) (http://stackoverflow.com/help/on-topic): 1. Вопросы, требующие отладки («почему этот код не работает?») должен включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См. [Как создать минимальный, завершенный и проверяемый пример] (http://stackoverflow.com/help/mcve). – user1155120

+1

Суммирование в процессе в вашем сумматоре, похоже, не соответствует слайду Фрэнка Вахида 63. – user1155120

+0

Нет, слайд Vahid показывает 4-битный множитель с 3 сумматорами, что я пытаюсь сделать, это 8-разрядный множитель, использующий только 1 сумматор (абстрагирование всех остальных внутри этого), поэтому я думаю, что ошибка на сумрале, но я не нашел, где это. –

ответ

0

Решением этой проблемы было использовать половину сумматоров и полные сумматоры в месте сумматора, показанный выше в вопросе.

Она была использована логика ниже:

enter image description here

Всего было использовано:

64 и ворота; 8 Половинщики; 48 полных суммарных.

0

Эта модель поведения является производным от слайда Вахида 63:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity multiplier_array is 
    port (
     a: in std_logic_vector (7 downto 0); 
     b: in std_logic_vector (7 downto 0); 
     p: out std_logic_vector (15 downto 0) 
    ); 
end entity; 

architecture and_array of multiplier_array is 

    signal b0:   unsigned (7 downto 0); 
    signal b1:   unsigned (7 downto 0); 
    signal b2:   unsigned (7 downto 0); 
    signal b3:   unsigned (7 downto 0); 
    signal b4:   unsigned (7 downto 0); 
    signal b5:   unsigned (7 downto 0); 
    signal b6:   unsigned (7 downto 0); 
    signal b7:   unsigned (7 downto 0); 

    signal pp1:   unsigned (7 downto 0); 
    signal pp2:   unsigned (7 downto 0); 
    signal pp3:   unsigned (7 downto 0); 
    signal pp4:   unsigned (7 downto 0); 
    signal pp5:   unsigned (7 downto 0); 
    signal pp6:   unsigned (7 downto 0); 
    signal pp7:   unsigned (7 downto 0); 
    signal pp8:   unsigned (7 downto 0); 

    signal s:   unsigned (15 downto 0); 

begin 

    -- AND Array Multiplies 

    b0 <= (others => b(0)); 
    b1 <= (others => b(1)); 
    b2 <= (others => b(2)); 
    b3 <= (others => b(3)); 
    b4 <= (others => b(4)); 
    b5 <= (others => b(5)); 
    b6 <= (others => b(6)); 
    b7 <= (others => b(7)); 

    pp1 <= unsigned (a) and b0; 

    pp2 <= unsigned (a) and b1; 

    pp3 <= unsigned (a) and b2; 

    pp4 <= unsigned (a) and b3; 

    pp5 <= unsigned (a) and b4; 

    pp6 <= unsigned (a) and b5; 

    pp7 <= unsigned (a) and b6; 

    pp8 <= unsigned (a) and b7; 

    -- Sum 

    s <= ('0' & pp8 & "0000000") -- lead '0' for 16 bit sum 
     + (  pp7 & "000000") -- "+" takes sum width from left operand 
     + (  pp6 & "00000" ) -- adds are in left to right order so 16 bit 
     + (  pp5 & "0000" ) 
     + (  pp4 & "000" ) 
     + (  pp3 & "00" ) 
     + (  pp2 & '0'  ) 
     +   pp1; 

    p <= std_logic_vector (s); 

end architecture; 

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity mult_tb is 
end entity; 

architecture foo of mult_tb is 
    signal a, b: std_logic_vector (7 downto 0) := (others =>'0'); 
    signal p:  std_logic_vector (15 downto 0); 

begin 
DUT: 
    entity work.multiplier_array 
     port map (
      a => a, 
      b => b, 
      p => p 
     ); 

STIMULI: 
    process 
    begin 
     wait for 10 ns; 
     a <= std_logic_vector (to_unsigned(245, a'length)); 
     b <= std_logic_vector (to_unsigned(175, b'length)); 
     wait for 10 ns; 
     wait; 
    end process; 

MONITOR: 
    process (p) 
    begin 
     if now > 9 ns then 
      report "a = " & natural'image (to_integer(unsigned(a))); 
      report "b = " & natural'image (to_integer(unsigned(b))); 
      report "product = " & natural'image (to_integer(unsigned(p))); 
      report "expected product = " & 
        natural'image (to_integer(unsigned(a) * unsigned(b))); 
     end if; 
    end process; 

end architecture; 

Сложения ассоциативно, который позволяет порядок добавления на обратном позволяя широкий операнд быть дать в качестве левого операнда первого сложения. Длина самого левого операнда для оператора «+» определяет ограничение длины результата, устанавливающее ширину для остальных дополнений. Обратите внимание, что операции конкатенации имеют тот же приоритет, что и оператор добавления, и заключены в круглые скобки для предотвращения ошибок границ.

Когда включена тестовая mult_tb запускается:

multiplier_array.vhdl: 113: 13: @ 10ns: (Докладная записка): а = 245
multiplier_array.vhdl: 114: 13: @ 10ns: (отчетная записка): b = 175
multiplier_array.vhdl: 115: 13: @ 10ns: (примечание к отчету): продукт = 42875
multiplier_array.vhdl: 116: 13: @ 10ns: (примечание к отчету): ожидаемый продукт = 42875

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

Кроме того, поддерживаемые VHDL -2008 логические операторы позволяют исключать сигналы с b0 по b8.

IEEE Std 1076-2008, 9.2 Операторы, 9.2.2 Логические операторы, пункт 3:

Если оба операнда являются одномерные массивы, операнды должны быть массивами одинаковой длины, операция выполняется по совпадающим элементам массивов, а результатом является массив с тем же диапазоном индексов, что и левый операнд. Если один операнд является скаляром, а другой операндом является одномерный массив, операция выполняется в скалярном операнде с каждым элементом операнда массива. Результатом является массив с тем же диапазоном индексов, что и операнд массива.

Это позволяет модели для VHDL -2008 быть немного менее сложной. В версиях -2008 пакетов std_logic_1164 и numeric_std поддерживаются скалярные/векторные логические операции.

Вдохновленный вашим комментарием «только 1 сумматор», можно получить правильные результаты, используя взвешивание Хэмминга (например, поведенческие функции popcount).

После прочтения информации о реализации весов Хэмминга в VHDL для FPGA, а также для выделения векторов, которые появляются 8 различных весовых сетей (для длин 3, 4, 5, 6, 7, 8, 9 и 10) требуются с несколькими экземплярами для длин 4, 7, 8 и 10.

Вес Хэмминга не указывает на то, что площадь заготовки или время распространения ограничены по сравнению с частичными сумматорами товаров. Если бы вы определяли весовые сети в легко приводимых терминах, вы, возможно, закончили бы с частичными добавителями товаров после того, как в ходе синтеза было бы очень много циклов ЦП. Весовые функции Хэмминга для не-сил двух также, по-видимому, вызывают неэффективное распространение переноса.

Вот архитектура реализации Хэмминга взвешивания:

architecture popcount of multiplier_array is 

    function popcount (inp: in std_logic_vector; len: in natural) 
      return std_logic_vector is 
     variable r: integer := 0; 
     variable result: std_logic_vector (len - 1 downto 0); 

    begin 
     for i in inp'range loop 
      if inp(i) = '1' then 
       r := r + 1; 
      elsif inp(i) /= '0' and now > 0 ns then 
       report "WARNING: function popcount encountered metavalue " & 
         "returned zero"; 
       r := 0; 
       exit;     
      end if; 
     end loop; 
     return std_logic_vector (to_unsigned(r,result'length)); 
    end function; 

    signal b0:   unsigned (7 downto 0); 
    signal b1:   unsigned (7 downto 0); 
    signal b2:   unsigned (7 downto 0); 
    signal b3:   unsigned (7 downto 0); 
    signal b4:   unsigned (7 downto 0); 
    signal b5:   unsigned (7 downto 0); 
    signal b6:   unsigned (7 downto 0); 
    signal b7:   unsigned (7 downto 0); 

    signal pp1:   unsigned (7 downto 0); 
    signal pp2:   unsigned (7 downto 0); 
    signal pp3:   unsigned (7 downto 0); 
    signal pp4:   unsigned (7 downto 0); 
    signal pp5:   unsigned (7 downto 0); 
    signal pp6:   unsigned (7 downto 0); 
    signal pp7:   unsigned (7 downto 0); 
    signal pp8:   unsigned (7 downto 0); 

    signal c1:   std_logic; 

    signal sum2:  std_logic_vector(2 downto 0); 
    signal sum3:  std_logic_vector(2 downto 0); 
    signal sum4:  std_logic_vector(2 downto 0); 
    signal sum5:  std_logic_vector(3 downto 0); 
    signal sum6:  std_logic_vector(3 downto 0); 
    signal sum7:  std_logic_vector(3 downto 0); 
    signal sum8:  std_logic_vector(3 downto 0); 
    signal sum9:  std_logic_vector(3 downto 0); 
    signal sum10:  std_logic_vector(3 downto 0); 
    signal sum11:  std_logic_vector(2 downto 0); 
    signal sum12:  std_logic_vector(2 downto 0); 
    signal sum13:  std_logic_vector(2 downto 0); 
    signal sum14:  std_logic_vector(1 downto 0); 

    signal c14:   std_logic; 
    signal c15:   std_logic; 

begin 

    -- AND Array Multiplies 

    b0 <= (others => b(0)); 
    b1 <= (others => b(1)); 
    b2 <= (others => b(2)); 
    b3 <= (others => b(3)); 
    b4 <= (others => b(4)); 
    b5 <= (others => b(5)); 
    b6 <= (others => b(6)); 
    b7 <= (others => b(7)); 

    pp1 <= unsigned (a) and b0; 

    pp2 <= unsigned (a) and b1; 

    pp3 <= unsigned (a) and b2; 

    pp4 <= unsigned (a) and b3; 

    pp5 <= unsigned (a) and b4; 

    pp6 <= unsigned (a) and b5; 

    pp7 <= unsigned (a) and b6; 

    pp8 <= unsigned (a) and b7; 


    p(0) <= pp1(0); -- nothing to do here 
    p(1) <= pp1(1) xor pp2(0); 
    c1 <= pp1(1) and pp2(0); -- single carry bit 

    sum2 <= popcount ((pp1(2), pp2(1), pp3(0), c1), sum2'length); 

    p(2) <= sum2(0); 

    sum3 <= popcount ((pp1(3), pp2(2), pp3(1), pp4(0), sum2(1)), sum3'length); 

    p(3) <= sum3(0); 

    sum4 <= popcount ((pp1(4), pp2(3), pp3(2), pp4(1), pp5(0), 
         sum2(2), sum3(1)), sum4'length); 

    p(4) <= sum4(0); 

    sum5 <= popcount ((pp1(5), pp2(4), pp3(3), pp4(2), pp5(1), pp6(0), 
         sum3(2), sum4(1)), sum5'length); 

    p(5) <= sum5(0); 

    sum6 <= popcount ((pp1(6), pp2(5), pp3(4), pp4(3), pp5(2), pp6(1), pp7(0), 
         sum4(2), sum5(1)), sum6'length); 

    p(6) <= sum6(0); 

    sum7 <= popcount ((pp1(7), pp2(6), pp3(5), pp4(4), pp5(3), pp6(2), pp7(1), 
         pp8(0), sum5(2), sum6(1)), sum7'length); 

    p(7) <= sum7(0); 

    sum8 <= popcount ((pp2(7), pp3(6), pp4(5), pp5(4), pp6(3), pp7(2), pp8(1), 
         sum5(3), sum6(2), sum7(1)), sum8'length); 

    p(8) <= sum8(0); 

    sum9 <= popcount ((pp3(7), pp4(6), pp5(5), pp6(4), pp7(3), pp8(2), 
         sum6(3), sum7(2), sum8(1)), sum9'length); 

    p(9) <= sum9(0); 

    sum10 <= popcount ((pp4(7), pp5(6), pp6(5), pp7(4), pp8(3), 
         sum7(3), sum8(2), sum9(1)), sum10'length); 

    p(10) <= sum10(0); 

    sum11 <= popcount ((pp5(7), pp6(6), pp7(5), pp8(4), 
         sum8(3), sum9(2), sum10(1)), sum11'length); 

    p(11) <= sum11(0);  

    sum12 <= popcount ((pp6(7), pp7(6), pp8(5), 
         sum9(3), sum10(2), sum11(1)), sum12'length); 

    p(12) <= sum12(0); 

    sum13 <= popcount ((pp7(7), pp8(6), 
         sum11(2), sum12(1)), sum13'length); 

    p(13) <= sum12(1);  

    sum14 <= popcount ((pp8(7), 
         sum12(2), sum13(1)), sum14'length); 

    p(14) <= sum14(0); 


    p(15) <= sum13(2) xor sum14(1); 

    c15 <= sum13(2) and sum14(1); -- overflow 

end architecture; 

multiplier_array.vhdl: 277: 13: @ 11ns: (отчет примечание): а = 245
multiplier_array.vhdl: 278: 13: @ 11ns: (примечание к докладу): b = 175
multiplier_array.vhdl: 279: 13: @ 11ns: (примечание к отчету): product = 42875
multiplier_array.vhdl: 280: 13: @ 11ns: (примечание к отчету): ожидается продукт = 42875

Он дает тот же ответ.

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

MONITOR: 
    process 
    begin 
      wait for 11 ns; 
      report "a = " & natural'image (to_integer(unsigned(a))); 
      report "b = " & natural'image (to_integer(unsigned(b))); 
      report "product = " & natural'image (to_integer(unsigned(p))); 
      report "expected product = " & 
        natural'image (to_integer(unsigned(a) * unsigned(b))); 
      wait; 
    end process; 

отметить также, потому что было два входа, вносящие вклад в левом бите продукта я произвел перенос, который можно было бы использовать для обнаружения ошибок (переполнения).

0

Я думаю, что основная проблема заключается в коде побитовой означает сделать суммирующий:

 for i in 0 to 14 loop 
      soma(i) := aux0(1) xor aux1(i) xor aux2(i) xor aux3(i) xor aux4(i) xor aux5(i) xor aux6(i) xor aux7(i) xor c; 
      c := (aux0(i) and aux1(i) and aux2(i) and aux3(i) and aux4(i) and aux5(i) and aux6(i) and aux7(i)) or ((aux0(i) xor aux1(i) xor aux2(i) xor aux3(i) xor aux4(i) xor aux5(i) xor aux6(i) xor aux7(i)) and c); 
     end loop; 

c здесь только один бит, который является весьма неадекватным, как ручная кладь для девяти членов (восемь Окса бит и переноса в, поэтому это возвращается, чтобы получить больше терминов, когда мы расширяем перенос в достаточной мере). Если бы мы предположили, что этих девяти бит было достаточно, вы все равно получали бы значения до 9, которые требуют битов в битах, поэтому по меньшей мере три переносят. Это происходит, как только у вас есть более трех терминов; суммарный сумматор суммирует от 1 + 1 + 1 до 2 + 1 (один бит имеет больший вес), используя все значения его выхода. Поскольку это сокращение, они могут быть привязаны по слоям, но более крупный сумматор должен использовать больше выходных битов (например, 5 входных сумматоров могут создавать 2 + 2 + 1, 7-битный сумматор может быть создан для создания 4 + 2 + 1); мы видим это, если подсчитать линии переноса между столбцами в схеме множителя массива. Есть так много переносов вокруг среднего столбца, поскольку в факторах есть бит.

Смежные вопросы