我创建了一个4位加法器,现在我想添加和将sub 2寄存器作为符号幅度值
因此,有两个名为A和B的寄存器,两个名为As和B的位在A和B中具有值的符号位,一个用于对B进行2补码减法的XOR门,最终结果应存储在A和As中(value和Sign)和名为AVF的寄存器中的溢出位
这是一个简单的图:

模式= 1 =>子; Mod = 0 =>添加
我写了这个代码:
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;
FSum : 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;
Run Code Online (Sandbox Code Playgroud)
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;
C : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
D : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Cs : IN STD_LOGIC;
Ds : IN STD_LOGIC;
Mode_ALU : IN STD_LOGIC;
Sum_ALU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
AVF : 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 E, Temp_Cs, Temp_Ds : STD_LOGIC;
SIGNAL Temp_S : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
Add : Adder_4_Bit PORT MAP(C, D, Mode_ALU, Temp_S, E);
-- Sum_ALU <= Temp_S;
-- Temp_Cs <= Cs;
-- Temp_Ds <= Ds;
PROCESS
BEGIN
WAIT FOR 30 ns;
Sum_ALU <= Temp_S;
Temp_Cs <= Cs;
Temp_Ds <= Ds;
END PROCESS;
PROCESS(C, D, Cs, Ds, Mode_ALU)
BEGIN
CASE Mode_ALU IS
WHEN '0' =>
IF ((Cs XOR Ds) = '1') THEN
AVF <= '0';
IF (E = '1') THEN
IF (Temp_S = "0000") THEN
Temp_Cs <= '0';
END IF;
ELSE
Sum_ALU <= (NOT Temp_S) + "0001";
Temp_Cs <= NOT Cs;
END IF;
ELSE
AVF <= E;
END IF;
WHEN '1' =>
IF ((Cs XOR Ds) = '1') THEN
AVF <= E;
ELSE
AVF <= '0';
IF (E = '1') THEN
IF (Temp_S = "0000") THEN
Temp_Cs <= '0';
END IF;
ELSE
Sum_ALU <= (NOT Temp_S) + "0001";
Temp_Cs <= NOT Cs;
END IF;
END IF;
WHEN Others =>
--
END CASE;
END PROCESS;
END Declare;
Run Code Online (Sandbox Code Playgroud)
试验台 :
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;
C : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
D : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Cs : IN STD_LOGIC;
Ds : IN STD_LOGIC;
Mode_ALU : IN STD_LOGIC;
Sum_ALU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
AVF : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL Xs, Ys, M, Av : STD_LOGIC;
SIGNAL X, Y, O : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
ALU_PM : ALU PORT MAP(X, Y, Xs, Ys, M, O, Av);
Mode_Process : PROCESS
BEGIN
M <= '1';
WAIT FOR 10 ns;
M <= '0';
WAIT FOR 10 ns;
END PROCESS;
Calc_Process : PROCESS
BEGIN
X <= "0010";
Y <= "1011";
Xs <= '0';
Ys <= '1';
WAIT FOR 20 ns;
X <= "0110";
Y <= "0011";
Xs <= '1';
Ys <= '1';
WAIT FOR 20 ns;
X <= "0010";
Y <= "1011";
Xs <= '0';
Ys <= '1';
WAIT FOR 20 ns;
END PROCESS;
END Declare;
Run Code Online (Sandbox Code Playgroud)
当我运行测试平台时,结果值填充为'X':

我知道问题出在ALU中,但是我找不到问题。
我测试过4位加法器没有问题。
另一个问题是结果的calc符号位,我写的过程正确吗?
我应该怎么做才能编码上面的图?
谢谢 ...
您有信号的多个驱动器Sum_ALU,Temp_Cs并Temp_Ds在文件alu.vhd。
PROCESS
BEGIN
WAIT FOR 30 ns;
Sum_ALU <= Temp_S;
Temp_Cs <= Cs;
Temp_Ds <= Ds;
END PROCESS;
PROCESS(C, D, Cs, Ds, Mode_ALU)
BEGIN
CASE Mode_ALU IS
WHEN '0' =>
IF ((Cs XOR Ds) = '1') THEN
AVF <= '0';
IF (E = '1') THEN
IF (Temp_S = "0000") THEN
Temp_Cs <= '0';
END IF;
ELSE
Sum_ALU <= (NOT Temp_S) + "0001";
Temp_Cs <= NOT Cs;
END IF;
ELSE
AVF <= E;
END IF;
WHEN '1' =>
IF ((Cs XOR Ds) = '1') THEN
AVF <= E;
ELSE
AVF <= '0';
IF (E = '1') THEN
IF (Temp_S = "0000") THEN
Temp_Cs <= '0';
END IF;
ELSE
Sum_ALU <= (NOT Temp_S) + "0001";
Temp_Cs <= NOT Cs;
END IF;
END IF;
WHEN Others =>
--
END CASE;
END PROCESS;
Run Code Online (Sandbox Code Playgroud)
每当您在多个过程中分配信号时(如此处所做的那样),就会产生多个驱动程序。如果驱动程序不同意该值(例如,一个驱动器为“ 1”,另一个驱动器为“ 0”),则结果不确定(“ X”)。您将必须自行解决问题,因为我不确定什么是正确的行为。但是,如果删除第一个过程,则模拟中不会出现未定义的信号。
此外,您应注意该语句wait for 30 ns;不可综合。合成器可能会失败,或者只是忽略wait语句。如果您的目标是模拟路由延迟,则您的用法很好,否则,如果目标是综合,则应更改逻辑。
最后,您的第二个过程将在合成后生成闩锁。锁存器是一种存储元件,使用不当会破坏电路。它们是电路行为与仿真不匹配的主要原因,应将其删除。只要您在组合过程中分配的信号没有在过程的每个路径中分配,就会出现闩锁。这意味着Temp_Cs并且Sum_ALU每次评估过程时都需要分配一个任务(AVF按原样进行);每个if都必须有一个else,并且必须分配所有信号。一种简单的处理方法是在过程开始时提供默认值,以便每个信号都有一个分配。如果在过程评估中多次分配信号,则只有最后一次分配才有效。例如:
PROCESS(C, D, Cs, Ds, Mode_ALU)
BEGIN
Temp_Cs <= Cs;
Sum_ALU <= Temp_S;
CASE Mode_ALU IS
Run Code Online (Sandbox Code Playgroud)
虽然others没有必要在案例分支中进行分配,但是我还是建议您这样做。例如,您可以分配所有信号'X'。