-- #################################################################################################
-- # << NEORV32 - Main VHDL Package File (CPU and SoC) >>                                          #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License                                                                          #
-- #                                                                                               #
-- # Copyright (c) 2024, Stephan Nolting. All rights reserved.                                     #
-- #                                                                                               #
-- # Redistribution and use in source and binary forms, with or without modification, are          #
-- # permitted provided that the following conditions are met:                                     #
-- #                                                                                               #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
-- #    conditions and the following disclaimer.                                                   #
-- #                                                                                               #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
-- #    provided with the distribution.                                                            #
-- #                                                                                               #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
-- #    endorse or promote products derived from this software without specific prior written      #
-- #    permission.                                                                                #
-- #                                                                                               #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
-- # ********************************************************************************************* #
-- # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32       (c) Stephan Nolting #
-- #################################################################################################

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package neorv32_package is

-- ****************************************************************************************************************************
-- Architecture Configuration and Constants
-- ****************************************************************************************************************************

  -- Architecture Configuration -------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- max response time for processor-internal bus transactions --
  -- cycles after which an unacknowledged internal bus access will timeout raising a bus fault exception
  constant bus_timeout_c : natural := 15; -- default = 15

  -- instruction monitor: raise exception if multi-cycle operation times out --
  constant monitor_mc_tmo_c : natural := 9; -- = log2 of max execution cycles; default = 2^9 = 512 cycles

  -- Architecture Constants -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090508"; -- hardware version
  constant archid_c     : natural := 19; -- official RISC-V architecture ID
  constant XLEN         : natural := 32; -- native data path width

  -- Check if we're inside the Matrix -------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant is_simulation_c : boolean := false -- seems like we're on real hardware
-- pragma translate_off
-- synthesis translate_off
-- RTL_SYNTHESIS OFF
  or true -- this MIGHT be a simulation
-- RTL_SYNTHESIS ON
-- synthesis translate_on
-- pragma translate_on
  ;

-- ****************************************************************************************************************************
-- Processor Address Space Layout
-- ****************************************************************************************************************************

  -- Main Address Regions ---
  constant mem_imem_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- IMEM size via generic
  constant mem_dmem_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- DMEM size via generic
  constant mem_xip_base_c  : std_ulogic_vector(31 downto 0) := x"e0000000"; -- page (4MSBs) only!
  constant mem_xip_size_c  : natural := 256*1024*1024;
  constant mem_boot_base_c : std_ulogic_vector(31 downto 0) := x"ffffc000";
  constant mem_boot_size_c : natural := 8*1024;
  constant mem_io_base_c   : std_ulogic_vector(31 downto 0) := x"ffffe000";
  constant mem_io_size_c   : natural := 8*1024;

  -- Start of uncached memory access (256MB page / 4MSBs only) --
  constant uncached_begin_c  : std_ulogic_vector(31 downto 0) := x"f0000000";

  -- IO Address Map --
  constant iodev_size_c      : natural := 256; -- size of a single IO device (bytes)
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe000"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe100"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe200"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe300"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe400"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe500"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe600"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe700"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe800"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffe900"; -- reserved
--constant base_io_???_c     : std_ulogic_vector(31 downto 0) := x"ffffea00"; -- reserved
  constant base_io_cfs_c     : std_ulogic_vector(31 downto 0) := x"ffffeb00";
  constant base_io_slink_c   : std_ulogic_vector(31 downto 0) := x"ffffec00";
  constant base_io_dma_c     : std_ulogic_vector(31 downto 0) := x"ffffed00";
  constant base_io_crc_c     : std_ulogic_vector(31 downto 0) := x"ffffee00";
  constant base_io_xip_c     : std_ulogic_vector(31 downto 0) := x"ffffef00";
  constant base_io_pwm_c     : std_ulogic_vector(31 downto 0) := x"fffff000";
  constant base_io_gptmr_c   : std_ulogic_vector(31 downto 0) := x"fffff100";
  constant base_io_onewire_c : std_ulogic_vector(31 downto 0) := x"fffff200";
  constant base_io_xirq_c    : std_ulogic_vector(31 downto 0) := x"fffff300";
  constant base_io_mtime_c   : std_ulogic_vector(31 downto 0) := x"fffff400";
  constant base_io_uart0_c   : std_ulogic_vector(31 downto 0) := x"fffff500";
  constant base_io_uart1_c   : std_ulogic_vector(31 downto 0) := x"fffff600";
  constant base_io_sdi_c     : std_ulogic_vector(31 downto 0) := x"fffff700";
  constant base_io_spi_c     : std_ulogic_vector(31 downto 0) := x"fffff800";
  constant base_io_twi_c     : std_ulogic_vector(31 downto 0) := x"fffff900";
  constant base_io_trng_c    : std_ulogic_vector(31 downto 0) := x"fffffa00";
  constant base_io_wdt_c     : std_ulogic_vector(31 downto 0) := x"fffffb00";
  constant base_io_gpio_c    : std_ulogic_vector(31 downto 0) := x"fffffc00";
  constant base_io_neoled_c  : std_ulogic_vector(31 downto 0) := x"fffffd00";
  constant base_io_sysinfo_c : std_ulogic_vector(31 downto 0) := x"fffffe00";
  constant base_io_dm_c      : std_ulogic_vector(31 downto 0) := x"ffffff00";

  -- On-Chip Debugger - Debug Module Entry Points (Code ROM) --
  constant dm_exc_entry_c  : std_ulogic_vector(31 downto 0) := x"ffffff00"; -- = base_io_dm_c + 0, exceptions entry point
  constant dm_park_entry_c : std_ulogic_vector(31 downto 0) := x"ffffff08"; -- = base_io_dm_c + 8, normal entry point

-- ****************************************************************************************************************************
-- SoC Definitions
-- ****************************************************************************************************************************

  -- SoC Clock Select -----------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant clk_div2_c    : natural := 0;
  constant clk_div4_c    : natural := 1;
  constant clk_div8_c    : natural := 2;
  constant clk_div64_c   : natural := 3;
  constant clk_div128_c  : natural := 4;
  constant clk_div1024_c : natural := 5;
  constant clk_div2048_c : natural := 6;
  constant clk_div4096_c : natural := 7;

  -- Internal Memory Types ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  type mem32_t is array (natural range <>) of std_ulogic_vector(31 downto 0); -- memory with 32-bit entries
  type mem8_t  is array (natural range <>) of std_ulogic_vector(07 downto 0); -- memory with 8-bit entries

  -- Internal Bus Interface -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- bus request --
  type bus_req_t is record
    addr  : std_ulogic_vector(31 downto 0); -- access address
    data  : std_ulogic_vector(31 downto 0); -- write data
    ben   : std_ulogic_vector(03 downto 0); -- byte enable
    stb   : std_ulogic; -- request strobe (single-shot)
    rw    : std_ulogic; -- 0=read, 1=write
    src   : std_ulogic; -- access source (1=instruction fetch, 0=data access)
    priv  : std_ulogic; -- set if privileged (machine-mode) access
    rvso  : std_ulogic; -- set if reservation set operation (atomic LR/SC)
    fence : std_ulogic; -- fence(.i) operation, independent of STB
  end record;

  -- bus response --
  type bus_rsp_t is record
    data : std_ulogic_vector(31 downto 0); -- read data
    ack  : std_ulogic; -- access acknowledge (single-shot)
    err  : std_ulogic; -- access error (single-shot)
  end record;

  -- source (request) termination --
  constant req_terminate_c : bus_req_t := (
    addr  => (others => '0'),
    data  => (others => '0'),
    ben   => (others => '0'),
    stb   => '0',
    rw    => '0',
    src   => '0',
    priv  => '0',
    rvso  => '0',
    fence => '0'
  );

  -- endpoint (response) termination --
  constant rsp_terminate_c : bus_rsp_t := (
    data => (others => '0'),
    ack  => '0',
    err  => '0'
  );

  -- Debug Module Interface -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- request --
  type dmi_req_t is record
    addr : std_ulogic_vector(06 downto 0);
    op   : std_ulogic_vector(01 downto 0);
    data : std_ulogic_vector(31 downto 0);
  end record;

  -- request operation --
  constant dmi_req_nop_c : std_ulogic_vector(1 downto 0) := "00"; -- no operation
  constant dmi_req_rd_c  : std_ulogic_vector(1 downto 0) := "01"; -- read access
  constant dmi_req_wr_c  : std_ulogic_vector(1 downto 0) := "10"; -- write access

  -- response --
  type dmi_rsp_t is record
    data : std_ulogic_vector(31 downto 0);
    ack  : std_ulogic;
  end record;

