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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 40 and 41

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

Rev 40 Rev 41
Line 232... Line 232...
 
 
  -- RISC-V control and status registers (CSRs) --
  -- RISC-V control and status registers (CSRs) --
  type pmp_ctrl_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(7 downto 0);
  type pmp_ctrl_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(7 downto 0);
  type pmp_addr_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
  type pmp_addr_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
  type csr_t is record
  type csr_t is record
 
    addr             : std_ulogic_vector(11 downto 0); -- csr address
    we           : std_ulogic; -- csr write enable
    we           : std_ulogic; -- csr write enable
    we_nxt       : std_ulogic;
    we_nxt       : std_ulogic;
    re           : std_ulogic; -- csr read enable
    re           : std_ulogic; -- csr read enable
    re_nxt       : std_ulogic;
    re_nxt       : std_ulogic;
    wdata        : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
    wdata        : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
Line 248... Line 249...
    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)
    mie_firqe    : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
    mie_firqe    : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
    --
    --
 
    mcounteren_cy    : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
 
    mcounteren_tm    : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
 
    mcounteren_ir    : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
 
    --
 
    mcountinhibit_cy : std_ulogic; -- mcounterinhibit.cy: enable auto-increment
 
    mcountinhibit_ir : std_ulogic; -- mcounterinhibit.ir: enable auto-increment
 
    --
    mip_status   : std_ulogic_vector(interrupt_width_c-1  downto 0); -- current buffered IRQs
    mip_status   : std_ulogic_vector(interrupt_width_c-1  downto 0); -- current buffered IRQs
    mip_clear    : std_ulogic_vector(interrupt_width_c-1  downto 0); -- set bits clear the according buffered IRQ
    mip_clear    : std_ulogic_vector(interrupt_width_c-1  downto 0); -- set bits clear the according buffered IRQ
    --
    --
    privilege    : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
    privilege    : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
    priv_m_mode  : std_ulogic; -- CPU in M-mode
    priv_m_mode  : std_ulogic; -- CPU in M-mode
Line 342... Line 350...
          fetch_engine.state_nxt <= IFETCH_ISSUE;
          fetch_engine.state_nxt <= IFETCH_ISSUE;
        end if;
        end if;
 
 
      when IFETCH_ISSUE => -- store instruction data to prefetch buffer
      when IFETCH_ISSUE => -- store instruction data to prefetch buffer
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
        if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
        if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
          fetch_engine.pc_nxt    <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
          fetch_engine.pc_nxt    <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
          ipb.we                 <= '1';
          ipb.we                 <= '1';
          fetch_engine.state_nxt <= IFETCH_REQUEST;
          fetch_engine.state_nxt <= IFETCH_REQUEST;
        end if;
        end if;
Line 456... Line 465...
      when ISSUE_ACTIVE => -- issue instruction if available
      when ISSUE_ACTIVE => -- issue instruction if available
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (ipb.avail = '1') then -- instructions available?
        if (ipb.avail = '1') then -- instructions available?
 
 
          if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
          if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
            if (execute_engine.state = DISPATCH) then
            if (execute_engine.state = DISPATCH) then -- ready to issue new command?
              cmd_issue.valid      <= '1';
              cmd_issue.valid      <= '1';
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
              if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
              if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
                ipb.re <= '1';
                ipb.re <= '1';
                cmd_issue.data <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
                cmd_issue.data <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
Line 470... Line 479...
                issue_engine.align_nxt <= '1';
                issue_engine.align_nxt <= '1';
              end if;
              end if;
            end if;
            end if;
 
 
          else -- begin check in HIGH instruction half-word
          else -- begin check in HIGH instruction half-word
            if (execute_engine.state = DISPATCH) then
            if (execute_engine.state = DISPATCH) then -- ready to issue new command?
              cmd_issue.valid      <= '1';
              cmd_issue.valid      <= '1';
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
              if (issue_engine.buf(1 downto 0) = "11") then -- uncompressed and "unaligned"
              if (issue_engine.buf(1 downto 0) = "11") then -- uncompressed and "unaligned"
                ipb.re <= '1';
                ipb.re <= '1';
                cmd_issue.data <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
                cmd_issue.data <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
