<<<
:sectnums:
==== Instruction Memory (IMEM)

[cols="<3,<3,<4"]
[grid="none"]
|=======================
| Hardware source files:  | neorv32_imem.vhd       | generic processor-internal instruction memory (RAM or ROM)
|                         | neorv32_imem_image.vhd | memory initialization image (VHDL package)
|                         | neorv32_imem_ram.vhd   | RAM component (primitive/IP wrapper)
|                         | neorv32_imem_rom.vhd   | ROM component (primitive/IP wrapper)
| Software driver files:  | none                   |
| Top entity ports:       | none                   |
| Configuration generics: | `IMEM_EN`              | implement IMEM when `true`
|                         | `IMEM_BASE`            | 32-bit base address (naturally aligned to IMEM size)
|                         | `IMEM_SIZE`            | IMEM size in bytes (use a power of 2)
|                         | `IMEM_OUTREG_EN`       | add IMEM output register stage
|                         | `BOOT_MODE_SELECT`     | implement IMEM as ROM when `BOOT_MODE_SELECT` = 2; see <<_boot_configuration>>
| CPU interrupts:         | none                   |
|=======================

**Key Features**

* Burst-capable tightly-coupled on-chip instruction memory
* Configurable RAM size
* Accessible at the byte level
* Mapped to memory primitives
* Optional output register for improved timing
* Can be implemented as pre-initialized ROM containing application firmware


**Overview**

Implementation of the processor-internal instruction memory is enabled by the processor's
`IMEM_EN` generic. The total memory size in bytes is defined via the `IMEM_SIZE` generic.
Only sizes that are powers of two are supported. If enabled, the IMEM is mapped to base
address `0x00000000` by default (see section <<_address_space>>).

.Custom IMEM Base Address
[IMPORTANT]
The base address of the IMEM can be customized via the `IMEM_BASE` generic. Please note that
the selected address must be naturally aligned to the IMEM size (`IMEM_SIZE`) and that there must
be no overlap with other sections of the internal <<_address_space>> (internal DMEM if enabled
and the internal IO/peripheral address space). Any non-default address must also be passed to the
<<_linker_script>> (e.g. `USER_FLAGS += -Wl,--defsym,__neorv32_rom_base=<IMEM_BASE>`).

By default the IMEM is implemented as true RAM so the content can be modified during run time.
Alternatively, the IMEM can be implemented as **pre-initialized read-only memory (ROM)**, so the
processor can directly boot from it after reset. This option is configured via the `BOOT_MODE_SELECT`
generic. See section <<_boot_configuration>> for more information. If the IMEM is implemented as ROM
any write attempt to it will raise a _store access fault_ exception.

The software framework provides an option to generate and override the default VHDL initialization
file `rtl/core/neorv32_imem_image.vhd`, which is automatically inserted into the IMEM (see
<<_makefile_targets>>. If the IMEM is implemented as RAM (default), the memory block will not be
initialized at all.

.Output Register Stage
[TIP]
An optional output register stage can be enabled via `IMEM_OUTREG_EN`. For FPGA targets this might improve
mapping/timing results. Note that this option will increase the read latency by one clock cycle. Write accesses
are not affected by this at all.

.Retrieve Memory Configuration by Software
[TIP]
Software can retrieve the DMEM size from the <<_sysinfo_miscellaneous_configuration>> register.

.Memory Primitives
[TIP]
The memory's memory core is encapsulated as individual wrapper (`neorv32_imem_ram.vhd` / `neorv32_imem_ram.vhd`)
that can be replaced by a technology-specific IP. All interface ports provide static signal widths to ease replacement.