-- ****************************************************************************************************************************
-- RISC-V ISA Definitions
-- ****************************************************************************************************************************

  -- RISC-V 32-Bit Instruction Word Layout --------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant instr_opcode_lsb_c  : natural :=  0; -- opcode bit 0
  constant instr_opcode_msb_c  : natural :=  6; -- opcode bit 6
  constant instr_rd_lsb_c      : natural :=  7; -- destination register address bit 0
  constant instr_rd_msb_c      : natural := 11; -- destination register address bit 4
  constant instr_funct3_lsb_c  : natural := 12; -- funct3 bit 0
  constant instr_funct3_msb_c  : natural := 14; -- funct3 bit 2
  constant instr_rs1_lsb_c     : natural := 15; -- source register 1 address bit 0
  constant instr_rs1_msb_c     : natural := 19; -- source register 1 address bit 4
  constant instr_rs2_lsb_c     : natural := 20; -- source register 2 address bit 0
  constant instr_rs2_msb_c     : natural := 24; -- source register 2 address bit 4
  constant instr_rs3_lsb_c     : natural := 27; -- source register 3 address bit 0
  constant instr_rs3_msb_c     : natural := 31; -- source register 3 address bit 4
  constant instr_funct7_lsb_c  : natural := 25; -- funct7 bit 0
  constant instr_funct7_msb_c  : natural := 31; -- funct7 bit 6
  constant instr_funct12_lsb_c : natural := 20; -- funct12 bit 0
  constant instr_funct12_msb_c : natural := 31; -- funct12 bit 11
  constant instr_imm12_lsb_c   : natural := 20; -- immediate12 bit 0
  constant instr_imm12_msb_c   : natural := 31; -- immediate12 bit 11
  constant instr_imm20_lsb_c   : natural := 12; -- immediate20 bit 0
  constant instr_imm20_msb_c   : natural := 31; -- immediate20 bit 21
  constant instr_funct5_lsb_c  : natural := 27; -- funct5 select bit 0
  constant instr_funct5_msb_c  : natural := 31; -- funct5 select bit 4

  -- RISC-V Opcodes -------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- alu --
  constant opcode_alui_c   : std_ulogic_vector(6 downto 0) := "0010011"; -- ALU operation with immediate
  constant opcode_alu_c    : std_ulogic_vector(6 downto 0) := "0110011"; -- ALU operation
  constant opcode_lui_c    : std_ulogic_vector(6 downto 0) := "0110111"; -- load upper immediate
  constant opcode_auipc_c  : std_ulogic_vector(6 downto 0) := "0010111"; -- add upper immediate to PC
  -- control flow --
  constant opcode_jal_c    : std_ulogic_vector(6 downto 0) := "1101111"; -- jump and link
  constant opcode_jalr_c   : std_ulogic_vector(6 downto 0) := "1100111"; -- jump and link with register
  constant opcode_branch_c : std_ulogic_vector(6 downto 0) := "1100011"; -- branch
  -- memory access --
  constant opcode_load_c   : std_ulogic_vector(6 downto 0) := "0000011"; -- load
  constant opcode_store_c  : std_ulogic_vector(6 downto 0) := "0100011"; -- store
  constant opcode_amo_c    : std_ulogic_vector(6 downto 0) := "0101111"; -- atomic memory access
  constant opcode_fence_c  : std_ulogic_vector(6 downto 0) := "0001111"; -- fence / fence.i
  -- system/csr --
  constant opcode_system_c : std_ulogic_vector(6 downto 0) := "1110011"; -- system/csr access
  -- floating point operations --
  constant opcode_fop_c    : std_ulogic_vector(6 downto 0) := "1010011"; -- dual/single operand instruction
  -- official custom RISC-V opcodes - free for custom instructions --
  constant opcode_cust0_c  : std_ulogic_vector(6 downto 0) := "0001011"; -- custom-0
  constant opcode_cust1_c  : std_ulogic_vector(6 downto 0) := "0101011"; -- custom-1
  constant opcode_cust2_c  : std_ulogic_vector(6 downto 0) := "1011011"; -- custom-2
  constant opcode_cust3_c  : std_ulogic_vector(6 downto 0) := "1111011"; -- custom-3

  -- RISC-V Funct3 --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- control flow --
  constant funct3_beq_c    : std_ulogic_vector(2 downto 0) := "000"; -- branch if equal
  constant funct3_bne_c    : std_ulogic_vector(2 downto 0) := "001"; -- branch if not equal
  constant funct3_blt_c    : std_ulogic_vector(2 downto 0) := "100"; -- branch if less than
  constant funct3_bge_c    : std_ulogic_vector(2 downto 0) := "101"; -- branch if greater than or equal
  constant funct3_bltu_c   : std_ulogic_vector(2 downto 0) := "110"; -- branch if less than (unsigned)
  constant funct3_bgeu_c   : std_ulogic_vector(2 downto 0) := "111"; -- branch if greater than or equal (unsigned)
  -- memory access --
  constant funct3_lb_c     : std_ulogic_vector(2 downto 0) := "000"; -- load byte (signed)
  constant funct3_lh_c     : std_ulogic_vector(2 downto 0) := "001"; -- load half word (signed)
  constant funct3_lw_c     : std_ulogic_vector(2 downto 0) := "010"; -- load word (signed)
  constant funct3_lbu_c    : std_ulogic_vector(2 downto 0) := "100"; -- load byte (unsigned)
  constant funct3_lhu_c    : std_ulogic_vector(2 downto 0) := "101"; -- load half word (unsigned)
  constant funct3_lwu_c    : std_ulogic_vector(2 downto 0) := "110"; -- load word (unsigned)
  constant funct3_sb_c     : std_ulogic_vector(2 downto 0) := "000"; -- store byte
  constant funct3_sh_c     : std_ulogic_vector(2 downto 0) := "001"; -- store half word
  constant funct3_sw_c     : std_ulogic_vector(2 downto 0) := "010"; -- store word
  -- alu --
  constant funct3_subadd_c : std_ulogic_vector(2 downto 0) := "000"; -- sub/add via funct7
  constant funct3_sll_c    : std_ulogic_vector(2 downto 0) := "001"; -- shift logical left
  constant funct3_slt_c    : std_ulogic_vector(2 downto 0) := "010"; -- set on less
  constant funct3_sltu_c   : std_ulogic_vector(2 downto 0) := "011"; -- set on less unsigned
  constant funct3_xor_c    : std_ulogic_vector(2 downto 0) := "100"; -- xor
  constant funct3_sr_c     : std_ulogic_vector(2 downto 0) := "101"; -- shift right via funct7
  constant funct3_or_c     : std_ulogic_vector(2 downto 0) := "110"; -- or
  constant funct3_and_c    : std_ulogic_vector(2 downto 0) := "111"; -- and
  -- system/csr --
  constant funct3_env_c    : std_ulogic_vector(2 downto 0) := "000"; -- ecall, ebreak, mret, wfi, ...
  constant funct3_csrrw_c  : std_ulogic_vector(2 downto 0) := "001"; -- csr r/w
  constant funct3_csrrs_c  : std_ulogic_vector(2 downto 0) := "010"; -- csr read & set
  constant funct3_csrrc_c  : std_ulogic_vector(2 downto 0) := "011"; -- csr read & clear
  constant funct3_csril_c  : std_ulogic_vector(2 downto 0) := "100"; -- undefined/illegal csr command
  constant funct3_csrrwi_c : std_ulogic_vector(2 downto 0) := "101"; -- csr r/w immediate
  constant funct3_csrrsi_c : std_ulogic_vector(2 downto 0) := "110"; -- csr read & set immediate
  constant funct3_csrrci_c : std_ulogic_vector(2 downto 0) := "111"; -- csr read & clear immediate
  -- fence --
  constant funct3_fence_c  : std_ulogic_vector(2 downto 0) := "000"; -- fence - order IO/memory access
  constant funct3_fencei_c : std_ulogic_vector(2 downto 0) := "001"; -- fence.i - instruction stream sync

  -- RISC-V Funct12 - SYSTEM ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant funct12_ecall_c  : std_ulogic_vector(11 downto 0) := x"000"; -- ecall
  constant funct12_ebreak_c : std_ulogic_vector(11 downto 0) := x"001"; -- ebreak
  constant funct12_wfi_c    : std_ulogic_vector(11 downto 0) := x"105"; -- wfi
  constant funct12_mret_c   : std_ulogic_vector(11 downto 0) := x"302"; -- mret
  constant funct12_dret_c   : std_ulogic_vector(11 downto 0) := x"7b2"; -- dret

  -- RISC-V Floating-Point Stuff ------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant float_single_c : std_ulogic_vector(1 downto 0) := "00"; -- single-precision (32-bit)
