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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 9 and 11

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 9 Rev 11
Line 102... Line 102...
    csr_wdata_i   : in  std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data
    csr_wdata_i   : in  std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
    -- external interrupt --
    -- external interrupt --
    clic_irq_i    : in  std_ulogic; -- CLIC interrupt request
    clic_irq_i    : in  std_ulogic; -- CLIC interrupt request
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
 
    -- system time input from MTIME --
 
    time_i        : in  std_ulogic_vector(63 downto 0); -- current system time
    -- bus access exceptions --
    -- bus access exceptions --
    mar_i         : in  std_ulogic_vector(data_width_c-1 downto 0);  -- memory address register
    mar_i         : in  std_ulogic_vector(data_width_c-1 downto 0);  -- memory address register
    ma_instr_i    : in  std_ulogic; -- misaligned instruction address
    ma_instr_i    : in  std_ulogic; -- misaligned instruction address
    ma_load_i     : in  std_ulogic; -- misaligned load data address
    ma_load_i     : in  std_ulogic; -- misaligned load data address
    ma_store_i    : in  std_ulogic; -- misaligned store data address
    ma_store_i    : in  std_ulogic; -- misaligned store data address
    be_instr_i    : in  std_ulogic; -- bus error on instruction access
    be_instr_i    : in  std_ulogic; -- bus error on instruction access
    be_load_i     : in  std_ulogic; -- bus error on load data access
    be_load_i     : in  std_ulogic; -- bus error on load data access
    be_store_i    : in  std_ulogic; -- bus error on store data access
    be_store_i    : in  std_ulogic; -- bus error on store data access
    bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
 
    bus_busy_i    : in  std_ulogic  -- bus unit is busy
    bus_busy_i    : in  std_ulogic  -- bus unit is busy
  );
  );
end neorv32_cpu_control;
end neorv32_cpu_control;
 
 
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
Line 138... Line 139...
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
    ci_return       : std_ulogic;
    ci_return       : std_ulogic;
    ci_return_nxt   : std_ulogic;
    ci_return_nxt   : std_ulogic;
    reset           : std_ulogic;
    reset           : std_ulogic;
    bus_err_ack     : std_ulogic;
    bus_err_ack     : std_ulogic;
 
    bus_reset       : std_ulogic;
  end record;
  end record;
  signal fetch_engine : fetch_engine_t;
  signal fetch_engine : fetch_engine_t;
 
 
  -- pre-decoder --
  -- pre-decoder --
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
Line 177... Line 179...
    branch_taken : std_ulogic; -- branch condition fullfilled
    branch_taken : std_ulogic; -- branch condition fullfilled
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
 
    sleep        : std_ulogic; -- CPU in sleep mode
 
    sleep_nxt    : std_ulogic; -- CPU in sleep mode
  end record;
  end record;
  signal execute_engine : execute_engine_t;
  signal execute_engine : execute_engine_t;
 
 
  -- trap controller --
  -- trap controller --
  type trap_ctrl_t is record
  type trap_ctrl_t is record
Line 210... Line 214...
  -- CPU control signals --
  -- CPU control signals --
  signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
  signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
 
 
  -- fast bus access --
  -- fast bus access --
  signal bus_fast_ir : std_ulogic;
  signal bus_fast_ir : std_ulogic;
  signal bus_fast_rd : std_ulogic;
 
  signal bus_fast_wr : std_ulogic;
 
 
 
  -- RISC-V control and status registers (CSRs) --
  -- RISC-V control and status registers (CSRs) --
  type csr_t is record
  type csr_t is record
    we           : std_ulogic; -- write enable
    we           : std_ulogic; -- write enable
    we_nxt       : std_ulogic;
    we_nxt       : std_ulogic;
