library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ------------------------------------------------------------------------------- -- This module is the top level of the ALU design. It contains structural code -- only. Operand width is determined by the generic OPERAND_WIDTH. -- Opcode width is fixed at 3 bits. The MSB (opcode(2)) determines whetehr -- an instruction is an arithmatic or logical operation. arithmetic=1, logic=0. -- The calculation is synchronous (registered, produced on rising edge of clock) -- and the ouput then passes through a combinatorial mux. ------------------------------------------------------------------------------- entity alu is Generic ( -- Generics are like constants for a component, but they can be set -- by a higher level module when the component is instantiated. -- Default values are usually given, in which case the higher -- level does not need to explicitly provide a value. -- Generics are useful to allow flexible, reuseable code. -- In this case, we have an ALU that can be instantiated to take -- any width of operands, and the given width is passed to lower -- levels though their generics. OPERAND_WIDTH : integer := 4 ); Port ( -- The input/ouput interface of the module opcode : in std_logic_vector(2 downto 0); operand1 : in std_logic_vector(OPERAND_WIDTH-1 downto 0); operand2 : in std_logic_vector(OPERAND_WIDTH-1 downto 0); alu_result : out std_logic_vector(OPERAND_WIDTH-1 downto 0) ); end alu; architecture alu_arch of alu is ----------------------------------------------------------------------------- -- All the components that are being used must be declared -- beforehand. This occurs here, prior to the begin statement. ----------------------------------------------------------------------------- -- The arithmetic alu component (from arithmetic_module.vhd) component arithmetic_module Generic ( OPERAND_WIDTH : integer ); 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 component; -- The logic alu component (from logic_module.vhd) component logic_module Generic ( OPERAND_WIDTH : integer ); 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 component; -- The 2-to-1 multiplexer (from alu_mux.vhd) component mux Generic ( DATA_WIDTH : integer ); Port ( selection : in std_logic; inputA : in std_logic_vector(DATA_WIDTH-1 downto 0); inputB : in std_logic_vector(DATA_WIDTH-1 downto 0); output : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end component; -- signals we need to connect the math and logic components to the -- output multiplexer signal arith_result : std_logic_vector(OPERAND_WIDTH-1 downto 0); signal logic_result : std_logic_vector(OPERAND_WIDTH-1 downto 0); begin -- instantiate the arithmetic part of the alu Inst_arithmetic_module: arithmetic_module Generic Map ( -- here we set the generic so the math alu has the right size -- for it's operands. We are overriding the default value -- of 2 bits. OPERAND_WIDTH => OPERAND_WIDTH ) Port Map( -- the MSB selects arith or logic, the lower bits are the actual opcode for the unit operation => opcode(1 downto 0), operandA => operand1, operandB => operand2, result => arith_result ); -- instantiate the logic part of the alu Inst_logic_module: logic_module Generic Map ( OPERAND_WIDTH => OPERAND_WIDTH ) Port Map( operation => opcode(1 downto 0), operandA => operand1, operandB => operand2, result => logic_result ); -- instantiate the multiplexer to choose the correct output Inst_mux: mux Generic Map ( -- Notice that generic names do not need to be the same. -- You could even use a numeric constant (but that is bad style!) DATA_WIDTH => OPERAND_WIDTH ) Port Map ( selection => opcode(2), inputA => arith_result, inputB => logic_result, output => alu_result ); end alu_arch;