--constant float_double_c : std_ulogic_vector(1 downto 0) := "01"; -- double-precision (64-bit)
--constant float_half_c   : std_ulogic_vector(1 downto 0) := "10"; -- half-precision (16-bit)
--constant float_quad_c   : std_ulogic_vector(1 downto 0) := "11"; -- quad-precision (128-bit)

  -- number class flags --
  constant fp_class_neg_inf_c    : natural := 0; -- negative infinity
  constant fp_class_neg_norm_c   : natural := 1; -- negative normal number
  constant fp_class_neg_denorm_c : natural := 2; -- negative subnormal number
  constant fp_class_neg_zero_c   : natural := 3; -- negative zero
  constant fp_class_pos_zero_c   : natural := 4; -- positive zero
  constant fp_class_pos_denorm_c : natural := 5; -- positive subnormal number
  constant fp_class_pos_norm_c   : natural := 6; -- positive normal number
  constant fp_class_pos_inf_c    : natural := 7; -- positive infinity
  constant fp_class_snan_c       : natural := 8; -- signaling NaN (sNaN)
  constant fp_class_qnan_c       : natural := 9; -- quiet NaN (qNaN)

  -- exception flags --
  constant fp_exc_nx_c : natural := 0; -- inexact
  constant fp_exc_uf_c : natural := 1; -- underflow
  constant fp_exc_of_c : natural := 2; -- overflow
  constant fp_exc_dz_c : natural := 3; -- division by zero
  constant fp_exc_nv_c : natural := 4; -- invalid operation

  -- special values (single-precision) --
  constant fp_single_qnan_c     : std_ulogic_vector(31 downto 0) := x"7fc00000"; -- quiet NaN
  constant fp_single_snan_c     : std_ulogic_vector(31 downto 0) := x"7fa00000"; -- signaling NaN
  constant fp_single_pos_max_c  : std_ulogic_vector(31 downto 0) := x"7f7FFFFF"; -- positive max
  constant fp_single_neg_max_c  : std_ulogic_vector(31 downto 0) := x"Ff7FFFFF"; -- negative max
  constant fp_single_pos_inf_c  : std_ulogic_vector(31 downto 0) := x"7f800000"; -- positive infinity
  constant fp_single_neg_inf_c  : std_ulogic_vector(31 downto 0) := x"ff800000"; -- negative infinity
  constant fp_single_pos_zero_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- positive zero
  constant fp_single_neg_zero_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- negative zero

  -- RISC-V CSRs ----------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- user floating-point CSRs --
  constant csr_fflags_c         : std_ulogic_vector(11 downto 0) := x"001";
  constant csr_frm_c            : std_ulogic_vector(11 downto 0) := x"002";
  constant csr_fcsr_c           : std_ulogic_vector(11 downto 0) := x"003";
  -- machine trap setup --
  constant csr_mstatus_c        : std_ulogic_vector(11 downto 0) := x"300";
  constant csr_misa_c           : std_ulogic_vector(11 downto 0) := x"301";
  constant csr_mie_c            : std_ulogic_vector(11 downto 0) := x"304";
  constant csr_mtvec_c          : std_ulogic_vector(11 downto 0) := x"305";
  constant csr_mcounteren_c     : std_ulogic_vector(11 downto 0) := x"306";
  constant csr_mstatush_c       : std_ulogic_vector(11 downto 0) := x"310";
  -- machine configuration --
  constant csr_menvcfg_c        : std_ulogic_vector(11 downto 0) := x"30a";
  constant csr_menvcfgh_c       : std_ulogic_vector(11 downto 0) := x"31a";
  -- machine counter setup --
  constant csr_mcountinhibit_c  : std_ulogic_vector(11 downto 0) := x"320";
  constant csr_mhpmevent3_c     : std_ulogic_vector(11 downto 0) := x"323";
  constant csr_mhpmevent4_c     : std_ulogic_vector(11 downto 0) := x"324";
  constant csr_mhpmevent5_c     : std_ulogic_vector(11 downto 0) := x"325";
  constant csr_mhpmevent6_c     : std_ulogic_vector(11 downto 0) := x"326";
  constant csr_mhpmevent7_c     : std_ulogic_vector(11 downto 0) := x"327";
  constant csr_mhpmevent8_c     : std_ulogic_vector(11 downto 0) := x"328";
  constant csr_mhpmevent9_c     : std_ulogic_vector(11 downto 0) := x"329";
  constant csr_mhpmevent10_c    : std_ulogic_vector(11 downto 0) := x"32a";
  constant csr_mhpmevent11_c    : std_ulogic_vector(11 downto 0) := x"32b";
  constant csr_mhpmevent12_c    : std_ulogic_vector(11 downto 0) := x"32c";
  constant csr_mhpmevent13_c    : std_ulogic_vector(11 downto 0) := x"32d";
  constant csr_mhpmevent14_c    : std_ulogic_vector(11 downto 0) := x"32e";
  constant csr_mhpmevent15_c    : std_ulogic_vector(11 downto 0) := x"32f";
  -- machine trap handling --
  constant csr_mscratch_c       : std_ulogic_vector(11 downto 0) := x"340";
  constant csr_mepc_c           : std_ulogic_vector(11 downto 0) := x"341";
  constant csr_mcause_c         : std_ulogic_vector(11 downto 0) := x"342";
  constant csr_mtval_c          : std_ulogic_vector(11 downto 0) := x"343";
  constant csr_mip_c            : std_ulogic_vector(11 downto 0) := x"344";
  constant csr_mtinst_c         : std_ulogic_vector(11 downto 0) := x"34a";
  -- physical memory protection - configuration --
  constant csr_pmpcfg0_c        : std_ulogic_vector(11 downto 0) := x"3a0";
  constant csr_pmpcfg1_c        : std_ulogic_vector(11 downto 0) := x"3a1";
  constant csr_pmpcfg2_c        : std_ulogic_vector(11 downto 0) := x"3a2";
  constant csr_pmpcfg3_c        : std_ulogic_vector(11 downto 0) := x"3a3";
  -- physical memory protection - address --
  constant csr_pmpaddr0_c       : std_ulogic_vector(11 downto 0) := x"3b0";
  constant csr_pmpaddr1_c       : std_ulogic_vector(11 downto 0) := x"3b1";
  constant csr_pmpaddr2_c       : std_ulogic_vector(11 downto 0) := x"3b2";
  constant csr_pmpaddr3_c       : std_ulogic_vector(11 downto 0) := x"3b3";
  constant csr_pmpaddr4_c       : std_ulogic_vector(11 downto 0) := x"3b4";
  constant csr_pmpaddr5_c       : std_ulogic_vector(11 downto 0) := x"3b5";
  constant csr_pmpaddr6_c       : std_ulogic_vector(11 downto 0) := x"3b6";
  constant csr_pmpaddr7_c       : std_ulogic_vector(11 downto 0) := x"3b7";
  constant csr_pmpaddr8_c       : std_ulogic_vector(11 downto 0) := x"3b8";
  constant csr_pmpaddr9_c       : std_ulogic_vector(11 downto 0) := x"3b9";
  constant csr_pmpaddr10_c      : std_ulogic_vector(11 downto 0) := x"3ba";
  constant csr_pmpaddr11_c      : std_ulogic_vector(11 downto 0) := x"3bb";
  constant csr_pmpaddr12_c      : std_ulogic_vector(11 downto 0) := x"3bc";
  constant csr_pmpaddr13_c      : std_ulogic_vector(11 downto 0) := x"3bd";
  constant csr_pmpaddr14_c      : std_ulogic_vector(11 downto 0) := x"3be";
  constant csr_pmpaddr15_c      : std_ulogic_vector(11 downto 0) := x"3bf";
  -- trigger module registers --
  constant csr_tselect_c        : std_ulogic_vector(11 downto 0) := x"7a0";
  constant csr_tdata1_c         : std_ulogic_vector(11 downto 0) := x"7a1";
  constant csr_tdata2_c         : std_ulogic_vector(11 downto 0) := x"7a2";
  constant csr_tinfo_c          : std_ulogic_vector(11 downto 0) := x"7a4";
  -- debug mode registers --
  constant csr_dcsr_c           : std_ulogic_vector(11 downto 0) := x"7b0";
  constant csr_dpc_c            : std_ulogic_vector(11 downto 0) := x"7b1";
  constant csr_dscratch0_c      : std_ulogic_vector(11 downto 0) := x"7b2";
  -- NEORV32-specific user-mode registers --
  constant csr_cfureg0_c        : std_ulogic_vector(11 downto 0) := x"800";
  constant csr_cfureg1_c        : std_ulogic_vector(11 downto 0) := x"801";
  constant csr_cfureg2_c        : std_ulogic_vector(11 downto 0) := x"802";
  constant csr_cfureg3_c        : std_ulogic_vector(11 downto 0) := x"803";
  -- machine counters/timers --
  constant csr_mcycle_c         : std_ulogic_vector(11 downto 0) := x"b00";
