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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 35 and 36

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

Rev 35 Rev 36
Line 71... Line 71...
    bus_i_wait_i  : in  std_ulogic; -- wait for bus
    bus_i_wait_i  : in  std_ulogic; -- wait for bus
    bus_d_wait_i  : in  std_ulogic; -- wait for bus
    bus_d_wait_i  : in  std_ulogic; -- wait for bus
    -- data input --
    -- data input --
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
    alu_res_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU processing result
    alu_add_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result
 
    rs1_i         : in  std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
    -- data output --
    -- data output --
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
    next_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction)
    next_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction)
Line 89... Line 90...
    -- system time input from MTIME --
    -- system time input from MTIME --
    time_i        : in  std_ulogic_vector(63 downto 0); -- current system time
    time_i        : in  std_ulogic_vector(63 downto 0); -- current system time
    -- physical memory protection --
    -- physical memory protection --
    pmp_addr_o    : out pmp_addr_if_t; -- addresses
    pmp_addr_o    : out pmp_addr_if_t; -- addresses
    pmp_ctrl_o    : out pmp_ctrl_if_t; -- configs
    pmp_ctrl_o    : out pmp_ctrl_if_t; -- configs
    priv_mode_o   : out std_ulogic_vector(1 downto 0); -- current CPU privilege level
 
    -- 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
Line 267... Line 267...
 
 
  signal mcycle_msb   : std_ulogic;
  signal mcycle_msb   : std_ulogic;
  signal minstret_msb : std_ulogic;
  signal minstret_msb : std_ulogic;
 
 
  -- illegal instruction check --
  -- illegal instruction check --
 
  signal illegal_opcode_lsbs : std_ulogic; -- if opcode != rv32
  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
 
 
  -- access (privilege) check --
  -- access (privilege) check --
Line 357... Line 358...
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
 
 
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  instr_prefetch_buffer_ctrl: process(rstn_i, clk_i)
  instr_prefetch_buffer: process(clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if rising_edge(clk_i) then
      ipb.w_pnt <= (others => '0');
 
      ipb.r_pnt <= (others => '0');
 
    elsif rising_edge(clk_i) then
 
      -- write port --
      -- write port --
      if (ipb.clear = '1') then
      if (ipb.clear = '1') then
        ipb.w_pnt <= (others => '0');
        ipb.w_pnt <= (others => '0');
      elsif (ipb.we = '1') then
      elsif (ipb.we = '1') then
        ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
        ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
      end if;
      end if;
      -- read ports --
      if (ipb.we = '1') then -- write port
 
        ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata;
 
      end if;
 
      -- read port --
      if (ipb.clear = '1') then
      if (ipb.clear = '1') then
        ipb.r_pnt <= (others => '0');
        ipb.r_pnt <= (others => '0');
      elsif (ipb.re = '1') then
      elsif (ipb.re = '1') then
        ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1);
        ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1);
      end if;
      end if;
    end if;
    end if;
  end process instr_prefetch_buffer_ctrl;
  end process instr_prefetch_buffer;
 
 
  instr_prefetch_buffer_data: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      if (ipb.we = '1') then -- write port
 
        ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata;
 
      end if;
 
    end if;
 
  end process instr_prefetch_buffer_data;
 
 
 
  -- async read --
  -- async read --
  ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
  ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
 
 
  -- status --
  -- status --
Line 448... Line 440...
    -- instruction prefetch buffer interface defaults --
    -- instruction prefetch buffer interface defaults --
    ipb.re <= '0';
    ipb.re <= '0';
 
 
    -- instruction buffer interface defaults --
    -- instruction buffer interface defaults --
    i_buf.we    <= '0';
    i_buf.we    <= '0';
 
    -- i_buf = <illegal_compressed_instruction> & <bus_error & alignment_error> & <is_compressed_instrucion> & <32-bit_instruction_word>
    i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
    i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
 
 
    -- state machine --
    -- state machine --
    case issue_engine.state is
    case issue_engine.state is
 
 
