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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 45 and 47

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

Rev 45 Rev 47
Line 61... Line 61...
    CPU_EXTENSION_RISCV_Zifencei : boolean := true;  -- implement instruction stream sync.?
    CPU_EXTENSION_RISCV_Zifencei : boolean := true;  -- implement instruction stream sync.?
    -- Physical memory protection (PMP) --
    -- Physical memory protection (PMP) --
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
    PMP_MIN_GRANULARITY          : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    PMP_MIN_GRANULARITY          : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    -- Hardware Performance Monitors (HPM) --
    -- Hardware Performance Monitors (HPM) --
    HPM_NUM_CNTS                 : natural := 0      -- number of inmplemnted HPM counters (0..29)
    HPM_NUM_CNTS                 : natural := 0      -- number of implemented HPM counters (0..29)
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i         : in  std_ulogic; -- global clock, rising edge
    clk_i         : in  std_ulogic; -- global clock, rising edge
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
Line 87... Line 87...
    -- interrupts (risc-v compliant) --
    -- interrupts (risc-v compliant) --
    msw_irq_i     : in  std_ulogic; -- machine software interrupt
    msw_irq_i     : in  std_ulogic; -- machine software interrupt
    mext_irq_i    : in  std_ulogic; -- machine external interrupt
    mext_irq_i    : in  std_ulogic; -- machine external interrupt
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
    -- fast interrupts (custom) --
    -- fast interrupts (custom) --
    firq_i        : in  std_ulogic_vector(3 downto 0);
    firq_i        : in  std_ulogic_vector(7 downto 0);
 
    firq_ack_o    : out std_ulogic_vector(7 downto 0);
    -- 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
Line 211... Line 212...
  -- trap controller --
  -- trap controller --
  type trap_ctrl_t is record
  type trap_ctrl_t is record
    exc_buf       : std_ulogic_vector(exception_width_c-1 downto 0);
    exc_buf       : std_ulogic_vector(exception_width_c-1 downto 0);
    exc_fire      : std_ulogic; -- set if there is a valid source in the exception buffer
    exc_fire      : std_ulogic; -- set if there is a valid source in the exception buffer
    irq_buf       : std_ulogic_vector(interrupt_width_c-1 downto 0);
    irq_buf       : std_ulogic_vector(interrupt_width_c-1 downto 0);
 
    firq_sync     : std_ulogic_vector(7 downto 0);
    irq_fire      : std_ulogic; -- set if there is a valid source in the interrupt buffer
    irq_fire      : std_ulogic; -- set if there is a valid source in the interrupt buffer
    exc_ack       : std_ulogic; -- acknowledge all exceptions
    exc_ack       : std_ulogic; -- acknowledge all exceptions
    irq_ack       : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
    irq_ack       : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
    irq_ack_nxt   : std_ulogic_vector(interrupt_width_c-1 downto 0);
    irq_ack_nxt   : std_ulogic_vector(interrupt_width_c-1 downto 0);
    cause         : std_ulogic_vector(5 downto 0); -- trap ID for mcause CSR
    cause         : std_ulogic_vector(5 downto 0); -- trap ID for mcause CSR
Line 273... Line 275...
    mstatus_mpp       : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
    mstatus_mpp       : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
    --
    --
    mie_msie          : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
    mie_msie          : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
    mie_meie          : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
    mie_meie          : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
    mie_mtie          : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
    mie_mtie          : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
    mie_firqe         : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
    mie_firqe         : std_ulogic_vector(7 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
    --
    --
    mcounteren_cy     : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
    mcounteren_cy     : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
    mcounteren_tm     : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
    mcounteren_tm     : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
    mcounteren_ir     : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
    mcounteren_ir     : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
    mcounteren_hpm    : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounteren.hpmx: allow mhpmcounterx[h] access from user-mode
    mcounteren_hpm    : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounteren.hpmx: allow mhpmcounterx[h] access from user-mode
Line 640... Line 642...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  branch_check: process(execute_engine.i_reg, cmp_i)
  branch_check: process(execute_engine.i_reg, cmp_i)
  begin
  begin
    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_beq_c => -- branch if equal
      when funct3_beq_c => -- branch if equal
        execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c);
        execute_engine.branch_taken <= cmp_i(cmp_equal_c);
      when funct3_bne_c => -- branch if not equal
      when funct3_bne_c => -- branch if not equal
        execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c);
        execute_engine.branch_taken <= not cmp_i(cmp_equal_c);
      when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
      when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
        execute_engine.branch_taken <= cmp_i(alu_cmp_less_c);
        execute_engine.branch_taken <= cmp_i(cmp_less_c);
      when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
      when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
        execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c);
        execute_engine.branch_taken <= not cmp_i(cmp_less_c);
      when others => -- undefined
      when others => -- undefined
        execute_engine.branch_taken <= '0';
        execute_engine.branch_taken <= '0';
    end case;
    end case;
  end process branch_check;
  end process branch_check;
 
 