--constant csr_mtime_c          : std_ulogic_vector(11 downto 0) := x"b01";
  constant csr_minstret_c       : std_ulogic_vector(11 downto 0) := x"b02";
  constant csr_mhpmcounter3_c   : std_ulogic_vector(11 downto 0) := x"b03";
  constant csr_mhpmcounter4_c   : std_ulogic_vector(11 downto 0) := x"b04";
  constant csr_mhpmcounter5_c   : std_ulogic_vector(11 downto 0) := x"b05";
  constant csr_mhpmcounter6_c   : std_ulogic_vector(11 downto 0) := x"b06";
  constant csr_mhpmcounter7_c   : std_ulogic_vector(11 downto 0) := x"b07";
  constant csr_mhpmcounter8_c   : std_ulogic_vector(11 downto 0) := x"b08";
  constant csr_mhpmcounter9_c   : std_ulogic_vector(11 downto 0) := x"b09";
  constant csr_mhpmcounter10_c  : std_ulogic_vector(11 downto 0) := x"b0a";
  constant csr_mhpmcounter11_c  : std_ulogic_vector(11 downto 0) := x"b0b";
  constant csr_mhpmcounter12_c  : std_ulogic_vector(11 downto 0) := x"b0c";
  constant csr_mhpmcounter13_c  : std_ulogic_vector(11 downto 0) := x"b0d";
  constant csr_mhpmcounter14_c  : std_ulogic_vector(11 downto 0) := x"b0e";
  constant csr_mhpmcounter15_c  : std_ulogic_vector(11 downto 0) := x"b0f";
  --
  constant csr_mcycleh_c        : std_ulogic_vector(11 downto 0) := x"b80";
--constant csr_mtimeh_c         : std_ulogic_vector(11 downto 0) := x"b81";
  constant csr_minstreth_c      : std_ulogic_vector(11 downto 0) := x"b82";
  constant csr_mhpmcounter3h_c  : std_ulogic_vector(11 downto 0) := x"b83";
  constant csr_mhpmcounter4h_c  : std_ulogic_vector(11 downto 0) := x"b84";
  constant csr_mhpmcounter5h_c  : std_ulogic_vector(11 downto 0) := x"b85";
  constant csr_mhpmcounter6h_c  : std_ulogic_vector(11 downto 0) := x"b86";
  constant csr_mhpmcounter7h_c  : std_ulogic_vector(11 downto 0) := x"b87";
  constant csr_mhpmcounter8h_c  : std_ulogic_vector(11 downto 0) := x"b88";
  constant csr_mhpmcounter9h_c  : std_ulogic_vector(11 downto 0) := x"b89";
  constant csr_mhpmcounter10h_c : std_ulogic_vector(11 downto 0) := x"b8a";
  constant csr_mhpmcounter11h_c : std_ulogic_vector(11 downto 0) := x"b8b";
  constant csr_mhpmcounter12h_c : std_ulogic_vector(11 downto 0) := x"b8c";
  constant csr_mhpmcounter13h_c : std_ulogic_vector(11 downto 0) := x"b8d";
  constant csr_mhpmcounter14h_c : std_ulogic_vector(11 downto 0) := x"b8e";
  constant csr_mhpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"b8f";
  -- user counters/timers --
  constant csr_cycle_c          : std_ulogic_vector(11 downto 0) := x"c00";
--constant csr_time_c           : std_ulogic_vector(11 downto 0) := x"c01";
  constant csr_instret_c        : std_ulogic_vector(11 downto 0) := x"c02";
  constant csr_hpmcounter3_c    : std_ulogic_vector(11 downto 0) := x"c03";
  constant csr_hpmcounter4_c    : std_ulogic_vector(11 downto 0) := x"c04";
  constant csr_hpmcounter5_c    : std_ulogic_vector(11 downto 0) := x"c05";
  constant csr_hpmcounter6_c    : std_ulogic_vector(11 downto 0) := x"c06";
  constant csr_hpmcounter7_c    : std_ulogic_vector(11 downto 0) := x"c07";
  constant csr_hpmcounter8_c    : std_ulogic_vector(11 downto 0) := x"c08";
  constant csr_hpmcounter9_c    : std_ulogic_vector(11 downto 0) := x"c09";
  constant csr_hpmcounter10_c   : std_ulogic_vector(11 downto 0) := x"c0a";
  constant csr_hpmcounter11_c   : std_ulogic_vector(11 downto 0) := x"c0b";
  constant csr_hpmcounter12_c   : std_ulogic_vector(11 downto 0) := x"c0c";
  constant csr_hpmcounter13_c   : std_ulogic_vector(11 downto 0) := x"c0d";
  constant csr_hpmcounter14_c   : std_ulogic_vector(11 downto 0) := x"c0e";
  constant csr_hpmcounter15_c   : std_ulogic_vector(11 downto 0) := x"c0f";
  --
  constant csr_cycleh_c         : std_ulogic_vector(11 downto 0) := x"c80";
--constant csr_timeh_c          : std_ulogic_vector(11 downto 0) := x"c81";
  constant csr_instreth_c       : std_ulogic_vector(11 downto 0) := x"c82";
  constant csr_hpmcounter3h_c   : std_ulogic_vector(11 downto 0) := x"c83";
  constant csr_hpmcounter4h_c   : std_ulogic_vector(11 downto 0) := x"c84";
  constant csr_hpmcounter5h_c   : std_ulogic_vector(11 downto 0) := x"c85";
  constant csr_hpmcounter6h_c   : std_ulogic_vector(11 downto 0) := x"c86";
  constant csr_hpmcounter7h_c   : std_ulogic_vector(11 downto 0) := x"c87";
  constant csr_hpmcounter8h_c   : std_ulogic_vector(11 downto 0) := x"c88";
  constant csr_hpmcounter9h_c   : std_ulogic_vector(11 downto 0) := x"c89";
  constant csr_hpmcounter10h_c  : std_ulogic_vector(11 downto 0) := x"c8a";
  constant csr_hpmcounter11h_c  : std_ulogic_vector(11 downto 0) := x"c8b";
  constant csr_hpmcounter12h_c  : std_ulogic_vector(11 downto 0) := x"c8c";
  constant csr_hpmcounter13h_c  : std_ulogic_vector(11 downto 0) := x"c8d";
  constant csr_hpmcounter14h_c  : std_ulogic_vector(11 downto 0) := x"c8e";
  constant csr_hpmcounter15h_c  : std_ulogic_vector(11 downto 0) := x"c8f";
  -- machine information registers --
  constant csr_mvendorid_c      : std_ulogic_vector(11 downto 0) := x"f11";
  constant csr_marchid_c        : std_ulogic_vector(11 downto 0) := x"f12";
  constant csr_mimpid_c         : std_ulogic_vector(11 downto 0) := x"f13";
  constant csr_mhartid_c        : std_ulogic_vector(11 downto 0) := x"f14";
  constant csr_mconfigptr_c     : std_ulogic_vector(11 downto 0) := x"f15";
  -- NEORV32-specific machine-mode registers --
  constant csr_mxisa_c          : std_ulogic_vector(11 downto 0) := x"fc0";