Line 500... Line 509...
        issue_engine.state_nxt <= ISSUE_ACTIVE;
        issue_engine.state_nxt <= ISSUE_ACTIVE;
 
 
    end case;
    end case;
  end process issue_engine_fsm_comb;
  end process issue_engine_fsm_comb;
 
 
  -- 16-bit instruction: half-word select --
  -- 16-bit instructions: half-word select --
  ci_instr16 <= ipb.rdata(15 downto 0) when (issue_engine.align = '0') else issue_engine.buf(15 downto 0);
  ci_instr16 <= ipb.rdata(15 downto 0) when (issue_engine.align = '0') else issue_engine.buf(15 downto 0);
 
 
 
 
  -- Compressed Instructions Recoding -------------------------------------------------------
  -- Compressed Instructions Recoding -------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 610... Line 619...
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- PC update --
      -- PC update --
      if (execute_engine.pc_we = '1') then
      if (execute_engine.pc_we = '1') then
        case execute_engine.pc_mux_sel is
        case execute_engine.pc_mux_sel is
          when "00"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
          when "00"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
          when "01"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/branch
          when "01"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0'; -- trap return
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0';  -- trap exit
        end case;
        end case;
      end if;
      end if;
      --
      --
      execute_engine.state  <= execute_engine.state_nxt;
      execute_engine.state  <= execute_engine.state_nxt;
      execute_engine.sleep  <= execute_engine.sleep_nxt;
      execute_engine.sleep  <= execute_engine.sleep_nxt;
Line 648... Line 657...
      -- main control bus --
      -- main control bus --
      ctrl <= ctrl_nxt;
      ctrl <= ctrl_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync;
  end process execute_engine_fsm_sync;
 
 
 
  -- CSR access address --
 
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
 
 
  -- PC output --
  -- PC output --
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- PC for ALU ops
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- PC for ALU ops
 
 
 
 
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- CPU Control Bus Output -----------------------------------------------------------------
Line 841... Line 853...
              when funct3_xor_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_xor_c; -- XOR(I)
              when funct3_xor_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_xor_c; -- XOR(I)
              when funct3_or_c  => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c;  -- OR(I)
              when funct3_or_c  => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c;  -- OR(I)
              when others       => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
              when others       => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
            end case;
            end case;
 
 
            -- cp access? --
            -- co-processor (cp) access? --
            ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- just in case a mul/div operation
            ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- just in case a mul/div operation
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV CP op?
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV CP op?
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
            -- ALU operation - function select --
            -- ALU operation - function select --
Line 1100... Line 1112...
      csr_wacc_v := or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
      csr_wacc_v := or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
--    csr_racc_v := '1'; -- always read CSR
--    csr_racc_v := '1'; -- always read CSR
    end if;
    end if;
 
 
    -- check CSR access --
    -- check CSR access --
    case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
    case csr.addr is
 
      -- standard read/write CSRs --
      when csr_mstatus_c   => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mstatus_c   => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mstatush_c  => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mstatush_c  => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_misa_c      => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we don't cause an exception here for compatibility
      when csr_misa_c       => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
      when csr_mie_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mie_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mtvec_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mtvec_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mscratch_c  => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mscratch_c  => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mepc_c      => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mepc_c      => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mcause_c    => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mcause_c    => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
 
      when csr_mcounteren_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mtval_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mtval_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mip_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mip_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      --
      --
      when csr_pmpcfg0_c   => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 1)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpcfg0_c   => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 1)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpcfg1_c   => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 5)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpcfg1_c   => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 5)) and csr.priv_m_mode; -- M-mode only