Line 729... Line 731...
    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_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);
    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) <= 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; -- instruction fetch bus access error 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; -- data access bus error access ACK
 
    -- memory access size / sign --
 
    ctrl_o(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
 
    ctrl_o(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
 
    -- alu.shifter --
 
    ctrl_o(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
 
    ctrl_o(ctrl_alu_shift_ar_c)  <= execute_engine.i_reg(30); -- is arithmetic shift
    -- instruction's function blocks (for co-processors) --
    -- instruction's function blocks (for co-processors) --
    ctrl_o(ctrl_ir_opcode7_6_c  downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c  downto instr_opcode_lsb_c);
    ctrl_o(ctrl_ir_opcode7_6_c  downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c  downto instr_opcode_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_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);
    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);
    -- locked bus operation (for atomica memory operations) --
    -- locked bus operation (for atomic memory operations) --
    ctrl_o(ctrl_bus_lock_c) <= atomic_ctrl.lock; -- (bus) lock status
    ctrl_o(ctrl_bus_lock_c) <= atomic_ctrl.lock; -- (bus) lock status
 
    -- cpu status --
 
    ctrl_o(ctrl_sleep_c) <= execute_engine.sleep; -- cpu is in sleep mode
  end process ctrl_output;
  end process ctrl_output;
 
 
 
 
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 839... Line 849...
    atomic_ctrl.env_end         <= '0';
    atomic_ctrl.env_end         <= '0';
    atomic_ctrl.env_abort       <= '0';
    atomic_ctrl.env_abort       <= '0';
 
 
    -- CONTROL DEFAULTS --
    -- CONTROL DEFAULTS --
    ctrl_nxt <= (others => '0'); -- default: all off
    ctrl_nxt <= (others => '0'); -- default: all off
 
    -- ALU main control --
 
    ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
 
    ctrl_nxt(ctrl_alu_func1_c  downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
 
    ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- default ALU arithmetic operation: ADDSUB
 
    -- ALU sign control --
    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;
    -- memory access --
 
    ctrl_nxt(ctrl_bus_unsigned_c)                            <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
 
    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
 
    -- alu.shifter --
 
    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
 
    -- ALU main control --
 
    ctrl_nxt(ctrl_alu_addsub_c)                         <= '0'; -- ADD(I)
 
    ctrl_nxt(ctrl_alu_func1_c  downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
 
    ctrl_nxt(ctrl_alu_arith_c)                          <= alu_arith_cmd_addsub_c; -- default ALU arithmetic operation: ADDSUB
 
 
 
 
 
    -- state machine --
    -- state machine --
    case execute_engine.state is
    case execute_engine.state is
 
 
Line 1125... Line 1130...
 
 
 
 
      when FENCE_OP => -- fence operations - execution
      when FENCE_OP => -- fence operations - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.state_nxt  <= SYS_WAIT;
        execute_engine.state_nxt  <= SYS_WAIT;
        execute_engine.pc_mux_sel <= "01"; -- linear next PC = "refetch" next instruction (only relevant for fence.i)
 
        -- FENCE.I --
        -- FENCE.I --
        if (CPU_EXTENSION_RISCV_Zifencei = true) and (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
        if (CPU_EXTENSION_RISCV_Zifencei = true) then
 
          execute_engine.pc_mux_sel <= "01"; -- linear next PC = start *new* instruction fetch with next instruction (only relevant for fence.i)
 
          if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
          execute_engine.pc_we        <= '1';
          execute_engine.pc_we        <= '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
          fetch_engine.reset          <= '1';
          fetch_engine.reset          <= '1';
          ctrl_nxt(ctrl_bus_fencei_c) <= '1';
          ctrl_nxt(ctrl_bus_fencei_c) <= '1';
        end if;
        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;
 
 
Line 1572... Line 1579...
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      trap_ctrl.exc_buf   <= (others => '0');
      trap_ctrl.exc_buf   <= (others => '0');
      trap_ctrl.irq_buf   <= (others => '0');
      trap_ctrl.irq_buf   <= (others => '0');
      trap_ctrl.exc_ack   <= '0';
      trap_ctrl.exc_ack   <= '0';
      trap_ctrl.irq_ack   <= (others => '0');
      trap_ctrl.irq_ack   <= (others => '0');
      trap_ctrl.cause     <= trap_reset_c;
 
      trap_ctrl.env_start <= '0';
      trap_ctrl.env_start <= '0';
 
      trap_ctrl.cause     <= trap_reset_c;
 
      trap_ctrl.firq_sync <= (others => '0');
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
        -- exception buffer: misaligned load/store/instruction address
        -- exception buffer: misaligned load/store/instruction address
        trap_ctrl.exc_buf(exception_lalign_c)    <= (trap_ctrl.exc_buf(exception_lalign_c)    or ma_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_lalign_c)    <= (trap_ctrl.exc_buf(exception_lalign_c)    or ma_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_salign_c)    <= (trap_ctrl.exc_buf(exception_salign_c)    or ma_store_i)         and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_salign_c)    <= (trap_ctrl.exc_buf(exception_salign_c)    or ma_store_i)         and (not trap_ctrl.exc_ack);
Line 1594... Line 1602...
        -- interrupt buffer: machine software/external/timer interrupt
        -- interrupt buffer: machine software/external/timer interrupt
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c)   or msw_irq_i)   and (not (trap_ctrl.irq_ack(interrupt_msw_irq_c)   or csr.mip_clear(interrupt_msw_irq_c)));
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c)   or msw_irq_i)   and (not (trap_ctrl.irq_ack(interrupt_msw_irq_c)   or csr.mip_clear(interrupt_msw_irq_c)));
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or mext_irq_i)  and (not (trap_ctrl.irq_ack(interrupt_mext_irq_c)  or csr.mip_clear(interrupt_mext_irq_c)));
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or mext_irq_i)  and (not (trap_ctrl.irq_ack(interrupt_mext_irq_c)  or csr.mip_clear(interrupt_mext_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) or csr.mip_clear(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) or csr.mip_clear(interrupt_mtime_irq_c)));
        -- interrupt buffer: custom fast interrupts
        -- interrupt buffer: custom fast interrupts
        trap_ctrl.irq_buf(interrupt_firq_0_c)    <= csr.mie_firqe(0) and (trap_ctrl.irq_buf(interrupt_firq_0_c) or firq_i(0)) and (not (trap_ctrl.irq_ack(interrupt_firq_0_c) or csr.mip_clear(interrupt_firq_0_c)));
        trap_ctrl.firq_sync <= firq_i;
        trap_ctrl.irq_buf(interrupt_firq_1_c)    <= csr.mie_firqe(1) and (trap_ctrl.irq_buf(interrupt_firq_1_c) or firq_i(1)) and (not (trap_ctrl.irq_ack(interrupt_firq_1_c) or csr.mip_clear(interrupt_firq_1_c)));
        --
        trap_ctrl.irq_buf(interrupt_firq_2_c)    <= csr.mie_firqe(2) and (trap_ctrl.irq_buf(interrupt_firq_2_c) or firq_i(2)) and (not (trap_ctrl.irq_ack(interrupt_firq_2_c) or csr.mip_clear(interrupt_firq_2_c)));
        trap_ctrl.irq_buf(interrupt_firq_0_c)    <= csr.mie_firqe(0) and (trap_ctrl.irq_buf(interrupt_firq_0_c) or trap_ctrl.firq_sync(0)) and (not (trap_ctrl.irq_ack(interrupt_firq_0_c) or csr.mip_clear(interrupt_firq_0_c)));
        trap_ctrl.irq_buf(interrupt_firq_3_c)    <= csr.mie_firqe(3) and (trap_ctrl.irq_buf(interrupt_firq_3_c) or firq_i(3)) and (not (trap_ctrl.irq_ack(interrupt_firq_3_c) or csr.mip_clear(interrupt_firq_3_c)));
        trap_ctrl.irq_buf(interrupt_firq_1_c)    <= csr.mie_firqe(1) and (trap_ctrl.irq_buf(interrupt_firq_1_c) or trap_ctrl.firq_sync(1)) and (not (trap_ctrl.irq_ack(interrupt_firq_1_c) or csr.mip_clear(interrupt_firq_1_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_2_c)    <= csr.mie_firqe(2) and (trap_ctrl.irq_buf(interrupt_firq_2_c) or trap_ctrl.firq_sync(2)) and (not (trap_ctrl.irq_ack(interrupt_firq_2_c) or csr.mip_clear(interrupt_firq_2_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_3_c)    <= csr.mie_firqe(3) and (trap_ctrl.irq_buf(interrupt_firq_3_c) or trap_ctrl.firq_sync(3)) and (not (trap_ctrl.irq_ack(interrupt_firq_3_c) or csr.mip_clear(interrupt_firq_3_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_4_c)    <= csr.mie_firqe(4) and (trap_ctrl.irq_buf(interrupt_firq_4_c) or trap_ctrl.firq_sync(4)) and (not (trap_ctrl.irq_ack(interrupt_firq_4_c) or csr.mip_clear(interrupt_firq_4_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_5_c)    <= csr.mie_firqe(5) and (trap_ctrl.irq_buf(interrupt_firq_5_c) or trap_ctrl.firq_sync(5)) and (not (trap_ctrl.irq_ack(interrupt_firq_5_c) or csr.mip_clear(interrupt_firq_5_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_6_c)    <= csr.mie_firqe(6) and (trap_ctrl.irq_buf(interrupt_firq_6_c) or trap_ctrl.firq_sync(6)) and (not (trap_ctrl.irq_ack(interrupt_firq_6_c) or csr.mip_clear(interrupt_firq_6_c)));
 
        trap_ctrl.irq_buf(interrupt_firq_7_c)    <= csr.mie_firqe(7) and (trap_ctrl.irq_buf(interrupt_firq_7_c) or trap_ctrl.firq_sync(7)) and (not (trap_ctrl.irq_ack(interrupt_firq_7_c) or csr.mip_clear(interrupt_firq_7_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 to continue execution even if permanent IRQ
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only to continue execution even if permanent IRQ
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
Line 1625... Line 1639...
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- interrupts CAN be masked
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- interrupts CAN be masked
 
 
  -- current pending interrupts (for CSR.MIP register) --
  -- current pending interrupts (for CSR.MIP register) --
  csr.mip_status <= trap_ctrl.irq_buf;
  csr.mip_status <= trap_ctrl.irq_buf;
 
 
 
  -- acknowledge mask output --
 
  firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_7_c downto interrupt_firq_0_c);
 
 
 
 
  -- Trap Priority Encoder ------------------------------------------------------------------
  -- Trap Priority Encoder ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  trap_priority: process(trap_ctrl)
  trap_priority: process(trap_ctrl)
  begin
  begin
Line 1673... Line 1690...
    -- interrupt: 1.19 fast interrupt channel 3 --
    -- interrupt: 1.19 fast interrupt channel 3 --
    elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
    elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
      trap_ctrl.cause_nxt <= trap_firq3_c;
      trap_ctrl.cause_nxt <= trap_firq3_c;
      trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
      trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
 
 
 
    -- interrupt: 1.20 fast interrupt channel 4 --
 
    elsif (trap_ctrl.irq_buf(interrupt_firq_4_c) = '1') then
 
      trap_ctrl.cause_nxt <= trap_firq4_c;
 
      trap_ctrl.irq_ack_nxt(interrupt_firq_4_c) <= '1';
 
 
 
    -- interrupt: 1.21 fast interrupt channel 5 --
 
    elsif (trap_ctrl.irq_buf(interrupt_firq_5_c) = '1') then
 
      trap_ctrl.cause_nxt <= trap_firq5_c;
 
      trap_ctrl.irq_ack_nxt(interrupt_firq_5_c) <= '1';
 
 
 
    -- interrupt: 1.22 fast interrupt channel 6 --
 
    elsif (trap_ctrl.irq_buf(interrupt_firq_6_c) = '1') then
 
      trap_ctrl.cause_nxt <= trap_firq6_c;
 
      trap_ctrl.irq_ack_nxt(interrupt_firq_6_c) <= '1';
 
 
 
    -- interrupt: 1.23 fast interrupt channel 7 --
 
    elsif (trap_ctrl.irq_buf(interrupt_firq_7_c) = '1') then
 
      trap_ctrl.cause_nxt <= trap_firq7_c;
 
      trap_ctrl.irq_ack_nxt(interrupt_firq_7_c) <= '1';
 
 
 
 
    -- the following traps are caused by *synchronous* exceptions (= 'classic' exceptions)
    -- the following traps are caused by *synchronous* exceptions (= 'classic' exceptions)
    -- here we do not need a specific acknowledge mask since only one exception (the one
    -- here we do not need a specific acknowledge mask since only one exception (the one
    -- with highest priority) is evaluated at once
    -- with highest priority) is evaluated at once
 
 
Line 1852... Line 1889...
              --
              --
              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
 
              csr.mie_firqe(4) <= csr.wdata(20); -- fast interrupt channel 4
 
              csr.mie_firqe(5) <= csr.wdata(21); -- fast interrupt channel 5
 
              csr.mie_firqe(6) <= csr.wdata(22); -- fast interrupt channel 6
 
              csr.mie_firqe(7) <= csr.wdata(22); -- fast interrupt channel 7
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
            when csr_mcounteren_c => -- R/W: machine counter enable register
            when csr_mcounteren_c => -- R/W: machine counter enable register
              csr.mcounteren_cy  <= csr.wdata(0); -- enable user-level access to cycle[h]
              csr.mcounteren_cy  <= csr.wdata(0); -- enable user-level access to cycle[h]
              csr.mcounteren_tm  <= csr.wdata(1); -- enable user-level access to time[h]
              csr.mcounteren_tm  <= csr.wdata(1); -- enable user-level access to time[h]
Line 1881... Line 1922...
              --
              --
              csr.mip_clear(interrupt_firq_0_c) <= not csr.wdata(16);
              csr.mip_clear(interrupt_firq_0_c) <= not csr.wdata(16);
              csr.mip_clear(interrupt_firq_1_c) <= not csr.wdata(17);
              csr.mip_clear(interrupt_firq_1_c) <= not csr.wdata(17);
              csr.mip_clear(interrupt_firq_2_c) <= not csr.wdata(18);
              csr.mip_clear(interrupt_firq_2_c) <= not csr.wdata(18);
              csr.mip_clear(interrupt_firq_3_c) <= not csr.wdata(19);
              csr.mip_clear(interrupt_firq_3_c) <= not csr.wdata(19);
 
              csr.mip_clear(interrupt_firq_4_c) <= not csr.wdata(20);
 
              csr.mip_clear(interrupt_firq_5_c) <= not csr.wdata(21);
 
              csr.mip_clear(interrupt_firq_6_c) <= not csr.wdata(22);
 
              csr.mip_clear(interrupt_firq_7_c) <= not csr.wdata(23);
 
 
            -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
            -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c  | csr_pmpcfg3_c  | csr_pmpcfg4_c  | csr_pmpcfg5_c  | csr_pmpcfg6_c  | csr_pmpcfg7_c |
            when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c  | csr_pmpcfg3_c  | csr_pmpcfg4_c  | csr_pmpcfg5_c  | csr_pmpcfg6_c  | csr_pmpcfg7_c |
                 csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
                 csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
Line 1936... Line 1981...
                 csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
                 csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
                 csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
                 csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
              for i in 0 to HPM_NUM_CNTS-1 loop
              for i in 0 to HPM_NUM_CNTS-1 loop
                if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
                if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
                  csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
                  csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
 
                  csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
                end if;
                end if;
              end loop; -- i (CSRs)
              end loop; -- i (CSRs)
 
 
            -- undefined --
            -- undefined --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
Line 1974... Line 2020...
                csr.mtval <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
                csr.mtval <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
              when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
              when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
                csr.mtval <= mar_i; -- faulting data access address
                csr.mtval <= mar_i; -- faulting data access address
              when trap_iil_c => -- illegal instruction
              when trap_iil_c => -- illegal instruction
                csr.mtval <= execute_engine.i_reg_last; -- faulting instruction itself
                csr.mtval <= execute_engine.i_reg_last; -- faulting instruction itself
              when others => -- everything else including interrupts
              when others => -- everything else including all interrupts
                csr.mtval <= (others => '0');
                csr.mtval <= (others => '0');
            end case;
            end case;
          end if;
          end if;
 
 
          -- mstatus: context switch --
          -- mstatus: context switch --
Line 2119... Line 2165...
  -- (HPM) Counter Event Control ------------------------------------------------------------
  -- (HPM) Counter Event Control ------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  hpmcnt_ctrl: process(clk_i)
  hpmcnt_ctrl: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
 
      -- buffer event sources --
      cnt_event      <= cnt_event_nxt;
      cnt_event      <= cnt_event_nxt;
 
      -- enable selected triggers by ANDing actual events and according CSR configuration bits --
 
      -- OR everything to see if counter should increment --
      hpmcnt_trigger <= (others => '0'); -- default
      hpmcnt_trigger <= (others => '0'); -- default
      for i in 0 to HPM_NUM_CNTS-1 loop
      for i in 0 to HPM_NUM_CNTS-1 loop
        -- enable selected triggers by ANDing events and configuration bits --
        hpmcnt_trigger(i) <= or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
        -- OR everything to see if counter should increment --
 
        -- AND with inverted sleep flag to increment only when CPU is awake --
 
        hpmcnt_trigger(i) <= (or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0))) and (not execute_engine.sleep);
 
      end loop; -- i
      end loop; -- i
    end if;
    end if;
  end process hpmcnt_ctrl;
  end process hpmcnt_ctrl;
 
 
  -- counter event trigger - RISC-V specific --
  -- counter event trigger - RISC-V specific --
Line 2192... Line 2238...
            --
            --
            csr.rdata(16) <= csr.mie_firqe(0); -- fast interrupt channel 0
            csr.rdata(16) <= csr.mie_firqe(0); -- fast interrupt channel 0
            csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
            csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
            csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
            csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
            csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
            csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
 
            csr.rdata(20) <= csr.mie_firqe(4); -- fast interrupt channel 4
 
            csr.rdata(21) <= csr.mie_firqe(5); -- fast interrupt channel 5
 
            csr.rdata(22) <= csr.mie_firqe(6); -- fast interrupt channel 6
 
            csr.rdata(23) <= csr.mie_firqe(7); -- fast interrupt channel 7
          when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
          when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
            csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
            csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
          when csr_mcounteren_c => -- R/W: machine counter enable register
          when csr_mcounteren_c => -- R/W: machine counter enable register
            csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
            csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
            csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
            csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
Line 2218... Line 2268...
            --
            --
            csr.rdata(16) <= csr.mip_status(interrupt_firq_0_c);
            csr.rdata(16) <= csr.mip_status(interrupt_firq_0_c);
            csr.rdata(17) <= csr.mip_status(interrupt_firq_1_c);
            csr.rdata(17) <= csr.mip_status(interrupt_firq_1_c);
            csr.rdata(18) <= csr.mip_status(interrupt_firq_2_c);
            csr.rdata(18) <= csr.mip_status(interrupt_firq_2_c);
            csr.rdata(19) <= csr.mip_status(interrupt_firq_3_c);
            csr.rdata(19) <= csr.mip_status(interrupt_firq_3_c);
 
            csr.rdata(20) <= csr.mip_status(interrupt_firq_4_c);
 
            csr.rdata(21) <= csr.mip_status(interrupt_firq_5_c);
 
            csr.rdata(22) <= csr.mip_status(interrupt_firq_6_c);
 
            csr.rdata(23) <= csr.mip_status(interrupt_firq_7_c);
 
 
          -- physical memory protection - configuration --
          -- physical memory protection - configuration --
          when csr_pmpcfg0_c  => csr.rdata <= csr.pmpcfg_rd(03) & csr.pmpcfg_rd(02) & csr.pmpcfg_rd(01) & csr.pmpcfg_rd(00); -- R/W: pmpcfg0
          when csr_pmpcfg0_c  => csr.rdata <= csr.pmpcfg_rd(03) & csr.pmpcfg_rd(02) & csr.pmpcfg_rd(01) & csr.pmpcfg_rd(00); -- R/W: pmpcfg0
          when csr_pmpcfg1_c  => csr.rdata <= csr.pmpcfg_rd(07) & csr.pmpcfg_rd(06) & csr.pmpcfg_rd(05) & csr.pmpcfg_rd(04); -- R/W: pmpcfg1
          when csr_pmpcfg1_c  => csr.rdata <= csr.pmpcfg_rd(07) & csr.pmpcfg_rd(06) & csr.pmpcfg_rd(05) & csr.pmpcfg_rd(04); -- R/W: pmpcfg1
          when csr_pmpcfg2_c  => csr.rdata <= csr.pmpcfg_rd(11) & csr.pmpcfg_rd(10) & csr.pmpcfg_rd(09) & csr.pmpcfg_rd(08); -- R/W: pmpcfg2
          when csr_pmpcfg2_c  => csr.rdata <= csr.pmpcfg_rd(11) & csr.pmpcfg_rd(10) & csr.pmpcfg_rd(09) & csr.pmpcfg_rd(08); -- R/W: pmpcfg2

powered by: WebSVN 2.1.0

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