OpenCores
URL https://opencores.org/ocsvn/t400/t400/trunk

Subversion Repositories t400

[/] [t400/] [trunk/] [rtl/] [vhdl/] [t400_alu.vhd] - Rev 179

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- The Arithmetic Logic Unit (ALU).
-- It contains the accumulator and the C flag.
--
-- $Id: t400_alu.vhd 179 2009-04-01 19:48:38Z arniml $
--
-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
--      http://www.opencores.org/cvsweb.shtml/t400/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t400_pack.all;
use work.t400_opt_pack.all;
 
entity t400_alu is
 
  generic (
    opt_cko_g : integer := t400_opt_cko_crystal_c
  );
  port (
    -- System Interface -------------------------------------------------------
    ck_i       : in  std_logic;
    ck_en_i    : in  boolean;
    por_i      : in  boolean;
    res_i      : in  boolean;
    cko_i      : in  std_logic;
    -- Control Interface ------------------------------------------------------
    op_i       : in  alu_op_t;
    -- Data Interface ---------------------------------------------------------
    m_i        : in  dw_t;
    dec_data_i : in  dec_data_t;
    q_low_i    : in  dw_t;
    b_i        : in  b_t;
    g_i        : in  dw_t;
    in_i       : in  dw_t;
    sio_i      : in  dw_t;
    a_o        : out dw_t;
    carry_o    : out std_logic;
    c_o        : out std_logic
  );
 
end t400_alu;
 
 
library ieee;
use ieee.numeric_std.all;
 
architecture rtl of t400_alu is
 
  subtype alu_dw_t     is unsigned(dw_t'high+1 downto 0);
  signal  alu_result_s : alu_dw_t;
 
  signal  a_q          : dw_t;
  signal  c_q          : std_logic;
 
begin
 
  -----------------------------------------------------------------------------
  -- Process regs
  --
  -- Purpose:
  --   Implements the sequential registers of the ALU:
  --     * A - accumulator
  --     * C - carry flag
  --
  regs: process (ck_i, por_i)
  begin
    if por_i then
      a_q <= (others => '0');
      c_q <= '0';
 
    elsif ck_i'event and ck_i = '1' then
      if res_i then
        -- synchronous reset upon external reset event
        a_q <= (others => '0');
        c_q <= '0';
 
      elsif ck_en_i then
        -- update accumulator
        case op_i is
          when ALU_CLRA    |
               ALU_ADD     |
               ALU_ADD_10  |
               ALU_ADD_C   |
               ALU_ADD_DEC |
               ALU_COMP    |
               ALU_XOR     =>
            a_q <= std_logic_vector(alu_result_s(dw_t'range));
          when ALU_LOAD_M =>
            a_q <= m_i;
          when ALU_LOAD_Q =>
            a_q <= q_low_i;
          when ALU_LOAD_G =>
            a_q <= g_i;
          when ALU_LOAD_IN =>
            a_q <= in_i;
          when ALU_LOAD_IL =>
            a_q(3) <= in_i(3);
            if opt_cko_g = t400_opt_cko_gpi_c then
              a_q(2) <= cko_i;
            else
              a_q(2) <= '1';
            end if;
            a_q(1) <= '0';
            a_q(0) <= in_i(0);
          when ALU_LOAD_BR =>
            a_q(3 downto 2) <= (others => '0');
            a_q(1 downto 0) <= b_i(br_range_t);
          when ALU_LOAD_BD =>
            a_q <= b_i(bd_range_t);
          when ALU_LOAD_SIO =>
            a_q <= sio_i;
          when others =>
            null;
        end case;
 
        -- update C flag upon the following instructions
        case op_i is
          -- carry result of addition -----------------------------------------
          when ALU_ADD_C =>
            c_q <= alu_result_s(alu_dw_t'high);
 
          -- reset C flag -----------------------------------------------------
          when ALU_RC =>
            c_q <= '0';
 
          -- set C flag -------------------------------------------------------
          when ALU_SC =>
            c_q <= '1';
 
          when others =>
            null;
        end case;
      end if;
    end if;
  end process regs;
  --
  -----------------------------------------------------------------------------
 
 
  -----------------------------------------------------------------------------
  -- Process dp
  --
  -- Purpose:
  --   Implements the ALU's data path.
  --
  dp: process (op_i,
               a_q,
               m_i,
               dec_data_i,
               c_q)
    variable in1_v,
             in2_v,
             in3_v,
             add_v, xor_v : alu_dw_t;
  begin
    -- prepare adder
    in1_v      := '0' & unsigned(a_q);
    if    op_i = ALU_ADD_10 then
      in2_v    := to_unsigned(10, alu_dw_t'length);
    elsif op_i = ALU_ADD_DEC then
      in2_v    := '0' & unsigned(dec_data_i(dw_t'range));
    else
      in2_v    := '0' & unsigned(m_i);
    end if;
    if op_i = ALU_ADD_C then
      in3_v    := (others => '0');
      in3_v(0) := c_q;
    else
      in3_v    := (others => '0');
    end if;
    add_v := in1_v + in2_v + in3_v;
 
    -- prepare exclusive or
    xor_v := in1_v xor in2_v;
 
    case op_i is
      -- ALU operation: Clear accumulator -------------------------------------
      when ALU_CLRA =>
        alu_result_s <= (others => '0');
 
      -- ALU operation: Add to accumulator ------------------------------------
      when ALU_ADD     |
           ALU_ADD_10  |
           ALU_ADD_C   |
           ALU_ADD_DEC =>
        alu_result_s <= add_v;
 
      -- ALU operation: Complement accumulator --------------------------------
      when ALU_COMP =>
        alu_result_s <= '0' & not unsigned(a_q);
 
      -- ALU operation: XOR to accumulator ------------------------------------
      when ALU_XOR =>
        alu_result_s <= xor_v;
 
      when others =>
        alu_result_s <= (others => '-');
    end case;
  end process dp;
  --
  -----------------------------------------------------------------------------
 
 
  -----------------------------------------------------------------------------
  -- Output mapping
  -----------------------------------------------------------------------------
  a_o     <= a_q;
  carry_o <= alu_result_s(alu_dw_t'high);
  c_o     <= c_q;
 
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.