Line 459... Line 452...
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        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 (i_buf.free = '1') then
            if (i_buf.free = '1') then
 
              i_buf.we <= '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';
                i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
                i_buf.wdata <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
                i_buf.we    <= '1';
 
              else -- compressed
              else -- compressed
                ipb.re      <= '1';
                ipb.re      <= '1';
                i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
                i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
                i_buf.we    <= '1';
 
                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 (i_buf.free = '1') then
            if (i_buf.free = '1') then
 
              i_buf.we <= '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';
                i_buf.wdata <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
                i_buf.wdata <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
                i_buf.we    <= '1';
 
              else -- compressed
              else -- compressed
                --ipb.re      <= '1';
                -- do not read from ipb here!
                i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
                i_buf.wdata <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
                i_buf.we    <= '1';
 
                issue_engine.align_nxt <= '0';
                issue_engine.align_nxt <= '0';
              end if;
              end if;
            end if;
            end if;
          end if;
          end if;
        end if;
        end if;
Line 531... Line 522...
  end generate;
  end generate;
 
 
 
 
  -- Instruction Buffer ---------------------------------------------------------------------
  -- Instruction Buffer ---------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  instruction_buffer_ctrl: process(rstn_i, clk_i)
  instruction_buffer: process(clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if rising_edge(clk_i) then
      i_buf.status <= '0';
 
    elsif rising_edge(clk_i) then
 
      if (i_buf.clear = '1') then
      if (i_buf.clear = '1') then
        i_buf.status <= '0';
        i_buf.status <= '0';
      elsif (i_buf.we = '1') then
      elsif (i_buf.we = '1') then
        i_buf.status <= '1';
        i_buf.status <= '1';
      elsif (i_buf.re = '1') then
      elsif (i_buf.re = '1') then
        i_buf.status <= '0';
        i_buf.status <= '0';
      end if;
      end if;
    end if;
 
  end process instruction_buffer_ctrl;
 
 
 
  instruction_buffer_data: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      if (i_buf.we = '1') then
      if (i_buf.we = '1') then
        i_buf.rdata <= i_buf.wdata;
        i_buf.rdata <= i_buf.wdata;
      end if;
      end if;
    end if;
    end if;
  end process instruction_buffer_data;
  end process instruction_buffer;
 
 
  -- status --
  -- status --
  i_buf.free  <= not i_buf.status;
  i_buf.free  <= not i_buf.status;
  i_buf.avail <= i_buf.status;
  i_buf.avail <= i_buf.status;
 
 
Line 596... Line 579...
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
          imm_o(11)           <= execute_engine.i_reg(20);
          imm_o(11)           <= execute_engine.i_reg(20);
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
          imm_o(00)           <= '0';
          imm_o(00)           <= '0';
        when opcode_syscsr_c => -- CSR-immediate (uimm5)
 
          imm_o(31 downto 05) <= (others => '0');
 
          imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
 
        when others => -- I-immediate
        when others => -- I-immediate
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
          imm_o(00)           <= execute_engine.i_reg(20);
          imm_o(00)           <= execute_engine.i_reg(20);
Line 678... Line 658...
  next_pc_o <= next_pc_tmp(data_width_c-1 downto 1) & '0';
  next_pc_o <= next_pc_tmp(data_width_c-1 downto 1) & '0';
 
 
 
 
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine)
  ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr.privilege)
  begin
  begin
 
    -- signals from execute engine --
    ctrl_o <= ctrl;
    ctrl_o <= ctrl;
 
    -- current privilege level --
 
    ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege;
 
    -- register addresses --
 
    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_rd_adr4_c   downto ctrl_rf_rd_adr0_c)  <= execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c);
    -- fast bus access requests --
    -- fast bus access requests --
    ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
    ctrl_o(ctrl_bus_if_c) <= bus_fast_ir;
    -- bus error control --
    -- bus error control --
    ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack;
    ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack;
    ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack;
    ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack;
    -- co-processor operation --
    -- instruction's function blocks (for co-processors) --
    ctrl_o(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c);
    ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
 
    ctrl_o(ctrl_ir_funct3_2_c   downto ctrl_ir_funct3_0_c)  <= execute_engine.i_reg(instr_funct3_msb_c  downto instr_funct3_lsb_c);
  end process ctrl_output;
  end process ctrl_output;
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  execute_engine_fsm_comb: process(execute_engine, fetch_engine, i_buf, trap_ctrl, csr, ctrl, csr_acc_valid,
  execute_engine_fsm_comb: process(execute_engine, fetch_engine, i_buf, trap_ctrl, csr, ctrl, csr_acc_valid,
                                   alu_res_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
                                   alu_add_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
    variable alu_immediate_v : std_ulogic;
    variable alu_immediate_v : std_ulogic;
    variable rs1_is_r0_v     : std_ulogic;
    variable rs1_is_r0_v     : std_ulogic;
 
    variable opcode_v        : std_ulogic_vector(6 downto 0);
  begin
  begin
    -- arbiter defaults --
    -- arbiter defaults --
    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';
Line 729... Line 718...
    -- CSR access --
    -- CSR access --
    csr.we_nxt                 <= '0';
    csr.we_nxt                 <= '0';
    csr.re_nxt                 <= '0';
    csr.re_nxt                 <= '0';
 
 
    -- control defaults --
    -- control defaults --
    ctrl_nxt <= (others => '0'); -- all off at first
    ctrl_nxt <= (others => '0'); -- default: all off
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU)
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
    else -- branches
    else -- branches
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU)
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
    end if;
    end if;
    ctrl_nxt(ctrl_bus_unsigned_c)  <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
    ctrl_nxt(ctrl_bus_unsigned_c)  <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
    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_alu_cmd2_c     downto ctrl_alu_cmd0_c)     <= alu_cmd_addsub_c; -- default ALU operation: ADD(I)
    ctrl_nxt(ctrl_alu_cmd2_c     downto ctrl_alu_cmd0_c)     <= alu_cmd_addsub_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_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_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_bus_size_msb_c downto ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c); -- mem transfer size
    ctrl_nxt(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c); -- mem transfer size
 
 
    -- is immediate ALU operation? --
    -- is immediate ALU operation? --
    alu_immediate_v := not execute_engine.i_reg(instr_opcode_msb_c-1);
    alu_immediate_v := not execute_engine.i_reg(instr_opcode_msb_c-1);
 
 