-- ****************************************************************************************************************************
-- CPU Control
-- ****************************************************************************************************************************

  -- Main CPU Control Bus -------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  type ctrl_bus_t is record
    -- register file --
    rf_wb_en     : std_ulogic; -- write back enable
    rf_rs1       : std_ulogic_vector(04 downto 0); -- source register 1 address
    rf_rs2       : std_ulogic_vector(04 downto 0); -- source register 2 address
    rf_rs3       : std_ulogic_vector(04 downto 0); -- source register 3 address
    rf_rd        : std_ulogic_vector(04 downto 0); -- destination register address
    rf_mux       : std_ulogic_vector(01 downto 0); -- input source select
    rf_zero_we   : std_ulogic;                     -- allow/force write access to x0
    -- alu --
    alu_op       : std_ulogic_vector(02 downto 0); -- ALU operation select
    alu_opa_mux  : std_ulogic;                     -- operand A select (0=rs1, 1=PC)
    alu_opb_mux  : std_ulogic;                     -- operand B select (0=rs2, 1=IMM)
    alu_unsigned : std_ulogic;                     -- is unsigned ALU operation
    alu_cp_trig  : std_ulogic_vector(05 downto 0); -- co-processor trigger (one-hot)
    -- load/store unit --
    lsu_req      : std_ulogic;                     -- trigger memory access request
    lsu_rw       : std_ulogic;                     -- 0: read access, 1: write access
    lsu_mo_we    : std_ulogic;                     -- memory address and data output register write enable
    lsu_fence    : std_ulogic;                     -- fence(.i) operation
    lsu_priv     : std_ulogic;                     -- effective privilege level for load/store
    -- instruction word --
    ir_funct3    : std_ulogic_vector(02 downto 0); -- funct3 bit field
    ir_funct12   : std_ulogic_vector(11 downto 0); -- funct12 bit field
    ir_opcode    : std_ulogic_vector(06 downto 0); -- opcode bit field
    -- cpu status --
    cpu_priv     : std_ulogic;                     -- effective privilege mode
    cpu_sleep    : std_ulogic;                     -- set when CPU is in sleep mode
    cpu_trap     : std_ulogic;                     -- set when CPU is entering trap exec
    cpu_debug    : std_ulogic;                     -- set when CPU is in debug mode
  end record;

  -- control bus reset initializer --
  constant ctrl_bus_zero_c : ctrl_bus_t := (
    rf_wb_en     => '0',
    rf_rs1       => (others => '0'),
    rf_rs2       => (others => '0'),
    rf_rs3       => (others => '0'),
    rf_rd        => (others => '0'),
    rf_mux       => (others => '0'),
    rf_zero_we   => '0',
    alu_op       => (others => '0'),
    alu_opa_mux  => '0',
    alu_opb_mux  => '0',
    alu_unsigned => '0',
    alu_cp_trig  => (others => '0'),
    lsu_req      => '0',
    lsu_rw       => '0',
    lsu_mo_we    => '0',
    lsu_fence    => '0',
    lsu_priv     => '0',
    ir_funct3    => (others => '0'),
    ir_funct12   => (others => '0'),
    ir_opcode    => (others => '0'),
    cpu_priv     => '0',
    cpu_sleep    => '0',
    cpu_trap     => '0',
    cpu_debug    => '0'
  );

  -- Comparator Bus -------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant cmp_equal_c : natural := 0;
  constant cmp_less_c  : natural := 1; -- for signed and unsigned comparisons

  -- CPU Co-Processor IDs -------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant cp_sel_shifter_c  : natural := 0; -- CP0: shift operations (base ISA)
  constant cp_sel_muldiv_c   : natural := 1; -- CP1: multiplication/division operations ('M' extensions)
  constant cp_sel_bitmanip_c : natural := 2; -- CP2: bit manipulation ('B' extensions)
  constant cp_sel_fpu_c      : natural := 3; -- CP3: floating-point unit ('Zfinx' extension)
  constant cp_sel_cfu_c      : natural := 4; -- CP4: custom instructions CFU ('Zxcfu' extension)
  constant cp_sel_cond_c     : natural := 5; -- CP5: conditional operations ('Zicond' extension)

  -- ALU Function Codes [DO NOT CHANGE ENCODING!] -------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant alu_op_add_c  : std_ulogic_vector(2 downto 0) := "000"; -- result <= A + B
  constant alu_op_sub_c  : std_ulogic_vector(2 downto 0) := "001"; -- result <= A - B
  constant alu_op_cp_c   : std_ulogic_vector(2 downto 0) := "010"; -- result <= ALU co-processor
  constant alu_op_slt_c  : std_ulogic_vector(2 downto 0) := "011"; -- result <= A < B
  constant alu_op_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- result <= B
  constant alu_op_xor_c  : std_ulogic_vector(2 downto 0) := "101"; -- result <= A xor B
  constant alu_op_or_c   : std_ulogic_vector(2 downto 0) := "110"; -- result <= A or B
  constant alu_op_and_c  : std_ulogic_vector(2 downto 0) := "111"; -- result <= A and B

  -- Register File Input Select -------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant rf_mux_alu_c : std_ulogic_vector(1 downto 0) := "00"; -- register file <= alu result
  constant rf_mux_mem_c : std_ulogic_vector(1 downto 0) := "01"; -- register file <= memory read data
  constant rf_mux_csr_c : std_ulogic_vector(1 downto 0) := "10"; -- register file <= CSR read data
  constant rf_mux_ret_c : std_ulogic_vector(1 downto 0) := "11"; -- register file <= link-PC (return address)

  -- Trap ID Codes --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- MSB:   1 = interrupt, 0 = sync. exception
  -- MSB-1: 1 = entry to debug mode, 0 = normal trapping
  -- RISC-V compliant synchronous exceptions --
  constant trap_ima_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00000"; -- 0: instruction misaligned
  constant trap_iaf_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00001"; -- 1: instruction access fault
  constant trap_iil_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00010"; -- 2: illegal instruction
  constant trap_brk_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00011"; -- 3: environment breakpoint
  constant trap_lma_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00100"; -- 4: load address misaligned
  constant trap_laf_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00101"; -- 5: load access fault
  constant trap_sma_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00110"; -- 6: store address misaligned
  constant trap_saf_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "00111"; -- 7: store access fault
  constant trap_env_c      : std_ulogic_vector(6 downto 0) := "0" & "0" & "010UU"; -- 8..11: environment call from u/s/h/m
  -- RISC-V compliant asynchronous exceptions (interrupts) --
  constant trap_msi_c      : std_ulogic_vector(6 downto 0) := "1" & "0" & "00011"; -- 3:  machine software interrupt
  constant trap_mti_c      : std_ulogic_vector(6 downto 0) := "1" & "0" & "00111"; -- 7:  machine timer interrupt
  constant trap_mei_c      : std_ulogic_vector(6 downto 0) := "1" & "0" & "01011"; -- 11: machine external interrupt
  -- NEORV32-specific (RISC-V custom) asynchronous exceptions (interrupts) --
  constant trap_firq0_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10000"; -- 16: fast interrupt 0
  constant trap_firq1_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10001"; -- 17: fast interrupt 1
  constant trap_firq2_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10010"; -- 18: fast interrupt 2
  constant trap_firq3_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10011"; -- 19: fast interrupt 3
  constant trap_firq4_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10100"; -- 20: fast interrupt 4
  constant trap_firq5_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10101"; -- 21: fast interrupt 5
  constant trap_firq6_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10110"; -- 22: fast interrupt 6
  constant trap_firq7_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "10111"; -- 23: fast interrupt 7
  constant trap_firq8_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "11000"; -- 24: fast interrupt 8
  constant trap_firq9_c    : std_ulogic_vector(6 downto 0) := "1" & "0" & "11001"; -- 25: fast interrupt 9
  constant trap_firq10_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11010"; -- 26: fast interrupt 10
  constant trap_firq11_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11011"; -- 27: fast interrupt 11
  constant trap_firq12_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11100"; -- 28: fast interrupt 12
  constant trap_firq13_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11101"; -- 29: fast interrupt 13
  constant trap_firq14_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11110"; -- 30: fast interrupt 14
  constant trap_firq15_c   : std_ulogic_vector(6 downto 0) := "1" & "0" & "11111"; -- 31: fast interrupt 15
  -- entering debug mode (sync./async. exceptions) --
  constant trap_db_break_c : std_ulogic_vector(6 downto 0) := "0" & "1" & "00001"; -- 1: break instruction (sync)
  constant trap_db_trig_c  : std_ulogic_vector(6 downto 0) := "0" & "1" & "00010"; -- 2: hardware trigger (sync)
  constant trap_db_halt_c  : std_ulogic_vector(6 downto 0) := "1" & "1" & "00011"; -- 3: external halt request (async)
  constant trap_db_step_c  : std_ulogic_vector(6 downto 0) := "1" & "1" & "00100"; -- 4: single-stepping (async)

  -- Trap System ----------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- exception source bits --
  constant exc_iaccess_c  : natural :=  0; -- instruction access fault
  constant exc_illegal_c  : natural :=  1; -- illegal instruction
  constant exc_ialign_c   : natural :=  2; -- instruction address misaligned
  constant exc_ecall_c    : natural :=  3; -- environment call
  constant exc_ebreak_c   : natural :=  4; -- breakpoint
  constant exc_salign_c   : natural :=  5; -- store address misaligned
  constant exc_lalign_c   : natural :=  6; -- load address misaligned
  constant exc_saccess_c  : natural :=  7; -- store access fault
  constant exc_laccess_c  : natural :=  8; -- load access fault
  constant exc_db_break_c : natural :=  9; -- enter debug mode via ebreak instruction
  constant exc_db_hw_c    : natural := 10; -- enter debug mode via hw trigger
  --
  constant exc_width_c    : natural := 11; -- length of this list in bits
  -- interrupt source bits --
  constant irq_msi_irq_c  : natural :=  0; -- machine software interrupt
  constant irq_mti_irq_c  : natural :=  1; -- machine timer interrupt
  constant irq_mei_irq_c  : natural :=  2; -- machine external interrupt
  constant irq_firq_0_c   : natural :=  3; -- fast interrupt channel 0
  constant irq_firq_1_c   : natural :=  4; -- fast interrupt channel 1
  constant irq_firq_2_c   : natural :=  5; -- fast interrupt channel 2
  constant irq_firq_3_c   : natural :=  6; -- fast interrupt channel 3
  constant irq_firq_4_c   : natural :=  7; -- fast interrupt channel 4
  constant irq_firq_5_c   : natural :=  8; -- fast interrupt channel 5
  constant irq_firq_6_c   : natural :=  9; -- fast interrupt channel 6
  constant irq_firq_7_c   : natural := 10; -- fast interrupt channel 7
  constant irq_firq_8_c   : natural := 11; -- fast interrupt channel 8
  constant irq_firq_9_c   : natural := 12; -- fast interrupt channel 9
  constant irq_firq_10_c  : natural := 13; -- fast interrupt channel 10
  constant irq_firq_11_c  : natural := 14; -- fast interrupt channel 11
  constant irq_firq_12_c  : natural := 15; -- fast interrupt channel 12
  constant irq_firq_13_c  : natural := 16; -- fast interrupt channel 13
  constant irq_firq_14_c  : natural := 17; -- fast interrupt channel 14
  constant irq_firq_15_c  : natural := 18; -- fast interrupt channel 15
  constant irq_db_halt_c  : natural := 19; -- enter debug mode via external halt request
  constant irq_db_step_c  : natural := 20; -- enter debug mode via single-stepping
  --
  constant irq_width_c    : natural := 21; -- length of this list in bits

  -- Privilege Modes ------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  constant priv_mode_m_c : std_ulogic := '1'; -- machine mode
  constant priv_mode_u_c : std_ulogic := '0'; -- user mode

  -- HPM Events -----------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- RISC-V-compliant --
  constant hpmcnt_event_cy_c       : natural := 0;  -- active cycle
  constant hpmcnt_event_tm_c       : natural := 1;  -- time (unused/reserved)
  constant hpmcnt_event_ir_c       : natural := 2;  -- retired instruction
  -- NEORV32-specific --
  constant hpmcnt_event_compr_c    : natural := 3;  -- executed compressed instruction
  constant hpmcnt_event_wait_dis_c : natural := 4;  -- instruction dispatch wait cycle
  constant hpmcnt_event_wait_alu_c : natural := 5;  -- multi-cycle ALU co-processor wait cycle
  constant hpmcnt_event_branch_c   : natural := 6;  -- executed branch instruction
  constant hpmcnt_event_branched_c : natural := 7;  -- control flow transfer
  constant hpmcnt_event_load_c     : natural := 8;  -- load operation
  constant hpmcnt_event_store_c    : natural := 9;  -- store operation
  constant hpmcnt_event_wait_lsu_c : natural := 10; -- load-store unit memory wait cycle
  constant hpmcnt_event_trap_c     : natural := 11; -- entered trap
  --
  constant hpmcnt_event_size_c     : natural := 12; -- length of this list

