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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 12 and 13

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

Rev 12 Rev 13
Line 95... Line 95...
end neorv32_cpu_control;
end neorv32_cpu_control;
 
 
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
 
 
  -- instruction fetch enginge --
  -- instruction fetch enginge --
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3);
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2);
  type fetch_engine_t is record
  type fetch_engine_t is record
    state           : fetch_engine_state_t;
    state           : fetch_engine_state_t;
    state_nxt       : fetch_engine_state_t;
    state_nxt       : fetch_engine_state_t;
    i_buf           : std_ulogic_vector(33 downto 0);
    i_buf           : std_ulogic_vector(33 downto 0);
    i_buf_nxt       : std_ulogic_vector(33 downto 0);
    i_buf_nxt       : std_ulogic_vector(33 downto 0);
    i_buf2          : std_ulogic_vector(33 downto 0);
    i_buf2          : std_ulogic_vector(33 downto 0);
    i_buf2_nxt      : std_ulogic_vector(33 downto 0);
    i_buf2_nxt      : std_ulogic_vector(33 downto 0);
    ci_reg          : std_ulogic_vector(17 downto 0);
    ci_input        : std_ulogic_vector(15 downto 0); -- input to compressed instr. decoder
    ci_reg_nxt      : std_ulogic_vector(17 downto 0);
 
    i_buf_state     : std_ulogic_vector(01 downto 0);
    i_buf_state     : std_ulogic_vector(01 downto 0);
    i_buf_state_nxt : std_ulogic_vector(01 downto 0);
    i_buf_state_nxt : std_ulogic_vector(01 downto 0);
    pc_real         : std_ulogic_vector(data_width_c-1 downto 0);
    pc_real         : std_ulogic_vector(data_width_c-1 downto 0);
    pc_real_add     : std_ulogic_vector(data_width_c-1 downto 0);
    pc_real_add     : std_ulogic_vector(data_width_c-1 downto 0);
    pc_fetch        : std_ulogic_vector(data_width_c-1 downto 0);
    pc_fetch        : std_ulogic_vector(data_width_c-1 downto 0);
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
    ci_return       : std_ulogic;
 
    ci_return_nxt   : std_ulogic;
 
    reset           : std_ulogic;
    reset           : std_ulogic;
    bus_err_ack     : std_ulogic;
    bus_err_ack     : std_ulogic;
  end record;
  end record;
  signal fetch_engine : fetch_engine_t;
  signal fetch_engine : fetch_engine_t;
 
 
Line 124... Line 121...
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
  signal ci_illegal : std_ulogic;
  signal ci_illegal : std_ulogic;
 
 
  -- instrucion prefetch buffer (IPB) --
  -- instrucion prefetch buffer (IPB) --
  type ipb_t is record
  type ipb_t is record
    wdata  : std_ulogic_vector(34 downto 0);
    wdata  : std_ulogic_vector(35 downto 0);
    rdata  : std_ulogic_vector(34 downto 0);
    rdata  : std_ulogic_vector(35 downto 0);
    waddr  : std_ulogic_vector(31 downto 0);
    waddr  : std_ulogic_vector(31 downto 0);
    raddr  : std_ulogic_vector(31 downto 0);
    raddr  : std_ulogic_vector(31 downto 0);
    status : std_ulogic;
    status : std_ulogic;
    free   : std_ulogic;
    free   : std_ulogic;
    avail  : std_ulogic;
    avail  : std_ulogic;
Line 235... Line 232...
  neorv32_cpu_decompressor_inst_true:
  neorv32_cpu_decompressor_inst_true:
  if (CPU_EXTENSION_RISCV_C = true) generate
  if (CPU_EXTENSION_RISCV_C = true) generate
    neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
    neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
    port map (
    port map (
      -- instruction input --
      -- instruction input --
      ci_instr16_i => fetch_engine.ci_reg(15 downto 0), -- compressed instruction input
      ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
      -- instruction output --
      -- instruction output --
      ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
      ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
      ci_instr32_o => ci_instr32  -- 32-bit decompressed instruction
      ci_instr32_o => ci_instr32  -- 32-bit decompressed instruction
    );
    );
  end generate;
  end generate;
Line 281... Line 278...
      end if;
      end if;
      --
      --
      fetch_engine.i_buf       <= fetch_engine.i_buf_nxt;
      fetch_engine.i_buf       <= fetch_engine.i_buf_nxt;
      fetch_engine.i_buf2      <= fetch_engine.i_buf2_nxt;
      fetch_engine.i_buf2      <= fetch_engine.i_buf2_nxt;
      fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt;
      fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt;
      --
 
      fetch_engine.ci_reg      <= fetch_engine.ci_reg_nxt;
 
      fetch_engine.ci_return   <= fetch_engine.ci_return_nxt;
 
    end if;
    end if;
  end process fetch_engine_fsm_sync;
  end process fetch_engine_fsm_sync;
 
 
  -- PC output --
  -- PC output --
  fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0';
  fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0';
 
 
 
 
  -- Fetch Engine FSM Comb ------------------------------------------------------------------
  -- Fetch Engine FSM Comb ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  fetch_engine_fsm_comb: process(fetch_engine, csr, ipb, instr_i, bus_i_wait_i, ci_instr32, be_instr_i, ma_instr_i)
  fetch_engine_fsm_comb: process(fetch_engine, csr, ipb, instr_i, bus_i_wait_i, ci_instr32, ci_illegal, be_instr_i, ma_instr_i)
  begin
  begin
    -- arbiter defaults --
    -- arbiter defaults --
 
    bus_fast_ir                  <= '0';
    fetch_engine.state_nxt       <= fetch_engine.state;
    fetch_engine.state_nxt       <= fetch_engine.state;
    fetch_engine.pc_fetch_add    <= (others => '0');
    fetch_engine.pc_fetch_add    <= (others => '0');
    fetch_engine.pc_real_add     <= (others => '0');
    fetch_engine.pc_real_add     <= (others => '0');
    bus_fast_ir                  <= '0';
 
    fetch_engine.i_buf_nxt       <= fetch_engine.i_buf;
    fetch_engine.i_buf_nxt       <= fetch_engine.i_buf;
    fetch_engine.i_buf2_nxt      <= fetch_engine.i_buf2;
    fetch_engine.i_buf2_nxt      <= fetch_engine.i_buf2;
    fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
    fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
    fetch_engine.ci_reg_nxt      <= fetch_engine.ci_reg;
    fetch_engine.ci_input        <= fetch_engine.i_buf2(15 downto 00);
    fetch_engine.ci_return_nxt   <= fetch_engine.ci_return;
 
    fetch_engine.bus_err_ack     <= '0';
    fetch_engine.bus_err_ack     <= '0';
 
 
    -- instruction prefetch buffer interface --
    -- instruction prefetch buffer interface --
    ipb.we    <= '0';
    ipb.we    <= '0';
    ipb.clear <= '0';
    ipb.clear <= '0';
    ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
    ipb.wdata <= '0' & fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
 
 
    -- state machine --
    -- state machine --
    case fetch_engine.state is
    case fetch_engine.state is
 
 
      when IFETCH_RESET => -- reset engine, prefetch buffer, get appilcation PC
      when IFETCH_RESET => -- reset engine, prefetch buffer, get appilcation PC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.i_buf_state_nxt <= (others => '0');
        fetch_engine.i_buf_state_nxt <= (others => '0');
        fetch_engine.ci_return_nxt   <= '0';
 
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
        fetch_engine.state_nxt       <= IFETCH_0;
        fetch_engine.state_nxt       <= IFETCH_0;
 
 
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 346... Line 338...
        end if;
        end if;
 
 
      when IFETCH_2 => -- construct instruction word and issue
      when IFETCH_2 => -- construct instruction word and issue
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
       if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
       if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
         fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
          fetch_engine.ci_input <= fetch_engine.i_buf2(15 downto 00);
         ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
 
 
 
         if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
 
           if (ipb.free = '1') then -- free entry in buffer?
           if (ipb.free = '1') then -- free entry in buffer?
             ipb.we                    <= '1';
             ipb.we                    <= '1';
 
            if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
 
              ipb.wdata                 <= '0' & fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
             fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.state_nxt    <= IFETCH_0;
             fetch_engine.state_nxt    <= IFETCH_0;
           end if;
 
         else -- compressed
         else -- compressed
           fetch_engine.ci_return_nxt <= '1'; -- come back here after issueing
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf2(33 downto 32) & '1' & ci_instr32;
           fetch_engine.state_nxt     <= IFETCH_3;
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
 
              fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
 
              fetch_engine.state_nxt    <= IFETCH_2; -- try to get another 16-bit instruction word in next round
 
            end if;
         end if;
         end if;
 
 
       else -- 16-bit aligned
       else -- 16-bit aligned
         fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(31 downto 16);
          fetch_engine.ci_input <= fetch_engine.i_buf2(31 downto 16);
         ipb.wdata <= fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
 
 
 
         if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
 
           if (ipb.free = '1') then -- free entry in buffer?
           if (ipb.free = '1') then -- free entry in buffer?
             ipb.we                    <= '1';
             ipb.we                    <= '1';
 
            if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
 
              ipb.wdata                 <= '0' & fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
             fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
             fetch_engine.state_nxt    <= IFETCH_0;
             fetch_engine.state_nxt    <= IFETCH_0;
           end if;
            else -- uncompressed
         else -- compressed
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
           fetch_engine.ci_return_nxt <= '0'; -- start next fetch after issueing
 
           fetch_engine.state_nxt     <= IFETCH_3;
 
         end if;
 
       end if;
 
 
 
      when IFETCH_3 => -- additional cycle for issueing decompressed instructions
 
      -- ------------------------------------------------------------
 
        if (ipb.free = '1') then -- free entry in buffer?
 
          ipb.we                    <= '1';
 
          ipb.wdata                 <= fetch_engine.ci_reg(17 downto 16) & '1' & ci_instr32;
 
          fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
          fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
          fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
          fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
          if (fetch_engine.ci_return = '0') then
 
            fetch_engine.state_nxt <= IFETCH_0;
            fetch_engine.state_nxt <= IFETCH_0;
          else
            end if;
            fetch_engine.state_nxt <= IFETCH_2;
 
          end if;
          end if;
        end if;
        end if;
 
 
      when others => -- undefined
      when others => -- undefined
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 407... Line 389...
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
 
 
  -- Instruction Prefetch Buffer Stage ------------------------------------------------------
  -- Instruction Prefetch Buffer Stage ------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  instr_prefetch_buffer: process(rstn_i, clk_i)
  instr_prefetch_buffer: process(rstn_i, clk_i) -- once upon a time, this was a fifo with 8 entries
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      ipb.status <= '0';
      ipb.status <= '0';
      ipb.rdata  <= (others => '0');
      ipb.rdata  <= (others => '0');
      ipb.raddr  <= (others => '0');
      ipb.raddr  <= (others => '0');
Line 507... Line 489...
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      execute_engine.pc      <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.pc      <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.last_pc <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.last_pc <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.state   <= SYS_WAIT;
      execute_engine.state   <= SYS_WAIT;
      --
 
      execute_engine.sleep <= '0';
      execute_engine.sleep <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
      if (execute_engine.state = EXECUTE) then
      if (execute_engine.state = EXECUTE) then
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
      end if;
      end if;
      execute_engine.state <= execute_engine.state_nxt;
      execute_engine.state <= execute_engine.state_nxt;
      --
 
      execute_engine.sleep <= execute_engine.sleep_nxt;
      execute_engine.sleep <= execute_engine.sleep_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync_rst;
  end process execute_engine_fsm_sync_rst;
 
 
 
 
Line 570... Line 550...
    -- 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';
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
    execute_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0';
    execute_engine.pc_nxt      <= execute_engine.pc;
    execute_engine.sleep_nxt   <= execute_engine.sleep;
    execute_engine.sleep_nxt   <= execute_engine.sleep;
 
 
    -- instruction dispatch --
    -- instruction dispatch --
    fetch_engine.reset         <= '0';
    fetch_engine.reset         <= '0';
    ipb.re                     <= '0';
    ipb.re                     <= '0';
Line 586... Line 566...
    -- exception trigger --
    -- exception trigger --
    trap_ctrl.instr_be         <= '0';
    trap_ctrl.instr_be         <= '0';
    trap_ctrl.instr_ma         <= '0';
    trap_ctrl.instr_ma         <= '0';
    trap_ctrl.env_call         <= '0';
    trap_ctrl.env_call         <= '0';
    trap_ctrl.break_point      <= '0';
    trap_ctrl.break_point      <= '0';
 
    illegal_compressed         <= '0';
 
 
    -- CSR access --
    -- CSR access --
    csr.we_nxt                 <= '0';
    csr.we_nxt                 <= '0';
    csr.re_nxt                 <= '0';
    csr.re_nxt                 <= '0';
 
 
Line 599... Line 580...
      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
    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); -- 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_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 (MULDIV) implemented yet
 
 
Line 647... Line 628...
 
 
       when DISPATCH => -- Get new command from instruction prefetch buffer (IPB)
       when DISPATCH => -- Get new command from instruction prefetch buffer (IPB)
       -- ------------------------------------------------------------
       -- ------------------------------------------------------------
         if (ipb.avail = '1') then -- instruction available?
         if (ipb.avail = '1') then -- instruction available?
           ipb.re <= '1';
           ipb.re <= '1';
           trap_ctrl.instr_ma    <= ipb.rdata(33);
          trap_ctrl.instr_ma <= ipb.rdata(33); -- misaligned instruction fetch address
           trap_ctrl.instr_be    <= ipb.rdata(34);
          trap_ctrl.instr_be <= ipb.rdata(34); -- bus access fault druing instrucion fetch
           if (trap_ctrl.env_start = '1') or (ipb.rdata(33) = '1') or (ipb.rdata(34) = '1') then -- exception/interrupt?
          illegal_compressed <= ipb.rdata(35); -- invalid decompressed instruction
 
          if (trap_ctrl.env_start = '1') or ((ipb.rdata(33) or ipb.rdata(34) or ipb.rdata(35)) = '1') then -- exception/interrupt?
             execute_engine.state_nxt <= TRAP;
             execute_engine.state_nxt <= TRAP;
           else
           else
             execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
             execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
             execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
             execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
             execute_engine.pc_nxt    <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction
            execute_engine.pc_nxt    <= ipb.raddr; -- the PC according to the current instruction
             if (execute_engine.sleep = '1') then
             if (execute_engine.sleep = '1') then
               execute_engine.state_nxt <= TRAP;
               execute_engine.state_nxt <= TRAP;
             else
             else
               execute_engine.state_nxt <= EXECUTE;
               execute_engine.state_nxt <= EXECUTE;
             end if;
             end if;
Line 666... Line 648...
         end if;
         end if;
 
 
      when TRAP => -- Start trap environment (also used as cpu sleep state)
      when TRAP => -- Start trap environment (also used as cpu sleep state)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.reset <= '1';
        fetch_engine.reset <= '1';
        if (trap_ctrl.env_start = '1') then
        if (trap_ctrl.env_start = '1') then -- check here again if we came directly from DISPATCH
          trap_ctrl.env_start_ack  <= '1';
          trap_ctrl.env_start_ack  <= '1';
 
          execute_engine.pc_nxt    <= csr.mtvec;
          execute_engine.sleep_nxt <= '0'; -- waky waky
          execute_engine.sleep_nxt <= '0'; -- waky waky
          execute_engine.pc_nxt    <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- has to be here for wfi to work
 
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= SYS_WAIT;
        end if;
        end if;
 
 
      when EXECUTE => -- Decode and execute instruction
      when EXECUTE => -- Decode and execute instruction
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 740... Line 722...
            else -- JALR
            else -- JALR
              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
            end if;
            end if;
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
            -- save return address --
            -- save return address --
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = current PC
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = next PC (save return address)
            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.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;
 
 