Line 226... Line 228...
    mip_msip     : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
    mip_msip     : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
    mie_msie     : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
    mie_msie     : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
    mie_meie     : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
    mie_meie     : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
    mie_mtie     : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
    mie_mtie     : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
    mepc         : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
    mepc         : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
    mcause       : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
    mcause       : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/W)
    mtvec        : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
    mtvec        : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
    mtval        : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
    mtval        : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/W)
    mscratch     : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
    mscratch     : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
    cycle        : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit
    mcycle       : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
    instret      : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit
    minstret     : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
    cycleh       : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-)
    mcycleh      : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
    instreth     : std_ulogic_vector(31 downto 0); -- instreth (R/-)
    minstreth    : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
    misa_c_en    : std_ulogic; -- misa: C extension enable bit (R/W)
 
    misa_m_en    : std_ulogic; -- misa: M extension enable bit (R/W)
 
  end record;
  end record;
  signal csr : csr_t;
  signal csr : csr_t;
 
 
  signal cycle_msb   : std_ulogic;
  signal mcycle_msb   : std_ulogic;
  signal instret_msb : std_ulogic;
  signal minstret_msb : std_ulogic;
 
 
  -- illegal instruction check --
  -- illegal instruction check --
  signal illegal_instruction : std_ulogic;
  signal illegal_instruction : std_ulogic;
  signal illegal_register    : std_ulogic; -- only for E-extension
  signal illegal_register    : std_ulogic; -- only for E-extension
  signal illegal_compressed  : std_ulogic; -- only fir C-extension
  signal illegal_compressed  : std_ulogic; -- only fir C-extension
Line 328... Line 328...
    fetch_engine.i_buf2_nxt      <= fetch_engine.i_buf2;
    fetch_engine.i_buf2_nxt      <= fetch_engine.i_buf2;
    fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
    fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
    fetch_engine.ci_reg_nxt      <= fetch_engine.ci_reg;
    fetch_engine.ci_reg_nxt      <= fetch_engine.ci_reg;
    fetch_engine.ci_return_nxt   <= fetch_engine.ci_return;
    fetch_engine.ci_return_nxt   <= fetch_engine.ci_return;
    fetch_engine.bus_err_ack     <= '0';
    fetch_engine.bus_err_ack     <= '0';
 
    fetch_engine.bus_reset       <= '0';
 
 
    -- instruction prefetch buffer interface --
    -- instruction prefetch buffer interface --
    ipb.we    <= '0';
    ipb.we    <= '0';
    ipb.clear <= '0';
    ipb.clear <= '0';
    ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
    ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
 
 
    -- state machine --
    -- state machine --
    case fetch_engine.state is
    case fetch_engine.state is
 
 
      when IFETCH_RESET => -- reset engine, prefetch buffer, get PC
      when IFETCH_RESET => -- reset engine, prefetch buffer, get appilcation PC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.i_buf_state_nxt <= (others => '0');
        fetch_engine.i_buf_state_nxt <= (others => '0');
        fetch_engine.ci_return_nxt   <= '0';
        fetch_engine.ci_return_nxt   <= '0';
 
        fetch_engine.bus_reset       <= '1'; -- reset bus unit
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
        fetch_engine.bus_err_ack     <= '1'; -- ack bus errors, the execute engine has to take care of them
 
        fetch_engine.state_nxt       <= IFETCH_0;
        fetch_engine.state_nxt       <= IFETCH_0;
 
 
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and
        if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and
Line 371... Line 372...
        end if;
        end if;
 
 
      when IFETCH_2 => -- construct instruction and issue
      when IFETCH_2 => -- construct instruction and issue
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (fetch_engine.i_buf_state(1) = '1') then
        if (fetch_engine.i_buf_state(1) = '1') then
          if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- 32-bit aligned
          if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
            ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
            ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
 
 
            if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- uncompressed
            if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
              if (ipb.free = '1') then -- free entry in buffer?
              if (ipb.free = '1') then -- free entry in buffer?
                ipb.we                    <= '1';
                ipb.we                    <= '1';
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
                fetch_engine.state_nxt    <= IFETCH_0;
                fetch_engine.state_nxt    <= IFETCH_0;
Line 546... Line 547...
        execute_engine.pc      <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
        execute_engine.pc      <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
        execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
        execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
      end if;
      end if;
      execute_engine.state      <= SYS_WAIT;
      execute_engine.state      <= SYS_WAIT;
      execute_engine.state_prev <= SYS_WAIT;
      execute_engine.state_prev <= SYS_WAIT;
 
      --
 
      execute_engine.sleep <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
      if (execute_engine.state = EXECUTE) then
      if (execute_engine.state = EXECUTE) then
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
      end if;
      end if;
      execute_engine.state      <= execute_engine.state_nxt;
      execute_engine.state      <= execute_engine.state_nxt;
      execute_engine.state_prev <= execute_engine.state;
      execute_engine.state_prev <= execute_engine.state;
 
      --
 
      execute_engine.sleep <= execute_engine.sleep_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync_rst;
  end process execute_engine_fsm_sync_rst;
 
 
 
 
  -- for registers that DO NOT require a specific reset state --
  -- for registers that DO NOT require a specific reset state --
