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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 19 and 20

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

Rev 19 Rev 20
Line 117... Line 117...
    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_input        : std_ulogic_vector(15 downto 0); -- input to compressed instr. decoder
    ci_input        : std_ulogic_vector(15 downto 0); -- input to compressed instr. decoder
    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              : std_ulogic_vector(data_width_c-1 downto 0);
    pc_real_add     : std_ulogic_vector(data_width_c-1 downto 0);
    pc_add          : 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);
 
    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;
 
 
  -- pre-decoder --
  -- pre-decoder --
  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_dbuf_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(35 downto 0);
  type ipb_t is record
  type ipb_t is record
    wdata  : std_ulogic_vector(35 downto 0);
    wdata  : std_ulogic_vector(35 downto 0); -- data (+ status) to be written
    rdata  : std_ulogic_vector(35 downto 0);
    we     : std_ulogic; -- trigger write
    waddr  : std_ulogic_vector(31 downto 0);
    free   : std_ulogic; -- free entry available?
    raddr  : std_ulogic_vector(31 downto 0);
    --
    status : std_ulogic;
    rdata  : std_ulogic_vector(35 downto 0); -- read data (+ status)
    free   : std_ulogic;
    re     : std_ulogic; -- trigger read
    avail  : std_ulogic;
    avail  : std_ulogic; -- data available?
    we     : std_ulogic;
    --
    re     : std_ulogic;
    clear  : std_ulogic; -- clear all entries
    clear  : std_ulogic;
    --
 
    data   : ipb_dbuf_t; -- the data fifo
 
    w_pnt  : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
 
    r_pnt  : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
 
    empty  : std_ulogic;
 
    full   : std_ulogic;
  end record;
  end record;
  signal ipb : ipb_t;
  signal ipb : ipb_t;
 
 
  -- instruction execution engine --
  -- instruction execution engine --
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, CSR_ACCESS);
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, CSR_ACCESS);
Line 164... Line 168...
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
    sleep        : std_ulogic; -- CPU in sleep mode
    sleep        : std_ulogic; -- CPU in sleep mode
    sleep_nxt    : std_ulogic; -- CPU in sleep mode
    sleep_nxt    : std_ulogic; -- CPU in sleep mode
 
    if_rst       : std_ulogic; -- instruction fetch was reset
 
    if_rst_nxt   : std_ulogic; -- instruction fetch was reset
  end record;
  end record;
  signal execute_engine : execute_engine_t;
  signal execute_engine : execute_engine_t;
 
 
  signal next_pc_tmp : std_ulogic_vector(data_width_c-1 downto 0);
  signal next_pc_tmp : std_ulogic_vector(data_width_c-1 downto 0);
 
 