Line 759... Line 745...
 
 
      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 --
        -- 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?
          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 (hacky! 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'; -- force RF write access and force rd=r0
          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;
 
 
      when DISPATCH => -- Get new command from instruction buffer (I_BUF)
      when DISPATCH => -- Get new command from instruction buffer (i_buf)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= i_buf.rdata(instr_rd_msb_c  downto instr_rd_lsb_c); -- rd addr
 
        ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= i_buf.rdata(instr_rs1_msb_c downto instr_rs1_lsb_c); -- rs1 addr
 
        ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= i_buf.rdata(instr_rs2_msb_c downto instr_rs2_lsb_c); -- rs2 addr
 
        --
 
        if (i_buf.avail = '1') then -- instruction available?
        if (i_buf.avail = '1') then -- instruction available?
          i_buf.re <= '1';
          i_buf.re <= '1';
          --
          --
          execute_engine.is_ci_nxt  <= i_buf.rdata(32); -- flag to indicate this is a de-compressed instruction beeing executed
          execute_engine.is_ci_nxt  <= i_buf.rdata(32); -- flag to indicate this is a de-compressed instruction beeing executed
          execute_engine.i_reg_nxt  <= i_buf.rdata(31 downto 0);
          execute_engine.i_reg_nxt  <= i_buf.rdata(31 downto 0);
          execute_engine.if_rst_nxt <= '0';
 
          --
 
          trap_ctrl.instr_ma <= i_buf.rdata(33); -- misaligned instruction fetch address
          trap_ctrl.instr_ma <= i_buf.rdata(33); -- misaligned instruction fetch address
          trap_ctrl.instr_be <= i_buf.rdata(34); -- bus access fault during instrucion fetch
          trap_ctrl.instr_be <= i_buf.rdata(34); -- bus access fault during instrucion fetch
          illegal_compressed <= i_buf.rdata(35); -- invalid decompressed instruction
          illegal_compressed <= i_buf.rdata(35); -- invalid decompressed instruction
          --
          --
 
          execute_engine.if_rst_nxt <= '0';
          if (execute_engine.if_rst = '0') then -- if there was NO non-linear PC modification
          if (execute_engine.if_rst = '0') then -- if there was NO non-linear PC modification
            execute_engine.pc_nxt <= execute_engine.next_pc;
            execute_engine.pc_nxt <= execute_engine.next_pc;
          end if;
          end if;
          --
          --
          -- any reason to go FAST to trap state? --
          -- any reason to go FAST to trap state? --
Line 812... Line 791...
 
 
      when EXECUTE => -- Decode and execute instruction
      when EXECUTE => -- Decode and execute instruction
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.last_pc_nxt <= execute_engine.pc; -- store address of current instruction for commit
        execute_engine.last_pc_nxt <= execute_engine.pc; -- store address of current instruction for commit
        --
        --
        case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
 
        case opcode_v is
 
 
          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_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opa_mux_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
Line 899... Line 879...
            execute_engine.is_jump_nxt <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- is this is a jump operation? (for JAL/JALR)
            execute_engine.is_jump_nxt <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- is this is a jump operation? (for JAL/JALR)
            execute_engine.state_nxt   <= BRANCH;
            execute_engine.state_nxt   <= BRANCH;
 
 
          when opcode_fence_c => -- fence operations
          when opcode_fence_c => -- fence operations
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            -- for simplicity: internally, fence and fence.i perform the same operations (flush and reload of instruction prefetch buffer)
            execute_engine.state_nxt <= SYS_WAIT;
 
            -- for simplicity: internally, fence and fence.i perform the same operations (clear and reload instruction prefetch buffer)
            -- FENCE.I --
            -- FENCE.I --
            if (CPU_EXTENSION_RISCV_Zifencei = true) then
            if (CPU_EXTENSION_RISCV_Zifencei = true) then
              execute_engine.pc_nxt     <= execute_engine.next_pc; -- "refetch" next instruction
              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
              fetch_engine.reset        <= '1';
              fetch_engine.reset        <= '1';
Line 913... Line 894...
            end if;
            end if;
            -- FENCE --
            -- FENCE --
            if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
            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;
 
 
 
          when opcode_syscsr_c => -- system/csr access
          when opcode_syscsr_c => -- system/csr access
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            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
                  trap_ctrl.env_call <= '1';
                  trap_ctrl.env_call <= '1';
                when funct12_ebreak_c => -- EBREAK
                when funct12_ebreak_c => -- EBREAK
Line 931... Line 908...
                when funct12_mret_c => -- MRET
                when funct12_mret_c => -- MRET
                  trap_ctrl.env_end <= '1';
                  trap_ctrl.env_end <= '1';
                  execute_engine.pc_nxt <= csr.mepc;
                  execute_engine.pc_nxt <= csr.mepc;
                  fetch_engine.reset <= '1';
                  fetch_engine.reset <= '1';
                  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
                when funct12_wfi_c => -- WFI (CPU sleep)
                when funct12_wfi_c => -- WFI
                  execute_engine.sleep_nxt <= '1'; -- good night
                  execute_engine.sleep_nxt <= '1'; -- good night
                when others => -- undefined
                when others => -- undefined
                  NULL;
                  NULL;
              end case;
              end case;
              execute_engine.state_nxt <= SYS_WAIT;
              execute_engine.state_nxt <= SYS_WAIT;
Line 950... Line 927...
 
 
        end case;
        end case;
 
 
      when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR
      when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_alu_opb_mux_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- OPB = rs2 (which is rs1 here) / immediate
 
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_movb_c; -- actual ALU operation = MOVB
 
        -- CSR write access --
        -- CSR write access --
        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_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
          when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
            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 | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
          when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
Line 984... Line 959...
        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_res_i; -- branch/jump destination
          execute_engine.pc_nxt     <= alu_add_i; -- branch/jump destination
          fetch_engine.reset        <= '1'; -- trigger new instruction fetch from modified PC
          fetch_engine.reset        <= '1'; -- trigger new instruction fetch from modified PC
          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.state_nxt  <= SYS_WAIT;
          execute_engine.state_nxt  <= SYS_WAIT;
        else
        else
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
Line 1014... Line 989...
        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 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 (keep writing back all the time)
          end if;
          end if;
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
        end if;
        end if;
 
 
      when others => -- undefined
      when others => -- undefined
Line 1109... Line 1084...
 
 
 
 
  -- Illegal Instruction Check --------------------------------------------------------------
  -- Illegal Instruction Check --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  illegal_instruction_check: process(execute_engine, csr_acc_valid)
  illegal_instruction_check: process(execute_engine, csr_acc_valid)
 
    variable opcode_v : std_ulogic_vector(6 downto 0);
  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 should not commit any illegal instruction
    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';
 
 
 
      -- check opcode for rv32 --
 
      if (execute_engine.i_reg(instr_opcode_lsb_c+1 downto instr_opcode_lsb_c) = "11") then
 
        illegal_opcode_lsbs <= '0';
 
      else
 
        illegal_opcode_lsbs <= '1';
 
      end if;
 
 
      -- check instructions --
      -- check instructions --
      case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
      opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
 
      case opcode_v is
 
 
        -- OPCODE check sufficient: LUI, UIPC, JAL --
        -- OPCODE check sufficient: LUI, UIPC, JAL --
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
          illegal_instruction <= '0';
          illegal_instruction <= '0';
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
Line 1264... Line 1248...
            end if;
            end if;
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
 
 
        when others => -- compressed instruction or undefined instruction
        when others => -- undefined instruction -> illegal!
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
 
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
 
 
 
      end case;
      end case;
    else
    else
 
      illegal_opcode_lsbs <= '0';
      illegal_instruction <= '0';
      illegal_instruction <= '0';
      illegal_register    <= '0';
      illegal_register    <= '0';
    end if;
    end if;
  end process illegal_instruction_check;
  end process illegal_instruction_check;
 
 
  -- any illegal condition? --
  -- any illegal condition? --
  trap_ctrl.instr_il <= illegal_instruction or illegal_register or illegal_compressed;
  trap_ctrl.instr_il <= illegal_instruction or illegal_opcode_lsbs or illegal_register or illegal_compressed;
 
 
 
 
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Exception and Interrupt Control
-- Exception and Interrupt Control
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
Line 1449... Line 1432...
-- Control and Status Registers (CSRs)
-- Control and Status Registers (CSRs)
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
  -- Control and Status Registers Write Data ------------------------------------------------
  -- Control and Status Registers Write Data ------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_write_data: process(execute_engine.i_reg, csr.rdata, alu_res_i)
  csr_write_data: process(execute_engine.i_reg, csr.rdata, rs1_i)
 
    variable csr_operand_v : std_ulogic_vector(data_width_c-1 downto 0);
  begin
  begin
 
    -- CSR operand source --
 
    if (execute_engine.i_reg(instr_funct3_msb_c) = '1') then -- immediate
 
      csr_operand_v := (others => '0');
 
      csr_operand_v(4 downto 0) := execute_engine.i_reg(19 downto 15);
 
    else -- register
 
      csr_operand_v := rs1_i;
 
    end if;
    -- "mini ALU" for CSR update operations --
    -- "mini ALU" for CSR update operations --
    case execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c) is
    case execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c) is
      when "10"   => csr.wdata <= csr.rdata or alu_res_i; -- CSRRS(I)
      when "10"   => csr.wdata <= csr.rdata or csr_operand_v; -- CSRRS(I)
      when "11"   => csr.wdata <= csr.rdata and (not alu_res_i); -- CSRRC(I)
      when "11"   => csr.wdata <= csr.rdata and (not csr_operand_v); -- CSRRC(I)
      when others => csr.wdata <= alu_res_i; -- CSRRW(I)
      when others => csr.wdata <= csr_operand_v; -- CSRRW(I)
    end case;
    end case;
  end process csr_write_data;
  end process csr_write_data;
 
 
 
 
  -- Control and Status Registers Write Access ----------------------------------------------
  -- Control and Status Registers Write Access ----------------------------------------------