Line 580... Line 585...
  next_pc_o  <= execute_engine.next_pc(data_width_c-1 downto 1) & '0';
  next_pc_o  <= execute_engine.next_pc(data_width_c-1 downto 1) & '0';
 
 
 
 
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ctrl_output: process(ctrl, execute_engine, csr, bus_fast_ir, bus_fast_rd, bus_fast_wr)
  ctrl_output: process(ctrl, execute_engine, fetch_engine, trap_ctrl, csr, bus_fast_ir)
  begin
  begin
    ctrl_o <= ctrl;
    ctrl_o <= ctrl;
    -- direct output of register addresses --
    -- direct output of register addresses --
    ctrl_o(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c);
    ctrl_o(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c);
    ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
    ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
    ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
    ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
    -- bus access requests --
    -- bus access requests --
    ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
    ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
    ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) or bus_fast_rd;
    -- bus control --
    ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) or bus_fast_wr;
    ctrl_o(ctrl_bus_exc_ack_c) <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
    -- cpu extension control --
    ctrl_o(ctrl_bus_reset_c)   <= fetch_engine.bus_reset;
    ctrl_o(ctrl_sys_c_ext_en_c) <= csr.misa_c_en; -- C extension enabled
 
    ctrl_o(ctrl_sys_m_ext_en_c) <= csr.misa_m_en; -- M extension enabled
 
  end process ctrl_output;
  end process ctrl_output;
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 612... Line 615...
    execute_engine.state_nxt   <= execute_engine.state;
    execute_engine.state_nxt   <= execute_engine.state;
    execute_engine.i_reg_nxt   <= execute_engine.i_reg;
    execute_engine.i_reg_nxt   <= execute_engine.i_reg;
    execute_engine.is_jump_nxt <= '0';
    execute_engine.is_jump_nxt <= '0';
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
    execute_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0';
    execute_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0';
 
    execute_engine.sleep_nxt   <= execute_engine.sleep;
 
 
    -- instruction dispatch --
    -- instruction dispatch --
    fetch_engine.reset         <= '0';
    fetch_engine.reset         <= '0';
    ipb.re                     <= '0';
    ipb.re                     <= '0';
 
 
    -- trap environment control --
    -- trap environment control --
    trap_ctrl.env_start_ack    <= '0';
    trap_ctrl.env_start_ack    <= '0';
    trap_ctrl.env_end          <= '0';
    trap_ctrl.env_end          <= '0';
 
 
    -- bus access (fast) --
 
    bus_fast_rd                <= '0';
 
    bus_fast_wr                <= '0';
 
 
 
    -- exception trigger --
    -- exception trigger --
    trap_ctrl.instr_be         <= '0';
    trap_ctrl.instr_be         <= '0';
    trap_ctrl.instr_ma         <= '0';
    trap_ctrl.instr_ma         <= '0';
    trap_ctrl.env_call         <= '0';
    trap_ctrl.env_call         <= '0';
    trap_ctrl.break_point      <= '0';
    trap_ctrl.break_point      <= '0';
