VHDL: ложные результаты в 4-битном сумматоре и вычитателе

Я хочу сделать 4-битный сумматор и вычитатель с VHDL. Я создал 1-битный полный сумматор, XOR Gate (для вычитания) и 4-битный сумматор, как показано ниже:

Полный сумматор:

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY FullAdder_1_Bit IS
  PORT(
    X, Y : IN STD_LOGIC;
    CIn  : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC;
    COut : OUT STD_LOGIC
  );
END FullAdder_1_Bit;

ARCHITECTURE Behavier OF FullAdder_1_Bit IS
BEGIN
  Sum <= X XOR Y XOR CIn;
  COut <= (X AND Y) OR (X AND CIn) OR (Y AND CIn);
END Behavier;

XOR-ворота:

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY XORGate IS
  PORT(
    X1, X2 : IN STD_LOGIC;
    Y : OUT STD_LOGIC
  );  
END XORGate;

ARCHITECTURE Declare OF XORGate IS
BEGIN  
 Y <= X1 XOR X2;
END Declare;

4-битный сумматор:

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY Adder
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY Add_AND_Sub IS

END Add_AND_Sub;

ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
  PORT(
    A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    Mode : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    COut : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN 

 Add : Adder_4_Bit
 PORT MAP(XA, XB, Mode, Sum, E);

 PROCESS(A, B, Mode)
 BEGIN
  As <= A(4);
  Bs <= B(4);

  XA <= A(3 DOWNTO 0);
  XB <= B(3 DOWNTO 0);  

  CASE Mode IS
   WHEN '0' =>
     IF ((As XOR Bs) = '1') THEN                   
       Mode <= '1';
       XA <= Sum;       
       AVF <= '0';
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE           
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF; 
     ELSE
       XA <= Sum;
     END IF;   

   WHEN '1' =>
     IF ((As XOR Bs) = '1') THEN              
       Mode <= '0';       
       XA <= Sum;       
       AVF <= E;        
     ELSE       
       AVF <= '0';
       XA <= Sum;
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF;      
     END IF;
   WHEN Others =>  
    --   
  END CASE;          
 END PROCESS; 

END Declare;
Bit IS PORT( A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0); Mode : IN STD_LOGIC; Sum : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); COut : OUT STD_LOGIC ); END Adder
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY Add_AND_Sub IS

