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

Subversion Repositories rise

[/] [rise/] [trunk/] [vhdl/] [ex_stage.vhd] - Rev 71

Go to most recent revision | Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- File: ex_stage.vhd
-- Author: Jakob Lechner, Urban Stadler, Harald Trinkl, Christian Walter
-- Created: 2006-11-29
-- Last updated: 2006-11-29
 
-- Description:
-- Execute stage
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.STD_LOGIC_ARITH.all;
 
use WORK.RISE_PACK.all;
use work.RISE_PACK_SPECIFIC.all;
 
entity ex_stage is
 
  port (
    clk                 : in std_logic;
    reset               : in std_logic;
 
    id_ex_register      : in ID_EX_REGISTER_T;
    ex_mem_register     : out EX_MEM_REGISTER_T;
 
    branch              : out std_logic;
    stall_in            : in std_logic;
    clear_in            : in std_logic;
    clear_out           : out std_logic);
 
end ex_stage;
 
architecture ex_stage_rtl of ex_stage is
 
--  signal id_ex_register : ID_EX_REGISTER_T;
 
  signal ex_mem_register_int     : EX_MEM_REGISTER_T;
  signal ex_mem_register_next    : EX_MEM_REGISTER_T;
  signal isLoadOp : std_logic;
  signal isJmpOp : std_logic;
 
  signal aluop1_int : ALUOP1_T;
  signal aluop2_int : ALUOP2_T;
 
  signal execute : std_logic;
  signal clear_out_int : std_logic;
  signal branch_int : std_logic;
 
  function isOverflowAdd (
    op1 : std_logic_vector;
    op2 : std_logic_vector;
    result : std_logic_vector)
    return std_logic is
    variable x : std_logic;
  begin
    x := '0';
    if op1(REGISTER_WIDTH-1) = '0' and op2(REGISTER_WIDTH-1) = '0' then
      x := result(REGISTER_WIDTH-1);       
    end if;
    if op1(REGISTER_WIDTH-1) = '1' and op2(REGISTER_WIDTH-1) = '1' then
      x := not result(REGISTER_WIDTH-1);       
    end if;
    return x;
  end isOverflowAdd;
 
  function isOverflowSub (
    op1 : std_logic_vector;
    op2 : std_logic_vector;
    result : std_logic_vector)
    return std_logic is
    variable x : std_logic;
  begin
    x := '0';
    if op1(REGISTER_WIDTH-1) = '0' and op2(REGISTER_WIDTH-1) = '1' then
      x := result(REGISTER_WIDTH-1);       
    end if;
    if op1(REGISTER_WIDTH-1) = '1' and op2(REGISTER_WIDTH-1) = '0' then
      x := not result(REGISTER_WIDTH-1);       
    end if;
 
    return x;
  end isOverflowSub;
 