Line 1476... Line 1467...
      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.mie_firqe    <= (others => '0');
      csr.mie_firqe    <= (others => '0');
      csr.mtvec        <= (others => '0');
      csr.mtvec        <= (others => '0');
      csr.mscratch     <= (others => '0');
      csr.mscratch     <= x"19880704"; -- :)
      csr.mepc         <= (others => '0');
      csr.mepc         <= (others => '0');
      csr.mcause       <= (others => '0');
      csr.mcause       <= (others => '0');
      csr.mtval        <= (others => '0');
      csr.mtval        <= (others => '0');
      csr.pmpcfg       <= (others => (others => '0'));
      csr.pmpcfg       <= (others => (others => '0'));
      csr.pmpaddr      <= (others => (others => '0'));
      csr.pmpaddr      <= (others => (others => '0'));
Line 1490... Line 1481...
      csr.mcycleh      <= (others => '0');
      csr.mcycleh      <= (others => '0');
      csr.minstreth    <= (others => '0');
      csr.minstreth    <= (others => '0');
      mcycle_msb       <= '0';
      mcycle_msb       <= '0';
      minstret_msb     <= '0';
      minstret_msb     <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
 
 
      -- write access? --
      -- write access? --
      csr.we <= csr.we_nxt;
      csr.we <= csr.we_nxt;
 
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
 
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      -- CSRs that can be written by application software only
        -- CSR access by application software
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (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
        -- machine CSRs --
 
        if (execute_engine.i_reg(31 downto 28) = csr_mie_c(11 downto 8)) then
 
 
 
          -- machine trap setup --
          -- machine trap setup --
          if (execute_engine.i_reg(27 downto 24) = csr_mie_c(7 downto 4)) then
            -- --------------------------------------------------------------------
            if (execute_engine.i_reg(23 downto 20) = csr_mie_c(3 downto 0)) then -- R/W: mie - machine interrupt-enable register
            when csr_mstatus_c => -- R/W: mstatus - machine status register
 
              csr.mstatus_mie  <= csr.wdata(03);
 
              csr.mstatus_mpie <= csr.wdata(07);
 
              if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
 
                csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
 
                csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
 
              end if;
 
            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
            end if;
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            if (execute_engine.i_reg(23 downto 20) = csr_mtvec_c(3 downto 0)) then -- 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
            end if;
 
          end if;
 
 
 
          -- machine trap handling --
          -- machine trap handling --
          if (execute_engine.i_reg(27 downto 20) = csr_mscratch_c(7 downto 0)) then -- R/W: mscratch - machine scratch register
            -- --------------------------------------------------------------------
 
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
            csr.mscratch <= csr.wdata;
            csr.mscratch <= csr.wdata;
          end if;
            when csr_mepc_c => -- R/W: mepc - machine exception program counter
 
              csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
 
            when csr_mcause_c => -- R/W: mcause - machine trap cause
 
              csr.mcause <= (others => '0');
 
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
 
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
 
            when csr_mtval_c => -- R/W: mtval - machine bad address or instruction
 
              csr.mtval <= csr.wdata;
 
 
          -- machine physical memory protection (pmp) --
            -- physical memory protection - configuration --
          if (PMP_USE = true) then
            -- --------------------------------------------------------------------
            -- pmpcfg --
            when csr_pmpcfg0_c => -- R/W: pmpcfg0 - PMP configuration register 0
            if (execute_engine.i_reg(27 downto 24) = csr_pmpcfg0_c(7 downto 4)) then
              if (PMP_USE = true) and (PMP_NUM_REGIONS >= 1) then
              if (PMP_NUM_REGIONS >= 1) then
 
                if (execute_engine.i_reg(23 downto 20) = csr_pmpcfg0_c(3 downto 0)) then -- pmpcfg0
 
                  for j in 0 to 3 loop -- bytes in pmpcfg CSR
                  for j in 0 to 3 loop -- bytes in pmpcfg CSR
                    if ((j+1) <= PMP_NUM_REGIONS) then
                    if ((j+1) <= PMP_NUM_REGIONS) then
                      if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access
                      if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access
                        csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R (rights.read)
                        csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R (rights.read)
                        csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W (rights.write)
                        csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W (rights.write)
Line 1545... Line 1544...
                        csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode)
                        csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode)
                      end if;
                      end if;
                    end if;
                    end if;
                  end loop; -- j (bytes in CSR)
                  end loop; -- j (bytes in CSR)
                end if;
                end if;
              end if;
            when csr_pmpcfg1_c => -- R/W: pmpcfg1 - PMP configuration register 1
              if (PMP_NUM_REGIONS >= 5) then
              if (PMP_USE = true) and (PMP_NUM_REGIONS >= 5) then
                if (execute_engine.i_reg(23 downto 20) = csr_pmpcfg1_c(3 downto 0)) then -- pmpcfg1
 
                  for j in 0 to 3 loop -- bytes in pmpcfg CSR
                  for j in 0 to 3 loop -- bytes in pmpcfg CSR
                    if ((j+1+4) <= PMP_NUM_REGIONS) then
                    if ((j+1+4) <= PMP_NUM_REGIONS) then
                      if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access
                      if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access
                        csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R (rights.read)
                        csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R (rights.read)
                        csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W (rights.write)
                        csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W (rights.write)