-- ****************************************************************************************************************************
-- Helper Functions
-- ****************************************************************************************************************************

  function index_size_f(input : natural) return natural;
  function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer;
  function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural;
  function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector;
  function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string;
  function bool_to_ulogic_f(cond : boolean) return std_ulogic;
  function bin_to_gray_f(input : std_ulogic_vector) return std_ulogic_vector;
  function gray_to_bin_f(input : std_ulogic_vector) return std_ulogic_vector;
  function or_reduce_f(input : std_ulogic_vector) return std_ulogic;
  function and_reduce_f(input : std_ulogic_vector) return std_ulogic;
  function xor_reduce_f(input : std_ulogic_vector) return std_ulogic;
  function su_undefined_f(input : std_ulogic) return boolean;
  function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character;
  function to_hstring32_f(input : std_ulogic_vector(31 downto 0)) return string;
  function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector;
  function is_power_of_two_f(input : natural) return boolean;
  function bswap32_f(input : std_ulogic_vector) return std_ulogic_vector;
  function popcount_f(input : std_ulogic_vector) return natural;
  function leading_zeros_f(input : std_ulogic_vector) return natural;
  impure function mem32_init_f(init : mem32_t; depth : natural) return mem32_t;

-- ****************************************************************************************************************************
-- NEORV32 Processor Top Entity (component prototype)
-- ****************************************************************************************************************************

  component neorv32_top
    generic (
      -- General --
      CLOCK_FREQUENCY            : natural;
      CLOCK_GATING_EN            : boolean                        := false;
      HART_ID                    : std_ulogic_vector(31 downto 0) := x"00000000";
      VENDOR_ID                  : std_ulogic_vector(31 downto 0) := x"00000000";
      INT_BOOTLOADER_EN          : boolean                        := false;
      -- On-Chip Debugger (OCD) --
      ON_CHIP_DEBUGGER_EN        : boolean                        := false;
      DM_LEGACY_MODE             : boolean                        := false;
      -- RISC-V CPU Extensions --
      CPU_EXTENSION_RISCV_A      : boolean                        := false;
      CPU_EXTENSION_RISCV_B      : boolean                        := false;
      CPU_EXTENSION_RISCV_C      : boolean                        := false;
      CPU_EXTENSION_RISCV_E      : boolean                        := false;
      CPU_EXTENSION_RISCV_M      : boolean                        := false;
      CPU_EXTENSION_RISCV_U      : boolean                        := false;
      CPU_EXTENSION_RISCV_Zfinx  : boolean                        := false;
      CPU_EXTENSION_RISCV_Zicntr : boolean                        := true;
      CPU_EXTENSION_RISCV_Zicond : boolean                        := false;
      CPU_EXTENSION_RISCV_Zihpm  : boolean                        := false;
      CPU_EXTENSION_RISCV_Zmmul  : boolean                        := false;
      CPU_EXTENSION_RISCV_Zxcfu  : boolean                        := false;
      -- Tuning Options --
      FAST_MUL_EN                : boolean                        := false;
      FAST_SHIFT_EN              : boolean                        := false;
      REGFILE_HW_RST             : boolean                        := false;
      -- Physical Memory Protection (PMP) --
      PMP_NUM_REGIONS            : natural range 0 to 16          := 0;
      PMP_MIN_GRANULARITY        : natural                        := 4;
      PMP_TOR_MODE_EN            : boolean                        := true;
      PMP_NAP_MODE_EN            : boolean                        := true;
      -- Hardware Performance Monitors (HPM) --
      HPM_NUM_CNTS               : natural range 0 to 13          := 0;
      HPM_CNT_WIDTH              : natural range 0 to 64          := 40;
      -- Atomic Memory Access - Reservation Set Granularity --
      AMO_RVS_GRANULARITY        : natural                        := 4;
      -- Internal Instruction memory (IMEM) --
      MEM_INT_IMEM_EN            : boolean                        := false;
      MEM_INT_IMEM_SIZE          : natural                        := 16*1024;
      -- Internal Data memory (DMEM) --
      MEM_INT_DMEM_EN            : boolean                        := false;
      MEM_INT_DMEM_SIZE          : natural                        := 8*1024;
      -- Internal Instruction Cache (iCACHE) --
      ICACHE_EN                  : boolean                        := false;
      ICACHE_NUM_BLOCKS          : natural range 1 to 256         := 4;
      ICACHE_BLOCK_SIZE          : natural range 4 to 2**16       := 64;
      ICACHE_ASSOCIATIVITY       : natural range 1 to 2           := 1;
      -- Internal Data Cache (dCACHE) --
      DCACHE_EN                  : boolean                        := false;
      DCACHE_NUM_BLOCKS          : natural range 1 to 256         := 4;
      DCACHE_BLOCK_SIZE          : natural range 4 to 2**16       := 64;
      -- External memory interface (WISHBONE) --
      MEM_EXT_EN                 : boolean                        := false;
      MEM_EXT_TIMEOUT            : natural                        := 255;
      MEM_EXT_PIPE_MODE          : boolean                        := false;
      MEM_EXT_BIG_ENDIAN         : boolean                        := false;
      MEM_EXT_ASYNC_RX           : boolean                        := false;
      MEM_EXT_ASYNC_TX           : boolean                        := false;
      -- Execute in-place module (XIP) --
      XIP_EN                     : boolean                        := false;
      XIP_CACHE_EN               : boolean                        := false;
      XIP_CACHE_NUM_BLOCKS       : natural range 1 to 256         := 8;
      XIP_CACHE_BLOCK_SIZE       : natural range 1 to 2**16       := 256;
      -- External Interrupts Controller (XIRQ) --
      XIRQ_NUM_CH                : natural range 0 to 32          := 0;
      XIRQ_TRIGGER_TYPE          : std_ulogic_vector(31 downto 0) := x"ffffffff";
      XIRQ_TRIGGER_POLARITY      : std_ulogic_vector(31 downto 0) := x"ffffffff";
      -- Processor peripherals --
      IO_GPIO_NUM                : natural range 0 to 64          := 0;
      IO_MTIME_EN                : boolean                        := false;
      IO_UART0_EN                : boolean                        := false;
      IO_UART0_RX_FIFO           : natural range 1 to 2**15       := 1;
      IO_UART0_TX_FIFO           : natural range 1 to 2**15       := 1;
      IO_UART1_EN                : boolean                        := false;
      IO_UART1_RX_FIFO           : natural range 1 to 2**15       := 1;
      IO_UART1_TX_FIFO           : natural range 1 to 2**15       := 1;
      IO_SPI_EN                  : boolean                        := false;
      IO_SPI_FIFO                : natural range 1 to 2**15       := 1;
      IO_SDI_EN                  : boolean                        := false;
      IO_SDI_FIFO                : natural range 1 to 2**15       := 1;
      IO_TWI_EN                  : boolean                        := false;
      IO_PWM_NUM_CH              : natural range 0 to 12          := 0;
      IO_WDT_EN                  : boolean                        := false;
      IO_TRNG_EN                 : boolean                        := false;
      IO_TRNG_FIFO               : natural range 1 to 2**15       := 1;
      IO_CFS_EN                  : boolean                        := false;
      IO_CFS_CONFIG              : std_ulogic_vector(31 downto 0) := x"00000000";
      IO_CFS_IN_SIZE             : natural                        := 32;
      IO_CFS_OUT_SIZE            : natural                        := 32;
      IO_NEOLED_EN               : boolean                        := false;
      IO_NEOLED_TX_FIFO          : natural range 1 to 2**15       := 1;
      IO_GPTMR_EN                : boolean                        := false;
      IO_ONEWIRE_EN              : boolean                        := false;
      IO_DMA_EN                  : boolean                        := false;
      IO_SLINK_EN                : boolean                        := false;
      IO_SLINK_RX_FIFO           : natural range 1 to 2**15       := 1;
      IO_SLINK_TX_FIFO           : natural range 1 to 2**15       := 1;
      IO_CRC_EN                  : boolean                        := false
    );
    port (
      -- Global control --
      clk_i          : in  std_ulogic;
      rstn_i         : in  std_ulogic;
      -- JTAG on-chip debugger interface --
      jtag_trst_i    : in  std_ulogic := 'H';
      jtag_tck_i     : in  std_ulogic := 'L';
      jtag_tdi_i     : in  std_ulogic := 'L';
      jtag_tdo_o     : out std_ulogic;
      jtag_tms_i     : in  std_ulogic := 'L';
      -- Wishbone bus interface (available if MEM_EXT_EN = true) --
      wb_tag_o       : out std_ulogic_vector(02 downto 0);
      wb_adr_o       : out std_ulogic_vector(31 downto 0);
      wb_dat_i       : in  std_ulogic_vector(31 downto 0) := (others => 'L');
      wb_dat_o       : out std_ulogic_vector(31 downto 0);
      wb_we_o        : out std_ulogic;
      wb_sel_o       : out std_ulogic_vector(03 downto 0);
      wb_stb_o       : out std_ulogic;
      wb_cyc_o       : out std_ulogic;
      wb_ack_i       : in  std_ulogic := 'L';
      wb_err_i       : in  std_ulogic := 'L';
      -- Stream Link Interface (available if IO_SLINK_EN = true) --
      slink_rx_dat_i : in  std_ulogic_vector(31 downto 0) := (others => 'L');
      slink_rx_val_i : in  std_ulogic := 'L';
      slink_rx_lst_i : in  std_ulogic := 'L';
      slink_rx_rdy_o : out std_ulogic;
      slink_tx_dat_o : out std_ulogic_vector(31 downto 0);
      slink_tx_val_o : out std_ulogic;
      slink_tx_lst_o : out std_ulogic;
      slink_tx_rdy_i : in  std_ulogic := 'L';
      -- XIP (execute in-place via SPI) signals (available if XIP_EN = true) --
      xip_csn_o      : out std_ulogic;
      xip_clk_o      : out std_ulogic;
      xip_dat_i      : in  std_ulogic := 'L';
      xip_dat_o      : out std_ulogic;
      -- GPIO (available if IO_GPIO_NUM > 0) --
      gpio_o         : out std_ulogic_vector(63 downto 0);
      gpio_i         : in  std_ulogic_vector(63 downto 0) := (others => 'L');
      -- primary UART0 (available if IO_UART0_EN = true) --
      uart0_txd_o    : out std_ulogic;
      uart0_rxd_i    : in  std_ulogic := 'L';
      uart0_rts_o    : out std_ulogic;
      uart0_cts_i    : in  std_ulogic := 'L';
      -- secondary UART1 (available if IO_UART1_EN = true) --
      uart1_txd_o    : out std_ulogic;
      uart1_rxd_i    : in  std_ulogic := 'L'; -- UART1 receive data
      uart1_rts_o    : out std_ulogic;
      uart1_cts_i    : in  std_ulogic := 'L';
      -- SPI (available if IO_SPI_EN = true) --
      spi_clk_o      : out std_ulogic;
      spi_dat_o      : out std_ulogic;
      spi_dat_i      : in  std_ulogic := 'L';
      spi_csn_o      : out std_ulogic_vector(07 downto 0); -- SPI CS
      -- SDI (available if IO_SDI_EN = true) --
      sdi_clk_i      : in  std_ulogic := 'L';
      sdi_dat_o      : out std_ulogic;
      sdi_dat_i      : in  std_ulogic := 'L';
      sdi_csn_i      : in  std_ulogic := 'H';
      -- TWI (available if IO_TWI_EN = true) --
      twi_sda_i      : in  std_ulogic := 'H';
      twi_sda_o      : out std_ulogic;
      twi_scl_i      : in  std_ulogic := 'H';
      twi_scl_o      : out std_ulogic;
      -- 1-Wire Interface (available if IO_ONEWIRE_EN = true) --
      onewire_i      : in  std_ulogic := 'H';
      onewire_o      : out std_ulogic;
      -- PWM (available if IO_PWM_NUM_CH > 0) --
      pwm_o          : out std_ulogic_vector(11 downto 0); -- pwm channels
      -- Custom Functions Subsystem IO --
      cfs_in_i       : in  std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L');
      cfs_out_o      : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
      -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
      neoled_o       : out std_ulogic;
      -- Machine timer system time (available if IO_MTIME_EN = true) --
      mtime_time_o   : out std_ulogic_vector(63 downto 0);
      -- GPTMR timer capture (available if IO_GPTMR_EN = true) --
      gptmr_trig_i   : in  std_ulogic := 'L';
      -- External platform interrupts (available if XIRQ_NUM_CH > 0) --
      xirq_i         : in  std_ulogic_vector(31 downto 0) := (others => 'L');
      -- CPU Interrupts --
      mtime_irq_i    : in  std_ulogic := 'L';
      msw_irq_i      : in  std_ulogic := 'L';
      mext_irq_i     : in  std_ulogic := 'L'
    );
  end component;