Line 760... Line 742...
            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 <= '1'; -- always read CSR
            csr.re_nxt <= '1'; -- always read CSR - regardless of actual operation
            --
 
            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
                  trap_ctrl.break_point <= '1';
                  trap_ctrl.break_point <= '1';
                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(data_width_c-1 downto 1) & '0';
                  execute_engine.pc_nxt <= csr.mepc;
                  fetch_engine.reset    <= '1';
                  fetch_engine.reset    <= '1';
                when funct12_wfi_c => -- WFI = "CPU sleep"
                when funct12_wfi_c => -- WFI = "CPU sleep"
                  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;
            else
            else -- CSR access
              if (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
 
                execute_engine.state_nxt <= CSR_ACCESS;
                execute_engine.state_nxt <= CSR_ACCESS;
              else -- undefined
 
                execute_engine.state_nxt <= DISPATCH;
 
              end if;
 
            end if;
            end if;
 
 
          when others => -- undefined
          when others => -- undefined
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.state_nxt <= DISPATCH;
            execute_engine.state_nxt <= DISPATCH;
Line 853... Line 830...
          execute_engine.state_nxt  <= DISPATCH;
          execute_engine.state_nxt  <= DISPATCH;
        end if;
        end if;
 
 
      when BRANCH => -- update PC for taken branches and jumps
      when BRANCH => -- update PC for taken branches and jumps
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        execute_engine.pc_nxt <= alu_add_i; -- branch/jump destination
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
          execute_engine.pc_nxt    <= alu_add_i(data_width_c-1 downto 1) & '0'; -- branch/jump destination
          fetch_engine.reset       <= '1'; -- trigger new instruction fetch from modified PC
          fetch_engine.reset       <= '1';
 
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= SYS_WAIT;
        else
        else
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
        end if;
        end if;
 
 
Line 898... Line 875...
  end process execute_engine_fsm_comb;
  end process execute_engine_fsm_comb;
 
 
 
 
  -- Illegal Instruction Check --------------------------------------------------------------
  -- Illegal Instruction Check --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt)
  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 --
      illegal_instruction <= '0';
      illegal_instruction <= '0';
      illegal_register    <= '0';
      illegal_register    <= '0';
      illegal_compressed  <= '0';
 
 
 
      -- check if using reg >= 16 for E-CPUs --
      -- check if using reg >= 16 for E-CPUs --
--if (CPU_EXTENSION_RISCV_E = true) then
--if (CPU_EXTENSION_RISCV_E = true) then
--  illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c);
      --  illegal_register <= ????? FIXME
--else
--else
--  illegal_register <= '0';
--  illegal_register <= '0';
--end if;
--end if;
 
 
      -- check instructions --
      -- check instructions --
Line 1053... Line 1029...
          end if;
          end if;
 
 
        when others => -- compressed instruction or undefined instruction
        when others => -- compressed instruction or undefined instruction
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          else -- compressed instruction: illegal or not implemented
 
            illegal_compressed <= ci_illegal;
 
          end if;
          end if;
 
 
      end case;
      end case;
    else
    else
      illegal_instruction <= '0';
      illegal_instruction <= '0';
      illegal_register    <= '0';
      illegal_register    <= '0';
      illegal_compressed  <= '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_register or illegal_compressed;
Line 1107... Line 1080...
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i)  and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c));
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i)  and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c));
 
 
        -- trap control --
        -- trap control --
        if (trap_ctrl.env_start = '0') then -- no started trap handler
        if (trap_ctrl.env_start = '0') then -- no started trap handler
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only -> continue execution even if permanent IRQ
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
            trap_ctrl.env_start <= '1';                   -- now we want to start the trap handler
            trap_ctrl.env_start <= '1';                   -- now execute engine can start trap handler
          end if;
          end if;
        else -- trap waiting to get started
        else -- trap waiting to get started
          if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
          if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
            trap_ctrl.exc_ack   <= '0';
            trap_ctrl.exc_ack   <= '0';
            trap_ctrl.irq_ack   <= (others => '0');
            trap_ctrl.irq_ack   <= (others => '0');
Line 1125... Line 1098...
      end if;
      end if;
    end if;
    end if;
  end process trap_controller;
  end process trap_controller;
 
 
  -- any exception/interrupt? --
  -- any exception/interrupt? --
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- exceptions/faults cannot be masked
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- interrupts can be masked
 
 
 
 
  -- Trap Priority Detector -----------------------------------------------------------------
  -- Trap Priority Detector -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  trap_priority: process(trap_ctrl)
  trap_priority: process(trap_ctrl)
Line 1278... Line 1251...
        else
        else
 
 
          -- machine exception PC & trap value register --
          -- machine exception PC & 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?
            csr.mcause <= trap_ctrl.cause(4) & "000" & x"000000" & trap_ctrl.cause(3 downto 0);
            csr.mcause <= trap_ctrl.cause(4) & "000" & x"000000" & trap_ctrl.cause(3 downto 0);
            if (trap_ctrl.cause(4) = '1') then -- for INTERRUPTS only
            if (trap_ctrl.cause(4) = '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(3 downto 0) = trap_iba_c(3 downto 0)) or -- instr access error OR
              if (trap_ctrl.cause(3 downto 0) = trap_iba_c(3 downto 0)) or -- instr access error OR

powered by: WebSVN 2.1.0

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