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

Subversion Repositories marca

[/] [marca/] [tags/] [INITIAL/] [vhdl/] [execute.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 execution stage
-------------------------------------------------------------------------------
-- architecture of the execution pipeline stage
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-- 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 execute is
 
component alu is
  port (
    clock   : in  std_logic;
    reset   : in  std_logic;
    busy    : out std_logic;
    op      : in  ALU_OP;
    a       : in  std_logic_vector(REG_WIDTH-1 downto 0);
    b       : in  std_logic_vector(REG_WIDTH-1 downto 0);
    i       : in  std_logic_vector(REG_WIDTH-1 downto 0);
    pc      : in  std_logic_vector(REG_WIDTH-1 downto 0);
    intr    : in  std_logic;
    exc     : out std_logic;
    iena    : out std_logic;
    pcchg   : out std_logic;
    result  : out std_logic_vector(REG_WIDTH-1 downto 0));
end component;
 
component mem is
  port (
    clock   : in  std_logic;
    reset   : in  std_logic;
    op      : in  MEM_OP;
    address : in  std_logic_vector(REG_WIDTH-1 downto 0);
    data    : in  std_logic_vector(REG_WIDTH-1 downto 0);
    exc     : out std_logic;
    busy    : out std_logic;
    result  : out std_logic_vector(REG_WIDTH-1 downto 0);
    intrs   : out std_logic_vector(VEC_COUNT-1 downto 3);
    ext_in  : in  std_logic_vector(IN_BITS-1 downto 0);
    ext_out : out std_logic_vector(OUT_BITS-1 downto 0));
end component;
 
component intr is
  port (
    clock   : in  std_logic;
    reset   : in  std_logic;
    enable  : in  std_logic;
    trigger : in  std_logic_vector(VEC_COUNT-1 downto 1);
    op      : in  INTR_OP;
    a       : in  std_logic_vector(REG_WIDTH-1 downto 0);
    i       : in  std_logic_vector(REG_WIDTH-1 downto 0);
    pc      : in  std_logic_vector(REG_WIDTH-1 downto 0);
    exc     : out std_logic;
    pcchg   : out std_logic;
    result  : out std_logic_vector(REG_WIDTH-1 downto 0));
end component;
 
signal any_busy : std_logic;
 
signal alu_iena   : std_logic;
signal alu_exc    : std_logic;
signal alu_busy   : std_logic;
signal alu_pcchg  : std_logic;
signal alu_result : std_logic_vector(REG_WIDTH-1 downto 0);
 
signal mem_exc    : std_logic;
signal mem_busy   : std_logic;
signal mem_result : std_logic_vector(REG_WIDTH-1 downto 0);
signal mem_intrs  : std_logic_vector(VEC_COUNT-1 downto 3);
 
signal intr_enable : std_logic;
signal intr_exc    : std_logic;
signal intr_pcchg  : std_logic;
signal intr_result : std_logic_vector(REG_WIDTH-1 downto 0);
 
signal pc_reg   : std_logic_vector(REG_WIDTH-1 downto 0);
 
signal src1_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0);
signal src2_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0);
signal dest_reg : std_logic_vector(REG_COUNT_LOG-1 downto 0);
 
signal op1_reg  : std_logic_vector(REG_WIDTH-1 downto 0);
signal op2_reg  : std_logic_vector(REG_WIDTH-1 downto 0);
signal imm_reg  : std_logic_vector(REG_WIDTH-1 downto 0);
 
signal op1_fwed : std_logic_vector(REG_WIDTH-1 downto 0);
signal op2_fwed : std_logic_vector(REG_WIDTH-1 downto 0);
 
signal aop_reg  : ALU_OP;
signal mop_reg  : MEM_OP;
signal iop_reg  : INTR_OP;
 
signal unit_reg   : UNIT_SELECTOR;
signal target_reg : TARGET_SELECTOR;
 
signal stall_cnt      : std_logic_vector(1 downto 0);  -- prohibiting                                                        
signal next_stall_cnt : std_logic_vector(1 downto 0);  -- interrupts during reti
 
