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

Subversion Repositories rv01_riscv_core

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

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2015 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 CSR's unit
---------------------------------------------------------------
 
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_ARITH_PKG.all;
use WORK.RV01_FUNCS_PKG.all;
use WORK.RV01_OP_PKG.all;
use WORK.RV01_CSR_PKG.all;
--use WORK.RV01_CFG_PKG.all;
 
entity RV01_CSRU is
  generic(
    PXE : std_logic := '1';
    FPU_PRESENT : std_logic := '0';
    NW : natural := 2
  );
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
    IX1_V0_i : in std_logic;
    CS_OP_i : in CS_OP_T;
    RS1_i : in RID_T;
    ADR_i : in signed(12-1 downto 0);
    WE_i : in std_logic;
    CSRD_i : in SDWORD_T;
    EXCP_i : in std_logic;
    EPC_i : in ADR_T;
    ECAUSE_i : in std_logic_vector(5-1 downto 0);
    EBADR_i : in ADR_T;
    ERET_i : in std_logic;
    IX3_V_i : in std_logic_vector(NW-1 downto 0);
    NOPR_i : in std_logic;
    HALT_i : in std_logic;
    STOPCYCLE_i : in std_logic;
    STOPTIME_i : in std_logic;
    --
    MFROMHOST_WE_i : in std_logic;
    MFROMHOST_i : in std_logic_vector(SDLEN-1 downto 0);
    -- Debug interface
    DMODE_i : in std_logic; -- debug mode flag
    DIE_i : in std_logic; -- debug int. enable flag
    -- Control port
    CPRE_i : in std_logic;
    CPWE_i : in std_logic;
    CPADR_i : in std_logic_vector(17-1 downto 0);
    CPD_i : in std_logic_vector(SDLEN-1 downto 0);
 
    PXE_o : out std_logic;
    MSTATUS_o : out SDWORD_T;
    MEPC_o : out ADR_T;
    MBASE_o : out ADR_T;
    MBOUND_o : out ADR_T;
    MIBASE_o : out ADR_T;
    MIBOUND_o : out ADR_T;
    MDBASE_o : out ADR_T;
    MDBOUND_o : out ADR_T;
    --RSTVA_o : out ADR_T;
    ETVA_o : out ADR_T;
    MTOHOST_o : out std_logic_vector(SDLEN-1 downto 0);
    MTOHOST_OE_o : out std_logic;
    ILLG_o : out std_logic;
    SFT_INT_o : out std_logic;
    TMR_INT_o : out std_logic;
    FFLAGS_o : out std_logic_vector(5-1 downto 0);
    FRM_o : out std_logic_vector(3-1 downto 0);
    IE_o : out std_logic;
    CSRQ_o : out SDWORD_T;
    -- Control port
    CPQ_o : out std_logic_vector(SDLEN-1 downto 0)
  );
end RV01_CSRU;
 
architecture ARC of RV01_CSRU is
 
  constant MAX_CNT : natural := 2147483647; --2**(SDLEN-1)-1;
 
  constant MSIP : natural := 3;
  constant MTIP : natural := 7;
  constant MSIE : natural := 3;
  constant MTIE : natural := 7;
 
  signal CS_OP_q : CS_OP_T;
  signal CS_OP_V : std_logic;
  signal CSRD_q,ICSRD : SDWORD_T;
  signal RS1_q : RID_T;
  signal WE_q,IWE : std_logic;
  signal ADR_q : signed(12-1 downto 0);
  signal MSTATUS_q : SDWORD_T;
  signal MTVEC_q : SDWORD_T;
  signal MIE_q : SDWORD_T;
  --signal MTIMECMP_q : SDWORD_T;
  signal MTIMECMP_q : natural range 0 to MAX_CNT;
  signal MTIME,MTIME_q,MTIME_q2 : natural range 0 to MAX_CNT;
  signal MTIMEH,MTIMEH_q : natural range 0 to MAX_CNT;
  signal MTIME_INC,MTIMEH_INC : std_logic;
  signal MSCRATCH_q : SDWORD_T;
  signal MEPC_q : SDWORD_T;
  signal MCAUSE_q : SDWORD_T;
  signal MBADADDR_q : SDWORD_T;
  signal MIP_q : SDWORD_T;
  signal MBASE_q : SDWORD_T;
  signal MBOUND_q : SDWORD_T;
  signal MIBASE_q : SDWORD_T;
  signal MIBOUND_q : SDWORD_T;
  signal MDBASE_q : SDWORD_T;
  signal MDBOUND_q : SDWORD_T;
  signal MTDELEG_q : SDWORD_T;
  signal MTOHOST_q : SDWORD_T;
  signal MFROMHOST_q : SDWORD_T;
  signal MRV01CC_q : SDWORD_T;
  signal CSRQ,CSRQ_q,CSRQ_q2 : SDWORD_T;
  signal ILLG,ILLG_q,ILLG_q2 : std_logic;
  signal ADR_ERR : std_logic;
  signal TMR_MTCH,TMR_INT,TMR_INT_q : std_logic; 
  signal SFT_INT,SFT_INT_q : std_logic; 
  signal MMODE : std_logic;
  signal MTOHOST_OE,MTOHOST_OE_q : std_logic;
  signal UCYCLE,UCYCLE_q,UCYCLE_q2 : natural range 0 to MAX_CNT;
  signal UCYCLEH,UCYCLEH_q : natural range 0 to MAX_CNT;
  signal UINSTRET,UINSTRET_q,UINSTRET_q2 : natural range 0 to MAX_CNT;
  signal UINSTRETH,UINSTRETH_q : natural range 0 to MAX_CNT;
  signal USTATS_q : SDWORD_T;
  signal UCYCLEH_INC,UINSTRETH_INC : std_logic;
  signal UFCSR_q : SDWORD_T;
  signal UFRM_q : SDWORD_T;
  signal VM : std_logic_vector(4-1 downto 0);
  signal IADR,IADR_q : unsigned(12-1 downto 0);
  --signal RSTVA_q : ADR_T;
  signal UTRPVA_q : ADR_T;
  signal MTRPVA_q : ADR_T;
  signal IBASE : ADR_T;
  signal DBASE : ADR_T;
  signal CPQ : SDWORD_T;
  signal CP_WE_q : std_logic;
  signal CP_IADR,CP_IADR_q : unsigned(12-1 downto 0);
  signal CP_D_q : SDWORD_T;
 
  function push_stack(
    S : SDWORD_T;
    D : std_logic_vector(3-1 downto 0)
  ) return SDWORD_T is
    variable TMP : SDWORD_T;
  begin
    TMP(SDLEN-1 downto 12) := S(SDLEN-1 downto 12);
    TMP(12-1 downto 3) := S(9-1 downto 0);
    TMP(3-1 downto 0) := to_signed(D);
    return(TMP);
  end function;
 
  function pop_stack(
    S : SDWORD_T;
    D : std_logic_vector(3-1 downto 0)
  ) return SDWORD_T is
    variable TMP : SDWORD_T;
  begin
    TMP(SDLEN-1 downto 12) := S(SDLEN-1 downto 12);
    TMP(12-1 downto 9) := to_signed(D);
    TMP(9-1 downto 0) := S(12-1 downto 3);
    return(TMP);
  end function;
 
  function update_csr(
    PREVD : SDWORD_T;
    MSK : SDWORD_T;
    NEWD : SDWORD_T
  ) return SDWORD_T is
    variable TMP1,TMP2,TMP3 : SDWORD_T;
  begin
    -- clear new data non-writable bits
    TMP1 := NEWD and MSK;
    -- clear previous data writable bits
    TMP2 := PREVD and not(MSK);
    -- build merged data
    TMP3 := TMP1 or TMP2;
    return(TMP3);
  end function;
 
