美好的一天,
我已经实现了一个8位CLA加/减模块,效果很好。代码如下:我在下面列出了其中两个模块来创建一个16位加法器/减法器。这个16位版本适用于加法,进位由低位的1 8位加法器产生,然后传递到下一个加法器以处理高位。
问题在于减法。它甚至在纸上都不起作用。让我给你举个例子。让我们说我想做350 - 50
300: 00000001 00101100
50: 00000000 00110010
因此,如果我让一个加法器处理低位,而另一个加法器处理高位,则它根本不起作用。原因如下:
300: 00000001 00101100
50 in 2's compliment: 11111111 11001110
250 is supposed to be 00000000 11111010
第一个加法器:加入11111010后生成正确的值。这很酷。现在第二个加法器,是一个问题。它会做(1' s恭维+ 1),它将给出00000000(带进位)。它应该是(11111111),但由于算法中的+ 1是一般实现,它搞砸了最终的答案。
右边,因为加法器0没有进位,加法器1不应该执行+ 1.我怎样才能在通用8位子/加法器的逻辑中实现它?这是正确的想法,我是否涵盖了所有可能的后果/边缘情况?
entity CLA_ADD_SUB is
generic (N : integer := 8);
Port ( A : in STD_LOGIC_VECTOR (N-1 downto 0);
B : in STD_LOGIC_VECTOR (N-1 downto 0);
Binv : in STD_LOGIC;
C_in: in STD_LOGIC;
S : out STD_LOGIC_VECTOR (N-1 downto 0);
TEST : out STD_LOGIC_VECTOR (N-1 downto 0);
C_out : out STD_LOGIC
);
end CLA_ADD_SUB;
architecture CLA_ADD_SUB_ARCH of CLA_ADD_SUB is
SIGNAL h_sum : STD_LOGIC_VECTOR(N-1 DOWNTO 0);
SIGNAL carry_generate : STD_LOGIC_VECTOR(N-1 DOWNTO 0);
SIGNAL carry_propagate : STD_LOGIC_VECTOR(N-1 DOWNTO 0);
SIGNAL carry_in_internal : STD_LOGIC_VECTOR(N-1 DOWNTO 1);
SIGNAL B_mod : STD_LOGIC_VECTOR(N-1 DOWNTO 0) := B;
SIGNAL C_in_mod: STD_LOGIC := C_in;
signal S_wider : std_logic_vector(N downto 0);
begin
WITH Binv SELECT
B_mod <= B WHEN '0',
not B WHEN '1',
B WHEN OTHERS;
WITH Binv SELECT
C_in_mod <= C_in WHEN '0',
not C_in WHEN '1',
C_in WHEN OTHERS;
-- Sum, P and G
h_sum <= A XOR B_mod;
carry_generate <= A AND B_mod;
carry_propagate <= A OR B_mod;
PROCESS (carry_generate,carry_propagate,carry_in_internal,C_in_mod)
BEGIN
carry_in_internal(1) <= carry_generate(0) OR (carry_propagate(0) AND C_in_mod);
inst: FOR i IN 1 TO (N-2) LOOP
carry_in_internal(i+1) <= carry_generate(i) OR (carry_propagate(i) AND carry_in_internal(i));
END LOOP;
C_out <= carry_generate(N-1) OR (carry_propagate(N-1) AND carry_in_internal(N-1));
END PROCESS;
S(0) <= h_sum(0) XOR C_in_mod;
S(N-1 DOWNTO 1) <= h_sum(N-1 DOWNTO 1) XOR carry_in_internal(N-1 DOWNTO 1);
end CLA_ADD_SUB_ARCH;
答案 0 :(得分:1)
问题是,你在计算50的2的补码时出错:
在你的等式中你使用:
50 in 2's compliment: 11111111 11001101 <--- WRONG.
只有50,所有位都被反转。然而,通过首先反转这些位来构建二进制补码,然后将其加一。
16位整数中-50的正确表示是:
50 in 2's compliment: 11111111 11001110
如果我们现在做300到50的数学运算,我们会得到:
00000001 00101100 | 300
+ 11111111 11001110 | -50 in 2's complement form
-------------------
00000000 11111010 | 250 (expected result)
对于VHDL实现,这意味着您可以通过重用加法部分来实现减法。为此,分两步建立两个补码:
如果是减法模式:
第二步将把一个添加到否定的B,然后是正确的二进制补码。现在你像往常一样添加你的数字并得到一个功能性减法器。
答案 1 :(得分:0)
u_ADDER_0: entity work.CLA_ADD_SUB(CLA_ADD_SUB_ARCH)
port map(
A => ADDER_0_A, -- Bits 0-7
B => ADDER_0_B,
Binv => TOADD_BINV,
C_in => ADDER_0_CARRY_IN,
S => ADDER_0_SUM,
TEST => ADDER_0_TEST,
C_out => ADDER_0_CARRY_OUT
);
u_ADDER_1: entity work.CLA_ADD_SUB(CLA_ADD_SUB_ARCH)
port map(
A => ADDER_1_A, --Bits 7 to 15
B => ADDER_1_B,
Binv => TOADD_BINV,
C_in => TOADD_BINV xor ADDER_0_CARRY_OUT,
S => ADDER_1_SUM,
TEST => ADDER_1_TEST,
C_out => ADDER_1_CARRY_OUT
);
啊,我明白了,实际上我所做的是所有后续加法器(对于第7-15位等)我将Carry设置为(Binv xor Adder_0_Carry)。因此,如果第一个加法器因为2的恭维而有一个进位,那么它将从进位中传出,并且由于我用Binv对其进行测量,我告诉第二个加法器不要添加进位。
这个想法是,如果我们减去(做2的恭维),如果第一个加法器没有进位,我们应该做(1的恭维)
我无法对所有测试用例进行确认。这只是一个理论,到目前为止似乎有效
答案 2 :(得分:0)
这是对你自己答案的补充。
嗯......如果我将B_inv设置为0,意味着我正在添加,我传入两个有符号的位。说50和-250,它将无法工作,因为第二个加法器的C_in由Binv xor Adder_0_carry确定
我认为您的手动算术有问题:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_add_sub_gang is
constant n: natural := 8;
end entity;
architecture foo of tb_add_sub_gang is
signal a: std_logic_vector (2*n-1 downto 0);
signal b: std_logic_vector (2*n-1 downto 0);
signal s: std_logic_vector (2*n-1 downto 0);
signal test: std_logic_vector (2*n-1 downto 0);
signal binv: std_logic;
signal cout0: std_logic;
signal cin1: std_logic;
signal cout1: std_logic;
begin
cin1 <= cout0 xor binv;
uadder0:
entity work.cla_add_sub(cla_add_sub_arch)
port map(
a => a((2*n-1)/2 downto 0), -- bits 0-7
b => b((2*n-1)/2 downto 0),
binv => binv,
c_in => '0',
s => s((2*n-1)/2 downto 0),
test => s((2*n-1)/2 downto 0),
c_out => cout0
);
uadder1:
entity work.cla_add_sub(cla_add_sub_arch)
port map(
a => a(2*n-1 downto n), --bits 8 to 15
b => b(2*n-1 downto n),
binv => binv,
c_in => cin1,
s => s(2*n-1 downto n),
test => test(2*n-1 downto n),
c_out => cout1
);
STIMULUS:
process
begin
wait for 100 ns;
a <= std_logic_vector(to_unsigned(350,a'length));
b <= std_logic_vector(to_unsigned(50,b'length));
binv <= '1';
wait for 100 ns;
binv <= '0';
wait for 100 ns;
a <= std_logic_vector(to_unsigned(50,a'length));
b <= std_logic_vector(to_unsigned(250,b'length));
binv <= '1';
wait for 100 ns;
binv <= '0';
wait for 600 ns;
wait;
end process;
end architecture;
给出:
(我更新了有符号减法/加法的波形图像。)
cla_add_sub
中的binv选择器相当于Binv
和C_in
之间的XOR。对于最高有效Binv
位加法器,在外部再次进行异常n
会为您提供偶数个XOR来消除其影响,并执行最低有效加法器的执行。
正确的做法实际上只是用B
反转Binv
并使用Binv
来反转LS加法器的进位。因为除了减法之外你永远不会携带它,直接将它挂钩到Binv
。这将解决所有问题。
在cla_add_sub
中发表评论:
-- WITH Binv SELECT
-- C_in_mod <= C_in WHEN '0',
-- not C_in WHEN '1',
-- C_in WHEN OTHERS;
C_in_mod
声明:
-- SIGNAL C_in_mod: STD_LOGIC := C_in;
直接使用C_in
:
PROCESS (carry_generate,carry_propagate,carry_in_internal,C_in)
BEGIN
carry_in_internal(1) <= carry_generate(0) OR (carry_propagate(0) AND C_in);
inst: FOR i IN 1 TO (N-2) LOOP
carry_in_internal(i+1) <= carry_generate(i) OR (carry_propagate(i) AND carry_in_internal(i));
END LOOP;
C_out <= carry_generate(N-1) OR (carry_propagate(N-1) AND carry_in_internal(N-1));
END PROCESS;
对于S(0)
:
S(0) <= h_sum(0) XOR C_in;
在顶层:
-- signal cin1: std_logic;
-- cin1 <= cout0 xor binv;
uadder0:
entity work.cla_add_sub(cla_add_sub_arch)
port map(
a => a((2*n-1)/2 downto 0), -- bits 0-7
b => b((2*n-1)/2 downto 0),
binv => binv,
c_in => binv,
s => s((2*n-1)/2 downto 0),
test => s((2*n-1)/2 downto 0),
c_out => cout0
);
uadder1:
entity work.cla_add_sub(cla_add_sub_arch)
port map(
a => a(2*n-1 downto n), --bits 8 to 15
b => b(2*n-1 downto n),
binv => binv,
c_in => cout,
s => s(2*n-1 downto n),
test => test(2*n-1 downto n),
c_out => cout1
);
这给出了与上面显示的相同的结果。
请注意这与Nils的回答一致。
如果你只有一个n
位加法器/减法器,你将在你的答案中使用这个方法,其中进位(LS)进位(MS)将再次被反转为将两个8位操作链接在一起。
这实例化两个恰好反转B
的加法器,即2的补语的1的补码部分,减去'B'。您可以向cla_add_sub
添加输入,表示何时是LS加法器,然后只有XOR Binv
。这样它既可以作为独立的n
位加法器,也可以作为菊花链接的。