library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ------------------------------------------------------------------------------- -- This module implements an arithmetic unit. The width of the operands is -- determined by the generic OPERAND_WIDTH. -- Opcode width is fixed at 2 bits. -- The output is synchronous (registered, produced on rising edge of clock). ------------------------------------------------------------------------------- entity arithmetic_module is Generic ( OPERAND_WIDTH : integer := 2 ); Port ( operation : in std_logic_vector(1 downto 0); operandA : in std_logic_vector(OPERAND_WIDTH-1 downto 0); operandB : in std_logic_vector(OPERAND_WIDTH-1 downto 0); result : out std_logic_vector(OPERAND_WIDTH-1 downto 0) ); end arithmetic_module; architecture arithmetic_module_arch of arithmetic_module is -- declare math opcode constants constant ADD : std_logic_vector(1 downto 0) := "00"; constant SUB : std_logic_vector(1 downto 0) := "01"; constant MUL : std_logic_vector(1 downto 0) := "10"; constant NEG : std_logic_vector(1 downto 0) := "11"; -- Declare a zero constant for negation constant ZERO : std_logic_vector(OPERAND_WIDTH-1 downto 0) := (others => '0'); -- multiplication returns a result with length = sum of lengths of operands signal ext_result : std_logic_vector(OPERAND_WIDTH*2-1 downto 0); begin ------------------------------------------------------------------------------- -- This process evaluates the operation specified by opcode on the operands -- operand1 and operand2 (or just operand1 for unary operators). ------------------------------------------------------------------------------- EVAL_ARITH: process(operandA, operandB, operation) begin case operation is -- perform addition when ADD => ext_result(OPERAND_WIDTH-1 downto 0) <= operandA + operandB; -- perform subtraction when SUB => ext_result(OPERAND_WIDTH-1 downto 0) <= operandA - operandB; -- perform multiplication when MUL => ext_result <= operandA * operandB; -- perform mathematical negation when NEG => ext_result(OPERAND_WIDTH-1 downto 0) <= ZERO - operandA; -- cover all cases not explicitly stated in case statement when others => ext_result <= (others => '0'); end case; end process EVAL_ARITH; -- get the part of the result that we care about -- If we were designing a proper ALU, we should check -- the upper bits to detect over/underflow result <= ext_result(OPERAND_WIDTH-1 downto 0); end arithmetic_module_arch;