Ошибка логического моделирования VHDL при сложении и сдвиге множителя

Я пытаюсь сделать «множитель сложения и сдвига (последовательный)», и у меня возникают проблемы с окончательной симуляцией, значение на выходе всегда неверно. Я использовал логику конечного автомата, чтобы создать блок управления частичными суммами.

Когда я делаю 1 x 1, вывод идет не так (для всех продуктов не так):

Ошибка вывода в файле VWF

Эта ошибка появляется для всех входных множителей и множителей.

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

 library IEEE;
 use IEEE.std_logic_1164.all;

 entity adder_8bits is 
 port (
     cin: in STD_LOGIC;
     a,b: in STD_LOGIC_VECTOR(7 DOWNTO 0);
     s: out STD_LOGIC_VECTOR(8 DOWNTO 0)
 );
 end adder_8bits;

 architecture arch_1 of adder_8bits is 
 begin 
     process(a,b,cin)
     variable soma:std_logic_vector(8 downto 0);
     variable c:std_logic; 
     begin
          c := cin;
          for i in 0 to 7 loop
                soma(i) := a(i) xor b(i) xor c;
                c := (a(i) and b(i)) or ((a(i) xor b(i)) and c);
          end loop;
          s(7 downto 0) <= soma(7 downto 0);
          s(8) <= c;
      end process;
end arch_1;

8-битный сумматор для суммирования частичных результатов.

 library IEEE;
 use IEEE.std_logic_1164.all;
 use IEEE.numeric_std.all;

 entity sum_register is 
 port (
     i_DIN   : in UNSIGNED(8 DOWNTO 0);
     i_LOAD  : in STD_LOGIC;
     i_CLEAR : in STD_LOGIC;
     i_SHIFT : in STD_LOGIC;
     i_CLK : in STD_ULOGIC;
     o_DOUT  : buffer UNSIGNED(15 downto 0)
 );
 end sum_register;


 architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 7) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
            IF (i_DIN(8) = '1') THEN
              o_DOUT <= o_DOUT SRL 1;
            END IF;
        END IF;
      END IF;
      end process;
end arch_1;

Регистр суммы для получения фактического значения суммы и сдвига перед другой суммой.

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

ENTITY controller IS
  PORT (
        i_CLK     : IN STD_ULOGIC;
        i_START   : IN  STD_LOGIC; 
        i_MLTPLR  : IN STD_LOGIC_VECTOR(7 downto 0);
        o_MDLD    : OUT STD_LOGIC; 
        o_MRLD    : OUT STD_LOGIC;  
        o_RSLD    : OUT STD_LOGIC;
        o_RSCLR   : OUT STD_LOGIC;
        o_RSSHR   : OUT STD_LOGIC
      );     
END controller;

ARCHITECTURE arch_1 OF controller IS
  TYPE state_type IS (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18);
  SIGNAL stateT : state_type;
BEGIN
  PROCESS(i_CLK)
  BEGIN
  IF rising_edge(i_CLK) THEN
      IF (i_START = '0') THEN
        stateT <= s0;
      ELSE
        CASE stateT IS
          when s0 => if (i_START = '1') then 
                         stateT <= s1; 
                     end if;
          when s1 =>  stateT <= s2;          
          when s2 => if (i_MLTPLR(0) = '1') then
                         stateT <= s3;
                     else
                         stateT <= s4;
                     end if;
          when s3 => stateT <= s4;                    
          when s4 => if (i_MLTPLR(1) = '1') then
                         stateT <= s5;
                     else
                         stateT <= s6;
                     end if;
          when s5 => stateT <= s6;
          when s6 => if (i_MLTPLR(2) = '1') then
                         stateT <= s7;
                     else
                         stateT <= s8;
                     end if;
          when s7 => stateT <= s8;
          when s8 => if (i_MLTPLR(3) = '1') then
                         stateT <= s9;
                     else
                         stateT <= s10;
                     end if;
          when s9 => stateT <= s10;
          when s10 => if (i_MLTPLR(4) = '1') then
                         stateT <= s11;
                     else
                         stateT <= s12;
                     end if;
          when s11 => stateT <= s12;
          when s12 => if (i_MLTPLR(5) = '1') then
                         stateT <= s13;
                     else
                         stateT <= s14;
                     end if;  
          when s13 => stateT <= s14; 
          when s14 => if (i_MLTPLR(6) = '1') then
                         stateT <= s15;
                     else
                         stateT <= s16;
                     end if;  
          when s15 => stateT <= s16; 
          when s16 => if (i_MLTPLR(7) = '1') then
                         stateT <= s17;
                     else
                         stateT <= s18;
                     end if;           
          when s17 => stateT <= s18; 
          when s18 => stateT <= s0;    
        END CASE;
      END IF;
    END IF;
  END PROCESS;

  o_MDLD <= '1' when (stateT = s1) else '0';  
  o_MRLD <= '1' when (stateT = s1) else '0';  
  o_RSCLR <= '1' when (stateT = s1) else '0';
  o_RSLD  <= '1' when (stateT = s3 or stateT = s5 or 
                       stateT = s7 or stateT = s9 or 
                       stateT = s11 or stateT = s13 or 
                       stateT = s15 or stateT = s17) else '0';    
  o_RSSHR <= '1' when (stateT = s4 or stateT = s6 or 
                       stateT = s8 or stateT = s10 or 
                       stateT = s12 or stateT = s14 or 
                       stateT = s16 or stateT = s18) else '0'; 