Line 1124... Line 1138...
      when csr_pmpaddr4_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 5)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr4_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 5)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr5_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 6)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr5_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 6)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr6_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 7)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr6_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 7)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr7_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 8)) and csr.priv_m_mode; -- M-mode only
      when csr_pmpaddr7_c  => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(pmp_num_regions_c >= 8)) and csr.priv_m_mode; -- M-mode only
      --
      --
      when csr_mcycle_c    => csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(zicnt_en_c); -- M-mode only and "Zicnt" = true
      when csr_mcountinhibit_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_minstret_c  => csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(zicnt_en_c); -- M-mode only and "Zicnt" = true
 
      --
 
      when csr_mcycleh_c   => csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(zicnt_en_c); -- M-mode only and "Zicnt" = true
 
      when csr_minstreth_c => csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(zicnt_en_c); -- M-mode only and "Zicnt" = true
 
      --
 
      when csr_cycle_c     => csr_acc_valid <= (not csr_wacc_v) and bool_to_ulogic_f(zicnt_en_c); -- all modes, read-only and "Zicnt" = true
 
      when csr_time_c      => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
 
      when csr_instret_c   => csr_acc_valid <= (not csr_wacc_v) and bool_to_ulogic_f(zicnt_en_c); -- all modes, read-only and "Zicnt" = true
 
      --
      --
      when csr_cycleh_c    => csr_acc_valid <= (not csr_wacc_v) and bool_to_ulogic_f(zicnt_en_c); -- all modes, read-only and "Zicnt" = true
      when csr_mcycle_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_timeh_c     => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only
      when csr_minstret_c   => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_instreth_c  => csr_acc_valid <= (not csr_wacc_v) and bool_to_ulogic_f(zicnt_en_c); -- all modes, read-only and "Zicnt" = true
 
      --
      --
      when csr_mvendorid_c => csr_acc_valid <= csr.priv_m_mode and (not csr_wacc_v); -- M-mode only, read-only
      when csr_mcycleh_c    => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_marchid_c   => csr_acc_valid <= csr.priv_m_mode and (not csr_wacc_v); -- M-mode only, read-only
      when csr_minstreth_c  => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
      when csr_mimpid_c    => csr_acc_valid <= csr.priv_m_mode and (not csr_wacc_v); -- M-mode only, read-only
      -- standard read-only CSRs --
      when csr_mhartid_c   => csr_acc_valid <= csr.priv_m_mode and (not csr_wacc_v); -- M-mode only, read-only
      when csr_cycle_c      => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
 
      when csr_time_c       => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
 
      when csr_instret_c    => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
 
      --
 
      when csr_cycleh_c     => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
 
      when csr_timeh_c      => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
 
      when csr_instreth_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
 
      --
 
      when csr_mvendorid_c  => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
      when csr_marchid_c    => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
      when csr_mimpid_c     => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
      when csr_mhartid_c    => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
      -- custom read-only CSRs --
 
      when csr_mzext_c      => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
      --
      --
      when csr_mzext_c     => csr_acc_valid <= csr.priv_m_mode and (not csr_wacc_v); -- M-mode only, read-only
      when others => csr_acc_valid <= '0'; -- invalid access
      --
 
      when others => csr_acc_valid <= '0'; -- undefined, invalid access
 
    end case;
    end case;
  end process invalid_csr_access_check;
  end process invalid_csr_access_check;
 
 
 
 
  -- Illegal Instruction Check --------------------------------------------------------------
  -- Illegal Instruction Check --------------------------------------------------------------