begin  -- ex_stage_rtl
 
  ex_mem_register        <= ex_mem_register_int;
 
  output: process (clk, reset)
  begin  -- process
    if reset = '0' then                 -- asynchronous reset (active low)
      ex_mem_register_int.aluop1        <= (others => '0');
      ex_mem_register_int.aluop2        <= (others => '0');
      ex_mem_register_int.reg           <= (others => '0');
      ex_mem_register_int.alu           <= (others => '0');
      ex_mem_register_int.dreg_addr     <= (others => '0');
      ex_mem_register_int.lr            <= (others => '0');
      ex_mem_register_int.sr            <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      -- if PIPELINE isn't stalled: update registers
      if stall_in = '0' then            
        ex_mem_register_int        <= ex_mem_register_next;
        --id_ex_register <= id_ex_register_in;
        clear_out <= clear_out_int;
        branch <= branch_int;
      end if;
    end if;
  end process output;  
 
  cond_check: process (id_ex_register, aluop1_int, aluop2_int)
  begin  -- process cond_check
    execute <= '0';
 
    case id_ex_register.cond is
      when COND_UNCONDITIONAL =>
        execute <= '1';
      when COND_NOT_ZERO =>
        if id_ex_register.sr(SR_ZERO_BIT) = '0' then
          execute <= '1';
        end if;
      when COND_ZERO =>
        if id_ex_register.sr(SR_ZERO_BIT) = '1' then
          execute <= '1';
        end if;
      when COND_CARRY =>
        if id_ex_register.sr(SR_CARRY_BIT) = '1' then
          execute <= '1';
        end if;
      when COND_NEGATIVE =>
        if id_ex_register.sr(SR_NEGATIVE_BIT) = '1' then
          execute <= '1';
        end if;
      when COND_OVERFLOW =>
        if id_ex_register.sr(SR_OVERFLOW_BIT) = '1' then
          execute <= '1';
        end if;
      when COND_ZERO_NEGATIVE =>
        if id_ex_register.sr(SR_ZERO_BIT) = '1' or
          id_ex_register.sr(SR_ZERO_BIT) = '1' then
          execute <= '1';
        end if;
      when others => null;
    end case;
  end process cond_check;
 
  aluop: process (execute, aluop1_int, aluop2_int, clear_in)
  begin  -- process aluop
    -- insert nop in pipeline if instruction is conditional and
    -- condition is not met, or if pipeline is cleared
    if execute = '0' or clear_in = '1' then
      ex_mem_register_next.aluop1 <= (others => '0');
      ex_mem_register_next.aluop2 <= (others => '0');
    else
      ex_mem_register_next.aluop1 <= aluop1_int;
      ex_mem_register_next.aluop2 <= aluop2_int;  
    end if;    
  end process aluop;
 
  alu: process (id_ex_register, ex_mem_register_next)
  begin
 
    ex_mem_register_next.alu <= (others => '0');
    ex_mem_register_next.dreg_addr <= id_ex_register.rX_addr;
    ex_mem_register_next.reg <= (others => '0');
    ex_mem_register_next.lr <= (others => '0');
    ex_mem_register_next.sr <= (others => '0');
 
    aluop1_int(ALUOP1_LD_MEM_BIT) <= '0';
    aluop1_int(ALUOP1_ST_MEM_BIT) <= '0';
    aluop1_int(ALUOP1_WB_REG_BIT) <= '1';
 
    aluop2_int <=  (ALUOP2_LR_BIT => '0', ALUOP2_SR_BIT => '1', others => '0');
 
    isLoadOp <= '0';
    isJmpOp <= '0';
 
    case id_ex_register.opcode is
      -- load opcodes
      when OPCODE_LD_IMM =>
        ex_mem_register_next.alu <= x"00" & id_ex_register.immediate(7 downto 0);
        isLoadOp <= '1';
      when OPCODE_LD_IMM_HB =>
        ex_mem_register_next.alu <= id_ex_register.rX or (id_ex_register.immediate(7 downto 0) & x"00");
        isLoadOp <= '1';
      when OPCODE_LD_DISP =>
        ex_mem_register_next.alu <= id_ex_register.rY + id_ex_register.rZ;
        aluop1_int(ALUOP1_LD_MEM_BIT) <= '1';
        isLoadOp <= '1';
      when OPCODE_LD_DISP_MS =>
        ex_mem_register_next.alu <= id_ex_register.rY + id_ex_register.rZ;
        aluop1_int(ALUOP1_LD_MEM_BIT) <= '1';
        isLoadOp <= '1';
      when OPCODE_LD_REG =>
        ex_mem_register_next.alu <= id_ex_register.rY;
        isLoadOp <= '1';
 
        -- store opcodes
      when OPCODE_ST_DISP =>
        ex_mem_register_next.alu <= id_ex_register.rY + id_ex_register.rZ;
        ex_mem_register_next.reg <= id_ex_register.rX;
        aluop1_int(ALUOP1_ST_MEM_BIT) <= '1';
        aluop2_int(ALUOP2_SR_BIT) <= '0';
 
        -- arithmetic opcodes
      when OPCODE_ADD =>
        ex_mem_register_next.alu <= id_ex_register.rX + id_ex_register.rY;
        ex_mem_register_next.sr(SR_OVERFLOW_BIT) <= isOverflowAdd(id_ex_register.rX,
                                                                  id_ex_register.rY,
                                                                  ex_mem_register_next.alu);
      when OPCODE_ADD_IMM =>
        ex_mem_register_next.alu <= id_ex_register.rX + id_ex_register.immediate;
        ex_mem_register_next.sr(SR_OVERFLOW_BIT) <= isOverflowAdd(id_ex_register.rX,
                                                                  id_ex_register.immediate,
                                                                  ex_mem_register_next.alu);
      when OPCODE_SUB =>
        ex_mem_register_next.alu <= id_ex_register.rX - id_ex_register.rY;
        ex_mem_register_next.sr(SR_OVERFLOW_BIT) <= isOverflowSub(id_ex_register.rX,
                                                                  id_ex_register.rY,
                                                                  ex_mem_register_next.alu);
      when OPCODE_SUB_IMM =>
        ex_mem_register_next.alu <= id_ex_register.rX - id_ex_register.immediate;
        ex_mem_register_next.sr(SR_OVERFLOW_BIT) <= isOverflowSub(id_ex_register.rX,
                                                                  id_ex_register.immediate,
                                                                  ex_mem_register_next.alu);
      when OPCODE_NEG =>
        ex_mem_register_next.alu <= not id_ex_register.rY + x"0001";
      when OPCODE_ALS =>
        ex_mem_register_next.alu <= id_ex_register.rY(REGISTER_WIDTH-2 downto 0) & "0";
        ex_mem_register_next.sr(SR_OVERFLOW_BIT) <= id_ex_register.rY(REGISTER_WIDTH-1) xor
                                                    id_ex_register.rY(REGISTER_WIDTH-2);
      when OPCODE_ARS =>
        ex_mem_register_next.alu <= id_ex_register.rY(REGISTER_WIDTH-1) & id_ex_register.rY(REGISTER_WIDTH-1 downto 1);
 
 
        -- logical opcodes
      when OPCODE_AND =>
        ex_mem_register_next.alu <= id_ex_register.rX and id_ex_register.rY;            
      when OPCODE_NOT =>
        ex_mem_register_next.alu <= not id_ex_register.rY;            
      when OPCODE_EOR =>
        ex_mem_register_next.alu <= id_ex_register.rX xor id_ex_register.rY;            
      when OPCODE_LS =>
        ex_mem_register_next.alu <= id_ex_register.rY(REGISTER_WIDTH-2 downto 0) & "0";
      when OPCODE_RS =>
        ex_mem_register_next.alu <= "0" & id_ex_register.rY(REGISTER_WIDTH-1 downto 1);
 
        -- program control
      when OPCODE_JMP =>
        ex_mem_register_next.lr             <= id_ex_register.pc;
        ex_mem_register_next.dreg_addr      <= PC_ADDR;
        ex_mem_register_next.alu            <= id_ex_register.rX;
        aluop1_int(ALUOP1_WB_REG_BIT) <= '0';
        aluop2_int(ALUOP2_SR_BIT) <= '0';
        aluop2_int(ALUOP2_LR_BIT) <= '1';
        isJmpOp <= '1';
 
      when OPCODE_NOP =>
        aluop1_int(ALUOP1_WB_REG_BIT) <= '0';
        aluop2_int(ALUOP2_SR_BIT) <= '0';
 
      when OPCODE_TST =>
        aluop1_int(ALUOP1_WB_REG_BIT) <= '0';
        aluop2_int(ALUOP2_SR_BIT) <= '1';
 
      when others =>
        aluop1_int(ALUOP1_WB_REG_BIT) <= '0';
        aluop2_int(ALUOP2_SR_BIT) <= '0';
 
    end case;
  end process;
 
  branch_logic: process (id_ex_register, isLoadOp, isJmpOp)
  begin  -- process branch_logic
    branch_int <= '0';
    clear_out_int <= '0';
    if (id_ex_register.rX_addr = PC_ADDR and isLoadOp = '1') or (isJmpOp = '1') then
      branch_int <= '1';
      clear_out_int <= '1';
    end if;
  end process branch_logic;
 
end ex_stage_rtl;
 

Go to most recent revision | 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.