Line 1563... Line 1561...
                        csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode)
                        csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode)
                      end if;
                      end if;
                    end if;
                    end if;
                  end loop; -- j (bytes in CSR)
                  end loop; -- j (bytes in CSR)
                end if;
                end if;
              end if;
 
            end if;
            -- physical memory protection - addresses --
            -- pmpaddr --
            -- --------------------------------------------------------------------
            if (execute_engine.i_reg(27 downto 24) = csr_pmpaddr0_c(7 downto 4)) then
            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
 
              if (PMP_USE = true) then
              for i in 0 to PMP_NUM_REGIONS-1 loop
              for i in 0 to PMP_NUM_REGIONS-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 (execute_engine.i_reg(23 downto 20) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
                  csr.pmpaddr(i) <= csr.wdata(31 downto 1) & '0'; -- min granularity is 8 bytes -> bit zero cannot be configured
                  csr.pmpaddr(i) <= csr.wdata(31 downto 1) & '0'; -- min granularity is 8 bytes -> bit zero cannot be configured
                end if;
                end if;
              end loop; -- i (CSRs)
              end loop; -- i (CSRs)
            end if;
            end if;
          end if; -- implement PMP at all?
 
        end if;
 
 
 
      end if;
 
 
 
      -- --------------------------------------------------------------------------------
 
      -- CSRs that can be written by application and hardware (application access)
 
      -- --------------------------------------------------------------------------------
 
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.we = '1') then -- manual update
 
 
 
        -- machine CSRs --
 
        if (execute_engine.i_reg(31 downto 28) = csr_mstatus_c(11 downto 8)) then
 
 
 
          -- machine trap setup --
            -- undefined --
          if (execute_engine.i_reg(27 downto 20) = csr_mstatus_c(7 downto 0)) then -- R/W: mstatus - machine status register
            -- --------------------------------------------------------------------
            csr.mstatus_mie  <= csr.wdata(03);
            when others =>
            csr.mstatus_mpie <= csr.wdata(07);
              NULL;
            --
 
            if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
 
              csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
 
              csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
 
            end if;
 
          end if;
 
 
 
          -- machine trap handling --
 
          if (execute_engine.i_reg(27 downto 24) = csr_mepc_c(7 downto 4)) then
 
            if (execute_engine.i_reg(23 downto 20) = csr_mepc_c(3 downto 0)) then -- R/W: mepc - machine exception program counter
 
              csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
 
            end if;
 
            if (execute_engine.i_reg(23 downto 20) = csr_mcause_c(3 downto 0)) then -- R/W: mcause - machine trap cause
 
              csr.mcause <= (others => '0');
 
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
 
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
 
            end if;
 
            if (execute_engine.i_reg(23 downto 20) = csr_mtval_c(3 downto 0)) then -- R/W: mtval - machine bad address or instruction
 
              csr.mtval <= csr.wdata;
 
            end if;
 
          end if;
 
 
 
        end if;
          end case;
 
 
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      -- CSRs that can be written by application and hardware (hardware access)
        -- CSR access by hardware
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      else -- hardware update
        else
 
 
        -- mepc & mtval: machine exception PC & machine trap value register --
        -- mepc & mtval: machine exception PC & machine trap value register --
 
          -- --------------------------------------------------------------------
        if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
        if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
          if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS (is mcause(31))
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS
            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 -- instruction access error OR
            if (trap_ctrl.cause(4 downto 0) = trap_iba_c(4 downto 0)) or -- instruction access error OR