Line 706... Line 706...
             execute_engine.state_nxt <= TRAP;
             execute_engine.state_nxt <= TRAP;
           else
           else
             execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
             execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
             execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
             execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
             execute_engine.pc_nxt    <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction
             execute_engine.pc_nxt    <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction
 
             if (execute_engine.sleep = '1') then
 
               execute_engine.state_nxt <= TRAP;
 
             else
             execute_engine.state_nxt <= EXECUTE;
             execute_engine.state_nxt <= EXECUTE;
           end if;
           end if;
         end if;
         end if;
 
         end if;
 
 
      when TRAP => -- Start trap environment (also used as sleep state)
      when TRAP => -- Start trap environment (also used as cpu sleep state)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        fetch_engine.reset <= '1';
        if (trap_ctrl.env_start = '1') then
        if (trap_ctrl.env_start = '1') then
          trap_ctrl.env_start_ack  <= '1';
          trap_ctrl.env_start_ack  <= '1';
 
          execute_engine.sleep_nxt <= '0'; -- waky waky
          execute_engine.pc_nxt    <= csr.mtvec(data_width_c-1 downto 1) & '0';
          execute_engine.pc_nxt    <= csr.mtvec(data_width_c-1 downto 1) & '0';
          fetch_engine.reset       <= '1';
 
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= SYS_WAIT;
        end if;
        end if;
 
 
      when EXECUTE => -- Decode and execute instruction
      when EXECUTE => -- Decode and execute instruction
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 730... Line 735...
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
            -- multi cycle alu operation? --
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
            if (alu_operation_v = alu_cmd_shift_c) or -- shift operation
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
                (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001")) then -- MULDIV?
              execute_engine.state_nxt <= ALU_WAIT;
 
            elsif (alu_operation_v = alu_cmd_shift_c) then -- multi-cycle shift operation?
 
              execute_engine.state_nxt <= ALU_WAIT;
              execute_engine.state_nxt <= ALU_WAIT;
            else
            else
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              execute_engine.state_nxt <= DISPATCH;
              execute_engine.state_nxt <= DISPATCH;
            end if;
            end if;
 
            -- cp access? --
 
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
 
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
 
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
 
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
 
            end if;
 
 
 
 
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
Line 815... Line 825...
              csr.re_nxt <= '1'; -- always read CSR
              csr.re_nxt <= '1'; -- always read CSR
            end if;
            end if;
            --
            --
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
              case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
              case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
                when x"000" => -- ECALL
                when funct12_ecall_c => -- ECALL
                  trap_ctrl.env_call <= '1';
                  trap_ctrl.env_call <= '1';
                  execute_engine.state_nxt <= SYS_WAIT;
                when funct12_ebreak_c => -- EBREAK
                when x"001" => -- EBREAK
 
                  trap_ctrl.break_point <= '1';
                  trap_ctrl.break_point <= '1';
                  execute_engine.state_nxt <= SYS_WAIT;
                when funct12_mret_c => -- MRET
                when x"302" => -- MRET
 
                  trap_ctrl.env_end        <= '1';
                  trap_ctrl.env_end        <= '1';
                  execute_engine.pc_nxt    <= csr.mepc(data_width_c-1 downto 1) & '0';
                  execute_engine.pc_nxt    <= csr.mepc(data_width_c-1 downto 1) & '0';
                  fetch_engine.reset       <= '1';
                  fetch_engine.reset       <= '1';
                  execute_engine.state_nxt <= SYS_WAIT;
                when funct12_wfi_c => -- WFI = "CPU sleep"
                when x"105" => -- WFI
                  execute_engine.sleep_nxt <= '1'; -- good night
                  execute_engine.state_nxt <= TRAP;
 
                when others => -- undefined
                when others => -- undefined
                  NULL;
                  NULL;
              end case;
              end case;
 
              execute_engine.state_nxt <= SYS_WAIT;
            elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
            elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
              execute_engine.state_nxt <= CSR_ACCESS;
              execute_engine.state_nxt <= CSR_ACCESS;
            else
            else
              execute_engine.state_nxt <= DISPATCH;
              execute_engine.state_nxt <= DISPATCH;
            end if;
            end if;
Line 904... Line 912...
        end if;
        end if;
 
 
      when BRANCH => -- update PC for taken branches and jumps
      when BRANCH => -- update PC for taken branches and jumps
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
          execute_engine.pc_nxt <= alu_add_i(data_width_c-1 downto 1) & '0';
          execute_engine.pc_nxt    <= alu_add_i(data_width_c-1 downto 1) & '0'; -- branch/jump destination
          fetch_engine.reset    <= '1';
          fetch_engine.reset    <= '1';
        end if;
 
        execute_engine.state_nxt <= SYS_WAIT;
        execute_engine.state_nxt <= SYS_WAIT;
 
        else
 
          execute_engine.state_nxt <= DISPATCH;
 
        end if;
 
 
      when LOAD => -- trigger memory read request
      when LOAD => -- trigger memory read request
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_rd_c)  <= '1';--bus_fast_rd <= '1'; -- fast read request
        ctrl_nxt(ctrl_bus_rd_c)  <= '1'; -- fast read request
        execute_engine.state_nxt <= LOADSTORE_0;
        execute_engine.state_nxt <= LOADSTORE_0;
 
 
      when STORE => -- trigger memory write request
      when STORE => -- trigger memory write request
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_wr_c)  <= '1';--bus_fast_wr <= '1'; -- fast write request
        ctrl_nxt(ctrl_bus_wr_c)  <= '1'; -- fast write request
        execute_engine.state_nxt <= LOADSTORE_0;
        execute_engine.state_nxt <= LOADSTORE_0;
 
 
      when LOADSTORE_0 => -- memory latency
      when LOADSTORE_0 => -- memory latency
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
Line 949... Line 959...
 
 
  -- Illegal Instruction Check --------------------------------------------------------------
  -- Illegal Instruction Check --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
  begin
  begin
 
    -- illegal instructions are checked in the EXECUTE stage
 
    -- the execute engine will only commit valid instructions
    if (execute_engine.state = EXECUTE) then
    if (execute_engine.state = EXECUTE) then
      -- defaults --
      -- defaults --
      illegal_instruction <= '0';
      illegal_instruction <= '0';
      illegal_register    <= '0';
      illegal_register    <= '0';
      illegal_compressed  <= '0';
      illegal_compressed  <= '0';
