Код
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU is
generic(
MIN:integer:=-255; -- не всегда совпадает с 2**DATA_WIDTH
MAX:integer:=255;
DATA_WIDTH:integer:=9
);
Port ( RST : in STD_LOGIC;
CLK : in STD_LOGIC;
A : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
B : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
C : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
R : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
OPCODE : in STD_LOGIC_VECTOR (2 downto 0));
end ALU;
architecture Behavioral of ALU is
signal i_result,i_rmul: signed(DATA_WIDTH*2-1 downto 0);
signal i_A,i_B,i_C: STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
begin
process (CLK,RST)
begin
if RST='1' then
i_result<=(others=>'0');
i_rmul<=(others=>'0');
i_A<=(others=>'0');
i_B<=(others=>'0');
i_C<=(others=>'0');
else
if (rising_edge(CLK)) then
i_A<=A;
i_B<=B;
i_C<=C;
case OPCODE is
when "000" => --- R=0
i_result<=to_signed(0,DATA_WIDTH*2);
i_rmul<=to_signed(0,DATA_WIDTH*2);
when "001" => --- R=R+(A*B)
i_rmul<=(signed(i_A)*signed(i_B));
i_result<=resize(i_result+i_rmul,DATA_WIDTH*2);
when "010" => --- R=C+(A*B)
i_rmul<=(signed(i_A)*signed(i_B));
i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2);
when "011" => --- R=R+(A+B)
i_rmul<=(signed(i_A)+signed(i_B));
i_result<=resize(i_result+i_rmul,DATA_WIDTH*2);
when "100" => --- R=C+(A+B)
i_rmul<=(signed(i_A)+signed(i_B));
i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2);
when others => --- default do nothing
i_result<=i_result;
i_rmul<= i_rmul;
end case;
end if;
end if;
if i_result<MIN then R <=std_logic_vector(to_signed(MIN,DATA_WIDTH));
elsif i_result>MAX then R <=std_logic_vector(to_signed(MAX,DATA_WIDTH));
else R<=std_logic_vector(i_result(DATA_WIDTH-1 downto 0));
end if;
end process;
end Behavioral;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU is
generic(
MIN:integer:=-255; -- не всегда совпадает с 2**DATA_WIDTH
MAX:integer:=255;
DATA_WIDTH:integer:=9
);
Port ( RST : in STD_LOGIC;
CLK : in STD_LOGIC;
A : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
B : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
C : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
R : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
OPCODE : in STD_LOGIC_VECTOR (2 downto 0));
end ALU;
architecture Behavioral of ALU is
signal i_result,i_rmul: signed(DATA_WIDTH*2-1 downto 0);
signal i_A,i_B,i_C: STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
begin
process (CLK,RST)
begin
if RST='1' then
i_result<=(others=>'0');
i_rmul<=(others=>'0');
i_A<=(others=>'0');
i_B<=(others=>'0');
i_C<=(others=>'0');
else
if (rising_edge(CLK)) then
i_A<=A;
i_B<=B;
i_C<=C;
case OPCODE is
when "000" => --- R=0
i_result<=to_signed(0,DATA_WIDTH*2);
i_rmul<=to_signed(0,DATA_WIDTH*2);
when "001" => --- R=R+(A*B)
i_rmul<=(signed(i_A)*signed(i_B));
i_result<=resize(i_result+i_rmul,DATA_WIDTH*2);
when "010" => --- R=C+(A*B)
i_rmul<=(signed(i_A)*signed(i_B));
i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2);
when "011" => --- R=R+(A+B)
i_rmul<=(signed(i_A)+signed(i_B));
i_result<=resize(i_result+i_rmul,DATA_WIDTH*2);
when "100" => --- R=C+(A+B)
i_rmul<=(signed(i_A)+signed(i_B));
i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2);
when others => --- default do nothing
i_result<=i_result;
i_rmul<= i_rmul;
end case;
end if;
end if;
if i_result<MIN then R <=std_logic_vector(to_signed(MIN,DATA_WIDTH));
elsif i_result>MAX then R <=std_logic_vector(to_signed(MAX,DATA_WIDTH));
else R<=std_logic_vector(i_result(DATA_WIDTH-1 downto 0));
end if;
end process;
end Behavioral;