Я прошел через это тщательно. Основная проблема заключается в преобразовании типов, поэтому я прокомментировал, где я их добавил. Я также внес некоторые изменения в код, чтобы сделать его более читабельным, добавив константы для имен команд, что, как правило, является хорошей практикой, и оператор case для выбора команд. И std_logic_unsigned
является устаревшей нестандартной библиотекой.
Я обновил ее в соответствии с вашими обновлениями к вашему первоначальному вопросу, касающемуся обработки неподписанных логи c. Я также добавил еще пару констант и три подтипа в соответствии с принципом дизайна, согласно которому только одна версия истины.
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 and subtypes to make the code more readable and maintainable.
constant ALU_MSB: natural := ALU_BITS - 1;
subtype TALURegister is std_logic_vector(ALU_MSB downto 0);
subtype TALURegisterX is std_logic_vector(ALU_BITS downto 0);
subtype TALURegisterXU is unsigned(ALU_BITS downto 0);
constant ALU_REGISTER_ZERO: TALURegister := (others => '0');
constant ALU_REGISTER_ONE : TALURegister := (ALU_MSB downto 1 => '0') & '1';
constant CMD_ADD : std_logic_vector := "0010";
constant CMD_SUB : std_logic_vector := "0110";
constant CMD_SLT : std_logic_vector := "0111";
constant CMD_SLT_U : std_logic_vector := "1000";
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, sltu : TALURegister;
signal add_result, sub_result, a32, b32: TALURegisterX;
-- create separate a and b for unsigned
signal add_u, sub_u, a32u, b32u: TALURegisterXU;
signal c32: TALURegisterX := (others => '0');
signal add_ov, sub_ov: std_logic;
begin
-- Alternative command selection using a case statement.
process(ALUCntl, add_result, sub_result, slt, sltu, add_u, sub_u, A, B)
begin
case ALUCntl is
when CMD_ADD => ALU_Result <= add_result(ALU_MSB downto 0);
when CMD_SUB => ALU_Result <= sub_result(ALU_MSB downto 0);
when CMD_SLT => ALU_Result <= slt;
when CMD_SLT_U => ALU_Result <= sltu;
when CMD_ADD_U => ALU_Result <= TALURegister(add_u(ALU_MSB downto 0)); -- Added type conversion.
when CMD_SUB_U => ALU_Result <= TALURegister(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(ALU_MSB downto 0) when CMD_ADD, -- add
-- sub_result(ALU_MSB downto 0) when CMD_SUB, -- sub
-- slt when CMD_SLT, -- set less than
-- - Getting an error that indexed name is not STD_LOGIC_VECTOR --
-- TALURegister(add_u(ALU_MSB downto 0)) when CMD_ADD_U, -- add unsigned -- Added type conversion.
-- TALURegister(sub_u(ALU_MSB downto 0)) when CMD_SUB_U, -- sub unsigned -- Added type conversion.
---------------------------------------------------------
-- sltu when CMD_SLT_U, -- set less than unsigned
-- A AND B when CMD_AND,
-- A OR B when CMD_OR,
-- A XOR B when CMD_XOR,
-- A NOR B when CMD_NOR,
-- 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 <= ALU_REGISTER_ONE;
else
slt <= ALU_REGISTER_ZERO;
end if;
end process;
----Set less than unsigned--------------------------
process(a32u, b32u)
begin
if (a32u < b32u) then
sltu <= ALU_REGISTER_ONE;
else
sltu <= ALU_REGISTER_ZERO;
end if;
end process;
----Addition Operation and carry out generation-----
a32 <= '0' & A;
b32 <= '0' & B;
c32(0) <= Carryin;
add_result <= TALURegisterX(signed(a32) + signed(b32) + signed(c32)); -- Added type conversion.
sub_result <= TALURegisterX(signed(a32) - signed(b32)); -- Added type conversion.
-- Getting "'0' definitions found" errors here --
a32u <= TALURegisterXU('0' & A); -- Added type conversion.
b32u <= TALURegisterXU('0' & B); -- Added type conversion.
add_u <= a32u + b32u + TALURegisterXU(c32); -- Added type conversion.
sub_u <= a32u - b32u;
-------------------------------------------------
---Zero flag-----------------------------
Zero <= '1' when ALU_Result = ALU_REGISTER_ZERO else '0';
---Overflow flag---------------------------------------
add_ov <= (A(ALU_MSB) and B(ALU_MSB) and (not alu_result(ALU_MSB))) or ((not A(ALU_MSB)) and (not B(ALU_MSB)) and alu_result(ALU_MSB));
sub_ov <= (A(ALU_MSB) and (not B(ALU_MSB)) and (not alu_result(ALU_MSB))) or ((not A(ALU_MSB)) and B(ALU_MSB) and alu_result(ALU_MSB));
with ALUCntl select
Overflow <=
add_ov when CMD_ADD | CMD_ADD_U,
sub_ov when CMD_SUB | CMD_SUB_U,
'Z' when others;
---Carryout-------------------------------------------------
with ALUCntl select
Carryout <=
add_result(ALU_BITS) when CMD_ADD,
sub_result(ALU_BITS) when CMD_SUB,
add_u(ALU_BITS) when CMD_ADD_U,
sub_u(ALU_BITS) when CMD_SUB_U,
'Z' when others;
end Behavioral;