Line 1640... Line 1608...
            end if;
            end if;
          end if;
          end if;
        end if;
        end if;
 
 
        -- mstatus: context switch --
        -- mstatus: context switch --
 
          -- --------------------------------------------------------------------
        if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
        if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
          -- trap ID code --
          -- trap ID code --
          csr.mcause <= (others => '0');
          csr.mcause <= (others => '0');
          csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
          csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
          csr.mcause(4 downto 0)      <= trap_ctrl.cause(4 downto 0); -- identifier
          csr.mcause(4 downto 0)      <= trap_ctrl.cause(4 downto 0); -- identifier
Line 1665... Line 1634...
        -- user mode NOT implemented --
        -- user mode NOT implemented --
        if (CPU_EXTENSION_RISCV_U = false) then
        if (CPU_EXTENSION_RISCV_U = false) then
          csr.privilege   <= priv_mode_m_c;
          csr.privilege   <= priv_mode_m_c;
          csr.mstatus_mpp <= priv_mode_m_c;
          csr.mstatus_mpp <= priv_mode_m_c;
        end if;
        end if;
      end if;
 
 
        end if; -- hardware csr access
 
 
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      -- Counter CSRs
      -- Counter CSRs
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
 
 
        -- mcycle (cycle) --
        -- mcycle (cycle) --
        mcycle_msb <= csr.mcycle(csr.mcycle'left);
 
        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 (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycle_c) then -- write access
          csr.mcycle(31 downto 0) <= csr.wdata;
          csr.mcycle <= '0' & csr.wdata;
          csr.mcycle(32) <= '0';
          mcycle_msb <= '0';
        elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
        elsif (execute_engine.sleep = '0') then -- 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);
        end if;
        end if;
 
 
        -- mcycleh (cycleh) --
        -- mcycleh (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 (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycleh_c) then -- write access
          csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
          csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
        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
          csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
          csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
        end if;
        end if;
 
 
        -- minstret (instret) --
        -- minstret (instret) --
        minstret_msb <= csr.minstret(csr.minstret'left);
 
        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 (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstret_c) then -- write access
          csr.minstret(31 downto 0) <= csr.wdata;
          csr.minstret <= '0' & csr.wdata;
          csr.minstret(32) <= '0';
          minstret_msb <= '0';
        elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
        elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update (if CPU commits 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);
        end if;
        end if;
 
 
        -- minstreth (instreth) --
        -- minstreth (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 (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstreth_c) then -- write access
          csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
          csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
        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
          csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
          csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
        end if;
        end if;
 
 
      end if;
      end if;
    end if;
    end if;
  end process csr_write_access;
  end process csr_write_access;
 
 
  -- CPU's current privilege level --
  -- PMP configuration output to bus unit --
  priv_mode_o <= csr.privilege;
 
 
 
  -- PMP output --
 
  pmp_output: process(csr)
  pmp_output: process(csr)
  begin
  begin
    pmp_addr_o <= (others => (others => '0'));
    pmp_addr_o <= (others => (others => '0'));
    pmp_ctrl_o <= (others => (others => '0'));
    pmp_ctrl_o <= (others => (others => '0'));
    if (PMP_USE = true) then
    if (PMP_USE = true) then
Line 1741... Line 1708...
            csr.rdata(03) <= csr.mstatus_mie;  -- MIE
            csr.rdata(03) <= csr.mstatus_mie;  -- MIE
            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_misa_c => -- R/-: misa - ISA and extensions
          when csr_misa_c => -- R/-: misa - ISA and extensions
 
            csr.rdata(00) <= '0';                                         -- A CPU extension
 
            csr.rdata(01) <= '0';                                         -- B 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)
            csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
            csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
            csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);     -- U CPU extension
            csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);     -- U CPU extension

powered by: WebSVN 2.1.0

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