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;