diff --git a/CHANGELOG.md b/CHANGELOG.md index 591ee9d2b..f12a20214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,9 @@ Releases are linked and highlighted. The latest release is A list of all releases can be found [here](https://github.com/stnolting/neorv32/releases). Starting with version `1.5.7` this project uses [semantic versioning](https://semver.org). -The _version identifier_ uses an additional **custom** element (`MAJOR.MINOR.PATCH.custom`) -to track _individual_ changes. The identifier number is incremented with every core RTL -modification and also by major framework modifications. +The **version identifier** uses an additional custom element (`MAJOR.MINOR.PATCH.custom`) +to track individual changes. The identifier is incremented by every core RTL modification +and also by major software/project changes. The version identifier is globally defined by the `hw_version_c` constant in the main VHDL [package file](https://github.com/stnolting/neorv32/blob/main/rtl/core/neorv32_package.vhd). @@ -32,6 +32,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12 | Date (*dd.mm.yyyy*) | Version | Comment | |:-------------------:|:-------:|:--------| +| 27.07.2023 | 1.8.7.2 | :bug: make sure that IMEM/DMEM size is always a power of two; [#658](https://github.com/stnolting/neorv32/pull/658) | | 27.07.2023 | 1.8.7.1 | :warning: remove `CUSTOM_ID` generic; cleanup and re-layout `NEORV32_SYSINFO.SOC` bits; (:bug:) fix gateway's generics (`positive` -> `natural` as these generics are allowed to be zero); [#657](https://github.com/stnolting/neorv32/pull/657) | | 26.07.2023 | [**:rocket:1.8.7**](https://github.com/stnolting/neorv32/releases/tag/v1.8.7) | **New release** | | 24.07.2023 | 1.8.6.10 | :bug: fixing some LR/SC design flaws; [#654](https://github.com/stnolting/neorv32/pull/654) | diff --git a/docs/datasheet/soc.adoc b/docs/datasheet/soc.adoc index 39595e25f..dc49082a6 100644 --- a/docs/datasheet/soc.adoc +++ b/docs/datasheet/soc.adoc @@ -232,10 +232,10 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt | `AMO_RVS_GRANULARITY` | natural | 4 | Size in bytes, has to be a power of 2, min 4. 4+^| **Internal <<_instruction_memory_imem>>** | `MEM_INT_IMEM_EN` | boolean | false | Implement the processor-internal instruction memory. -| `MEM_INT_IMEM_SIZE` | natural | 16*1024 | Size in bytes of the processor internal instruction memory. +| `MEM_INT_IMEM_SIZE` | natural | 16*1024 | Size in bytes of the processor internal instruction memory (use a power of 2). 4+^| **Internal <<_data_memory_dmem>>** | `MEM_INT_DMEM_EN` | boolean | false | Implement the processor-internal data memory. -| `MEM_INT_DMEM_SIZE` | natural | 8*1024 | Size in bytes of the processor-internal data memory. +| `MEM_INT_DMEM_SIZE` | natural | 8*1024 | Size in bytes of the processor-internal data memory (use a power of 2). 4+^| **<<_processor_internal_instruction_cache_icache>>** | `ICACHE_EN` | boolean | false | Implement the instruction cache. | `ICACHE_NUM_BLOCKS` | natural | 4 | Number of blocks ("pages" or "lines") Has to be a power of two. diff --git a/docs/datasheet/soc_dmem.adoc b/docs/datasheet/soc_dmem.adoc index 201bcf5b3..343909aee 100644 --- a/docs/datasheet/soc_dmem.adoc +++ b/docs/datasheet/soc_dmem.adoc @@ -10,7 +10,7 @@ | Software driver file(s): | none | _implicitly used_ | Top entity port: | none | | Configuration generics: | `MEM_INT_DMEM_EN` | implement processor-internal DMEM when `true` -| | `MEM_INT_DMEM_SIZE` | DMEM size in bytes +| | `MEM_INT_DMEM_SIZE` | DMEM size in bytes (use a power of 2) | CPU interrupts: | none | |======================= @@ -20,6 +20,12 @@ the memory is mapped into the data memory space and located right at the beginni space (default `dspace_base_c` = 0x80000000), see <<_address_space>>. The DMEM is always implemented as true RAM. +.Memory Size +[IMPORTANT] +If the configured memory size (via the `MEM_INT_IMEM_SIZE` generic) is **not** a power of two the actual memory +size will be auto-adjusted to the next power of two (e.g. configuring a memory size of 60kB will result in a +physical memory size of 64kB). + .VHDL Source File [NOTE] The actual DMEM is split into two design files: a plain entity definition (`neorv32_dmem.entity.vhd`) and the actual diff --git a/docs/datasheet/soc_imem.adoc b/docs/datasheet/soc_imem.adoc index 1f1fb14b2..5b1d0b981 100644 --- a/docs/datasheet/soc_imem.adoc +++ b/docs/datasheet/soc_imem.adoc @@ -10,7 +10,7 @@ | Software driver file(s): | none | _implicitly used_ | Top entity port: | none | | Configuration generics: | `MEM_INT_IMEM_EN` | implement processor-internal IMEM when `true` -| | `MEM_INT_IMEM_SIZE` | IMEM size in bytes +| | `MEM_INT_IMEM_SIZE` | IMEM size in bytes (use a power of 2) | | `INT_BOOTLOADER_EN` | use internal bootloader when `true` (implements IMEM as _uninitialized_ RAM, otherwise the IMEM is implemented an _pre-intialized_ ROM) | CPU interrupts: | none | |======================= @@ -31,6 +31,12 @@ image. The compiler toolchain provides an option to generate and override the de `rtl/core/neorv32_application_image.vhd`, which is automatically inserted into the IMEM. If the IMEM is implemented as RAM (default), the memory will **not be initialized at all**. +.Memory Size +[IMPORTANT] +If the configured memory size (via the `MEM_INT_IMEM_SIZE` generic) is **not** a power of two the actual memory +size will be auto-adjusted to the next power of two (e.g. configuring a memory size of 60kB will result in a +physical memory size of 64kB). + .VHDL Source File [NOTE] The actual IMEM is split into two design files: a plain entity definition (`neorv32_imem.entity.vhd`) and the actual diff --git a/rtl/core/mem/neorv32_dmem.default.vhd b/rtl/core/mem/neorv32_dmem.default.vhd index f08b7b9d9..92fca2718 100644 --- a/rtl/core/mem/neorv32_dmem.default.vhd +++ b/rtl/core/mem/neorv32_dmem.default.vhd @@ -68,6 +68,9 @@ begin assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic DMEM." severity note; + assert not (is_power_of_two_f(DMEM_SIZE) = false) report + "NEORV32 PROCESSOR CONFIG ERROR: Internal DMEM size has to be a power of two!" severity error; + assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) & " bytes)." severity note; diff --git a/rtl/core/mem/neorv32_dmem.legacy.vhd b/rtl/core/mem/neorv32_dmem.legacy.vhd index fb105df30..729cb4df1 100644 --- a/rtl/core/mem/neorv32_dmem.legacy.vhd +++ b/rtl/core/mem/neorv32_dmem.legacy.vhd @@ -69,6 +69,9 @@ begin assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using legacy HDL style DMEM." severity note; + assert not (is_power_of_two_f(DMEM_SIZE) = false) report + "NEORV32 PROCESSOR CONFIG ERROR: Internal DMEM size has to be a power of two!" severity error; + assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) & " bytes)." severity note; diff --git a/rtl/core/mem/neorv32_imem.default.vhd b/rtl/core/mem/neorv32_imem.default.vhd index 8dbd08448..6d2f10923 100644 --- a/rtl/core/mem/neorv32_imem.default.vhd +++ b/rtl/core/mem/neorv32_imem.default.vhd @@ -85,6 +85,9 @@ begin assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic IMEM." severity note; + assert not (is_power_of_two_f(IMEM_SIZE) = false) report + "NEORV32 PROCESSOR CONFIG ERROR: Internal IMEM size has to be a power of two!" severity error; + assert not (IMEM_AS_IROM = true) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) & " bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note; diff --git a/rtl/core/mem/neorv32_imem.legacy.vhd b/rtl/core/mem/neorv32_imem.legacy.vhd index 0a5a148cb..ad559f661 100644 --- a/rtl/core/mem/neorv32_imem.legacy.vhd +++ b/rtl/core/mem/neorv32_imem.legacy.vhd @@ -86,6 +86,9 @@ begin assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using legacy HDL style IMEM." severity note; + assert not (is_power_of_two_f(IMEM_SIZE) = false) report + "NEORV32 PROCESSOR CONFIG ERROR: Internal IMEM size has to be a power of two!" severity error; + assert not (IMEM_AS_IROM = true) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) & " bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note; diff --git a/rtl/core/neorv32_dmem.entity.vhd b/rtl/core/neorv32_dmem.entity.vhd index 8e064ed00..9711754c6 100644 --- a/rtl/core/neorv32_dmem.entity.vhd +++ b/rtl/core/neorv32_dmem.entity.vhd @@ -41,7 +41,7 @@ use neorv32.neorv32_package.all; entity neorv32_dmem is generic ( - DMEM_SIZE : natural -- processor-internal instruction memory size in bytes + DMEM_SIZE : natural -- processor-internal instruction memory size in bytes, has to be a power of 2 ); port ( clk_i : in std_ulogic; -- global clock line diff --git a/rtl/core/neorv32_imem.entity.vhd b/rtl/core/neorv32_imem.entity.vhd index 6e9e63e4f..b80a82d8e 100644 --- a/rtl/core/neorv32_imem.entity.vhd +++ b/rtl/core/neorv32_imem.entity.vhd @@ -41,7 +41,7 @@ use neorv32.neorv32_package.all; entity neorv32_imem is generic ( - IMEM_SIZE : natural; -- processor-internal instruction memory size in bytes + IMEM_SIZE : natural; -- processor-internal instruction memory size in bytes, has to be a power of 2 IMEM_AS_IROM : boolean -- implement IMEM as pre-initialized read-only memory? ); port ( diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index 759703fd1..f5edd4558 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -56,7 +56,7 @@ package neorv32_package is -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080701"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080702"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width, do not change! @@ -919,10 +919,10 @@ package neorv32_package is AMO_RVS_GRANULARITY : natural := 4; -- size in bytes, has to be a power of 2, min 4 -- Internal Instruction memory (IMEM) -- MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory - MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes + MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes (use a power of 2) -- Internal Data memory (DMEM) -- MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory - MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes + MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes (use a power of 2) -- Internal Instruction Cache (iCACHE) -- ICACHE_EN : boolean := false; -- implement instruction cache ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2 diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd index 3d59b28f2..31d2e5bf3 100644 --- a/rtl/core/neorv32_top.vhd +++ b/rtl/core/neorv32_top.vhd @@ -88,11 +88,11 @@ entity neorv32_top is -- Internal Instruction memory (IMEM) -- MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory - MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes + MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes (use a power of 2) -- Internal Data memory (DMEM) -- MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory - MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes + MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes (use a power of 2) -- Internal Instruction Cache (iCACHE) -- ICACHE_EN : boolean := false; -- implement instruction cache @@ -261,6 +261,15 @@ architecture neorv32_top_rtl of neorv32_top is constant io_xirq_en_c : boolean := boolean(XIRQ_NUM_CH > 0); constant io_pwm_en_c : boolean := boolean(IO_PWM_NUM_CH > 0); + -- make sure physical memory sizes are a power of two -- + constant imem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_IMEM_SIZE); + constant imem_size_pow2_c : natural := 2**index_size_f(MEM_INT_IMEM_SIZE); + constant imem_size_c : natural := cond_sel_natural_f(imem_size_valid_c, MEM_INT_IMEM_SIZE, imem_size_pow2_c); + -- + constant dmem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_DMEM_SIZE); + constant dmem_size_pow2_c : natural := 2**index_size_f(MEM_INT_DMEM_SIZE); + constant dmem_size_c : natural := cond_sel_natural_f(dmem_size_valid_c, MEM_INT_DMEM_SIZE, dmem_size_pow2_c); + -- reset generator -- signal rstn_ext_sreg, rstn_int_sreg : std_ulogic_vector(3 downto 0); signal rstn_ext, rstn_int, rstn_wdt : std_ulogic; @@ -381,11 +390,13 @@ begin assert not ((INT_BOOTLOADER_EN = false) and (MEM_INT_IMEM_EN = false)) report "NEORV32 PROCESSOR CONFIG NOTE: Boot configuration = direct boot from memory (processor-external memory)." severity note; - -- memory layout -- - assert not (mem_ispace_base_c /= x"00000000") report - "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for INSTRUCTION ADDRESS SPACE. Make sure this is sync with the software framework." severity warning; - assert not (mem_dspace_base_c /= x"80000000") report - "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for DATA ADDRESS SPACE. Make sure this is sync with the software framework." severity warning; + -- internal memory sizes -- + assert not ((imem_size_valid_c = false) and (MEM_INT_IMEM_EN = true)) report + "NEORV32 PROCESSOR CONFIG WARNING: Configured internal IMEM size (" & natural'image(MEM_INT_IMEM_SIZE) & " bytes) is not a power of two. " & + "Auto-increasing memory size to the next power of two (" & natural'image(imem_size_c) & " bytes)" severity warning; + assert not ((dmem_size_valid_c = false) and (MEM_INT_DMEM_EN = true)) report + "NEORV32 PROCESSOR CONFIG WARNING: Configured internal DMEM size (" & natural'image(MEM_INT_DMEM_SIZE) & " bytes) is not a power of two. " & + "Auto-increasing memory size to the next power of two (" & natural'image(dmem_size_c) & " bytes)" severity warning; -- on-chip debugger -- assert not (ON_CHIP_DEBUGGER_EN = true) report @@ -719,11 +730,11 @@ begin -- IMEM port -- IMEM_ENABLE => MEM_INT_IMEM_EN, IMEM_BASE => mem_ispace_base_c, - IMEM_SIZE => MEM_INT_IMEM_SIZE, + IMEM_SIZE => imem_size_c, -- DMEM port -- DMEM_ENABLE => MEM_INT_DMEM_EN, DMEM_BASE => mem_dspace_base_c, - DMEM_SIZE => MEM_INT_DMEM_SIZE, + DMEM_SIZE => dmem_size_c, -- XIP port -- XIP_ENABLE => IO_XIP_EN, XIP_BASE => mem_xip_base_c, @@ -773,10 +784,10 @@ begin -- Processor-Internal Instruction Memory (IMEM) ------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_int_imem_inst_true: - if (MEM_INT_IMEM_EN = true) and (MEM_INT_IMEM_SIZE > 0) generate + if (MEM_INT_IMEM_EN = true) and (imem_size_c > 0) generate neorv32_int_imem_inst: entity neorv32.neorv32_imem generic map ( - IMEM_SIZE => MEM_INT_IMEM_SIZE, + IMEM_SIZE => imem_size_c, IMEM_AS_IROM => imem_as_rom_c ) port map ( @@ -787,7 +798,7 @@ begin end generate; neorv32_int_imem_inst_false: - if (MEM_INT_IMEM_EN = false) or (MEM_INT_IMEM_SIZE = 0) generate + if (MEM_INT_IMEM_EN = false) or (imem_size_c = 0) generate imem_rsp <= rsp_terminate_c; end generate; @@ -795,10 +806,10 @@ begin -- Processor-Internal Data Memory (DMEM) -------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_int_dmem_inst_true: - if (MEM_INT_DMEM_EN = true) and (MEM_INT_DMEM_SIZE > 0) generate + if (MEM_INT_DMEM_EN = true) and (dmem_size_c > 0) generate neorv32_int_dmem_inst: entity neorv32.neorv32_dmem generic map ( - DMEM_SIZE => MEM_INT_DMEM_SIZE + DMEM_SIZE => dmem_size_c ) port map ( clk_i => clk_i, @@ -808,7 +819,7 @@ begin end generate; neorv32_int_dmem_inst_false: - if (MEM_INT_DMEM_EN = false) or (MEM_INT_DMEM_SIZE = 0) generate + if (MEM_INT_DMEM_EN = false) or (dmem_size_c = 0) generate dmem_rsp <= rsp_terminate_c; end generate; @@ -1473,10 +1484,10 @@ begin PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- internal Instruction memory -- MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, - MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, + MEM_INT_IMEM_SIZE => imem_size_c, -- Internal Data memory -- MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, - MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, + MEM_INT_DMEM_SIZE => dmem_size_c, -- Instruction cache -- ICACHE_EN => ICACHE_EN, ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS,