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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 25 and 26

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

Rev 25 Rev 26
Line 619... Line 619...
    ctrl_nxt(ctrl_alu_shift_dir_c)  <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
    ctrl_nxt(ctrl_alu_shift_dir_c)  <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
    ctrl_nxt(ctrl_alu_shift_ar_c)   <= execute_engine.i_reg(30); -- is arithmetic shift
    ctrl_nxt(ctrl_alu_shift_ar_c)   <= execute_engine.i_reg(30); -- is arithmetic shift
    ctrl_nxt(ctrl_bus_size_lsb_c)   <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
    ctrl_nxt(ctrl_bus_size_lsb_c)   <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
    ctrl_nxt(ctrl_bus_size_msb_c)   <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
    ctrl_nxt(ctrl_bus_size_msb_c)   <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
    ctrl_nxt(ctrl_cp_cmd2_c     downto ctrl_cp_cmd0_c)     <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
    ctrl_nxt(ctrl_cp_cmd2_c     downto ctrl_cp_cmd0_c)     <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
    ctrl_nxt(ctrl_cp_id_msb_c   downto ctrl_cp_id_lsb_c)   <= cp_sel_muldiv_c; -- only CP0 (MULDIV) implemented yet
    ctrl_nxt(ctrl_alu_cmd2_c    downto ctrl_alu_cmd0_c)    <= alu_cmd_add_c; -- default ALU operation: ADD(I)
 
    ctrl_nxt(ctrl_cp_id_msb_c   downto ctrl_cp_id_lsb_c)   <= cp_sel_muldiv_c; -- only CP0 (=MULDIV) implemented yet
    ctrl_nxt(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= ctrl(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c); -- keep rd addr
    ctrl_nxt(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= ctrl(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c); -- keep rd addr
    ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- keep rs1 addr
    ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- keep rs1 addr
    ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c); -- keep rs2 addr
    ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c); -- keep rs2 addr
 
 
    -- is immediate operation? --
    -- is immediate ALU operation? --
    alu_immediate_v := '0';
    alu_immediate_v := not execute_engine.i_reg(instr_opcode_msb_c-1);
    if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then
 
      alu_immediate_v := '1';
    -- is rs1 == r0? --
    end if;
    rs1_is_r0_v := not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
 
 
    -- is rs1 = r0? --
 
    rs1_is_r0_v := '0';
 
    if (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
 
      rs1_is_r0_v := '1';
 
    end if;
 
 
 
    -- state machine --
    -- state machine --
    case execute_engine.state is
    case execute_engine.state is
 
 
      when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) ((and to init r0 with zero if it is a physical register))
      when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) ((and to init r0 with zero if it is a physical register))
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        -- set reg_file's r0 to zero --
        if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
        if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
          -- set reg_file.r0 to zero
 
          ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= (others => '0'); -- rd addr = r0
          ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= (others => '0'); -- rd addr = r0
          ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (results zero since there is no valid CSR_read request)
          ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (hacky! results zero since there is no valid CSR_read request)
          ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- allow write access to r0
          ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- allow write access to r0
          ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
          ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
        end if;
        end if;
        --
        --
        execute_engine.state_nxt <= DISPATCH;
        execute_engine.state_nxt <= DISPATCH;