Line 290... Line 296...
  -- for registers that DO NOT require a specific reset state --
  -- for registers that DO NOT require a specific reset state --
  fetch_engine_fsm_sync: process(clk_i)
  fetch_engine_fsm_sync: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      if (fetch_engine.state = IFETCH_RESET) then
      if (fetch_engine.state = IFETCH_RESET) then
        fetch_engine.pc_fetch  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
        fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
        fetch_engine.pc_real   <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
 
      else
      else
        fetch_engine.pc_real   <= std_ulogic_vector(unsigned(fetch_engine.pc_real(data_width_c-1 downto 1) & '0')  + unsigned(fetch_engine.pc_real_add(data_width_c-1 downto 1) & '0'));
        fetch_engine.pc <= std_ulogic_vector(unsigned(fetch_engine.pc(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_add(data_width_c-1 downto 1) & '0'));
        fetch_engine.pc_fetch  <= std_ulogic_vector(unsigned(fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_fetch_add(data_width_c-1 downto 1) & '0'));
 
      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;
    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(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, ci_illegal, 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';
    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_add          <= (others => '0');
    fetch_engine.pc_real_add     <= (others => '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_input        <= fetch_engine.i_buf2(15 downto 00);
    fetch_engine.ci_input        <= fetch_engine.i_buf2(15 downto 00);
    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 <= (others => '0');
    ipb.wdata <= (others => '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
Line 352... Line 354...
          fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state(0) & '1';
          fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state(0) & '1';
          fetch_engine.bus_err_ack     <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them
          fetch_engine.bus_err_ack     <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them
          if (fetch_engine.i_buf_state(0) = '1') then -- buffer filled?
          if (fetch_engine.i_buf_state(0) = '1') then -- buffer filled?
            fetch_engine.state_nxt <= IFETCH_2;
            fetch_engine.state_nxt <= IFETCH_2;
          else
          else
            fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
            fetch_engine.pc_add    <= std_ulogic_vector(to_unsigned(4, data_width_c));
            fetch_engine.state_nxt    <= IFETCH_0; -- get another instruction word
            fetch_engine.state_nxt    <= IFETCH_0; -- get another instruction word
          end if;
          end if;
        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(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
          fetch_engine.ci_input <= fetch_engine.i_buf2(15 downto 00);
          fetch_engine.ci_input <= fetch_engine.i_buf2(15 downto 00);
 
 
          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
            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);
              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_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;
            else -- compressed
            else -- compressed
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf2(33 downto 32) & '1' & ci_instr32;
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf2(33 downto 32) & '1' & ci_instr32;
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.pc_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
              fetch_engine.state_nxt    <= IFETCH_2; -- try to get another 16-bit instruction word in next round
            end if;
            end if;
          end if;
          end if;
 
 
        else -- 16-bit aligned
        else -- 16-bit aligned
Line 384... Line 384...
 
 
          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
            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);
              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_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;
            else -- compressed
            else -- compressed
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.pc_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_0;
              fetch_engine.state_nxt    <= IFETCH_0;
            end if;
            end if;
          end if;
          end if;
       end if;
       end if;
 
 
Line 409... Line 407...
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Instruction Prefetch Buffer
-- Instruction Prefetch Buffer
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
 
 
  -- Instruction Prefetch Buffer Stage ------------------------------------------------------
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  instr_prefetch_buffer: process(rstn_i, clk_i) -- once upon a time, this was a fifo with 8 entries
  instr_prefetch_buffer_ctrl: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      ipb.status <= '0';
      ipb.w_pnt <= (others => '0');
      ipb.rdata  <= (others => '0');
      ipb.r_pnt <= (others => '0');
      ipb.raddr  <= (others => '0');
 
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
 
      -- write port --
      if (ipb.clear = '1') then
      if (ipb.clear = '1') then
        ipb.status <= '0';
        ipb.w_pnt <= (others => '0');
      elsif (ipb.we = '1') then
      elsif (ipb.we = '1') then
        ipb.status <= '1';
        ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
 
      end if;
 
      -- read port --
 
      if (ipb.clear = '1') then
 
        ipb.r_pnt <= (others => '0');
      elsif (ipb.re = '1') then
      elsif (ipb.re = '1') then
        ipb.status <= '0';
        ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1);
      end if;
      end if;
      if (ipb.we = '1') then
 
        ipb.rdata <= ipb.wdata;
 
        ipb.raddr <= ipb.waddr;
 
      end if;
      end if;
 
  end process instr_prefetch_buffer_ctrl;
 
 
 
  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;
    end if;
 
  end process instr_prefetch_buffer_data;
 
 
 
  -- async read --
 
  ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.w_pnt'left-1 downto 0))));
 
 
  -- status --
  -- status --
  ipb.free  <= not ipb.status;
  ipb.full  <= '1' when (ipb.r_pnt(ipb.r_pnt'left) /= ipb.w_pnt(ipb.w_pnt'left)) and (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0)) else '0';
  ipb.avail <= ipb.status;
  ipb.empty <= '1' when (ipb.r_pnt(ipb.r_pnt'left)  = ipb.w_pnt(ipb.w_pnt'left)) and (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0)) else '0';
 
 
 
  ipb.free  <= not ipb.full;
 
  ipb.avail <= not ipb.empty;
 
 
 
 
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Instruction Execution
-- Instruction Execution
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
Line 512... Line 525...
    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';
 
      execute_engine.if_rst  <= '1'; -- IF is reset after system reset
    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;
 
      execute_engine.if_rst <= execute_engine.if_rst_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync_rst;
  end process execute_engine_fsm_sync_rst;
 
 
 
 
  -- for registers that do NOT require a specific reset state --
  -- for registers that do NOT require a specific reset state --
