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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_bjxlog.vhd] - Rev 2

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2017 Stefano Tonello                          --
--                                                             --
-- This source file may be used and distributed without        --
-- restriction provided that this copyright statement is not   --
-- removed from the file and that any derivative work contains --
-- the original copyright notice and the associated disclaimer.--
--                                                             --
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
-- FOR A PARTICULAR PURPOSE. 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.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- RV01 Branch/Jump eXecute Logic
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
library work;
use work.RV01_CONSTS_PKG.all;
use work.RV01_TYPES_PKG.all;
use work.RV01_FUNCS_PKG.all;
use work.RV01_ARITH_PKG.all;
use work.RV01_OP_PKG.all;
 
entity RV01_BJXLOG is
  generic(
    JRPE : std_logic := '1'
  );
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
    BJ_OP_i : in BJ_OP_T;
    SU_i : in std_logic;
    PC_i : in unsigned(ALEN-1 downto 0);
    OPA_i : in SDWORD_T;
    OPB_i : in SDWORD_T;
    IMM_i : in SDWORD_T;
    IV_i : in std_logic;
    FSTLL_i : in std_logic;
    MPJRX_i : in std_logic;
 
    BJX_o : out std_logic;
    BJTA_o : out unsigned(ALEN-1 downto 0)
  );
end RV01_BJXLOG;
 
architecture ARC of RV01_BJXLOG is
 
  signal BJX,BJX_q : std_logic;
  signal BJTA,BJTA_q : unsigned(SDLEN-1 downto 0);
  signal OPB_N,SUB_RES : SDWORD_T;
  signal AEQB,ALTB : std_logic;
  signal BJAL_TA,JALR_TA,PCP4 : ADR_T;
  signal BX,JX : std_logic;
 
begin 
 
  ------------------------------------
  -- Calculate B/J target addresses
  ------------------------------------
 
  -- Calculate B/J target addresses
 
  process(OPA_i,PC_i,IMM_i,BJ_OP_i)
    variable IOPA,IPC,IIMM : signed(SDLEN downto 0);
    variable TA0,TA1 : signed(SDLEN downto 0);
  begin
 
    -- sign-extend OPA_i by one bit
    if(OPA_i >= 0) then
      IOPA := '0' & OPA_i;
    else
      IOPA := '1' & OPA_i;
    end if;
 
    -- sign-extend IMM_i by one bit
    if(IMM_i >= 0) then
      IIMM := '0' & IMM_i;
    else
      IIMM := '1' & IMM_i;
    end if;
 
    -- sign-extend PC_i by one bit
    IPC := '0' & to_signed(PC_i);
 
    TA0 := IOPA + IIMM;
 
    TA1 := IPC + IIMM;
 
    -- Jalr target address
    JALR_TA <= to_unsigned(TA0(SDLEN-1 downto 0));
 
    -- branch/jal target address
    BJAL_TA <= to_unsigned(TA1(SDLEN-1 downto 0));
 
  end process;
 
  -- Address of instruction following the branch/jal
  PCP4 <= PC_i + 4;
 
  -- Select address to branch at in case of
  -- misprediction
 
  process(BX,JX,BJX_q,PCP4,BJAL_TA,JALR_TA,BJTA_q)
  begin
    if(BX = '1' and BJX_q = '0') then 
      BJTA <= BJAL_TA;
    elsif(JX = '1' and BJX_q = '0') then
      BJTA <= JALR_TA(SDLEN-1 downto 1) & '0' ;
    elsif(BJX_q = '0') then
      BJTA <= PCP4;
    else
      BJTA <= BJTA_q;
    end if; 
  end process;
 
  ------------------------------------
  -- Calculate OPA_i - OPB_i (for blt* and bge*)
  ------------------------------------
 
  SUB_RES <= OPA_i - OPB_i;
 
  ------------------------------------
  -- Branch control flags
  ------------------------------------
 
  -- OPA_i less-than OPB_i flag
  AEQB <= '1' when (OPA_i = OPB_i) else '0';
 
  -- if OPA > 0 and OPB > 0, then ALTB = sign(SUB_RES)
  -- if OPA < 0 and OPB < 0, then ALTB = sign(SUB_RES)
  -- if OPA > 0 and OPB < 0, then ALTB = '0'
  -- if OPA < 0 and OPB > 0, then ALTB = '1'
 
  -- OPA_i less-than OPB_i flag
  ALTB <=
    SUB_RES(SDLEN-1) when (OPA_i(SDLEN-1) = OPB_i(SDLEN-1)) else
    OPA_i(SDLEN-1) when (SU_i = '1') else
    OPB_i(SDLEN-1) ;
 
  ------------------------------------
  -- Set branch/jump execute flag
  ------------------------------------
 
  process(BJ_OP_i,AEQB,ALTB,IV_i)
  begin
 
    if(ALTB = '1') then
 
      case BJ_OP_i is
 
        when BJ_BEQ =>
          BX <= AEQB and IV_i;
 
        when BJ_BNE =>
          BX <= not(AEQB) and IV_i;
 
        when BJ_BLT =>
          BX <= IV_i;
 
        when BJ_BGE =>
          BX <= '0';
 
        when BJ_JAL =>
          BX <= IV_i;
 
        when others =>
          BX <= '0';
 
      end case;
 
    else
 
      case BJ_OP_i is
 
        when BJ_BEQ =>
          BX <= AEQB and IV_i;
 
        when BJ_BNE =>
          BX <= not(AEQB) and IV_i;
 
        when BJ_BLT =>
          BX <= '0';
 
        when BJ_BGE =>
          BX <= IV_i;
 
        when BJ_JAL =>
          BX <= IV_i;
 
        when others =>
          BX <= '0';
 
      end case;
 
    end if;
  end process;
 
  ------------------------------------
  -- Set jalr execute flag
  ------------------------------------
 
  GJRPE0_1 : if(JRPE = '1') generate
 
  JX <= MPJRX_i;
 
  end generate;
 
  GJRPE0_0 : if(JRPE = '0') generate
 
  JX <= IV_i when (BJ_OP_i = BJ_JALR) else '0';
 
  end generate;
 
  ------------------------------------
  -- Set B/J execute flag
  ------------------------------------
 
  BJX <= (BX or JX);
 
  -- B/J execute flag and target address register.
  -- These registers are needed when a B/J is taken
  -- while fetch is stalled: in such condition B/J
  -- must deferred to first un-stalled cycle.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(FSTLL_i = '1') then
        BJTA_q <= BJTA;
      end if;
      if(RST_i = '1' or FSTLL_i = '0') then
        BJX_q <= '0';
      elsif(FSTLL_i = '1') then
        BJX_q <= (BJX and IV_i);
      end if;
    end if;
  end process;
 
  -- A branch/jump is actually executed if:
  -- 1) there's a valid B/J instruction in IX1 stage, OR
  -- 2) there's a pending B/J.
 
  BJX_o <= BJX or BJX_q;
 
  BJTA_o <= BJTA;
 
end ARC;
 

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.