2013-11-21 3 views
0

Это симуляция длинного деления двоичного делителя. Программа выполняет, как ожидалось, за исключением того, что не будет вычитать дивизор из 5 MSB регистра независимо от того, как я его кодирую.Почему мой конечный автомат VHDL не вычитает?

Ниже приведен код:

  library ieee; 
      use ieee.std_logic_1164.all; 
      use ieee.std_logic_unsigned.all; 
      use ieee.std_logic_arith.all; 

      ENTITY divider IS 

       PORT(
          Clock    :IN STD_LOGIC; 
          Dividend   :IN STD_LOGIC_VECTOR(7 DOWNTO 0); 
          Divisor   :IN STD_LOGIC_VECTOR(4 DOWNTO 0); 
          Reset    :IN STD_LOGIC; 
          St     :IN STD_LOGIC; 

          outDRegister   :OUT STD_LOGIC_VECTOR(8 DOWNTO 0):="000000000"; 
          outCurrentState   :OUT STD_LOGIC_VECTOR(2 DOWNTO 0):="000"; 
          Quotient   :OUT STD_LOGIC_VECTOR(3 DOWNTO 0); 
          Remainder  :OUT STD_LOGIC_VECTOR(4 DOWNTO 0)); 
      END divider; 

      ARCHITECTURE Behavior of divider IS 

      SIGNAL DRegister      :STD_LOGIC_VECTOR(8 DOWNTO 0); 
      SIGNAL SubOut       :STD_LOGIC_VECTOR(4 DOWNTO 0); 
      Signal C,ShiftIn, ShiftRes   :STD_LOGIC; 
      Signal ShiftEnable     :STD_LOGIC; 
      Signal tempSt       :STD_LOGIC:='1'; 
      TYPE State_type IS (S0, S1, S2, S3, S4, S5); 
      SIGNAL y:State_type:=S0; 

      BEGIN 
      PROCESS(Dividend,Divisor,y, st, reset, clock) IS 
      BEGIN 
      If (Reset='0') THEN 
      Y<=S0; 
      ELSIF (Clock'EVENT and CLOCK = '1') THEN 

       CASE y IS 
        WHEN S0=> 
         IF(st='0' AND tempSt='1' AND reset = '1') THEN 
          DRegister <= '0'&Dividend; 
          y<=S1; 
         ELSIF(st='1' AND reset = '1') THEN 
          Quotient <= DRegister(3 DOWNTO 0); 
          Remainder <= DRegister(8 DOWNTO 4); 
          y<=S0; 
         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="000"; 
         tempSt<=st; 

        WHEN S1=> 
         IF(DRegister(8 DOWNTO 4)>=Divisor) THEN 
          y<=S0; 
         ELSE 
          DRegister <= (DRegister(7 DOWNTO 0) & '0'); 
          y<=S2; 
         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="001"; 
        WHEN S2=> 
         IF(DRegister(8 DOWNTO 4)>=Divisor) THEN 
          DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing. 
          DRegister <= DRegister(7 DOWNTO 0) & '1'; 
         ELSE 
          DRegister <= DRegister(7 DOWNTO 0) & '0'; 
         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="010";  
         y<=S3; 

        WHEN S3=> 
         IF(DRegister(8 DOWNTO 4)>=Divisor) THEN 
          DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing. 
          DRegister <= DRegister(7 DOWNTO 0) & '1'; 
         ELSE 
          DRegister <= DRegister(7 DOWNTO 0) & '0'; 

         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="011"; 
         y<=S4; 

        WHEN S4=> 
         IF(DRegister(8 DOWNTO 4)>=Divisor) THEN 
          DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing. 
          DRegister <= DRegister(7 DOWNTO 0) & '1'; 
         ELSE 
          DRegister <= DRegister(7 DOWNTO 0) & '0'; 
         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="100"; 
         y<=S5; 

        WHEN S5=> 
         IF(DRegister(8 DOWNTO 4)>=Divisor) THEN 
          DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing. 
         END IF; 
         outDRegister<=DRegister; 
         outCurrentState<="101"; 

         y<=S0; 

       END CASE; 

      END IF; 




      END PROCESS; 


      END Behavior; 

ответ

0

Первый шаг, чтобы прочитать о разнице между переменной и присвоения сигнала в VHDL. Ваша проблема там. Одно из решений включает промежуточную переменную для проблемных состояний; другой предполагает переписывание назначения сигнала.

Мое обычное объяснение here, есть ссылка внизу страницы на "VHDL's Crown Jewel", который также очень стоит прочитать.

Также обратите внимание:

  • Есть лучшие библиотеки для арифметики: ieee.numeric_std, а не std_logic_unsigned или std_logic_arith или (что хуже всего) смешивание двух.
  • Существует более качественный тип данных для арифметики, чем std_logic_vector: ieee.numeric_std.unsigned (или подписанный) или даже подтипы integer или natural;
  • Как вы пишете хорошую чистую однопроцессное состояние машины, список его чувствительности требуется только clock, reset
  • Вы можете потерять скобки вокруг условных выражений, If Reset='0' Then прекрасно (это не C компилятор вашего отца)
  • rising_edge(Clock) предпочтительно Clock'EVENT and CLOCK = '1'
    , но все они являются периферийными для основной проблемы.
0

Проблемная часть кода, как вы также отмечено, является:

... 
DRegister(8 downto 4) <= (DRegister(8 downto 4) - Divisor); --Does not work!! Does nothing. 
DRegister    <= DRegister(7 downto 0) & '1'; 
... 

В VHDL, значение сигнала не обновляется до конца текущего цикла моделирования, так что значение DRegister, используемый во втором назначении для . DRegister не изменяется первым назначением DRegister.

Таким образом, эффект первого правопреемника к DRegister(8 downto 4) переопределяется второй назначить для всех битов в DRegister, в результате чего вычитание Divisor не оказывает никакого эффекта.

Один из способов исправить код, поэтому сделать только одно назначение для всех DRegister бит.

Возможно, вы захотите взглянуть на Давида Коонца на вопрос https://stackoverflow.com/a/20104800/2352082, так как это касается аналогичной проблемы.

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