Line 1021... Line 1033...
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
 
 
        when opcode_alu_c => -- check ALU funct3 & funct7
        when opcode_alu_c => -- check ALU funct3 & funct7
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
            if (CPU_EXTENSION_RISCV_M = false) or (csr.misa_m_en = '0') then -- not implemented or disabled
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
              illegal_instruction <= '1';
              illegal_instruction <= '1';
            end if;
            end if;
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
Line 1062... Line 1074...
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
               --
               --
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- time
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (IO_MTIME_USE = true)) or -- time
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instret
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instret
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycleh
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycleh
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- timeh
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (IO_MTIME_USE = true)) or -- timeh
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instreth
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instreth
               --
               --
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycle
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycle
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstret
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstret
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycleh
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycleh
Line 1090... Line 1102...
            end if;
            end if;
 
 
          -- ecall, ebreak, mret, wfi --
          -- ecall, ebreak, mret, wfi --
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
            if (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000000000000") or -- ECALL
            if (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK 
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK 
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "001100000010") or -- MRET
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_mret_c) or -- MRET
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000100000101") then -- WFI
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI
              illegal_instruction <= '0';
              illegal_instruction <= '0';
            else
            else
              illegal_instruction <= '1';
              illegal_instruction <= '1';
            end if;
            end if;
          else
          else
Line 1106... Line 1118...
 
 
        when others => -- compressed instruction or undefined instruction
        when others => -- compressed instruction or undefined instruction
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          else -- compressed instruction: illegal or disabled / not implemented
          else -- compressed instruction: illegal or disabled / not implemented
            illegal_compressed <= ci_illegal or (not csr.misa_c_en);
            illegal_compressed <= ci_illegal;
          end if;
          end if;
 
 
      end case;
      end case;
    else
    else
      illegal_instruction <= '0';
      illegal_instruction <= '0';
Line 1159... Line 1171...
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or clic_irq_i)   and (not trap_ctrl.irq_ack(interrupt_mext_irq_c));
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or clic_irq_i)   and (not trap_ctrl.irq_ack(interrupt_mext_irq_c));
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i)  and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c));
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i)  and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c));
 
 
        -- trap control --
        -- trap control --
        if (trap_ctrl.env_start = '0') then -- no started trap handler
        if (trap_ctrl.env_start = '0') then -- no started trap handler
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- exception/IRQ detected!
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program
            trap_ctrl.exc_src   <= trap_ctrl.exc_buf;     -- capture exception source for hardware
            trap_ctrl.exc_src   <= trap_ctrl.exc_buf;     -- capture exception source for hardware
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
            trap_ctrl.env_start <= '1';                   -- now we want to start the trap handler
            trap_ctrl.env_start <= '1';                   -- now we want to start the trap handler
Line 1182... Line 1194...
 
 
  -- any exception/interrupt? --
  -- any exception/interrupt? --
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
 
 
  -- exception acknowledge for bus unit --
 
  bus_exc_ack_o <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
 
 
 
  -- exception/interrupt/status ID visible for program --
 
  csr.mcause <= trap_ctrl.cause;
 
 
 
 
 
  -- Trap Priority Detector -----------------------------------------------------------------
  -- Trap Priority Detector -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  trap_priority: process(trap_ctrl)
  trap_priority: process(trap_ctrl)
  begin
  begin