begin
 
  ----------------------------------------------
 
  IADR <= to_unsigned(ADR_i);
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        WE_q <= '0';
      else
        WE_q <= WE_i;
      end if;
      CS_OP_q <= CS_OP_i;
      IADR_q <= IADR;
      CSRD_q <= CSRD_i;
      RS1_q <= RS1_i;
    end if;
  end process;
 
  IWE <= WE_q and not(HALT_i);
 
  ----------------------------------------------
 
  CP_IADR <= to_unsigned(CPADR_i(14-1 downto 2));
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then     
      if(RST_i = '1') then
        CP_WE_q <= '0';
      else
        CP_WE_q <= CPWE_i and CPADR_i(16);
      end if;
    end if;
  end process;
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then     
      CP_IADR_q <= CP_IADR;
      CP_D_q <= to_signed(CPD_i);
    end if;
  end process;
 
  ----------------------------------------------
 
  process(CS_OP_q,CSRD_q,RS1_q,CSRQ_q)
    variable ZXRS1 : SDWORD_T;
  begin
 
    -- zero-extended RS1
    ZXRS1(log2(REGNUM)-1 downto 0) :=
      to_signed(RS1_q,log2(REGNUM));
    ZXRS1(SDLEN-1 downto log2(REGNUM)) := (others => '0');
 
    case CS_OP_q is
      when CS_RW =>
        ICSRD <= CSRD_q;
      when CS_RS =>
        if(RS1_q = 0) then
          ICSRD <= CSRD_q;
        else
          ICSRD <= CSRQ_q or CSRD_q;
        end if;
      when CS_RC =>
        if(RS1_q = 0) then
          ICSRD <= CSRD_q;
        else
          ICSRD <= CSRQ_q and not(CSRD_q);
        end if;
      when CS_RWI =>
        ICSRD <= ZXRS1;
      when CS_RSI =>
        if(RS1_q = 0) then
          ICSRD <= CSRD_q;
        else
          ICSRD <= CSRQ_q or ZXRS1;
        end if;
      when CS_RCI =>
        if(RS1_q = 0) then
          ICSRD <= CSRD_q;
        else
          ICSRD <= CSRQ_q and not(ZXRS1);
        end if;
      when others =>
        ICSRD <= CSRD_q;        
    end case;
  end process;
 
  CS_OP_V <= IX1_V0_i when (
    CS_OP_i = CS_RW or
    CS_OP_i = CS_RS or
    CS_OP_i = CS_RC or
    CS_OP_i = CS_RWI or
    CS_OP_i = CS_RSI or
    CS_OP_i = CS_RCI
  ) else '0';
 
  ----------------------------------------------
  -- MSTATUS register
  ----------------------------------------------
 
  -- Note: mode/IE stack is used to handle debug
  -- mode too, this however works only if supervisor
  -- and hypervisor modes are not implemented (otherwise
  -- a mode/IE pair may get deleted).
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MSTATUS_q <= MSTATUS_RST;
      elsif(CP_WE_q = '1' and CP_IADR_q = MSTATUS_ADR and DMODE_i = '1') then
        MSTATUS_q <= update_csr(MSTATUS_q,MSTATUS_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MSTATUS_ADR and MMODE = '1') then
        MSTATUS_q <= update_csr(MSTATUS_q,MSTATUS_WMSK,ICSRD);
      elsif(EXCP_i = '1') then
        MSTATUS_q <= push_stack(MSTATUS_q,"110");
      elsif(ERET_i = '1') then
        MSTATUS_q <= pop_stack(MSTATUS_q,"001");
      end if;
    end if;
  end process;
 
  -- Machine mode flag
  MMODE <= '1' when (
    MSTATUS_q(2 downto 1) = "11" or DMODE_i = '1'
  ) else '0';
 
  -- Interrupt Enable flag
  IE_o <= '0' when ( 
    (DMODE_i = '1') or 
    (DIE_i = '0')
  ) else MSTATUS_q(0);
 
  -- Virtual addressing env.
  VM <= to_std_logic_vector(MSTATUS_q(21 downto 18));
 
  MSTATUS_o <= MSTATUS_q;
 
  ----------------------------------------------
  -- MTVEC register
  ----------------------------------------------
 
  -- MTVEC is a R/W register, but only MTVEC_LO and
  -- MTVEC_HI patterns can be written to it.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTVEC_q <= to_signed(MTVEC_LO);
      elsif(CP_WE_q = '1' and CP_IADR_q = MTVEC_ADR and DMODE_i = '1') then
        MTVEC_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MTVEC_ADR and MMODE = '1') then
        if(to_unsigned(ICSRD) = MTVEC_LO) then
          MTVEC_q <= to_signed(MTVEC_LO);
        elsif(to_unsigned(ICSRD) = MTVEC_HI) then
          MTVEC_q <= to_signed(MTVEC_HI);
        end if;
      end if;
    end if;
  end process;
 
  -- Set reset, user mode trap and machine mode trap vectors
  -- according to mtvec value (at reset, trap vectors location
  -- is set to "low").
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UTRPVA_q <= UTRAP_VA_LO;
        MTRPVA_q <= MTRAP_VA_LO;
      elsif(CP_WE_q = '1' and CP_IADR_q = MTVEC_ADR and DMODE_i = '1') then
        if(to_unsigned(CP_D_q) = MTVEC_LO) then
          UTRPVA_q <= UTRAP_VA_LO;
          MTRPVA_q <= MTRAP_VA_LO;
        elsif(to_unsigned(CP_D_q) = MTVEC_HI) then
          UTRPVA_q <= UTRAP_VA_HI;
          MTRPVA_q <= MTRAP_VA_HI;
        end if;
      elsif(IWE = '1' and IADR_q = MTVEC_ADR and MMODE = '1') then
        if(to_unsigned(ICSRD) = MTVEC_LO) then
          UTRPVA_q <= UTRAP_VA_LO;
          MTRPVA_q <= MTRAP_VA_LO;
        elsif(to_unsigned(ICSRD) = MTVEC_HI) then
          UTRPVA_q <= UTRAP_VA_HI;
          MTRPVA_q <= MTRAP_VA_HI;
        end if;
      end if;
    end if;
  end process;
 
  -- exception trap vector address
  ETVA_o <= 
    MTRPVA_q when MMODE = '1' else 
    UTRPVA_q;
 
  ----------------------------------------------
  -- MTDELEG register
  ----------------------------------------------
 
  -- This register is not implemented.
 
  MTDELEG_q <= (others => '0');
 
  ----------------------------------------------
  -- MIE register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MIE_q <= (others => '0'); 
      elsif(CP_WE_q = '1' and CP_IADR_q = MIE_ADR and DMODE_i = '1') then
        MIE_q <= update_csr(MIE_q,MIE_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MIE_ADR and MMODE = '1') then
        MIE_q <= update_csr(MIE_q,MIE_WMSK,ICSRD);
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- MTIMECMP register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTIMECMP_q <= 0;
      elsif(CP_WE_q = '1' and CP_IADR_q = MTIMECMP_ADR and DMODE_i = '1') then
        MTIMECMP_q <= to_integer(CP_D_q);
      elsif(IWE = '1' and IADR_q = MTIMECMP_ADR and MMODE = '1') then
        MTIMECMP_q <= to_integer(ICSRD);
      end if;
    end if;
  end process;
 
  -- TMR_INT_q remains asserted after an TMR_INT pulse
  -- until this event can be recorded in MIP register
  -- (this precaution is needed to insure that TMR_INT
  -- pulse is not lost because of a write to MIP).
 
  TMR_INT <= '1' when (MTIMECMP_q = MTIME_q) else '0';
 
  --process(CLK_i)
  --begin
  --  if(CLK_i = '1' and CLK_i'event) then
  --    if(RST_i = '1') then
  --      TMR_INT_q <= '0';
  --    elsif(TMR_INT_q = '0' and TMR_INT = '1') then
  --      TMR_INT_q <= '1';
  --    elsif(MIP_q(MTIE) = '1') then
  --      TMR_INT_q <= '0';
  --    end if;
  --  end if;
  --end process;
 
  ----------------------------------------------
  -- MTIME register 
  -- (Machine Mode Cycles counter)
  ----------------------------------------------
 
  -- mcycle register is incremented at every cycle,
  -- and wraps-up when count reaches MAX_CNT value.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTIME_q <= 0;
      elsif(CP_WE_q = '1' and CP_IADR_q = MTIME_ADR and DMODE_i = '1') then
        MTIME_q <= to_integer(CP_D_q);
      elsif(IWE = '1' and IADR_q = MTIME_ADR and MMODE = '1') then
        MTIME_q <= to_integer(ICSRD);
      else
        MTIME_q <= MTIME;
      end if;
      MTIME_q2 <= MTIME_q;
    end if;
  end process;
 
  process(MTIME_q)
  begin
    if(MTIME_q < MAX_CNT) then
      MTIME <= MTIME_q + 1;
      MTIMEH_INC <= '0';
    else
      MTIME <= 0;
      MTIMEH_INC <= '1';
    end if;
  end process;
 
  -- ucycleh register is incremented when ucycle
  -- one wraps-up. ucycleh wraps-up when count
  -- reaches MAX_CNT value.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTIMEH_q <= 0;
      elsif(CP_WE_q = '1' and CP_IADR_q = MTIMEH_ADR and DMODE_i = '1') then
        MTIMEH_q <= to_integer(CP_D_q);
      elsif(IWE = '1' and IADR_q = MTIMEH_ADR and MMODE = '1') then
        MTIMEH_q <= to_integer(ICSRD);
      elsif(MTIMEH_INC = '1') then
        MTIMEH_q <= MTIMEH;
      end if;
    end if;
  end process;
 
  process(MTIMEH_q)
  begin
    if(MTIMEH_q < MAX_CNT) then
      MTIMEH <= MTIMEH_q + 1;
    else
      MTIMEH <= 0;
    end if;
  end process;
 
  ----------------------------------------------
  -- MSCRATCH register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MSCRATCH_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MSCRATCH_ADR and DMODE_i = '1') then
        MSCRATCH_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MSCRATCH_ADR and MMODE = '1') then
        MSCRATCH_q <= ICSRD; --CSRD_q;
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- MEPC register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MEPC_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MEPC_ADR and DMODE_i = '1') then
        MEPC_q <= update_csr(MEPC_q,MEPC_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MEPC_ADR and MMODE = '1') then
        MEPC_q <= update_csr(MEPC_q,MEPC_WMSK,ICSRD);
      elsif(EXCP_i = '1') then
        MEPC_q <= to_signed(EPC_i);
      end if;
    end if;
  end process;
 
  -- mepc content must be made available to fetch
  -- logic when returning from an exception.
 
  MEPC_o <= to_unsigned(MEPC_q);
 
  ----------------------------------------------
  -- MCAUSE register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MCAUSE_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MCAUSE_ADR and DMODE_i = '1') then
        MCAUSE_q <= update_csr(MCAUSE_q,MCAUSE_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MCAUSE_ADR and MMODE = '1') then
        MCAUSE_q <= update_csr(MCAUSE_q,MCAUSE_WMSK,ICSRD);
      elsif(EXCP_i = '1') then
        MCAUSE_q(SDLEN-2 downto 4) <= (others => '0');
        if(ECAUSE_i = UMCALL and MMODE = '1') then
          MCAUSE_q(4-1 downto 0) <= to_signed(MMCALL(4-1 downto 0));
        else 
          MCAUSE_q(4-1 downto 0) <= to_signed(ECAUSE_i(4-1 downto 0)); 
        end if;
        MCAUSE_q(SDLEN-1) <= ECAUSE_i(4);
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- MBADADDR register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MBADADDR_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MBADADDR_ADR and DMODE_i = '1') then
        MBADADDR_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MBADADDR_ADR and MMODE = '1') then
        MBADADDR_q <= ICSRD;
      elsif(EXCP_i = '1') then 
        MBADADDR_q <= to_signed(EBADR_i);
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- MIP register
  ----------------------------------------------
 
  -- Note: while timer interrupt pending bit is implicilty
  -- cleared by writing mtimecmp register, software interrupt
  -- pending bit must be explicitly cleared by writing mip
  -- register.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MIP_q <= (others => '0'); 
      elsif(CP_WE_q = '1' and CP_IADR_q = MIP_ADR and DMODE_i = '1') then
        MIP_q <= update_csr(MIP_q,MIP_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MIP_ADR and MMODE = '1') then
        -- mip is written as a CSR (even if only MSIP bit is writable)
        MIP_q <= update_csr(MIP_q,MIP_WMSK,ICSRD);
      elsif(TMR_INT = '1') then 
        MIP_q(MTIP) <= '1';
      elsif(
        (IWE = '1' and IADR_q = MTIMECMP_ADR and MMODE = '1') or
        (CP_WE_q = '1' and CP_IADR_q = MTIMECMP_ADR and DMODE_i = '1') 
      ) then
        -- mip[MTIP] is cleared when mtimecmp register is written
        MIP_q(MTIP) <= '0';
      end if;
    end if;
  end process;
 
  -- Timer Interrupt exception is actually raised only if:
  -- 1) mip[MTIP] is set, AND
  -- 2) timer int's are enabled by mie[MTIE], AND
  -- 3) exceptions are anabled by mstatus[IE].
 
  TMR_INT_o <= MIP_q(MTIP) and MIE_q(MTIE) and MSTATUS_q(0);
 
  --process(CLK_i)
  --begin
  --  if(CLK_i = '1' and CLK_i'event) then
  --    if(RST_i = '1') then
  --      TMR_INT_q <= '0';
  --    else
  --      TMR_INT_q <= TMR_INT;
  --    end if;
  --  end if;
  --end process;
 
  --TMR_INT_o <= TMR_INT_q;
 
  -- Soft Interrupt exception is actually raised only if:
  -- 1) mip[MSIP] is set, AND
  -- 2) soft int's are enabled by mie[MSIE], AND
  -- 3) exceptions are anabled by mstatus[IE].
 
  SFT_INT <= MIP_q(MSIP) and MIE_q(MSIE) and MSTATUS_q(0);
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        SFT_INT_q <= '0';
      else
        SFT_INT_q <= SFT_INT;
      end if;
    end if;
  end process;
 
  SFT_INT_o <= SFT_INT_q;
 
  ----------------------------------------------
  -- MBASE register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MBASE_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MBASE_ADR and DMODE_i = '1') then
        MBASE_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MBASE_ADR and MMODE = '1') then
        MBASE_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MBASE_o <= to_unsigned(MBASE_q);
 
  ----------------------------------------------
  -- MBOUND register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MBOUND_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MBOUND_ADR and DMODE_i = '1') then
        MBOUND_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MBOUND_ADR and MMODE = '1') then
        MBOUND_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MBOUND_o <= to_unsigned(MBOUND_q);
 
  ----------------------------------------------
  -- MIBASE register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MIBASE_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MIBASE_ADR and DMODE_i = '1') then
        MIBASE_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MIBASE_ADR and MMODE = '1') then
        MIBASE_q <= ICSRD;
      elsif(
        IWE = '1' and IADR_q = MBASE_ADR and 
        MMODE = '1' and VM = MBBID
      ) then
        MIBASE_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MIBASE_o <= to_unsigned(MIBASE_q);
 
  ----------------------------------------------
  -- MIBOUND register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MIBOUND_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MIBOUND_ADR and DMODE_i = '1') then
        MIBOUND_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MIBOUND_ADR and MMODE = '1') then
        MIBOUND_q <= ICSRD;
      elsif(
        IWE = '1' and IADR_q = MBOUND_ADR and 
        MMODE = '1' and VM = MBBID
      ) then
        MIBOUND_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MIBOUND_o <= to_unsigned(MIBOUND_q);
 
  ----------------------------------------------
  -- MDBASE register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MDBASE_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MDBASE_ADR and DMODE_i = '1') then
        MDBASE_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MDBASE_ADR and MMODE = '1') then
        MDBASE_q <= ICSRD;
      elsif(
        IWE = '1' and IADR_q = MBASE_ADR and
        MMODE = '1' and VM = MBBID
      ) then
        MDBASE_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MDBASE_o <= to_unsigned(MDBASE_q);
 
  ----------------------------------------------
  -- MDBOUND register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MDBOUND_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MDBOUND_ADR and DMODE_i = '1') then
        MDBOUND_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MDBOUND_ADR and MMODE = '1') then
        MDBOUND_q <= ICSRD;
      elsif(
        IWE = '1' and IADR_q = MBOUND_ADR and 
        MMODE = '1' and VM = MBBID
      ) then
        MDBOUND_q <= ICSRD;        
      end if;
    end if;
  end process;
 
  MDBOUND_o <= to_unsigned(MDBOUND_q);
 
  ----------------------------------------------
  -- MTOHOST register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTOHOST_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MTOHOST_ADR and DMODE_i = '1') then
        MTOHOST_q <= CP_D_q;
      elsif(IWE = '1' and IADR_q = MTOHOST_ADR and MMODE = '1') then
        MTOHOST_q <= ICSRD;
      end if;
    end if;
  end process;
 
  MTOHOST_OE <= IWE when(
    IADR_q = MTOHOST_ADR and MMODE = '1'
  ) else '0';
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MTOHOST_OE_q <= '0';
      else
        MTOHOST_OE_q <= MTOHOST_OE ;
      end if;
    end if;
  end process;
 
  MTOHOST_OE_o <= MTOHOST_OE_q;
 
  MTOHOST_o <= to_std_logic_vector(MTOHOST_q);
 
  ----------------------------------------------
  -- MFROMHOST register
  ----------------------------------------------
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MFROMHOST_q <= (others => '0');
      elsif(CP_WE_q = '1' and CP_IADR_q = MFROMHOST_ADR and DMODE_i = '1') then
        MFROMHOST_q <= CP_D_q;
      elsif(MFROMHOST_WE_i = '1') then
        MFROMHOST_q <= to_signed(MFROMHOST_i);
      elsif(IWE = '1' and IADR_q = MFROMHOST_ADR and MMODE = '1') then
        MFROMHOST_q <= ICSRD;
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- RV01 Core Control register (MRV01CC)
  ----------------------------------------------
 
  -- This register allows to enable/disable 
  -- implementation dependent features. In the
  -- this version of RV01 core, the only feature
  -- that can be enabled/disabled through MRV01CC
  -- register is parallel execution capability.
 
  GPXE_1 : if(PXE = '1') generate
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        MRV01CC_q <= MRV01CC_RST;
      elsif(CP_WE_q = '1' and CP_IADR_q = MRV01CC_ADR and DMODE_i = '1') then
        MRV01CC_q <= update_csr(MRV01CC_q,MRV01CC_WMSK,CP_D_q);
      elsif(IWE = '1' and IADR_q = MRV01CC_ADR and MMODE = '1') then
        MRV01CC_q <= update_csr(MRV01CC_q,MRV01CC_WMSK,ICSRD);
      end if;
    end if;
  end process;
 
  end generate;
 
  GPXE_0 : if(PXE = '0') generate
 
  MRV01CC_q <= (others => '0');
 
  end generate;
 
  PXE_o <= MRV01CC_q(0);
 
  ----------------------------------------------
  -- UTIME/H registers
  -- (User Mode Cycles counter)
  ----------------------------------------------
 
  -- ucycle register is incremented at every cycle,
  -- and wraps-up when count reaches MAX_CNT value.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UCYCLE_q <= 0;
      else
        UCYCLE_q <= UCYCLE;
      end if;
      UCYCLE_q2 <= UCYCLE_q;
    end if;
  end process;
 
  process(UCYCLE_q,STOPCYCLE_i,STOPTIME_i)
  begin
    if(UCYCLE_q < MAX_CNT and STOPCYCLE_i = '0' and STOPTIME_i = '0') then
      UCYCLE <= UCYCLE_q + 1;
      UCYCLEH_INC <= '0';
    else
      UCYCLE <= 0;
      UCYCLEH_INC <= '1';
    end if;
  end process;
 
  -- ucycleh register is incremented when ucycle
  -- one wraps-up. ucycleh wraps-up when count
  -- reaches MAX_CNT value.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UCYCLEH_q <= 0;
      elsif(UCYCLEH_INC = '1' and STOPCYCLE_i = '0' and STOPTIME_i = '0') then
        UCYCLEH_q <= UCYCLEH;
      end if;
    end if;
  end process;
 
  process(UCYCLEH_q)
  begin
    if(UCYCLEH_q < MAX_CNT) then
      UCYCLEH <= UCYCLEH_q + 1;
    else
      UCYCLEH <= 0;
    end if;
  end process;
 
  ----------------------------------------------
  -- Retired instructions counter
  ----------------------------------------------
 
  -- uinstret register is incremented every time
  -- an instruction is retired (this event may occur
  -- twice per cycle), and wraps-up when count reaches
  -- MAX_CNT value.
  -- Instruction eret is a special case because it
  -- must be counted as a valid instruction even if
  -- its valid bit is cleared.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UINSTRET_q <= 0;
      else
        UINSTRET_q <= UINSTRET;
      end if;
      UINSTRET_q2 <= UINSTRET_q;
    end if;
  end process;
 
  process(UINSTRET_q,IX3_V_i,ERET_i,STOPCYCLE_i)
  begin
    if(IX3_V_i = "11" and STOPCYCLE_i = '0') then
      if(UINSTRET_q < MAX_CNT-1) then
        UINSTRET <= UINSTRET_q + 2;
        UINSTRETH_INC <= '0';
      elsif(UINSTRET_q = MAX_CNT-1) then
        UINSTRET <= 0;
        UINSTRETH_INC <= '1';
      else
        UINSTRET <= 1;
        UINSTRETH_INC <= '1';
      end if;
    elsif((IX3_V_i(0) = '1' or IX3_V_i(1) = '1') and STOPCYCLE_i = '0') then
      if(UINSTRET_q < MAX_CNT) then
        UINSTRET <= UINSTRET_q + 1;
        UINSTRETH_INC <= '0';
      else
        UINSTRET <= 0;
        UINSTRETH_INC <= '1';
      end if;
    else
      UINSTRET <= UINSTRET_q;
      UINSTRETH_INC <= '0';
    end if;
  end process;
 
  -- uinstreth register is incremented when uinstret
  -- one wraps-up. uinstreth wraps-up when count
  -- reaches MAX_CNT value.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UINSTRETH_q <= 0;
      elsif(UINSTRETH_INC = '1' and STOPCYCLE_i = '0') then
        UINSTRETH_q <= UINSTRETH;
      end if;
    end if;
  end process;
 
  process(UINSTRETH_q)
  begin
    if(UINSTRETH_q < MAX_CNT) then
      UINSTRETH <= UINSTRETH_q + 1;
    else
      UINSTRETH <= 0;
    end if;
  end process;
 
  ----------------------------------------------
  -- UFCSR, UFFLAGS and UFRM registers
  ----------------------------------------------
 
  GF0_1 : if(FPU_PRESENT = '1') generate
 
  -- UFFLAGS register is implicitly implemented by UFCSR[4:0],
  -- while UFRM is explicitly implemented.
  -- A write to UFCSR modifies UFFLAGS[4:0] (implicitly) and
  -- UFRM[2:0] (explicitly).
  -- A write to UFFLAGS modifies UFCSR bits [4:0] only.
  -- A write to UFRM modifies UFRM and UFCSR bits [7:5].
 
  process(CLK_i)
  variable TMP : SDWORD_T;
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UFCSR_q <= (others => '0');
      elsif(IWE = '1' and IADR_q = UFCSR_ADR) then
        UFCSR_q <= update_csr(UFCSR_q,UFCSR_WMSK,ICSRD);
      elsif(IWE = '1' and IADR_q = UFFLAGS_ADR) then
        UFCSR_q <= update_csr(UFCSR_q,UFFLAGS_WMSK,ICSRD);
      elsif(IWE = '1' and IADR_q = UFRM_ADR) then
        TMP := update_csr(UFRM_q,UFRM_WMSK,ICSRD);
        UFCSR_q <= UFCSR_q(SDLEN-1 downto 8) & TMP(3-1 downto 0) & UFCSR_q(5-1 downto 0) ;
      end if;
    end if;
  end process;
 
  process(CLK_i)
  variable TMP : SDWORD_T;
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        UFRM_q <= (others => '0');
      elsif(IWE = '1' and IADR_q = UFCSR_ADR) then
        TMP := update_csr(UFCSR_q,UFCSR_WMSK,ICSRD);
        UFRM_q <= UFRM_q(SDLEN-1 downto 3) & TMP(3-1 downto 0);
      elsif(IWE = '1' and IADR_q = UFRM_ADR) then
        UFRM_q <= update_csr(UFRM_q,UFRM_WMSK,ICSRD);
      end if;
    end if;
  end process;
 
  FFLAGS_o <= to_std_logic_vector(UFCSR_q(5-1 downto 0));
  FRM_o <= to_std_logic_vector(UFCSR_q(8-1 downto 5));
 
  end generate;
 
  GF0_0 : if(FPU_PRESENT = '0') generate
 
  UFCSR_q <= (others => '0');
  UFRM_q <= (others => '0');
  FFLAGS_o <= (others => '0');
  FRM_o <= (others => '0');
 
  end generate;
 
  ----------------------------------------------
  -- Sodor "Stats" register
  ----------------------------------------------
 
  -- This register has been added only for partial
  -- compatibility with Sodor RISC-V core.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(IWE = '1' and IADR_q = USTATS_ADR) then
        USTATS_q <= ICSRD;
      end if;
    end if;
  end process;
 
  ----------------------------------------------
  -- CSR output mux
  ----------------------------------------------
 
  -- Notes:
  -- 1) utime(h) register is coincident with ucycle(h) register.
  -- 2) ucycleh and uinstreth are updated with one cycle delay
  -- with respect to ucycle and uinstret, therefore, in order to
  -- get consistent read values, one-cycle delayed version of
  -- ucycle and uinstret are accessed on reads.
  -- 3) mtime register is implemented as mcycle for a matter of
  -- uniformity with utime one.
  -- 4) one-cycle delayed version of mcycle is accessed on reads
  -- (see note #2).
 
  process(IADR,MSTATUS_q,MTVEC_q,MIE_q,MTIMECMP_q,MTIME_q2,MTIMEH_q,
    MSCRATCH_q,MEPC_q,MCAUSE_q,MBADADDR_q,MIP_q,MBASE_q,MBOUND_q,
    MIBASE_q,MIBOUND_q,MDBASE_q,MDBOUND_q,MTOHOST_q,MFROMHOST_q,
    UCYCLE_q2,UINSTRET_q2,UCYCLEH_q,UINSTRETH_q,UFCSR_q,UFRM_q,USTATS_q,
    MTDELEG_q,MRV01CC_q,VM,WE_i,MMODE
  )
  begin
    ADR_ERR <= '0';
    case IADR is
 
      -- User mode CSR's
 
      when UCYCLE_ADR =>
        CSRQ <= to_signed(UCYCLE_q2,SDLEN);
        ADR_ERR <= WE_i;
      when UTIME_ADR =>
        CSRQ <= to_signed(UCYCLE_q2,SDLEN);
        ADR_ERR <= WE_i;
      when UINSTRET_ADR =>
        CSRQ <= to_signed(UINSTRET_q2,SDLEN);
        ADR_ERR <= WE_i;
      when UCYCLEH_ADR =>
        CSRQ <= to_signed(UCYCLEH_q,SDLEN);
        ADR_ERR <= WE_i;
      when UTIMEH_ADR =>
        CSRQ <= to_signed(UCYCLEH_q,SDLEN);
        ADR_ERR <= WE_i;
      when UINSTRETH_ADR =>
        CSRQ <= to_signed(UINSTRETH_q,SDLEN);
        ADR_ERR <= WE_i;
      when UFCSR_ADR =>
        CSRQ <= UFCSR_q;
      when UFFLAGS_ADR =>
        CSRQ(5-1 downto 0) <= UFCSR_q(5-1 downto 0);
        CSRQ(SDLEN-1 downto 5) <= (others => '0');
      when UFRM_ADR =>
        CSRQ <= UFRM_q;
      when USTATS_ADR =>
        CSRQ <= USTATS_q;
 
      -- Machine mode CSR's
 
      when MCPUID_ADR =>
        CSRQ <= MCPUID_RO;
        ADR_ERR <= WE_i or not(MMODE);
      when MIMPID_ADR =>
        CSRQ <= MIMPID_RO;
        ADR_ERR <= WE_i or not(MMODE);
      when MHARTID_ADR =>
        CSRQ <= MHARTID_RO;
        ADR_ERR <= WE_i or not(MMODE);
      when MSTATUS_ADR =>
        CSRQ <= MSTATUS_q;
        ADR_ERR <= not(MMODE);
      when MTVEC_ADR =>
        CSRQ <= MTVEC_q;
        ADR_ERR <= not(MMODE);
      when MTDELEG_ADR =>
        CSRQ <= MTDELEG_q;
        ADR_ERR <= WE_i or not(MMODE);
      when MIE_ADR =>
        CSRQ <= MIE_q;
        ADR_ERR <= not(MMODE);
      when MTIMECMP_ADR =>
        CSRQ <= to_signed(MTIMECMP_q,SDLEN);
        ADR_ERR <= not(MMODE);
      when MTIME_ADR =>
        CSRQ <= to_signed(MTIME_q2,SDLEN);
        ADR_ERR <= not(MMODE);
      when MTIMEH_ADR =>
        CSRQ <= to_signed(MTIMEH_q,SDLEN);
        ADR_ERR <= not(MMODE);
      when MSCRATCH_ADR =>
        CSRQ <= MSCRATCH_q;
        ADR_ERR <= not(MMODE);
      when MEPC_ADR =>
        CSRQ <= MEPC_q;
        ADR_ERR <= not(MMODE);
      when MCAUSE_ADR =>
        CSRQ <= MCAUSE_q;
        ADR_ERR <= not(MMODE);
      when MBADADDR_ADR =>
        CSRQ <= MBADADDR_q;
        ADR_ERR <= not(MMODE);
      when MIP_ADR =>
        CSRQ <= MIP_q;
      when MBASE_ADR =>
        if(VM = MBBID) then -- is it correct?
          CSRQ <= MDBASE_q;
        else
          CSRQ <= MBASE_q;
        end if;
        ADR_ERR <= not(MMODE);
      when MBOUND_ADR =>
        if(VM = MBBID) then -- is it correct?
          CSRQ <= MDBOUND_q;
        else
          CSRQ <= MBOUND_q;
        end if;
        ADR_ERR <= not(MMODE);
      when MIBASE_ADR =>
        CSRQ <= MIBASE_q;
        ADR_ERR <= not(MMODE);
      when MIBOUND_ADR =>
        CSRQ <= MIBOUND_q;
        ADR_ERR <= not(MMODE);
      when MDBASE_ADR =>
        CSRQ <= MDBASE_q;
        ADR_ERR <= not(MMODE);
      when MDBOUND_ADR =>
        CSRQ <= MDBOUND_q;
        ADR_ERR <= not(MMODE);
      --when HTIMEW_ADR =>
      --  CSRQ <= HTIMEW_q;
      --when HTIMEHW_ADR =>
      --  CSRQ <= HTIMEHW_q;
      when MRV01CC_ADR =>
        CSRQ <= MRV01CC_q;
        ADR_ERR <= not(MMODE);
 
      -- Host interface CSR's
 
      when MTOHOST_ADR =>
        CSRQ <= MTOHOST_q;
        ADR_ERR <= not(MMODE);
      when MFROMHOST_ADR =>
        CSRQ <= MFROMHOST_q;
        ADR_ERR <= not(MMODE);
 
      when others =>
        CSRQ <= (others => '0');
        ADR_ERR <= '1';
 
    end case;
  end process;
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      CSRQ_q <= CSRQ;
    end if;
  end process;
 
  -- Illegal instruction exception must be raised if:
  -- 1) an un-existent CSR address is specified, OR
  -- 2) write access is attempted on a read-only CSR, OR
  -- 3) access is attempted on a CSR without appropriate
  -- privileges.
 
  ILLG <= CS_OP_V when (
    ADR_ERR = '1' or -- cases 1,2
    (IADR(9 downto 8) = "11" and MMODE = '0') -- case 3
  ) else '0';
 
  CSRQ_o <= CSRQ;
 
  ILLG_o <= ILLG;
 
  ----------------------------------------------
  -- Control port output
  ----------------------------------------------
 
  process(CP_IADR,MSTATUS_q,MTVEC_q,MIE_q,MTIMECMP_q,MTIME_q2,MTIMEH_q,
    MSCRATCH_q,MEPC_q,MCAUSE_q,MBADADDR_q,MIP_q,MBASE_q,MBOUND_q,
    MIBASE_q,MIBOUND_q,MDBASE_q,MDBOUND_q,MTOHOST_q,MFROMHOST_q,
    UCYCLE_q2,UINSTRET_q2,UCYCLEH_q,UINSTRETH_q,UFCSR_q,UFRM_q,USTATS_q,
    MTDELEG_q,MRV01CC_q,VM
  )
  begin
    case CP_IADR is
 
      -- User mode CSR's
 
      when UCYCLE_ADR =>
        CPQ <= to_signed(UCYCLE_q2,SDLEN);
      when UTIME_ADR =>
        CPQ <= to_signed(UCYCLE_q2,SDLEN);
      when UINSTRET_ADR =>
        CPQ <= to_signed(UINSTRET_q2,SDLEN);
      when UCYCLEH_ADR =>
        CPQ <= to_signed(UCYCLEH_q,SDLEN);
      when UTIMEH_ADR =>
        CPQ <= to_signed(UCYCLEH_q,SDLEN);
      when UINSTRETH_ADR =>
        CPQ <= to_signed(UINSTRETH_q,SDLEN);
      when UFCSR_ADR =>
        CPQ <= UFCSR_q;
      when UFFLAGS_ADR =>
        CPQ(5-1 downto 0) <= UFCSR_q(5-1 downto 0);
        CPQ(SDLEN-1 downto 5) <= (others => '0');
      when UFRM_ADR =>
        CPQ <= UFRM_q;
      when USTATS_ADR =>
        CPQ <= USTATS_q;
 
      -- Machine mode CSR's
 
      when MCPUID_ADR =>
        CPQ <= MCPUID_RO;
      when MIMPID_ADR =>
        CPQ <= MIMPID_RO;
      when MHARTID_ADR =>
        CPQ <= MHARTID_RO;
      when MSTATUS_ADR =>
        CPQ <= MSTATUS_q;
      when MTVEC_ADR =>
        CPQ <= MTVEC_q;
      when MTDELEG_ADR =>
        CPQ <= MTDELEG_q;
      when MIE_ADR =>
        CPQ <= MIE_q;
      when MTIMECMP_ADR =>
        CPQ <= to_signed(MTIMECMP_q,SDLEN);
      when MTIME_ADR =>
        CPQ <= to_signed(MTIME_q2,SDLEN);
      when MTIMEH_ADR =>
        CPQ <= to_signed(MTIMEH_q,SDLEN);
      when MSCRATCH_ADR =>
        CPQ <= MSCRATCH_q;
      when MEPC_ADR =>
        CPQ <= MEPC_q;
      when MCAUSE_ADR =>
        CPQ <= MCAUSE_q;
      when MBADADDR_ADR =>
        CPQ <= MBADADDR_q;
      when MIP_ADR =>
        CPQ <= MIP_q;
      when MBASE_ADR =>
        if(VM = MBBID) then -- is it correct?
          CPQ <= MDBASE_q;
        else
          CPQ <= MBASE_q;
        end if;
      when MBOUND_ADR =>
        if(VM = MBBID) then -- is it correct?
          CPQ <= MDBOUND_q;
        else
          CPQ <= MBOUND_q;
        end if;
      when MIBASE_ADR =>
        CPQ <= MIBASE_q;
      when MIBOUND_ADR =>
        CPQ <= MIBOUND_q;
      when MDBASE_ADR =>
        CPQ <= MDBASE_q;
      when MDBOUND_ADR =>
        CPQ <= MDBOUND_q;
      when MRV01CC_ADR =>
        CPQ <= MRV01CC_q;
 
      -- Host interface CSR's
 
      when MTOHOST_ADR =>
        CPQ <= MTOHOST_q;
      when MFROMHOST_ADR =>
        CPQ <= MFROMHOST_q;
 
      when others =>
        CPQ <= (others => '0');
 
    end case;
  end process;
 
  CPQ_o <= to_std_logic_vector(CPQ);
 
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.