end neorv32_package;

package body neorv32_package is

-- ****************************************************************************************************************************
-- Helper Functions
-- ****************************************************************************************************************************

  -- Minimal required number of bits to represent <input> numbers ---------------------------
  -- -------------------------------------------------------------------------------------------
  function index_size_f(input : natural) return natural is
  begin
    for i in 0 to natural'high loop
      if (2**i >= input) then
        return i;
      end if;
    end loop;
    return 0;
  end function index_size_f;

  -- Conditional select integer -------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer is
  begin
    if cond then
      return val_t;
    else
      return val_f;
    end if;
  end function cond_sel_int_f;

  -- Conditional select natural -------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural is
  begin
    if cond then
      return val_t;
    else
      return val_f;
    end if;
  end function cond_sel_natural_f;

  -- Conditional select std_ulogic_vector ---------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector is
  begin
    if cond then
      return val_t;
    else
      return val_f;
    end if;
  end function cond_sel_suv_f;

  -- Conditional select string --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string is
  begin
    if cond then
      return val_t;
    else
      return val_f;
    end if;
  end function cond_sel_string_f;

  -- Convert boolean to std_ulogic ----------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function bool_to_ulogic_f(cond : boolean) return std_ulogic is
  begin
    if cond then
      return '1';
    else
      return '0';
    end if;
  end function bool_to_ulogic_f;

  -- Convert binary to gray -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function bin_to_gray_f(input : std_ulogic_vector) return std_ulogic_vector is
    variable tmp_v : std_ulogic_vector(input'range);
  begin
    tmp_v(input'length-1) := input(input'length-1); -- keep MSB
    for i in input'length-2 downto 0 loop
      tmp_v(i) := input(i) xor input(i+1);
    end loop;
    return tmp_v;
  end function bin_to_gray_f;

  -- Convert gray to binary -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function gray_to_bin_f(input : std_ulogic_vector) return std_ulogic_vector is
    variable tmp_v : std_ulogic_vector(input'range);
  begin
    tmp_v(input'length-1) := input(input'length-1); -- keep MSB
    for i in input'length-2 downto 0 loop
      tmp_v(i) := tmp_v(i+1) xor input(i);
    end loop;
    return tmp_v;
  end function gray_to_bin_f;

  -- OR all bits ----------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function or_reduce_f(input : std_ulogic_vector) return std_ulogic is
    variable tmp_v : std_ulogic;
  begin
    tmp_v := '0';
    for i in input'range loop
      tmp_v := tmp_v or input(i);
    end loop;
    return tmp_v;
  end function or_reduce_f;

  -- AND all bits ---------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function and_reduce_f(input : std_ulogic_vector) return std_ulogic is
    variable tmp_v : std_ulogic;
  begin
    tmp_v := '1';
    for i in input'range loop
      tmp_v := tmp_v and input(i);
    end loop;
    return tmp_v;
  end function and_reduce_f;

  -- XOR all bits ---------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function xor_reduce_f(input : std_ulogic_vector) return std_ulogic is
    variable tmp_v : std_ulogic;
  begin
    tmp_v := '0';
    for i in input'range loop
      tmp_v := tmp_v xor input(i);
    end loop;
    return tmp_v;
  end function xor_reduce_f;

  -- Check if std_ulogic is not '1' or '0' --------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function su_undefined_f(input : std_ulogic) return boolean is
  begin
    case input is
      when '1' | '0' => return false;
      when others    => return true;
    end case;
  end function su_undefined_f;

  -- Convert std_ulogic_vector to lowercase HEX char ----------------------------------------
  -- -------------------------------------------------------------------------------------------
  function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character is
    variable hex_v : string(1 to 16);
  begin
    hex_v := "0123456789abcdef";
    if su_undefined_f(input(3)) or su_undefined_f(input(2)) or
       su_undefined_f(input(1)) or su_undefined_f(input(0)) then
      return '?';
    else
      return hex_v(to_integer(unsigned(input)) + 1);
    end if;
  end function to_hexchar_f;

  -- Convert 32-bit std_ulogic_vector to hex string -----------------------------------------
  -- -------------------------------------------------------------------------------------------
  function to_hstring32_f(input : std_ulogic_vector(31 downto 0)) return string is
    variable res_v : string(1 to 8);
  begin
    for i in 7 downto 0 loop
      res_v(8-i) := to_hexchar_f(input(i*4+3 downto i*4+0));
    end loop;
    return res_v;
  end function to_hstring32_f;

  -- Bit reversal ---------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector is
    variable output_v : std_ulogic_vector(input'range);
  begin
    for i in 0 to input'length-1 loop
      output_v(input'length-i-1) := input(i);
    end loop;
    return output_v;
  end function bit_rev_f;

  -- Test if input number is a power of two -------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function is_power_of_two_f(input : natural) return boolean is
    variable tmp : unsigned(31 downto 0);
  begin
    if (input = 0) then
      return false;
    elsif (input = 1) then
      return true;
    else
      tmp := to_unsigned(input, 32);
      if ((tmp and (tmp - 1)) = 0) then
        return true;
      else
        return false;
      end if;
    end if;
  end function is_power_of_two_f;

  -- Swap all bytes of a 32-bit word (endianness conversion) --------------------------------
  -- -------------------------------------------------------------------------------------------
  function bswap32_f(input : std_ulogic_vector) return std_ulogic_vector is
    variable output_v : std_ulogic_vector(input'range);
  begin
    output_v(07 downto 00) := input(31 downto 24);
    output_v(15 downto 08) := input(23 downto 16);
    output_v(23 downto 16) := input(15 downto 08);
    output_v(31 downto 24) := input(07 downto 00);
    return output_v;
  end function bswap32_f;

  -- Population count (number of set bits) --------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function popcount_f(input : std_ulogic_vector) return natural is
    variable cnt_v : natural range 0 to input'length;
  begin
    cnt_v := 0;
    for i in input'length-1 downto 0 loop
      if (input(i) = '1') then
        cnt_v := cnt_v + 1;
      end if;
    end loop;
    return cnt_v;
  end function popcount_f;

  -- Count leading zeros --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  function leading_zeros_f(input : std_ulogic_vector) return natural is
    variable cnt_v : natural range 0 to input'length;
  begin
    cnt_v := 0;
    for i in input'length-1 downto 0 loop
      if (input(i) = '0') then
        cnt_v := cnt_v + 1;
      else
        exit;
      end if;
    end loop;
    return cnt_v;
  end function leading_zeros_f;

  -- Initialize mem32_t array from another mem32_t array ------------------------------------
  -- -------------------------------------------------------------------------------------------
  impure function mem32_init_f(init : mem32_t; depth : natural) return mem32_t is
    variable mem_v : mem32_t(0 to depth-1);
  begin
    mem_v := (others => (others => '0')); -- [IMPORTANT] make sure remaining memory entries are set to zero
    if (init'length > depth) then
      return mem_v;
    end if;
    for i in 0 to init'length-1 loop -- initialize only in range of source data array
      mem_v(i) := init(i);
    end loop;
    return mem_v;
  end function mem32_init_f;


end neorv32_package;

-- ****************************************************************************************************************************
-- Additional Packages
-- ****************************************************************************************************************************

  -- Prototype Definition: bootloader_init_image --------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- > memory content in 'neorv32_bootloader_image.vhd', auto-generated by 'image_gen'
  -- > used by 'neorv32_boot_rom.vhd'
  -- > enables body-only recompile in case of firmware change (NEORV32 PR #338)

library ieee;
use ieee.std_logic_1164.all;

library neorv32;
use neorv32.neorv32_package.all;

package neorv32_bootloader_image is
  constant bootloader_init_image : mem32_t;
end neorv32_bootloader_image;


  -- Prototype Definition: neorv32_application_image ----------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- > memory content in 'neorv32_application_image.vhd', auto-generated by 'image_gen'
  -- > used by 'mem/neorv32_imem.*.vhd'
  -- > enables body-only recompile in case of firmware change (NEORV32 PR #338)

library ieee;
use ieee.std_logic_1164.all;

library neorv32;
use neorv32.neorv32_package.all;

package neorv32_application_image is
  constant application_init_image : mem32_t;
end neorv32_application_image;
