VHDL:4位加法器和减法器中的错误结果

时间:2015-05-26 13:54:30

标签: logic vhdl digital-logic

我想用VHDL制作一个4位加法器和减法器 我创建了1位全加器,XOR门(用于减法)和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 Gate:

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_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 Adder_4_Bit;

ARCHITECTURE Structure OF Adder_4_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

中输出
  • 我应该使用算法中显示的寄存器,例如&#34; E&#34;和&#34; AVF&#34;

有一个问题:

我们知道端口地图是连续连接的,所以当我改变模式值时,结果(总和)必须改变,是真的吗?!

我已经尝试过这段代码,但是我无法在XA中获得输出,并且sum值没有True结果,我知道我的主代码(Process)存在一些问题,但是我找不到问题

请检查代码并告诉我出了什么问题!

修改

我正在使用ModelSim及其模拟来测试我的代码,首先强制使用&#34; A&#34;,&#34; B&#34;和&#34; Mode&#34;然后运行以获得结果并挥动

谢谢......

2 个答案:

答案 0 :(得分:1)

您的测试平台add_and_sub不会对ab进行任何分配,它们的默认值都是'U'。

当您对adder_4_bit的输入未定义时,您期望什么?

查看std_logic_1164包正文中的not_tableor_tableand_tablexor_table

同样是Minimal, Complete, and Verifiable example您的读者需要预期和实际结果。

如果你实际上正在模拟测试平台,我希望它不会消耗模拟时间,并且在初始化期间显示sume之后会有一些delta周期充满'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 (点击)

我们发现我们在ab上收到了一个活动,但sum没有改变。

原因在于流程中的案例陈述中显而易见。 mode的默认值为“U”,case语句包含01

的选项
   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现在从未定义导致同样的问题:

enter image description here (点击)

这是这个过程中的一个问题:

 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_bitfull_adder_1bit看起来应该有效。问题似乎都在测试平台中。

答案 1 :(得分:-1)

我做了一些改变

我做了一个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和Test Bench

我多次更换ALU并测试了许多方法,但有时出现问题!

如果您想对该算法进行编码,您将创建哪些单位,或者您将创建哪些单位?你将如何编码?!

感谢您的帮助......