Line 1... |
Line 1... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- The Arithmetic Logic Unit (ALU).
|
-- The Arithmetic Logic Unit (ALU).
|
-- It contains the ALU core plus the Accumulator and the Temp Reg.
|
-- It contains the ALU core plus the Accumulator and the Temp Reg.
|
--
|
--
|
-- $Id: alu.vhd,v 1.3 2004-04-04 14:18:52 arniml Exp $
|
-- $Id: alu.vhd,v 1.4 2004-04-06 18:10:41 arniml Exp $
|
--
|
--
|
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
|
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
|
--
|
--
|
-- All rights reserved
|
-- All rights reserved
|
--
|
--
|
Line 105... |
Line 105... |
signal in_a_s,
|
signal in_a_s,
|
in_b_s : word_t;
|
in_b_s : word_t;
|
-- output of the ALU core
|
-- output of the ALU core
|
signal data_s : word_t;
|
signal data_s : word_t;
|
|
|
|
signal add_result_s : alu_operand_t;
|
|
|
begin
|
begin
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Process working_regs
|
-- Process working_regs
|
--
|
--
|
Line 186... |
Line 188... |
-- All operations defined in alu_op_t are handled here.
|
-- All operations defined in alu_op_t are handled here.
|
--
|
--
|
alu_core: process (in_a_s,
|
alu_core: process (in_a_s,
|
in_b_s,
|
in_b_s,
|
alu_op_i,
|
alu_op_i,
|
use_carry_i,
|
add_result_s)
|
carry_i,
|
|
aux_carry_i)
|
|
|
|
variable add_v : alu_operand_t;
|
|
variable c_v : std_logic;
|
|
|
|
function add_f(a, b : alu_operand_t;
|
|
c : std_logic ) return alu_operand_t is
|
|
begin
|
|
return UNSIGNED(a) + UNSIGNED(b) + CONV_UNSIGNED(c, alu_operand_t'length);
|
|
end;
|
|
|
|
begin
|
begin
|
-- default assigments
|
-- default assigments
|
data_s <= (others => '0');
|
data_s <= (others => '0');
|
carry_o <= '0';
|
carry_o <= '0';
|
Line 219... |
Line 210... |
when ALU_XOR =>
|
when ALU_XOR =>
|
data_s <= in_a_s xor in_b_s;
|
data_s <= in_a_s xor in_b_s;
|
|
|
-- Operation: Add -------------------------------------------------------
|
-- Operation: Add -------------------------------------------------------
|
when ALU_ADD =>
|
when ALU_ADD =>
|
if use_carry_i then
|
data_s <= add_result_s(data_s'range);
|
c_v := carry_i;
|
carry_o <= add_result_s(add_result_s'high);
|
else
|
|
c_v := '0';
|
|
end if;
|
|
|
|
add_v := add_f("0" & in_a_s, "0" & in_b_s, c_v);
|
|
|
|
data_s <= add_v(data_s'range);
|
|
carry_o <= add_v(add_v'high);
|
|
|
|
-- Operation: CPL -------------------------------------------------------
|
-- Operation: CPL -------------------------------------------------------
|
when ALU_CPL =>
|
when ALU_CPL =>
|
data_s <= not in_a_s;
|
data_s <= not in_a_s;
|
|
|
Line 267... |
Line 250... |
data_s(3 downto 0) <= in_a_s(7 downto 4);
|
data_s(3 downto 0) <= in_a_s(7 downto 4);
|
data_s(7 downto 4) <= in_a_s(3 downto 0);
|
data_s(7 downto 4) <= in_a_s(3 downto 0);
|
|
|
-- Operation: DEC -------------------------------------------------------
|
-- Operation: DEC -------------------------------------------------------
|
when ALU_DEC =>
|
when ALU_DEC =>
|
add_v := add_f(not ("0" & in_a_s), "000000001", '0');
|
data_s <= add_result_s(data_s'range);
|
data_s <= not add_v(data_s'range);
|
|
|
|
-- Operation: INC -------------------------------------------------------
|
-- Operation: INC -------------------------------------------------------
|
when ALU_INC =>
|
when ALU_INC =>
|
add_v := add_f("0" & in_a_s, "000000001", '0');
|
data_s <= add_result_s(data_s'range);
|
data_s <= add_v(data_s'range);
|
|
|
|
-- Operation CONCAT -----------------------------------------------------
|
-- Operation CONCAT -----------------------------------------------------
|
when ALU_CONCAT =>
|
when ALU_CONCAT =>
|
data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
|
data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
|
|
|
Line 298... |
Line 279... |
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Process aux_carry
|
-- Process adder
|
--
|
--
|
-- Purpose:
|
-- Purpose:
|
-- Calculates the Auxiliary Carry.
|
-- Implements the adder used by several instructions.
|
|
-- This way of modelling the adder forces resource sharing of:
|
|
-- * ADD
|
|
-- * INC
|
|
-- * DEC
|
--
|
--
|
aux_carry: process (in_a_s,
|
adder: process (in_a_s,
|
in_b_s,
|
in_b_s,
|
data_s)
|
alu_op_i,
|
|
carry_i,
|
|
use_carry_i)
|
|
|
|
variable add_a_v, add_b_v : alu_operand_t;
|
|
variable result_v : alu_operand_t;
|
|
variable c_v : std_logic;
|
variable aux_c_v : std_logic_vector(1 downto 0);
|
variable aux_c_v : std_logic_vector(1 downto 0);
|
|
|
begin
|
begin
|
aux_carry_o <= '0';
|
-- Carry Selection --------------------------------------------------------
|
|
if use_carry_i then
|
|
c_v := carry_i;
|
|
else
|
|
c_v := '0';
|
|
end if;
|
|
|
|
-- Operand Selection ------------------------------------------------------
|
|
-- defaults for ADD
|
|
add_a_v := '0' & in_a_s;
|
|
add_b_v := '0' & in_b_s;
|
|
|
|
case alu_op_i is
|
|
when ALU_INC =>
|
|
add_b_v := "000000001";
|
|
when ALU_DEC =>
|
|
add_b_v := "111111111";
|
|
when others =>
|
|
null;
|
|
end case;
|
|
|
|
-- The Adder --------------------------------------------------------------
|
|
result_v := UNSIGNED(add_a_v) +
|
|
UNSIGNED(add_b_v) +
|
|
CONV_UNSIGNED(c_v, alu_operand_t'length);
|
|
|
|
add_result_s <= result_v;
|
|
|
|
-- Auxiliary Carry --------------------------------------------------------
|
aux_c_v := in_a_s(4) & in_b_s(4);
|
aux_c_v := in_a_s(4) & in_b_s(4);
|
|
|
case aux_c_v is
|
case aux_c_v is
|
when "00" | "11" =>
|
when "00" | "11" =>
|
if data_s(4) = '1' then
|
if result_v(4) = '1' then
|
aux_carry_o <= '1';
|
aux_carry_o <= '1';
|
end if;
|
end if;
|
|
|
when "01" | "10" =>
|
when "01" | "10" =>
|
if data_s(4) = '0' then
|
if result_v(4) = '0' then
|
aux_carry_o <= '1';
|
aux_carry_o <= '1';
|
end if;
|
end if;
|
|
|
when others =>
|
when others =>
|
|
aux_carry_o <= '0';
|
null;
|
null;
|
|
|
end case;
|
end case;
|
|
|
end process aux_carry;
|
end process adder;
|
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
Line 396... |
Line 417... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- File History:
|
-- File History:
|
--
|
--
|
-- $Log: not supported by cvs2svn $
|
-- $Log: not supported by cvs2svn $
|
|
-- Revision 1.3 2004/04/04 14:18:52 arniml
|
|
-- add measures to implement XCHD
|
|
--
|
-- Revision 1.2 2004/03/28 21:08:51 arniml
|
-- Revision 1.2 2004/03/28 21:08:51 arniml
|
-- support for DA instruction
|
-- support for DA instruction
|
--
|
--
|
-- Revision 1.1 2004/03/23 21:31:52 arniml
|
-- Revision 1.1 2004/03/23 21:31:52 arniml
|
-- initial check-in
|
-- initial check-in
|