Line 1282... Line 1288...
 
 
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Control and Status Registers (CSRs)
-- Control and Status Registers (CSRs)
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
  -- CSR CPU Access -------------------------------------------------------------------------
 
  -- -------------------------------------------------------------------------------------------
 
  csr_cpu_acc: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      csr.we <= csr.we_nxt;
 
      csr.re <= csr.re_nxt;
 
    end if;
 
  end process csr_cpu_acc;
 
 
 
 
 
  -- Control and Status Registers Write Access ----------------------------------------------
  -- Control and Status Registers Write Access ----------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_write_access: process(rstn_i, clk_i)
  csr_write_access: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
 
      csr.we <= '0';
 
      csr.re <= '0';
 
      --
      csr.mstatus_mie  <= '0';
      csr.mstatus_mie  <= '0';
      csr.mstatus_mpie <= '0';
      csr.mstatus_mpie <= '0';
      csr.mie_msie     <= '0';
      csr.mie_msie     <= '0';
      csr.mie_meie     <= '0';
      csr.mie_meie     <= '0';
      csr.mie_mtie     <= '0';
      csr.mie_mtie     <= '0';
      csr.mtvec        <= (others => '0');
      csr.mtvec        <= (others => '0');
      csr.mtval        <= (others => '0');
      csr.mtval        <= (others => '0');
      csr.mepc         <= (others => '0');
      csr.mepc         <= (others => '0');
      csr.mip_msip     <= '0';
      csr.mip_msip     <= '0';
      csr.misa_c_en    <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
 
      csr.misa_m_en    <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
 
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
        -- access --
 
        csr.we <= csr.we_nxt;
 
        csr.re <= csr.re_nxt;
 
 
 
        -- defaults --
        csr.mip_msip <= '0';
        csr.mip_msip <= '0';
 
 
        -- register that can be modified by user --
        -- registers that can be modified by user --
        if (csr.we = '1') then -- manual update
        if (csr.we = '1') then -- manual update
 
 
 
          -- Machine CSRs: Standard read/write
 
          if (execute_engine.i_reg(31 downto 28) = x"3") then
          -- machine trap setup --
          -- machine trap setup --
          if (execute_engine.i_reg(31 downto 24) = x"30") then
            if (execute_engine.i_reg(27 downto 24) = x"0") then
            if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
              case execute_engine.i_reg(23 downto 20) is
 
              when x"0" => -- R/W: mstatus - machine status register
              csr.mstatus_mie  <= csr_wdata_i(03);
              csr.mstatus_mie  <= csr_wdata_i(03);
              csr.mstatus_mpie <= csr_wdata_i(07);
              csr.mstatus_mpie <= csr_wdata_i(07);
            end if;
              when x"4" => -- R/W: mie - machine interrupt-enable register
            if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
 
              csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable during runtime
 
              csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable during runtime
 
            end if;
 
            if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
 
              csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
              csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
              csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
              csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
              csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
              csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
            end if;
              when x"5" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
 
              csr.mtvec <= csr_wdata_i;
              csr.mtvec <= csr_wdata_i;
 
              when others =>
 
                NULL;
 
              end case;
            end if;
            end if;
          end if;
 
 
 
          -- machine trap handling --
          -- machine trap handling --
          if (execute_engine.i_reg(31 downto 24) = x"34") then
            if (execute_engine.i_reg(27 downto 24) = x"4") then
            if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
              case execute_engine.i_reg(23 downto 20) is
 
                when x"0" => -- R/W: mscratch - machine scratch register
              csr.mscratch <= csr_wdata_i;
              csr.mscratch <= csr_wdata_i;
            end if;
                when x"1" => -- R/W: mepc - machine exception program counter
            if (execute_engine.i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter
 
              csr.mepc <= csr_wdata_i;
              csr.mepc <= csr_wdata_i;
            end if;
                when x"2" => -- R/W: mcause - machine trap cause
            if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
                  csr.mcause <= csr_wdata_i;
 
                when x"3" => -- R/W: mtval - machine bad address or instruction
 
                  csr.mtval <= csr_wdata_i;
 
                when x"4" => -- R/W: mip - machine interrupt pending
              csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
              csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
 
                when others =>
 
                  NULL;
 
              end case;
            end if;
            end if;
          end if;
          end if;
 
 
        else -- automatic update by hardware
        -- automatic update by hardware --
 
        else
 
 
          -- machine exception PC & exception value register --
          -- machine exception PC & exception value register --
          if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
          if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
            if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
            csr.mcause <= trap_ctrl.cause;
 
            if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
              csr.mtval <= (others => '0');
              csr.mtval <= (others => '0'); -- mtval not defined for interrupts
            else -- for EXCEPTIONS (according to their priority)
            else -- for EXCEPTIONS (according to their priority)
              csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
              csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
              if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
              if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
                csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
                csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
              elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
              elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
Line 1390... Line 1397...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_read_access: process(clk_i)
  csr_read_access: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      csr_rdata_o <= (others => '0'); -- default
      csr_rdata_o <= (others => '0'); -- default
      if (CPU_EXTENSION_RISCV_Zicsr = true) then -- implement CSR access at all?
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
        if (csr.re = '1') then
 
          case execute_engine.i_reg(31 downto 20) is
          case execute_engine.i_reg(31 downto 20) is
 
 
            -- machine trap setup --
            -- machine trap setup --
            when x"300" => -- R/W: mstatus - machine status register
            when x"300" => -- R/W: mstatus - machine status register
              csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
              csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
              csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
              csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
              csr_rdata_o(11) <= '1'; -- MPP low
              csr_rdata_o(11) <= '1'; -- MPP low
              csr_rdata_o(12) <= '1'; -- MPP high
              csr_rdata_o(12) <= '1'; -- MPP high
            when x"301" => -- R/W: misa - ISA and extensions
          when x"301" => -- R/-: misa - ISA and extensions
              csr_rdata_o(02) <= csr.misa_c_en;                               -- C CPU extension
            csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C);     -- C CPU extension
              csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
              csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
              csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
              csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
              csr_rdata_o(12) <= csr.misa_m_en;                               -- M CPU extension
            csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
              csr_rdata_o(23) <= '1';                                         -- X CPU extension: non-standard extensions
 
              csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
              csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
              csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
              csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
              csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
              csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
            when x"304" => -- R/W: mie - machine interrupt-enable register
            when x"304" => -- R/W: mie - machine interrupt-enable register
              csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable
              csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable
              csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable
              csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable
              csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable
              csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable
            when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
              csr_rdata_o <= csr.mtvec;
              csr_rdata_o <= csr.mtvec;
 
 
            -- machine trap handling --
            -- machine trap handling --
            when x"340" => -- R/W: mscratch - machine scratch register
            when x"340" => -- R/W: mscratch - machine scratch register
              csr_rdata_o <= csr.mscratch;
              csr_rdata_o <= csr.mscratch;
            when x"341" => -- R/W: mepc - machine exception program counter
            when x"341" => -- R/W: mepc - machine exception program counter
              csr_rdata_o <= csr.mepc;
              csr_rdata_o <= csr.mepc;
            when x"342" => -- R/-: mcause - machine trap cause
          when x"342" => -- R/W: mcause - machine trap cause
              csr_rdata_o <= csr.mcause;
              csr_rdata_o <= csr.mcause;
            when x"343" => -- R/-: mtval - machine bad address or instruction
          when x"343" => -- R/W: mtval - machine bad address or instruction
              csr_rdata_o <= csr.mtval;
              csr_rdata_o <= csr.mtval;
            when x"344" => -- R/W: mip - machine interrupt pending
            when x"344" => -- R/W: mip - machine interrupt pending
              csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
              csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
              csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
              csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
              csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
              csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
 
 
            -- counter and timers --
            -- counter and timers --
            when x"c00" | x"c01" | x"b00" => -- R/-: cycle/time/mcycle: Cycle counter LOW / Timer LOW
          when x"c00" | x"b00" => -- R/(W): cycle/mcycle: Cycle counter LOW
              csr_rdata_o <= csr.cycle(31 downto 0);
            csr_rdata_o <= csr.mcycle(31 downto 0);
            when x"c02" | x"b02" => -- R/-: instret/minstret: Instructions-retired counter LOW
          when x"c02" | x"b02" => -- R/(W): instret/minstret: Instructions-retired counter LOW
              csr_rdata_o <= csr.instret(31 downto 0);
            csr_rdata_o <= csr.minstret(31 downto 0);
            when x"c80" | x"c81" | x"b80" => -- R/-: cycleh/timeh/mcycleh: Cycle counter HIGH / Timer HIGH
          when x"c80" | x"b80" => -- R/(W): cycleh/mcycleh: Cycle counter HIGH
              csr_rdata_o <= csr.cycleh;
            csr_rdata_o <= csr.mcycleh;
            when x"c82" | x"b82" => -- R/-: instreth/minstreth: Instructions-retired counter HIGH
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
              csr_rdata_o <= csr.instreth;
            csr_rdata_o <= csr.minstreth;
 
 
 
          when x"c01" => -- R/-: time: System time LOW (from MTIME unit)
 
            csr_rdata_o <= time_i(31 downto 0);
 
          when x"c81" => -- R/-: timeh: System time HIGH (from MTIME unit)
 
            csr_rdata_o <= time_i(63 downto 32);
 
 
            -- machine information registers --
            -- machine information registers --
            when x"f13" => -- R/-: mimpid - implementation ID / version
            when x"f13" => -- R/-: mimpid - implementation ID / version
              csr_rdata_o <= hw_version_c;
              csr_rdata_o <= hw_version_c;
            when x"f14" => -- R/-: mhartid - hardware thread ID
            when x"f14" => -- R/-: mhartid - hardware thread ID
              csr_rdata_o <= HART_ID;
              csr_rdata_o <= HART_ID;
 
 
            -- CUSTOM read-only machine CSRs --
            -- CUSTOM read-only machine CSRs --
            when x"fc0" => -- R/-: mfeatures - implemented processor devices/features
            when x"fc0" => -- R/-: mfeatures - implemented processor devices/features
              csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE);   -- implement processor-internal bootloader?
              csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE);   -- implement processor-internal bootloader?
              csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE);      -- implement external memory bus interface?
              csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE);      -- implement external memory bus interface?
              csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
              csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
