[英]Carry/Borrow in VHDL ALU
我正在VHDL中制作通用的N位ALU。 我在分配加法或减法借用进位值时遇到麻烦。 我尝试了以下方法:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity alu is
generic(n: integer :=1); --Default to 1
port (
a : in std_logic_vector(n-1 downto 0);
b : in std_logic_vector(n-1 downto 0);
op : in std_logic_vector(1 downto 0);
output : out std_logic_vector(n-1 downto 0);
carryborrow: out std_logic
);
end alu;
architecture Behavioral of alu is
signal result: std_logic_vector(n downto 0);
begin
process( a, b, op )
begin
case op is
when "00" =>
result(n) <= '0';
result(n-1 downto 0) <= a and b; --and gate
output <= result(n-1 downto 0);
carryborrow <= '0';
when "01" =>
result(n) <= '0';
result(n-1 downto 0) <= a or b; --or gate
output <= result(n-1 downto 0);
carryborrow <= '0';
when "10" =>
result(n) <= '0';
result(n-1 downto 0) <= std_logic_vector(signed(a) + signed(b)); --addition
output <= result(n-1 downto 0);
carryborrow <= result(n);
when "11" =>
result(n) <= '0';
result(n-1 downto 0) <= std_logic_vector(signed(a) - signed(b)); --subtraction
output <= result(n-1 downto 0);
carryborrow <= result(n);
when others =>
NULL;
end case;
end process;
end Behavioral;
这似乎将carryborrow
位carryborrow
位设置为始终为0。如何将其分配给应该没有类型错误的内容?
您的代码中有错误:
i)您没有考虑到信号不会立即更新的事实。 因此,以下几行将不符合您的预期:
result(n) <= '0';
result(n-1 downto 0) <= a and b; --and gate
output <= result(n-1 downto 0);
取而代之的是,您需要将驱动output
和carryborrow
借位的线放在组合过程之外,如下所示。 ii)假设您希望此代码是可综合的,只需将NULL
放入always分支中将导致推断出锁存器。 您还需要在other分支中驱动result
。
因此,假设您的进位输出如何与and
和or
运算相符,这就是我编写代码的方式:
architecture Behavioral of alu is
signal result: std_logic_vector(n downto 0);
begin
process( a, b, op )
begin
case op is
when "00" =>
result <= '0' & (a and b); --and gate
when "01" =>
result <= '0' & (a or b); --or gate
when "10" =>
result <= std_logic_vector(resize(signed(a), n+1) + resize(signed(b), n+1)); --addition
when "11" =>
result <= std_logic_vector(resize(signed(a), n+1) - resize(signed(b), n+1)); --subtraction
when others =>
result <= (others => 'X');
end case;
end process;
output <= result(n-1 downto 0);
carryborrow <= result(n);
end Behavioral;
我通常这样做:
result <= std_logic_vector(signed(a(n-1) & a) + signed(b(n-1) & b));
result <= std_logic_vector(signed(a(n-1) & a) - signed(b(n-1) & b));
当结果加长一位时,请扩展符号,然后进行操作以防止溢出。
嗯,在4位环境中考虑这个问题,例如a="0101"
和b="1001"
。 添加它们应得到output="1110"
,不带进位。
但是,以resize(signed(a), n+1)
和resize(signed(b), n+1)
扩展的resize(signed(a), n+1)
将设置a="00101"
和b="11001"
,从而设置result="11110"
和进位carryborrow='1'
,这是错误的!
通过符号扩展向量a
和b
,数字范围已增加到5位,因此result
必须是6位才能保持进位,然后回到平方。 向量a
和b
只能进行零扩展,即在将它们添加到result
之前为'0' & a
和'0' & b
,然后carryborrow
位carryborrow
位作为result
MSB(最高有效位)将获得正确的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.