Skip to content

Commit 32e2065

Browse files
authored
⚠️ Rework IO/peripheral address space (#1126)
2 parents 8313306 + 0eefce4 commit 32e2065

40 files changed

+724
-768
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
2929

3030
| Date | Version | Comment | Ticket |
3131
|:----:|:-------:|:--------|:------:|
32+
| 23.12.2024 | 1.10.7.9 | :warning: rework IO/peripheral address space; :sparkles: increase device size from 256 bytes to 64kB | [#1126](https://github.com/stnolting/neorv32/pull/1126) |
3233
| 22.12.2024 | 1.10.7.8 | :warning: rename CPU tuning options / generics | [#1125](https://github.com/stnolting/neorv32/pull/1125) |
3334
| 22.12.2024 | 1.10.7.7 | :warning: move clock gating switch from processor top to CPU clock; `CLOCK_GATING_EN` is now a CPU tuning option | [#1124](https://github.com/stnolting/neorv32/pull/1124) |
3435
| 21.12.2024 | 1.10.7.6 | minor rtl cleanups and optimizations | [#1123](https://github.com/stnolting/neorv32/pull/1123) |

docs/datasheet/soc.adoc

Lines changed: 55 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -468,55 +468,47 @@ table (the channel number also corresponds to the according FIRQ priority: 0 = h
468468
=== Address Space
469469

470470
As a 32-bit architecture the NEORV32 can access a 4GB physical address space. By default, this address space is
471-
split into six main regions. Each region provides specific _physical memory attributes_ ("PMAs") that define
472-
the access capabilities (`rwxac`; `r` = read permission, `w` = write permission, `x` - execute permission,
473-
`a` = atomic access support, `c` = cached CPU access, `p` = privileged access only).
471+
split into four main regions. All accesses to "unmapped" addresses (a.k.a. "the void") are redirected to the
472+
<<_processor_external_bus_interface_xbus>>. For example, if the internal IMEM is disabled, the accesses to the
473+
_entire_ address space between `0x00000000` and `0x7FFFFFFF` are converted into XBUS requests. If the XBUS interface
474+
is not enabled any access to the void will raise a bus error exception.
474475

475476
.NEORV32 Processor Address Space (Default Configuration)
476477
image::address_space.png[900]
477478

478-
.The "Void" (Unmapped Addresses)
479-
[NOTE]
480-
All accesses to "unmapped" addresses (= "void") are redirected to the <<_processor_external_bus_interface_xbus>>.
481-
For example, if the internal IMEM is disabled, the accesses to the _entire_ address space between `0x00000000` and
482-
`0x7FFFFFFF` are converted into XBUS requests. If the XBUS interface is not enabled any access to the void will
483-
raise a bus error exception.
479+
Each region provides specific _physical memory attributes_ ("PMAs") that define the access capabilities (`rwxac`;
480+
`r` = read access, `w` = write access, `x` - execute access, `a` = atomic access, `c` = cached CPU access).
481+
482+
.Custom PMAs
483+
[TIP]
484+
Custom physical memory attributes enforced by the CPU's _physcial memory protection_ (<<_smpmp_isa_extension>>)
485+
can be used to further constrain the physical memory attributes.
484486

485487
.Main Address Regions
486488
[cols="<1,^4,^2,<7"]
487489
[options="header",grid="rows"]
488490
|=======================
489-
| # | Region | PMAs | Description
490-
| 1 | Internal IMEM address space | `rwxac-` | For instructions (=code) and constants; mapped to the internal <<_instruction_memory_imem>>.
491-
| 2 | Internal DMEM address space | `rwxac-` | For application runtime data (heap, stack, etc.); mapped to the internal <<_data_memory_dmem>>).
492-
| 3 | Memory-mapped XIP flash | `r-xac-` | Memory-mapped access to the <<_execute_in_place_module_xip>> SPI flash.
493-
| 4 | Bootloader address space | `r-xa-p` | Read-only memory for the internal <<_bootloader_rom_bootrom>> containing the default <<_bootloader>>.
494-
| 5 | IO/peripheral address space | `rwxa-p` | Processor-internal peripherals / IO devices.
495-
| 6 | The "**void**" | `rwxac-` | Unmapped address space. All accesses to this region(s) are redirected to the <<_processor_external_bus_interface_xbus>> (if implemented).
491+
| # | Region | PMAs | Description
492+
| 1 | Internal IMEM address space | `rwxac` | For instructions / code and constants; mapped to the internal <<_instruction_memory_imem>> if implemented.
493+
| 2 | Internal DMEM address space | `rwxac` | For application runtime data (heap, stack, etc.); mapped to the internal <<_data_memory_dmem>>) if implemented.
494+
| 3 | Memory-mapped XIP flash | `r-xac` | Transparent memory-mapped access to an external <<_execute_in_place_module_xip>> SPI flash.
495+
| 4 | IO/peripheral address space | `rwxa-` | Processor-internal peripherals / IO devices including the <<_bootloader_rom_bootrom>>.
496+
| - | The "**void**" | `rwxa[c]` | Unmapped address space. All accesses to this region(s) are redirected to the <<_processor_external_bus_interface_xbus>> if implemented.
496497
|=======================
497498

498-
.Privileged IO and BOOTROM Access Only
499-
[IMPORTANT]
500-
Only privileged accesses (M-mode) to the IO/peripheral and bootloader address spaces are allowed.
501-
If an unprivileged application tries to access this address space a bus access error exception is raised.
502-
503-
.Custom PMAs
504-
[TIP]
505-
Custom physical memory attributes enforced by the CPU's _physcial memory protection_ (<<_smpmp_isa_extension>>)
506-
can be used to further constrain the physical memory attributes.
507-
508499

509500
:sectnums:
510501
==== Bus System
511502

512-
The CPU can access all of the 32-bit address space from the instruction fetch interface and also from the data access
513-
interface. Both CPU interfaces can be equipped with optional caches (<<_processor_internal_data_cache_dcache>> and
514-
<<_processor_internal_instruction_cache_icache>>). The two CPU interfaces are multiplexed by a simple bus switch into
515-
a _single processor-internal bus_. Optionally, this bus is further switched by another instance of the bus switch so the
516-
<<_direct_memory_access_controller_dma>> controller can also access the entire address space. Accesses via the
517-
resulting SoC bus are split by the <<_bus_gateway>> that redirects accesses to the according main address regions
518-
(see table above). Accesses to the processor-internal IO/peripheral devices are further redirected via a
519-
dedicated <<_io_switch>>.
503+
The CPU provides individual interfaces for instruction fetch and data access. It can can access all of the 32-bit
504+
address space from each of the interface. Both of them can be equipped with optional caches (<<_processor_internal_data_cache_dcache>>
505+
and <<_processor_internal_instruction_cache_icache>>).
506+
507+
The two CPU interfaces are multiplexed by a simple bus switch into a _single processor-internal bus_. Optionally,
508+
this bus is further multiplexed by another instance of the bus switch so the <<_direct_memory_access_controller_dma>>
509+
controller can also access the entire address space. Accesses via the resulting SoC bus are split by the <<_bus_gateway>>
510+
that redirects accesses to the according main address regions (see table above). Accesses to the processor-internal
511+
IO/peripheral devices are further redirected via a dedicated <<_io_switch>>.
520512

521513
.Processor-Internal Bus Architecture
522514
image::neorv32_bus.png[1300]
@@ -533,31 +525,27 @@ See sections CPU <<_architecture>> and <<_bus_interface>> for more information r
533525
:sectnums:
534526
==== Bus Gateway
535527

536-
The central bus gateway serves two purposes: **redirect** core accesses to the according modules (e.g. memory accesses
537-
vs. memory-mapped IO accesses) and **monitor** all bus transactions. The redirection of access request is based on a
528+
The central bus gateway serves two purposes: it **redirects** accesses to the according modules (e.g. memory accesses
529+
vs. memory-mapped IO accesses) and also **monitors** all bus transactions. The redirection of access request is based on a
538530
customizable memory map implemented via VHDL constants in the main package file (`rtl/core/neorv323_package.vhd`):
539531

540532
.Main Address Regions Configuration in the VHDL Package File
541533
[source,vhdl]
542534
----
543535
-- Main Address Regions ---
544-
constant mem_imem_base_c : std_ulogic_vector(31 downto 0) := x"00000000";
545-
constant mem_dmem_base_c : std_ulogic_vector(31 downto 0) := x"80000000";
546-
constant mem_xip_base_c : std_ulogic_vector(31 downto 0) := x"e0000000";
536+
constant mem_imem_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- IMEM size via generic
537+
constant mem_dmem_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- DMEM size via generic
538+
constant mem_xip_base_c : std_ulogic_vector(31 downto 0) := x"e0000000"; -- page (4 MSBs) only!
547539
constant mem_xip_size_c : natural := 256*1024*1024;
548-
constant mem_boot_base_c : std_ulogic_vector(31 downto 0) := x"ffffc000";
549-
constant mem_boot_size_c : natural := 8*1024;
550-
constant mem_io_base_c : std_ulogic_vector(31 downto 0) := x"ffffe000";
551-
constant mem_io_size_c : natural := 8*1024;
540+
constant mem_io_base_c : std_ulogic_vector(31 downto 0) := x"ffe00000";
541+
constant mem_io_size_c : natural := 32*64*1024; -- = 32 * iodev_size_c
552542
----
553543

554-
Besides the delegation of bus requests the gateway also implements a bus monitor (aka "the bus keeper") that tracks all
555-
active bus transactions to ensure _safe_ and _deterministic_ operations.
556-
557-
Whenever a memory-mapped device is accessed (a real memory, a memory-mapped IO or some processor-external module) the bus
558-
monitor starts an internal timer. The accessed module has to respond ("ACK") to the bus request within a specific
559-
**time window**. This time window is defined by a global constant in the processor's VHDL package file
560-
(`rtl/core/neorv323_package.vhd`).
544+
Besides the redirecting of bus requests the gateway also implements a bus monitor (aka "the bus keeper") that tracks all
545+
active bus transactions to ensure _safe_ and _deterministic_ operations. Whenever a memory-mapped device is accessed (a
546+
real memory, a memory-mapped IO or some processor-external module) the bus monitor starts an internal countdown. The
547+
accessed module has to respond ("ACK") to the bus request within a bound **time window**. This time window is defined
548+
by a global constant in the processor's VHDL package file (`rtl/core/neorv323_package.vhd`).
561549

562550
.Internal Bus Timeout Configuration
563551
[source,vhdl]
@@ -662,12 +650,6 @@ constant base_io_slink_c : std_ulogic_vector(31 downto 0) := x"ffffec00";
662650
constant base_io_dma_c : std_ulogic_vector(31 downto 0) := x"ffffed00";
663651
----
664652

665-
.IO Access Latency
666-
[IMPORTANT]
667-
In order to shorten the critical path of the IO system, the IO switch contain a partial register stage that
668-
buffers the address bus. Hence, accesses to the processor-internal IO region requires an additional clock cycle
669-
to complete.
670-
671653

672654
<<<
673655
// ####################################################################################################################
@@ -737,30 +719,31 @@ need for an explicit initialization / executable upload.
737719
:sectnums:
738720
=== Processor-Internal Modules
739721

740-
.Privileged IO Access Only
722+
.Full-Word Write Accesses Only
741723
[IMPORTANT]
742-
Only privileged accesses (M-mode) to the IO/peripheral modules are allowed. If an unprivileged application
743-
tries to access this address space a bus access error exception is raised.
724+
All peripheral/IO devices should only be accessed in full-word mode (i.e. 32-bit).
725+
Byte or half-word (8/16-bit) write accesses might cause undefined behavior.
744726

745-
.Full-Word Write Accesses Only
746-
[NOTE]
747-
All peripheral/IO devices should only be written in full-word mode (i.e. 32-bit). Byte or half-word (8/16-bit) write accesses
748-
might cause undefined behavior.
727+
.IO Module Address Space
728+
[IMPORTAN]
729+
Each peripheral/IO module occupies an address space of 64kB bytes. Most devices do not fully utilize this
730+
address space and will _mirror_ the available memory-mapped registers across the entire 64kB address space.
731+
However, accessing memory-mapped registers other than the specified ones should be avoided.
749732

750-
.Writing to Read-Only Registers
733+
.Unimplemented Modules / Address Holes
751734
[NOTE]
752-
Unless otherwise specified, writing to registers that are listed as read-only does not trigger an exception.
753-
The write access is simply ignored by the corresponding hardware module.
735+
When accessing an IO device that hast not been implemented (disabled via the according generic)
736+
or when accessing an address that is actually unused, a load/store access fault exception is raised.
754737

755-
.IO Module's Address Space
738+
.Writing to Read-Only Registers
756739
[NOTE]
757-
Each peripheral/IO module occupies an address space of 256 bytes (64 words). Most devices do not fully utilize this address
758-
space and will simply _mirror_ the available interface registers across the entire 256 bytes of address space.
740+
Unless otherwise specified, writing to registers that are listed as read-only does not trigger an exception
741+
as the write access is simply ignored by the corresponding hardware module.
759742

760-
.Unimplemented Modules / Address Holes
743+
.IO Access Latency
761744
[NOTE]
762-
When accessing an IO device that hast not been implemented (disabled via the according generic)
763-
or when accessing an address that is actually unused, a load/store access fault exception is raised.
745+
In order to shorten the critical path of the IO system, the IO switch provides register stages for the request and
746+
response buses.Hence, accesses to the processor-internal IO region require two additional clock cycles to complete.
764747

765748
.Module Interrupts
766749
[NOTE]

docs/datasheet/soc_bootrom.adoc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919

2020
The boot ROM contains the executable image of the default NEORV32 <<_bootloader>>. When the
2121
<<_boot_configuration>> is set to _bootloader_ mode (0) via the `BOOT_MODE_SELECT` generic, the
22-
boot ROM is automatically enabled and the CPU boot address is automatically adjusted to the
23-
base address of the boot ROM.
22+
boot ROM is automatically enabled and the CPU boot address is adjusted to the base address of the boot ROM.
2423

2524
.Bootloader Image
2625
[IMPORTANT]
27-
The boot ROM is initialized during synthesis with the default bootloader image
28-
(`rtl/core/neorv32_bootloader_image.vhd`). Note that the BOOTROM size is constrained to 4kB.
26+
The bootloader ROM is initialized during synthesis with the default bootloader image
27+
(`rtl/core/neorv32_bootloader_image.vhd`). The physical size of the ROM is automatically
28+
adjusted to the next power of two of the image size. However, note that the BOOTROM is
29+
constrained to a maximum size of 64kB.

docs/datasheet/soc_cfs.adoc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
**Overview**
2323

2424
The custom functions subsystem is meant for implementing custom tightly-coupled co-processors or interfaces.
25-
IT provides up to 64 32-bit memory-mapped read/write registers (`REG`, see register map below) that can be
25+
IT provides up to 16384 32-bit memory-mapped read/write registers (`REG`, see register map below) that can be
2626
accessed by the CPU via normal load/store operations. The actual functionality of these register has to be
2727
defined by the hardware designer. Furthermore, the CFS provides two IO conduits to implement custom on-chip
2828
or off-chip interfaces.
@@ -94,9 +94,9 @@ If the CFU output signals are to be used outside the chip, it is recommended to
9494
[options="header",grid="all"]
9595
|=======================
9696
| Address | Name [C] | Bit(s) | R/W | Function
97-
| `0xffffeb00` | `REG[0]` |`31:0` | (r)/(w) | custom CFS register 0
98-
| `0xffffeb04` | `REG[1]` |`31:0` | (r)/(w) | custom CFS register 1
99-
| ... | ... |`31:0` | (r)/(w) | ...
100-
| `0xffffebf8` | `REG[62]` |`31:0` | (r)/(w) | custom CFS register 62
101-
| `0xffffebfc` | `REG[63]` |`31:0` | (r)/(w) | custom CFS register 63
97+
| `0xffeb0000` | `REG[0]` |`31:0` | (r)/(w) | custom CFS register 0
98+
| `0xffeb0004` | `REG[1]` |`31:0` | (r)/(w) | custom CFS register 1
99+
| ... | ... |`31:0` | (r)/(w) | ...
100+
| `0xffebfff8` | `REG[16382]` |`31:0` | (r)/(w) | custom CFS register 16382
101+
| `0xffebfffc` | `REG[16383]` |`31:0` | (r)/(w) | custom CFS register 16383
102102
|=======================

docs/datasheet/soc_crc.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ and for CRC32-mode the entire 32-bit of `POLY` and `SREG` are used.
6363
[options="header",grid="all"]
6464
|=======================
6565
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
66-
.2+<| `0xffffee00` .2+<| `CTRL` <|`1:0` ^| r/w <| CRC mode select (`00` CRC8, `01`: CRC16, `10`: CRC32)
66+
.2+<| `0xffee0000` .2+<| `CTRL` <|`1:0` ^| r/w <| CRC mode select (`00` CRC8, `01`: CRC16, `10`: CRC32)
6767
<|`31:2` ^| r/- <| _reserved_, read as zero
68-
| `0xffffee04` | `POLY` |`31:0` | r/w | CRC polynomial
69-
.2+<| `0xffffee08` .2+<| `DATA` <|`7:0` ^| r/w <| data input (single byte)
68+
| `0xffee0004` | `POLY` |`31:0` | r/w | CRC polynomial
69+
.2+<| `0xffee0008` .2+<| `DATA` <|`7:0` ^| r/w <| data input (single byte)
7070
<|`31:8` ^| r/- <| _reserved_, read as zero, writes are ignored
71-
| `0xffffee0c` | `SREG` |`32:0` | r/w | current CRC shift register value (set start value on write)
71+
| `0xffee000c` | `SREG` |`32:0` | r/w | current CRC shift register value (set start value on write)
7272
|=======================

docs/datasheet/soc_dma.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ register).
142142
[options="header",grid="all"]
143143
|=======================
144144
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
145-
.12+<| `0xffffed00` .12+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable
145+
.12+<| `0xffed0000` .12+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable
146146
<|`1` `DMA_CTRL_AUTO` ^| r/w <| Enable automatic mode (FIRQ-triggered)
147147
<|`2` `DMA_CTRL_FENCE` ^| r/w <| Issue a downstream FENCE operation when DMA transfer completes (without errors)
148148
<|`7:3` _reserved_ ^| r/- <| reserved, read as zero
@@ -154,9 +154,9 @@ register).
154154
<|`15` `DMA_CTRL_FIRQ_TYPE` ^| r/w <| Trigger on rising-edge (`0`) or high-level (`1`) or selected FIRQ channel
155155
<|`19:16` `DMA_CTRL_FIRQ_SEL_MSB : DMA_CTRL_FIRQ_SEL_LSB` ^| r/w <| FIRQ trigger select (FIRQ0=0 ... FIRQ15=15)
156156
<|`31:20` _reserved_ ^| r/- <| reserved, read as zero
157-
| `0xffffed04` | `SRC_BASE` |`31:0` | r/w | Source base address (shows the last-accessed source address when read)
158-
| `0xffffed08` | `DST_BASE` |`31:0` | r/w | Destination base address (shows the last-accessed destination address when read)
159-
.6+<| `0xffffed0c` .6+<| `TTYPE` <|`23:0` `DMA_TTYPE_NUM_MSB : DMA_TTYPE_NUM_LSB` ^| r/w <| Number of elements to transfer (shows the last-transferred element index when read)
157+
| `0xffed0004` | `SRC_BASE` |`31:0` | r/w | Source base address (shows the last-accessed source address when read)
158+
| `0xffed0008` | `DST_BASE` |`31:0` | r/w | Destination base address (shows the last-accessed destination address when read)
159+
.6+<| `0xffed000c` .6+<| `TTYPE` <|`23:0` `DMA_TTYPE_NUM_MSB : DMA_TTYPE_NUM_LSB` ^| r/w <| Number of elements to transfer (shows the last-transferred element index when read)
160160
<|`26:24` _reserved_ ^| r/- <| reserved, read as zero
161161
<|`28:27` `DMA_TTYPE_QSEL_MSB : DMA_TTYPE_QSEL_LSB` ^| r/w <| Quantity select (`00` = byte -> byte, `01` = byte -> zero-extended-word, `10` = byte -> sign-extended-word, `11` = word -> word)
162162
<|`29` `DMA_TTYPE_SRC_INC` ^| r/w <| Constant (`0`) or incrementing (`1`) source address

docs/datasheet/soc_gpio.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ be performed within a single clock cycle.
4141
[options="header",grid="rows"]
4242
|=======================
4343
| Address | Name [C] | Bit(s) | R/W | Function
44-
| `0xfffffc00` | `INPUT[0]` | 31:0 | r/- | parallel input port pins 31:0
45-
| `0xfffffc04` | `INPUT[1]` | 31:0 | r/- | parallel input port pins 63:32
46-
| `0xfffffc08` | `OUTPUT[0]` | 31:0 | r/w | parallel output port pins 31:0
47-
| `0xfffffc0c` | `OUTPUT[1]` | 31:0 | r/w | parallel output port pins 63:32
44+
| `0xfffc0000` | `INPUT[0]` | 31:0 | r/- | parallel input port pins 31:0
45+
| `0xfffc0004` | `INPUT[1]` | 31:0 | r/- | parallel input port pins 63:32
46+
| `0xfffc0008` | `OUTPUT[0]` | 31:0 | r/w | parallel output port pins 31:0
47+
| `0xfffc000c` | `OUTPUT[1]` | 31:0 | r/w | parallel output port pins 63:32
4848
|=======================

0 commit comments

Comments
 (0)