Line 1590... Line 1606...
      csr.mtval        <= (others => '0');
      csr.mtval        <= (others => '0');
      csr.mip_clear    <= (others => '0');
      csr.mip_clear    <= (others => '0');
      csr.pmpcfg       <= (others => (others => '0'));
      csr.pmpcfg       <= (others => (others => '0'));
      csr.pmpaddr      <= (others => (others => '1'));
      csr.pmpaddr      <= (others => (others => '1'));
      --
      --
 
      csr.mcounteren_cy    <= '0';
 
      csr.mcounteren_tm    <= '0';
 
      csr.mcounteren_ir    <= '0';
 
      csr.mcountinhibit_cy <= '0';
 
      csr.mcountinhibit_ir <= '0';
 
      --
      csr.mcycle       <= (others => '0');
      csr.mcycle       <= (others => '0');
      csr.minstret     <= (others => '0');
      csr.minstret     <= (others => '0');
      csr.mcycleh      <= (others => '0');
      csr.mcycleh      <= (others => '0');
      csr.minstreth    <= (others => '0');
      csr.minstreth    <= (others => '0');
      mcycle_msb       <= '0';
      mcycle_msb       <= '0';
Line 1608... Line 1630...
 
 
        -- --------------------------------------------------------------------------------
        -- --------------------------------------------------------------------------------
        -- CSR access by application software
        -- CSR access by application software
        -- --------------------------------------------------------------------------------
        -- --------------------------------------------------------------------------------
        if (csr.we = '1') then -- manual update
        if (csr.we = '1') then -- manual update
          case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
          case csr.addr is
 
 
            -- machine trap setup --
            -- machine trap setup --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_mstatus_c => -- R/W: mstatus - machine status register
            when csr_mstatus_c => -- R/W: mstatus - machine status register
              csr.mstatus_mie  <= csr.wdata(03);
              csr.mstatus_mie  <= csr.wdata(03);
Line 1621... Line 1643...
                csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
                csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
                csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
                csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
              else -- only machine mode is available
              else -- only machine mode is available
                csr.mstatus_mpp <= priv_mode_m_c;
                csr.mstatus_mpp <= priv_mode_m_c;
              end if;
              end if;
            when csr_mie_c => -- R/W: mie - machine interrupt-enable register
            when csr_mie_c => -- R/W: mie - machine interrupt enable register
              csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
              csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
              csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
              csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
              csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
              csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
              --
              --
              csr.mie_firqe(0) <= csr.wdata(16); -- fast interrupt channel 0
              csr.mie_firqe(0) <= csr.wdata(16); -- fast interrupt channel 0
              csr.mie_firqe(1) <= csr.wdata(17); -- fast interrupt channel 1
              csr.mie_firqe(1) <= csr.wdata(17); -- fast interrupt channel 1
              csr.mie_firqe(2) <= csr.wdata(18); -- fast interrupt channel 2
              csr.mie_firqe(2) <= csr.wdata(18); -- fast interrupt channel 2
              csr.mie_firqe(3) <= csr.wdata(19); -- fast interrupt channel 3
              csr.mie_firqe(3) <= csr.wdata(19); -- fast interrupt channel 3
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
 
            when csr_mcounteren_c => -- R/W: machine counter enable register
 
              csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
 
              csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
 
              csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
 
 
            -- machine trap handling --
            -- machine trap handling --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
              csr.mscratch <= csr.wdata;
              csr.mscratch <= csr.wdata;