Line 1470... Line 1485...
              csr_rdata_o <= MEM_DSPACE_BASE;
              csr_rdata_o <= MEM_DSPACE_BASE;
            when x"fc6" => -- R/-: mispacesize - Total size of instruction memory space in byte
            when x"fc6" => -- R/-: mispacesize - Total size of instruction memory space in byte
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_ISPACE_SIZE, 32));
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_ISPACE_SIZE, 32));
            when x"fc7" => -- R/-: mdspacesize - Total size of data memory space in byte
            when x"fc7" => -- R/-: mdspacesize - Total size of data memory space in byte
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
 
 
            -- undefined/unavailable --
            -- undefined/unavailable --
            when others =>
            when others =>
              csr_rdata_o <= (others => '0'); -- not implemented (yet)
            csr_rdata_o <= (others => '0'); -- not implemented
 
 
          end case;
          end case;
        end if;
        end if;
      end if;
      end if;
    end if;
 
  end process csr_read_access;
  end process csr_read_access;
 
 
 
 
  -- RISC-V Counter CSRs --------------------------------------------------------------------
  -- RISC-V Counter CSRs --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_counters: process(rstn_i, clk_i)
  csr_counters: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      csr.cycle    <= (others => '0');
      csr.mcycle    <= (others => '0');
      csr.instret  <= (others => '0');
      csr.minstret  <= (others => '0');
      csr.cycleh   <= (others => '0');
      csr.mcycleh   <= (others => '0');
      csr.instreth <= (others => '0');
      csr.minstreth <= (others => '0');
      cycle_msb    <= '0';
      mcycle_msb    <= '0';
      instret_msb  <= '0';
      minstret_msb  <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then
      if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then
        -- low word overflow buffers --
 
        cycle_msb   <= csr.cycle(csr.cycle'left);
        -- mcycle (cycle) --
        instret_msb <= csr.instret(csr.instret'left);
        mcycle_msb <= csr.mcycle(csr.mcycle'left);
        -- low word counters --
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b00") then -- write access
        csr.cycle <= std_ulogic_vector(unsigned(csr.cycle) + 1);
          csr.mcycle(31 downto 0) <= csr_wdata_i;
        if (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then
          csr.mcycle(32) <= '0';
          csr.instret <= std_ulogic_vector(unsigned(csr.instret) + 1);
        elsif (execute_engine.sleep = '0') then -- automatic update
        end if;
          csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
        -- high word counters --
        end if;
        if ((cycle_msb xor csr.cycle(csr.cycle'left)) = '1') then
 
          csr.cycleh <= std_ulogic_vector(unsigned(csr.cycleh) + 1);
        -- mcycleh (cycleh) --
        end if;
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b80") then -- write access
        if ((instret_msb xor csr.instret(csr.instret'left)) = '1') then
          csr.mcycleh <= csr_wdata_i;
          csr.instreth <= std_ulogic_vector(unsigned(csr.instreth) + 1);
        elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
 
          csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
 
        end if;
 
 
 
        -- minstret (instret) --
 
        minstret_msb <= csr.minstret(csr.minstret'left);
 
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
 
          csr.minstret(31 downto 0) <= csr_wdata_i;
 
          csr.minstret(32) <= '0';
 
        elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
 
          csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
 
        end if;
 
 
 
        -- minstreth (instreth) --
 
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
 
          csr.minstreth <= csr_wdata_i;
 
        elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
 
          csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
        end if;
        end if;
 
 
      end if;
      end if;
    end if;
    end if;
  end process csr_counters;
  end process csr_counters;
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.