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_bv.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 & branch verificatio nLogic 
---------------------------------------------------------------
 
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_BV 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 ADR_T;
    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;
    -- verification port
    BPVD_i : std_logic_vector(3-1 downto 0);
    MPJRX_i : in std_logic;
 
    BJX_o : out std_logic;
    BJTA_o : out unsigned(ALEN-1 downto 0);
    -- verification port
    BHT_WE_o : out std_logic;
    BHT_TA_o : out ADR_T;
    BHT_PC_o : out ADR_T;
    BHT_CNT_o : out std_logic_vector(2-1 downto 0)
  );
end RV01_BJXLOG_BV;
 
architecture ARC of RV01_BJXLOG_BV is
 
  function updt_cnt(
    CNT : std_logic_vector(2-1 downto 0);
    TKN : std_logic
  ) return std_logic_vector is
    variable TMP : std_logic_vector(3-1 downto 0);
    variable UCNT : std_logic_vector(2-1 downto 0);
  begin
    TMP := CNT & TKN;
    case TMP is
      when "000" => UCNT := "11";
      when "001" => UCNT := "01";
      when "010" => UCNT := "00";
      when "011" => UCNT := "01";
      when "100" => UCNT := "10";
      when "101" => UCNT := "11";
      when "110" => UCNT := "10";
      when others => UCNT := "00";
    end case;
    return(UCNT);
  end function;
 
  signal BJX,BJX_q : std_logic;
  signal BX,JX,PBX,MPBX : std_logic;
  signal BP_HIT : std_logic;
  signal BP_CNT,BP_UCNT : std_logic_vector(2-1 downto 0);
  signal BJTA,BJTA_q : ADR_T;
  signal BJAL_TA,JALR_TA,PCP4 : ADR_T;
  signal OPB_N,SUB_RES : SDWORD_T;
  signal AEQB,ALTB : std_logic;
 
begin 
 
  ---------------------------------------
  -- Notes
  ---------------------------------------
 
  -- This module performs branch and jal instructions
  -- prediction verification and jalr instructions
  -- executions. Jal instructions are treated as
  -- always-taken branches and are therefore
  -- assigned an entry in BHT. Jal instructions
  -- are surely mispredicted as not taken the first
  -- time they're encountered.
  -- Jalr instructions are not predicted at all
  -- and so no entry is assigned to them in BHT.
  -- If a branch/jal instruction is predicted correctly,
  -- it's treated as a nop, otherwise a branch is
  -- executed to the correct target address or to
  -- the address following the branch instruction
  -- itself.
  -- BHT is updated every time a valid branch/jal
  -- instruction reaches IX1 stage, regardless of
  -- prediction correctness.
 
  ---------------------------------------
  -- Branch/Jump execution
  ---------------------------------------
 
  -- Calculate B/J target addresses
 
  process(OPA_i,PC_i,IMM_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);
 
    -- Note: there's no timing benefit from
    -- replacing these adders with carry-select
    -- ones.
 
    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,MPJRX_i,BJX_q,PCP4,BJAL_TA,JALR_TA,BJTA_q)
  begin
    if(BX = '1' and BJX_q = '0') then 
      BJTA <= BJAL_TA;
    elsif((JX = '1' or MPJRX_i = '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 and jal 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 <= '0';
 
  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 <= (MPBX 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;
 
  ---------------------------------------
  -- Branch verification
  ---------------------------------------
 
  -- branch prediction hit flag
  BP_HIT <= BPVD_i(0);
 
  -- branch prediction count
  BP_CNT <= BPVD_i(3-1 downto 1);
 
  -- branch prediction updated count
  BP_UCNT <= updt_cnt(BP_CNT,BX) when BP_HIT = '1' else (not(BX) & not(BX));
 
  -- predicted branch execute flag
  -- (1 -> predicted taken, 0 -> predicted not taken)
 
  PBX <= BP_HIT and not(BP_CNT(1)) and IV_i;
 
  -- branch mis-prediction flag
  MPBX <= (PBX xor BX) or MPJRX_i;
 
  -- BHT updated data
 
  BHT_WE_o <= IV_i when(
    BJ_OP_i = BJ_BEQ or
    BJ_OP_i = BJ_BNE or
    BJ_OP_i = BJ_BLT or
    BJ_OP_i = BJ_BGE or
    BJ_OP_i = BJ_JAL
  ) else '0';
 
  BHT_CNT_o <= BP_UCNT;
 
  BHT_TA_o <= JALR_TA when (BJ_OP_i = BJ_JALR) else BJAL_TA;
 
  BHT_PC_o <= PC_i;
 
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.