Line 536... Line 551...
      --
      --
      ctrl <= ctrl_nxt;
      ctrl <= ctrl_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync;
  end process execute_engine_fsm_sync;
 
 
  -- PC output --
  -- next PC --
  curr_pc_o              <= execute_engine.pc(data_width_c-1 downto 1) & '0';
 
  next_pc_tmp            <= std_ulogic_vector(unsigned(execute_engine.pc) + 2) when (execute_engine.is_ci = '1') else std_ulogic_vector(unsigned(execute_engine.pc) + 4);
  next_pc_tmp            <= std_ulogic_vector(unsigned(execute_engine.pc) + 2) when (execute_engine.is_ci = '1') else std_ulogic_vector(unsigned(execute_engine.pc) + 4);
  execute_engine.next_pc <= next_pc_tmp(data_width_c-1 downto 1) & '0';
  execute_engine.next_pc <= next_pc_tmp(data_width_c-1 downto 1) & '0';
 
 
 
  -- PC output --
 
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0';
  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 -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 575... Line 592...
    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;
    execute_engine.pc_nxt      <= execute_engine.pc;
    execute_engine.sleep_nxt   <= execute_engine.sleep;
    execute_engine.sleep_nxt   <= execute_engine.sleep;
 
    execute_engine.if_rst_nxt  <= execute_engine.if_rst;
 
 
    -- instruction dispatch --
    -- instruction dispatch --
    fetch_engine.reset         <= '0';
    fetch_engine.reset         <= '0';
    ipb.re                     <= '0';
    ipb.re                     <= '0';
 
 
Line 652... Line 670...
       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); -- misaligned instruction fetch address
          trap_ctrl.instr_ma <= ipb.rdata(33); -- misaligned instruction fetch address
          trap_ctrl.instr_be <= ipb.rdata(34); -- bus access fault druing instrucion fetch
          trap_ctrl.instr_be <= ipb.rdata(34); -- bus access fault during instrucion fetch
          illegal_compressed <= ipb.rdata(35); -- invalid decompressed instruction
          illegal_compressed <= ipb.rdata(35); -- invalid decompressed instruction
          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; -- the PC according to the current instruction
execute_engine.if_rst_nxt <= '0';
          -- ipb.rdata(35) is not immediately checked here!
if (execute_engine.if_rst = '0') then -- if there was no non-linear PC modification
 
  execute_engine.pc_nxt <= execute_engine.next_pc;
 
end if;
 
          -- ipb.rdata(35) (invalid decompressed instruction) is not immediately checked here!
          if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or ((ipb.rdata(33) or ipb.rdata(34)) = '1') then
          if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or ((ipb.rdata(33) or ipb.rdata(34)) = '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;
        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';
 
        execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
        if (trap_ctrl.env_start = '1') then -- check here again if we came directly from DISPATCH
        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.pc_nxt    <= csr.mtvec;
          execute_engine.sleep_nxt <= '0'; -- waky waky
          execute_engine.sleep_nxt <= '0'; -- waky waky
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= SYS_WAIT;
Line 749... Line 771...
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
            execute_engine.state_nxt   <= BRANCH;
            execute_engine.state_nxt   <= BRANCH;
 
 
          when opcode_fence_c => -- fence operations
          when opcode_fence_c => -- fence operations
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.pc_nxt <= execute_engine.next_pc; -- "refetch" next instruction (only relevant for fencei)
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCEI
 
              fetch_engine.reset          <= '1';
              fetch_engine.reset          <= '1';
 
              execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
 
              execute_engine.pc_nxt       <= execute_engine.next_pc; -- "refetch" next instruction (only relevant for fence.i)
              ctrl_nxt(ctrl_bus_fencei_c) <= '1';
              ctrl_nxt(ctrl_bus_fencei_c) <= '1';
            end if;
            end if;
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
            end if;
            end if;
Line 772... Line 795...
                  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;
                  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
                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;
Line 854... Line 878...
          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; -- 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.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 1389... Line 1414...
              end if;
              end if;
              -- pmpaddr --
              -- pmpaddr --
              if (execute_engine.i_reg(27 downto 24) = x"b") then
              if (execute_engine.i_reg(27 downto 24) = x"b") 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_i;
                    csr.pmpaddr(i) <= csr_wdata_i(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; -- implement PMP at all?
          end if;
          end if;

powered by: WebSVN 2.1.0

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