END arch_1;

Контроллер конечного автомата для управления входным сигналом из регистра суммирования.

Я использую файл BDF для соединения всех блоков, единственное отличие от схемы ниже в том, что в блоке сумматора есть входной перенос. Часы всех блоков находятся на одном выводе.

Моделирование контроллера

Кто-нибудь знает, что вызывает эту ошибку?


person Mutante    schedule 07.06.2016    source источник
comment
Ваш вопрос не является минимальным, полным и поддающимся проверке примером, в котором отсутствуют какие-либо средства для воспроизведения (неустановленной) ошибки. Ваша форма волны даже не показывает stateT, ни ваши элементы управления (o_MDLD, o_MRLD, o_RSLD, o_RSCLR, o_RSSHR), ни соединения с каналом передачи данных не показаны.   -  person    schedule 08.06.2016
comment
Я не могу публиковать больше изображений, и я считаю, что ошибка не в конечном автомате, потому что, когда я моделирую каждый компонент по отдельности, все они работают правильно, но когда я имитирую их интегрированными, появляется ошибка, я собираюсь поместить форму волны с выходами вы говорите.   -  person Mutante    schedule 08.06.2016
comment
Я добавил снимок экрана с симуляцией контроллера в исходный пост user1155120. Я считаю, что блок контроллера работает правильно.   -  person Mutante    schedule 08.06.2016
comment
Итак, ваша проблема в том, что он не работает должным образом или у вас возникают ошибки?   -  person Shmwel    schedule 09.06.2016


Ответы (2)


При реализации вашего ответа:

architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 8) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
              o_DOUT <= o_DOUT SRL 1;

        END IF;
      END IF;
      end process;
end arch_1;

что произойдет, если вы умножите 255 на 255?

Ваш продукт равен 1 (что было бы правильно, если бы это было знаковое умножение, вы указали беззнаковый множитель и множимое, где правильный ответ был бы 65025 ("1111111000000001"). Поскольку у вас есть отдельные операции загрузки и сдвига, вам необходимо сохранить отброшенные переносить и использовать его при сдвиге внутрь. И поскольку у вас могут быть последовательные биты умножителя, которые равны «0», вам необходимо очистить этот перенос после того, как он используется в инструкции сдвига (по умолчанию ожидаемый знак, который равен «0» для беззнаковых умножений ).

Вы можете сделать это с исходным 9-битным путем для суммы adder_8bits и сохранением переноса:

architecture foo of sum_register is
    signal carry: std_logic;
begin
    process (i_clk)
    begin
        if rising_edge(i_clk) then
            if i_clear = '1' then
                o_dout <= (others => '0');
                carry <= '0';
            elsif i_load = '1' then
                o_dout(15 downto 8) <= i_din (7 downto 0);
                carry <= i_din(8);
            elsif i_shift = '1' then
                o_dout <= carry & o_dout(15 downto 1);
                carry <= '0';  -- expected sign for multiply result
            end if;
        end if;
    end process;
end architecture;

Обратите внимание, что он очищается при потреблении, требуя, чтобы предыдущая загрузка вставляла перенос = '1'.

И это приспособление могло бы исчезнуть, если у вас есть две: загрузка и сдвиг, загрузка и инструкция загрузки вместо инструкции загрузки и инструкции сдвига. Для этого потребуется переключиться с конечного автомата Мура на конечный автомат Мили и уменьшить количество состояний.

Вы - контролер, конечный автомат Мура может проходить 16 состояний как сдвига, так и загрузки для множителя «11111111», машина Мили может делать это в 8 состояниях с помощью операций сдвига и загрузки и сдвига в sum_register.

И sum_register будет выглядеть примерно так:

architecture fum of sum_register is

begin
    process (i_clk)
    begin
        if rising_edge(i_clk) then
            if i_clear = '1' then
                o_dout <= (others => '0');
            elsif i_load_shift = '1' then
                o_dout(15 downto 7) <= i_din & o_dout (6 downto 1); 
            elsif i_shift = '1' then
                o_dout <= '0' & o_dout(15 downto 1); -- '0' expected result sign
            end if;
        end if;
    end process;
end architecture;

для 9-битной суммы от adder_8bits. Обратите внимание, что сигнал i_load переименован в i_load_shift, и конечный автомат контроллера необходимо переписать как машину Мили, выдающую либо i_load_shift = '1', либо i_shift = '1', а другой '0', в зависимости от того, установлен ли оцененный бит множителя. «1» или «0».

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

person Community    schedule 11.06.2016

Проблема заключалась в sum_register, я отправлял бит переноса сумматора в регистр суммы, поэтому это приводит к неправильному выводу, я просто выполняю перенос из байта, отправленного в регистр суммы.

 s <= soma;

а переменная сома из сумматора была изменена на 8 бит:

variable soma:std_logic_vector(7 downto 0);

Регистр суммы был изменен, чтобы получать от сумматора только 8 бит:

architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 8) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
              o_DOUT <= o_DOUT SRL 1;

        END IF;
      END IF;
      end process;
end arch_1;

С этими изменениями симуляция идет нормально!

person Mutante    schedule 10.06.2016
comment
Это неверный ответ. Что произойдет, если вы умножите 255 на 255? Ваш продукт равен 1, где правильный ответ - 65025 (1111111000000001). Это также подчеркивает необходимость в минимальном, полном и поддающемся проверке примере. - person ; 11.06.2016