URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_ftchlog_2w.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 Instruction Fecthing 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_CSR_PKG.all; entity RV01_FTCHLOG_2W is port( CLK_i : in std_logic; RST_i : in std_logic; STRT_i : in std_logic; STRTPC_i : in ADR_T; HALT_i : in std_logic; BJX_i : in std_logic; BJTA_i : in ADR_T; PBX_i : in std_logic; PBTA_i : in ADR_T; KLL1_i : in std_logic; PJRX_i : std_logic; PJRTA_i : in ADR_T; EXCP_i : in std_logic; ERET_i : in std_logic; RFTCH_i : in std_logic; ETVA_i : in ADR_T; PSTALL_i : in std_logic; -- Debug interface DHALT_i : in std_logic; IFV_o : out std_logic_vector(2-1 downto 0); IADR0_o : out ADR_T; IADR1_o : out ADR_T; IADR_MIS_o : out std_logic ); end RV01_FTCHLOG_2W; architecture ARC of RV01_FTCHLOG_2W is signal SZERO : ADR_T := (others => '0'); signal ONE : std_logic := '1'; signal PC,PC_q : unsigned(ALEN-4 downto 0); signal PC_NS : unsigned(ALEN-4 downto 0); signal PCP8,PCP8_q : unsigned(ALEN-4 downto 0); signal HALT_q : std_logic; signal EVEN_PC : std_logic; signal EVEN_PC_NS : std_logic; signal FC : std_logic; signal PC_NS_FC : unsigned(ALEN-4 downto 0); signal EVEN_PC_NS_FC : std_logic; begin -- Halt flag register process(CLK_i) begin if(CLK_i = '1' and CLK_i'event) then if(RST_i = '1' or HALT_i = '1') then HALT_q <= '1'; elsif(STRT_i = '1') then HALT_q <= '0'; end if; end if; end process; -- Instructions are always fetched in pair from an address -- aligned on a two-word boundary, so that PC LS 3 bits are -- guaranteed to be zero and are therefore not physically -- implemented. -- When start or B/J address is an odd word address, fetch -- address is still an even word address, but instruction #0 -- gets nullified. -- Fetched instruction #0 is always valid, unless processor is -- halted or fetch address is odd. IFV_o(0) <= (not(HALT_q) or STRT_i) and EVEN_PC; -- Fetched instruction #1 is always valid, unless processor is -- halted. IFV_o(1) <= (not(HALT_q) or STRT_i); -- PC register reset value is set to reset exception vector -- "low" address. -- PC register is incremented only if pipeline is not -- stalled (i.e. when PSTALL_i = '0'). -- PC+8 value is pre-calculated in current cycle and stored -- into PCP8 to remove addition from address critical path. -- Program Counter register process(CLK_i) begin if(CLK_i = '1' and CLK_i'event) then if(RST_i = '1') then PC_q <= to_unsigned(0,SDLEN-3); PCP8_q <= to_unsigned(1,SDLEN-3); elsif((HALT_q = '0') or (STRT_i = '1')) then PC_q <= PC; PCP8_q <= PCP8; end if; end if; end process; -- PC plus 8 PCP8 <= PC_NS + 1 when ( PSTALL_i = '0' or EXCP_i = '1' or ERET_i = '1' or RFTCH_i = '1' ) else PCP8_q; -- Flow change flag FC <= EXCP_i or ERET_i or RFTCH_i or BJX_i; -- PC no-stall value process(PBX_i,PJRX_i,FC,PC_NS_FC,PBTA_i,PJRTA_i,PSTALL_i,PC_q,KLL1_i) begin if(PBX_i = '1' and FC = '0' and PSTALL_i = '0' and KLL1_i = '0') then PC_NS <= PBTA_i(ALEN-1 downto 3); elsif(PJRX_i = '1' and FC = '0' and PSTALL_i = '0') then PC_NS <= PJRTA_i(ALEN-1 downto 3); elsif(FC = '1' or PSTALL_i = '0') then PC_NS <= PC_NS_FC; else PC_NS <= PC_q; end if; end process; -- PC no-stall even flag process(PBX_i,PJRX_i,FC,EVEN_PC_NS_FC,PBTA_i,PJRTA_i,PSTALL_i,PC_q,KLL1_i) begin if(PBX_i = '1' and FC = '0' and PSTALL_i = '0' and KLL1_i = '0') then EVEN_PC_NS <= not(PBTA_i(2)); elsif(PJRX_i = '1' and FC = '0' and PSTALL_i = '0') then EVEN_PC_NS <= not(PJRTA_i(2)); elsif(FC = '1' or PSTALL_i = '0') then EVEN_PC_NS <= EVEN_PC_NS_FC; else EVEN_PC_NS <= '1'; end if; end process; -- Current cycle PC value mux. -- ETVA_i can be true exception vector, an address from CSR MEPC, -- a re-fetch address, debug memory address or a resume address. -- STRTPC_i can be the reset vector or an address from CSR MRV01HA. process(STRT_i,EXCP_i,ERET_i,RFTCH_i,ETVA_i,BJX_i,BJTA_i,PBX_i,PBTA_i, PCP8_q,DHALT_i,STRTPC_i) begin if( BJX_i = '1' and (EXCP_i = '0' and ERET_i = '0' and RFTCH_i = '0' and DHALT_i = '0') ) then -- Note: the complicated if-condition allows to remove one -- muxing level on BJTA_i path. PC_NS_FC <= BJTA_i(ALEN-1 downto 3); EVEN_PC_NS_FC <= not(BJTA_i(2)); elsif( EXCP_i = '1' or ERET_i = '1' or RFTCH_i = '1' or DHALT_i = '1' ) then PC_NS_FC <= ETVA_i(ALEN-1 downto 3); EVEN_PC_NS_FC <= not(ETVA_i(2)); elsif(STRT_i = '1') then PC_NS_FC <= STRTPC_i(ALEN-1 downto 3); EVEN_PC_NS_FC <= not(STRTPC_i(2)); else PC_NS_FC <= PCP8_q; EVEN_PC_NS_FC <= '1'; end if; end process; -- Current cycle PC PC <= PC_NS; -- Even PC flag EVEN_PC <= EVEN_PC_NS; -- Fetch addresses -- instruction #0 address is always an even word address, while -- instruction #1 address is always an odd word one. IADR0_o <= PC & "000"; IADR1_o <= PC & "100"; -- A misaligned instruction address can be generated only -- by a B/J instruction. process(BJX_i,PBX_i,PJRX_i,BJTA_i,PJRTA_i,PBTA_i,KLL1_i) begin IADR_MIS_o <= '0'; if(BJX_i = '1' and BJTA_i(1 downto 0) /= "00") then IADR_MIS_o <= '1'; elsif(PBX_i = '1' and PBTA_i(1 downto 0) /= "00" and KLL1_i = '0') then IADR_MIS_o <= '1'; elsif(PJRX_i = '1' and PJRTA_i(1 downto 0) /= "00") then IADR_MIS_o <= '1'; end if; end process; end ARC;