begin  -- behaviour
 
  -- interrupts do not work while jumping
  intr_enable <= alu_iena and zero(stall_cnt) and not any_busy;
 
  alu_unit : alu
    port map (
      clock => clock,
      reset => reset,
      op => aop_reg,
      a => op1_fwed,
      b => op2_fwed,
      i => imm_reg,
      pc => pc_reg,
      intr => intr_exc,
      exc => alu_exc,
      busy => alu_busy,
      iena => alu_iena,
      pcchg => alu_pcchg,
      result => alu_result);
 
  mem_unit : mem
    port map (
      clock   => clock,
      reset   => reset,
      op      => mop_reg,
      address => op2_fwed,
      data    => op1_fwed,
      exc     => mem_exc,
      busy    => mem_busy,
      result  => mem_result,
      intrs   => mem_intrs,
      ext_in  => ext_in,
      ext_out => ext_out);
 
  intr_unit : intr
    port map (
      clock            => clock,
      reset            => reset,
      enable           => intr_enable,
      trigger(EXC_ALU) => alu_exc,
      trigger(EXC_MEM) => mem_exc,
      trigger(VEC_COUNT-1 downto 3) => mem_intrs,
      op               => iop_reg,
      a                => op1_fwed,
      i                => imm_reg,
      pc               => pc_reg,
      exc              => intr_exc,
      pcchg            => intr_pcchg,
      result           => intr_result);
 
  syn_proc: process (clock, reset)
  begin  -- process syn_proc
    if reset = RESET_ACTIVE then                 -- asynchronous reset (active low)
      stall_cnt <= (others => '0');
      pc_reg <= (others => '0');
      src1_reg <= (others => '0');
      src2_reg <= (others => '0');
      dest_reg <= (others => '0');
      aop_reg <= ALU_NOP;
      mop_reg <= MEM_NOP;
      iop_reg <= INTR_NOP;
      op1_reg <= (others => '0');
      op2_reg <= (others => '0');
      imm_reg <= (others => '0');
      unit_reg <= UNIT_ALU;
      target_reg <= TARGET_NONE;
    elsif clock'event and clock = '1' then  -- rising clock edge
      if any_busy = '0' then
        stall_cnt <= next_stall_cnt;
        if stall = '1' then
          pc_reg <= (others => '0');
          src1_reg <= (others => '0');
          src2_reg <= (others => '0');
          dest_reg <= (others => '0');
          aop_reg <= ALU_NOP;
          mop_reg <= MEM_NOP;
          iop_reg <= INTR_NOP;
          op1_reg <= (others => '0');
          op2_reg <= (others => '0');
          imm_reg <= (others => '0');
          unit_reg <= UNIT_ALU;
          target_reg <= TARGET_NONE;
        else
          pc_reg <= pc_in;
          dest_reg <= dest_in;
          src1_reg <= src1;
          src2_reg <= src2;
          aop_reg <= aop;
          mop_reg <= mop;
          iop_reg <= iop;
          op1_reg <= op1;
          op2_reg <= op2;
          imm_reg <= imm;      
          unit_reg <= unit;
          target_reg <= target_in;   
        end if;
      end if;
    end if;
  end process syn_proc;
 
  stalling: process (stall, stall_cnt)
  begin  -- process hold_pc
 
    next_stall_cnt <= std_logic_vector(unsigned(stall_cnt) - 1);  
    if zero(stall_cnt) = '1' then
      next_stall_cnt <= "00";
    end if;
    if stall = '1' then
      next_stall_cnt <= "11";
    end if;
 
  end process stalling;
 
  business: process (any_busy, alu_busy, mem_busy)
  begin  -- process business
    any_busy <= alu_busy or mem_busy;
    busy <= any_busy;
  end process business;
 
  feedthrough: process (pc_reg, dest_reg, unit_reg, target_reg, op2_fwed, intr_exc)
  begin  -- process feedthrough
    if unit_reg /= UNIT_CALL then
      pc_out <= pc_reg;
    else
      pc_out <= op2_fwed;
    end if;
    dest_out <= dest_reg;
    if intr_exc = '1' then
      target_out <= TARGET_PC;
    else
      target_out <= target_reg;
    end if;
  end process feedthrough;
 
  forward: process (src1_reg, src2_reg, op1_reg, op2_reg, fw_ena, fw_dest, fw_val)
  begin  -- process forward
    op1_fwed <= op1_reg;
    op2_fwed <= op2_reg;
    if fw_ena = '1' then
      if src1_reg = fw_dest then
        op1_fwed <= fw_val;
      end if;
      if src2_reg = fw_dest then
        op2_fwed <= fw_val;        
      end if;
    end if;
  end process forward;
 
  select_result: process(unit_reg, alu_result, mem_result, intr_result, pc_reg,
                         alu_pcchg, intr_pcchg,
                         intr_exc)
  begin  -- process select_result
    case unit_reg is
      when UNIT_ALU => result <= alu_result;
      when UNIT_MEM => result <= mem_result;
      when UNIT_INTR => result <= intr_result;
      when UNIT_CALL => result <= std_logic_vector(unsigned(pc_reg) + 1);
      when others => null;
    end case;
    if intr_exc = '1' then
      result <= intr_result;
    end if;
    pcchg <= alu_pcchg or intr_pcchg;    
  end process select_result;
 
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.