Line 1698... Line 1724...
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c |
            when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c |
                 csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c => -- R/W: pmpaddr0..7 - PMP address register 0..7
                 csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c => -- R/W: pmpaddr0..7 - PMP address register 0..7
              if (PMP_USE = true) then
              if (PMP_USE = true) then
                for i in 0 to pmp_num_regions_c-1 loop
                for i in 0 to pmp_num_regions_c-1 loop
                  if (execute_engine.i_reg(23 downto 20) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
                  if (csr.addr(2 downto 0) = std_ulogic_vector(to_unsigned(i, 3))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
                    csr.pmpaddr(i) <= csr.wdata;
                    csr.pmpaddr(i) <= csr.wdata;
                    csr.pmpaddr(i)(index_size_f(pmp_min_granularity_c)-4 downto 0) <= (others => '1');
                    csr.pmpaddr(i)(index_size_f(pmp_min_granularity_c)-4 downto 0) <= (others => '1');
                  end if;
                  end if;
                end loop; -- i (CSRs)
                end loop; -- i (CSRs)
              end if;
              end if;
 
 
 
            -- machine counter setup --
 
            -- --------------------------------------------------------------------
 
            when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
 
              csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
 
              csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
 
 
            -- undefined --
            -- undefined --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when others =>
            when others =>
              NULL;
              NULL;
 
 
Line 1771... Line 1803...
          end if;
          end if;
 
 
        end if; -- hardware csr access
        end if; -- hardware csr access
 
 
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      -- Counter CSRs (each counter is split in 2 32-bit counters)
      -- Counter CSRs (each counter is split in two 32-bit counters)
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
        if (zicnt_en_c = true) then -- implement standard RISC-V performance counters?
 
          -- [m]cycle --
          -- [m]cycle --
          if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycle_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
            csr.mcycle <= '0' & csr.wdata;
            csr.mcycle <= '0' & csr.wdata;
            mcycle_msb <= '0';
            mcycle_msb <= '0';
          elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
        elsif (csr.mcountinhibit_cy = '0') and (execute_engine.sleep = '0') then -- non-inhibited automatic update (if CPU is not in sleep mode)
            csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
            csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
            mcycle_msb <= csr.mcycle(csr.mcycle'left);
            mcycle_msb <= csr.mcycle(csr.mcycle'left);
          end if;
          end if;
 
 
          -- [m]cycleh --
          -- [m]cycleh --
          if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycleh_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
            csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
          csr.mcycleh <= csr.wdata;
          elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
        elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update (continued)
            csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
            csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
          end if;
          end if;
 
 
          -- [m]instret --
          -- [m]instret --
          if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstret_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
            csr.minstret <= '0' & csr.wdata;
            csr.minstret <= '0' & csr.wdata;
            minstret_msb <= '0';
            minstret_msb <= '0';
          elsif (execute_engine.state = EXECUTE) then -- automatic update (if CPU actually executes an instruction)
        elsif (csr.mcountinhibit_ir = '0') and (execute_engine.state = EXECUTE) then -- non-inhibited automatic update (if CPU actually executes an instruction)
            csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
            csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
            minstret_msb <= csr.minstret(csr.minstret'left);
            minstret_msb <= csr.minstret(csr.minstret'left);
          end if;
          end if;
 
 
          -- [m]instreth --
          -- [m]instreth --
          if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstreth_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
            csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
          csr.minstreth <= csr.wdata;
          elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
        elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update (continued)
            csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
            csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
          end if;
          end if;
        else -- performance counters NOT implemented (not RISC-V-compliant!)
 
          csr.mcycle    <= (others => '0');
 
          csr.minstret  <= (others => '0');
 
          csr.mcycleh   <= (others => '0');
 
          csr.minstreth <= (others => '0');
 
          mcycle_msb    <= '0';
 
          minstret_msb  <= '0';
 
        end if;
 
 
 
      end if;
      end if;
    end if;
    end if;
  end process csr_write_access;
  end process csr_write_access;
 
 
Line 1845... Line 1868...
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      csr.re    <= csr.re_nxt; -- read access?
      csr.re    <= csr.re_nxt; -- read access?
      csr.rdata <= (others => '0'); -- default output
      csr.rdata <= (others => '0'); -- default output
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
        case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
        case csr.addr is
 
 
          -- machine trap setup --
          -- machine trap setup --
          when csr_mstatus_c => -- R/W: mstatus - machine status register
          when csr_mstatus_c => -- R/W: mstatus - machine status register
            csr.rdata(03) <= csr.mstatus_mie;  -- MIE
            csr.rdata(03) <= csr.mstatus_mie;  -- MIE
 
            csr.rdata(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
            csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
            csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
            csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
            csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
            csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
            csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
          when csr_mstatush_c => -- R/-: mstatush - machine status register - high part
          when csr_mstatush_c => -- R/-: mstatush - machine status register - high part
            csr.rdata(05) <= '1'; -- MBE: CPU/Processor is BIG-ENDIAN
            csr.rdata(05) <= '1'; -- MBE: CPU/Processor is BIG-ENDIAN (in machine-mode)
          when csr_misa_c => -- R/-: misa - ISA and extensions
          when csr_misa_c => -- R/-: misa - ISA and extensions
            csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A);     -- A CPU extension
            csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A);     -- A CPU extension
            csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C);     -- C CPU extension
            csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C);     -- C CPU extension
            csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
            csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
            csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
            csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
Line 1876... Line 1900...
            csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
            csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
            csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
            csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
            csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
            csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
          when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
          when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
            csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
 
          when csr_mcounteren_c => -- R/W: machine counter enable register
 
            csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
 
            csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
 
            csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h]
 
 
          -- machine trap handling --
          -- machine trap handling --
          when csr_mscratch_c => -- R/W: mscratch - machine scratch register
          when csr_mscratch_c => -- R/W: mscratch - machine scratch register
            csr.rdata <= csr.mscratch;
            csr.rdata <= csr.mscratch;
          when csr_mepc_c => -- R/W: mepc - machine exception program counter
          when csr_mepc_c => -- R/W: mepc - machine exception program counter
Line 1986... Line 2014...
              if (csr.pmpcfg(7)(4 downto 3) = "00") then -- mode = off
              if (csr.pmpcfg(7)(4 downto 3) = "00") then -- mode = off
                csr.rdata(index_size_f(pmp_min_granularity_c)-3 downto 0) <= (others => '0'); -- required for granularity check by SW
                csr.rdata(index_size_f(pmp_min_granularity_c)-3 downto 0) <= (others => '0'); -- required for granularity check by SW
              end if;
              end if;
            end if;
            end if;
 
 
 
          -- machine counter setup --
 
          -- --------------------------------------------------------------------
 
          when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
 
            csr.rdata(0) <= csr.mcountinhibit_cy; -- enable auto-increment of [m]cycle[h] counter
 
            csr.rdata(2) <= csr.mcountinhibit_ir; -- enable auto-increment of [m]instret[h] counter
 
 
          -- counters and timers --
          -- counters and timers --
          when csr_cycle_c | csr_mcycle_c => -- R/(W): [m]cycle: Cycle counter LOW
          when csr_cycle_c | csr_mcycle_c => -- R/(W): [m]cycle: Cycle counter LOW
            csr.rdata <= csr.mcycle(31 downto 0);
            csr.rdata <= csr.mcycle(31 downto 0);
          when csr_time_c => -- R/-: time: System time LOW (from MTIME unit)
          when csr_time_c => -- R/-: time: System time LOW (from MTIME unit)
            csr.rdata <= time_i(31 downto 0);
            csr.rdata <= time_i(31 downto 0);
Line 2015... Line 2049...
          -- custom machine read-only CSRs --
          -- custom machine read-only CSRs --
          when csr_mzext_c => -- R/-: mzext - available Z* extensions
          when csr_mzext_c => -- R/-: mzext - available Z* extensions
            csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr);    -- RISC-V.Zicsr CPU extension
            csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr);    -- RISC-V.Zicsr CPU extension
            csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- RISC-V.Zifencei CPU extension
            csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- RISC-V.Zifencei CPU extension
            csr.rdata(2) <= bool_to_ulogic_f(PMP_USE);                      -- RISC-V physical memory protection
            csr.rdata(2) <= bool_to_ulogic_f(PMP_USE);                      -- RISC-V physical memory protection
            csr.rdata(3) <= bool_to_ulogic_f(zicnt_en_c);                   -- RISC-V performance counters ([m]cycle[h] & [m]instret[h]) implemented
 
 
 
          -- undefined/unavailable --
          -- undefined/unavailable --
          when others =>
          when others =>
            csr.rdata <= (others => '0'); -- not implemented
            csr.rdata <= (others => '0'); -- not implemented
 
 

powered by: WebSVN 2.1.0

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