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

Subversion Repositories marca

[/] [marca/] [tags/] [INITIAL/] [vhdl/] [alu.vhd] - Rev 8

Compare with Previous | Blame | View Log

--  This file is part of the marca processor.
--  Copyright (C) 2007 Wolfgang Puffitsch
 
--  This program is free software; you can redistribute it and/or modify it
--  under the terms of the GNU Library General Public License as published
--  by the Free Software Foundation; either version 2, or (at your option)
--  any later version.
 
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Library General Public License for more details.
 
--  You should have received a copy of the GNU Library General Public
--  License along with this program; if not, write to the Free Software
--  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
-------------------------------------------------------------------------------
-- MARCA ALU
-------------------------------------------------------------------------------
-- architecture for the ALU
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-- Wolfgang Puffitsch
-- Computer Architecture Lab, Group 3
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
use work.marca_pkg.all;
 
architecture behaviour of alu is
 
  type WAIT_STATE is (WAIT_NONE, WAIT_MULT, WAIT_DIV, WAIT_UDIV, WAIT_MOD, WAIT_UMOD);
  signal state      : WAIT_STATE;
  signal next_state : WAIT_STATE;
 
  signal flags      : std_logic_vector(REG_WIDTH-1 downto 0);
  signal next_flags : std_logic_vector(REG_WIDTH-1 downto 0);
 
  signal shflags      : std_logic_vector(REG_WIDTH-1 downto 0);
  signal next_shflags : std_logic_vector(REG_WIDTH-1 downto 0);
 
  signal old_sgna, old_sgnb : std_logic;
  signal sgna, sgnb         : std_logic;
 
  component multiplier is
                         generic (
                           width : integer := REG_WIDTH);
                       port (
                         clock    : in std_logic;
                         reset    : in std_logic;
                         trigger  : in std_logic;
                         operand1 : in std_logic_vector(width-1 downto 0);
                         operand2 : in std_logic_vector(width-1 downto 0);
                         busy     : out std_logic;
                         product  : out std_logic_vector(width downto 0));
  end component;
 
  signal mult_op1     : std_logic_vector(REG_WIDTH-1 downto 0);
  signal mult_op2     : std_logic_vector(REG_WIDTH-1 downto 0);
  signal mult_trigger : std_logic;
  signal mult_busy    : std_logic;
  signal mult_result  : std_logic_vector(REG_WIDTH downto 0);
 
 
  component divider is
                      generic (
                        width : integer := REG_WIDTH);
                    port (
                      clock    : in std_logic;
                      reset    : in std_logic;
                      trigger  : in std_logic;
                      denom    : in std_logic_vector(width-1 downto 0);
                      numer    : in std_logic_vector(width-1 downto 0);
                      exc      : out std_logic;
                      busy     : out std_logic;
                      quotient : out std_logic_vector(width-1 downto 0);
                      remain   : out std_logic_vector(width-1 downto 0));
  end component;
 
  signal udiv_op1     : std_logic_vector(REG_WIDTH-1 downto 0);
  signal udiv_op2     : std_logic_vector(REG_WIDTH-1 downto 0);
  signal udiv_trigger : std_logic;
  signal udiv_exc     : std_logic;
  signal udiv_busy    : std_logic;
  signal udiv_result  : std_logic_vector(REG_WIDTH-1 downto 0);
  signal umod_result  : std_logic_vector(REG_WIDTH-1 downto 0);
 
 
  signal adder_op1    : std_logic_vector(REG_WIDTH downto 0);
  signal adder_op2    : std_logic_vector(REG_WIDTH downto 0);
  signal adder_op3    : std_logic;
  signal adder_result : std_logic_vector(REG_WIDTH downto 0);
 
 
  function shift_left (a : std_logic_vector;
                       b : std_logic_vector)
    return std_logic_vector is
    variable result : std_logic_vector(a'length-1 downto 0);
    variable i : integer;
  begin
    for i in 0 to a'length-1 loop
      if i < to_integer(unsigned(b)) then
        result(i) := '0';
      else
        result(i) := a(i - to_integer(unsigned(b)));
      end if;
    end loop;  
    return result;
  end;
 
  function shift_right (a : std_logic_vector;
                        b : std_logic_vector)
    return std_logic_vector is
    variable result : std_logic_vector(a'length-1 downto 0);
    variable i : integer;
  begin
    for i in 0 to a'length-1 loop
      if i < to_integer(unsigned(b)) then
        result(i) := a(i + to_integer(unsigned(b)));
      elsif i < a'length-1 then       
        result(i) := '0';
      else
        result(i) := a(to_integer(unsigned(b)) - 1);
      end if;
    end loop;
    return result;
  end;
 
  function shift_aright (a : std_logic_vector;
                         b : std_logic_vector)
    return std_logic_vector is
    variable result : std_logic_vector(a'length-1 downto 0);
    variable i : integer;
  begin
    for i in 0 to a'length-1 loop
      if i < to_integer(unsigned(b)) then
        result(i) := a(i + to_integer(unsigned(b)));
      elsif i < a'length-1 then       
        result(i) := a(a'length-1);
      else
        result(i) := a(to_integer(unsigned(b)) - 1);
      end if;
    end loop;
    return result;
  end;
 
  function rotate_left (a : std_logic_vector;
                        b : std_logic_vector;
                        c : std_logic)
    return std_logic_vector is
    variable result : std_logic_vector(a'length-1 downto 0);
    variable i : integer;
  begin
    for i in 0 to a'length-1 loop
      if i < to_integer(unsigned(b)) - 1 then
        result(i) := a(a'length - to_integer(unsigned(b)) + i);
      elsif i = to_integer(unsigned(b)) - 1 then
        result(i) := c;
      else
        result(i) := a(i - to_integer(unsigned(b)));
      end if;
    end loop;  
    return result;
  end;
 
  function rotate_right(a : std_logic_vector;
                        b : std_logic_vector;
                        c : std_logic)
    return std_logic_vector is
    variable result : std_logic_vector(a'length-1 downto 0);
    variable i : integer;
  begin
    for i in 0 to a'length-1 loop
      if i < a'length - to_integer(unsigned(b)) then
        result(i) := a(to_integer(unsigned(b)) + i);
      elsif i = a'length - to_integer(unsigned(b)) - 1 then
        result(i) := c;
      else
        result(i) := a(i - a'length - to_integer(unsigned(b)));
      end if;    
    end loop;
    return result;
  end;
 
  function to_unsigned(a : std_logic)
    return unsigned is
    variable result : unsigned(0 downto 0);
  begin  -- to_unsigned
    if a = '1' then
      result := "1";
    else
      result := "0";
    end if;
    return result;
  end to_unsigned;
 
  function parity(a : std_logic_vector)
    return std_logic is
    variable result : std_logic;
    variable i : integer;
  begin
    result := '1';
    for i in a'low to a'high loop
      result := result xor a(i);
    end loop;
    return result;
  end;
 
begin  -- behaviour
 
  -- hardwire the interrupt enable flag
  iena <= flags(FLAG_I);
  -- and the exception signal to the divider
  exc <= udiv_exc;
 
  mult_unit : multiplier
    port map (
      clock    => clock,
      reset    => reset,
      trigger  => mult_trigger,
      operand1 => mult_op1,
      operand2 => mult_op2,
      busy     => mult_busy,
      product  => mult_result);
 
  udiv_unit : divider
    port map (
      clock    => clock,
      reset    => reset,
      trigger  => udiv_trigger,
      numer    => udiv_op1,
      denom    => udiv_op2,
      exc      => udiv_exc,
      busy     => udiv_busy,
      quotient => udiv_result,
      remain   => umod_result);
 
  syn_proc: process (clock, reset)
  begin  -- process syn_proc
    if reset = RESET_ACTIVE then                 -- asynchronous reset (active low)
      flags <= (others => '0');
      shflags <= (others => '0');
      state <= WAIT_NONE;
      old_sgna <= '0';
      old_sgnb <= '0';
    elsif clock'event and clock = '1' then  -- rising clock edge
      flags <= next_flags;
      shflags <= next_shflags;
      state <= next_state;
      old_sgna <= sgna;
      old_sgnb <= sgnb;
    end if;
  end process syn_proc;
 
  business: process(next_state)
  begin  -- process business
    if next_state /= WAIT_NONE then
      busy <= '1';
    else
      busy <= '0';
    end if;
  end process business;
 
  adder: process (adder_op1, adder_op2, adder_op3)
  begin  -- process adder
    adder_result <= std_logic_vector(unsigned(adder_op1) + unsigned(adder_op2)
                                     + to_unsigned(adder_op3));
  end process adder;
 
  compute: process (state, op, a, b, i, pc, flags, shflags,
                    intr,
                    sgna, sgnb, old_sgna, old_sgnb,
                    mult_busy, mult_result,
                    udiv_busy, udiv_result, umod_result,
                    adder_result)
 
    variable wr_flags : std_logic;
    variable tmp : std_logic_vector(REG_WIDTH downto 0);
 
  begin
    wr_flags := '1';
    tmp := (others => '0');
 
    next_flags <= flags;
    next_shflags <= shflags;
    next_state <= state;
 
    sgna <= a(REG_WIDTH-1);
    sgnb <= b(REG_WIDTH-1);
 
    mult_op1 <= (others => '0');
    mult_op2 <= (others => '0');
    mult_trigger <= '0';
 
    udiv_op1 <= (others => '0');
    udiv_op2 <= (others => '0');
    udiv_trigger <= '0';
 
    adder_op1 <= (others => '0');
    adder_op2 <= (others => '0');
    adder_op3 <= '0';
 
    pcchg <= '0';
 
    case state is
      when WAIT_MULT =>
        sgna <= old_sgna;
        sgnb <= old_sgnb;
        tmp := mult_result;
        if mult_busy = '0' then
          next_state <= WAIT_NONE;
        end if;
      when WAIT_DIV =>
        sgna <= old_sgna;
        sgnb <= old_sgnb;
        if sgna = sgnb then
          tmp(REG_WIDTH-1 downto 0) := udiv_result;
        else
          tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(udiv_result));
        end if;
        if udiv_busy = '0' then
          next_state <= WAIT_NONE;
        end if;
      when WAIT_UDIV =>
        sgna <= old_sgna;
        sgnb <= old_sgnb;
        tmp(REG_WIDTH-1 downto 0) := udiv_result;
        if udiv_busy = '0' then
          next_state <= WAIT_NONE;
        end if;
      when WAIT_MOD =>
        sgna <= old_sgna;
        sgnb <= old_sgnb;
        if sgna = sgnb then
          tmp(REG_WIDTH-1 downto 0) := umod_result;
        else
          tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(umod_result));
        end if;
        if udiv_busy = '0' then
          next_state <= WAIT_NONE;
        end if;
      when WAIT_UMOD =>
        sgna <= old_sgna;
        sgnb <= old_sgnb;
        tmp(REG_WIDTH-1 downto 0) := umod_result;
        if udiv_busy = '0' then
          next_state <= WAIT_NONE;
        end if;
      when WAIT_NONE =>
        case op is
          when ALU_ADD  => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
                           tmp := adder_result;
          when ALU_SUB  => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
                           adder_op3 <= '1';
                           tmp := adder_result;
          when ALU_ADDC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
                           adder_op3 <= flags(FLAG_C);
                           tmp := adder_result;
          when ALU_SUBC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
                           adder_op3 <= not flags(FLAG_C);
                           tmp := adder_result;
          when ALU_AND  => tmp(REG_WIDTH-1 downto 0) := a and b;
          when ALU_OR   => tmp(REG_WIDTH-1 downto 0) := a or b;
          when ALU_XOR  => tmp(REG_WIDTH-1 downto 0) := a xor b;
-------------------------------------------------------------------------------                       
          when ALU_MUL  => mult_trigger <= '1';
                           mult_op1 <= a;
                           mult_op2 <= b;
                           next_state <= WAIT_MULT;
          when ALU_DIV  => udiv_trigger <= '1';
                           udiv_op1 <= std_logic_vector(abs(signed(a)));
                           udiv_op2 <= std_logic_vector(abs(signed(b)));
                           next_state <= WAIT_DIV;
          when ALU_UDIV => udiv_trigger <= '1';
                           udiv_op1 <= a;
                           udiv_op2 <= b;
                           next_state <= WAIT_UDIV;
          when ALU_MOD  => udiv_trigger <= '1';
                           udiv_op1 <= std_logic_vector(abs(signed(a)));
                           udiv_op2 <= std_logic_vector(abs(signed(b)));
                           next_state <= WAIT_MOD;
          when ALU_UMOD => udiv_trigger <= '1';
                           udiv_op1 <= a;
                           udiv_op2 <= b;
                           next_state <= WAIT_UMOD;
-------------------------------------------------------------------------------                       
          when ALU_LDIL => tmp(REG_WIDTH-1 downto 0) := a(REG_WIDTH-1 downto REG_WIDTH/2) & i(REG_WIDTH/2-1 downto 0);
          when ALU_LDIH => tmp(REG_WIDTH-1 downto 0) := i(REG_WIDTH/2-1 downto 0) & a(REG_WIDTH/2-1 downto 0);
          when ALU_LDIB => tmp(REG_WIDTH-1 downto 0) := i;
-------------------------------------------------------------------------------                       
          when ALU_MOV  => tmp(REG_WIDTH-1 downto 0) := b;
          when ALU_NOT  => tmp(REG_WIDTH-1 downto 0) := not b;
          when ALU_NEG  => adder_op1 <= (others => '0');
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
                           adder_op3 <= '1';
                           tmp := adder_result;
          when ALU_ADDI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                           tmp := adder_result;
                           sgnb <= i(REG_WIDTH-1);
          when ALU_CMPI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
                           adder_op2 <= not std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                           adder_op3 <= '1';
                           tmp := adder_result;
                           sgnb <= i(REG_WIDTH-1);
          when ALU_SHL  => tmp := shift_left   (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b);
          when ALU_SHR  => tmp := shift_right  (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b);
          when ALU_SAR  => tmp := shift_aright (std_logic_vector(resize(  signed(a), REG_WIDTH+1)), b);
          when ALU_ROLC => tmp := rotate_left  (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C));
          when ALU_RORC => tmp := rotate_right (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C));
          when ALU_BSET => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '1';
          when ALU_BCLR => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '0';
          when ALU_BTEST => tmp := (others => '0'); tmp(0) := a(to_integer(unsigned(i)));
          when ALU_SEXT => tmp(REG_WIDTH-1 downto 0) := std_logic_vector(resize(signed(a(REG_WIDTH/2-1 downto 0)), REG_WIDTH));
-------------------------------------------------------------------------------
          when ALU_BRZ  => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '1' then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRNZ => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '0' then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRLE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRLT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                           if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                             pcchg <= '1';
                           end if;
                           tmp := adder_result;
                           wr_flags := '0';
          when ALU_BRULE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                            if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                              pcchg <= '1';
                            end if;
                            tmp := adder_result;
                            wr_flags := '0';
          when ALU_BRULT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                            if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                              pcchg <= '1';
                            end if;
                            tmp := adder_result;
                            wr_flags := '0';
          when ALU_BRUGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                            if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                              pcchg <= '1';
                            end if;
                            tmp := adder_result;
                            wr_flags := '0';
          when ALU_BRUGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
                            if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then                              
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
                              pcchg <= '1';
                            end if;
                            tmp := adder_result;
                            wr_flags := '0';
-------------------------------------------------------------------------------
          when ALU_JMP   => tmp(REG_WIDTH-1 downto 0) := a;
                            pcchg <= '1';
                            wr_flags := '0';
          when ALU_JMPZ  => if flags(FLAG_Z) = '1' then
                              tmp(REG_WIDTH-1 downto 0) := a;
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc;
                            end if;
                            wr_flags := '0';
          when ALU_JMPNZ => if flags(FLAG_Z) = '0' then
                              tmp(REG_WIDTH-1 downto 0) := a;
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc;
                            end if;
                            wr_flags := '0';
          when ALU_JMPLE => if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then
                              tmp(REG_WIDTH-1 downto 0) := a; 
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc; 
                            end if;
                            wr_flags := '0';
          when ALU_JMPLT => if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then
                              tmp(REG_WIDTH-1 downto 0) := a;
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc; 
                            end if;
                            wr_flags := '0';
          when ALU_JMPGE => if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then
                              tmp(REG_WIDTH-1 downto 0) := a; 
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc; 
                            end if;
                            wr_flags := '0';
          when ALU_JMPGT => if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then
                              tmp(REG_WIDTH-1 downto 0) := a; 
                              pcchg <= '1';
                            else
                              tmp(REG_WIDTH-1 downto 0) := pc; 
                            end if;
                            wr_flags := '0';
          when ALU_JMPULE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then
                               tmp(REG_WIDTH-1 downto 0) := a; 
                               pcchg <= '1';
                             else
                               tmp(REG_WIDTH-1 downto 0) := pc; 
                             end if;
                             wr_flags := '0';
          when ALU_JMPULT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then
                               tmp(REG_WIDTH-1 downto 0) := a; 
                               pcchg <= '1';
                             else
                               tmp(REG_WIDTH-1 downto 0) := pc; 
                             end if;
                             wr_flags := '0';
          when ALU_JMPUGE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then
                               tmp(REG_WIDTH-1 downto 0) := a; 
                               pcchg <= '1';
                             else
                               tmp(REG_WIDTH-1 downto 0) := pc; 
                             end if;
                             wr_flags := '0';
          when ALU_JMPUGT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then
                               tmp(REG_WIDTH-1 downto 0) := a; 
                               pcchg <= '1';
                             else
                               tmp(REG_WIDTH-1 downto 0) := pc; 
                             end if;
                             wr_flags := '0';
-------------------------------------------------------------------------------
          when ALU_GETFL => tmp(REG_WIDTH-1 downto 0) := flags;
                            wr_flags := '0';
          when ALU_SETFL => next_flags <= a;
                            wr_flags := '0';
          when ALU_GETSHFL => tmp(REG_WIDTH-1 downto 0) := shflags;
                              wr_flags := '0';
          when ALU_SETSHFL => next_shflags <= a;
                              wr_flags := '0';
          when ALU_INTR => next_shflags <= flags;
                           next_flags(FLAG_I) <= '0';
                           wr_flags := '0';
          when ALU_RETI => next_flags <= shflags;
                           wr_flags := '0';
          when ALU_SEI => next_flags(FLAG_I) <= '1';
                          wr_flags := '0';
          when ALU_CLI => next_flags(FLAG_I) <= '0';
                          wr_flags := '0';
-------------------------------------------------------------------------------
          when ALU_NOP => wr_flags := '0';
          when others => null;
        end case;
      when others => null;
    end case;
 
    -- if the result is to be ignored, it will be ignored in the write-back stage
    result <= tmp(REG_WIDTH-1 downto 0);
 
    -- the flags do not make sense with all instructions yet
    if wr_flags = '1' then
      next_flags(FLAG_C) <= tmp(REG_WIDTH);
      next_flags(FLAG_N) <= tmp(REG_WIDTH-1);
      next_flags(FLAG_Z) <= zero(tmp(REG_WIDTH-1 downto 0));
      next_flags(FLAG_V) <= sgna xor sgnb xor tmp(REG_WIDTH) xor tmp(REG_WIDTH-1);
      next_flags(FLAG_P) <= parity(tmp(REG_WIDTH-1 downto 0));
    end if;
 
    if intr = '1' then
      next_shflags <= flags;
      next_flags(FLAG_I) <= '0';
    end if;
 
  end process compute;
 
end behaviour;
 

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.