我必须创建一个ALU,该ALU具有添加,无符号,子,子无符号和,或xor,或slt和slt无符号的条件。我很难实现包含未签名条件的设计。我已经在代码中指出了发生错误的位置。而且,ALU的其他所有方面都可以正常工作,只有我需要帮助的未签名部分。我正在研究unsigned和std_logic,但找不到类似于我的问题。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;
entity ALU is
Port (A, B : in STD_LOGIC_VECTOR (31 downto 0);
ALUCntl : in STD_LOGIC_VECTOR (3 downto 0);
Carryin : in STD_LOGIC;
ALUOut : out STD_LOGIC_VECTOR (31 downto 0);
Zero : out STD_LOGIC;
Carryout : out STD_LOGIC;
Overflow : out STD_LOGIC);
end ALU;
architecture Behavioral of ALU is
signal ALU_Result, slt : std_logic_vector (31 downto 0);
signal add_result,sub_result,a32,b32: std_logic_vector(32 downto 0);
signal c32: std_logic_vector(32 downto 0):=(others=>'0');
signal add_ov,sub_ov:std_logic;
-- create separate signal for unsigned
signal add_u,sub_u,a32u,b32u: unsigned(32 downto 0);
begin
with ALUCntl select
ALU_Result <=add_result(31 downto 0) when "0010", -- add
sub_result(31 downto 0) when "0110", -- sub
slt when "0111", -- set less than
----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
add_u(31 downto 0) when "0100", -- add unsigned
sub_u(31 downto 0) when "0101", -- sub unsigned
-------------------------------------------------------------------
A AND B when "0000",
A OR B when "0001",
A XOR B when "0011",
A NOR B when "1100",
A when others;---condition for all other alu control signals
ALUOut <= ALU_Result;
----Set less than-----------------------------------
process(a32,b32)
begin
if (a32 < b32) then
slt <= x"00000001";
else
slt <= x"00000000";
end if;
end process;
----Addition Operation and carry out generation-----
a32 <='0'& A;
b32 <='0'& B;
c32(0)<=Carryin;
add_result<=a32 + b32 + c32;
sub_result<=a32 - b32;
-- Getting "'0' definitions found" errors here --
a32u <='0'& A;
b32u <='0'& B;
add_u<=a32u + b32u + c32;
sub_u<=a32u - b32u;
-------------------------------------------------
---Zero flag-----------------------------
Zero <= '1' when ALU_Result =x"00000000" else '0';
---Overflow flag---------------------------------------
add_ov<= (A(31)and B(31) and (not alu_result(31))) or ((not A(31))and (not B(31)) and alu_result(31));
sub_ov<= (A(31)and (not B(31)) and (not alu_result(31))) or ((not A(31))and B(31) and alu_result(31));
with ALUCntl select
Overflow<= add_ov when "0010",
sub_ov when "0110",
'Z' when others;
---Carryout-------------------------------------------------
With ALUCntl select
Carryout<= add_result(32) when "0010",
sub_result(32) when "0110",
'Z' when others;
end Behavioral;
我已经仔细阅读了。主要问题是类型转换,因此我评论了添加它们的位置。我还通过添加命令名称常量和用于命令选择的case语句,对一些代码进行了调整,以使其更具可读性。 std_logic_unsigned
是已弃用的非标准库。
library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_unsigned.all; -- Not advisable to use this non standard library.
use ieee.numeric_std.all;
entity ALU is
generic
(
ALU_BITS: natural := 32 -- Added a generic parameter to specify the number of bits in the ALU.
);
port
(
A, B : in std_logic_vector (ALU_BITS - 1 downto 0);
ALUCntl : in std_logic_vector (3 downto 0);
Carryin : in std_logic;
ALUOut : out std_logic_vector (ALU_BITS - 1 downto 0);
Zero : out std_logic;
Carryout : out std_logic;
Overflow : out std_logic
);
end ALU;
architecture Behavioral of ALU is
-- Added some constants to make the code more readable.
constant ALU_MSB: natural := ALU_BITS - 1;
constant CMD_ADD : std_logic_vector := "0010";
constant CMD_SUB : std_logic_vector := "0110";
constant CMD_SLT : std_logic_vector := "0111";
constant CMD_ADD_U : std_logic_vector := "0100";
constant CMD_SUB_U : std_logic_vector := "0101";
constant CMD_AND : std_logic_vector := "0000";
constant CMD_OR : std_logic_vector := "0001";
constant CMD_XOR : std_logic_vector := "0011";
constant CMD_NOR : std_logic_vector := "1100";
signal ALU_Result, slt: std_logic_vector (ALU_MSB downto 0);
signal add_result, sub_result, a32, b32: std_logic_vector(ALU_BITS downto 0);
signal c32: std_logic_vector(ALU_BITS downto 0) := (others => '0');
signal add_ov, sub_ov: std_logic;
-- create separate signal for unsigned
signal add_u, sub_u, a32u, b32u: unsigned(ALU_BITS downto 0);
begin
-- Alternative command selection using a case statement.
process(ALUCntl, add_result, add_ov, sub_result, sub_ov, slt, add_u, sub_u, A, B)
begin
case ALUCntl is
when CMD_ADD => ALU_Result <= add_result(ALU_MSB downto 0);
Carryout <= add_result(ALU_BITS);
Overflow <= add_ov;
when CMD_SUB => ALU_Result <= sub_result(ALU_MSB downto 0);
Carryout <= sub_result(ALU_BITS);
Overflow <= sub_ov;
when CMD_SLT => ALU_Result <= slt;
when CMD_ADD_U => ALU_Result <= std_logic_vector(add_u(ALU_MSB downto 0)); -- Added type conversion.
when CMD_SUB_U => ALU_Result <= std_logic_vector(sub_u(ALU_MSB downto 0)); -- Added type conversion.
when CMD_AND => ALU_Result <= A and B;
when CMD_OR => ALU_Result <= A or B;
when CMD_XOR => ALU_Result <= A xor B;
when CMD_NOR => ALU_Result <= A nor B;
when others => ALU_Result <= A;
end case;
end process;
-- with ALUCntl select
-- ALU_Result <= add_result(31 downto 0) when "0010", -- add
-- sub_result(31 downto 0) when "0110", -- sub
-- slt when "0111", -- set less than
-- ----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
-- std_logic_vector(add_u(31 downto 0)) when "0100", -- add unsigned -- Added type conversion.
-- std_logic_vector(sub_u(31 downto 0)) when "0101", -- sub unsigned -- Added type conversion.
-- -------------------------------------------------------------------
-- A AND B when "0000",
-- A OR B when "0001",
-- A XOR B when "0011",
-- A NOR B when "1100",
-- A when others;---condition for all other alu control signals
ALUOut <= ALU_Result;
----Set less than-----------------------------------
process(a32, b32)
begin
if (a32 < b32) then
slt <= x"00000001";
else
slt <= x"00000000";
end if;
end process;
----Addition Operation and carry out generation-----
a32 <= '0' & A;
b32 <= '0' & B;
c32(0) <= Carryin;
add_result <= std_logic_vector(signed(a32) + signed(b32) + signed(c32)); -- Added type conversion.
sub_result <= std_logic_vector(signed(a32) - signed(b32)); -- Added type conversion.
-- Getting "'0' definitions found" errors here --
a32u <= unsigned('0' & A); -- Added type conversion.
b32u <= unsigned('0' & B); -- Added type conversion.
add_u <= a32u + b32u + unsigned(c32); -- Added type conversion.
sub_u <= a32u - b32u;
-------------------------------------------------
---Zero flag-----------------------------
Zero <= '1' when ALU_Result = x"00000000" else '0';
---Overflow flag---------------------------------------
add_ov <= (A(31)and B(31) and (not alu_result(31))) or ((not A(31))and (not B(31)) and alu_result(31));
sub_ov <= (A(31)and (not B(31)) and (not alu_result(31))) or ((not A(31))and B(31) and alu_result(31));
-- Moved to the case statement above.
-- with ALUCntl select
-- Overflow <= add_ov when "0010",
-- sub_ov when "0110",
-- 'Z' when others;
---Carryout-------------------------------------------------
-- Moved to the case statement above.
-- With ALUCntl select
-- Carryout <= add_result(32) when "0010",
-- sub_result(32) when "0110",
-- 'Z' when others;
end Behavioral;
因此,无需查看细节,我可以告诉您为什么您遇到第一个错误的编译问题。首先,让我们看看您的信号。它们都被声明为无符号类型。
signal add_u,sub_u,a32u,b32u: unsigned(32 downto 0);
但是,您的ALUOut
输出端口是STD_LOGIC_VECTOR
类型。您会遇到问题,因为signed
与STD_LOGIC_VECTOR
不同。幸运的是,在这些类型之间进行转换非常容易。实际上,我一直都方便this nandland conversion cheatsheet。
尝试以下操作。它应该将您的签名类型转换为STD_LOGIC_VECTOR。
ALU_Result <=add_result(31 downto 0) when "0010", -- add
sub_result(31 downto 0) when "0110", -- sub
slt when "0111", -- set less than
----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
STD_LOGIC_VECTOR(add_u(31 downto 0)) when "0100", -- add unsigned
STD_LOGIC_VECTOR(sub_u(31 downto 0)) when "0101", -- sub unsigned
因此,作为速成课程的回顾,我将描述我对std_logic_vector,有符号和无符号的看法。再一次,nandland has a good review of these types。这是我的想象:
std_logic_vector
不知道STD_LOGIC的矢量应该是带符号的表示还是无符号的表示。因此,任何加法,减法和乘法运算均不起作用。signed
将std_logic的向量解释为使用二进制补码形式。这允许将带符号的类型加,减和乘在一起]unsigned
与有符号相似,但假定整数是无符号表示。 如果您尝试不使用signed
或unsigned
进行分配,那么您将需要实现逻辑。但是,您可以让有符号和无符号类型为您实现逻辑。
因此,我们添加两种类型的std_logic_vector
。如下所示,我将A和B向量转换为有符号/无符号,然后转换回std_logic_vector
。
signal A, B: std_logic_vector(31 downto 0);
signal result: std_logic_vector(31 + 1 downto 0);
-- Lets add them together as though they were unsigned
-- We pad a 0 to the end of the value to extend its length
result <= std_logic_vector(unsigned('0' & A) + unsigned(B));
-- Lets add them together as though they were signed
-- We copy the last bit of A for signed values
result <= std_logic_vector(signed((A(31) & & A) + signed(B));
我希望这会有所帮助!