Line 698... Line 694...
 
 
          when opcode_alu_c | opcode_alui_c => -- (immediate) ALU operation
          when opcode_alu_c | opcode_alui_c => -- (immediate) ALU operation
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            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_c)     <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opb_mux_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)     <= alu_immediate_v; -- use IMM as ALU.OPC for immediate operations (SLT(I)(U))
            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
 
 
            -- actual ALU operation (re-coding) --
            -- actual ALU operation (re-coding) --
            case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
            case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
              when funct3_subadd_c => -- ADD(I) / SUB
 
                if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 => SUB
 
                  ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_sub_c; -- SUB
 
                else
 
                  ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- ADD(I)
 
                end if;
 
              when funct3_sll_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SLL(I)
              when funct3_sll_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SLL(I)
              when funct3_slt_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c;   -- SLT(I)
              when funct3_slt_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c;   -- SLT(I)
              when funct3_sltu_c   => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c;   -- SLTU(I)
              when funct3_sltu_c   => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c;   -- SLTU(I)
              when funct3_xor_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_xor_c;   -- XOR(I)
              when funct3_xor_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_xor_c;   -- XOR(I)
              when funct3_sr_c     => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SRL(I) / SRA(I)
              when funct3_sr_c     => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SRL(I) / SRA(I)
              when funct3_or_c     => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c;    -- OR(I)
              when funct3_or_c     => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c;    -- OR(I)
              when funct3_and_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_and_c;   -- AND(I)
              when funct3_and_c    => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_and_c;   -- AND(I)
              when others          => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= (others => '0'); -- undefined
              when others => -- ADD(I) / SUB
 
                if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not an immediate op and funct7.6 set => SUB
 
                  ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_sub_c; -- SUB
 
                else
 
                  ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- ADD(I)
 
                end if;
            end case;
            end case;
 
 
            -- cp access? --
            -- cp access? --
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
            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?
               (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
Line 730... Line 725...
            -- multi cycle alu operation? --
            -- multi cycle alu operation? --
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
               ((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?
               ((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?
              execute_engine.state_nxt <= ALU_WAIT;
              execute_engine.state_nxt <= ALU_WAIT;
            else
            else -- single cycle ALU operation
              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;
 
 
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
              ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- ALU.OPA = CSR = 0 (hacky: csr.result is 0 since there was no csr_read_request)
              ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- ALU.OPA = CSR = 0 (hacky: csr.result is 0 since there is no csr_read_request)
            end if;
            end if;
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
            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
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
Line 758... Line 753...
            ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
            ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
            execute_engine.state_nxt    <= LOADSTORE_0;
            execute_engine.state_nxt    <= LOADSTORE_0;
 
 
          when opcode_branch_c => -- branch instruction
          when opcode_branch_c => -- branch instruction
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
            ctrl_nxt(ctrl_alu_opb_mux_c)     <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_opb_mux_c)     <= '1'; -- use IMM as ALU.OPB (branch target address offset)
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= '1'; -- use RS2 as ALU.OPC
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= '0'; -- use RS2 as ALU.OPC (for branch condition check)
            execute_engine.state_nxt         <= BRANCH;
            execute_engine.state_nxt         <= BRANCH;
 
 
          when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
          when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            -- compute target address --
            -- compute target address --
Line 781... Line 776...
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
            execute_engine.state_nxt   <= BRANCH;
            execute_engine.state_nxt   <= BRANCH;
 
 
          when opcode_fence_c => -- fence operations
          when opcode_fence_c => -- fence operations
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
            -- foe simplicity: internally, fence and fence.i perform the same operations ;)
              fetch_engine.reset          <= '1';
            -- FENCE.I --
 
            if (CPU_EXTENSION_RISCV_Zifencei = true) then
 
              execute_engine.pc_nxt     <= execute_engine.next_pc; -- "refetch" next instruction
              execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
              execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
              execute_engine.pc_nxt       <= execute_engine.next_pc; -- "refetch" next instruction (only relevant for fence.i)
              fetch_engine.reset        <= '1';
 
              if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
              ctrl_nxt(ctrl_bus_fencei_c) <= '1';
              ctrl_nxt(ctrl_bus_fencei_c) <= '1';
            end if;
            end if;
            if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then -- FENCE
            end if;
 
            -- FENCE --
 
            if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
            end if;
            end if;
 
            --
            execute_engine.state_nxt <= SYS_WAIT;
            execute_engine.state_nxt <= SYS_WAIT;
 
 
          when opcode_syscsr_c => -- system/csr access
          when opcode_syscsr_c => -- system/csr access
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access
            csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access
            ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= (others => '0'); -- set rs1_addr to r0 (zero)
            ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= (others => '0'); -- set rs1_addr to r0 (zero) (for CSR mod)
            ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- copy rs1_addr to rs2_addr (for CSR mod)
            ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- copy rs1_addr to rs2_addr (for CSR mod)
            --
            --
            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 funct12_ecall_c => -- ECALL
                when funct12_ecall_c => -- ECALL
Line 837... Line 838...
            csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
            csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
          when funct3_csrrs_c | funct3_csrrsi_c => -- CSRRS(I)
          when funct3_csrrs_c | funct3_csrrsi_c => -- CSRRS(I)
            ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
            ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
            csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
            csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
          when others => -- CSRRC(I)
          when others => -- CSRRC(I) -- FIXME?!
            ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
            ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bclr_c; -- actual ALU operation = bit clear
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bclr_c; -- actual ALU operation = bit clear
            csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
            csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
        end case;
        end case;
        -- RF write back --
        -- RF write back --
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output
        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; -- FIXME? should be SYS_WAIT? have another cycle to let side-effects kick in
        execute_engine.state_nxt  <= SYS_WAIT; -- have another cycle to let side-effects kick in
 
 
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c;
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c;
        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
Line 892... Line 893...
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
        if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
        if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= SYS_WAIT;
        elsif (bus_d_wait_i = '0') then -- wait here for bus to finish transaction
        elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
          if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then -- LOAD
          if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then -- LOAD
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
          end if;
          end if;
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
        end if;
        end if;
Line 914... Line 915...
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
 
 
  -- Illegal CSR Access Check ---------------------------------------------------------------
  -- Illegal CSR Access Check ---------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  invalid_csr_access_check: process(execute_engine, csr.privilege)
  invalid_csr_access_check: process(execute_engine.i_reg, csr.privilege)
    variable is_m_mode_v : std_ulogic;
    variable is_m_mode_v : std_ulogic;
  begin
  begin
    -- are we in machine mode? --
    -- are we in machine mode? --
    is_m_mode_v := '0';
    is_m_mode_v := '0';
    if (csr.privilege = m_priv_mode_c) then
    if (csr.privilege = m_priv_mode_c) then
Line 928... Line 929...
    -- check CSR access --
    -- check CSR access --
    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"300" => csr_acc_valid <= is_m_mode_v; -- mstatus
      when x"300" => csr_acc_valid <= is_m_mode_v; -- mstatus
      when x"301" => csr_acc_valid <= is_m_mode_v; -- misa
      when x"301" => csr_acc_valid <= is_m_mode_v; -- misa
      when x"304" => csr_acc_valid <= is_m_mode_v; -- mie
      when x"304" => csr_acc_valid <= is_m_mode_v; -- mie
      when x"305" => csr_acc_valid <= is_m_mode_v; -- mtvev
      when x"305" => csr_acc_valid <= is_m_mode_v; -- mtvec
      when x"340" => csr_acc_valid <= is_m_mode_v; -- mscratch
      when x"340" => csr_acc_valid <= is_m_mode_v; -- mscratch
      when x"341" => csr_acc_valid <= is_m_mode_v; -- mepc
      when x"341" => csr_acc_valid <= is_m_mode_v; -- mepc
      when x"342" => csr_acc_valid <= is_m_mode_v; -- mcause
      when x"342" => csr_acc_valid <= is_m_mode_v; -- mcause
      when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
      when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
      when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
      when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
Line 973... Line 974...
  end process invalid_csr_access_check;
  end process invalid_csr_access_check;
 
 
 
 
  -- Illegal Instruction Check --------------------------------------------------------------
  -- Illegal Instruction Check --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, csr_acc_valid)
  illegal_instruction_check: process(execute_engine, csr_acc_valid)
  begin
  begin
    -- illegal instructions are checked in the EXECUTE stage
    -- illegal instructions are checked in the EXECUTE stage
    -- the execute engine will only commit valid instructions
    -- the execute engine will only commit valid instructions
    if (execute_engine.state = EXECUTE) then
    if (execute_engine.state = EXECUTE) then
      -- defaults --
      -- defaults --
Line 1449... Line 1450...
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS only (is mcause(31))
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS only (is mcause(31))
              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'); -- mtval is zero for interrupts
              csr.mtval <= (others => '0'); -- mtval is zero 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.cause(4 downto 0) = trap_iba_c(4 downto 0)) or -- instr access error OR
              if (trap_ctrl.cause(4 downto 0) = trap_iba_c(4 downto 0)) or -- instruction access error OR
                 (trap_ctrl.cause(4 downto 0) = trap_ima_c(4 downto 0)) or -- misaligned instruction OR
                 (trap_ctrl.cause(4 downto 0) = trap_ima_c(4 downto 0)) or -- misaligned instruction address OR
                 (trap_ctrl.cause(4 downto 0) = trap_brk_c(4 downto 0)) or -- breakpoint OR
                 (trap_ctrl.cause(4 downto 0) = trap_brk_c(4 downto 0)) or -- breakpoint OR
                 (trap_ctrl.cause(4 downto 0) = trap_menv_c(4 downto 0)) then -- env call OR
                 (trap_ctrl.cause(4 downto 0) = trap_menv_c(4 downto 0)) then -- environment call
                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.cause(4 downto 0) = trap_iil_c(4 downto 0)) then -- illegal instruction
              elsif (trap_ctrl.cause(4 downto 0) = trap_iil_c(4 downto 0)) then -- illegal instruction
                csr.mtval <= execute_engine.i_reg; -- faulting instruction itself
                csr.mtval <= execute_engine.i_reg; -- faulting instruction itself
              else -- load/store misalignments/access errors
              else -- load/store misalignments/access errors
                csr.mtval <= mar_i; -- faulting data access address
                csr.mtval <= mar_i; -- faulting data access address
Line 1665... Line 1666...
            csr_rdata_o <= time_i(63 downto 32);
            csr_rdata_o <= time_i(63 downto 32);
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
            csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
            csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
 
 
          -- machine information registers --
          -- machine information registers --
          when x"f11" => -- R/-: mvendorid
          when x"f11" => -- R/-: mvendorid - vendor ID
            csr_rdata_o <= (others => '0'); -- not assigned
            csr_rdata_o <= (others => '0'); -- not assigned
          when x"f12" => -- R/-: marchid
          when x"f12" => -- R/-: marchid - architecture ID
            csr_rdata_o <= (others => '0'); -- not assigned
            csr_rdata_o <= (others => '0'); -- not assigned
          when x"f13" => -- R/-: mimpid - implementation ID / NEORV32 version
          when x"f13" => -- R/-: mimpid - implementation ID / NEORV32 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 <= HW_THREAD_ID;
            csr_rdata_o <= HW_THREAD_ID;

powered by: WebSVN 2.1.0

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