END Add_AND_Sub;

ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
  PORT(
    A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    Mode : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    COut : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN 

 Add : Adder_4_Bit
 PORT MAP(XA, XB, Mode, Sum, E);

 PROCESS(A, B, Mode)
 BEGIN
  As <= A(4);
  Bs <= B(4);

  XA <= A(3 DOWNTO 0);
  XB <= B(3 DOWNTO 0);  

  CASE Mode IS
   WHEN '0' =>
     IF ((As XOR Bs) = '1') THEN                   
       Mode <= '1';
       XA <= Sum;       
       AVF <= '0';
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE           
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF; 
     ELSE
       XA <= Sum;
     END IF;   

   WHEN '1' =>
     IF ((As XOR Bs) = '1') THEN              
       Mode <= '0';       
       XA <= Sum;       
       AVF <= E;        
     ELSE       
       AVF <= '0';
       XA <= Sum;
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF;      
     END IF;
   WHEN Others =>  
    --   
  END CASE;          
 END PROCESS; 

END Declare;
Bit; ARCHITECTURE Structure OF Adder
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY Add_AND_Sub IS

END Add_AND_Sub;

ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
  PORT(
    A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    Mode : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    COut : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN 

 Add : Adder_4_Bit
 PORT MAP(XA, XB, Mode, Sum, E);

 PROCESS(A, B, Mode)
 BEGIN
  As <= A(4);
  Bs <= B(4);

  XA <= A(3 DOWNTO 0);
  XB <= B(3 DOWNTO 0);  

  CASE Mode IS
   WHEN '0' =>
     IF ((As XOR Bs) = '1') THEN                   
       Mode <= '1';
       XA <= Sum;       
       AVF <= '0';
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE           
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF; 
     ELSE
       XA <= Sum;
     END IF;   

   WHEN '1' =>
     IF ((As XOR Bs) = '1') THEN              
       Mode <= '0';       
       XA <= Sum;       
       AVF <= E;        
     ELSE       
       AVF <= '0';
       XA <= Sum;
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF;      
     END IF;
   WHEN Others =>  
    --   
  END CASE;          
 END PROCESS; 

END Declare;
Bit IS COMPONENT FullAdder_1_Bit IS PORT( X, Y : IN STD_LOGIC; CIn : IN STD_LOGIC; Sum : OUT STD_LOGIC; COut : OUT STD_LOGIC ); END COMPONENT; COMPONENT XORGate IS PORT( X1, X2 : IN STD_LOGIC; Y : OUT STD_LOGIC ); END COMPONENT; SIGNAL COut_Temp : STD_LOGIC_VECTOR(2 DOWNTO 0); SIGNAL XB : STD_LOGIC_VECTOR(3 DOWNTO 0); BEGIN B_0 : XORGate PORT MAP(Mode, B(0), XB(0)); B_1 : XORGate PORT MAP(Mode, B(1), XB(1)); B_2 : XORGate PORT MAP(Mode, B(2), XB(2)); B_3 : XORGate PORT MAP(Mode, B(3), XB(3)); SUM_0 : FullAdder_1_Bit PORT MAP (A(0), XB(0), Mode, Sum(0), COut_Temp(0)); SUM_1 : FullAdder_1_Bit PORT MAP (A(1), XB(1), COut_Temp(0), Sum(1), COut_Temp(1)); SUM_2 : FullAdder_1_Bit PORT MAP (A(2), XB(2), COut_Temp(1), Sum(2), COut_Temp(2)); SUM_3 : FullAdder_1_Bit PORT MAP (A(3), XB(3), COut_Temp(2), Sum(3), COut); END;

и в моих основных кодах я использовал их (например, Test-Bench!):

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY Add_AND_Sub IS

END Add_AND_Sub;

ARCHITECTURE Declare OF Add_AND_Sub IS
COMPONENT Adder_4_Bit IS
  PORT(
    A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    Mode : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    COut : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL A, B : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;
SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN 

 Add : Adder_4_Bit
 PORT MAP(XA, XB, Mode, Sum, E);

 PROCESS(A, B, Mode)
 BEGIN
  As <= A(4);
  Bs <= B(4);

  XA <= A(3 DOWNTO 0);
  XB <= B(3 DOWNTO 0);  

  CASE Mode IS
   WHEN '0' =>
     IF ((As XOR Bs) = '1') THEN                   
       Mode <= '1';
       XA <= Sum;       
       AVF <= '0';
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE           
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF; 
     ELSE
       XA <= Sum;
     END IF;   

   WHEN '1' =>
     IF ((As XOR Bs) = '1') THEN              
       Mode <= '0';       
       XA <= Sum;       
       AVF <= E;        
     ELSE       
       AVF <= '0';
       XA <= Sum;
       IF (E = '1') THEN
         IF (XA = "0000") THEN
           As <= '0';
         END IF;
       ELSE
         XA <= (NOT XA) + "0001";
         As <= NOT As;
       END IF;      
     END IF;
   WHEN Others =>  
    --   
  END CASE;          
 END PROCESS; 

END Declare;

Основной сценарий заключается в моделировании этого алгоритма:

Add_Sub_Algorithm

но теперь я хочу иметь вывод в XA и As

  • Я должен использовать регистры, показанные в алгоритме, такие как «E» и «AVF».

есть один вопрос:

мы знаем, что карты портов постоянно подключены, поэтому, когда я меняю значение режима, результат (сумма) должен измениться, это правда?!

Я пробовал этот код, но я не могу получить вывод в XA, и нет истинного результата для значений суммы, я знаю, что в моем основном коде (процессе) есть какая-то проблема, но я не могу найти проблемы

Пожалуйста, проверьте эти коды и скажите мне, что пошло не так!

Изменить :

Я использую ModelSim и его симуляцию для тестирования моего кода, сначала я задаю значения «A», «B» и «Mode», затем запускаю, чтобы получить результат и волну

Спасибо ...


person G3ntle_Man    schedule 26.05.2015    source источник


Ответы (2)


Ваш тестовый стенд add_and_sub не присваивает своим a и b значения по умолчанию, все они равны "U".

Что вы ожидаете, когда ваши входные данные для adder_4_bit не определены?

Посмотрите на not_table, or_table, and_table и xor_table в теле пакета std_logic_1164.

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

Если вы на самом деле симулируете тестовый стенд, я ожидаю, что он не будет потреблять время симуляции, и после некоторого количества дельта-циклов во время инициализации покажет sum и e битком набитые «U».

Я лично не модифицировал ваш тестовый стенд, чтобы определить, работает ли ваш adder_4_bit, но если вы предоставите ему действительный стимул, вы сможете его отладить. Может быть полезно потратить время на моделирование и использовать разные входные значения.

Добавление процесса монитора в add_and_sub:

 MONITOR:
     process (sum)
         function to_string(inp: std_logic_vector) return string is
             variable image_str: string (1 to inp'length);
             alias input_str:  std_logic_vector (1 to inp'length) is inp;
         begin
             for i in input_str'range loop
                 image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
             end loop;
             -- report "image_str = " & image_str;
             return image_str;
         end;
     begin
         report "sum = " & to_string(sum);
     end process;

дает:

Fourbitadder.vhdl:174:10:@0ms:(примечание к отчету): sum = uuuu

одно событие sum.

Добавьте процесс, чтобы вызвать события на a и 'b`:

STIMULUS:
     process
     begin
         a <= "00000" after 10 ns;
         b <= "00000" after 10 ns;
         wait for 20 ns;
         wait;
     end process;

и мы получаем:

add_and_sub.png (кликабельно)

Мы обнаруживаем, что получили событие a и b, но sum не изменилось.

И причина почему видна в постановке дела в процессе. Значение режима по умолчанию — «U», а в операторе case есть варианты для 0, 1 и:

   when others =>  
    --   
  end case;  

И выбор других не приводит к новому значению в mode.

Почему ничего не работает, можно узнать, прочитав исходный код тела пакета std_logic_1164, xor_table, and_table, or_table. С mode = 'U' все ваши комбинаторные выходы будут 'U'.

И чтобы исправить это, вы можете назначить значение по умолчанию для mode, где оно объявлено в тестовом стенде:

signal mode : std_logic := '0';

Когда mode определено как допустимый выбор, приводящий к некоторому действию, мы отмечаем, что xa теперь никогда не определяется, вызывая ту же проблему:

введите здесь описание изображения (кликабельно)

И это проблема в процессе:

 process(a, b, mode)
 begin
  as <= a(4);
  bs <= b(4);

  xa <= a(3 downto 0);
  xb <= b(3 downto 0);  

  case mode is
   when '0' =>
     if ((as xor bs) = '1') then                   
       mode <= '1';
       xa <= sum;       
       avf <= '0';
       if (e = '1') then
         if (xa = "0000") then
           as <= '0';
         end if;
       else           
         xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
         as <= not as;
       end if; 
     else
       xa <= sum;
     end if;   

   when '1' =>
     if ((as xor bs) = '1') then              
       mode <= '0';       
       xa <= sum;       
       avf <= e;        
     else       
       avf <= '0';
       xa <= sum;
       if (e = '1') then
         if (xa = "0000") then
           as <= '0';
         end if;
       else
         xa <= std_logic_vector(unsigned(not xa) + unsigned'("0001"));
         as <= not as;
       end if;      
     end if;
   when others =>  
    --   
  end case; 

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

Так как же решить эту головоломку? Есть две возможности. Во-первых, вы не могли попытаться выполнить алгоритмическую генерацию стимула, явно назначая входные данные add с операторами ожидания между последовательными присвоениями различных значений. Вы также можете вставлять задержки между последовательными назначениями одного и того же сигнала в существующем процессе, что требует существенной перезаписи.

Положительным моментом является то, что adder_4_bit и full_adder_1bit выглядят так, как будто они должны работать. Проблема, кажется, все в тестовом стенде.

person Community    schedule 26.05.2015
comment
Спасибо, я забыл сказать, что я использую ModelSim, и я использую его симуляцию для тестирования своего кода, сначала я принуждаю значения A, B и Mode, затем запускаю его, чтобы получить результат и волну, но для суммы значений результат неверен, и как вы говорите, что у моего процесса есть проблемы; Так как же решить эту головоломку? Есть две возможности: Можно ли привести пример? - person G3ntle_Man; 27.05.2015
comment
Я знаю, что у меня должен быть блок управления для каждой последовательности алгоритма; например, каждая последовательность выполняется с компонентом и управляющим битом на нем, но я не знаю, как это сделать! - person G3ntle_Man; 27.05.2015

я внес некоторые изменения

Я сделал блок ALU как:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY ALU IS
  PORT(
    --Clk  : IN STD_LOGIC;
    A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
    Sel  : IN STD_LOGIC;
    AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
    AsO  : OUT STD_LOGIC
  );  
END ALU;

ARCHITECTURE Declare OF ALU IS
COMPONENT Adder_4_Bit IS
  PORT(
    A, B : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    Mode : IN STD_LOGIC;
    Sum  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    COut : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL As, Bs, E, AVF : STD_LOGIC;
SIGNAL XA, XB, Sum : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Mode : STD_LOGIC;

BEGIN  

 Add : Adder_4_Bit
 PORT MAP(XA, XB, Mode, Sum, E);  

 PROCESS
 BEGIN

 As <= A(4);
 Bs <= B(4);

 XA <= A(3 DOWNTO 0);
 XB <= B(3 DOWNTO 0);  

  CASE Sel IS
   WHEN '0' =>
     IF ((As XOR Bs) = '1') THEN                  
       Mode <= '1';              
       AVF <= '0';
       WAIT ON Sum;
       IF (E = '1') THEN
         IF (Sum = "0000") THEN
           As <= '0';
         END IF;
       ELSE          
         Sum <= (NOT Sum) + "0001";
         As <= NOT As;
       END IF;
     ELSE
       Mode <= '0';
       WAIT ON Sum;
     END IF;

     AOut <= Sum;
     AsO  <= As;  

   WHEN '1' =>
     IF ((As XOR Bs) = '1') THEN              
       Mode <= '0';
       WAIT ON Sum;                    
       AVF <= E;        
     ELSE      
       Mode <= '1';
       WAIT ON Sum;
       AVF <= '0';
       IF (E = '1') THEN
         IF (Sum = "0000") THEN
           As <= '0';
         END IF;
       ELSE
         Sum <= (NOT Sum) + "0001";
         As <= NOT As;
       END IF;      
     END IF;
     AOut <= Sum;
     AsO  <= As;
   WHEN Others =>  
    --  
  END CASE;

 END PROCESS;

END Declare;

и испытательный стенд, подобный этому:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.ALL;

ENTITY ALU_Test_Bench IS

END ALU_Test_Bench;

ARCHITECTURE Declare OF ALU_Test_Bench IS
COMPONENT ALU IS
  PORT(
    --Clk  : IN STD_LOGIC;
    A, B : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
    Sel  : IN STD_LOGIC;
    AOut : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
    AsO  : OUT STD_LOGIC
  );  
END COMPONENT;

SIGNAL Xs, S : STD_LOGIC;
SIGNAL X, Y, O : STD_LOGIC_VECTOR(4 DOWNTO 0);

BEGIN

  ALU_PM : ALU PORT MAP(X, Y, S, O, Xs);

  Main_Process : PROCESS
  BEGIN      
   WAIT FOR 100 ns;  
   X <= "00010";
   Y <= "11011";

   S <= '0';
   WAIT FOR 30 ns;
   S <= '1';
   WAIT FOR 30 ns;

   WAIT FOR 100 ns;  
   X <= "01110";
   Y <= "10011";

   S <= '0';
   WAIT FOR 30 ns;
   S <= '1';
   WAIT FOR 30 ns;

   WAIT FOR 100 ns;  
   X <= "10011";
   Y <= "11111";

   S <= '0';
   WAIT FOR 30 ns;
   S <= '1';
   WAIT FOR 30 ns;

  END PROCESS;

END Declare;

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

есть какая-то проблема...

например, когда я имитирую и запускаю тестовый стенд, в O и X нет выходного значения!

Я знаю, что проблема в ALU и тестовом стенде

Я много раз менял ALU и тестировал множество способов, но всегда что-то идет не так!

Если вы хотите закодировать тот алгоритм, какие блоки вы будете создавать или вообще что вы будете создавать?! и как вы будете это кодировать?!

Спасибо за вашу помощь ...

person G3ntle_Man    schedule 14.06.2015